The Intl API is Cool

History

For years, Javascript developers have made do with a mediocre standard library, especially when it comes to difficult problems like localization, date formatting, and really anything that is formatted differently between different locales.

To get around the lack of built-in support, libraries have popped up to provide solutions. Libraries like Moment were the gold standard, but it came at a cost of a heavy payload of JS that users had to download. Fortunately, these days there is a much better alternative, and it comes built-in to browsers!

Enter the Intl API

The Intl API is a series of APIs built into Javascript that provide support for common formatting and comparison needs across different locales. The most popular APIs are likely these three:

  1. Intl.DateTimeFormat
  2. Intl.NumberFormat
  3. Intl.RelativeTimeFormat

DateTimeFormat

The DateTimeFormat API is my favorite - thought slightly more difficult to work with than a "traditional" date formatter with different string patterns like MMMM, dd, etc, it provides out-of-the-box functionality for however you could want to display a date.

For instance, take this example from Moment's docs on their format function:

moment().format("dddd, MMMM Do YYYY, h:mm:ss a");
// "Sunday, February 19th 2023, 3:25:50 pm"

This can be achieved with the Intl.DateTimeFormat API like so:

new Intl.DateTimeFormat(
    'en-US',
    {weekday: 'long', month: 'long', year: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric'}
).format((new Date())));
// "Sunday, February 19th 2023 at 3:25:50 pm"

Note that there are a couple of differences: with Moment you can put in other text like the comma, and it has built-in support for the ordinal suffix on dates - "14th" instead of "14". However, you can easily build on top of the raw DateTimeFormat call by using formatToParts instead of format and pulling together the different parts of the date you need. Ordinal suffixes are more difficult, but you can use the PluralRules Intl API to determine the ordinality of a numer. A solid approach is in this blog post.

NumberFormat

I remember pulling in a library to deal specifically with currency formatting at my old job. Fortunately, with the NumberFormat API, that's no longer necessary! (Unless you have some super specific usecase, probably). It's so straightforward to represent any currency in any locale.

new Intl.NumberFormat("es-la", { style: "currency", currency: "USD" }).format(
	1234.67,
);
// "1234,67 US$"

It doesn't just work with currencies though - it has many different formatting styles available.

new Intl.NumberFormat("pt-PT", { style: "unit", unit: "kilometer-per-hour" })
	.format(50);
// 50 km/h

new Intl.NumberFormat("en-gb", { style: "unit", unit: "stone" }).format(
	1234.67,
);
// "1,234.67 st"

// Percentages
new Intl.NumberFormat("en-us", {
	style: "percent",
	minimumSignificantDigits: "2",
}).format(.765);
// 76.5%

There are several options for different "simple units", that can be combined as shown in the kilometer-per-hour example to create more complex units.

RelativeTimeFormat

Relative time formatting has a straightforward API here:

new Intl.RelativeTimeFormat("en-us", { numeric: "auto", style: "long" }).format(
	-5,
	"weeks",
);
// 5 weeks ago

// The numeric: auto option is what allows this
new Intl.RelativeTimeFormat("en-us", { numeric: "auto", style: "long" }).format(
	-1,
	"days",
);
// yesterday

Conclusion

There's a lot more to the Intl API, but this covers three of the big APIs that provide a huge amount of built-in support when displaying or formatting dates, numbers, times, or even things like lists. To see all the APIs provided, you can read about the Intl namespace on MDN.