Internationalization (i18n) in Flash games? Is there an easy way?

I want to internationalize some texts in a flash (not flex) game I'm working on and I can not find an easy way to achieve that... I have found some libraries and other solutions, but I expected something a lot easier (it is really easy with other technologies).

Do you have experience in this? How do you do it?

• "it is really easy with other technologies" - which other ones have you used? – Kylotan Oct 1 '10 at 11:13
• For instance: PHP, .NET, Java... But, ok, if I have to think only of game development, it is not so easy. – miguelSantirso Oct 1 '10 at 13:17

I recently developed a Flash Game that I translated to German and English. You can have a look at it here: http://www.bioaschi.ch/?lang=en#/game. You can change the language on the fly in the settings menu.

To translate the game, I used the following approach: I have a custom written Config class that is basically just a registry of key => value pairs. The config class can read from an XML file and also dispatches events when a value changes.

For the game I created 2 different config files. One is the main config, and then one file containing the translations (called lang). Them main config contains a key that specifies the language, eg. lang = en. In game I listen for change events on that key. Whenever that happens, I read/apply the values from the appropriate language.

Here's a small snippet of code that shows how the language is switched in game:

Somewhere in the "Settings" panel code:

Config.getConfig('main').setValue('lang', 'de'); // or 'en'


Then anywhere else where text needs to be localized:

        // this is in the construtor or some init method
...
var cfg:Config = Config.getConfig('main');

updateText(cfg.getValue('lang', 'en') + '.');
}

private function updateText(langns:String) : void {
var langCfg:Config = Config.getConfig('lang');
this.title.htmlText = langCfg.getValue(langns + "credits.TITLE", "<title>");
this.text.htmlText = langCfg.getValue(langns + "credits.TEXT", "<text>");
_btnClose.label = langCfg.getValue(langns + 'highscore.CLOSE', 'X');
}

private function onConfigChange(evt:ConfigEvent) : void {
if(evt.key == 'lang'){
updateText(evt.value + ".");
}
}


You can have a look at the file that is being loaded by the game here: http://www.bioaschi.ch/game/language.xml

To substitute parts of the text with variables (eg. your score is %d transforms to your score is 10000), I suggest you use the excellent Polygonal Datastructures Library. It contains a AS3 implementation of Sprintf.

Instead of having all translations in one file, you could also easily have one single file per language.

For the sake of completeness, here are some code listings:

Wow, this kinda turned out to be a long post, I'm sorry. The approach I took is rather simplistic and doesn't cover the more complicated topics of internationalization, like date formats, number or currency formatting etc. For simple translations it works just fine though.

• This is a good answer, but I can not upvote because I am a new user :( I will accept your answer if there isn't anything better soon. – miguelSantirso Oct 1 '10 at 13:18

Coming from the C++ world, the general idea for changing languages on the fly is to have all language text in memory in a table somewhere, with each string (or sprite that contains text) assigned a numeric ID. All IDs are the same in different languages, plus a language offset. For example:

const LANG_EN:int = 0; const LANG_DE:int = 1000;

const STRING_HELLO_WORLD:int = 0;

var StringTable:array /* of string */; StringTable[STRING_HELLO_WORLD+LANG_EN] = "Hello, World!" StringTable[STRING_HELLO_WORLD+LANG_DE] = "Hallo, Veldt!"

This takes considerable setup time, granted, but it only has to be done once.

Then, in your code, you just reference the table using the string and current language offset: myObject.text = StringTable[STRING_HELLO_WORLD+currentLanguage];

• I've seen something similar on shipped games, except the data is usually read in from an Excel spreadsheet, one language per column. – Kylotan Oct 6 '10 at 10:31

Bind your components to a flash.utils.Dictionary object. A Dictionary is basically an associative array. If you swap one with another, and your bindings are in place, the views will change automatically. Use can place date formatting etc information there two. I also introduced an unpopular and unfriendly "numbered id" system. This was because when you truly explore internationalization/multilingual apps, you will find that some words English translate differently depending on context (in French or Spanish it is very common).