Internationalization
This page describes how to translate either a new or an existing qooxdoo-based application. It shows how to prepare the application, extract and translate the messages and finally update and run the translated application.
Prepare the Application
To translate an application, all translatable strings must be marked using one of the following functions:
this.tr(): translate a messagethis.trn(): translate a message that supports a plural formthis.marktr(): mark a string for translation, but do not perform any translation
For convenience these functions are added to qx.core.Object, which is the base class of all qooxdoo objects. Therefore, they can simply be used as this.tr() and so on.
self instead of this when you use the translation features inside a closure e.g. self.tr(). See using_self_for_closures for details using self as a local variable name.
Example
Change original code like this:
var button = new qx.ui.form.Button("Hello World");
to:
var button = new qx.ui.form.Button(this.tr("Hello World"));
In the following, the three methods are explained in more detail:
tr
var button = new qx.ui.form.Button(this.tr("Hello World"));
Marks the string Hello World for translation and returns an instance of qx.locale.String. The toString() method of the returned object performs the actual translation based on the current locale.
this.tr("Hello World")
is valid whereas
this.tr('Hello World')
won’t be processed correctly by gettext, as it is a C tool.
There is one exception to the simple rule that all strings can just be replaced by wrapping them in an appropriate this.tr() function call: if init values of dynamic properties are meant to be localizable, the init value has either to be set in the class constructor using this.tr(), or qx.locale.Manager.tr() has to be used inside the property declaration. See documentation on Defining an init value for details.
trn
var n = 2; var label = new qx.ui.basic.Label(this.trn("Copied one file.", "Copied %1 files.", n, n));
Translate a message but take differences between singular and plural forms into account. The first argument represents the singular form, while the second argument represents the plural form. If the third argument is bigger than one, the plural form is chosen. All remaining parameters are the inputs for the format string.
marktr
Sometimes it is necessary to mark a string for translation but not yet perform the translation.
var s = this.marktr("Hello");
Marks the string Hello for translation and returns the string unmodified.
Format Strings
Since sentences in different languages can have different structures, it is always better to prefer a format string over string concatenation to compose messages. This is why the methods above all support format strings like Copied %1 files as messages and a variable number of additional arguments. The additional arguments are converted to strings and inserted into the original message. % is used as an escape character and the number following % references the corresponding additional argument.
Extract the Messages
After the source code has been prepared, the desired languages of the application may be specified in the Makefile, for example
APPLICATION_LOCALES=de fr
This would add a German and a French translation to the project. A run of make will generate a .pot file with all translatable strings of the project and merge this file with all existing translations.
If a specified translation does not yet exist, an empty translation file will be put into the source/translation folder. In this example two files source/translation/de.po and source/translation/fr.po would be created.
Translate the Messages
These .po files are the actual files you - or your translator
- would have to edit. Since qooxdoo internally uses the well-known and mature tools and formats for internationalization ("gettext"), any “po”-aware editor or even a simple text editor can be used.
Some of the programs that support manipulation of .po files:
- KBabel (Linux)
- poedit (Linux, Windows, Mac OS X)
- LocFactory Editor (Mac OS X)
Update the Application
After editing and saving the .po files, another make integrates the translations into your application’s source directory. The application is now translated and can simply be reloaded in your browser.
If the source code changes, e.g. by adding, removing or changing translatable strings, it can be merged with the existing translation files just by calling make (or make build if you are about to deploy your application).
Run the translated Application
By default the application tries to use the browser’s default language. You can change the language of the application by using qx.locale.Manager. For example, the following sets the language of the application to French:
qx.locale.Manager.getInstance().setLocale("fr");
The qooxdoo widgets are supposed to update their contents on a locale change. Custom widgets may have to be modified to allow for an update on locale change. To inform the application of a language change, qooxdoo fires a “changeLocale” event.
A widget that needs custom update logic may listen to this event:
qx.locale.Manager.getInstance().addEventListener("changeLocale", this._update, this);
