@samveys/i18n

Intl formatting, locale negotiation and MessageFormat 2 translations

Version
1.0.3Nov 5, 2026
Install
pnpm add @samveys/i18n

This list was read from version 1.0.2; run pnpm sync to refresh it.

Import
import { createI18nManager, defineI18nConfig, i18n, negotiateLocale, parseAcceptLanguage } from '@samveys/i18n'

Function (5)

createI18nManager Function

No documentation comment.

function createI18nManager(config: I18nConfig): I18nManager;

Exported from packages/i18n/src/manager.ts

defineI18nConfig Function

Typed helper for `i18n({ ... })` config.

function defineI18nConfig<const C extends I18nConfig>(config: C): C;

Exported from packages/i18n/src/manager.ts

i18n Function

The `@samveys/i18n` plugin: binds `'i18n'`, and adds `ctx.locale` and `ctx.i18n` to every request.

function i18n(config: I18nConfig): import("@samveys/core").Plugin<I18nConfig>;

Exported from packages/i18n/src/plugin.ts

negotiateLocale Function

Chooses the supported locale for a request, or `fallback`. For each requested tag, in quality order: an exact match (case-insensitive), then the bare language (`id-ID` → `id`), then any supported locale of the same language (`en-GB` → `en-US`).

function negotiateLocale(header: string | null | undefined, supported: readonly string[], fallback: string): string;

Exported from packages/i18n/src/negotiate.ts

parseAcceptLanguage Function

Parses `Accept-Language` into tags sorted by quality (stable for equal q). `q=0` entries and `*` are dropped.

function parseAcceptLanguage(header: string | null | undefined): readonly string[];

Exported from packages/i18n/src/negotiate.ts

Interface (4)

I18nConfig Interface

No documentation comment.

interface I18nConfig {
    /** Locale used when the request names none we support. */
    readonly defaultLocale: string;
    /** Catalog consulted when the requested locale lacks a key. Default: `defaultLocale`. */
    readonly fallbackLocale?: string;
    /**
     * Locales the app serves. Default: `defaultLocale`, `fallbackLocale`, every `lang/<locale>.json`
     * file and every key of `messages`.
     */
    readonly locales?: readonly string[];
  …
Show the whole declaration (19 lines)
interface I18nConfig {
    /** Locale used when the request names none we support. */
    readonly defaultLocale: string;
    /** Catalog consulted when the requested locale lacks a key. Default: `defaultLocale`. */
    readonly fallbackLocale?: string;
    /**
     * Locales the app serves. Default: `defaultLocale`, `fallbackLocale`, every `lang/<locale>.json`
     * file and every key of `messages`.
     */
    readonly locales?: readonly string[];
    /** Directory of `<locale>.json` catalogs, relative to the working directory. Default `lang`. */
    readonly langDir?: string;
    /** Catalogs given in code. They win over files with the same locale and key. */
    readonly messages?: Readonly<Record<string, MessageCatalog | NestedCatalog>>;
    /** Throw SVS_E111 for a key missing from the locale and the fallback (instead of returning the key). */
    readonly strict?: boolean;
    /** Time zone for `date()`. Default: the process zone. */
    readonly timeZone?: string;
}

Exported from packages/i18n/src/contracts.ts

I18nManager Interface

No documentation comment.

interface I18nManager {
    /** The locales the app serves, in the order they were configured. */
    readonly locales: readonly string[];
    readonly defaultLocale: string;
    /** A translator for `locale` (any BCP 47 tag; unsupported ones format with the default locale's catalog). */
    for(locale?: string): Translator;
    /** Picks the best supported locale for an `Accept-Language` header; the default when nothing fits. */
    negotiate(acceptLanguage: string | null | undefined): string;
}

Exported from packages/i18n/src/contracts.ts

NestedCatalog Interface

A catalog file may nest keys: `{ "cart": { "items": "…" } }` is the key `cart.items`.

interface NestedCatalog {
    readonly [key: string]: string | NestedCatalog;
}

Exported from packages/i18n/src/contracts.ts

Translator Interface

Everything that depends on one locale.

interface Translator {
    /** The BCP 47 tag this translator formats with, e.g. `id-ID`. */
    readonly locale: string;
    /** Translates `key` as MessageFormat 2 with `values`. */
    t(key: string, values?: MessageValues): string;
    /** `money(1250001, 'IDR')` → `Rp 1.250.001` in `id-ID`. */
    money(amount: number | bigint, currency: string): string;
    number(value: number | bigint, options?: Intl.NumberFormatOptions): string;
    /** `date(value, 'long')`. `value` is a Date, epoch milliseconds or an ISO string. */
    date(value: Date | number | string, style?: DateStyle): string;
  …
Show the whole declaration (19 lines)
interface Translator {
    /** The BCP 47 tag this translator formats with, e.g. `id-ID`. */
    readonly locale: string;
    /** Translates `key` as MessageFormat 2 with `values`. */
    t(key: string, values?: MessageValues): string;
    /** `money(1250001, 'IDR')` → `Rp 1.250.001` in `id-ID`. */
    money(amount: number | bigint, currency: string): string;
    number(value: number | bigint, options?: Intl.NumberFormatOptions): string;
    /** `date(value, 'long')`. `value` is a Date, epoch milliseconds or an ISO string. */
    date(value: Date | number | string, style?: DateStyle): string;
    /** `date` and time. */
    dateTime(value: Date | number | string, style?: DateStyle): string;
    /** `list(['a', 'b', 'c'])` → `a, b, and c` (en) / `a, b, dan c` (id). */
    list(items: readonly string[], type?: ListStyle): string;
    /** "3 days ago" / "in 2 hours", choosing the largest fitting unit. `now` is for tests. */
    relative(value: Date | number | string, now?: Date | number): string;
    /** True when `key` has a message in this locale or the fallback. */
    has(key: string): boolean;
}

Exported from packages/i18n/src/contracts.ts

Type (4)

DateStyle Type

Public contracts of `@samveys/i18n`.

type DateStyle = 'short' | 'medium' | 'long' | 'full';

Exported from packages/i18n/src/contracts.ts

ListStyle Type

No documentation comment.

type ListStyle = 'conjunction' | 'disjunction' | 'unit';

Exported from packages/i18n/src/contracts.ts

MessageCatalog Type

No documentation comment.

type MessageCatalog = Readonly<Record<string, string>>;

Exported from packages/i18n/src/contracts.ts

MessageValues Type

No documentation comment.

type MessageValues = Readonly<Record<string, unknown>>;

Exported from packages/i18n/src/contracts.ts