Documentation/Maemo 5 Developer Guide/Application Development/Maemo Localization

This section describes how to localize Maemo applications. Localization is needed to provide native translations of the software. The section contains information on how to localize an application, how to ease extraction of message strings, how to make the translations, and how to test the localization.

Changes are presented with code examples to help the localization process. MaemoPad is used as an example here.

Contents

[edit] Localization

Localization means translating the application to different languages. Maemo localization is based on the standard gettext package, and all the necessary tools are included in Scratchbox. For applications, localization requires a couple of files in the po/ directory. The following files will be used for localization:

  • Makefile.am
  • en_GB.po
    • contains translated text for target en_GB
  • fi_FI.po
    • contains translated text for target fi_FI
  • POTFILES.in
    • contains the list of source code files that will be localized

[edit] Localizing Application

To localize an application, l10n needs to be set up before gtk_init() by including the following headers:

maemopad/src/main.c

#include <locale.h>
#include <glib/gi18n.h>

To initialize the locale functions, the following lines need to be added:

maemopad/src/main.c

setlocale(LC_ALL, "");
bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
textdomain(GETTEXT_PACKAGE);

The most important of these are GETTEXT_PACKAGE and localedir, which come from configure.ac:

maemopad/configure.ac


GeSHi Error: GeSHi could not find the language autoconf (using path /usr/share/php-geshi/geshi/) (code 2)

You need to specify a language like this: <source lang="html4strict">...</source>

Supported languages for syntax highlighting:

abap, actionscript, actionscript3, ada, apache, applescript, apt_sources, asm, asp, autoit, avisynth, bash, basic4gl, bf, bibtex, blitzbasic, bnf, boo, c, c_mac, caddcl, cadlisp, cfdg, cfm, cil, cmake, cobol, cpp, cpp-qt, csharp, css, d, dcs, delphi, diff, div, dos, dot, eiffel, email, erlang, fo, fortran, freebasic, genero, gettext, glsl, gml, gnuplot, groovy, haskell, hq9plus, html4strict, idl, ini, inno, intercal, io, java, java5, javascript, kixtart, klonec, klonecpp, latex, lisp, locobasic, lolcode, lotusformulas, lotusscript, lscript, lsl2, lua, m68k, make, matlab, mirc, modula3, mpasm, mxml, mysql, nsis, oberon2, objc, ocaml, ocaml-brief, oobas, oracle11, oracle8, pascal, per, perl, php, php-brief, pic16, pixelbender, plsql, povray, powershell, progress, prolog, properties, providex, python, qbasic, rails, rebol, reg, robots, ruby, sas, scala, scheme, scilab, sdlbasic, smalltalk, smarty, sql, tcl, teraterm, text, thinbasic, tsql, typoscript, vb, vbnet, verilog, vhdl, vim, visualfoxpro, visualprolog, whitespace, whois, winbatch, xml, xorg_conf, xpp, z80

Of these, only GETTEXT_PACKAGE needs special attention, as it is the l10n domain that is to be used, and ALL_LINGUAS lists the available translations.

[edit] Easing Extraction of Strings

In the source code, there are multiple strings that eventually get shown in the user interface. For example:

maemopad_window_show_error ("maemopad_open_failed", self);

In order to make the strings localizable, they need to be wrapped in gettext("String") calls. In practice, writing gettext() for every string is tedious. The common practice is to set the following #define which is already done in included gi18n.h:

#define _(String) gettext (String)

Thus, the i18n version of the example would be:

maemopad/src/main.c

maemopad_window_show_error (_("maemopad_open_failed"), self);

[edit] Creating Translation Files

Creating *.po files is quite straightforward. Maemopad has two localization files, en_GB.po and fi_FI.po. Creating the Finnish translation is explained next. Localization .po files are filled with simple structures, defining the localization id and the actual text string, e.g.

#: src/maemopad-window.c:573 src/maemopad-window.c:580
msgid "maemopad_open_failed"
msgstr "Open failed!"

"msgid" defines the original string (key) used in code, and "msgstr" defines the translated string for localization.

First, a template file is created with all strings from sources for translation. GNU xgettext command is used to extract the strings from sources:

[sbox-FREMANTLE_X86: ~/maemopad] > xgettext -f po/POTFILES.in -C -a -o po/template.po

Option "-f po/POTFILES.in" uses POTFILES.in to get the files to be localized, "-C" is for C-code type of strings, "-a" is for ensuring that all the strings are received from sources, and "-o template.po" defines the output filename.

This may output some warnings. Usually they are not serious, but it is better to check them anyway.

If the translation in question is into Finnish, the edited po/template.po needs to be copied to po/fi_FI.po , and fi_FI.po needs to be added to ALL_LINGUAS in configure.ac.

Now po/fi_FI.po will include lines such as the following:

#: src/maemopad-window.c:253
msgid "maemopad_save_changes_made"
msgstr "Save changes?"

All msgstrings should be translated into the desired language:

#: src/maemopad-window.c:253
msgid "maemopad_save_changes_made"
msgstr "Tallenna muutokset?"

Autotools should now automatically convert the .po file to .mo file during the build process, and install it to the correct location.

To do it manually:

[sbox-FREMANTLE_X86: ~/maemopad] > msgfmt po/fi_FI.po -o debian/maemopad/usr/share/locale/fi_FI/LC_MESSAGES/maemopad.mo

Where debian/maemopad/usr/share/locale/fi_FI/LC_MESSAGES/ is the directory where the software should be installed to.

[edit] Testing

Inside scratchbox, the translated application should be tested by setting LANGUAGE environment variable to contain the newly created locale (in this example case for Finnish translation, fi_FI):

[sbox-FREMANTLE_X86: ~] > LANGUAGE="fi_FI" run-standalone.sh maemopad

On the target device, a wrapper script is needed to accomplish this, if the device does not have a locale for the locale identifier used. The script can simply consist of:

#!/bin/sh
LANGUAGE="fi_FI" /usr/bin/maemopad

The example above assumes that the installation package installs the executable into /usr/bin. This script needs then to be configured to be run in the application's .desktop file, instead of the actual executable.