Files
Art-gallery/Documentation/i18n-russian.md
T
Danila KhodjaefandCursor bc8369e373 Add public curator notes and U-shaped hall wall hang.
Paintings get editable curator notes with brass plates in the 3D hall, and visit order now uses the far/end wall between left and right.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-25 14:21:22 +03:00

4.1 KiB

Russian localization (i18n)

Full Russian support: UI chrome via react-i18next, catalog text via PostgreSQL entity_translations, with Cyrillic display aliases where available and English fallback.


Architecture

Layer English Russian
UI labels, buttons client/src/locales/en/*.json client/src/locales/ru/*.json
Names / titles (display) canonical DB columns entity_translations (name, title)
Bios, notes, descriptions canonical DB columns entity_translations (bio_full, body, notes, …)

English remains canonical in main tables. Russian rows use status: draftreviewedpublished. Public API returns only published (unless curator preview).


User-facing locale switch

Timeline header: EN | RU toggle (LocaleSwitcher).

  • Persists gallery_locale in localStorage
  • Sets document.documentElement.lang
  • Passes ?locale=ru on catalog API requests
  • Refetches bootstrap catalog when locale changes

Setup (dev)

npm run dev:migrate              # includes migrate-i18n.sql
npm run dev:fetch-artist-bios-ru # draft bios + Cyrillic names from ru.wikipedia
# Curator: Translations page → review → Publish
npm run dev:import-translations -- --file path/to/translations.json --publish

Optional manual import JSON:

[
  { "entity_type": "painting", "entity_id": 42, "field_name": "title", "value": "Джоконда", "status": "published", "source": "manual" }
]

CSV: entity_type,entity_id,field_name,value,status,source


Curator translation review

  1. Sign in as curator
  2. Header → Translations (or Переводы in RU UI)
  3. Pick entity type (artist / painting / movement)
  4. Select row → edit Russian fields side-by-side with English canonical
  5. Publish saves and marks rows published

Coverage stats show artists with bio_full, paintings with title alias, draft vs published counts.

API (curator-only): see API.md.


Translatable fields (v1)

entity_type fields
era, movement name, description
artist name, bio_short, bio_full
artist_period name, description
painting title, description (not curator_notes — English-only for now)
annotation label, body
influence_source notes, aspects, quote, period_note

API locale

Public endpoints accept ?locale=ru or Accept-Language: ru. Responses include "locale": "ru" on catalog payloads; field names unchanged — values are already resolved.

Search matches canonical text or published Russian name / title aliases (partial index entity_translations_search_alias_idx; long bio_full text is stored but not btree-indexed).


Prod rollout

  1. npm run dev:migrate on dev; curator review + publish Russian rows on dev
  2. npm run devtoprod:release (full profile) — includes Step 4 schema migrate + Step 5 restore; or npm run harmonize:schema then harmonize/sync if you prefer merge over full promote
  3. After restore, verify locale toggle on https://gallery.mysuperlab.netcraze.pro

entity_translations is included in harmonize-db.js catalog sync.

dev:fetch-artist-bios-ru index limit

Early migrate-i18n.sql indexed all value text; very long Russian bios (e.g. Michelangelo) could fail with index row size … exceeds btree maximum. Current migration uses a partial index on name and title only (char_length(value) <= 512). Re-run npm run dev:migrate (or prod Step 4) after pulling this fix, then re-run npm run dev:fetch-artist-bios-ru for any artists that failed.


npm scripts

Script Purpose
dev:migrate:i18n Apply entity_translations table only
dev:fetch-artist-bios-ru Fetch ru.wikipedia bios into translations (draft)
dev:import-translations Import JSON/CSV translation rows

See also setup.md, environments.md, harmonize-dev-prod.md.