Game localization is the process whereby a product is modified to be suitable for other distinct markets through the process of translation and cultural adaptation of its content. Localization includes (but is not limited to):
- text translation
- font management
- user-interface considerations such as reading order (right-to-left, left-to-right, or alternating? up or down?), currency symbols, date/time formatting, voice acting content, etc.
- culture-specific changes such as changing the color of blood from red to another color and removing bodies/body parts immediately following death for countries that have prohibitions on graphic depictions of blood/violence.
Going hand-in-hand with localization is the concept of internationalization or globalization which is the process whereby a product is designed to be easy to localize by hiding or removing cultural or language specific content through planning and game design.
HeroEngine's Localization system provides a fully internationalized interface for management of translated text strings. The Localization system has two operating modes:
- In DEV mode (while the game is under development), multiple translations of game-specific text phrases are prepared and stored in the repository. Phrases are identified by numeric string IDs.
- In RT mode (when the game is being played), phrases are retrieved from the repository by string ID. You can switch to a different language simply by changing the current locale.
Be aware that the Localization system provides only a small part of what is necessary for the proper internationalization of your game... as you too are responsible for developing your game's systems to support internationalization.
On this page and the pages it references you will find an overview of HeroEngine's Localization system as well as a variety of topics addressing some of the issues. This documentation is not intended to explain all of the issues in the problem space of internationalization and localization.
What Problem(s) Does HeroEngine Localization Solve?
- Provides a simple method for switching text strings into different languages at the time that a game is played.
What Problem(s) Does HeroEngine Localization Not Solve?
- Does not actually translate the text, that is up to you, an in-house, or third-party translation service.
- Does not automatically load the fonts necessary for correct display of text for a particular language. However, HeroEngine does provide the capability to store fonts in the repository and load them using the LoadFontResource() external function.
- Does not substitute non-text content for alternate market versions. In other words, the localization system does not change blood from red to green nor does it handle swapping voice content for alternate voice content
- Does not make your user interface magically work for alternate markets. For example, implementation of right-to-left, alternating, and bottom-up reading orders, special currency symbols, culture-specific date formats, etc. are left to the game developer.
For background in the issues of localization, we recommend books such as: Game Localization Handbook
“Globalization Step by Step” provides a good overview of the factors involved in internationalization.
The DEV-mode Localization system is highly customizable, and there are many different ways in which game developers can use it. However, the Localization Table Editor will meet the needs of most game developers.
See the Example below and/or the Localization Table Editor page for further instructions.
See the Example below and/or the $LOCALIZE system node page for further instructions.
Recommended Usage Example
Let's say that we have a quest game whose GUI interface includes a window that displays the name and description of a quest ...
... and that we'd like to localize this window so that we can easily change the language at runtime:
We can accomplish this with the following steps:
- Use theLocalization Table Editor to create a localized string database containing the desired translations.
- Use HeroBlade to create the quest window. Include GUILabel controls for the quest name and description.
- Write the HSL for the quest window, using the $LOCALIZE system node to retrieve the quest name and description in the desired language.
The next two sections provide detailed step-by-step instructions for this example (except for the details of creating the quest window: see the "GUI Window Tutorial" for that).
Create Localized String Database with Localization Table Editor
To open the Localization Table Editor in HeroBlade:
- Click on the Viewport window to ensure that it is selected.
- Hit the F5 key to bring up the Utilities Interface window.
- Select the Tools tab, then click on Localization Table Editor.
"en-US" indicates English as spoken in the US.
Your first step will be to add the locales into which you desire to translate your game. Locales are added using the /HELOCALIZATION chat command.
For example, to enable Spanish translations, type "/HELOCALIZATION addlocale es" in HeroBlade's chat window.
When you have added all your locales, enter your strings:
- Enter the US English translation into the "Add New String..." edit box. US English ("en-US") is used because it is the default base locale of the default localization configuration. To switch to another default base locale, modify the locale name returned by the $LOCALIZATION system node's _LOC_GetDefaultBaseLocale() method.
- Enter translations for the other locales in the String Value boxes of their rows.
- If desired, enter a description of the string in the base locale's Context box. Because all translations of a string share the same context, it can be edited only in the base locale's row.
You can also edit an existing string in its String Value box, or an existing string context in its Context box.
The examples use the baseline Localization Table Editor. Note that Korean (locale "ko") translations are displayed as c characters, but Russian characters are displayed in the Cyrillic alphabet. The reason for this is that there were no freely distributable pan-lingual fonts at the time of Localization Table Editor development. Refer to the Font Licensing section for further details.
Write RT-Mode HSL
Finally, we can use the $LOCALIZE system node to query the string tables at runtime and customize the GUI for a specific language:
//$QUEST system node method constructQuestWindow(questSpec as NodeRef of class SomeGameQuestSpecClass, locale as String) as noderef of class SomeGameQuestWindowClass questWindow as noderef of class SomeGameQuestWindowClass = CreateNodeFromPrototype("SomeGameQuestWindowClass") questWindow.build = true questWindow.initializeQuestWindow(questSpec, POSITION_DEFAULT, PARENT_NONE) questWindow.updateQuestWindowGUI(locale) // "locale" is the locale name of the language in which the quest window will be displayed .
//SomeGameQuestWindowClass method initializeQuestWindow(questSpec as NodeRef of class SomeGameQuestSpecClass, position as enum SomeGameWindowPositionEnum, parent as noderef of class SomeGameWindowClass) me.setQuestWindowQuestSpec(questSpec) me.setQuestWindowPosition(position) me.setQuestWindowParent(parent) . method updateQuestWindowGUI(locale as String) questSpec as NodeRef of class SomeGameQuestSpecClass = me.getMyQuestWindowQuestSpec() localizeRequestID as ID // set the language in which we want the localized string to be retrieved if (questSpec.LOC_SetCurrentLocale(locale) != true) // This is a fatal error. The most likely causes are that "locale" is not a valid locale name, or that "locale" is not in your localized string database. // The LOC_OnRTError() callback will be invoked, with a detailed error message. . //request quest name localized string questNameStringID as string = questSpec.getQuestNameStringID() // this is the string ID assigned to the quest name by the Localization Table Editor. You must initialize it in the quest spec. localizeRequestID = $LOCALIZE._GetLocalizedStringValueAsync(me, questNameStringID) // start asynchronous retrieval of localized string me.questWindowAddPendingLocalizedStringUpdateRequest(localizeRequestID, me.getQuestWindowNameLabel()) // link the asynchronous request ID to the GUI control which will be updated by the string and save it //request quest description localized string questDescriptionStringID as string = questSpec.getQuestDescriptionStringID() localizeRequestID = $LOCALIZE._GetLocalizedStringValueAsync(me, questSpec.getQuestDescriptionStringID()) me.questWindowAddPendingLocalizedStringUpdateRequest(localizeRequestID, me.getQuestWindowDescriptionLabel()) . method _GotLocalizedStringValueAsync( request_id as ID, localized_string_number as Integer, localized_string_value as String ) //If the string we've just received fulfills the request with ID 'request_id', process it and remove it from our pending list if me.questWindowIsWaitingForLocalizedString(request_id) me.questWindowProcessPendingLocalizedStringUpdateRequest(request_id, localized_string_value) me.questWindowRemovePendingLocalizedStringUpdateRequest(request_id) . . method questWindowProcessPendingLocalizedStringUpdateRequest(request_id as ID, localized_string_value as String) //Get the label we want to update, then update its text value labelToUpdate as NodeRef of class _GUILabel = me.questWindowGetLabelForLocalizedStringRequest(request_id) labelToUpdate.text = localized_string_value .Now, in order to create a quest window whose text will match the locality of the player, we need only to call $QUEST.constructQuestWindow(...) from an HSL script with the appropriate quest spec and locale.
When a HeroEngine game is played, the fonts available for displaying localized strings include:
- fonts accessible to the game platform OS, and
- fonts stored in the repository.
Some web resources for finding fonts include:
Numerous freeware fonts are available on the Web, but (as of November 2012), there are no freeware pan-lingual fonts.
IF Studios recommends the Localization Table Editor for most game developers. However, it does make some default assumptions that might not be suitable for all developers, including:
- By default, the Localization Table Editor always uses the same configuration file repository pathnames. Because every game should have its own configuration files, this is not well suited for development in a multi-game environment.
- The Localization Table Editor does not directly support import of third-party localization files.
- By default, the Localization Table Editor assigns string IDs starting with 1, and incrementing every time a new string ID is entered. It does not explicitly allow users to group strings into similar categories.
The low-level Localization system concept of operations is:
- DEV-mode Localization external functions are used to either create a new localized string database or to load an existiing localized string database from the repository.
- DEV-mode Localization external functions are used to edit the localized string database. This includes the creation of new localized strings and the editing and deletion of existing localized strings.
- When the DEV-mode localized string database is ready for in-game use, the DEV-mode Localization runtime database generation external functions are used to generate an RT-mode localized string database and upload it to the repository. This is the only write access to the RT-mode localized string database which is provided by the Localization external functions.
- When the game is played, the RT-mode Localization external functions are used to load an RT-mode localized string database, select a language in which localized strings are to be retrieved, and retrieve localized strings.
Import of Localization Files
Translation String Table
TABLE (tab) ID (tab) $BASE_LOCALE (tab) CONTEXT (tab) $TRANSLATOR_LOCALE $TABLE_NAME (tab) $STRING_ID (tab) $STRING[base] (tab) $STRING[context] (tab) $STRING[translator_locale] $TABLE_NAME (tab) $STRING_ID (tab) $STRING[base] (tab) $STRING[context] (tab) $STRING[translator_locale] $TABLE_NAME (tab) $STRING_ID (tab) $STRING[base] (tab) $STRING[context] (tab) $STRING[translator_locale] $TABLE_NAME (tab) $STRING_ID (tab) $STRING[base] (tab) $STRING[context] (tab) $STRING[translator_locale] $TABLE_NAME (tab) $STRING_ID (tab) $STRING[base] (tab) $STRING[context] (tab) $STRING[translator_locale]
Which would look something like this with real data for a japanese translation of the table:
TABLE (tab) ID (tab) en_US (tab) CONTEXT (tab) ja_JP GameTable1 (tab) 456 (tab) Hello, World! (tab) A generic programmer greeting used in code samples. (tab) こんにちは、世界！ GameTable1 (tab) 457 (tab) Goodbye, World! (tab) An orthogonal phrase to the classic "Hello, World!" (tab) さようなら、世界！
Asynchronous RT-Mode Localization
Synchronous RT-Mode Localization
When a game is being played, the base locale specifies the fallback language in which localized strings are to be retrieved by the RT-mode Localization interface should a translation not be available in the current locale.
When a game is being played, the current locale specifies the preferred language in which localized strings are to be retrieved by the RT-mode Localization interface.
"DEV mode" refers to operations during game development. The HeroEngine DEV-mode Localization system provides a suite of tools for the import, creation, and editing of localized string databases for use by RT-mode Localization.
Locales identify the target culture/language. HeroEngine identifies locales using the same locale names as the host operating system. Locales in table 1 include English as spoken in the US ("en-US"), French ("fr"), Spanish ("es"), Russian ("ru"), Japanese ("ja-JP"), Korean ("ko-KR"), and traditional Chinese ("zh-CN").
A translation uniquely identified by the combination of a string ID and a locale. For example, in table 1 the localized string "안녕히 가세요" translates the phrase "Goodbye" (string ID 100002) into Korean (locale "ko-KR").
A font that displays text in all of the world's major languages (for example, Arial Unicode).
"RT mode" refers to operations while a game is being played (i.e., during the game's runtime). The HeroEngine RT-mode Localization system provides an external function library for efficient retrieval of localized strings from the repository files created by DEV-mode Localization.
A 64 bit signed integer that uniquely identifies a particular phrase. In Table 1, string ID 100001 identifies the phrase "Hello" and string ID 100001 identifies the phrase "Goodbye". Zero is an invalid string ID and negative string IDs are reserved for HeroEngine's use.
Localization Data/File Hierarchy
In both DEV and RT modes, localization data is organized into configurations, universes, and string tables.
- Configurations map one-to-one to games. Every game should have one and only one configuration, and all the localized strings used by that game should be stored in the universes and string tables belonging to that configuration.
- String tables are localized string containers and universes are string table containers. They are provided primarily to support reuse of localized strings in different games. For example, if you have several games that use the same weapon names, you could put all the weapon names in one universe, then reuse the universe. At your discretion, you could either use the same universe repository file in both games (making it easy to propagate weapon name changes), or you could create a new copy of the universe file.
Configurations, universes, and DEV-mode string tables all map one-to-one to localization files in the repository. However, RT-mode string tables correspond to multiple repository files.
- DEV-mode files are by convention stored in the "/Localization/Development" root folder.
- RT-mode files are by convention stored in the "/Localization/Runtime" root folder.
In both DEV and RT modes, the Localization external functions enforce a rule that one and only one configuration file can be loaded at any time (however, DEV-mode and RT-mode configurations are not the same, so one DEV-mode configuration and one RT-mode configuration can coexist.).
Both DEV-mode and RT-mode external functions also enforce "hierarchical access": universes cannot be loaded until a configuration that references them has been loaded, and string tables cannot be loaded until a universe that references them has been loaded. Universes and string tables are referenced by random unsigned 64-bit integer "file keys" assigned by the external functions. Note that file keys are of HSL type "ID".
Configurations are the highest-level localization data item, and contain an indefinite number of universes. All of the localized strings for a game should be stored in one and only one configuration.
- Configurations map one-to-one to configuration files in the repository.
- Localization system external functions identify configurations by their repository pathnames.
- It is not strictly required, but it is strongly recommended that all of the localized strings used by a game be in the same configuration.
- Within a configuration, universe string ID ranges may not overlap.
- Configurations contain a master locale list. No universe can provide translations for a locale which is not in its parent configuration's locale list.
- By convention, negative string IDs are members of the HeroEngine universe, and should not be modified by game developers.
- Universes map one-to-one to universe files in the repository.
- Localization system external functions identify universes by their file keys.
- Within a universe, string table string ID ranges may not overlap.
- Universe also contain a locale list, and no string table can provide translations for a locale which is not in its parent universe's locale list.
String tables are the lowest-level localization data item, and contain an indefinite number of localized strings.
- DEV-mode string tables map one-to-one to DEV-mode string table files, which contain all of the localized strings within the string table's range for each of the parent universe's locales.
- RT-mode string tables map many-to-one to RT-mode string table files, because RT-mode string table files contain all of the localized strings within the string table's range for just one of the parent universe's locales. This is done as a runtime memory conservation measure. Runtime string table files are loaded only for the base locale and current locale.
- Localization system external functions identify string tables by their file keys. This is true even for RT-mode string tables, when the file key actually maps to an indefinite number of RT-mode string table files.
How to use HeroBlade's Localization Table Editor to create translation databases.
For information on the HSL DEV-mode localization system node.
For information on the HSL RT-mode localization system node.
Descriptions of the Localization external functions.
Descriptions of the Localization repository files.