An ECMAScript Internationalization API Feature that currently is in Stage-3 and that has already landed in V8 version 8.1 is Intl.DisplayNames
. It’s a way to get localized display names for languages, scripts, regions and others.
🤔 Note that this proposal is part of ECMA-402 (the ECMAScript Internationalization API Specification) and not ECMA-262 (The ECMAScript Language Specification). Therefore this proposal will not be part of the yearly "ES20XX”, as that term only applies to ECMA-262.
To advance proposals in ECMA-402, TC39 uses the same 5-stage-process as they use in ECMA-262.
💁♂️ Stage-3?
The Technical Committee which is concerned with the standardization of ECMAScript (i.e. TC39) has a 5 stage process in place, ranging from stage-0 to stage-4, by which it develops a new language feature.
Stage-3 is the Candidate Stage where the feature is considered complete and only critical changes will happen based on implementation experience. If all goes well the proposal will advance to Stage 4 without any changes, after which it will to become part of the ECMAScript Specification.
The idea is that you as a developer should not build your own list of localized strings for languages, regions, etc. but that the JavaScript runtime should provide if for you:
Translation of languages, regions or script display names requires large amount of data to transmit on the network, which is already available in most browsers. The
Intl.DisplayNames
API will allow web developers to shrink the size of their HTML and/or ECMA script code without the need to include the human readable form of display names and therefore reduce the download size to decrease latency.
💁♂️ Another nice API exposed on Intl
is Intl.RelativeTimeFormat
which allows you to relatively format time in JavaScript.
~
Examples
// Get display names of region in English
const regionNames = new Intl.DisplayNames(['en'], {type: 'region'});
console.log(regionNames.of('419')); // "Latin America"
console.log(regionNames.of('BZ')); // "Belize"
console.log(regionNames.of('US')); // "United States"
console.log(regionNames.of('BA')); // "Bosnia & Herzegovina"
console.log(regionNames.of('MM')); // "Myanmar (Burma)"
// Get display names of language in Traditional Chinese
const languageNames = new Intl.DisplayNames(['zh-Hant'], {type: 'language'});
console.log(languageNames.of('fr')); // "法文"
console.log(languageNames.of('zh')); // "中文"
console.log(languageNames.of('de')); // "德文"
// Get display names of script in Traditional Chinese
const scriptNames = new Intl.DisplayNames(['zh-Hant'], {type: 'script'});
console.log(scriptNames.of('Latn')); // "拉丁文"
console.log(scriptNames.of('Arab')); // "阿拉伯文"
console.log(scriptNames.of('Kana')); // "片假名"
// Get display names of currency code in English
const currencyNames = new Intl.DisplayNames(['en'], {type: 'currency'});
console.log(currencyNames.of('USD')); // "US Dollar"
console.log(currencyNames.of('EUR')); // "Euro"
console.log(currencyNames.of('TWD')); // "New Taiwan Dollar"
console.log(currencyNames.of('CNY')); // "Chinese Yuan"
~
Syntax
The constructor takes two arguments: locales
and options
. Both are optional:
new Intl.DisplayNames([locales[, options]]);
Once you have a Intl.DisplayNames
instance, you use its .of
method to request a localised string
Intl.DisplayNames.prototype.of(code);
~
Constructor Arguments
locales
The locales
argument is a BCP 47 language tag which identifies the locale to use. The main parts, amongst others, of a BCP 47 language tag are language
, script
, and region
- The
language
part is a 2/3 character long ISO 639-1 code - The (optional)
script
part is a 4 character long ISO 15924 code - The (optional)
region
part is a 2 alpha or 3 digit long ISO 3166-1 code
When more than one part is present, they are separated by a dash (-
)
Examples:
"nl"
: Dutch (language
)."nl-BE"
: Dutch as used in Belgium (language
+region
)."zh-Hans-CN"
: Chinese written in simplified characters as used in China (language
+script
+region
).
When locales
is omitted, it will default to the language-setting of the browser/system.
options
The options
object allows you to tweak how Intl.DisplayNames
behaves. It has the following properties:
-
localeMatcher
The locale matching algorithm to use. Possible values are
"lookup"
and"best fit"
(default) -
style
The length of the output message, e.g.
"English (United States)"
vs."English (US)"
. Possible values are"long"
(default) and"short"
, or “narrow” (which mostly yields the same result as"short"
, depending on the language) -
type
What you want to display. Possible values are
"region"
,"script"
,"language"
, or"currency"
.
~
Intl.DisplayNames.prototype.of Arguments
code
Depending on the type
you passed into the constructor, you pass in a different value for code
:
-
If the
type
is"region"
:The code should be either an ISO-3166 two letters region code, or a three digits UN M49 Geographic Regions.
-
If the
type
is"script"
:The code should be an ISO-15924 four letters script code.
-
If the
type
is"language"
:The code should follow UTS 35’s Unicode Language and Locale Identifiers grammar. languageCode is either a two letters ISO 639-1 language code or a three letters ISO 639-2 language code.
-
If the
type
is"currency"
:The code should be a 3-letter ISO 4217 currency code.
~
JS/Browser Support
Intl.DisplayNames
already shipped in V8 v8.1 (included in the upcoming Chrome 81) and will be available in Node 14. Other JS runtimes / browsers don’t support it at the time of writing.
~
The future: More types to come!
When looking at the open issues listed on the proposal’s repository you can see that there’s more to come in a future version of Intl.DisplayNames
: support for units, timezones, emoji names, date parts (such as months, weekdays, etc).
For this first release the scope was limited to supporting the types "region"
, "script"
, "language"
, and "currency"
.
~
Thank me with a coffee.
I don\'t do this for profit but a small one-time donation would surely put a smile on my face. Thanks!
To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.