API reference
Every public export of active-i18n, per entry point - the package's own reference, and every export generated from the source.
First the package's own docs/, included unchanged: the contract. Then
every export of each entry point, generated from the source.
Every public export of @workspace/, per entry point. The
authority is the exports map in package. and the three barrels
(src/, src/, src/); the compiler is authoritative on exact shapes.
Each symbol has exactly one public home. Structure and rationale:
ARCHITECTURE..
Formatting and parsing, and the language code type Locale, are not
exported here: they are owned by @workspace/, which this package
imports (active-). The
former / entry and the root Locale were removed on
2026-10-18 without a second path.
react is an optional peer dependency: only / consumers need it,
and they need React 19 or later (^19.0.0; D30). / reads its
context with React., which React 18 does not have, so React 18 is not
supported. A consumer that typechecks the source provides @types/
^19.0.0 beside it. The root has no React dependency.
next is an optional peer dependency as well: only the Next framework
integrations / and / import it, and both mark
themselves with server- (they load in a React Server Components server
and throw anywhere else). The root and / never reach them (D28).
A host with a resource package usually binds the server runtime once there and
lets its applications import the bound, typed entries from that package rather
than calling create themselves.
Root#
import {...} from '@workspace/
Translation#
- Kind
- function
(translations: Locale. Pure. A miss returns the raw key and calls on; invalid path, invalid value and failed plural selection call on; an exception calls on. Every failure returns the raw key
- Kind
- type
(missing: Missing: the optional observer of a key the tree does not carry. It observes; the result stays the raw key
- Kind
- type
{readonly key: string; readonly locale: Locale
- Kind
- type
Translation: (key: Plain and <K extends keyof Params & string>(key: K, variables): string, where variables must satisfy EVERY key in K (the intersection of their variables, so a key union cannot compile with the variables of one member). The canonical translation contract; a host instantiates it with its own key types
- Kind
- type
Translation with its defaults: any string key, optionally with a variables bag {count?: number; [name: string]: string | number | undefined}
- Kind
- type
Record<string, Record<string, unknown>>: the translation tree keyed by namespace
- Kind
- type
{code: string; label: string; flag?: string; direction?: 'ltr' | 'rtl'}: one entry of the provider's supported. Nothing in this package reads flag, and no language UI may show a flag
Translation semantics (paths, interpolation, plural classification, callback
table): ARCHITECTURE. ยง 6 to ยง 9.
Locale lookup#
RFC 4647 ยง 3.4 lookup (D29, D33): lookup only, not a negotiation engine. No best fit, no likely subtags, no sibling region and no default; the set and what follows a miss are the host's. Framework-free, like the rest of the root.
- Kind
- function
(requested: string, supported. The request is canonicalised (malformed: undefined); the exact canonical tag wins, then the request is truncated one subtag at a time (zh- โ zh- โ zh). Never more specific: pt does not reach pt-. The set must be canonical
- Kind
- function
(requested: readonly string[], supported. The first request of a priority list that lookup answers; each request is truncated before the next is tried (['de- against de, fr gives de). undefined for an empty list or no hit
Language names#
- Kind
- function
(language. The in-sentence name from Intl. in the display language; where Intl gives no name (it cannot be constructed, or answers with the code), the host's label for that code from known, then the upper-case code. Never empty (D28)
- Kind
- function
Same signature. The standalone-label form: the first grapheme cluster upper-cased with the display language's casing rules, for a list of names from different languages
- Kind
- type
readonly Pick<Language: host labels, used only when Intl gives no name
Diagnostics#
- Kind
- type
(source: string) => I18n. The host's logger factory: the runtime asks it once per part for active-, /, / or /. A factory such as active-logging's create fits as it is (D7, D28)
- Kind
- type
{warn(message, meta?), error(message, meta?)}: stable English messages, context in meta
Currency names#
- Kind
- function
(currency. The currency name from Intl. (type: 'currency') in the display language; falls back to the code itself. Never empty
- Kind
- function
(region. The region (country) name from Intl. (type: 'region') in the display language; falls back to the code itself. Never empty for a non-empty code
- Kind
- function
Same signature. The choice label CODE - name (hyphen, never an em-dash), or the bare code when the runtime does not know the name. Resolve it on the server for any server-rendered text: server and browser ICU data may differ
- Kind
- function
(codes: readonly string[], display. The options of a currency picker in display order: config. first, as given and unpruned (deduplicated), then every other code of codes sorted by its name with Intl.. config. ({code, name?}, the value a record carries) is kept at the front when it is in neither list, and its name, resolved on the server, replaces the local one. Names come from get (the code when unknown). The universe of codes is the caller's; nothing is derived from a language or a country and no default is chosen. Fits Currency in active-ui
{code, name}; {priority
Server#
import {...} from '@workspace/
A Next framework integration (D28): it marks itself with server-, so it
loads in a React Server Components server (Next, or a worker that resolves
server- to an empty module) and throws in plain Node and in a client
bundle.
- Kind
- function
(source: Translation. Binds the server runtime to one host source and the host's values. Call once per source at module scope; the loader cache belongs to the returned instance and is on when NODE_ is production at creation. Throws for an empty language set, an entry that is not a well-formed and canonical BCP 47 tag or that is listed twice, and a fallback that is not spelled as one of the entries (D29). options. is the host's one server installation of missing-key observability
- Kind
- type
{get, described below
- Kind
- type
{readonly supported. The language set and fallback are required (D28); every entry is a canonical BCP 47 tag (en-, pt-, zh-), and the fallback is one of them (D29); without on a miss is not reported, without logger nothing is
- Kind
- type
{readonly namespaces: readonly string[]; import. Every namespace is imported per locale; MODULE_ is skipped silently, any other failure with a warning; an empty bundle is left out
- Kind
- type
{preferred
- Kind
- function
From @workspace/, not from the barrel: it reads the request (next/), and the barrel is the runtime a request-free worker may load. () => Promise<string[]>. The Accept- request header as canonical BCP 47 tags with region and script kept (pt-, zh-), quality descending and header order for equal quality, unfiltered against any language set and never truncated (D33). Whitespace around ; and = is allowed and only q counts; dropped are an invalid qvalue (outside 0 to 1 or more than three decimals), q=0, * and a tag Intl refuses (en_); a repeated tag keeps its highest quality; at most 32 entries are read. A list of positive preferences only: it carries no exclusion and no default. For anonymous surfaces only; the host matches it, for example with lookup
The members of Server:
(locale: string) => Promise<{translations, locale}>. Loads every namespace in the entry of the host's supported that answers the given locale (D29: the request is canonicalised; the exact tag wins; only then the same tag with subtags removed from the end, so en- reaches en but never en-, and pt never reaches pt-), otherwise in the host's fallback with a warning. A malformed locale takes the fallback path too. The returned locale is the entry as the host spelled it. A load failure yields an empty tree and an error report
(locale: string) => Promise<{t, locale, translations}>. Same loading; t comes from create
(translations, locale) => Translate. The one server translator constructor of the instance: server-side on/on logging and the host's on. A host binding that types keys binds to it
(title. Translated title, optional description, then additional merged last. A missing key renders as the raw key, like every translation, and is reported through on only; a load failure logs an error
The locale is required on all three; omitting it does not compile.
React#
import {...} from '@workspace/
Client Components only, except the pure time-zone state constructors, which are safe in a Server Component.
Provider and translation hooks#
- Kind
- component
Props I18n. Distributes the translator for one server-resolved locale, wired to the active- logger of the host's factory when given
- Kind
- type
{children; locale; translations: Locale. Without persist the provider touches no storage; it never builds a cookie itself (D28). persist may be synchronous or return any Promise (native promise, object or callable thenable, assimilated like Promise.); the switch navigates only after it returned or its promise fulfilled (D31, D32). confirm is the host's guard for leaving the page, asked before anything is stored; anything other than true, a throw or a rejection resolves 'declined' (D32). A logger that throws never changes an outcome (D32)
- Kind
- type
{locale; t; translations; set. Public as the return type of use, so a caller can name what the hook returns; no workspace consumer uses either today (I18N-FINAL-015)
- Kind
- hook
() => I18n. Throws outside <I18n
- Kind
- hook
() => Translate. Throws outside the provider
- Kind
- hook
() => Locale. Throws outside the provider
- Kind
- hook
() => {locale, set. set matches the request canonically against the offered codes and resolves to a Locale; it never throws and the promise never rejects (D32). Order: confirm (when given), persist (when given), then <html lang> and a full navigation; the outcome of the navigation comes from the browser's beforeunload ('switched' without an objection, 'navigation- with one, 'navigation- when starting it threw). Every outcome except 'switched' and 'pending' leaves the page consistent and accepts a new choice. One switch at a time per provider: a further valid choice while one is being decided, stored or navigated resolves 'pending' (D31)
- Kind
- type
'switched' | 'disabled' | 'unchanged' | 'unavailable' | 'pending' | 'declined' | 'persist-: how a set call ended. Only 'switched' leaves the page. 'navigation- and 'navigation- mean the choice IS stored but this page stays, with <html lang> on its own language; choosing the shown language again stores it again (D31, D32)
Presentation and time zone#
- Kind
- component
Props {profile: Presentation. Distributes the owner's profile; null means "no configured profile"
- Kind
- hook
() => Presentation. Composes provider locale, profile and time zone; pass it as the presentation argument of any formatter. Without profile and zone it behaves like the bare locale. The surface's zone is its time field
- Kind
- component
Props {value; children}, where value is a state built with fixed or viewer. Distributes the surface's time-zone state
- Kind
- hook
() => Iana. The surface's resolved zone, for a calendar-day question (today, calendar); throws when the surface has no resolved zone (D15)
- Kind
- function
(time: the state of a surface whose host determined the zone. Pure; callable from a Server Component
- Kind
- function
(time: the state of a viewer-owned surface, resolved or unresolved. Pure
- Kind
- function
() => Iana. The browser's reported zone, or null
The time-zone state is mechanical and owner-blind: fixed, viewer or
viewer- (no provider). The state type and its readers are internal.
Formatting hook and components#
- Kind
- hook
() => {currency(value: Monetary. The formatters bound to use; no relative-time helper (D18)
- Kind
- component
Props {value: Date | string | number | null | undefined; fallback: string; absolute. Relative text within the recency threshold, absolute beyond it, with the canonical instant in <time date and a reachable absolute reading. The server and the hydrating render show the absolute reading; the policy applies once mounted (D18). The absolute reading uses the surface zone: mount it under a resolved <Time, because without one the server and the browser each read their own zone and the hydrating text can differ. phrase embeds the <time> in a translated sentence: it receives a stand-in and returns the translation with that stand-in interpolated exactly once (it throws otherwise). Not for the displayed value of a sortable or filterable date column
- Kind
- component
Props {value: string; preset?: Date. An instant on a viewer-owned surface, read in the viewer's zone; renders directly when the provider's viewer zone is resolved, otherwise after browser detection. Never on a surface with an administration or system owner
All exports, from the source#
@workspace/ active- i18n#
Functions, hooks and constants
Creates a translation function for a specific locale and translations set.
(localeTranslations: LocaleTranslations, currentLocale: LocaleCode, options?: CreateTranslateFunctionOptions) => TranslateFunctionThe name of a language, written in the language of the reader.
(languageCode: LocaleCode, displayLocale: LocaleCode, knownLabels?: KnownLanguageLabels) => stringThe name of a language in its standalone form: the form that applies when the name stands as a separate label and not inside a sentence.
WHY THIS FUNCTION EXISTS NEXT TO get
Intl. yields the form CLDR calls the *in-sentence* form: the spelling a language name has in the middle of running text. In Dutch, English and German that is a capital letter (Nederlands, English, Deutsch); in French and Spanish a lower-case letter (franรงais, espaรฑol), and that is the correct form there. Both are correct, and get must therefore keep yielding them that way: whoever interpolates a name into a sentence (the fallback notice on the public site) needs exactly that form.
A LIST of names from DIFFERENT languages side by side is something else. There none of those orthographies applies, because there is no sentence and no carrying language; what appears is a series of separate labels. CLDR has the standalone form for that case, and it starts with a capital letter where the script has case. Without it the public language picker reads as Nederlands ยท English ยท Deutsch ยท franรงais ยท espaรฑol: no error per line, but an incoherent list.
WHAT IT IS NOT
Not capitalize(), not char, not CSS text-. It touches exclusively the first GRAPHEME CLUSTER, leaves the rest of the name untouched (so Kreyรฒl ayisyen stays intact), and uses the casing rules of the DISPLAY LANGUAGE (to), so that the Turkish i ends up as ฤฐ and not as I.
It is moreover safe for scripts WITHOUT case: in Chinese, Japanese, Arabic or Hebrew the upper-case mapping is the identity, so ไธญๆ and ุงูุนุฑุจูุฉ come out unchanged. It makes no assumption about the length of a language code, the script or the number of words, and therefore works just as well for pt-, en- and zh-.
(languageCode: LocaleCode, displayLocale: LocaleCode, knownLabels?: KnownLanguageLabels) => stringThe name of a currency, written in the language of the reader.
(currencyCode: string, displayLocale: LocaleCode) => stringThe visible text of a currency choice: CODE - localized name, or only the code when this runtime does not know the name.
The code comes first: it is the identity an administrator recognizes. The symbol stays out on purpose: $ stands for dozens of currencies and kr for several, so it is no identity.
The separator is a hyphen (U+002D) and never an em-dash: the em-dash is forbidden in user-visible text, and an option label is that.
(currencyCode: string, displayLocale: LocaleCode) => stringThe options of a currency picker, in display order: the priority codes, then every other code sorted by its name in the reader's language.
The universe of codes is the caller's (in Datyx list from @workspace/); this helper only names and orders them. Nothing here derives a currency from a language or a country, and nothing chooses a default.
(codes: readonly string[], displayLocale: LocaleCode, config?: CurrencyOptionsConfig) => CurrencyOption[]The name of a region, written in the language of the reader.
(regionCode: string, displayLocale: LocaleCode) => stringThe first entry of a canonical supported set that answers a priority list of requested tags, or undefined when none does: RFC 4647 ยง 3.4 lookup over the list, each request in turn through lookup.
A request is truncated before the next one is tried, so pt- against pt, en gives pt. This is lookup only and not a negotiation engine: no best fit, no likely subtags, no sibling region (en- never reaches en-) and no default. Which set applies and what follows a miss are the host's (D33).
(requested: readonly string[], supportedLocales: readonly string[]) => string | undefinedThe entry of a canonical supported set that answers a requested tag, or undefined when none does (D29).
1. The request is canonicalised; a malformed request matches nothing. 2. The exact canonical tag wins when the set carries it. 3. Only then is the request made less specific, one subtag at a time from the end (RFC 4647 ยง 3.4 lookup): zh- โ zh- โ zh. A request is never made MORE specific, so pt does not pick pt- or pt-, and en- reaches en but never en-.
The set must already be canonical; create refuses one that is not.
(requested: string, supportedLocales: readonly string[]) => string | undefinedTypes
A collection of translations organized by namespace.
Each key is a namespace (e.g., 'common', 'admin', 'sidebar'), and the value contains all translations for that namespace.
type LocaleTranslations = Record<string, Translations>;- Type
type TranslateFunction = Translation Capability;
This package's generic translator: the canonical capability without key knowledge.
THE CANONICAL TRANSLATION CAPABILITY.
This is the ONE contract that says "this value translates". Everything that translates -- this package's generic runtime translator, and every TYPED translator of a host -- is an INSTANTIATION of this type, not a second, parallel concept next to it.
## Generic, and still owner-blind
The two parameters carry the key knowledge, and their DEFAULTS make it empty:
Plainis the set of keys that require no variables; by defaultKey string, so the generic translator accepts any key;Paramsbinds a key to the variables it requires; by default an open record, so the generic translator accepts any variable bag.
A host that KNOWS its keys fills them in -- Translation -- and obtains a STRICTER translator, without this package ever seeing one of that host's keys. active- describes the SHAPE of translating and never the content.
NOTE: lint- does not recognise translators through this type. It knows an explicit list of official translation operations (use, use, create here, and the @workspace/ binders) and infers nothing from a type.
interface TranslationCapability<
PlainKey extends string = string,
Params = Record<string, TranslationVariables | undefined>,
> {
(key: PlainKey): string;
<K extends keyof Params & string>(
key: K,
variables: VariablesForEvery<Params, K>,
): string;
}Callback type for observing a missing key.
It fires only when the namespace or the key path does not exist; the translator still returns the raw key. A malformed path, a non-string value and a failed plural selection stay with on, and a thrown exception with on.
type MissingKeyCallback = (missing: MissingTranslationKey) => void;A translation key that the loaded translations do not carry.
interface MissingTranslationKey {
readonly key: string;
readonly locale: LocaleCode;
}Labels the host already knows for some languages, used only when the environment's Intl. gives no name (D28). The host's own language list (Language) has this shape; Datyx passes its platform language set through @workspace/.
type KnownLanguageLabels = readonly Pick<
LanguageConfig,
'code' | 'label'
>[];One currency choice: the code as data, the name in the reader's language.
interface CurrencyOption {
code: string;
name: string;
}interface CurrencyOptionsConfig {
priorityCodes?: readonly string[];
current?: {code: string; name?: string};
}Configuration for a supported language.
interface LanguageConfig {
code: string;
label: string;
flag?: string;
direction?: 'ltr' | 'rtl';
}One logger, bound to one source name by the host.
interface I18nLogger {
warn(message: string, meta?: Record<string, unknown>): void;
error(message: string, meta?: Record<string, unknown>): void;
}Returns the host's logger for one source name of this package.
type I18nLoggerFactory = (source: string) => I18nLogger;@workspace/ active- i18n/ react#
I18nProvider
Props
- Type
ReactNode
- Type
string
- Type
readonly LanguageConfig[]
- Type
LocaleTranslations
- Type
boolean- Default
true
- Type
(locale) => โฆ
The host's guard for leaving the page (D32), asked with the offered code BEFORE anything is stored. Return (or resolve to) true to go on, or false to keep the page: set then resolves 'declined', nothing is stored and nothing changes. A guard that throws or rejects counts as a refusal and is reported through logger.
A page that protects unsaved work wires that protection here, so the user decides in the host's own words before the choice is stored. When it returns true, the host lets the coming navigation through (its own beforeunload objection is released). Without a guard every switch goes on; a beforeunload objection is then still detected and reported as 'navigation-.
- Type
I18nLogger Factory
The host's logger factory (core/). The provider asks it for the active- logger and reports translation warnings and refused switches through it; without it nothing is reported. A logger that throws is ignored for that report: diagnostics never change an outcome (D32).
- Type
(locale) => โฆ
Records a language choice where the host keeps it (a cookie, storage, a server call), before the provider reloads the page (D28, D31).
SYNCHRONOUS or ASYNCHRONOUS: return nothing when the write is done on return (a cookie: the navigation then starts in the same task), or any Promise that settles when it is done (a server call; a native promise, an object or a function with then, assimilated as Promise. does). The provider navigates only after it returned or its promise fulfilled. A throw, a throwing then or a rejection is a failed switch: no navigation, no <html lang> change, set resolves 'persist- and the failure is reported through logger.
OMITTING it means: touch NO storage. The package never builds a cookie itself: the name, the domain, the lifetime and Secure are the host's contract, in the same shape and for the same reason as the persistence of Theme in active-ui. Datyx passes it through Platform (@workspace/).
Takes only the props listed.
PresentationProfileProvider
Props
Takes only the props listed.
TimeZoneProvider
RecencyTime
Props
- Type
string
What is shown when the value is missing or unreadable. Required and must be supplied translated; active- does not translate.
- Type
stringnumberDatenullundefined
The instant: an ISO 8601 instant with Z or an offset, a Date or an epoch number. A zone-less date-time is not an instant and shows fallback (D18).
- Type
(absoluteText: string) => string
Accessible label for the absolute reading, translated by the caller. Appears as screen-reader text next to the relative text, for example "On 9 March 2026 at 21:18". If it is missing, only title plus date carry the absolute value.
- Type
string
- Type
RecencyOptions
Passed to resolve: preset and threshold.
- Type
(recency: string) => string
Embeds the recency in a translated sentence (D18). Receives a stand-in for the recency and returns the caller's translated text with that stand-in interpolated exactly once, for example (last. The component renders the sentence around a semantic <time>, so a translation stays one whole sentence in every language. Without it, the component renders the <time> alone.
Takes only the props listed.
ViewerDateTime
Props
- Type
string
What is shown while the viewer's zone is not known. That is only the case when the host supplies no resolved viewer zone: a public or anonymous screen, or a user before their first bootstrap. Required and must be supplied translated: active- does not translate.
- Type
string
The instant as a canonical ISO instant with Z. Deliberately a string and not a Date: this is the form that travels across the RSC boundary, and by contract it is zone-unambiguous.
- Type
string
- Type
DatePreset - Default
'datetime'
What is shown. Defaults to the readable date-time.
Takes only the props listed.
Functions, hooks and constants
- Type
() => I18nContext Value
Returns
An object with these fields.
- Type
string
- Type
TranslateFunction
- Type
LocaleTranslations
- Type
(newLocale) => โฆ
Switches the language (D31, D32). Never throws and the promise never rejects, whatever the host's guard, writer or logger does: it resolves to the Locale. A caller that does not need the outcome may ignore it (void set).
- Type
readonly string[]
- Type
readonly LanguageConfig[]
- Type
boolean
- Type
(code) => โฆundefined
- Type
LanguageConfig | undefined
- Type
() => LocaleCode
() => Pick<I18nContextValue, "locale" | "setLocale" | "availableLocales" | "availableLanguages" | "allowLocaleSwitching" | "currentLanguage" | "getLanguage">Returns
An object with these fields.
- Type
string
- Type
(newLocale) => โฆ
Switches the language (D31, D32). Never throws and the promise never rejects, whatever the host's guard, writer or logger does: it resolves to the Locale. A caller that does not need the outcome may ignore it (void set).
- Type
readonly string[]
- Type
readonly LanguageConfig[]
- Type
boolean
- Type
(code) => โฆundefined
- Type
LanguageConfig | undefined
- Type
() => TranslateFunction
- Type
() => PresentationContext
The composed presentation context of the current reader: language from I18n, notation from the owner's profile, and the business time zone from Time. The result fits unchanged as the presentation argument of every central formatter (date, number, percentage, currency). Without mounted providers the outcome behaves the same as the bare language code.
Three sources, one composition site. Language belongs to the reader, notation to the owner, zone also to the owner but from its own column and its own chain. They come together here and nowhere else, so no second composition can arise that falls out of step.
The memo keys on content (five scalar fields) and not on object identity: the profile object arrives freshly deserialized from the server on every RSC render, and a referentially fresh-but-equal context would make every consumer with the object in a dependency array (grids, charts, formatter hooks) recompute needlessly; in charts this is visible as an aborted entrance animation.
Returns
An object with these fields.
- Type
string
The language of the reader: words, labels, month names.
- Type
"LONG_TEXTUAL" "NUMERIC""SHORT_TEXTUAL"
The normal human date shape of the owner of this surface. If absent, the platform fallback SHORT_ applies (PP-054 level 3).
- Type
"DMY_NUMERIC" "ISO_NUMERIC" "MDY_NUMERIC"
Structural date notation of the administration, if configured.
- Type
"H12""H24"
Clock notation of the administration, if configured.
- Type
"COMMA_DECIMAL_ DOT_ GROUP" "COMMA_DECIMAL_ SPACE_ GROUP" "DOT_DECIMAL_ COMMA_ GROUP"
Number notation of the administration, if configured.
- Type
"CODE""SYMBOL"
Currency display style of the administration, if configured.
- Type
IanaTime Zone
The business time zone of the owner of this surface.
A sister dimension, not a fifth notation field. It comes from its own storage field (Tenant. or Application respectively) and its own resolution chain, and is explicitly not part of Presentation โ the stored notation carries exactly five dimensions per test, and that is a decision.
It travels along here because the call site of a formatter needs both: the shape of an instant and the moment being shown. That way no existing call needs to learn an extra argument.
If absent, the viewer reads their own zone โ the correct outcome on personal and public surfaces.
- Type
() => IanaTime Zone
The zone of this surface, for a calendar-day question that cannot be answered without one: "which day is today" (today) or "on which day does this instant fall" (calendar) (D15).
The same zone as use, but required: a surface whose zone has not been resolved throws a configuration error instead of letting the runtime decide the day. There is no fallback to UTC, to the browser or to another owner. A surface that asks a calendar-day question mounts a <Time with a resolved state.
Returns
An object with these fields.
- Type
"IanaTime Zone"
- Type
(timeZone: Iana Time Zone) => Time Zone State
A surface whose host has determined the zone, for example from the owner of the data on screen. This package does not know those owners and need not know them.
A surface that belongs to the viewer.
null means "the viewer zone has not (yet) been resolved" and yields UNRESOLVED_ โ explicitly not a fallback to a zone from another source.
(timeZone: IanaTimeZone | null | undefined) => TimeZoneState- Type
() => FormatUtils
Hook to get locale-aware formatting utilities.
Returns
An object with these fields.
- Type
(value, options?) => string
Format a monetary amount according to locale conventions.
The currency identity is required and comes from the data; the hook supplies the presentation from use.
- Type
(value, format?) => string
Format a number with a semantic preset (never a free Intl options bag)
- Type
(value, preset?) => string
Format a stored FRACTION (0.125 means 12.5%) as a percentage. For values stored in percentage points (12.5 means 12.5%) use Format โ the source unit is part of the name so no call site can guess it.
- Type
(value, preset?) => string
Format stored PERCENTAGE POINTS (12.5 means 12.5%) as a percentage.
- Type
(date, preset?) => string
Format a date. Without a preset the call inherits the normal human date form of the presentation; a preset is a semantic exception with a justification.
- Type
(date, preset?) => string
Format a calendar day (date of birth, start date, any @db. column): the same day in every time zone. For an instant use Format. Without a preset: inherit.
- Type
() => IanaTime Zone | null
The IANA zone the browser reports, or null when it does not supply a usable one.
null is a valid outcome and not an error: the caller then omits the zone, and the formatting layer uses the runtime zone, which in a browser is exactly the same zone. The degradation is therefore behaviour-neutral, and it is explicitly not a fallback to UTC or to a business zone.
Server-side this function always returns null: Intl reports the process zone there (UTC, ADR-016), and that says nothing about the viewer.
This is also the source of the one-time bootstrap of TZ-P21: the host reads it, validates it and stores it once. This component itself never stores anything.
Types
interface I18nContextValue {
locale: LocaleCode;
t: TranslateFunction;
translations: LocaleTranslations;
setLocale: (newLocale: LocaleCode) => Promise<LocaleSwitchOutcome>;
availableLocales: readonly string[];
availableLanguages: readonly LanguageConfig[];
allowLocaleSwitching: boolean;
getLanguage: (code: string) => LanguageConfig | undefined;
currentLanguage: LanguageConfig | undefined;
}The props of I18n, each described in its prop list on this page.
interface I18nProviderProps {
children: ReactNode;
locale: LocaleCode;
translations: LocaleTranslations;
supportedLanguages: readonly LanguageConfig[];
allowLocaleSwitching?: boolean;
persistLocale?: (locale: LocaleCode) => void | PromiseLike<void>;
confirmLocaleSwitch?: (locale: LocaleCode) => boolean | PromiseLike<boolean>;
logger?: I18nLoggerFactory;
}How a set call ended (D31, D32). Only 'switched' leaves the page; every other outcome leaves it consistent and accepts a new choice, except 'pending', which reports that a switch is still under way.
'switched': the choice is stored (or there is no storage),<html lang>carries it, and the browser is leaving the page: itsbeforeunloadcame without an objection.'disabled': the provider hasallow.Locale Switching={false} 'unchanged': the requested language is the current one.'unavailable': the requested tag is malformed or not offered.'pending': an earlier switch of this provider is still being decided, stored or navigated; this call did nothing.'declined':confirmrefused, or failed; nothing was stored and nothing changed.Locale Switch 'persist-:failed' persistthrew or its promise rejected; nothing navigated andLocale <html lang>is untouched.'navigation-: the choice IS stored, but starting the navigation threw;failed' <html lang>is back on the current language.'navigation-: the choice IS stored, but aguarded' beforeunloadhandler of the page objected to leaving, so the browser asks the user. The provider has put<html lang>back on the current language: if the user stays, the page is consistent and a new choice is accepted (choosing the current language again stores it again); if the user leaves, the next page renders the stored choice.
type LocaleSwitchOutcome =
| 'switched'
| 'disabled'
| 'unchanged'
| 'unavailable'
| 'pending'
| 'declined'
| 'persist-failed'
| 'navigation-failed'
| 'navigation-guarded';@workspace/ active- i18n/ server#
Functions, hooks and constants
Binds the generic server translation runtime to a host's resources.
This package knows no namespace and no resource location; the host declares both in source and publishes the returned entry points from its own server module. Call it once per source, at module scope: the loader cache belongs to the returned instance. The host also supplies the language set and fallback its resources carry (required; a configuration that cannot answer every request throws here), its logger factory, and options., the host's one installation point for missing-key observability on the server: every translator of the returned instance carries it (D28).
(source: TranslationSource, options: ServerTranslatorOptions) => ServerTranslationsTypes
The server translation entry points of one host's translation source.
interface ServerTranslations extends ServerTranslators {
getTranslatedMetadata: TranslatedMetadata;
}Where a host's translation resources come from.
import performs the host's own module import; the loader reads its default export as the namespace bundle. A module that does not exist (MODULE_) yields no entry silently; any other failure yields no entry and a warning.
interface TranslationSource {
readonly namespaces: readonly string[];
importNamespace(
locale: string,
namespace: string,
): Promise<{readonly default: unknown}>;
}Host choices for the server translators of one source.
interface ServerTranslatorOptions {
readonly supportedLocales: readonly string[];
readonly fallbackLocale: string;
readonly onMissingKey?: MissingKeyCallback;
readonly logger?: I18nLoggerFactory;
}Options for translated metadata generation.
interface TranslatedMetadataOptions {
descriptionKey?: string;
preferredLocale: string;
additionalMetadata?: Partial<Metadata>;
}@workspace/ active- i18n/ server/ get- locale#
Functions, hooks and constants
- Type
() => Promise<string[]>
The language preferences from the Accept- header, sorted by quality and normalised -- unfiltered.
Deliberately not checked against a language set: which set applies is a runtime policy question (ENABLED), and it does not belong in an owner-blind package. The caller filters, and that is resolve in @workspace/.
This source is valid only on an anonymous surface (LANG- class 2). On a surface with a known identity the browser language is no ongoing authority: it never overrides a stored choice.
It is not a precedence chain but a plain reading of one request header.