# Locale System Source: `src/dusk/locale/`, asset loader at `src/dusk/asset/loader/locale/` ## Overview The locale system loads Gettext PO files from the asset archive and provides string lookup with plural-form support and printf-style argument substitution. Locale files live in `locale/` inside `dusk.dsk`. ## Global state ```c extern localemanager_t LOCALE; // LOCALE.locale -- currently active localeinfo_t // LOCALE.entry -- locked assetentry_t for the current PO file ``` ## Initialise and switch locale ```c errorret_t localeManagerInit(); // Defaults to LOCALE_EN_US (locale/en_US.po). errorret_t localeManagerSetLocale(const localeinfo_t *locale); // Unlocks the old entry, loads and locks the new one. // Blocks until the new PO file is fully parsed. void localeManagerDispose(); ``` ## Getting a localised string ```c // Variadic (printf-style args): localeManagerGetText(id, buffer, bufferSize, plural, ...); // With a pre-built args array: localeManagerGetTextArgs(id, buffer, bufferSize, plural, args, argCount); ``` Both are macros that delegate to `assetLocaleGetStringWithVA` / `assetLocaleGetStringWithArgs`. - `id` -- message ID string (the English key in the PO file) - `plural` -- plural index (0 for singular, 1+ per PO plural rules) - `buffer` -- destination `char_t` array - `bufferSize` -- size of the destination buffer - `...` -- format arguments matching `%s`, `%d`, `%f` placeholders ## Locale descriptors (`localeinfo_t`) ```c typedef struct { const char_t *name; // e.g. "en-US" const char_t *file; // path inside dusk.dsk, e.g. "locale/en_US.po" } localeinfo_t; ``` The built-in descriptor is: ```c static const localeinfo_t LOCALE_EN_US = { .name = "en-US", .file = "locale/en_US.po", }; ``` Add new locales by declaring another `localeinfo_t` constant and shipping the corresponding `.po` file in the asset archive. ## PO file format notes The loader (`assetlocaleloader`) parses standard Gettext PO syntax: - `msgid` / `msgstr` pairs - `msgid_plural` / `msgstr[n]` for plural forms - The `Plural-Forms:` header (e.g. `nplurals=2; plural=(n != 1);`) is parsed and evaluated at lookup time Argument substitution uses `%s`, `%d`, `%f` placeholders (not standard Gettext `%1` positional args). ## Adding a new locale 1. Create `locale/.po` with a valid `Plural-Forms:` header and the translated `msgid`/`msgstr` entries. 2. Pack it into `dusk.dsk`. 3. Add a `localeinfo_t` constant in `localeinfo.h`. 4. Call `localeManagerSetLocale()` with the new descriptor to activate.