JavaScript International Methods

Photo by Tim Gouw on UnsplashIntroductionI’m lucky in that the company I work for is based mainly in the US and in English, with a few additional locations in Mexico and Canada.

This makes my job so much easier because I don’t have to worry much about internationalization: not about converting to different date formats, not about the idiosyncrasies resulting from language translations, and certainly not about the oddities regarding lists and currencies in other countries (really — who puts commas after periods when it comes to money??).

Just because these aren’t my problems though, doesn’t mean they aren’t incredibly painful for other engineers.

As an example, a lack of international standardizations (and the inability to convert numbers) resulted in a mismatch of metric units versus English units, causing NASA’s Mars Orbiter to completely miss entering orbit around Mars in 1999, to the tune of $125 million.

Oof… Source: https://www.

reactiongifs.

com/picard-facepalm/While the sums of money my software development team works with aren’t quite so large, and our errors result in bugs in the code we can usually fix in a matter of hours or days, I can definitely empathize with the NASA engineers, and I cringe thinking about how one simple mistake like not double checking everyone was using the same measurements in Orbiter’s code caused such a loss.

Which is why, when I heard the ECMAScript Internationalization API had recently been released, I was excited to see what kinds of improvements were about to make JavaScript around the world better and more standardized for everyone using it.

Today, let’s check out some of the best parts of Intl: the ECMAScript Internationalization API, which provides language sensitive string comparison, number formatting, and date and time formatting.

International Date Time HighlightsAs per usual, Mozilla’s MDN Web Docs, give the best summation of the new international API, and the properties that come with it:The INTL object provides access to several constructors as well as functionality common to the internationalization constructors and other language sensitive functions.

 — MDN Web DocsThere’s six properties that come along with the new Intl object, but in my opinion, only five of them deserve their own place in this blog post.

Intl.

DateTimeFormatIntl.

RelativeTimeFormatIntl.

ListFormatIntl.

NumberFormatIntl.

PluralRulesSo without further preamble, I’ll dive into the first property: the international date time format.

International Date Time FormatYes, we’ve all been there.

Yes, it’s really this much of a nightmare with dates and times.

The Intl.

DateTimeFormat object is a constructor for objects enabling language-sensitive date and time formatting.

At its most basic, the date time format takes in locales and options objects and outputs formatted time stamps based on those options.

Here’s an example using locales from around the globe to format this date variable.

Intl.

DateTimeFormat Locales Examplevar date = new Date(Date.

UTC(2012, 11, 20, 3, 0, 0));// using US date time formattingconsole.

log(new Intl.

DateTimeFormat('en-US').

format(date));// expected output: "12/19/2012" // using Great Britain date time formattingconsole.

log(new Intl.

DateTimeFormat('en-GB').

format(date));// expected output: "19/12/2012"// Include a fallback language, in this case US English with the Buddhist calendarconsole.

log(new Intl.

DateTimeFormat(['en-US-u-ca-buddhist']).

format(date));// expected output: "12/19/2555"In addition to being able to pass in locations, users can provide additional parameters strung together with the location, like:nu — the number systems used in different countries,ca — the calendar to use,hc — hour cycle ( h11, h24, etc.

).

After the additions to locales, comes the optionaloptions object which can include properties like:timezone — this can be either "UTC” or something like"America/New_York",hourCycle — once again, specs like "h12" or "h23",and my favorite one: formatMatcher — this algorithm can take in properties used to describe date-times and format the outputs to match.

Subsets for formatMatcher include things like:weekday, year, month, day, hour, minute, secondhour, minute, secondAnd even then, the subset properties have different options.

Here are the options for weekday.

"long" (e.

g.

, Thursday),"short" (e.

g.

, Thu),"narrow" (e.

g.

, T).

Check out this example using DateTimeFormat's options arguments to format the outputs.

Intl.

DateTimeFormat Options Arguments Examplesvar date = new Date(Date.

UTC(2012, 11, 20, 3, 0, 0));// request a weekday along with a long date in Japanesevar options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };console.

log(new Intl.

DateTimeFormat('ja-JP', options).

format(date));// expected output: "2012年12月19日水曜日"// an application may want to use UTC and make that visible in Germanoptions.

timeZone = 'UTC';options.

timeZoneName = 'short';console.

log(new Intl.

DateTimeFormat('de-DE', options).

format(date));// expected output: "Donnerstag, 20.

Dezember 2012, UTC"// sometimes you want to be more precise in Australian Englishoptions = { hour: 'numeric', minute: 'numeric', second: 'numeric', timeZone: 'Australia/Sydney', timeZoneName: 'short'};console.

log(new Intl.

DateTimeFormat('en-AU', options).

format(date));// expected output: "2:00:00 pm AEDT"// even the US needs 24-hour time for some occasionsoptions = { year: 'numeric', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric', hour12: false, timeZone: 'America/Los_Angeles' };console.

log(new Intl.

DateTimeFormat('en-US', options).

format(date));// expected output: "12/19/2012, 19:00:00"// to specify options but use the browser's default locale, use 'default'console.

log(new Intl.

DateTimeFormat('default', options).

format(date));// expected output: "12/19/2012, 19:00:00"This is such a cool feature.

It’s going to make it so much easier to translate dates and times properly and format them in so many specific ways that packages like moment.

js, made specifically for parsing, validating and manipulating JavaScript dates and times, will become unnecessary.

The next property I want to segue into, since I’m already on the subject of dates, is international relative time format.

International Relative Time FormatThe Intl.

RelativeTimeFormat object is a constructor for objects that enables language-sensitive relative time formatting.

Similar to the Intl.

DateTimeFormat, this object takes in a locales parameter and an options object.

The locales parameter functions exactly the same in this relative time format object as it does in the date time format, so I’ll skip any further explanation here.

As for options, the Intl.

RelativeTimeFormat has a variety of additional properties it accepts:localeMatcher — a locale matching algorithm, with the options "best fit" or "lookup",numeric — the format of the output message,style — the length of the internationalized message.

style follows the same lines as weekday, in that it has three different values:"long" (default, e.

g.

, in 2 months),"short" (e.

g.

, in 2 mo.

),or "narrow" (e.

g.

, in 2 mo.

).

narrow and short could be the same depending on the country.

Below are some samples using Intl.

RelativeTimeFormat in various locales and with various options passed to them.

Intl.

RelativeTimeFormat Examplesvar rtf1 = new Intl.

RelativeTimeFormat('en', { style: 'narrow' });// relative time formats in Englishconsole.

log(rtf1.

format(3, 'quarter'));//expected output: "in 3 qtrs.

"console.

log(rtf1.

format(-4, 'hour'));//expected output: "4 hr.

ago"var rtf2 = new Intl.

RelativeTimeFormat('de', { numeric: 'auto' });// relative time formats in Germanconsole.

log(rtf2.

format(2, 'day'));//expected output: "übermorgen"// Create a relative time formatter in your locale// with default values explicitly passed in.

const rtf = new Intl.

RelativeTimeFormat("en", { localeMatcher: "best fit", // other values: "lookup" numeric: "always", // other values: "auto" style: "long", // other values: "short" or "narrow"});// Format relative time in English using negative value (-1).

console.

log(rtf.

format(-1, "day"));// > "1 day ago"// Format relative time in English using positive value (1).

console.

log(rtf.

format(2, "day"));// > "in 2 days"Once again, super handy that we, as developers, don’t have to deal with the logic of formatting days or hours or even some words, in multiple languages no less, according to the number passed in.

No complicated if/else if/else logic blocks or even ternary expressions.

With the help of Intl.

RelativeTimeFormat just specify the language to use, the numeric output and the style and it’s good to go.

Nice!.????On that note of the Internationalization API, let’s look next at another thing that varies quite a bit from language to language: how lists are formatted.

International List FormatIt’s tough enough transforming an array in one language into something that resembles a human-readable list with ands or ors added in, try doing that in multiple languages.

The Intl.

ListFormat object is a constructor for objects to enable language-sensitive list formatting.

As is becoming the recurring theme of this article, the first optional parameter ListFormat accepts is a locales specification.

The second object is options with parameters like:localeMatcher — the locale matching algorithm, same options as with Intl.

RelativeTimeFormat,type — the format of the output message.

Possible values are "conjunction", which stands for "and"-based lists (default, e.

g.

, 1, 2, and 3), or "disjunction" that stands for "or"-based lists (e.

g.

, 1, 2, or 3).

"unit" stands for lists of values with units (e.

g.

, 7 pounds, 11 ounces).

style — the length of the formatted message.

Values include "long", "short", or "narrow".

Here’s some examples of how you could use the Intl.

ListFormat object in practice.

Intl.

ListFormat Examplesconst vehicles = ['Cat', 'Dog', 'Fish'];// list formats in Englishconst formatter = new Intl.

ListFormat('en', { style: 'long', type: 'conjunction' });console.

log(formatter.

format(vehicles));// expected output: "Cat, Dog, and Fish"// list formats in Frenchconst formatter2 = new Intl.

ListFormat('fr', { style: 'short', type: 'disjunction' });console.

log(formatter2.

format(vehicles));// expected output: "Cat, Dog ou Fish"// list formats in Spanishconst formatter3 = new Intl.

ListFormat('es', { style: 'narrow', type: 'unit' });console.

log(formatter3.

format(vehicles));// expected output: "Cat Dog Fish"const list = ['BMW', 'Volvo', 'Audi'];// list formats in British Englishconsole.

log(new Intl.

ListFormat('en-GB', { style: 'long', type: 'conjunction' }).

format(list));// expected output: "BMW, Volvo and Audi"console.

log(new Intl.

ListFormat('en-GB', { style: 'short', type: 'disjunction' }).

format(list));// expected output: "BMW, Volvo or Audi"console.

log(new Intl.

ListFormat('en-GB', { style: 'narrow', type: 'unit' }).

format(list));// expected output: "BMW Volvo Audi"How awesome is it that finally, finally there’s a built-in API that can make lists look good?.Heck, I’d take this even if it was only available for English-speaking countries or English language-only applications, this is so useful.

But wait!.I’ve got another incredibly useful constructor to introduce: the number formatter!.????International Number Format ????Make it rain, everybody.

Although the Intl.

NumberFormat definition doesn’t sound exciting at first, the implications are big.

This object is a constructor for objects that enables language sensitive number formatting.

And you know what that means?.The formatting for international currencies is a breeze.

In addition to locales and nu — the numbering system to be used, the Intl.

NumberFormat object can accept the following options parameters:localeMatcher,style — the formatting style to use.

Possible values are "decimal" for plain number formatting, "currency" for currency formatting, and "percent" for percent formatting; "decimal” is the default style.

currency — the currency to use in currency formatting,currencyDisplay — how to display the currency formatted.

The options are "symbol" to use a localized currency symbol such as €, "code" to use the ISO currency code, or "name"to use a localized currency name such as "dollar".

useGrouping — Whether to use grouping separators, such as thousands separators or thousand/lakh/crore separators.

Possible values are true and false.

There’s a few more options around digits: minimumIntegerDigits, maximumSignificantDigits, but I think their usefulness is limited, so I’ll skip defining them all here.

Intl.

NumberFormat Examplesvar number = 123456.

789;// currency formatting with euros in Germanconsole.

log(new Intl.

NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).

format(number));// expected output: "123.

456,79 €"// currency formatting in Japanese where the Japanese yen doesn't use a minor unitconsole.

log(new Intl.

NumberFormat('ja-JP', { style: 'currency', currency: 'JPY' }).

format(number));// expected output: "¥123,457"// limiting an Indian currency format to three significant digitsconsole.

log(new Intl.

NumberFormat('en-IN', { maximumSignificantDigits: 3 }).

format(number));// expected output: "1,23,000"// Arabic in most Arabic speaking countries uses real Arabic digitsconsole.

log(new Intl.

NumberFormat('ar-EG').

format(number));// expected output: ١٢٣٤٥٦٫٧٨٩// India uses thousands/lakh/crore separatorsconsole.

log(new Intl.

NumberFormat('en-IN').

format(number));// expected output: 1,23,456.

789// the nu extension key requests a numbering system, e.

g.

Chinese decimalconsole.

log(new Intl.

NumberFormat('zh-Hans-CN-u-nu-hanidec').

format(number));// expected output: 一二三,四五六.

七八九// when requesting a language that may not be supported, such as// Balinese, include a fallback language, in this case Indonesianconsole.

log(new Intl.

NumberFormat(['ban', 'id']).

format(number));// expected output: 123.

456,789In my mind, for an international company or website, this has got to be a huge, huge selling point for the Internationalization API.

Instead of hand-coding for all the varieties of currency differences that exist, we can rely on a single API to handle it for us — what a logic and time-saver!Ok, time for the last property I’ll cover today: Intl.

PluralRules.

International Plural RulesWhen you think about rules for plurals in English, the rules are hard: “ one dog” becomes “two dogs” but “one goose” becomes “two geese”, “one” becomes “two” but beyond “two” becomes “a few” or “many” or “other” when describing some vague, larger numbers of items, and so on and so forth— are you starting to see where I’m going with this?Now imagine needing to know unwritten rules like this in more than one language… ugh.

????Well, this is where the International Plural Rules becomes a life saver.

The Intl.

PluralRules object is a constructor for objects enabling plural sensitive formatting and plural language rules.

This constructor accepts locales (of course), and its options object takes in the following parameters:localeMatcher — The locale matching algorithm to use.

Possible values are "lookup" and "best fit"; the default is "best fit".

type — the type to use.

Possible values are: "cardinal" for cardinal numbers (referring to the quantity of things).

This is the default value.

Or "ordinal" for ordinal number (referring to the ordering or ranking of things, e.

g.

"1st", "2nd", "3rd" in English).

Uses for Intl.

PluralRulesThere’s a few different ways to use Intl.

PluralRules in your code.

Basic usage — In basic use without specifying a locale, a formatted string in the default locale and with default options is returned.

This is useful to distinguish between singular and plural forms such as “cat” and “cats”.

Locales usage — When using locales, the example code below shows some of the variations in localized plural rules.

In order to get the format of the language used in the user interface of your application, make sure to specify that language (and possibly some fallback languages) using the locales argument.

Options usage — The plural results can be customized using the options argument, which has one property called type which you can set to ordinal.

This is useful to figure out the ordinal indicator, e.

g.

"1st", "2nd", "3rd", "4th", "42nd" and so forth.

The code snippets below outline all the usages I just described.

Intl.

PluralRules Examples// basic usage examplesvar pr = new Intl.

PluralRules();// examples of plural rules if in US English localeconsole.

log(pr.

select(0));// expected output: 'other'console.

log(pr.

select(1)); // expected output: 'one'console.

log(pr.

select(2));// expected output: 'other'// examples using `locale`// for example: Arabic has different plural rulesconsole.

log(new Intl.

PluralRules('ar-EG').

select(0));// expected output: 'zero'console.

log(new Intl.

PluralRules('ar-EG').

select(1)); // expected output: 'one'console.

log(new Intl.

PluralRules('ar-EG').

select(2));// expected output: 'two'console.

log(new Intl.

PluralRules('ar-EG').

select(6));// expected output: 'few'console.

log(new Intl.

PluralRules('ar-EG').

select(18));// expected output: 'many'// examples using `options`var pr = new Intl.

PluralRules('en-US', { type: 'ordinal' });// examples using US English and `options type` specificationconsole.

log(pr.

select(0));// expected output: 'other'console.

log(pr.

select(1));// expected output: 'one'console.

log(pr.

select(2));// expected output: 'two'console.

log(pr.

select(3));// expected output: 'few'console.

log(pr.

select(4));// expected output: 'other'Pretty nice, huh?.I’ll admit, of all the Intl methods, this is less widely applicable than some of the other methods included, but I’m sure it will still have its moments where it’s just the ticket.

It is also worth noting that this method is still in “Draft” status, with the comment “initial definition” in MDN’s docs, so I would hold off for a while longer before attempting to rely on it completely in production.

ConclusionTranslating websites and applications for use in different countries and languages is tough enough, but being able to correctly handle things like date time formats, currencies and lists of items with their many language-specific rules is a real challenge.

The newest version of the ECMAScript Internationalization API aims to make some of these arduous tasks easier by letting its methods do the formatting for you, based on locales and whatever other options you might want to specify.

For JavaScript developers working with international requirements, this stands to be a huge boon, and I for one, am looking forward to incorporating these new features into my own applications just for the total convenience these properties provide.

Check back in a few weeks, I’ll be writing about JavaScript, ES6 or something else related to web development, so please follow me so you don’t miss out.

Thanks for reading, I hope you see the value the ECMAScript Internationalization API can provide to your applications, and are able to incorporate some of the properties into your web apps in the future.

Please share this with your friends if you found it helpful!If you enjoyed reading this, you may also enjoy some of my other blogs:4 Solutions To Run Multiple Node.

js or NPM Commands SimultaneouslyViewport Units, the CSS You Didn’t Know About But ShouldJavaScript’s Async/Await versus Promises: The Great DebateReferences and Further Resources:ECMAScript Internationalization API, MDN Docs: https://developer.

mozilla.

org/en-US/docs/Web/JavaScript/Reference/Global_Objects/IntlInternational Date Time Format, MDN Docs: https://developer.

mozilla.

org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormatInternational Relative Time Format, MDN Docs: https://developer.

mozilla.

org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RelativeTimeFormatInternational List Format, MDN Docs: https://developer.

mozilla.

org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ListFormatInternational Number Format, MDN Docs: https://developer.

mozilla.

org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormatInternational Plural Rules, MDN Docs: https://developer.

mozilla.

org/en-US/docs/Web/JavaScript/Reference/Global_Objects/PluralRules.

. More details

Leave a Reply