# @suaveplan/react-i18n - React bindings for @suaveplan/i18n: TranslationProvider, hooks, , , locale-detection chain glue, branded TranslationKey contract. ## Summary React bindings for `@suaveplan/i18n`. Ships the ``, twelve hooks, four headless components, the class-component HOC, the nine built-in locale detectors plus the default chain, the `useLocaleDetection` hook, the branded `TranslationKey` typing contract, the `tDynamic` runtime escape hatch, the React-tier OTel instruments, and the warn-once / identity-translator soft-failure substrate. The package is the leaf-most React library in the project — every other React package augments it (via `ContributedTranslationKeys`) but no React package may declare it as a downstream dependency. The [`check-no-backwards-deps.ts`](../../../scripts/lint/check-no-backwards-deps.ts) CI gate enforces that invariant on every commit. ## Documentation tree - [i18n-suspense](./src/components/i18n-suspense/i18n-suspense.md) — _(no submodules)_ - [fallback-bundle](./src/components/i18n-suspense/fallback-bundle.md) — Ships the strings that `` needs before the active catalog loads its own copies. Consumers can override th… - [i18n-suspense](./src/components/i18n-suspense/i18n-suspense.md) — _(no submodules)_ - [language-switcher](./src/components/language-switcher/language-switcher.md) — _(no submodules)_ - [language-switcher](./src/components/language-switcher/language-switcher.md) — _(no submodules)_ - [missing-key-overlay](./src/components/missing-key-overlay/missing-key-overlay.md) — _(no submodules)_ - [missing-key-overlay](./src/components/missing-key-overlay/missing-key-overlay.md) — _(no submodules)_ - [trans](./src/components/trans/trans.md) — _(no submodules)_ - [stringify-children](./src/components/trans/stringify-children.md) — Helpers that translate a `` `children` block into a canonical ICU message body string so the message parser rend… - [trans](./src/components/trans/trans.md) — _(no submodules)_ - [create-i18n-config](./src/config/create-i18n-config.md) — Builds a validated `I18nConfig` from a caller-supplied option bag and is the canonical entry point for ` _(no submodules)_ - [accept-language](./src/detector/accept-language/accept-language.md) — _(no submodules)_ - [cloudflare-ip-geo](./src/detector/cloudflare-ip-geo/cloudflare-ip-geo.md) — _(no submodules)_ - [cloudflare-ip-geo](./src/detector/cloudflare-ip-geo/cloudflare-ip-geo.md) — _(no submodules)_ - [cookie](./src/detector/cookie/cookie.md) — _(no submodules)_ - [cookie](./src/detector/cookie/cookie.md) — _(no submodules)_ - [default-chain](./src/detector/default-chain/default-chain.md) — _(no submodules)_ - [default-chain](./src/detector/default-chain/default-chain.md) — _(no submodules)_ - [fallback](./src/detector/fallback/fallback.md) — _(no submodules)_ - [fallback](./src/detector/fallback/fallback.md) — _(no submodules)_ - [html-lang](./src/detector/html-lang/html-lang.md) — _(no submodules)_ - [html-lang](./src/detector/html-lang/html-lang.md) — _(no submodules)_ - [local-storage](./src/detector/local-storage/local-storage.md) — _(no submodules)_ - [local-storage](./src/detector/local-storage/local-storage.md) — _(no submodules)_ - [navigator](./src/detector/navigator/navigator.md) — _(no submodules)_ - [navigator](./src/detector/navigator/navigator.md) — _(no submodules)_ - [querystring](./src/detector/querystring/querystring.md) — _(no submodules)_ - [querystring](./src/detector/querystring/querystring.md) — _(no submodules)_ - [user-preference](./src/detector/user-preference/user-preference.md) — _(no submodules)_ - [user-preference](./src/detector/user-preference/user-preference.md) — _(no submodules)_ - [error-codes](./src/errors/error-codes.md) — Registers the five stable error codes used by `@suaveplan/react-i18n` under the `REACT_I18N` namespace via `defineCodes… - [react-i18n-error](./src/errors/react-i18n-error.md) — Defines `ReactI18nError`, the single error class thrown by the React surface of `@suaveplan/react-i18n`. It extends the… - [with-translation](./src/hoc/with-translation/with-translation.md) — _(no submodules)_ - [with-translation](./src/hoc/with-translation/with-translation.md) — _(no submodules)_ - [use-currency](./src/hooks/use-currency/use-currency.md) — _(no submodules)_ - [use-currency](./src/hooks/use-currency/use-currency.md) — _(no submodules)_ - [use-date](./src/hooks/use-date/use-date.md) — _(no submodules)_ - [use-date](./src/hooks/use-date/use-date.md) — _(no submodules)_ - [use-direction](./src/hooks/use-direction/use-direction.md) — _(no submodules)_ - [use-direction](./src/hooks/use-direction/use-direction.md) — _(no submodules)_ - [use-error-message](./src/hooks/use-error-message/use-error-message.md) — _(no submodules)_ - [use-error-message](./src/hooks/use-error-message/use-error-message.md) — _(no submodules)_ - [use-formatter](./src/hooks/use-formatter/use-formatter.md) — _(no submodules)_ - [use-formatter](./src/hooks/use-formatter/use-formatter.md) — _(no submodules)_ - [use-i18n](./src/hooks/use-i18n/use-i18n.md) — _(no submodules)_ - [use-i18n](./src/hooks/use-i18n/use-i18n.md) — _(no submodules)_ - [use-list](./src/hooks/use-list/use-list.md) — _(no submodules)_ - [use-list](./src/hooks/use-list/use-list.md) — _(no submodules)_ - [use-locale](./src/hooks/use-locale/use-locale.md) — _(no submodules)_ - [use-locale](./src/hooks/use-locale/use-locale.md) — _(no submodules)_ - [use-locale-adapter](./src/hooks/use-locale-adapter/use-locale-adapter.md) — _(no submodules)_ - [use-locale-adapter](./src/hooks/use-locale-adapter/use-locale-adapter.md) — _(no submodules)_ - [use-locale-detection](./src/hooks/use-locale-detection/use-locale-detection.md) — _(no submodules)_ - [detector-chain-context](./src/hooks/use-locale-detection/detector-chain-context.md) — `DetectorChainContext` is the React context that carries the configured locale-detector chain (plus any SSR-authoritati… - [use-locale-detection](./src/hooks/use-locale-detection/use-locale-detection.md) — _(no submodules)_ - [use-number](./src/hooks/use-number/use-number.md) — _(no submodules)_ - [use-number](./src/hooks/use-number/use-number.md) — _(no submodules)_ - [use-plural](./src/hooks/use-plural/use-plural.md) — _(no submodules)_ - [use-plural](./src/hooks/use-plural/use-plural.md) — _(no submodules)_ - [use-relative-time](./src/hooks/use-relative-time/use-relative-time.md) — _(no submodules)_ - [use-relative-time](./src/hooks/use-relative-time/use-relative-time.md) — _(no submodules)_ - [use-translate](./src/hooks/use-translate/use-translate.md) — _(no submodules)_ - [use-translate](./src/hooks/use-translate/use-translate.md) — _(no submodules)_ - [use-translation](./src/hooks/use-translation/use-translation.md) — _(no submodules)_ - [use-translation](./src/hooks/use-translation/use-translation.md) — _(no submodules)_ - [observability](./src/observability/react-i18n-metrics.md) — _(no submodules)_ - [react-i18n-metrics](./src/observability/react-i18n-metrics.md) — _(no submodules)_ - [provider](./src/provider/provider.md) — _(no submodules)_ - [provider-context](./src/provider/provider-context.md) — Defines the React context that carries the active `I18nInstance` from `@suaveplan/i18n` to every descendant of ` _(no submodules)_ - [registry](./src/registry/registry.md) — _(no submodules)_ - built-in — _(no submodules)… - [built-in](./src/registry/formatters/built-in/built-in.md) — _(no submodules)_ - [built-in](./src/registry/formatters/built-in/built-in.md) — _(no submodules)_ - [built-in](./src/registry/locale-adapters/built-in/built-in.md) — _(no submodules)_ - [built-in](./src/registry/locale-adapters/built-in/built-in.md) — _(no submodules)_ - [post-processors](./src/registry/post-processors/post-processors.md) — _(no submodules)_ - [post-processors](./src/registry/post-processors/post-processors.md) — _(no submodules)_ - [registry-context](./src/registry/registry-context.md) — Module-scoped React context that carries the active `ReactI18nRegistry` to descendants of ``. Direct… - [registry-provider](./src/registry/registry-provider.md) — `` is the React-context surface for `ReactI18nRegistry`. It mounts a fresh registry per tree, registe… - [registry](./src/registry/registry.md) — _(no submodules)_ - built-in — _(no submodules)… - [registry.schemas](./src/registry/registry.schemas.md) — Strict-object Zod schemas for every plugin kind accepted by `ReactI18nRegistry`. The schemas are the boundary at which… - [use-registry](./src/registry/use-registry.md) — These hooks read the active `ReactI18nRegistry` from React context. The strict variant `useReactI18nRegistry()` throws… - [schemas](./src/schemas/i18n-config.schemas.md) — _(no submodules)_ - [i18n-config.schemas](./src/schemas/i18n-config.schemas.md) — _(no submodules)_ - [translation-key](./src/translation-key/translation-key.md) — _(no submodules)_ - [t-dynamic](./src/translation-key/t-dynamic.md) — `tDynamic(i18n, key, values?)` is the rare-use escape hatch for translation lookups whose key cannot be statically know… - [translation-key](./src/translation-key/translation-key.md) — _(no submodules)_ - [env](./src/utils/env.md) — Provides the single environment-detection helper the React surface uses to switch between dev-mode loud-failure and pro… - [identity-instance](./src/utils/identity-instance.md) — Provides the identity translator used as the production-mode fallback when a `useTranslation()` (or any sibling hook) i… - [warn-once-per-process](./src/utils/warn-once-per-process.md) — Implements the warn-once-per-process dedup ring used by every production-mode soft-failure path in `@suaveplan/react-i1… - [fallback-bundle](./src/components/i18n-suspense/fallback-bundle.md) — Ships the strings that `` needs before the active catalog loads its own copies. Consumers can override th… - [i18n-suspense](./src/components/i18n-suspense/i18n-suspense.md) — _(no submodules)_- [language-switcher](./src/components/language-switcher/language-switcher.md) — _(no submodules)_- [language-switcher](./src/components/language-switcher/language-switcher.md) — _(no submodules)_- [missing-key-overlay](./src/components/missing-key-overlay/missing-key-overlay.md) — _(no submodules)_- [missing-key-overlay](./src/components/missing-key-overlay/missing-key-overlay.md) — _(no submodules)_- [trans](./src/components/trans/trans.md) — _(no submodules)_- [stringify-children](./src/components/trans/stringify-children.md) — Helpers that translate a `` `children` block into a canonical ICU message body string so the message parser rend… - [trans](./src/components/trans/trans.md) — _(no submodules)_- [create-i18n-config](./src/config/create-i18n-config.md) — Builds a validated `I18nConfig` from a caller-supplied option bag and is the canonical entry point for ` _(no submodules)_- [accept-language](./src/detector/accept-language/accept-language.md) — _(no submodules)_- [cloudflare-ip-geo](./src/detector/cloudflare-ip-geo/cloudflare-ip-geo.md) — _(no submodules)_- [cloudflare-ip-geo](./src/detector/cloudflare-ip-geo/cloudflare-ip-geo.md) — _(no submodules)_- [cookie](./src/detector/cookie/cookie.md) — _(no submodules)_- [cookie](./src/detector/cookie/cookie.md) — _(no submodules)_- [default-chain](./src/detector/default-chain/default-chain.md) — _(no submodules)_- [default-chain](./src/detector/default-chain/default-chain.md) — _(no submodules)_- [fallback](./src/detector/fallback/fallback.md) — _(no submodules)_- [fallback](./src/detector/fallback/fallback.md) — _(no submodules)_- [html-lang](./src/detector/html-lang/html-lang.md) — _(no submodules)_- [html-lang](./src/detector/html-lang/html-lang.md) — _(no submodules)_- [local-storage](./src/detector/local-storage/local-storage.md) — _(no submodules)_- [local-storage](./src/detector/local-storage/local-storage.md) — _(no submodules)_- [navigator](./src/detector/navigator/navigator.md) — _(no submodules)_- [navigator](./src/detector/navigator/navigator.md) — _(no submodules)_- [querystring](./src/detector/querystring/querystring.md) — _(no submodules)_- [querystring](./src/detector/querystring/querystring.md) — _(no submodules)_- [user-preference](./src/detector/user-preference/user-preference.md) — _(no submodules)_- [user-preference](./src/detector/user-preference/user-preference.md) — _(no submodules)_- [error-codes](./src/errors/error-codes.md) — Registers the five stable error codes used by `@suaveplan/react-i18n` under the `REACT_I18N` namespace via `defineCodes… - [react-i18n-error](./src/errors/react-i18n-error.md) — Defines `ReactI18nError`, the single error class thrown by the React surface of `@suaveplan/react-i18n`. It extends the… - [with-translation](./src/hoc/with-translation/with-translation.md) — _(no submodules)_- [with-translation](./src/hoc/with-translation/with-translation.md) — _(no submodules)_- [use-currency](./src/hooks/use-currency/use-currency.md) — _(no submodules)_- [use-currency](./src/hooks/use-currency/use-currency.md) — _(no submodules)_- [use-date](./src/hooks/use-date/use-date.md) — _(no submodules)_- [use-date](./src/hooks/use-date/use-date.md) — _(no submodules)_- [use-direction](./src/hooks/use-direction/use-direction.md) — _(no submodules)_- [use-direction](./src/hooks/use-direction/use-direction.md) — _(no submodules)_- [use-error-message](./src/hooks/use-error-message/use-error-message.md) — _(no submodules)_- [use-error-message](./src/hooks/use-error-message/use-error-message.md) — _(no submodules)_- [use-formatter](./src/hooks/use-formatter/use-formatter.md) — _(no submodules)_- [use-formatter](./src/hooks/use-formatter/use-formatter.md) — _(no submodules)_- [use-i18n](./src/hooks/use-i18n/use-i18n.md) — _(no submodules)_- [use-i18n](./src/hooks/use-i18n/use-i18n.md) — _(no submodules)_- [use-list](./src/hooks/use-list/use-list.md) — _(no submodules)_- [use-list](./src/hooks/use-list/use-list.md) — _(no submodules)_- [use-locale](./src/hooks/use-locale/use-locale.md) — _(no submodules)_- [use-locale](./src/hooks/use-locale/use-locale.md) — _(no submodules)_- [use-locale-adapter](./src/hooks/use-locale-adapter/use-locale-adapter.md) — _(no submodules)_- [use-locale-adapter](./src/hooks/use-locale-adapter/use-locale-adapter.md) — _(no submodules)_- [use-locale-detection](./src/hooks/use-locale-detection/use-locale-detection.md) — _(no submodules)_- [detector-chain-context](./src/hooks/use-locale-detection/detector-chain-context.md) — `DetectorChainContext` is the React context that carries the configured locale-detector chain (plus any SSR-authoritati… - [use-locale-detection](./src/hooks/use-locale-detection/use-locale-detection.md) — _(no submodules)_- [use-number](./src/hooks/use-number/use-number.md) — _(no submodules)_- [use-number](./src/hooks/use-number/use-number.md) — _(no submodules)_- [use-plural](./src/hooks/use-plural/use-plural.md) — _(no submodules)_- [use-plural](./src/hooks/use-plural/use-plural.md) — _(no submodules)_- [use-relative-time](./src/hooks/use-relative-time/use-relative-time.md) — _(no submodules)_- [use-relative-time](./src/hooks/use-relative-time/use-relative-time.md) — _(no submodules)_- [use-translate](./src/hooks/use-translate/use-translate.md) — _(no submodules)_- [use-translate](./src/hooks/use-translate/use-translate.md) — _(no submodules)_- [use-translation](./src/hooks/use-translation/use-translation.md) — _(no submodules)_- [use-translation](./src/hooks/use-translation/use-translation.md) — _(no submodules)_- [observability](./src/observability/react-i18n-metrics.md) — _(no submodules)_- [react-i18n-metrics](./src/observability/react-i18n-metrics.md) — _(no submodules)_- [provider](./src/provider/provider.md) — _(no submodules)_- [provider-context](./src/provider/provider-context.md) — Defines the React context that carries the active `I18nInstance` from `@suaveplan/i18n` to every descendant of ` _(no submodules)_- [registry](./src/registry/registry.md) — _(no submodules)_- [built-in](./src/registry/formatters/built-in/built-in.md) — _(no submodules)_- [built-in](./src/registry/formatters/built-in/built-in.md) — _(no submodules)_- [built-in](./src/registry/locale-adapters/built-in/built-in.md) — _(no submodules)_- [built-in](./src/registry/locale-adapters/built-in/built-in.md) — _(no submodules)_- [post-processors](./src/registry/post-processors/post-processors.md) — _(no submodules)_- [post-processors](./src/registry/post-processors/post-processors.md) — _(no submodules)_- [registry-context](./src/registry/registry-context.md) — Module-scoped React context that carries the active `ReactI18nRegistry` to descendants of ``. Direct… - [registry-provider](./src/registry/registry-provider.md) — `` is the React-context surface for `ReactI18nRegistry`. It mounts a fresh registry per tree, registe… - [registry](./src/registry/registry.md) — _(no submodules)_- [registry.schemas](./src/registry/registry.schemas.md) — Strict-object Zod schemas for every plugin kind accepted by `ReactI18nRegistry`. The schemas are the boundary at which… - [use-registry](./src/registry/use-registry.md) — These hooks read the active `ReactI18nRegistry` from React context. The strict variant `useReactI18nRegistry()` throws… - [schemas](./src/schemas/i18n-config.schemas.md) — _(no submodules)_- [i18n-config.schemas](./src/schemas/i18n-config.schemas.md) — _(no submodules)_- [translation-key](./src/translation-key/translation-key.md) — _(no submodules)_- [t-dynamic](./src/translation-key/t-dynamic.md) — `tDynamic(i18n, key, values?)` is the rare-use escape hatch for translation lookups whose key cannot be statically know… - [translation-key](./src/translation-key/translation-key.md) — _(no submodules)_- [env](./src/utils/env.md) — Provides the single environment-detection helper the React surface uses to switch between dev-mode loud-failure and pro… - [identity-instance](./src/utils/identity-instance.md) — Provides the identity translator used as the production-mode fallback when a `useTranslation()` (or any sibling hook) i… - [warn-once-per-process](./src/utils/warn-once-per-process.md) — Implements the warn-once-per-process dedup ring used by every production-mode soft-failure path in `@suaveplan/react-i1… - [fallback-bundle](./src/components/i18n-suspense/fallback-bundle.md) — Ships the strings that `` needs before the active catalog loads its own copies. Consumers can override th… - [i18n-suspense](./src/components/i18n-suspense/i18n-suspense.md) — _(no submodules)_- [language-switcher](./src/components/language-switcher/language-switcher.md) — _(no submodules)_- [language-switcher](./src/components/language-switcher/language-switcher.md) — _(no submodules)_- [missing-key-overlay](./src/components/missing-key-overlay/missing-key-overlay.md) — _(no submodules)_- [missing-key-overlay](./src/components/missing-key-overlay/missing-key-overlay.md) — _(no submodules)_- [trans](./src/components/trans/trans.md) — _(no submodules)_- [stringify-children](./src/components/trans/stringify-children.md) — Helpers that translate a `` `children` block into a canonical ICU message body string so the message parser rend… - [trans](./src/components/trans/trans.md) — _(no submodules)_- [create-i18n-config](./src/config/create-i18n-config.md) — Builds a validated `I18nConfig` from a caller-supplied option bag and is the canonical entry point for ` _(no submodules)_- [accept-language](./src/detector/accept-language/accept-language.md) — _(no submodules)_- [cloudflare-ip-geo](./src/detector/cloudflare-ip-geo/cloudflare-ip-geo.md) — _(no submodules)_- [cloudflare-ip-geo](./src/detector/cloudflare-ip-geo/cloudflare-ip-geo.md) — _(no submodules)_- [cookie](./src/detector/cookie/cookie.md) — _(no submodules)_- [cookie](./src/detector/cookie/cookie.md) — _(no submodules)_- [default-chain](./src/detector/default-chain/default-chain.md) — _(no submodules)_- [default-chain](./src/detector/default-chain/default-chain.md) — _(no submodules)_- [fallback](./src/detector/fallback/fallback.md) — _(no submodules)_- [fallback](./src/detector/fallback/fallback.md) — _(no submodules)_- [html-lang](./src/detector/html-lang/html-lang.md) — _(no submodules)_- [html-lang](./src/detector/html-lang/html-lang.md) — _(no submodules)_- [local-storage](./src/detector/local-storage/local-storage.md) — _(no submodules)_- [local-storage](./src/detector/local-storage/local-storage.md) — _(no submodules)_- [navigator](./src/detector/navigator/navigator.md) — _(no submodules)_- [navigator](./src/detector/navigator/navigator.md) — _(no submodules)_- [querystring](./src/detector/querystring/querystring.md) — _(no submodules)_- [querystring](./src/detector/querystring/querystring.md) — _(no submodules)_- [user-preference](./src/detector/user-preference/user-preference.md) — _(no submodules)_- [user-preference](./src/detector/user-preference/user-preference.md) — _(no submodules)_- [error-codes](./src/errors/error-codes.md) — Registers the five stable error codes used by `@suaveplan/react-i18n` under the `REACT_I18N` namespace via `defineCodes… - [react-i18n-error](./src/errors/react-i18n-error.md) — Defines `ReactI18nError`, the single error class thrown by the React surface of `@suaveplan/react-i18n`. It extends the… - [with-translation](./src/hoc/with-translation/with-translation.md) — _(no submodules)_- [with-translation](./src/hoc/with-translation/with-translation.md) — _(no submodules)_- [use-currency](./src/hooks/use-currency/use-currency.md) — _(no submodules)_- [use-currency](./src/hooks/use-currency/use-currency.md) — _(no submodules)_- [use-date](./src/hooks/use-date/use-date.md) — _(no submodules)_- [use-date](./src/hooks/use-date/use-date.md) — _(no submodules)_- [use-direction](./src/hooks/use-direction/use-direction.md) — _(no submodules)_- [use-direction](./src/hooks/use-direction/use-direction.md) — _(no submodules)_- [use-error-message](./src/hooks/use-error-message/use-error-message.md) — _(no submodules)_- [use-error-message](./src/hooks/use-error-message/use-error-message.md) — _(no submodules)_- [use-formatter](./src/hooks/use-formatter/use-formatter.md) — _(no submodules)_- [use-formatter](./src/hooks/use-formatter/use-formatter.md) — _(no submodules)_- [use-i18n](./src/hooks/use-i18n/use-i18n.md) — _(no submodules)_- [use-i18n](./src/hooks/use-i18n/use-i18n.md) — _(no submodules)_- [use-list](./src/hooks/use-list/use-list.md) — _(no submodules)_- [use-list](./src/hooks/use-list/use-list.md) — _(no submodules)_- [use-locale](./src/hooks/use-locale/use-locale.md) — _(no submodules)_- [use-locale](./src/hooks/use-locale/use-locale.md) — _(no submodules)_- [use-locale-adapter](./src/hooks/use-locale-adapter/use-locale-adapter.md) — _(no submodules)_- [use-locale-adapter](./src/hooks/use-locale-adapter/use-locale-adapter.md) — _(no submodules)_- [use-locale-detection](./src/hooks/use-locale-detection/use-locale-detection.md) — _(no submodules)_- [detector-chain-context](./src/hooks/use-locale-detection/detector-chain-context.md) — `DetectorChainContext` is the React context that carries the configured locale-detector chain (plus any SSR-authoritati… - [use-locale-detection](./src/hooks/use-locale-detection/use-locale-detection.md) — _(no submodules)_- [use-number](./src/hooks/use-number/use-number.md) — _(no submodules)_- [use-number](./src/hooks/use-number/use-number.md) — _(no submodules)_- [use-plural](./src/hooks/use-plural/use-plural.md) — _(no submodules)_- [use-plural](./src/hooks/use-plural/use-plural.md) — _(no submodules)_- [use-relative-time](./src/hooks/use-relative-time/use-relative-time.md) — _(no submodules)_- [use-relative-time](./src/hooks/use-relative-time/use-relative-time.md) — _(no submodules)_- [use-translate](./src/hooks/use-translate/use-translate.md) — _(no submodules)_- [use-translate](./src/hooks/use-translate/use-translate.md) — _(no submodules)_- [use-translation](./src/hooks/use-translation/use-translation.md) — _(no submodules)_- [use-translation](./src/hooks/use-translation/use-translation.md) — _(no submodules)_- [observability](./src/observability/react-i18n-metrics.md) — _(no submodules)_- [react-i18n-metrics](./src/observability/react-i18n-metrics.md) — _(no submodules)_- [provider](./src/provider/provider.md) — _(no submodules)_- [provider-context](./src/provider/provider-context.md) — Defines the React context that carries the active `I18nInstance` from `@suaveplan/i18n` to every descendant of ` _(no submodules)_- [registry](./src/registry/registry.md) — _(no submodules)_- built-in — _(no submodules)_- [built-in](./src/registry/formatters/built-in/built-in.md) — _(no submodules)_- [built-in](./src/registry/locale-adapters/built-in/built-in.md) — _(no submodules)_- [built-in](./src/registry/locale-adapters/built-in/built-in.md) — _(no submodules)_- [post-processors](./src/registry/post-processors/post-processors.md) — _(no submodules)_- [post-processors](./src/registry/post-processors/post-processors.md) — _(no submodules)_- [registry-context](./src/registry/registry-context.md) — Module-scoped React context that carries the active `ReactI18nRegistry` to descendants of ``. Direct… - [registry-provider](./src/registry/registry-provider.md) — `` is the React-context surface for `ReactI18nRegistry`. It mounts a fresh registry per tree, registe… - [registry](./src/registry/registry.md) — _(no submodules)_- built-in — _(no submodules)_- [i18n-config.schemas](./src/schemas/i18n-config.schemas.md) — _(no submodules)_- [translation-key](./src/translation-key/translation-key.md) — _(no submodules)_- [t-dynamic](./src/translation-key/t-dynamic.md) — `tDynamic(i18n, key, values?)` is the rare-use escape hatch for translation lookups whose key cannot be statically know… - [translation-key](./src/translation-key/translation-key.md) — _(no submodules)_- [env](./src/utils/env.md) — Provides the single environment-detection helper the React surface uses to switch between dev-mode loud-failure and pro… - [identity-instance](./src/utils/identity-instance.md) — Provides the identity translator used as the production-mode fallback when a `useTranslation()` (or any sibling hook) i… - [warn-once-per-process](./src/utils/warn-once-per-process.md) — Implements the warn-once-per-process dedup ring used by every production-mode soft-failure path in `@suaveplan/react-i1… - [fallback-bundle](./src/components/i18n-suspense/fallback-bundle.md) — Ships the strings that `` needs before the active catalog loads its own copies. Consumers can override th… - [i18n-suspense](./src/components/i18n-suspense/i18n-suspense.md) — _(no submodules)_- [language-switcher](./src/components/language-switcher/language-switcher.md) — _(no submodules)_- [language-switcher](./src/components/language-switcher/language-switcher.md) — _(no submodules)_- [missing-key-overlay](./src/components/missing-key-overlay/missing-key-overlay.md) — _(no submodules)_- [missing-key-overlay](./src/components/missing-key-overlay/missing-key-overlay.md) — _(no submodules)_- [trans](./src/components/trans/trans.md) — _(no submodules)_- [stringify-children](./src/components/trans/stringify-children.md) — Helpers that translate a `` `children` block into a canonical ICU message body string so the message parser rend… - [trans](./src/components/trans/trans.md) — _(no submodules)_- [create-i18n-config](./src/config/create-i18n-config.md) — Builds a validated `I18nConfig` from a caller-supplied option bag and is the canonical entry point for ` _(no submodules)_- [accept-language](./src/detector/accept-language/accept-language.md) — _(no submodules)_- [cloudflare-ip-geo](./src/detector/cloudflare-ip-geo/cloudflare-ip-geo.md) — _(no submodules)_- [cloudflare-ip-geo](./src/detector/cloudflare-ip-geo/cloudflare-ip-geo.md) — _(no submodules)_- [cookie](./src/detector/cookie/cookie.md) — _(no submodules)_- [cookie](./src/detector/cookie/cookie.md) — _(no submodules)_- [default-chain](./src/detector/default-chain/default-chain.md) — _(no submodules)_- [default-chain](./src/detector/default-chain/default-chain.md) — _(no submodules)_- [fallback](./src/detector/fallback/fallback.md) — _(no submodules)_- [fallback](./src/detector/fallback/fallback.md) — _(no submodules)_- [html-lang](./src/detector/html-lang/html-lang.md) — _(no submodules)_- [html-lang](./src/detector/html-lang/html-lang.md) — _(no submodules)_- [local-storage](./src/detector/local-storage/local-storage.md) — _(no submodules)_- [local-storage](./src/detector/local-storage/local-storage.md) — _(no submodules)_- [navigator](./src/detector/navigator/navigator.md) — _(no submodules)_- [navigator](./src/detector/navigator/navigator.md) — _(no submodules)_- [querystring](./src/detector/querystring/querystring.md) — _(no submodules)_- [querystring](./src/detector/querystring/querystring.md) — _(no submodules)_- [user-preference](./src/detector/user-preference/user-preference.md) — _(no submodules)_- [user-preference](./src/detector/user-preference/user-preference.md) — _(no submodules)_- [error-codes](./src/errors/error-codes.md) — Registers the five stable error codes used by `@suaveplan/react-i18n` under the `REACT_I18N` namespace via `defineCodes… - [react-i18n-error](./src/errors/react-i18n-error.md) — Defines `ReactI18nError`, the single error class thrown by the React surface of `@suaveplan/react-i18n`. It extends the… - [with-translation](./src/hoc/with-translation/with-translation.md) — _(no submodules)_- [with-translation](./src/hoc/with-translation/with-translation.md) — _(no submodules)_- [use-currency](./src/hooks/use-currency/use-currency.md) — _(no submodules)_- [use-currency](./src/hooks/use-currency/use-currency.md) — _(no submodules)_- [use-date](./src/hooks/use-date/use-date.md) — _(no submodules)_- [use-date](./src/hooks/use-date/use-date.md) — _(no submodules)_- [use-direction](./src/hooks/use-direction/use-direction.md) — _(no submodules)_- [use-direction](./src/hooks/use-direction/use-direction.md) — _(no submodules)_- [use-error-message](./src/hooks/use-error-message/use-error-message.md) — _(no submodules)_- [use-error-message](./src/hooks/use-error-message/use-error-message.md) — _(no submodules)_- [use-formatter](./src/hooks/use-formatter/use-formatter.md) — _(no submodules)_- [use-formatter](./src/hooks/use-formatter/use-formatter.md) — _(no submodules)_- [use-i18n](./src/hooks/use-i18n/use-i18n.md) — _(no submodules)_- [use-i18n](./src/hooks/use-i18n/use-i18n.md) — _(no submodules)_- [use-list](./src/hooks/use-list/use-list.md) — _(no submodules)_- [use-list](./src/hooks/use-list/use-list.md) — _(no submodules)_- [use-locale](./src/hooks/use-locale/use-locale.md) — _(no submodules)_- [use-locale](./src/hooks/use-locale/use-locale.md) — _(no submodules)_- [use-locale-adapter](./src/hooks/use-locale-adapter/use-locale-adapter.md) — _(no submodules)_- [use-locale-adapter](./src/hooks/use-locale-adapter/use-locale-adapter.md) — _(no submodules)_- [use-locale-detection](./src/hooks/use-locale-detection/use-locale-detection.md) — _(no submodules)_- [detector-chain-context](./src/hooks/use-locale-detection/detector-chain-context.md) — `DetectorChainContext` is the React context that carries the configured locale-detector chain (plus any SSR-authoritati… - [use-locale-detection](./src/hooks/use-locale-detection/use-locale-detection.md) — _(no submodules)_- [use-number](./src/hooks/use-number/use-number.md) — _(no submodules)_- [use-number](./src/hooks/use-number/use-number.md) — _(no submodules)_- [use-plural](./src/hooks/use-plural/use-plural.md) — _(no submodules)_- [use-plural](./src/hooks/use-plural/use-plural.md) — _(no submodules)_- [use-relative-time](./src/hooks/use-relative-time/use-relative-time.md) — _(no submodules)_- [use-relative-time](./src/hooks/use-relative-time/use-relative-time.md) — _(no submodules)_- [use-translate](./src/hooks/use-translate/use-translate.md) — _(no submodules)_- [use-translate](./src/hooks/use-translate/use-translate.md) — _(no submodules)_- [use-translation](./src/hooks/use-translation/use-translation.md) — _(no submodules)_- [use-translation](./src/hooks/use-translation/use-translation.md) — _(no submodules)_- [observability](./src/observability/react-i18n-metrics.md) — _(no submodules)_- [react-i18n-metrics](./src/observability/react-i18n-metrics.md) — _(no submodules)_- [provider](./src/provider/provider.md) — _(no submodules)_- [provider-context](./src/provider/provider-context.md) — Defines the React context that carries the active `I18nInstance` from `@suaveplan/i18n` to every descendant of ` _(no submodules)_- [registry](./src/registry/registry.md) — _(no submodules)_- built-in — _(no submodules… - [built-in](./src/registry/formatters/built-in/built-in.md) — _(no submodules)_- [built-in](./src/registry/formatters/built-in/built-in.md) — _(no submodules)_- [built-in](./src/registry/locale-adapters/built-in/built-in.md) — _(no submodules)_- [built-in](./src/registry/locale-adapters/built-in/built-in.md) — _(no submodules)_- [post-processors](./src/registry/post-processors/post-processors.md) — _(no submodules)_- [post-processors](./src/registry/post-processors/post-processors.md) — _(no submodules)_- [registry-context](./src/registry/registry-context.md) — Module-scoped React context that carries the active `ReactI18nRegistry` to descendants of ``. Direct… - [registry-provider](./src/registry/registry-provider.md) — `` is the React-context surface for `ReactI18nRegistry`. It mounts a fresh registry per tree, registe… - [registry](./src/registry/registry.md) — _(no submodules)_- built-in — _(no submodules… - [registry.schemas](./src/registry/registry.schemas.md) — Strict-object Zod schemas for every plugin kind accepted by `ReactI18nRegistry`. The schemas are the boundary at which… - [use-registry](./src/registry/use-registry.md) — These hooks read the active `ReactI18nRegistry` from React context. The strict variant `useReactI18nRegistry()` throws… - [schemas](./src/schemas/i18n-config.schemas.md) — _(no submodules)_- [i18n-config.schemas](./src/schemas/i18n-config.schemas.md) — _(no submodules)_- [translation-key](./src/translation-key/translation-key.md) — _(no submodules)_- [t-dynamic](./src/translation-key/t-dynamic.md) — `tDynamic(i18n, key, values?)` is the rare-use escape hatch for translation lookups whose key cannot be statically know… - [translation-key](./src/translation-key/translation-key.md) — _(no submodules)_- [env](./src/utils/env.md) — Provides the single environment-detection helper the React surface uses to switch between dev-mode loud-failure and pro… - [identity-instance](./src/utils/identity-instance.md) — Provides the identity translator used as the production-mode fallback when a `useTranslation()` (or any sibling hook) i… - [warn-once-per-process](./src/utils/warn-once-per-process.md) — Implements the warn-once-per-process dedup ring used by every production-mode soft-failure path in `@suaveplan/react-i1… - [fallback-bundle](./src/components/i18n-suspense/fallback-bundle.md) — Ships the strings that `` needs before the active catalog loads its own copies. Consumers can override th… - [i18n-suspense](./src/components/i18n-suspense/i18n-suspense.md) — _(no submodules)_- [language-switcher](./src/components/language-switcher/language-switcher.md) — _(no submodules)_ - [language-switcher](./src/components/language-switcher/language-switcher.md) — _(no submodules)_- [missing-key-overlay](./src/components/missing-key-overlay/missing-key-overlay.md) — _(no submodules)_ - [missing-key-overlay](./src/components/missing-key-overlay/missing-key-overlay.md) — _(no submodules)_- [trans](./src/components/trans/trans.md) — _(no submodules)_ - [stringify-children](./src/components/trans/stringify-children.md) — Helpers that translate a `` `children` block into a canonical ICU message body string so the message parser rend… - [trans](./src/components/trans/trans.md) — _(no submodules)_- [create-i18n-config](./src/config/create-i18n-config.md) — Builds a validated `I18nConfig` from a caller-supplied option bag and is the canonical entry point for ` _(no submodules)_ - [accept-language](./src/detector/accept-language/accept-language.md) — _(no submodules)_- [cloudflare-ip-geo](./src/detector/cloudflare-ip-geo/cloudflare-ip-geo.md) — _(no submodules)_ - [cloudflare-ip-geo](./src/detector/cloudflare-ip-geo/cloudflare-ip-geo.md) — _(no submodules)_- [cookie](./src/detector/cookie/cookie.md) — _(no submodules)_ - [cookie](./src/detector/cookie/cookie.md) — _(no submodules)_- [default-chain](./src/detector/default-chain/default-chain.md) — _(no submodules)_ - [default-chain](./src/detector/default-chain/default-chain.md) — _(no submodules)_- [fallback](./src/detector/fallback/fallback.md) — _(no submodules)_ - [fallback](./src/detector/fallback/fallback.md) — _(no submodules)_- [html-lang](./src/detector/html-lang/html-lang.md) — _(no submodules)_ - [html-lang](./src/detector/html-lang/html-lang.md) — _(no submodules)_- [local-storage](./src/detector/local-storage/local-storage.md) — _(no submodules)_ - [local-storage](./src/detector/local-storage/local-storage.md) — _(no submodules)_- [navigator](./src/detector/navigator/navigator.md) — _(no submodules)_ - [navigator](./src/detector/navigator/navigator.md) — _(no submodules)_- [querystring](./src/detector/querystring/querystring.md) — _(no submodules)_ - [querystring](./src/detector/querystring/querystring.md) — _(no submodules)_- [user-preference](./src/detector/user-preference/user-preference.md) — _(no submodules)_ - [user-preference](./src/detector/user-preference/user-preference.md) — _(no submodules)_- [error-codes](./src/errors/error-codes.md) — Registers the five stable error codes used by `@suaveplan/react-i18n` under the `REACT_I18N` namespace via `defineCodes… - [react-i18n-error](./src/errors/react-i18n-error.md) — Defines `ReactI18nError`, the single error class thrown by the React surface of `@suaveplan/react-i18n`. It extends the… - [with-translation](./src/hoc/with-translation/with-translation.md) — _(no submodules)_ - [with-translation](./src/hoc/with-translation/with-translation.md) — _(no submodules)_- [use-currency](./src/hooks/use-currency/use-currency.md) — _(no submodules)_ - [use-currency](./src/hooks/use-currency/use-currency.md) — _(no submodules)_- [use-date](./src/hooks/use-date/use-date.md) — _(no submodules)_ - [use-date](./src/hooks/use-date/use-date.md) — _(no submodules)_- [use-direction](./src/hooks/use-direction/use-direction.md) — _(no submodules)_ - [use-direction](./src/hooks/use-direction/use-direction.md) — _(no submodules)_- [use-error-message](./src/hooks/use-error-message/use-error-message.md) — _(no submodules)_ - [use-error-message](./src/hooks/use-error-message/use-error-message.md) — _(no submodules)_- [use-formatter](./src/hooks/use-formatter/use-formatter.md) — _(no submodules)_ - [use-formatter](./src/hooks/use-formatter/use-formatter.md) — _(no submodules)_- [use-i18n](./src/hooks/use-i18n/use-i18n.md) — _(no submodules)_ - [use-i18n](./src/hooks/use-i18n/use-i18n.md) — _(no submodules)_- [use-list](./src/hooks/use-list/use-list.md) — _(no submodules)_ - [use-list](./src/hooks/use-list/use-list.md) — _(no submodules)_- [use-locale](./src/hooks/use-locale/use-locale.md) — _(no submodules)_ - [use-locale](./src/hooks/use-locale/use-locale.md) — _(no submodules)_- [use-locale-adapter](./src/hooks/use-locale-adapter/use-locale-adapter.md) — _(no submodules)_ - [use-locale-adapter](./src/hooks/use-locale-adapter/use-locale-adapter.md) — _(no submodules)_- [use-locale-detection](./src/hooks/use-locale-detection/use-locale-detection.md) — _(no submodules)_ - [detector-chain-context](./src/hooks/use-locale-detection/detector-chain-context.md) — `DetectorChainContext` is the React context that carries the configured locale-detector chain (plus any SSR-authoritati… - [use-locale-detection](./src/hooks/use-locale-detection/use-locale-detection.md) — _(no submodules)_- [use-number](./src/hooks/use-number/use-number.md) — _(no submodules)_ - [use-number](./src/hooks/use-number/use-number.md) — _(no submodules)_- [use-plural](./src/hooks/use-plural/use-plural.md) — _(no submodules)_ - [use-plural](./src/hooks/use-plural/use-plural.md) — _(no submodules)_- [use-relative-time](./src/hooks/use-relative-time/use-relative-time.md) — _(no submodules)_ - [use-relative-time](./src/hooks/use-relative-time/use-relative-time.md) — _(no submodules)_- [use-translate](./src/hooks/use-translate/use-translate.md) — _(no submodules)_ - [use-translate](./src/hooks/use-translate/use-translate.md) — _(no submodules)_- [use-translation](./src/hooks/use-translation/use-translation.md) — _(no submodules)_ - [use-translation](./src/hooks/use-translation/use-translation.md) — _(no submodules)_- [observability](./src/observability/react-i18n-metrics.md) — _(no submodules)_ - [react-i18n-metrics](./src/observability/react-i18n-metrics.md) — _(no submodules)_- [provider](./src/provider/provider.md) — _(no submodules)_ - [provider-context](./src/provider/provider-context.md) — Defines the React context that carries the active `I18nInstance` from `@suaveplan/i18n` to every descendant of ` _(no submodules)_- [registry](./src/registry/registry.md) — _(no submodules)_ - [built-in](./src/registry/formatters/built-in/built-in.md) — _(no submodules)_ - [built-in](./src/registry/formatters/built-in/built-in.md) — _(no submodules)_ - [built-in](./src/registry/locale-adapters/built-in/built-in.md) — _(no submodules)_ - [built-in](./src/registry/locale-adapters/built-in/built-in.md) — _(no submodules)_ - [post-processors](./src/registry/post-processors/post-processors.md) — _(no submodules)_ - [post-processors](./src/registry/post-processors/post-processors.md) — _(no submodules)_ - [registry-context](./src/registry/registry-context.md) — Module-scoped React context that carries the active `ReactI18nRegistry` to descendants of ``. Direct… - [registry-provider](./src/registry/registry-provider.md) — `` is the React-context surface for `ReactI18nRegistry`. It mounts a fresh registry per tree, registe… - [registry](./src/registry/registry.md) — _(no submodules)_ - [registry.schemas](./src/registry/registry.schemas.md) — Strict-object Zod schemas for every plugin kind accepted by `ReactI18nRegistry`. The schemas are the boundary at which… - [use-registry](./src/registry/use-registry.md) — These hooks read the active `ReactI18nRegistry` from React context. The strict variant `useReactI18nRegistry()` throws… - [schemas](./src/schemas/i18n-config.schemas.md) — _(no submodules)_ - [i18n-config.schemas](./src/schemas/i18n-config.schemas.md) — _(no submodules)_- [translation-key](./src/translation-key/translation-key.md) — _(no submodules)_ - [t-dynamic](./src/translation-key/t-dynamic.md) — `tDynamic(i18n, key, values?)` is the rare-use escape hatch for translation lookups whose key cannot be statically know… - [translation-key](./src/translation-key/translation-key.md) — _(no submodules)_- [env](./src/utils/env.md) — Provides the single environment-detection helper the React surface uses to switch between dev-mode loud-failure and pro… - [identity-instance](./src/utils/identity-instance.md) — Provides the identity translator used as the production-mode fallback when a `useTranslation()` (or any sibling hook) i… - [warn-once-per-process](./src/utils/warn-once-per-process.md) — Implements the warn-once-per-process dedup ring used by every production-mode soft-failure path in `@suaveplan/react-i1… ## Install ```bash bun add @suaveplan/react-i18n ``` Peer-installs: ```bash bun add react react-dom ``` The package targets `react ^18.0.0 || ^19.0.0` so `useSyncExternalStore` is available without the `use-sync-external-store/shim` polyfill. All internal `@suaveplan/*` deps resolve through the workspace. ## Quick start The minimum tree wires a Provider, a Trans component, and a hook-driven locale switch. The `t` function exposed by `useTranslation()` is the ergonomic-options-bag form from `@suaveplan/i18n`. ```tsx import { Trans, TranslationProvider, createI18nConfig, useTranslation, } from "@suaveplan/react-i18n"; const config = createI18nConfig({ defaultLocale: "en-GB", fallbackLocale: "en-GB", supportedLocales: ["en-GB", "fr-FR"], initialMessages: { "en-GB": { greeting: "Hello, {name}" }, "fr-FR": { greeting: "Bonjour, {name}" }, }, }); function Welcome({ name }: { name: string }): JSX.Element { const { t } = useTranslation(); return ( <>

{t("welcome", { defaultValue: "Welcome" })}

}} />

); } export function App({ children }: { children: React.ReactNode }) { return ( {children} ); } ``` ## Modules Every implementation file ships a sibling `.md` with the canonical sections (Purpose, Features, Basic + Advanced examples, API Reference, Implementation Notes). Read them inline alongside the source. ### Provider and context - [``](./src/provider/provider.md) — mounts an `I18nInstance` and exposes it through React context. Accepts either a caller-managed `i18n` prop (borrowed; not disposed) or a Provider-managed `config` prop (created on mount, disposed on unmount). - [`TranslationContext`](./src/provider/provider-context.md) — the raw context object for advanced consumers (mostly tests). ### Hooks - [`useI18n`](./src/hooks/use-i18n/use-i18n.md) — returns the active `I18nInstance` (or `null` when outside a Provider). - [`useTranslation`](./src/hooks/use-translation/use-translation.md) — Suspense-aware `{ t, i18n, ready }` triple. Auto-triggers `i18n.catalog.preload(locale, namespace)` when a backend is registered and the namespace is not yet loaded. - [`useTranslate`](./src/hooks/use-translate/use-translate.md) — terse alias returning the bound `t` function directly. - [`useLocale`](./src/hooks/use-locale/use-locale.md) — `{ locale, setLocale }` re-rendering on `languageChanged`. - [`useDirection`](./src/hooks/use-direction/use-direction.md) — `{ direction, locale }` derived from `getTextDirection(locale)`. - [`useErrorMessage`](./src/hooks/use-error-message/use-error-message.md) — maps a `SuaveplanError | unknown` to a translated string. - [`usePlural`](./src/hooks/use-plural/use-plural.md) — the plural category + rule for a count + locale. - [`useDate`](./src/hooks/use-date/use-date.md) — memoised `Intl.DateTimeFormat` wrapper. - [`useNumber`](./src/hooks/use-number/use-number.md) — memoised `Intl.NumberFormat` wrapper with the `clearUseNumberCache()` test helper. - [`useCurrency`](./src/hooks/use-currency/use-currency.md) — memoised currency formatter. - [`useRelativeTime`](./src/hooks/use-relative-time/use-relative-time.md) — memoised `Intl.RelativeTimeFormat` wrapper. - [`useList`](./src/hooks/use-list/use-list.md) — memoised `Intl.ListFormat` wrapper. - [`useLocaleDetection`](./src/hooks/use-locale-detection/use-locale-detection.md) — runs the configured detector chain on mount, exposes `{ detected, source, isPending, redetect }`. - [`DetectorChainContext` / `DetectorChainProvider`](./src/hooks/use-locale-detection/detector-chain-context.md) — the context wiring that exposes the chain to descendants. ### Components - [``](./src/components/trans/trans.md) — rich-text component using `MessageParser.formatChunks`. Supports tag interpolation, nested tags, plural via `count`, and a children-as- default-message fallback. - [``](./src/components/language-switcher/language-switcher.md) — headless render-prop component. Receives `{ locales, current, change, isPending }`. Wraps `change` in `useTransition` so namespace loads on locale change do not block urgent updates. - [``](./src/components/missing-key-overlay/missing-key-overlay.md) — dev-mode overlay listing untranslated keys in real-time, capped at 50 entries with `aria-live="polite"`. Renders `null` in production. - [``](./src/components/i18n-suspense/i18n-suspense.md) — convenience wrapper around React's `` with a default `aria-live="polite"` fallback and a fallback-render counter ([`react_i18n.suspense.fallback.total`](./src/observability/react-i18n-metrics.md)). The default loading label is resolved from the active catalog with the bundled English fallback supplied by [`fallback-bundle`](./src/components/i18n-suspense/fallback-bundle.md). - [`stringifyChild` / `childrenToMessageString`](./src/components/trans/stringify-children.md) — internal `` helpers exposed for advanced consumers building custom rich-text components. ### HOC - [`withTranslation`](./src/hoc/with-translation/with-translation.md) — class-component escape hatch. Injects `t` and `i18n` props. ### Locale detectors Each detector is independently importable from `@suaveplan/react-i18n` (and tree-shaken when unused). - [`querystringDetector`](./src/detector/querystring/querystring.md) — `?lang=...` (server URL or browser `location.search`). - [`userPreferenceDetector`](./src/detector/user-preference/user-preference.md) — async fetch against a configurable endpoint; persists on `cache()`. - [`cookieDetector`](./src/detector/cookie/cookie.md) — read + write a configurable cookie. - [`localStorageDetector`](./src/detector/local-storage/local-storage.md) — browser-only; persists to a configurable key. - [`htmlLangDetector`](./src/detector/html-lang/html-lang.md) — reads `document.documentElement.lang`. - [`acceptLanguageDetector`](./src/detector/accept-language/accept-language.md) — server-only; parses `Accept-Language` per RFC 9110. - [`navigatorDetector`](./src/detector/navigator/navigator.md) — iterates `navigator.languages`. - [`cloudflareIpGeoDetector`](./src/detector/cloudflare-ip-geo/cloudflare-ip-geo.md) — server-only; reads `cf-ipcountry` and maps via `@suaveplan/locale-data`. - [`fallbackDetector`](./src/detector/fallback/fallback.md) — always returns the configured fallback. Must appear last in any chain. - [`defaultDetectorChain`](./src/detector/default-chain/default-chain.md) — assembles the canonical 9-entry (or 8-entry, when no `userPreferenceEndpoint` is supplied) chain in spec order. ### Branded TranslationKey - [`TranslationKey` / `AppTranslationKeys` / `ContributedTranslationKeys`](./src/translation-key/translation-key.md) — branded string union pattern. Both interfaces start empty; downstream packages augment `ContributedTranslationKeys` and consumer apps augment `AppTranslationKeys`. - [`tDynamic`](./src/translation-key/t-dynamic.md) — runtime escape hatch. Throws `ReactI18nError(REACT_I18N.UNKNOWN_KEY)` on a missing key; emits a `warn` log on every call so observability surfaces every use site. ### Errors and observability - [`ReactI18nError`](./src/errors/react-i18n-error.md) — `extends SuaveplanError`. The only error type the React surface throws. - [`REACT_I18N_CODES`](./src/errors/error-codes.md) — five frozen codes: `NO_PROVIDER`, `NAMESPACE_LOAD_FAILED`, `HYDRATION_MISMATCH`, `TRANS_INVALID_CHILD`, `UNKNOWN_KEY`. - [`react_i18n.*` OTel instruments](./src/observability/react-i18n-metrics.md) — counters (`missing_key.total`, `suspense.fallback.total`), histogram (`render.duration_ms`), in-memory metrics state ring for tests, plus the public `getReactI18nMetrics()` / `recordMissingKey()` / `recordSuspenseFallback()` / `recordRenderDuration()` helpers. ### Schemas, config, and utils - [`createI18nConfig`](./src/config/create-i18n-config.md) — Zod validator that returns a typed `I18nConfig`. Routes `initialMessages` failures to `ReactI18nError(HYDRATION_MISMATCH)` and other shape failures to `I18nError(I18N.INVALID_OPTIONS)` so observability dashboards group on the React-tier code where appropriate. - [`toI18nInstanceOptions`](./src/config/to-i18n-instance-options.md) — pure mapping from `I18nConfig` to the universal-core `I18nInstanceOptions` shape. - [`I18nConfigSchema` / `TranslationProviderPropsSchema`](./src/schemas/i18n-config.schemas.md) — Zod boundary schemas for the Provider's accepted prop shape and the config bag. - [`isProductionEnv`](./src/utils/env.md) — single source of truth for the dev-vs-prod branch every soft-failure path uses. - [`getIdentityTranslator` / `IDENTITY_TRANSLATION_RETURN`](./src/utils/identity-instance.md) — no-op identity translator returned by `useTranslation` outside a Provider in production builds. - [`warnOncePerProcess`](./src/utils/warn-once-per-process.md) — global bag-of-warnings dedup so a misbehaving consumer logs each diagnostic exactly once across the process lifetime. ## Detector chain wiring The detector chain is the same on the server and the browser; the SSR render captures the resolved locale, embeds it in `initialLocale`, and the client hydrates without re-running browser-only detectors (per the spec's "browser detectors skipped during hydration" requirement). ```tsx import { DetectorChainProvider, TranslationProvider, cookieDetector, defaultDetectorChain, useLocaleDetection, } from "@suaveplan/react-i18n"; const detectors = defaultDetectorChain({ fallback: "en-GB", userPreferenceEndpoint: "/api/me/locale", }); function Bootstrap({ children }: { children: React.ReactNode }) { return ( {children} ); } function LocaleStatus(): JSX.Element { const { detected, source, isPending, redetect } = useLocaleDetection(); return ( {detected ?? "(unresolved)"} via {source ?? "(none)"} ); } ``` For ad-hoc chains, import detectors individually: ```tsx import { DetectorChainProvider, cookieDetector, fallbackDetector, navigatorDetector, } from "@suaveplan/react-i18n"; const detectors = [ cookieDetector({ name: "lang", maxAgeSeconds: 31_536_000 }), navigatorDetector(), fallbackDetector("en-GB"), ]; ``` ## Branded `TranslationKey` The branded type prevents misspelled translation keys from passing typecheck. Both the consumer-app interface (`AppTranslationKeys`) and the downstream-package interface (`ContributedTranslationKeys`) start empty; augmentation contributes the keys. ### Consumer app augmentation In your app, generate the augmentation file from the canonical `locales/en-GB.json` via the [`generate-translation-types.ts`](./scripts/generate-translation-types.ts) script: ```bash bun packages/react/react-i18n/scripts/generate-translation-types.ts \ --source locales/en-GB.json \ --target src/generated/translation-keys.d.ts \ --interface AppTranslationKeys \ --module @suaveplan/react-i18n ``` The script emits a `.d.ts` like: ```ts declare module "@suaveplan/react-i18n" { interface AppTranslationKeys { "app.welcome": true; "app.signin.title": true; "app.signin.submit": true; } } ``` After importing the generated file once at the app entrypoint, every typed `t(literalKey)` call typechecks the key against the registered union. ```ts import type { TranslationKey } from "@suaveplan/react-i18n"; const k: TranslationKey = "app.welcome"; // ✅ typechecks const bad: TranslationKey = "appp.welcome"; // ✗ TS error: not assignable ``` ### Downstream package augmentation When publishing a `react-ui-pack-*` or `react-ui-theme-*` package, augment `ContributedTranslationKeys` instead — that interface is namespaced for downstream contributions so consumer-app augmentations do not collide with library-defined keys. ```ts declare module "@suaveplan/react-i18n" { interface ContributedTranslationKeys { "react-ui.dialog.close": true; "react-ui.dialog.confirm": true; } } ``` The downstream package side-effect-imports the augmentation file from its `index.ts`. Once a consumer adds the package to their tree, the keys become assignable to `TranslationKey` without any per-consumer configuration. ## `tDynamic` runtime escape hatch For the rare case where a key is computed at runtime — most often mapping an error code like `error.code` to `errors:` — use `tDynamic`. It performs a runtime catalog lookup and throws `ReactI18nError(REACT_I18N.UNKNOWN_KEY)` when the key is missing. Every call also emits a `warn`-level log so observability surfaces each use site (the typed `t(literalKey)` path is preferred 99% of the time). ```ts import { ReactI18nError, tDynamic, useI18n } from "@suaveplan/react-i18n"; function ErrorMessage({ error }: { error: { code: string } }): string { const i18n = useI18n(); if (i18n === null) return ""; try { return tDynamic(i18n, `errors:${error.code}`); } catch (cause) { if ( cause instanceof ReactI18nError && cause.code === "REACT_I18N.UNKNOWN_KEY" ) { return error.code; } throw cause; } } ``` ## No-backwards-deps gate `@suaveplan/react-i18n` is the leaf-most React package . Every downstream React package — `@suaveplan/react-ui`, `@suaveplan/react-forms`, every `@suaveplan/react-ui-theme-*`, every `@suaveplan/react-ui-pack-*` — augments `ContributedTranslationKeys` via TypeScript module augmentation. For that pattern to stay sound, react-i18n MUST NOT depend on any of those packages in any of its dep buckets (`dependencies`, `peerDependencies`, `devDependencies`). The CI gate at [`scripts/lint/check-no-backwards-deps.ts`](../../../scripts/lint/check-no-backwards-deps.ts) enforces the rule on every commit: ```bash bun scripts/lint/check-no-backwards-deps.ts \ --package-json packages/react/react-i18n/package.json ``` The script is wired into `package.json`'s `lint` step so `bunx turbo lint --filter=@suaveplan/react-i18n` fails fast if a banned dep ever lands. ## Telemetry OTel instruments published via `getMeter("suaveplan.react-i18n")`: - Counter `react_i18n.missing_key.total` — labels: `locale`, `namespace`, `componentName?`. Incremented from `` (and `tDynamic`) when a key is absent from the catalog. - Counter `react_i18n.suspense.fallback.total` — labels: `namespace`, `locale`. Incremented every time `` renders its default fallback. - Histogram `react_i18n.render.duration_ms` — labels: `locale`, `namespace`, `componentName?`. Recorded around the `` `formatChunks` render. - Counter `i18n.detector.match_total{detector}` — recorded by every detector when it returns a non-null supported locale. - Histogram `i18n.detector.duration_ms{detector}` — recorded for each `detectAsync` call. - Span `i18n.detect` — wraps the entire chain run; carries `winning_detector` and `resolved_locale` attributes. The `tDynamic` call's per-use `warn` log is NOT OTel — it goes to the `@suaveplan/logger` sink and surfaces in centralised log aggregation. ## E2E sweep The Playwright suite at [`e2e/react-i18n.spec.ts`](./e2e/react-i18n.spec.ts) runs against a tiny Vite + React test app at [`e2e/test-app/`](./e2e/test-app/) and covers the five user-visible behaviours: 1. Live language switch through all five locales (`en-GB`, `ar-AE`, `zh-CN`, `cy-GB`, `ru-RU`) with localStorage persistence. 2. RTL flip on Arabic — `` updates and the layout reflows. 3. Lazy-namespace Suspense — the `` fallback resolves to translated content via the async test backend. 4. Missing-key overlay (dev mode) — caps at 50 entries with `aria-live="polite"`. 5. SSR hydration round-trip — the server-rendered HTML already contains the translated string (no flash) and the client hydrates without a React warning. Per `CLAUDE.md` "Web App & Page Verification": every scenario also asserts (a) zero browser-console errors, (b) zero failed network requests (4xx/5xx), and (c) the rendered DOM contains the expected content (not merely a 200 response). ```bash bunx turbo lint typecheck test:coverage build --filter=@suaveplan/react-i18n bun --cwd packages/react/react-i18n test:e2e ``` ## Testing ```bash bunx turbo lint typecheck test --filter=@suaveplan/react-i18n bunx turbo test:coverage --filter=@suaveplan/react-i18n ``` Coverage targets: 100/100/100/100 (statements / branches / functions / lines) per `CLAUDE.md` §"Quality". The thresholds are wired into `vitest.config.ts`. The pre-publish gate also runs the full §13 verification sequence — see `AGENTS.md` for the canonical checklist. ## License MIT.