If you want to use Globalize.js in your JS i18n project, there are a few things you need to do to make it work. First, you need to load the necessary resources to configure it. Subsequently, we only need to provide translations. Let’s discuss the steps one by one.
First Steps towards JS I18n with Globalize.js
Let’s start our journey with a simple HTML5 Boilerplate. If you want to access the source code of this project, it’s hosted on GitHub. First, create a project folder and download the sources from here.
Install the dependencies. Once the installation is completed, we can start building the application:
This will create a dist folder where all the static assets of your website are compiled. To run the application, just start a static webserver on that location. For example, using python3:
Navigate to http://0.0.0.0:8000/ on your browser and you will see the default message:
Now that we have created our boilerplate, let’s see how we can install Globalize.js into our application…
First, install it together with its dependencies using npm:
You’ll also want to install some gulp plugins needed to move forward:
Add some tasks to load the necessary libraries for Globalize.js and include them in the copy sequence:
Finally, reference the dependencies in the index.html file just below the jquery script tags:
Now we need to bootstrap the library with the right CLDR data. Because the cldr-data package downloads the whole list of locale data from a lot of languages, we may want to load all of them now Only the ones that we support, that is! Let’s say we want English and Greek.
We’ll need the following files:
- cldr/main/en/ca-gregorian.json and cldr/main/el/ca-gregorian.json for the Calendar data
- cldr/main/en/currencies.json and cldr/main/el/currenciens.json for currencies
- cldr/main/en/numbers.json and cldr/main/el/numbers.json for numbers
- cldr/main/en/units.json and cldr/main/el/units.json for units of measure
- cldr/supplemental/timeData.json for time data
- cldr/supplemental/weekData.json for week data
- cldr/supplemental/plurals.json for plural rules
- cldr/supplemental/likelySubtags.json for language tag rules
We can do the same thing as previously. Add a gulp task to copy those files into a cldr folder so we can retrieve them when we load the application.
Add the following gulp tasks:
If you run gulp build, you should be able to see the following file structure:
Now we are ready to bootstrap the library.
Add the following code in the main.js located inside the src folder:
Notice that we loaded only the English CLDR data. This is because we have the option to load the Greek CLDR data on demand when we switch the locale, thus saving resources. We can do that with the help of a small toolkit that we’re going to use to switch languages.
Let’s explore the Globalize.js API to see how it can help us with our needs:
- Loading Messages: The most basic task is to load the messages for each particular locale. To do this, we need to use the loadMessages method that accepts an object with language tags as keys, for example:
After loading the messages, we can use the formatMessage method to print a particular key:
- Variable Replacement: We can loadMessages that accept parameters. We can then use the messageFormatter method to return a formatter function that we can invoke with the parameters we want to provide:
- Plural Rules: We can also specify plural forms for the messages. We need to describe our message values in the following format:
- Gender Rules: We can also format messages based on the specified gender whenever it makes sense. For example:
In addition to the main API, there are some other useful methods available:
- relativeTimeFormatter – prints locale-specific relative time messages
- currencyFormatter – formats currency according to the specified locale
- dateFormatter – formats dates according to the specified locale
Detecting User Locale
Globalize.js does not offer a way to detect the current user locale so we have to manually add some checks. We can easily do that with a simple service.
Then, in our main.js file, we can import it as:
Using that approach, we can build our own little i18n toolkit that handles the current locale settings for us. For example:
Then, in our main app:
If you look at the console log output:
Using an EventEmitter, we can trigger now new events such as loading the Greek translations from the store.
Let’s create a folder that will load the locale messages:
Put some messages here for each locale:
Modify the initial loading bootstrapping of the app
Now, let’s see what the loadTranslationsFor function does:
So we need a language tag to load the relative CLDR data and messages for that. If we run the main.js we can see that it logs the correct message in the console:
Generally, when we change the locale, we also want to re-render the HTML that displays the old messages so as to reflect the current selection. Since we’re not using a framework, we can only rely on having multiple document.getElementById selectors to update the messages. However, you can do better if you have a template engine such as Mustache.js or Handlebars.js.
Alternatively, we can use a microframework such as Hyperapp that can trigger updates whenever the model changes. The fact that we can use Globalize.js in Node and refresh the page when we change the locale is also to the benefit of your project. Of course, this is a topic for another article, but for simple cases, we can have a tool that works without adding a lot of extra dependencies.
In this tutorial, we introduced Globalize.js to a startup HTML5 boilerplate code and explored some of the ways we can use it in practice. In general, we can say that this library has good support for different translation rules and good interoperability. By leveraging the utilities that we described in this post, we can make our lives so much easier and also provide some value to our users. We can also do better and integrate a fully fledged translation management system such as Phrase that will take care of a lot of the nitty details for us. Until then, stay put for more articles regarding i18n and l10n best practices!