JavaScript Internationalization API

I’m excited to announce that — as of r197261 — WebKit fully supports the ECMA-402 API for internationalization in JavaScript.

Previously, internationalization was only available through multi-megabyte libraries. Now, it’s built into the browser, saving time and bandwidth.

What is Internationalization?

Internationalization adapts data presentation to fit a user’s language and country.

Consider the following workout summary:

You biked for 1.2 hours, starting at 2:45 PM on 09/25/2016.

You might think that this summary works for any English speaker. But it’s inappropriate outside the US.

The best text in the UK is:

You biked for 1.2 hours, starting at 14:45 on 25/09/2016.

The best text in South Africa is:

You biked for 1,2 hours, starting at 2:45 PM on 2016/09/25.

These details differ between languages, and sometimes between countries that speak the same language.

If we have all our content ahead of time we can pre-translate it by hand. But we’ll generate workout data dynamically, so we need an API to change data presentation on the fly. The JavaScript Internationalization API addresses this need.

We call a combination of language and country — such as “English as spoken in the UK” — a “locale”.

Some kinds of data that change presentation based on locale include times, dates, numbers, currency, and alphabetized words.

Internationalization in Practice

There are two pieces to the Internationalization API: convenience functions and explicit constructors. The convenience functions encapsulate the explicit constructors, taking care of some details automatically.

Convenience functions exist for common data types that might need internationalization:

String.prototype.localeCompare()

Number.prototype.toLocaleString()

Date.prototype.toLocaleString()
Date.prototype.toLocaleDateString()
Date.prototype.toLocaleTimeString()

You can use the Date.prototype.toLocaleTimeString convenience function to produce a locale-aware variant of our time above:

var date = new Date(2016, 9, 25, 14, 45);
var timeString = date.toLocaleTimeString(); // "14:45:00" in the UK

With more options, you can achieve the exact display above, removing the seconds field:

var date = new Date(2016, 9, 25, 14, 45);
var timeString = date.toLocaleTimeString(
    undefined, { hour: "2-digit", minute:"2-digit" }); // "14:45" in the UK

Explicit constructors provide a persistent way to reference a set of internationalization rules:

Intl.Collator
Intl.NumberFormat
Intl.DateTimeFormat

If we planned to display lots of dates, we would save a date formatter and reuse it:

var formatter = Intl.DateTimeFormat(
    undefined, { hour: "2-digit", minute:"2-digit" }); // Persistent formatter

var date = new Date(2016, 9, 25, 14, 45);
var timeString = formatter.format(date); // "14:45" in the UK

Locale Codes

By default, the APIs above honor the user’s locale according to System Preferences.

You might prefer to specify locale. For example, if you’ve served a locale-specific variant of your web content, you’ll want your data presentation to match.

If we override the default, we can specify the South African variant of our hour count:

var hours = 1.2;
hours.toLocaleString("en-za"); // "1,2"

The string code “en-za” specifies “English as spoken in South Africa”. This code is an IETF BCP-47 tag. Each of the APIs above accepts, as an optional first argument, a locale tag.

Resources

The ECMA-402 specification is available on the web. You can also follow future developments in the specification.