Docs/Start

Localization

argui-i18n is the native localization engine. TSX applications use it through @argui/i18n, which loads JSON catalogs, formats Fluent messages with tr, negotiates locales, and reports left-to-right or right-to-left direction. The engine has no Rust UI dependency.

JSON catalogs in TSX

Each catalog is a flat JSON object. Its keys are message IDs and its values are Fluent patterns:

JSON
{
  "welcome": "Welcome, { $name }!",
  "message-count": "{ $count ->\n    [one] One message\n   *[other] { $count } messages\n}"
}

Initialize the catalogs before mounting the gallery or application:

TypeScript
import { loadI18n, selectLocale, tr } from '@argui/i18n'
import english from './locales/en-US.json'
import french from './locales/fr.json'

loadI18n({
  fallback: 'en-US',
  catalogs: { 'en-US': english, fr: french },
  locale: 'fr-CA',
})

tr('welcome', { name: 'Ada' })
selectLocale('en-US')

fr-CA selects the fr catalog when available. A missing message falls back to en-US. Arguments can be strings, numbers, or booleans; pass numbers as numbers for Fluent plural selection. Invalid catalogs and formatting errors are reported instead of silently returning broken text.

Solid components use useI18n from @argui/i18n/solid; React components use useI18n from @argui/i18n/react. Both provide tr, selectLocale, locale, and rtl. Solid exposes locale and rtl as accessors; React exposes their current values. Components rerender when the selected locale changes.

The gallery imports its JSON files into the Vite bundle. In development, editing a catalog triggers the existing TSX bundle watcher: the running native host reloads the bundle and its catalogs. Vite embeds the JSON in both Solid and React bundles. The packaged Solid gallery embeds its bundle in the native binary, so it needs no runtime JSON file beside the executable.

Native engine

Native Rust integrations can depend directly on argui-i18n. Catalog::from_json accepts the same flat JSON catalog as TSX. Catalog::parse and Catalog::from_resources also accept Fluent .ftl resources for more advanced messages and attributes:

Rust
use argui_i18n::{Catalog, FluentArgs, Localizer, langid};

let english = Catalog::from_json(
    langid!("en-US"),
    r#"{"welcome":"Welcome, { $name }!"}"#,
)?;
let french = Catalog::from_json(
    langid!("fr"),
    r#"{"welcome":"Bienvenue, { $name } !"}"#,
)?;
let mut localizer = Localizer::new(langid!("en-US"), [english, french])?;
localizer.select([langid!("fr-CA")]);

let mut args = FluentArgs::new();
args.set("name", "Ada");
let welcome = localizer.format("welcome", &args)?;
assert_eq!(welcome, "Bienvenue, \u{2068}Ada\u{2069} !");
# Ok::<(), Box<dyn std::error::Error>>(())

Localizer also provides text, attribute, and format_attribute for Fluent messages and accessibility labels. is_rtl() reports the selected locale's writing direction. Keep the locale and layout direction in sync when building custom components.