Aimpress_site/specs/001-multi-language/data-model.md
Vadym Samoilenko 6e932d76e4 Add multi-language support (EN/UK) across entire site
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>
2026-03-09 13:32:04 +00:00

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`