first commit
This commit is contained in:
78
docs/ui/react/react-ui/src/locales/schema.md
Normal file
78
docs/ui/react/react-ui/src/locales/schema.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# `LocaleBundleSchema` — Zod schema for `@suaveplan/react-ui` locale bundles
|
||||
|
||||
## Purpose
|
||||
|
||||
Zod schema asserting that every locale bundle declares exactly the keys
|
||||
present in the canonical `en-GB.json` source-of-truth. The schema is
|
||||
built dynamically from `en-GB.json` itself so adding a key in English
|
||||
automatically tightens the contract for every other locale shipped by
|
||||
the package — there is no place for a translator to add a key that the
|
||||
English bundle has not blessed first.
|
||||
|
||||
## Features
|
||||
|
||||
- Strict mode (`.strict()`) rejects extra keys so a stray entry in
|
||||
`cy-GB.json` cannot silently leak into a consumer's `t()` call surface
|
||||
- Every key is required and typed as `z.string()`
|
||||
- `REACT_UI_BUNDLE_KEYS` exposes the exhaustive key list as a const
|
||||
array so other parts of the chassis (the `<ReactUiProvider>` mount
|
||||
hook, the registry-completeness CI gate, the augmentation generator)
|
||||
can iterate the contracted keys without re-importing the JSON file
|
||||
|
||||
## Usage: Basic example
|
||||
|
||||
```ts
|
||||
import { LocaleBundleSchema } from "@suaveplan/react-ui/locales";
|
||||
import frFR from "./fr-FR.json";
|
||||
|
||||
const parsed = LocaleBundleSchema.safeParse(frFR);
|
||||
if (!parsed.success) {
|
||||
throw new Error(`fr-FR is missing keys: ${parsed.error.message}`);
|
||||
}
|
||||
```
|
||||
|
||||
## Usage: Advanced example
|
||||
|
||||
```ts
|
||||
import {
|
||||
LocaleBundleSchema,
|
||||
REACT_UI_BUNDLE_KEYS,
|
||||
reactUiBundles,
|
||||
SUPPORTED_LOCALES,
|
||||
} from "@suaveplan/react-ui/locales";
|
||||
|
||||
// Fail-fast key parity check at app startup
|
||||
async function assertKeyParity(): Promise<void> {
|
||||
for (const locale of SUPPORTED_LOCALES) {
|
||||
const bundle = await reactUiBundles[locale]();
|
||||
const result = LocaleBundleSchema.safeParse(bundle);
|
||||
if (!result.success) {
|
||||
throw new Error(`Locale ${locale} failed schema: ${result.error.message}`);
|
||||
}
|
||||
for (const key of REACT_UI_BUNDLE_KEYS) {
|
||||
if (!(key in bundle)) {
|
||||
throw new Error(`Locale ${locale} missing key ${key}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `LocaleBundleSchema: z.ZodObject<...>` — Zod schema with one
|
||||
`z.string()` field per key in `en-GB.json`. Strict.
|
||||
- `type LocaleBundle = z.infer<typeof LocaleBundleSchema>` — typed
|
||||
bundle shape. Equivalent to a `Record` over the contracted key set.
|
||||
- `REACT_UI_BUNDLE_KEYS: readonly string[]` — exhaustive key list.
|
||||
|
||||
## Implementation notes
|
||||
|
||||
The schema is built at module-load time by walking
|
||||
`Object.keys(enGB)` rather than at type-only level. That means adding
|
||||
a key to `en-GB.json` does not require regenerating any TypeScript file
|
||||
to extend the schema — the runtime build picks up the new key on the
|
||||
next module evaluation. The accompanying `augmentation.ts` file IS
|
||||
generated and DOES need to be regenerated when keys change; the
|
||||
`scripts/check-locale-completeness.ts` CI gate fails the build if a key
|
||||
appears in `en-GB.json` but is absent from any other locale bundle.
|
||||
Reference in New Issue
Block a user