Intl.NumberFormat
Localised, by the runtime.
Stop hand-rolling currency strings and percentage formatters. The browser ships a full ICU-backed localisation library.
Reuse your formatters
Instantiating an Intl.NumberFormat is genuinely expensive β it negotiates locales and loads ICU data. Build once, reuse forever.
The wider Intl family
Intl.DateTimeFormat, Intl.RelativeTimeFormat, Intl.ListFormat, Intl.PluralRules, Intl.Collator, Intl.Segmenter β almost every "localise this" task has a built-in answer.
BCP 47 locale tags
Use BCP 47 tags: en-GB (not en-UK), cs-CZ (not cz-CZ). The runtime is forgiving on unknown tags but you'll silently get the wrong locale.
Try it 3 examples
Currency formatting
JSintroThe same number renders as 112.358,13 β¬, $112,358.13, and Β£112,358.13 β each locale picks its own grouping/decimal separators and symbol placement (trailing for de-DE, leading for the English locales), so you never hand-assemble a currency string yourself.