Internationalization

Formatting numbers

The Intl.NumberFormat class is designed to format numbers in various ways. The constructor takes two arguments. The first argument specifies the locale the number should be formatted for, and the second specifies how the number should be formatted. The Intl.NumberFormat class defines a format() method that returns a string of the formatted number.

The second argument is given as an object with properties that specify the formatting options. The style property specifies the kind of formatting: "decimal" (default), "percent", or "currency".

If the style chosen is 'currency', the currency property specifies the three-letter ISO currency code for the desired currency.

let twd = Intl.NumberFormat('zh-guoyu', {
  style: 'currency',
  currency: 'TWD'
});

twd.format(10); // => 'NT$10.00'

The currencyDisplay property specifies how the currency should be displayed: "symbol" is the default value which uses a currency symbol, "code" uses three-letter ISO code, and "name" spells out the name of the currency.

let rub = Intl.NumberFormat('ru', {
  style: 'currency',
  currency: 'RUB',
  currencyDisplay: 'symbol',
}).format;

rub(10); // => '10,00 ₽'

let usd = Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  currencyDisplay: 'code',
}).format;

usd(10); // => 'USD 10.00'

let jpy = Intl.NumberFormat('ja', {
  style: 'currency',
  currency: 'JPY',
  currencyDisplay: 'name',
}).format;

jpy(10); // => '10円'

The minimumFractionDigits and maximumFractionDigits properties control the formatting of the fractional part of the number.

let percent = Intl.NumberFormat(undefined, {
  style: 'percent',
  minimumFractionDigits: 1,
  maximumFractionDigits: 1,
}).format;

let data = [1, .25, 0.05];
data.map(percent); // => ['100.0%', '25.0%', '5.0%']

The minimumSignificantDigits and maximumSignificantDigits properties control the number of significant digits used in a number.

let decimal = Intl.NumberFormat(undefined, {
  minimumSignificantDigits: 2,
  maximumSignificantDigits: 3,
}).format;

let values = [1.0025, 3.251, 0.5];
values.map(decimal); // => ['1.0', '3.25', '0.50']

The minimumIntegerDigits property pads the number with fewer integer digits than specified. Set the useGrouping property to false if you do not want numbers to have thousands separators.

let pad3 = Intl.NumberFormat(undefined, {
  minimumIntegerDigits: 3,
  useGrouping: false,
}).format;

let ids = [1, 12, 123, 1234];
ids.map(pad3); // => ['001', '012', '123', '1234']

Formatting dates and times

The Intl.DateTimeFormat() class provides fine-grained control over dates and times based on the properties in the options object that is passed as the second argument to the constructor.

let d = new Date('2024-05-18T07:28:09.476Z');
Intl.DateTimeFormat('en-US').format(d); // => '5/18/2024'

The year property can be set to either "numeric" for a four-digit year or "2-digit" for a two-digit abbreviation.

let year = Intl.DateTimeFormat('en-GB', {
  year: '2-digit',
}).format;

year(d); // => '24'

The month property uses "numeric" for a short number, "2-digit" for two-digit number, "long" for full name, "short" for abbreviated name, or "narrow" for one-character name.

let month = Intl.DateTimeFormat('en-US', {
  year: 'numeric',
  month: '2-digit',
}).format;

month(d); // => '05/2024'

For the day property, use either "numeric" for a one- or two-digit number or "2-digit" for a two-digit number for the day-of-month.

let day = Intl.DateTimeFormat('de', {
  year: '2-digit',
  month: '2-digit',
  day: '2-digit',
}).format;

day(d); // => '18.05.24'

The weekday property can be set to "long" for full name, "short" for an abbreviated name, and "narrow" for highly abbreviated name.

let weekday = Intl.DateTimeFormat('fr', {
  year: '2-digit',
  month: 'narrow',
  day: '2-digit',
  weekday: 'long',
}).format;

weekday(d); // => 'samedi 18 M 24'

The era property specifies whether an era should be added to the date with legal name "long", "short", and "narrow".

let era = Intl.DateTimeFormat('ru', {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  weekday: 'short',
  era: 'long',
}).format;

era(d); // => 'сб, 18 мая 2024 г. от Рождества Христова'

The hour, minute, and second properties specify how time should be displayed. Use "numeric" for a one- or two-digit field or "2-digit" to force single-digit numbers be padded on the left with 0.

let time = Intl.DateTimeFormat('ja', {
  hour: 'numeric',
  minute: '2-digit',
  second: '2-digit',
}).format;

time(d); // => '15:28:09'

The timeZone property specifies the time zone. If omitted, the local time zone is used. The recognized time zones include "UTC" and IANA time zones, such as "Asia/Tokyo".

let timeZone = Intl.DateTimeFormat('ja', {
  hour: 'numeric',
  minute: '2-digit',
  second: '2-digit',
  timeZone: 'UTC',
}).format;

timeZone(d); // => '7:28:09'

The timeZoneName property specifies how the time zone should displayed. Use either "long" or "short" values.

let timeZoneName = Intl.DateTimeFormat('ja', {
  hour: 'numeric',
  minute: '2-digit',
  second: '2-digit',
  timeZone: 'Asia/Tokyo',
  timeZoneName: 'long',
}).format;

timeZoneName(d); // => '16時28分09秒 日本標準時'

The hour12 is a boolean property that determines whether or not the 12-hour time should be used.

let hour12 = Intl.DateTimeFormat('zh-Hant-TW', {
  hour: 'numeric',
  minute: '2-digit',
  second: '2-digit',
  timeZone: 'Asia/Tokyo',
  timeZoneName: 'short',
  hour12: true,
}).format;

hour12(d); // => '下午4:28:09 [GMT+9]'

The hourCycle property specifies whether midnight is written as 0 hours, 12 hours, or 24 hours. Use "h11" for midnight 0, "h12" for midnight 12 and hour before 11pm, "h23" for midnight 0 and hour before 23, and "h24" for midnight 24.

let hourCycle = Intl.DateTimeFormat('es', {
  hour: 'numeric',
  minute: 'numeric',
  second: 'numeric',
  timeZone: 'America/Los_Angeles',
  timeZoneName: 'short',
  hourCycle: 'h24',
}).format;

hourCycle(d); // => '24:28:09 GMT-7'

Comparing strings

The Intl.Collator class is designed to perform locale-appropriate comparison of strings. The first argument to the constructor specifies the locale, and the second is an optional object of options. The compare() method of the Intl.Collator class takes two strings and returns a negative number if the first string comes before the second string, a positive number if the first string comes after the second string, and zero if both strings are equal.

const order = new Intl.Collator().compare;
['a', 'z', 'A', 'Z'].sort(order); // => ['a', 'A', 'z', 'Z']
````

The `usage` property specifies whether comparison is for sorting or for searching. The default value "sort" is for sorting, and "search" is for filtering a list of strings.

The `sensitivity` property specifies whether the collator is sensitive to letter case and accents. The value "base" ignores case and accents, "accent" take accents into account but ignores case, "case" considers case but ignores accents, and the default value "variant" performs strict comparisons that consider both case and accents.

```js
const collator = new Intl.Collator('en', {
  usage: 'search',
  sensitivity: 'base',
});

let items = ['apple', 'resume', 'Résumé', 'résumé'];
const searchTerm = 'resume';

const filteredItems = items.filter(
  item => collator.compare(item, searchTerm) === 0);
filteredItems; // => ['resume', 'Résumé', 'résumé']

Set the ignorePunctuation property to true to ignore spaces and punctuation when comparing strings.

const fuzzySearch = new Intl.Collator(undefined, {
  usage: 'search',
  sensitivity: 'base',
  ignorePunctuation: true,
}).compare;

let list = ['Anytime', 'Any time', 'sometime'];
const filteredList = list.filter(s => fuzzySearch(s, 'anytime') === 0);
filteredList; // => ['Anytime', 'Any time']

Set the numeric property to true to compare strings that contain integers for sorting in numerical order.

const fileOrder = new Intl.Collator(undefined, {
  numeric: true,
}).compare;
['file10', 'file9'].sort(fileOrder); // => ['file9', 'file10']

The caseFirst property specifies which letter case should come first. If you use the value "upper", then "A" comes before "a", when using "lower", then "a" is sorted before "A". The default is false.

const upperFirst = new Intl.Collator('en', {
  caseFirst: 'upper',
}).compare;
['a', 'z', 'A', 'Z'].sort(upperFirst); // => ['A', 'a', 'Z', 'z']

The collation property specifies the set of rules used to compare and sort strings in a particular locale. For example, you can sort Chinese strings in pinyin order.

const locale = new Intl.Locale("zh");
locale.collations; // => ['emoji', 'eor', 'pinyin', 'stroke', 'zhuyin']

const pinyinOrder = new Intl.Collator('zh-Hant', {
  collation: 'pinyin',
}).compare;
let countries = ['俄羅斯', '美國', '中國', '阿根廷'];
countries.sort(pinyinOrder); // => ['阿根廷', '俄羅斯', '美國', '中國']