Custom i18n system with typed translation dictionaries (~570 keys), LanguageProvider context, and useTranslation hook. All 31 components and pages wired with t() calls. Chatbot backend passes language hint to Claude for Ukrainian responses. Language preference persists via localStorage. SEO meta tags and html lang attribute update dynamically. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
57 lines
1.9 KiB
Markdown
57 lines
1.9 KiB
Markdown
# Data Model: Multi-Language Support
|
|
|
|
## Entities
|
|
|
|
### Language
|
|
|
|
A supported language for the site UI.
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| code | `'en' \| 'uk'` | ISO 639-1 language code |
|
|
| displayLabel | `string` | Label shown in toggle ("Eng", "Ukr") |
|
|
| locale | `string` | Full locale for date formatting ("en-GB", "uk-UA") |
|
|
|
|
**Supported languages** (hardcoded, no dynamic loading):
|
|
- English: `{ code: 'en', displayLabel: 'Eng', locale: 'en-GB' }`
|
|
- Ukrainian: `{ code: 'uk', displayLabel: 'Ukr', locale: 'uk-UA' }`
|
|
|
|
### Translations
|
|
|
|
A typed dictionary mapping translation keys to localized strings.
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| [key: TranslationKey] | `string` | Translated text for the given key |
|
|
|
|
**TranslationKey** is a union type of all valid dot-separated keys (e.g., `'header.nav.home' | 'hero.title' | ...`).
|
|
|
|
Both `en.ts` and `uk.ts` must satisfy the `Translations` type — TypeScript enforces that no keys are missing.
|
|
|
|
### Language Preference (Client-Side)
|
|
|
|
| Storage | Key | Type | Default |
|
|
|---------|-----|------|---------|
|
|
| localStorage | `aimpress_lang` | `'en' \| 'uk'` | `'en'` |
|
|
|
|
Read on app initialization. Updated on language toggle. No server-side persistence.
|
|
|
|
## State Transitions
|
|
|
|
```
|
|
First Visit → lang = 'en' (default)
|
|
↓
|
|
User clicks 'Ukr' → lang = 'uk', localStorage set
|
|
↓
|
|
User clicks 'Eng' → lang = 'en', localStorage set
|
|
↓
|
|
Return Visit → lang = localStorage value (or 'en' if cleared)
|
|
```
|
|
|
|
## Relationships
|
|
|
|
- `LanguageContext` holds current `Language` and provides `t()` function
|
|
- `t(key)` resolves against current language's `Translations` dict, falls back to English
|
|
- `ChatRequest` body includes `language` code for backend AI responses
|
|
- Date formatting uses `Language.locale` via `Intl.DateTimeFormat`
|
|
- `<html lang>` attribute set from `Language.code`
|