53 lines
1.7 KiB
TypeScript
53 lines
1.7 KiB
TypeScript
/**
|
|
* Locale-aware formatting helpers (Intl-based) + pluralization. Pair with the
|
|
* request language (`ctx.lang`) so numbers, dates, and currencies render right
|
|
* for each user.
|
|
*/
|
|
|
|
/** Format a number for a locale (e.g. 1234.5 → "1,234.5"). */
|
|
export function formatNumber(
|
|
value: number,
|
|
lang: string,
|
|
options?: Intl.NumberFormatOptions,
|
|
): string {
|
|
return new Intl.NumberFormat(lang || undefined, options).format(value);
|
|
}
|
|
|
|
/** Format a currency amount (e.g. 9.99, "USD" → "$9.99"). */
|
|
export function formatCurrency(value: number, currency: string, lang: string): string {
|
|
return new Intl.NumberFormat(lang || undefined, { style: "currency", currency }).format(value);
|
|
}
|
|
|
|
/** Format a date/timestamp for a locale. */
|
|
export function formatDate(
|
|
value: Date | number | string,
|
|
lang: string,
|
|
options: Intl.DateTimeFormatOptions = { dateStyle: "medium" },
|
|
): string {
|
|
const date = value instanceof Date ? value : new Date(value);
|
|
return new Intl.DateTimeFormat(lang || undefined, options).format(date);
|
|
}
|
|
|
|
/** Relative time, e.g. -3 days → "3 days ago" (localized). */
|
|
export function formatRelativeTime(
|
|
value: number,
|
|
unit: Intl.RelativeTimeFormatUnit,
|
|
lang: string,
|
|
): string {
|
|
return new Intl.RelativeTimeFormat(lang || undefined, { numeric: "auto" }).format(value, unit);
|
|
}
|
|
|
|
/**
|
|
* Pick a plural form for `count` in `lang` using CLDR rules, e.g.
|
|
* `plural(n, { one: "1 item", other: "# items" }, lang)` — "#" is replaced by n.
|
|
*/
|
|
export function plural(
|
|
count: number,
|
|
forms: Partial<Record<Intl.LDMLPluralRule, string>>,
|
|
lang: string,
|
|
): string {
|
|
const rule = new Intl.PluralRules(lang || undefined).select(count);
|
|
const template = forms[rule] ?? forms.other ?? "";
|
|
return template.replace(/#/g, String(count));
|
|
}
|