Runtime
Architecture
Section titled “Architecture”| Layer | Role |
|---|---|
Engine (IcuTranslationProviderMulti) | Mutable dictionary, compiled-message cache, loaded-resource registry |
Handle (I18nHandle via generated createI18n) | load / peek / serialize — namespaces + locale; partition from partitionForLocale |
Scope (I18nScopeMultiForLocale) | Typed t(namespace, key, params?) for a bound locale |
Generated createI18n(options?) builds the engine and returns a handle. Cold start: createI18n() or createI18n({}). Hydrate: createI18n({ state }) where state is { dictionary, resources? } from serialize().
With loaderStrategy: "fetch", options must include fetchImpl:
createI18n({ fetchImpl, state? });load({ namespaces, locale })
Section titled “load({ namespaces, locale })”- Requires a non-empty
namespacesarray. - Partition =
partitionForLocale(locale)(identity for split-by-locale;LOCALE_DELIVERY_AREA[locale]for custom). - For each namespace, if
(namespace, partition)is already marked loaded, skip. - Otherwise invoke
namespaceLoaders[ns](partition, { locale }), merge into the engine, mark loaded. - Return a locale-bound scope
{ t, locale, … }.
peek({ namespaces, locale })
Section titled “peek({ namespaces, locale })”Sync counterpart of load: returns a scope when every requested resource is already loaded (e.g. after hydrate), otherwise null.
getLoadState()
Section titled “getLoadState()”Returns a snapshot of builder resources this handle has attempted to load:
const state = i18n.getLoadState();// { resources: [{ namespace: "billing", partition: "en", status: "loaded" }, ...] }Each entry is namespace + partition (locale or delivery area) with status: "pending" | "loaded" | "error". Failed loads include error. Resources never touched by load() do not appear.
Serialize / hydrate
Section titled “Serialize / hydrate”const i18n = createI18n();const { t } = await i18n.load({ namespaces: ["billing"], locale: "en" });const state = i18n.serialize();
// client (or another request)const client = createI18n({ state });client.peek({ namespaces: ["billing"], locale: "en" }); // scope without re-fetchWith fetch strategy: createI18n({ state, fetchImpl }).
import { createI18n } from "./i18n/generated/instance.generated.js";
const i18n = createI18n();const { t } = await i18n.load({ namespaces: ["default", "billing"], locale: "en",});
t("default", "welcome", { name: "Ada" });t("billing", "invoice_summary", { count: 3 });Pass serialize() output into React as I18nRoot state so client gates resolve via peek without reloading warm namespaces. See React, Lazy loading, and External validation.