i18n formatting
atemporal uses Intl.DateTimeFormat for locale-aware formatting, so all standard BCP 47 locale tags work out of the box.
Default locale
import atemporal from 'atemporal';
atemporal.setDefaultLocale('es');
atemporal('2024-01-15T12:34:56Z').format({ dateStyle: 'full', timeStyle: 'short' });
// 'lunes, 15 de enero de 2024, 12:34'Per-call override
atemporal('2024-01-15T12:34:56Z').format(
{ dateStyle: 'long' },
'fr'
);
// '15 janvier 2024'Common locales cheat-sheet
| Locale | Sample output (dateStyle: 'long') |
|---|---|
en | January 15, 2024 |
en-GB | 15 January 2024 |
es | 15 de enero de 2024 |
fr | 15 janvier 2024 |
de | 15. Januar 2024 |
ja | 2024年1月15日 |
zh | 2024年1月15日 |
ar | ١٥ يناير ٢٠٢٤ (RTL) |
he | 15 בינואר 2024 (RTL) |
Token strings vs Intl options
atemporal supports two formatting modes:
| Mode | Example | When to use |
|---|---|---|
| Token | .format('YYYY-MM-DD') | Stable, machine-readable, log-friendly |
| Intl opts | .format({ dateStyle: 'full' }) | Locale-aware, user-facing, "natural" |
The token mode is not localized. MMMM is always the English month name. If you need "January" / "enero" / "1月", use the Intl options mode.
Mixed: token + locale
// Locale-aware weekday name with token-style date
atemporal('2024-01-15').format('DD [de] MMMM [de] YYYY', 'es');
// '15 de enero de 2024'The [...] escapes literal text; the rest is replaced with the locale-aware month name. (atemporal's [literal] escape syntax is moment-compatible.)
i18n catalog
The i18n module has standard message catalogs. To localize errors, see the logging recipe — the code field is what you index on, then look up the localized message in your catalog.
// i18n.ts
const messages = {
es: { ATEMPORAL_INVALID_DATE: 'La fecha no es válida.' },
en: { ATEMPORAL_INVALID_DATE: 'The date is not valid.' },
};
export function t(code: string, locale = 'en'): string {
return messages[locale]?.[code] ?? messages.en[code] ?? code;
}Bundling considerations
Intl.DateTimeFormat ships with a large CLDR dataset. V8/Node.js bake the data into the binary. Browsers ship it per user-agent.
- Node.js: the data is already there; no extra cost.
- Browsers: same.
- Cloudflare Workers: the data is in V8; cost is ~80 KB.
- Deno: same as Node.
There is no atemporal-side bundle penalty for supporting all locales.
See also
- REST input validation — for localizing the error messages.
- Structured logging — for emitting localized errors.
- React Server Components — for server-side rendering.