Marking strings for translation

String literals should be typed in the source code in English, but they should be surrounded by a call to the gettext() function. These strings will be extracted for translation and the translations may be used at runtime instead of the original English strings.

The GNU gettext package allows you to mark strings in source code, extract those strings for translation, and use the translated strings in your application.

However, Glib defines gettext() support macros which are shorter wrappers in an easy-to-use form. To use these macros, include <glibmm/i18n.h>, and then, for example, substitute:

display_message("Getting ready for i18n.");

with:

display_message(_("Getting ready for i18n."));

For reference, it is possible to generate a file which contains all strings which appear in your code, even if they are not marked for translation, together with file name and line number references. To generate such a file named my-strings, execute the following command, within the source code directory:

xgettext -a -o my-strings --omit-header *.cc *.h

Finally, to let your program use the translation for the current locale, add this code to the beginning of your main.cc file, to initialize gettext.

bindtextdomain(GETTEXT_PACKAGE, PROGRAMNAME_LOCALEDIR);
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
textdomain(GETTEXT_PACKAGE);

How gettext works

intltool / xgettext script extracts the strings and puts them in a mypackage.pot file. The translators of your application create their translations by first copying this .pot file to a localename.po file. A locale identifies a language and an encoding for that language, including date and numerical formats. Later, when the text in your source code has changed, the msmerge script is used to update the localename.po files from the regenerated .pot file.

At install time, the .po files are converted to a binary format (with the extension .mo) and placed in a system-wide directory for locale files, for example /usr/share/locale/.

When the application runs, the gettext library checks the system-wide directory to see if there is a .mo file for the user's locale environment (you can set the locale with, for instance, "export LANG=de_DE.UTF-8" from a bash console). Later, when the program reaches a gettext call, it looks for a translation of a particular string. If none is found, the original string is used.

Testing and adding translations

To convince yourself that you've done well, you may wish to add a translation for a new locale. In order to do that, go to the po subdirectory of your project and execute the following command:

intltool-update --pot

That will create a file named programname.pot. Now copy that file to languagecode.po, such as de.po or hu.po. Also add that language code to LINGUAS. The .po file contains a header and a list of English strings, with space for the translated strings to be entered. Make sure you set the encoding of the .po file (specified in the header, but also as content) to UTF-8.

[Note] Note

It's possible that certain strings will be marked as fuzzy in the .po file. These translations will not substitute the original string. To make them appear, simply remove the fuzzy tag.

Resources

More information about what lies behind the internationalization and localization process is presented and demonstrated in: