How to Implement Internationalization (i18n) in JavaScript

Share this article

Cartoon flying saucer approaching a planet

This article was peer reviewed by Julian Motz, Panayiotis Velisarakos, Vildan Softic and Tim Severien. Thanks to all of SitePoint’s peer reviewers for making SitePoint content the best it can be!

Cartoon flying saucer approaching a planet

So, you’re a developer working on the next big thing. Your customers love your product and it’s getting rave reviews on all the social networks. Even better, the CEO of the company has just secured $10,000,000 in funding to expand into new markets. But before you can go global, the product must be updated to support different languages, currencies, date formats, and much more. And guess what? You and your team are the ones in charge of making this happen. In technical terms, your software must be internationalized and then localized.

Internationalization (also known as i18n) is the process of creating or transforming products and services so that they can easily be adapted to specific local languages and cultures. Localization (also known as L10n) is the process of adapting internationalized software for a specific region or language. In other words, internationalization is the process of adapting your software to support multiple cultures (currency format, date format, and so on), while localization is the process of implementing one or more culture.

These two processes are usually adopted by companies that have interests in different countries, however they might also come in handy for a single developer working on their own site. For example, as you might know, I’m Italian and I own a website. My website is currently in English but I might decide to internationalize it and then localize it into Italian. This is beneficial for those that are native Italian speakers and aren’t well accustomed to the English language.

In this article I’ll introduce you to Globalize, a JavaScript library for internationalization and localization developed by some members of the jQuery team. All the snippets demonstrated in this article can be found on our GitHub repository.

But before delving into Globalize, I’d like to conclude this brief introduction on i18n with the words of Rafael Xavier de Souza, the lead of the project:

Developers think i18n is about translations to non-English languages. That i18n is only needed for expanding the current application to multiple countries or markets. I always try to explain that i18n is about “talking” in general. Every application, at some point, has to “talk” to its users. To talk with the users, the application may require pluralization support, gender inflection, date formatting, number formatting, and currency formatting. Even in English, it might be tricky to get this done properly.

What is Globalize?

Globalize is a JavaScript library for internationalization and localization that leverages the official Unicode CLDR JSON data. The library is open source and it’s developed by Rafael Xavier de Souza along with some of the members of the jQuery team.

Globalize is based on the Unicode Consortium’s Common Locale Data Repository (CLDR), the largest and most extensive standard repository of locale data available. So, unlike libraries that embed locale data, if you use Globalize it’s really easy to always be up-to-date with the latest CLDR data.

The library works both for the browser and as a Node.js module. Globalize 1.0 supports all major browsers including IE9+, Chrome, Firefox, Safari 5.1+, and Opera 12.1+.

The main features of the library are:

  • Number formatting and parsing
  • Date and time formatting and parsing
  • Relative time formatting
  • Currency formatting
  • Message formatting
  • Plural support
  • Unit support

One of the things I like the most about Globalize is that it has a module for each of its features. A developer may not need the whole library and can thus cherry-pick the module(s) needed. Another interesting feature is that, unlike other libraries, it keeps the code separated from the content by not hosting or embedding any locale data in the library.

But Globalize isn’t the only show in town. If you’re interested in some alternatives, Rafael has a dedicated page. The most notable alternative is i18next.

Globalize and the JavaScript Internationalization API

To some of you this may come to a surprise, but JavaScript has native support for internationalization in the form of the Internationalization API (also known as ECMA-402). The Intl object is an object available on the window object which acts as a namespace for the Internationalization API. This API currently provides methods to format numbers and dates, and to compare strings in a specific language.

Now that you know of the existence of the Internationalization API, you could be led into thinking that Globalize uses it behind the scenes. This approach would surely lead to better date and number formatting performance. However, because the support is low and very inconsistent among browsers, the library doesn’t use it.

Before we move on and start the discussion on Globalize, I want to give you a taste of the Internationalization API.

Formatting a Date

The first example I’m going to show uses the Internationalization API to format a date in several locales: IT, US, and GB.

// 30th of June 2016
var date = new Date(2016, 5, 30);

// "30/6/2016"
console.log(new Intl.DateTimeFormat('it-IT').format(date));

// "6/30/2016"
console.log(new Intl.DateTimeFormat('en-US').format(date));

// "30/06/2016"
console.log(new Intl.DateTimeFormat('en-GB').format(date));

In this example, I employ the DateTimeFormat constructor to create a new date formatter using the specified locale (“it-IT”, “en-US”, and “en-GB”). Then, I invoke the format method to format the date object.

The code above is also available as a JSBin.

Formatting a Number

As mentioned before, the API also allows you to format number. An example that employs the NumberFormat constructor is shown below:

var number = 1302.93;

// "1.302,93"
console.log(new Intl.NumberFormat('it-IT').format(number));

// "1,302.93"
console.log(new Intl.NumberFormat('us-US').format(number));

// "1,302.93"
console.log(new Intl.NumberFormat('en-GB').format(number));

By looking at the output of this second snippet, also available as a JSBin, you can notice that in Italy we format numbers differently compared to the USA and the UK.

As I mentioned earlier, the support for this API is low but in case you want to use it, you can employ this polyfill in your application.

Now that I’ve given you a better idea of how internationalization and localization work, let’s discuss Globalize.

Installing and Using Globalize

Globalize can easily be installed via npm:

npm install globalize cldr-data --save

This command also installs the CLDR data which is necessary to load the locale data (e.g. how numbers or dates are formatted in a certain language) that Globalize will use. With these two packages installed, we’re ready to use the library.

Note: the following examples assume Node. If you are interested in using Globalize in the browser, I recommend starting with one of the examples on the project’s homepage. The webpack example makes it especially easy to get up and running fast.

Next, I’ll employ Globalize to rewrite the two snippets listed in the previous section.

Formatting a Date

The first example can be implemented as shown below:

// Include the Globalize library
var Globalize = require('globalize');

// Include the CLDR data
var cldrData = require('cldr-data');

// Loads the supplemental data
Globalize.load(cldrData.entireSupplemental());

// Loads the data of the specified locales
Globalize.load(cldrData.entireMainFor('it', 'en', 'en-GB'));

// 30th of June 2016
var date = new Date(2016, 5, 30);

// "30/6/2016"
console.log(Globalize('it').formatDate(date));

// "6/30/2016"
console.log(Globalize('en').formatDate(date));

// "30/06/2016"
console.log(Globalize('en-GB').formatDate(date));

Despite its simplicity, the code above allows me to cover a few topics. The first thing that felt a bit weird to me the first time I played with Globalize, is that some of the language codes used by the CLDR data use only two letters. For consistency, I expected all the locales to require the full version of the ISO 3166 standard (e.g. “it-IT” and “en-US”) instead of the short version (e.g. “it” and “en”). While assuming Italian of Italy as the default seems legit (Italian originated in Italy after all), it was confusing for English. In fact, “en” represents American English and not British English. If you want to be sure not to make the same mistake I did, I suggest you to take a look at this table.

Another concept worth outlining is the entireSupplemental method (3rd statement of the code). This loads all the files that contain supplemental information for a country or its locale data. For example the telephone country code (39 for Italy), the population, some well-known abbreviations, how to spell other countries’ currencies, and much more.

The last point I want to cover is the fourth statement where I invoke the entireMainFor method. This allows to load the locale data for the desired countries (in the above example Italy, USA, and Great Britain).

Formatting a Number

To format a number, Globalize provides the formatNumber method. The signature of the method is

formatNumber(value[, options])

where value is the number to format and options is an object used to customize the return value of the method. Some examples of the options that you can specify are:

  • round: defines how the number will be rounded. Its value can be any of the following: ceil, floor, round, or truncate
  • useGrouping: A Boolean indicating whether a grouping separator should be used
  • minimumIntegerDigits: a non-negative integer indicating the minimum integer digits to be used.

The complete list of options available can be found in the documentation.

Now that we’ve learned more about the formatNumber method, let’s see it in action.

// Include the Globalize library
var Globalize = require('globalize');

// Include the CLDR data
var cldrData = require('cldr-data');

// Loads the supplemental data
Globalize.load(cldrData.entireSupplemental());

// Loads the data of the specified locales
Globalize.load(cldrData.entireMainFor('it', 'en', 'en-GB'));

var number = 1302.93;

// "1.302,93"
console.log(Globalize('it').formatNumber(number));

// "1,302.93"
console.log(Globalize('en').formatNumber(number));

// "1,302.93"
console.log(Globalize('en-GB').formatNumber(number));

Formatting Currency Values

The library provides a currencyFormatter method to help you format currency values. This method supports many options that let you define if you want to round the number, if you want to use the symbol of the currency (e.g. “$”) or its code (e.g. “USD”), and much more.

An example of use of currencyFormatter() is shown below:

// Include the Globalize library
var Globalize = require('globalize');

// Include the CLDR data
var cldrData = require('cldr-data');

// Loads the supplemental data
Globalize.load(cldrData.entireSupplemental());

// Loads the data of the specified locales
Globalize.load(cldrData.entireMainFor('en'));

var enGlobalize = Globalize('en');

var value = 229.431;

var usdFormatter = enGlobalize.currencyFormatter('USD');
// "$229.43"
console.log(usdFormatter(value));

var eurFormatter = enGlobalize.currencyFormatter('EUR', {
  style: 'code',
  round: 'ceil'
});
// "229.44 EUR"
console.log(eurFormatter(value));

Parsing Numbers

Parsing numbers can also be a task you have to perform, perhaps when dealing with user inputs. The following examples demonstrates how to do that:

// Include the Globalize library
var Globalize = require('globalize');

// Include the CLDR data
var cldrData = require('cldr-data');

// Loads the supplemental data
Globalize.load(cldrData.entireSupplemental());

// Loads the data of the specified locales
Globalize.load(cldrData.entireMainFor('en'));

// Set default locale
var enGlobalize = Globalize('en');

var numberParser = enGlobalize.numberParser();
// "229.431"
console.log(numberParser('229,431.00'));

var percentParser = enGlobalize.numberParser({style: 'percent'});
// "0.5341"
console.log(percentParser('53.41%'));

Formatting Relative Dates

Another very common feature in modern web apps is to show times and dates in relative terms. For example, instead of showing the full date of a day, you’ll usually find labels such as “yesterday” and “last week”. Achieving this task with Globalize is straightforward thanks to the relativeTimeFormatter method. An example of use is displayed below:

// Include the Globalize library
var Globalize = require('globalize');

// Include the CLDR data
var cldrData = require('cldr-data');

// Loads the supplemental data
Globalize.load(cldrData.entireSupplemental());

// Loads the data of the specified locales
Globalize.load(cldrData.entireMainFor('en'));

// Set default locale
var enGlobalize = Globalize('en');

var dayFormatter = enGlobalize.relativeTimeFormatter('day');
// "yesterday"
console.log(dayFormatter(-1));

var yearFormatter = enGlobalize.relativeTimeFormatter('year');
// "next year"
console.log(yearFormatter(1));

Globalize offers many other methods that I haven’t presented in this article. However, the topics covered here should have given you enough information to get you up and running. Moreover, the library’s documentation is very detailed.

Conclusion

In this article I discussed what internationalization and localization are and why they are important to expand a product’s market. I briefly introduced you to the Internationalization API by mentioning some supported features and then, I showed some examples of their use.

In the second part of the article I introduced you to Globalize, a JavaScript library for internationalization and localization developed by the jQuery team. The library is very powerful and comes with all the methods you might need to internationalize your project, for example: methods to parse numbers, format dates, and format currency values. If you think the library has saved you time, feel free to give something back by contributing to the project.

Once again, I want to remind you that all the snippets demonstrated in this article can be found on our GitHub repository.

Frequently Asked Questions (FAQs) on Implementing Internationalization (i18n) in JavaScript

What is the significance of internationalization (i18n) in JavaScript?

Internationalization, often abbreviated as i18n, is a crucial aspect of web development, especially when creating applications intended for a global audience. It involves preparing your website or application to support multiple languages and regional differences. This is particularly important in JavaScript, a language widely used for web development. By implementing i18n in JavaScript, developers can create applications that cater to a diverse user base, enhancing user experience and accessibility. It also helps in localizing the application, which can significantly boost the application’s reach and usability.

How does i18n work in JavaScript?

i18n in JavaScript works by allowing developers to externalize locale-specific strings or messages from the application’s code. These strings are then stored in separate files, often referred to as resource bundles. Each resource bundle corresponds to a specific locale. When the application runs, it identifies the user’s locale and loads the appropriate resource bundle. This way, the application can display messages and content in the user’s preferred language.

What are some popular libraries for implementing i18n in JavaScript?

There are several libraries available for implementing i18n in JavaScript. Some of the most popular ones include i18next, i18n-js, and Globalize. These libraries provide a range of features to facilitate internationalization, such as language detection, pluralization, formatting for numbers and dates, and more. They also support various frameworks like React, Angular, and Vue.js, making them versatile tools for web development.

How do I use the i18n-js library in my JavaScript project?

To use the i18n-js library in your JavaScript project, you first need to install it using npm or yarn. Once installed, you can import it into your project and start using its functions. The library provides functions for translating strings, formatting numbers and dates, and more. You can also define your translations in separate JSON files, which the library can load based on the user’s locale.

Can I implement i18n in JavaScript without using a library?

Yes, it is possible to implement i18n in JavaScript without using a library. This can be done by manually externalizing locale-specific strings from your code and storing them in separate files. However, this approach can be time-consuming and complex, especially for larger applications. Using a library can simplify the process and provide additional features that can enhance the internationalization of your application.

How do I handle pluralization in i18n?

Handling pluralization in i18n can be tricky due to the different rules for plural forms in different languages. However, many i18n libraries provide functions for handling pluralization. For example, the i18n-js library provides a pluralize function that can handle plural forms based on the user’s locale.

How do I test my application’s internationalization?

Testing your application’s internationalization involves checking whether the application correctly displays content in different languages and formats based on the user’s locale. This can be done manually by changing the locale settings in your browser or using automated testing tools. It’s also important to test edge cases, such as missing translations or incorrect plural forms.

How do I handle date and number formatting in i18n?

Date and number formatting can vary greatly between different locales. Many i18n libraries provide functions for formatting dates and numbers based on the user’s locale. For example, the i18n-js library provides formatDate and formatNumber functions that can handle these tasks.

How do I handle right-to-left (RTL) languages in i18n?

Handling right-to-left (RTL) languages in i18n involves adjusting the layout and text direction of your application based on the user’s locale. This can be done using CSS and HTML attributes. Some i18n libraries also provide functions for handling RTL languages.

How do I handle localization (l10n) along with i18n?

Localization, often abbreviated as l10n, involves adapting your application to a specific locale, including translating content, formatting dates and numbers, and more. While i18n prepares your application for supporting multiple locales, l10n involves implementing these adaptations for each specific locale. Many i18n libraries also provide features for handling localization.

Aurelio De RosaAurelio De Rosa
View Author

I'm a (full-stack) web and app developer with more than 5 years' experience programming for the web using HTML, CSS, Sass, JavaScript, and PHP. I'm an expert of JavaScript and HTML5 APIs but my interests include web security, accessibility, performance, and SEO. I'm also a regular writer for several networks, speaker, and author of the books jQuery in Action, third edition and Instant jQuery Selectors.

globalizei18ninternationalizationInternationalization APIjameshlocalization
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week