A strategy for i18n in node.js server templates
A website development nowadays requires to support multiple languages. This article describes the goal we want to achieve, existing tools in the node.js ecosystem and propose a strategy. We’ll explore what experience we want to bring to our users, the server side features we need.
What user experience do we want ?
I was never logged in the application. On first login, the application will sniff my browser prefered language and send appropriate templates. If ever the language isn’t available, the english templates will be sent.
I explicitely choose the language in my application settings. From now on, whatever browser I’m using, the server will send the template of the language I spedified (falling once again back to english if the localized template doesn’t exist).
What do, as developers, we want ?
We use Angular.js as our frontend library. Angular auto loads directive templates, which means we can’t pass some hints from the browser (e.g. ?lang=es). The server should get user preferences, and if set, use them. If not set, or if I’m not logged in, it should sniff the browser languages and use them. If not set, it should fallback to english.
Overview of node.js, and more specifically express, localization systems
As it’s the rule in node.js, the i18n is very fragmented. The mechanism of getting translated templates can be split onto those parts.
- The storage format
- The accept-languages headers are already parsed by express and available in the request object.
- The middleware responsible of getting the user preference and applying it
- The library that will provide nice utility functions in our template files
- And the glue to inject stored translations to this nice utility
Some libraries are focusing on one of those steps, others offers an end to end solution.
It will be a long day.
1. The storage format
There are two main standards in the software industry for translations storage: the GNU Gettext PO format, and the OASIS XLIFF format. In the node.js world, primary structures for translation informations are standard Javascript objects, so a lot of libraries uses the JSON format for translation storage. It’s also worth mentioning that there are a few utilities providing PO<=>JSON conversion. So many translation formats exists that soem websites provides conversion systems for them.
At Linagora, we love standars and we love GNU, so the obvious choice is to use the Gettext format as the storage format. However, we also love the Node.js ecosystem and conventions, and it’s clear that in this world, JSON translation files are kings.
2. The middleware responsible of getting the user preference and applying it
Well it’s not a surprise that this doesn’t exist. It’s tightly tied to the application. What we see are middleware that looks and record into cookies, in the query string, in headers. It won’t be a big deal to get this thing running.
3. The library providing template utility functions
Those are legion. It’s useless to study them all. Some however can be mentionned because they are written by rock stars. We find in this category i18n-2 written by John Resig (remember jQuery ?), and Polyglot brought by the folks at airbnb. Another big library is i18next, that also works in the browser. However, it’s more opiniated on how to use it.
Are template engines and i18n utility functions linked ? That is to say, is there some sort of dependance between the i18n mechanism and the template engine, resulting in some combinations not working ? The response is mitigated. The Express framework provides a way to inject utility functions to templates, and it should work for any template engine. However i18n library makers don’t test any combinations, so for a given library, some are known to work, and the others are labelled “Use at your own risks”.
What features do we need for the LINAGORA ESN project ?
The main features we need are:
- an integration with the templating engine through express
- support for localization ( i.e. en , en_US, en_GB )
- support for multiple files (that one isn’t as important as the others)
- a library with tests, and preferred with an active community
Overview of the main used libraries.
The website node-modules order the npm modules using a secret algorithm made of Github stars & followers, dependant modules, and other cool stuff. A search of “internationalization” and then “i18n” brings us interesting modules :
This one is heavily used, but is primarily for use in a browser. There is a big drawback using it in node.js : we set the active locale in the global Globalize object. That’s a real problem if two requests are using distinct languages (which should come soon in a web application).
This one is written by the engineers at AirBnB. It seems to be a cool library, however, there are missing pieces: polyglot doesn’t handle the loading of i18n data, and doesn’t provide an easy to use express compatibility layer.
JED is a powerfull translation library, using Gettext PO files (or, more specifically, JED specific JSON representation of PO files) as input, and provides a fluent interface. However, once again, we miss the express compatibility layer.
This one seems to be a de-facto standard for node.js projects. It’s used by 27 modules. It provides an express layer. It also supports region localization. This library seems to be a great choice. At least, it’s the first that provides all the features we need.
This module also provides everything in one library, from modules loading to express integration. The main difference with i18n is that the former uses plain “reference” strings, and this one uses keys. Also, the community seems a little less active.
This module once again provides everything in one library, from modules loading to express integration. However, it doesn’t provide pluralization system.
The great Mozilla Foundation is providing this nice library. It got a backend plugin system that allows for getting translations from various sources (po files, JSON, …). Unfortunately, the library is still young and the commit activity seems not that regular.
Some sort of conclusion
The team primary choice is i18n. We’ll now play with it to decide wether it fulfill our needs.
Browsers technologies we can use in a new project Deploy MongoDB – Replication – Sharding