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:
{
"welcome": "Welcome, { $name }!",
"message-count": "{ $count ->\n [one] One message\n *[other] { $count } messages\n}"
}Initialize the catalogs before mounting the gallery or application:
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:
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.