94 lines
2.9 KiB
Markdown
94 lines
2.9 KiB
Markdown
# @wrnexus/i18n
|
|
|
|
Recursive locale loading, fallback resolution, SSR/browser translations, locale formatting, and language UI blocks for WRNexusJS.
|
|
|
|
## Locale files
|
|
|
|
Both layouts can be used together:
|
|
|
|
```text
|
|
app/locales/en.json
|
|
app/locales/en/common.json
|
|
app/locales/en/auth.json
|
|
app/locales/mr/common.json
|
|
```
|
|
|
|
Namespaced files become keys such as `common.save` and `auth.signIn`.
|
|
|
|
```ts
|
|
import { loadLocales, makeT, resolveI18n, resolveLang } from "@wrnexus/i18n";
|
|
|
|
const i18n = resolveI18n(loadLocales("app/locales", { strict: true }), {
|
|
default: "en",
|
|
locales: ["en", "mr", "hi"],
|
|
fallbacks: { "mr-IN": ["mr", "en"] },
|
|
cookie: { name: "wrn-lang", sameSite: "Lax", secure: true },
|
|
});
|
|
|
|
const lang = resolveLang(i18n, cookieValue, request.headers.get("accept-language"));
|
|
const t = makeT(i18n, lang);
|
|
t("common.hello", { name: "Ajay" });
|
|
```
|
|
|
|
## Resolution behavior
|
|
|
|
- normalized BCP-47-style locale names
|
|
- cookie preference
|
|
- weighted `Accept-Language`
|
|
- wildcard language ranges
|
|
- regional base fallback
|
|
- explicit fallback chains
|
|
- configured default language
|
|
- automatic RTL for Arabic, Hebrew, Persian, Urdu, and related languages
|
|
|
|
Locale JSON is size-limited and rejects prototype-pollution keys. Recursive namespace collisions are resolved safely.
|
|
|
|
## Views and runtime
|
|
|
|
```html
|
|
<h1 data-t="dashboard.title">Dashboard</h1>
|
|
<input t:placeholder="search.placeholder" />
|
|
```
|
|
|
|
Text and translated attributes are resolved during SSR. Active/fallback messages are serialized safely for the language runtime, which rebinds `data-t` markers after client navigation.
|
|
|
|
Enable `i18nPlugin()` to use:
|
|
|
|
- `<LanguageSwitcher />`
|
|
- `<LocaleStatus />`
|
|
|
|
`LanguageSwitcher` renders a native `select[data-wrn-lang]`. The packaged runtime validates the
|
|
selection against the configured locales, writes the configured language cookie, updates the
|
|
document `lang`/`dir` attributes, emits `wrnexus:language-change`, and reloads so the next SSR
|
|
request uses the same cookie. No application-owned browser script is required.
|
|
|
|
## Formatting
|
|
|
|
- `formatNumber`
|
|
- `formatCurrency`
|
|
- `formatDate`
|
|
- `formatRelativeTime`
|
|
- `plural`
|
|
- `createLocaleFormatter`
|
|
- `translationCoverage`
|
|
Localization tooling can extract statically discoverable `t("key")`,
|
|
`i18n.t("key")`, and `data-i18n="key"` usage, compare every locale with a
|
|
reference, and create layout-stressing pseudo-locales:
|
|
|
|
```ts
|
|
import {
|
|
auditLocaleKeys,
|
|
createPseudoLocale,
|
|
extractTranslationKeysFromFiles,
|
|
} from "@wrnexus/i18n";
|
|
|
|
const used = extractTranslationKeysFromFiles(sourceFiles);
|
|
const coverage = auditLocaleKeys(messages, "en");
|
|
const enXA = createPseudoLocale(messages.en);
|
|
const arXB = createPseudoLocale(messages.en, { rtl: true });
|
|
```
|
|
|
|
Pseudo-localization preserves interpolation placeholders and markup tags. RTL
|
|
pseudo output uses Unicode direction controls, while runtime direction detection
|
|
continues to derive `rtl` from Arabic and other RTL language subtags.
|