first commit
This commit is contained in:
@@ -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).
|
||||
Reference in New Issue
Block a user