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,98 @@
# DisplayNameFormatter
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
`DisplayNameFormatter` and the `formatDisplayName` standalone helper
expose `Intl.DisplayNames` for the `@suaveplan/i18n` family at the
canonical Wave-3 formatter surface: Zod-validated options, structured
error mapping, per-(locale, type, style, fallback) cache, and OTel
emission. Consumers convert ISO codes (`"GB"`, `"USD"`, `"fr"`,
`"gregory"`) into their localised display names — the universal way to
render country names, currencies, languages, scripts, and calendar
identifiers in a user's locale.
## Features
- `DisplayNameFormatter` class with stored options + `format(code, locale)` method
- `formatDisplayName(code, locale, options)` standalone helper
- All six `Intl.DisplayNames` `type` values: `language` / `region` / `script` / `currency` / `calendar` / `dateTimeField`
- Three `style` values: `long` / `short` / `narrow`
- Two `fallback` policies: `code` (default) / `none`
- Construction-time Zod validation with `INVALID_FORMATTER_OPTIONS` mapping
- `Intl.DisplayNames` `RangeError` mapped to `UNSUPPORTED_LOCALE` with original error attached as `cause`
- Per-(locale, type, style, fallback) cache — repeated calls reuse the same `Intl.DisplayNames`
- `clearDisplayNameCache()` test-only helper
## Usage: Basic Example
```ts
import { formatDisplayName } from "@suaveplan/i18n-formatter-display-name";
formatDisplayName("GB", "en-GB", { type: "region" }); // "United Kingdom"
formatDisplayName("fr", "en-GB", { type: "language" }); // "French"
formatDisplayName("USD", "en-GB", { type: "currency" }); // "US Dollar"
```
## Usage: Advanced Example
```ts
import {
DisplayNameFormatter,
type DisplayNameFormatterOptions,
} from "@suaveplan/i18n-formatter-display-name";
const opts: DisplayNameFormatterOptions = {
type: "region",
style: "short",
fallback: "none",
};
const f = new DisplayNameFormatter(opts);
// Reuses the same cached Intl.DisplayNames per locale.
const us = f.format("US", "en-GB");
const fr = f.format("FR", "fr-FR");
// Unknown region with fallback: "none" returns the code unchanged.
const unknown = f.format("ZZ", "en-GB"); // "ZZ"
```
## API Reference
### `formatDisplayName(code, locale, options): string`
Standalone helper. Validates `options` via Zod, looks up or constructs
the cached `Intl.DisplayNames`, and returns
`formatter.of(code) ?? code`. Throws `I18nError(INVALID_FORMATTER_OPTIONS)`
on Zod failure or `I18nError(UNSUPPORTED_LOCALE)` on
`Intl.DisplayNames` `RangeError`.
### `class DisplayNameFormatter`
- `constructor(options: DisplayNameFormatterOptions)` — stores options after Zod validation
- `format(code: string, locale: string): string` — same semantics as the standalone
### `clearDisplayNameCache(): void`
Test-only helper that empties the per-(locale, type, style, fallback)
cache.
## Implementation Notes
- The cache is a process-wide `Map<string, Intl.DisplayNames>` keyed
by `${locale}|${type}|${style}|${fallback}`. The single shared
cache is a deliberate choice — `Intl.DisplayNames` instances are
immutable, so cross-call reuse is safe.
- `formatter.of(code)` returns `undefined` when the input is not a
recognised code AND `fallback: "none"` was specified. The `?? code`
fallback returns the input unchanged in that case.
- OTel histogram `i18n.format.display_name.duration_ms` records the
end-to-end format time per call; counter
`i18n.format.cache_hit{formatter="display_name"}` increments on
cache reuse only (not on first miss).
- Construction-time validation ensures the class never wraps invalid
options. The standalone re-validates on every call (cheap — a Zod
`safeParse` over a 3-field object).