Table of Contents
- Message Extraction
- Language Selection Menu
This topic explains the implementation details of internationalization and localization in the game. For documentation on how to use those features to either internationalize new game content or localize the game, see Internationalization and Localization.
The internationalization and localization implementation fo the game relies on two libraries:
- ICU is a common internationalization library that provides structures to handle locales, easily obtain the default system locale, handle date and number representations on each locale, or provide the localized names of locales to show them in a language combo box.
- tinygettext is a small library that we forked. This library provides the structures and methods that we use to load PO files in memory.
The Localization Singleton
The heart of the internationalization and localization implementation is at source/i18n/L10n.cpp.
The L10n class implemented in this file works as a singleton, and provides many functions that can be used from anywhere in the engine C++ codebase. You can access an instance of the singleton including the i18n/L10n.h header file and using g_L10n.
The singleton is initialized on engine startup, where it performs the following tasks:
- Creates a list of available locales based on the filenames of the PO files in the l10n virtual folder.
The l10n virtual folder holds the combination of the files in the binaries/data/l10n folder, which contains the engine PO files, and the l10n folder of each enabled mod. See source/ps/GameSetup/GameSetup.cpp .
You can obtain the list of available locales calculated here at any later time calling g_L10n.GetSupportedLocaleCodes() . This method returns an array of strings with the locale codes found here. g_L10n.GetSupportedLocaleDisplayNames() returns a similar vector, this one with display names instead of codes, where the name of each locale is in the language of the locale itself. The special locale "Long Strings", of code "long", is only returned if yours is a development copy (if the config/dev.cfg file exists in the virtual filesystem).
- Determines the current locale, first looking at the configuration value locale and, if undefined, looking at the system locale using icu::Locale::getDefault().
Once the locale is defined, it loads the dictionary of the target locale if it is available. The dictionary is a structure from the tinygettext library that holds the list of English strings linked to translated strings (including context and plural considerations).
You can change the locale later using g_L10n.SetLocale() . You can pass this method either a locale code as a string, such as "en_GB", or an instance of icu::Locale . The method reloads the dictionary if required.
The source/gui/CGUI.cpp and source/gui/COList.cpp files implement the parsing of the GUI XML localization elements:
- attribute (along with keep and translate)
See Internationalizing GUI Files to see how to use them.
The source/gui/GUIRenderer.cpp file, responsible for rendering images on the GUI, is configured to use g_L10n.LocalizePath(), which loads localized versions of images if available.
See Localizing Images for more information.
The source/i18n/scripting/JSI_L10n.cpp file publishes some of the functions that the L10n singleton offers, as well as some custom internationalization functions based on the L10n functionality.
translate(message); translatePlural(singularMessage, pluralMessage, number); translateWithContext(context, message); translatePluralWithContext(context, singularMessage, pluralMessage, number);
Object Translation Helper Function
The keys parameter is an array of strings with the names of the object properties to translate.
String Formatting Function
Message extractions is the process of parsing the source files searching for strings that need to be translated, and generating a translation template file (POT) from them that translators can use.
The script responsible for generating POT files is source/tools/i18n/updateTemplates.py. This scripts goes through the l10n folders of the sources (binaries/data/l10n and l10n in mod folders) and it reads the messages.json file there, which defines where to extract the strings from, and how to extract them.
The format of the messages.json file is a custom format. See Message Extraction for details.
The resulting POT files are generated on the same l10n folder that contains the messages.json file that define their configuration.
updateTemplates.py relies on the Python library pology.
Currently, the translation of the game happens in Transifex, at https://www.transifex.com/projects/p/0ad/
The l10n folders of the game sources contain a hidden folder, .tx, which contains a config file. This config file determines where in Transifex are the PO files that must be downloaded to that specific l10n folder.
To download the translation files from Transifex, you can call source/tools/i18n/pullTranslations.py, which uses those .tx/config files and the Transifex client library to automatically download the latest PO files into their respective folders. You need to install the Transifex client library to
To use this script you need a Transifex account and have the Transifex client library installed.
Long Strings Locale
The source/tools/i18n/generateLongStringTranslations.py is a special script that generates a PO file for an artificial language with code "long". This PO file consists of the longest strings (as in number of characters) of every available language for each message.
The generateLongStringTranslations.py script parses the PO files in the l10n folders of the sources, and generates the new PO file in each of those l10n folders as well. Remember to download the real PO files before you call the script, so that the script can read the translations from them in order to find the longest strings.
Language Selection Menu
The dialog box that you open when you select Options → Language in the main menu is defined in the following files: