Files
skills/docs/localization/i18n/react-i18n/src/utils/identity-instance.md
2026-05-29 08:20:56 +01:00

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 matching UseTranslationReturn so destructuring works without allocating a fresh object per fallback render.
  • Honours options.defaultValue so t("missing", { defaultValue: "x" }) still returns "x" even on the fallback path. This is the same contract the universal-core t honours, so consumers don't need to branch on ready.

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 useMemo on t to skip work; a fresh function reference per call would invalidate that memo.
  • The IDENTITY_TRANSLATION_RETURN object is constructed once at module load and shared. Consumers MUST NOT mutate it (the field types are readonly and the object is the singular shared instance).
  • The fallback honours defaultValue because 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.