4.3 KiB
identity-instance.ts
Purpose
Provides the identity translator used as the production-mode fallback
when a useTranslation() (or any sibling hook) is called outside a
<TranslationProvider> ancestor. The fallback exists so production
bundles don't crash on a null destructure — instead they degrade to a
visibly-broken-but-not-blocking state where every key renders as its
literal key string, and the misconfiguration is logged once via the
warn-once helper.
The dev-mode counterpart is a thrown ReactI18nError(NO_PROVIDER). The
split is by environment, not by hook — every hook that can be called
outside a Provider must use this fallback in production.
Features
- Stable reference identity:
getIdentityTranslator()returns the same function reference on every call so memoisation in consumers does not churn. IDENTITY_TRANSLATION_RETURN— a frozen singleton-shaped object matchingUseTranslationReturnso destructuring works without allocating a fresh object per fallback render.- Honours
options.defaultValuesot("missing", { defaultValue: "x" })still returns"x"even on the fallback path. This is the same contract the universal-corethonours, so consumers don't need to branch onready.
Usage: Basic Example
import { getIdentityTranslator } from "@suaveplan/react-i18n/utils/identity-instance";
const t = getIdentityTranslator();
t("hello"); // "hello"
t("hello", { defaultValue: "Hi" }); // "Hi"
Usage: Advanced Example
import { useState } from "react";
import {
IDENTITY_TRANSLATION_RETURN,
type IdentityTranslationReturn,
} from "@suaveplan/react-i18n/utils/identity-instance";
import type { UseTranslationReturn } from "@suaveplan/react-i18n";
function useFallbackOrLive(
live: UseTranslationReturn | null
): UseTranslationReturn | IdentityTranslationReturn {
return live ?? IDENTITY_TRANSLATION_RETURN;
}
API Reference
getIdentityTranslator(): IdentityTranslator
Returns a stable reference to the identity translator function. Same reference on every call.
IDENTITY_TRANSLATION_RETURN: IdentityTranslationReturn
Frozen singleton-shaped object with { t, i18n: undefined, ready: false }.
Mirrors UseTranslationReturn on the failure branch so consumers can
destructure safely. The i18n field is intentionally undefined
(not null) so the runtime distinction with a real instance is
trivial.
interface IdentityTranslator
(key: string, options?: IdentityTranslatorOptions) => string;
Returns options.defaultValue when provided, else the key string.
interface IdentityTranslatorOptions
Mirrors the ergonomic-options-bag the universal-core t accepts.
Carries defaultValue, count, and an open record of additional
fields so the fallback is signature-compatible with the live
translator.
interface IdentityTranslationReturn
The exact return shape used by the production-mode fallback path of
useTranslation(). The i18n field is undefined (not null) and
ready is the literal false so a TypeScript narrow on ready lets
consumers branch into the fallback's specific shape.
Implementation Notes
- The translator function is a module-level constant, not a per-call
factory product. Returning the same function reference is critical
because consumers downstream can
useMemoontto skip work; a fresh function reference per call would invalidate that memo. - The
IDENTITY_TRANSLATION_RETURNobject is constructed once at module load and shared. Consumers MUST NOT mutate it (the field types arereadonlyand the object is the singular shared instance). - The fallback honours
defaultValuebecause doing otherwise would silently regress the production-mode behaviour of any string with a default —t("greeting", { defaultValue: "Hi" })becomes"greeting"instead of"Hi", which is a worse failure mode than the known identity behaviour. - The fallback intentionally does NOT honour interpolation
(
{{count}}-style) because doing so would couple the React-tier fallback to the universal-core interpolation engine — the whole point of the identity path is to avoid the engine entirely. If a consumer wants interpolation in production-mode no-Provider rendering, they should write a Provider rather than rely on the fallback.