Internationalizing & Localizing Your Modern JavaScript App
The current state of internationalization and localization (sometimes called i18n and l10n) tools for modern javascript apps is discussed, both for client-side and server-side rendered applications, including how to manage translation strings, handling plural forms, testing, translation process, and interfacing with external translation providers. I'll go over the currently available libraries, status of the INTL browser standard, and what I've found successful. The goal is to achieve an easy and well-translated app that scales to your audience, no matter where they are located and what language they speak.
2. $ whoami
I’m Johnathan. I work at Airware on the cloud
platform for managing fleets of drones. Before that,
I worked at LinkedIn.
github.com/jleppert, blog @ stuffzies.com
i18n and translating apps is a reoccurring project
for me.
It can be painful, or fun.
4. Why should we translate our
apps?
• More users….? Quicker time to market than competitors.
• Enforce good design principles from day one
• It’s really hard and tedious after you have a lot of code
that didn’t care about it or consider it
• Bolted on i18n usually looks half-baked and janky —
you’ll have to make compromises
• Today’s apps are conversational. More than just about
button labels.
5. Goals
• Clean, simple workflows: developer first. Shouldn’t
“get in the way”
• Works on server/client with same idioms/API and, if
possible, code
• Shared messages resources for your translators or
translations provider
• Output is cacheable, strings sent down in javascript
bundles
6. Isn’t there a standard for
this? Kind of…
• ECMA-402 (2012)
• INTL object — available in the latest browsers, and,
now, node (v0.12 mainline — only en_US. Other
locales need a compile option). CLDR data is big.
• INTL.DateTimeFormat - Date formatting
• INTL.NumberFormat - Number formatting
• INTL.Collator (sorting)
8. How to use INTL
Step 0: Getting the user’s locale
Sadly, there is no defined API. navigator.language
(chrome/FF) and navigator.browserLanguage in IE,
or read the Accept-Language header.
I prefer to make an intelligent guess, then ask the
user — have it preselected. Store locale (string, e.g.
“en_US”) a cookie that is independent of your
session cookie.
11. Collation
var coll = new Intl.Collator(['en'], { sensitivity: 'base',
ignorePunctuation: true });
base = a = á, etc.
coll.compare('Bluebird', ‘bluebird') === 0, case is ignored.
coll.compare(‘blackbird’, ‘black-bird’) === 0, punctuation ignored
coll.compare('bluebird', ‘blackbird') === 1, (“u” is after “a”)
12. What about strings?
Something old, something new: gettext
• It works
• Handles pluralization and positional interpolation
• Use the existing ecosystem of tools, translation
providers
• Template-system, framework agnostic
13. An example app
• https://github.com/jleppert/rosetajs/
• Using Dust, Jed, po2json, browserify
• Same workflow client or server
• Same message format, code, helpers.
14. Developer API
• The @i18n template helper.
• {@i18n singular="Hello, {first_name}, you have
one message." plural="Hello, {first_name}, you
have {message_count} messages!"
value=“{message_count}"/}
• API: i18n.translate(‘Hello, {first_name}, you have
a new message!!.’, { first_name: ‘johnathan’});
15. How does it work?
• Template files and javascript source are read, an AST is
constructed and the @i18n helper calls/API are used to
create a .po file.
• xgettext - extracts translatable strings. I wrote a version that
understands javascript and dust templates, but you can do
so for most any language.
• po files are sent to translators, where they translate the
messages/re-arrange placeholders, etc.
• The right po file is selected based upon the user’s selected
locate and used during template helper/translation API
17. Considerations
• Organize templates by feature (hopefully…)
• Automated tar of po files, send to translators via CI system
• Translate by feature: “this feature is available in english, french,
and spanish will be launched 6/10”
• Suffix files by locale for easy organization and co-locate them
• Check files into some source control project: receive translations
out of order from deployment
• Consider adopting a pirate-speak locale — getttext project has
many such manglers for po files
18. Thanks, and here’s some
More info
• Mailing List: http://jsi18n.com
• Gettext Overview: https://developer.mozilla.org/en-
US/docs/gettext
• PO/POT Format:
http://pology.nedohodnik.net/doc/user/en_US/ch-
poformat.html
• JS Gettext Implementation:
http://slexaxton.github.io/Jed/
• po2json: https://github.com/mikeedwards/po2json
Notas do Editor
solving this problem many times
isn’t a sexy problem, but very important for the company
developer systems, processes: good, bad and ugly
calltech to teleperformance, traffic increases as more people can actually read and interact with the app in their language: step 0 in personalization
airware, drones aren’t legal in us, so the app needs to be international from the start
rethinking things to ease roll-out, new languages, process, translation quality.
everybody loves standards, when they do……come
INTL standards
Example app, can use everything as is, or just use the concepts
more users is obvious, more users === more money for most people
german: “my profile” = 32 characters. tabs will fall off the page
airplane analogy
lots of people use keys. keys. LONG keys. short keys. bad keys. positional? what’s that? plural? we only got one.
started work in 2012. embarrassing.
CLDR - big tech companies unite. lots of data. locale data.
locale, region
they forgot this part of the standard. step 0. yeah.
translators may need to re-arrange placeholders
it’s a PROCESS
buzzword alert: isomorphic. i love that word.
why i like dust: streams, compiling, fast. AST.