# i18n Contributing Guide This project uses ICU MessageFormat via `@formatjs/intl` with a custom Svelte 5 store. ## Adding a New Language 1. Create `locales/.json` (e.g. `locales/de.json`) with all keys from `locales/en.json`. 2. Register the locale in `src/mainview/i18n.svelte.ts`: - Add an entry to `AVAILABLE_LOCALES` with tag, label, nativeLabel, and dir. - Add a dynamic import entry to the `loaders` map. 3. The language will automatically appear in Settings > Appearance > Language. ## Key Naming Convention Use dot-notation: `component.element.state` ``` sidebar.settings -- component.element agent.status.running -- component.element.state settings.appearance -- component.element common.cancel -- shared across components errors.connectionFailed -- error messages ``` Group prefixes: - `sidebar.*` -- left sidebar - `agent.*` -- agent pane - `terminal.*` -- terminal tabs - `settings.*` -- settings drawer - `statusbar.*` -- bottom status bar - `notifications.*` -- notification drawer - `files.*` -- file browser - `search.*` -- search overlay - `comms.*` -- communications tab - `tasks.*` -- task board - `errors.*` -- error messages - `splash.*` -- splash screen - `common.*` -- shared labels (cancel, save, delete) - `project.*` -- project management - `palette.*` -- command palette ## ICU MessageFormat Syntax ### Plain text ```json "common.save": "Save" ``` ### Plurals (English: one/other) ```json "search.resultsCount": "{count, plural, one {{count} result} other {{count} results}}" ``` ### Plurals (Polish: one/few/many/other) ```json "search.resultsCount": "{count, plural, one {{count} wynik} few {{count} wyniki} many {{count} wynikow} other {{count} wynikow}}" ``` ### Plurals (Arabic: zero/one/two/few/many/other) ```json "tasks.taskCount": "{count, plural, =0 {no tasks} one {one task} two {two tasks} few {{count} tasks} many {{count} tasks} other {{count} tasks}}" ``` ### Interpolation ```json "errors.unhandled": "Unhandled error: {message}" ``` ### Select ```json "agent.status": "{status, select, running {Running} idle {Idle} other {Unknown}}" ``` ## Using Translations in Components ```svelte {t('sidebar.notifCount', { count: 5 })} ``` ## Testing Translations 1. Switch language in Settings > Appearance > Language. 2. All `t()` calls update reactively -- no page reload needed. 3. Missing keys fall back to the key name itself (e.g. `"agent.status.running"`). 4. Check the browser console for `[i18n]` warnings about missing or malformed messages. ## Regenerating Types After adding or removing keys in `locales/en.json`: ```bash bun scripts/i18n-types.ts ``` This regenerates `src/mainview/i18n.types.ts` with the updated `TranslationKey` union type. TypeScript will then flag any `t()` calls using keys that no longer exist. ## RTL Support Arabic (`ar`) sets `document.dir = 'rtl'` automatically. CSS should use logical properties (`inline-start`/`inline-end`) instead of `left`/`right` where possible.