# 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
