Translate pages

This commit is contained in:
Andras Schmelczer 2026-04-04 09:47:18 +01:00
parent a7aaf5effa
commit 96402228e3
49 changed files with 1458 additions and 926 deletions

View file

@ -276,6 +276,55 @@ Every UI element must use the correct token from this table. Do not invent new p
- [ ] Sidebars, dropdowns, and popups are readable in both modes
- [ ] HomePage and DataSourcesPage adapt correctly
## Internationalization (i18n) — MANDATORY
All user-visible text in the frontend MUST be translated. The build will fail if any language file is missing keys. Supported languages: English, French, German, Hungarian, Chinese.
### Architecture
```
frontend/src/i18n/
index.ts # i18next init, language detection, SUPPORTED_LANGUAGES
i18next.d.ts # Module augmentation — makes t() type-safe
server.ts # ts() for server-derived values, re-exports tsDesc()
descriptions.ts # Feature description translations (separate from locale files)
locales/
en.ts # English (source of truth, as const)
fr.ts / de.ts / hu.ts / zh.ts # Each typed as Translations = DeepStringify<typeof en>
```
**Three translation mechanisms:**
1. **`t('key')`** — UI strings (buttons, labels, headings). Type-safe: `t('typo')` is a compile error.
2. **`ts(value)`** — Server-derived values (feature names, group names, enum values, POI categories). Looks up `server.${value}` in the locale file, falls back to English.
3. **`tsDesc(featureName, englishFallback)`** — Feature descriptions. English comes from the server (single source of truth); other languages from `descriptions.ts`. Keyed by feature name, not description text.
### Adding a new UI string
1. Add the key to `en.ts` in the appropriate section
2. The build will immediately fail for all other locale files — add translations to each
3. Use `t('section.keyName')` in the component
### Adding a new language
1. Create `locales/xx.ts` importing `Translations` from `./en` — TypeScript enforces every key exists
2. Add a `xx` section to `descriptions.ts` for feature descriptions
3. Register in `index.ts`: import, add to `SUPPORTED_LANGUAGES` (with flag emoji) and `resources`
### Translating server-derived values (feature names, POI categories, etc.)
When a new feature is added in `features.rs`:
- Its name should be added to the `server` section of **all** locale files (keyed by the English name)
- Its description should be added to `descriptions.ts` for each non-English language
- English descriptions come from the server — do NOT duplicate them in `en.ts`
### Rules
- **Every `bg-*`, `text-*` class still needs `dark:` counterpart** (i18n doesn't change the design system)
- **URLs always contain English feature names**`ts()` only wraps display, never data keys or URL params
- **Never use dynamic key construction with `t()`** — it breaks TypeScript checking. Use `ts()` for runtime lookups or `tDynamic()` from `index.ts`
- **`useTranslatedModes()`** hook provides translated travel mode labels — don't use `MODE_LABELS` for display
- **Format utilities** (`formatRelativeTime`, `formatDuration`, `summarizeParams`) are already i18n-aware — they import `i18n` directly since they're not React components
## Coding Preferences
- **No backwards compatibility, no silent fallbacks**: Never add fallback codepaths for old data formats, legacy URL parameters, or alternate field names. Never silently swallow errors — always error loudly (return an error, panic, or at minimum log). If something is wrong, the code should fail visibly. One canonical name per field, one format per API, one way to do things. Specific patterns: