mozilla-b2g/gaia — pull request #12050 by stasm (2013-09-10 00:01:14+00:00)
Title: Bug 914414 - Refactor l10n.js

The first step of switching Gaia over to L20n (bug 913712) should minimize the impact of the change; we therefore simply aim to replace the shared/js/l10n.js file. No changes to the API nor the file format are being made at this point.

We created a branch of the main L20n codebase which supports the .properties files and is fully compatible with the navigator.mozL10n API. This means that no changes are need to the l10n infrastructure, the build infrastructure and the developer process. Everything should just work as it did before.

The code is developed in https://github.com/l20n/l20n.js/tree/gaia and bugs can be filed against the L20n Product in Bugzilla (Component: Gaia Bindings). Test results are at https://travis-ci.org/l20n/l20n.js

Switching to this special version of L20n already brings a number of improvements:

- modular code which encapsulates main concepts of localization with a clean OOP approach,
- clean start-up which prevents race conditions on app launch and on language change,
- robust language negotiation via the Intl object,
- smart language fallback using the negotiatied fallback chain,
- much better error reporting, especially on build time,
- increased security thanks to the compilation step.

Other features of L20n can be implemented over time as progressive improvements.

Some minimal changes were needed to the build scripts (because of the change in how the inlined JSON looks like and where we take the information about the available locales). The pull request also updates a few tests which made too many assumptions about how l10n.sj was loaded.

The last commit lands the actual L20n code in shared/js/l10n.js. It deserves perhaps a little bit more explanation:

The structure of L20n in https://github.com/l20n/l20n.js/tree/gaia (names of modules are derived from folder and file names):
- ./lib/l20n/ - the core library
- ./lib/client/l20n - clientside overrides (for I/O)
- ./bindings/l20n - platform bindings

We recommend to review the components in the following order, starting from most isolated classes, to more algorithmic code:

1) event.js - simple EventEmitter

2) io.js - simple XHR based I/O

3) intl.js
- subset of ECMA 402 implementation extended to support prioritizeLocales giving us full language negotiation
- once we standardize prioritizeLocales in second edition of ECMA 402 we will be able to remove this
- read more https://mail.mozilla.org/pipermail/es-discuss/2013-July/031771.html

4) plurals.js - pretty close copy of the l10n.js:getPluralRule

5) parser.js
- .properties parser.
- one thing to notice is that we initially parse every string as "simple" and only mark it for lazy complexString resolution

6) compiler.js - the compiler class creates JavaScript objects and functions out of the AST that is the result of the parsing. This provides a runtime environment for localization and helps safe-guard the evaluation of entities and macro expressions. The full version of L20n supports custom macros and the compilation step ensures no malicious code is being interpreted. Since shared/js/l10n.js doesn't support custom macros, we turned them off as well in this version, but by keeping the compiler we're ready to re-add them in the future with little effort.

7) context.js - context has three classes:
- Resource - single resource object,
- Locale - single locale object with multiple resources for a given locale id,
- Context - core class of L20n which manages loading resources, resolving them and locale fallback.

8) webl10n.js
- platform bindings. HTML node translation, pretranslation, INI parsing, public events