# App i18n Client-side UI string localization for the product client (`toju-app`), using the same `@ngx-translate/core` stack as the marketing website. ## Responsibilities - Bundle locale JSON under `toju-app/public/i18n/`. - Bootstrap translations at app startup via `AppI18nService` (root `App` constructor). - Expose `APP_TRANSLATE_IMPORTS` for standalone components that use the `translate` pipe in templates. - Resolve the active locale through `resolveAppLocale()` in `app-i18n.rules.ts`. ## Boundaries - **In scope:** user-visible UI copy in the Angular product client. - **Out of scope:** server error messages, plugin-authored strings, Electron IPC payloads, and marketing-site copy (`website/public/i18n/`). ## Key files | Path | Role | |------|------| | `toju-app/public/i18n/en.json` | English translation catalog (only locale shipped today). | | `toju-app/src/app/core/i18n/app-i18n.rules.ts` | Supported locales and locale resolution. | | `toju-app/src/app/core/i18n/app-i18n.service.ts` | Loads bundled JSON into `TranslateService`. | | `toju-app/src/app/core/i18n/app-translate.imports.ts` | `TranslateModule` import bundle for standalone components. | | `toju-app/src/app/app.config.ts` | `provideTranslateService()` registration. | ## Usage **Templates** — import `APP_TRANSLATE_IMPORTS` in the standalone component and use the pipe: ```html {{ 'common.brand' | translate }} ``` **TypeScript** — inject `AppI18nService` (or `TranslateService`) and call `instant()`: ```ts this.appI18n.instant('common.brand'); ``` ## Catalog workflow User-visible strings live in fragment files under `toju-app/public/i18n/catalog/*.json`, merged into `toju-app/public/i18n/en.json` by: ```bash npm run i18n:sync ``` The sync script also extracts `theme.registry.*` labels/descriptions from `theme-registry.logic.ts` and `permissions.*` from `access-control.constants.ts` so those large registries stay DRY. Extracted prefixes use dotted paths and are merged as nested JSON (e.g. `theme.registry.appShell.label`, not a flat `"theme.registry"` root key). ## Adding a locale later 1. Add `toju-app/public/i18n/catalog/*.json` fragments for the new locale (or mirror `en.json` structure). 2. Register the locale in `SUPPORTED_APP_LOCALES`. 3. Import and `setTranslation()` in `AppI18nService`. 4. Wire user preference (e.g. general settings) to `AppI18nService.initialize(preferredLocale)`. ## Tests - `toju-app/src/app/core/i18n/app-i18n.rules.spec.ts` - `toju-app/src/app/core/i18n/app-i18n.service.spec.ts` - `toju-app/src/app/core/i18n/app-i18n.testing.ts` — `provideAppI18nForTests()` / `initializeAppI18nForTests()` for Vitest injectors