Files
2026-05-27 23:47:53 +01:00

5.0 KiB
Raw Permalink Blame History

@suaveplan/i18n-formatter-number - Locale-aware number formatting backed by Intl.NumberFormat. Class wrapper + standalone helper + ergonomic helpers (formatPercent, formatCompact, formatUnit), Zod-validated options, per-(locale, options-hash) cache, OTel histogram + cache-hit counter. Wave 3 of the @suaveplan/i18n modular split.

Summary

Locale-aware number formatting backed by Intl.NumberFormat. Wave 3 of the 14-package i18n modular split. Provides both a class (NumberFormatter) and a standalone helper (formatNumber) plus ergonomic shortcuts (formatPercent, formatCompact, formatUnit) on top of a per-(locale, options-hash) cache, Zod-validated options, and the canonical OTel histogram + cache-hit counter that every Wave 3 formatter package emits.

Documentation tree

  • formatter — Locale-aware number formatting backed by Intl.NumberFormat. The package exposes both a class (NumberFormatter — con…
    • formatter — Locale-aware number formatting backed by Intl.NumberFormat. The package exposes both a class (NumberFormatter — con…
  • helpers — Pre-bound shortcuts over formatNumber and Intl.NumberFormat for the three most-asked number-formatting shapes: perc…
    • helpers — Pre-bound shortcuts over formatNumber and Intl.NumberFormat for the three most-asked number-formatting shapes: perc…
  • observability — Per-package OpenTelemetry instruments for @suaveplan/i18n-formatter-number. Exposes a histogram (`i18n.format.number.…
    • observability — Per-package OpenTelemetry instruments for @suaveplan/i18n-formatter-number. Exposes a histogram (`i18n.format.number.…

Why this exists

Each Intl.* wrapper lives in its own sibling package so consumers can pull only the formatters they actually use. This package is the canonical Wave 3 template — every other formatter package mirrors its layout (per-(locale, options-hash) cache, Zod schema, OTel metrics, helper + class twin surface). @suaveplan/i18n-formatter-currency declares a workspace dep on this package because currency formatting is Intl.NumberFormat({ style: "currency", ... }).

Install

bun add @suaveplan/i18n-formatter-number

Quick Start

import {
    formatCompact,
    formatNumber,
    formatPercent,
    NumberFormatter,
} from "@suaveplan/i18n-formatter-number";

formatNumber(1234567.89, "en-GB", {
    style: "decimal",
    maximumFractionDigits: 2,
}); // → "1,234,567.89"

formatPercent(0.5, "en-GB"); // → "50%"
formatCompact(1500, "en-US"); // → "1.5K"

const usd = new NumberFormatter({
    style: "currency",
    currency: "USD",
});
usd.format(42.5, "en-US"); // → "$42.50"

Modules

Subpath Description
@suaveplan/i18n-formatter-number Root barrel — class + standalone + helpers + observability
@suaveplan/i18n-formatter-number/formatter NumberFormatter, formatNumber, clearNumberFormatterCache, types, schema
@suaveplan/i18n-formatter-number/helpers formatPercent, formatCompact, formatUnit only

Modules Documentation

Public Surface (snapshot)

Export Kind Origin
NumberFormatter class formatter.ts
formatNumber function formatter.ts
clearNumberFormatterCache function formatter.ts
NumberFormatterOptionsSchema const formatter.ts
NumberFormatterStyle type formatter.types.ts
NumberFormatterNotation type formatter.types.ts
NumberFormatterCurrencyDisplay type formatter.types.ts
NumberFormatterSignDisplay type formatter.types.ts
NumberFormatterOptions type formatter.types.ts
NumberFormatterCacheKey type formatter.types.ts
formatPercent function helpers.ts
formatCompact function helpers.ts
formatUnit function helpers.ts
recordNumberFormat function observability.ts
recordNumberCacheHit function observability.ts
getNumberFormatMetricsState function observability.ts
resetNumberFormatMetricsState function observability.ts

Versioning

This package is part of the i18n modular-split rollout. Stays at 0.1.0 until the slim core (Wave 6) cuts the family 1.0.0 release.

Wave 3 Scope

This package is one of eight Wave 3 formatter packages. Pure addition — packages/i18n/i18n/src/formatting/number/ is preserved in the monolith until Wave 6 deletes it. Both copies coexist during Waves 3–5; downstream consumers continue to import from the monolith and observe no behaviour change.