Version 5 (modified by Adrián Chaves, 10 years ago) ( diff )

--

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 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 get an instance of the singleton including the i18n/L10n.h header file and calling L10n::instance().

Initialization

When you call the singleton for the first time, its initialization:

  1. 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 L10n::instance().getSupportedLocaleCodes(). This method returns an array of strings with the locale codes found here. L10n::instance().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).

  1. 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 L10n::instance().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.

Localization Functions

The L10n singleton provides many localization functions that you can use from C++, some of which are also published to be used in JavaScript.

Translation functions (Internationalization explains how to use them):

std::string translate(const std::string& sourceString);
std::string translateWithContext(const std::string& context, const std::string& sourceString);
std::string translatePlural(const std::string& singularSourceString, const std::string& pluralSourceString, int number);
std::string translatePluralWithContext(const std::string& context, const std::string& singularSourceString, const std::string& pluralSourceString, int number);
std::string translateLines(const std::string& sourceString);

Date and time functions:

// parseDateTime() and localizeDateTime() are used to convert dates from strings
// into icu::UDate and the other way around. These are used in
// “gui/scripting/ScriptFunctions.cpp”.
UDate parseDateTime(const std::string& dateTimeString, const std::string& dateTimeFormat, const Locale& locale);
std::string localizeDateTime(const UDate& dateTime, DateTimeType type, DateFormat::EStyle style);

// Converts a string from UNIX timestamp (in milliseconds, not seconds) into a
// string with the specified format. See the ‘Internationalization’ page in the
// documentation for more information.
std::string formatMillisecondsIntoDateString(int milliseconds, const std::string& formatString);

Number functions:

// Returns the specified floating-point number as a string using the current
// locale.
std::string formatDecimalNumberIntoString(double number);

Path functions:

// Returns the localized version of the specified path if there is one.
// Otherwise, it returns sourcePath.
// This is used for image localization (see below).
VfsPath localizePath(VfsPath sourcePath);

GUI

Text

TODO:

  • source/gui/CGUI.cpp

Images

TODO:

  • source/gui/GUIRenderer.cpp

Functions Published for JavaScript

TODO:

  • source/gui/scripting/ScriptFunctions.cpp

Third-Party Libraries

TODO:

  • tinygettext (third_party/tinygettext)
  • ICU

Message Extraction System

TODO:

  • source/tools/i18n/updateTemplates.py
  • <mod>/l10n/messages.json
  • source/tools/i18n/potter/

Long Strings Locale

TODO:

  • source/tools/i18n/generateLongStringTranslations.py

Transifex Integration

TODO:

  • .tx/config
  • source/tools/i18n/pullTranslations.py
  • source/tools/i18n/tx
  • source/tools/i18n/txclib/

JavaScript

The following sections describe some implementation details that are specific to the JavaScript side.

JavaScript Translation Cache System

TODO:

  • l10n.js (only cache stuff)

Object Translation Helper Function

TODO:

  • l10n.js (translateObjectKeys)

String Formatting Function

TODO:

  • sprintf.js

Public Mod

Language Selection Menu

TODO:

  • gui/page_locale.xml
  • gui/locale/*

TODO:

File Tree

binaries/data/mods/public/

globalscripts/

l10n.js

Implements the following global internationalization functions:

translate(message);
translatePlural(singularMessage, pluralMessage, number);
translateWithContext(context, message);
translatePluralWithContext(context, singularMessage, pluralMessage, number);
translateObjectKeys(object, keys);

The first four functions are simply wrappers for the engine internationalization functions (such as Engine.translate). These global functions use caching to reduce the number of calls to the engine functions, because calls to engine functions require string conversions that are far from cheap.

translateObjectKeys is a helper function that can translate specific properties (keys array) of a JavaScript object.

sprintf.js

Implements the sprintf() function, used for string formatting.

gui/

page_locale.xml

Represents the dialog box that you open when you select Options → Language in the main menu. The actual content of the dialog box is defined in gui/locale/.

Note: See TracWiki for help on using the wiki.