first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,114 @@
# `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
```ts
import { getIdentityTranslator } from "@suaveplan/react-i18n/utils/identity-instance";
const t = getIdentityTranslator();
t("hello"); // "hello"
t("hello", { defaultValue: "Hi" }); // "Hi"
```
## Usage: Advanced Example
```ts
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`
```ts
(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.