Last Comment Bug 706572 - Document best practices for localizing node.js services
: Document best practices for localizing node.js services
Product: Mozilla Localizations
Classification: Client Software
Component: Documentation (show other bugs)
: unspecified
: All All
-- normal (vote)
: ---
Assigned To: Jeff Beatty [:gueroJeff]
Depends on: 723775
  Show dependency treegraph
Reported: 2011-11-30 11:05 PST by Axel Hecht [:Pike]
Modified: 2012-02-15 15:35 PST (History)
11 users (show)
See Also:
Crash Signature:
QA Whiteboard:
Iteration: ---
Points: ---

Screenshot of signin dialog localized to fake pl (132.14 KB, image/png)
2012-01-05 18:14 PST, Austin King [:ozten]
no flags Details
BrowserID in db-LB (67.06 KB, image/png)
2012-01-11 09:17 PST, Austin King [:ozten]
no flags Details

Description User image Axel Hecht [:Pike] 2011-11-30 11:05:59 PST
browserid is our first site to be based on node.js.

Let's document what we do and why that works good or OK as we learn what we're doing.
Comment 1 User image Austin King [:ozten] 2011-12-12 09:19:10 PST
(In reply to Axel Hecht [:Pike] from comment #0)

Maybe you can re-work

If the way you document this isn't that page, we can redirect it to your solution that closes this bug.
Comment 2 User image Matjaz Horvat [:mathjazz] 2011-12-12 10:56:55 PST
Comment 3 User image Austin King [:ozten] 2012-01-04 13:54:16 PST
CCing Rik

Detailed work log is in

Update: I'm working with @Matjaž in two phases:
1) System perspective, making Node app localizable
2) Wrapping all strings in the app with gettext, extracting/merge po files

In first step we'll figure out which Node modules can be re-used and build missing glue based on sample set of template/JS files.

In second step we'll get the app codebase ready for the L10n community to contribute via PO files in SVN.
Comment 4 User image Axel Hecht [:Pike] 2012-01-05 04:43:37 PST
I briefly chatted with Austin, just to dump this somewhere in writing:

It might be easier to localize the templates server-side instead of doing both the templating and the localization in client js.
Comment 5 User image Austin King [:ozten] 2012-01-05 18:14:55 PST
Created attachment 586303 [details]
Screenshot of signin dialog localized to fake pl

@mathjazz, llyod, stomlinson based on our work in the etherpad, I've got a proof of concept hacked together for the sign-in dialog localized with fake (sorry) Polish. See attachment.

Proposed changes to browserid to support localization:

EJS templates and node.js JavaScript code will remain as is, but any user facing strings will be wrapped in gettext or ngettext. English strings will be used for msgids.
Example: <p><%= gettext('Please, enter an Email address to continue.') %></p>

Two new bash scripts in the browserid repo will be used to manage creation of PO files.

These are run at string freeze or periodically to get new strings.

locale would be a SVN repo checked out from

The output of these scripts goes into the typical svn locale layout. There are also two scripts that live in the SVN repo:

locale/ – string freeze time (or whever po files change), this script is run and the output is committed to the git repo (details below).

locale/ – deployment time “build” step, compiles PO into MO files. MO files are not checked into SVN.

New node.js dependencies:

node-gettext and iconv (a C node.js module) – Server side gettext will read strings from MO files. This will work for strings in JavaScript or EJS templates.

New client-side JavaScript dependencies:

Gettext.js and from the BerliOS project. (We'll probably fork and remove un-needed code from Gettext.js).

Machines which can run will need Perl and two CPAN libraries. This doesn't have to be done by browserid dev team and a post-commit hook could be setup to automate this. 

Usage: ./locale ./resources/static/i18n
For each locale the script creates a JSON formatted bag of strings that Gettext.js understands.

Example filename:
These strings are used by client-side EJS template rendering as well as client-side JavaScript which contains strings.

EJS Templates:
EJS use gettext, ngettext, etc as well as strargs on the client side and util.format on the server side for string interpolation.

Server-side Examples:
<%= _('Hello') %>
<%- gettext(“I have <em>Embeded</em> HTML”) %>

Client-side Examples:
<%= strargs(gettext('Hello %1'), 'World') %>

I'd recommend using same methods on client and sever EJS templates to improve consistency.

Note: _ is already used in client side JavaScript and EJS templates, so gettext or another alias should be used. (Or we can noConflict underscore.js).

New Middleware:

Server-side we'll detect the user's preferred locale by looking at the URL, a path limited Cookie, and the request's accept-language header.

Current locale will be detected and used to setup node-gettext for server side gettext.

Client side gettext will be setup via:

In development mode, the dialog template will include a script file
which will redirect to

In production mode, we'll include Gettext.js and messages.json in a performance sensitive way. Team is revisiting cache busting, which will inform this solution.

This middleware will be controlled by a new configuration parameter:
production.locales = ['en_US', 'pl', 'hu']
(or some such in lib/configuraiton.js)

Much of this proposal re-uses existing code, but none of the existing node.js modules for middleware are written with Mozilla l10n idioms in mind; Filling the gap won't be much code, so we'll either fork connect-i18n or write from scratch.

I think that covers most of what we'll need to localize the dialogs.

For more details on what was considered, but not chosen please see the updated etherpad.

How do we feel about this direction? Anything missing? Issues?
Comment 6 User image Matjaz Horvat [:mathjazz] 2012-01-06 13:23:36 PST
As I already said at the meeting today, I'm really impressed by the progress you made. Great job!

To test i18n support for the BrowsearID service, me and Axel agree we should localize a few dialogs with a fake locale. Perhaps Axel can say something more about translate toolkit, which creates similar translations.
Comment 7 User image Axel Hecht [:Pike] 2012-01-06 13:58:36 PST
I was thinking of podebug, I'll read and comment more.
Comment 8 User image Axel Hecht [:Pike] 2012-01-10 06:58:01 PST
I've found, which seems to be unhandled at this point?


I'd love to join a call of you guys to get a verbal update. The etherpad is useful, but I'm better digesting information aurally.

I'm particularly wondering about the combination of l10n on both client and server, even more so if we're doing them slightly different on the js side, ie. local gettext library on the server vs json on the client.
Comment 9 User image Austin King [:ozten] 2012-01-10 08:40:55 PST
(In reply to Axel Hecht [:Pike] from comment #8)

> I've found, 
> which seems to be unhandled at this point?

Good call, I didn't spend much time on email. I'll look into how those templates work.

> I'd love to join a call of you guys to get a verbal update.

We're in IRC in #identity. I'll look for you, maybe we can Skype today.
Comment 10 User image Austin King [:ozten] 2012-01-11 09:17:59 PST
Created attachment 587727 [details]
BrowserID in db-LB

(In reply to Axel Hecht [:Pike] from comment #7)

podebug is very useful! See attachment.

Adding a new debug locale 'db-lb' "David Bowie - Labyrinth"

to trigger debug mode, Esperanto on development servers will switch to db-lb instead of 'eo'.

As noted in making db-lb a RTL locale, to add to disorientation for westerners.
Comment 11 User image Austin King [:ozten] 2012-01-11 17:06:10 PST
Adding i18n to wsapi for email.

Organized strings into 
* messages.po - Node.js strings
* client.po - Client-side strings
Switched email from mustache to EJS templates.                                                                             
Created fake locale db-LB for development and debugging.       

Updated extract, merge, compile scripts

SVN updated

Github updated:
Comment 12 User image Austin King [:ozten] 2012-01-13 16:11:22 PST
Here is a short no-audio screencast to show which screens we've wrapped with gettext while implementing the i18n portion of this bug. - Loads directly in Firefox.

Code is currently under review at
Comment 13 User image Austin King [:ozten] 2012-01-20 15:34:20 PST

We're done with the i18n phase and things are looking good, so far.

Please try it out on dev
1) Set your preferred locale to Esperanto*
2) and Sign in

If you see English strings in a couple places, we are still working out caching and deployment bugs, probably Monday.

This current release train will be 2 weeks, instead of 1 week as previously discussed.

* Until we have a language picker, we need a locale to trigger our easter egg db-LB locale.
Comment 14 User image James Bonacci [:jbonacci] 2012-01-21 21:31:40 PST
In FireFox on Mac, selected Esperanto [eo] as my preferred (first pick) language.
Opened and signed in with a known account.
I see nothing localized.

Same result for Chrome on Mac.

Restarted each browser just in case I needed that for setting locale.

PS: + Safari is a sad face (I can not even Sign In)
Comment 15 User image Austin King [:ozten] 2012-02-01 16:06:07 PST
@mathjazz has us in the homestretch here...

Temporary preview environment -

Localizers can start testing their locales on this temporary server.

Progress -

A permanent l10n preview environment is being built, but due to lack of IP Addresses isn't ready. We're on schedule for a Feb 8th launch of signed off locales.
Comment 16 User image Austin King [:ozten] 2012-02-06 18:15:06 PST
Most locales are enabled on stage, we should test the deployment per Bug#723775

Live update is still only on temporary_preview.
Comment 17 User image Austin King [:ozten] 2012-02-10 08:37:40 PST
We are scheduled to ship to produciton either next Wed 2/15 or Thursday.

All locales that are 100% translated will be enabled.
Comment 18 User image Austin King [:ozten] 2012-02-15 15:35:56 PST
And where live in production with:
  "ca", "cs", "da", "de", "el", "en-US", "es", "et", "eu", "fi", "fr",
    "fy", "ga", "hr", "it", "lij", "nl", "pa", "pl", "ru", "sk", "sl",
    "sq", "sr", "sv", "tr", "zh-CN", "zh-TW"

Doing push verification, but marking bug fixed.

Note You need to log in before you can comment on or make changes to this bug.