# Translation System & Locale Configuration

# Translation System & Locale Configuration

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [docs/ai/i18n.md](docs/ai/i18n.md)
- [src/lib/components/AppPageBreadcrumb.svelte](src/lib/components/AppPageBreadcrumb.svelte)
- [src/lib/components/LangSelect.svelte](src/lib/components/LangSelect.svelte)
- [src/lib/components/ui/dropdown-menu/index.ts](src/lib/components/ui/dropdown-menu/index.ts)
- [src/lib/i18n/index.ts](src/lib/i18n/index.ts)
- [src/lib/i18n/languages.ts](src/lib/i18n/languages.ts)

</details>



The Primebrick frontend implements a reactive internationalization (i18n) system designed for multi-region support. It utilizes a dictionary-based approach with Svelte stores to provide real-time language switching without page reloads. The system supports BCP 47 language tags, template interpolation, and browser-preference-based language sorting.

## Core Translation Logic

The translation engine is centralized in `src/lib/i18n/index.ts`. It manages the loading of message bundles and provides the reactive `$t` store used throughout the application.

### Dictionary Management
Dictionaries are defined in a static map `DICTS` which associates a `UiLang` with its corresponding JSON message bundle. Notably, `en-US` is aliased to `en-GB` for string content, while maintaining its distinct locale tag for `Intl` formatting (dates, numbers).

| Function | Description |
| :--- | :--- |
| `getPath(obj, path)` | Traverses a nested dictionary object using dot-notation strings (e.g., `"app.sidebar.title"`) to retrieve a translation template. |
| `interpolate(template, params)` | Replaces placeholders in the format `{variable}` within a template string with values from the provided `params` object. |

### Reactive Stores
The system exposes two primary stores:
1.  `dict`: A derived store that returns the active dictionary based on the current `uiLang`.
2.  `t`: A derived store providing the translation function. It implements a fallback mechanism where if a key is missing in the current language, it attempts to resolve it from `en-GB` before returning the key itself.

**Sources:** [src/lib/i18n/index.ts:1-50](), [src/lib/i18n/store.svelte:1-10]()

## Locale Configuration & Resolution

The system defines supported locales and provides utilities for normalizing user input (like browser headers or stored settings) into valid application languages.

### Language Definitions
Supported languages are defined in the `UI_LANGS` constant. The system differentiates between full BCP 47 tags and their ISO 639-1 base components.

| Entity | Role |
| :--- | :--- |
| `UI_LANGS` | The authoritative list of supported BCP 47 tags: `en-GB`, `en-US`, `it-IT`, `fr-FR`, `es-ES`, `de-DE`, `pt-PT`. |
| `normalizeLang` | Resolves strings to a `UiLang`. It first checks for an exact match, then falls back to the `BASE_TO_DEFAULT` map for primary language subtags (e.g., `fr-CA` resolves to `fr-FR`). |
| `uiLangRegionSuffix` | Extracts the region subtag for UI badges (e.g., `en-GB` → `GB`). |

### Browser Preference Sorting
The `orderLangEntriesByBrowser` function ensures a personalized user experience by reordering the language selection list. It prioritizes languages found in `navigator.languages` (ordered by the user's browser preference) and appends the remaining supported languages sorted alphabetically by their label.

**Sources:** [src/lib/i18n/languages.ts:1-92]()

## Language Switcher UI

The `LangSelect.svelte` component provides the interface for users to change the application language. It is typically rendered in the top bar or settings area.

### Implementation Details
*   **Trigger:** Displays the current language's flag (using `fi` classes) and a two-letter region suffix generated by `uiLangTopBarTwoLetterSuffix`.
*   **Dropdown:** Lists all available languages. The list is sorted dynamically based on the user's browser settings using `orderLangEntriesByBrowser`.
*   **State Change:** Selecting an item calls `setUiLang(code)`, which updates the `uiLang` store and triggers a global update of all `$t` references.

**Sources:** [src/lib/components/LangSelect.svelte:1-65]()

## System Data Flow

### Translation Resolution Pipeline
This diagram illustrates how a key requested in the UI is resolved into a localized string.

```mermaid
graph TD
    subgraph "Natural Language Space"
        User["User Interface (e.g. Sidebar)"]
        Request["Request: $t('shell.logout')"]
    end

    subgraph "Code Entity Space"
        TStore["t store (derived)"]
        UIStore["uiLang store"]
        DictMap["DICTS Map"]
        GetPath["getPath()"]
        Interp["interpolate()"]
        
        TStore -- "subscribes to" --> UIStore
        UIStore -- "provides key to" --> DictMap
        DictMap -- "returns JSON" --> GetPath
        GetPath -- "searches key" --> Template["Template String"]
        Template -- "passed to" --> Interp
        Interp -- "returns final string" --> User
    end

    User --> Request
    Request --> TStore
```
**Sources:** [src/lib/i18n/index.ts:14-50](), [src/lib/i18n/store.svelte:6-6]()

### Locale Selection Flow
This diagram bridges the browser environment settings to the internal application state.

```mermaid
graph LR
    subgraph "Natural Language Space"
        Browser["Browser Settings (navigator.languages)"]
        Dropdown["LangSelect Dropdown"]
    end

    subgraph "Code Entity Space"
        OrderFn["orderLangEntriesByBrowser()"]
        NormFn["normalizeLang()"]
        LangSelect["LangSelect.svelte"]
        SetUiLang["setUiLang()"]
        UIStore["uiLang store"]

        Browser -- "raw strings" --> OrderFn
        OrderFn -- "calls" --> NormFn
        NormFn -- "matches BCP 47" --> OrderFn
        OrderFn -- "sorted array" --> LangSelect
        LangSelect -- "user clicks" --> SetUiLang
        SetUiLang -- "updates" --> UIStore
    end
```
**Sources:** [src/lib/i18n/languages.ts:30-68](), [src/lib/components/LangSelect.svelte:24-54]()

## Development Guidelines

To maintain i18n integrity, developers must follow strict rules when adding new UI elements:

1.  **Immediate Translation:** Any new label must be added to all JSON files in `src/lib/i18n/messages/` simultaneously.
2.  **Namespace Convention:** Keys should be prefixed by their component or module name (e.g., `eventToast.title`) to prevent collisions.
3.  **Interpolation:** Use curly braces `{}` for dynamic values. The `t` function handles the replacement via the `interpolate` utility.

**Sources:** [docs/ai/i18n.md:1-24]()

---
