# 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` - `` attribute set from `Language.code`