# I18n

BullX I18n loads server and client translation catalogs from TOML files and
resolves translations through `BullX.I18n`.

The implementation lives in `BullX.I18n.*`, `BullX.Config.I18n`, Phoenix I18n
helpers, and the React client i18n runtime.

## Catalog Files

Server catalogs live under:

- `priv/locales/en-US.toml`
- `priv/locales/zh-Hans-CN.toml`

Client catalogs live under:

- `priv/locales/client/en-US.toml`
- `priv/locales/client/zh-Hans-CN.toml`

Server TOML files are loaded by `BullX.I18n.Loader`. The filename without
`.toml` is the locale id.

## Configuration

`BullX.Config.I18n` declares:

- `i18n_default_locale`, default `en-US`;
- `i18n_locales_dir`, default `priv/locales`.

`BullX.I18n.Catalog` reads these settings at boot and on reload.

## Server Catalog Runtime

`BullX.I18n.Catalog` is a GenServer under `BullX.Application`. On startup it:

1. scans `priv/locales/*.toml`;
2. validates that the configured default locale is available;
3. updates Localize supported locales and default locale;
4. writes messages and metadata into `:persistent_term` through
   `BullX.I18n.Resolver`.

In development, when `FileSystem` is available, TOML changes under the locale
directory trigger a full rescan.

## Fallback Chain

`BullX.I18n.Resolver` tries translations in this order:

1. requested locale;
2. the requested locale's `__meta__.fallback`, when present;
3. application default locale;
4. `en-US`.

Only loaded full tags are used. BullX does not infer parent tags by trimming
BCP 47 subtags.

## Server API

`BullX.I18n.t/3` returns a string and falls back to a literal key marker when no
translation is found.

`BullX.I18n.translate/3` returns structured success or error tuples.

Other current calls include:

- `default_locale/0`
- `put_default_locale/1`
- `get_locale/0`
- `put_locale/1`
- `with_locale/2`
- `reload/0`
- `available_locales/0`

The `use BullX.I18n` macro provides scoped translation helpers.

## Phoenix Integration

Phoenix controllers and views use BullX I18n helpers to render localized setup,
session, and error text. Error translation is implemented under
`BullXWeb.I18n`.

The setup session page can update the default locale through runtime config.

## Client Runtime

React setup and console code consume client TOML catalogs projected into the
web UI build/runtime. Client strings are separate from server strings so browser
bundles do not need all server translation keys.

## Validation

`mix i18n.check` validates locale catalog shape and key consistency.

Tests cover loader, resolver, catalog, server API, Phoenix error translation,
and the Mix validation task.

## Invariants

- Translation catalogs do not store secrets, tokens, activation codes, login
  codes, provider raw payloads, or private user data.
- Locale ids are full tags such as `en-US` and `zh-Hans-CN`.
- Missing translations are visible failures, not silent blank strings.
- I18n only renders text; authorization and business policy decisions happen in
  their owning subsystems before rendering.
