I18N in qooxdoo
Filed under: Technical, Tool Chain
By Thomas Herchenröder @ January 14, 2009 1:00 pm
"I-what?!" Well, I18N stands for "Internationalization", a word that starts with an "I" and ends with an "N" and has roughly 18 characters in between. It's all about making a system support different natural languages and locales in its user interface.
If you are creating a qooxdoo application and want to support I18N, an important part is to allow for the translation of user visible strings. In a typical qooxdoo app you have those kinds of strings all over the place: as labels of buttons and menus, user instructions, help texts and pop-up messages. In the first step those strings simply appear as literals in your JS code.
The support of qooxdoo to aid you in translation now is two-fold: For one, you can wrap all strings in calls to one of qooxdoo's translate methods, like qx.locale.Manager.tr() (static) or this.trn() (instance). In your config.json you specify a list of locales, like "en", "en_us", "fr" asf., you want to see supported (in the LOCALES macro). When you then run generate.py translation, for each given locale a .po file is generated.
.po files are essentially text files that contain a list of translatable strings. The strings from the JS source code are used as keys in these files. Then, a translator can add a proper translation to each key. So, if you halfway expected qooxdoo to magically do the actual translation, I have to disappoint you; we're not quite there
. But .po files are a fairly common way to organize translatable strings of applications, and were devised in the context of GNU's gettext project. Since we strive to rely on Python only in our tooling, we use David Jean Louis' polib module for Python to create and manage .po files.
After the keys in the .po files have been translated, the next invocation of generate.py source or build will pick up those translations and add them to the generated application output where they are available to the application at run time. A call to qx.locale.Manager.getInstance().setLocale() allows you to dynamically switch between locales. All strings that take part in translation are immediately resolved with their translation of the chosen language. To see this in action take a look at the Feedreader demo and play with the Preferences dialog.
One thing to note here is that calls to the tr*() methods in the code are evaluated twice: First, when generating the .po files (this is sort of a preprocessing step); and second, at run time when they return the proper translation to the running code. This also means that the first step needs string literals to pick them up as keys for the .po files. At run time tr() also runs fine with variable arguments so you can use this in your code. But you have to make sure that all values the variable might take appear elsewhere as string literals in a call to tr(). Otherwise your variable might take a value at run time for which no translation exists. (Some people resolve this issue by injecting dummy classes in their application that only hold calls to tr() on string literals. These classes do nothing at run time, and can actually be pruned from the build).
For more information on translation support see this wiki page.

Comment by Sebastian Werner
Nice writeup Thomas. Should be really helpful for new users to this topic.
January 14, 2009 4:51 pm
Comment by Earth
Very interesting indeed
January 14, 2009 9:18 pm
Pingback by qooxdoo » News » Generator and Unicode Application Name Spaces
[...] and Unicode support in qooxdoo, and qooxdoo’s tool chain particularly. (The other so far were 1 and [...]
June 3, 2009 7:18 pm