Add Russian i18n with DB translations, locale API, and curator review UI.
UI chrome via react-i18next, catalog text in entity_translations with ru.wikipedia seeding, locale-aware search, and Translations page for publish workflow. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
f247b418d8
commit
ca58c43648
@@ -0,0 +1,105 @@
|
||||
# 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`: `draft` → `reviewed` → `published`. 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)
|
||||
|
||||
```powershell
|
||||
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:
|
||||
|
||||
```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](API.md#translations-curator).
|
||||
|
||||
---
|
||||
|
||||
## Translatable fields (v1)
|
||||
|
||||
| entity_type | fields |
|
||||
|-------------|--------|
|
||||
| `era`, `movement` | `name`, `description` |
|
||||
| `artist` | `name`, `bio_short`, `bio_full` |
|
||||
| `artist_period` | `name`, `description` |
|
||||
| `painting` | `title`, `description` |
|
||||
| `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 aliases.
|
||||
|
||||
---
|
||||
|
||||
## Prod rollout
|
||||
|
||||
1. `npm run dev:migrate` on dev; prod schema: `npm run harmonize:schema` (dev → prod only)
|
||||
2. Seed Russian on dev: `npm run dev:fetch-artist-bios-ru`
|
||||
3. Curator review + publish
|
||||
4. `npm run harmonize` to sync `entity_translations` to prod (or full promote if preferred)
|
||||
|
||||
`entity_translations` is included in [`harmonize-db.js`](../scripts/harmonize-db.js) catalog sync.
|
||||
|
||||
---
|
||||
|
||||
## 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](setup.md), [environments.md](environments.md), [harmonize-dev-prod.md](harmonize-dev-prod.md).
|
||||
Reference in New Issue
Block a user