6
\$\begingroup\$

I'm writing a simple android game. I planned to store all levels in xml files that contain info about level, including a level_name field. The Level class would load an appropriate level by parsing the corresponding XML file and reading data into the Level's fields) when user selects it.

Everything seems fine, until I want the game to support multiple languages. With UI it is clear how to solve this problem since we have strings.xml file. But what about localizing level data stored in XML files?

I considered having multiple fields for a given piece of data in a level.xml file, with each containing a different translation. Another thought was storing only the ID of level and get related level name from strings.xml file.

However, neither of these seem very elegant. Is there a more better way of doing this?

\$\endgroup\$

2 Answers 2

9
\$\begingroup\$

When you put all languages in one file, no two translators can work with the same map at the same time, because there will be edit conflicts. You also have to train your translators how to edit your level files. XML might seem intuitive to a programmer, but to a non-technical person it isn't.

But when you use a string file for each language, all translators can work independent from each other. It will also be easier for you to check the completeness of each translation, because you only have to look into one file.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ The only advantage XML has over JSON is readability. And I'm pretty sure non-technical people could understand it. They're not idiots... \$\endgroup\$
    – jcora
    Jan 18, 2013 at 12:26
6
\$\begingroup\$

My preferred elegant solution is this:

The English text in any file (or whatever your base language might be) must be passed through a translation function before display.

The gist is that your string table(s) consist of the English version of the string followed by the localised version(s) of the string, and your translation function takes the english version of the string as a parameter, and returns the localised string to be drawn to the screen.

  • If the translation function finds a translated version of the requested string, it returns the translated version, and everything works normally.
  • If the translation function doesn't find a translated version of the requested string (and this is the elegant part of this system), it returns $$string$$. That is, it returns the requested string, surrounded by $$ on each side.

Calling the function might look something like this:

string translatedString = XLAT( rawString );

Ideally, I advise putting this code into your string drawing code, immediately before rendering, so that you can be certain that every string which makes it to the screen has been through the translation function exactly once.

Here are the benefits of this system:

  1. Your English-language developers can still easily read and use the non-translated strings during development, by simply ignoring the $$ characters. Additionally, all your level files do not require any special localisation: any strings placed in them which wind up being rendered to screen will automatically be translated through this system.
  2. Any non-translated strings are very obvious, due to the $$ characters surrounding them. It's easy to not notice untranslated strings if you don't do something like this.
  3. If a string is changed at all in your code or data, it automatically becomes an untranslated string again, even if it had already been translated. This means that it starts showing up as untranslated again when you run your program, and you don't wind up with old, no-longer-accurate translations peppering your game the way that you can in integer-keyed string tables where none of your programmers or testers actually speak the translated language.

Downside of this system:

  • By keying translated strings by the non-translated string, you can sometimes wind up with English strings that appear in more than one context, but need different translations in those different contexts ("OK" is a frequent culprit for this). In these cases, you wind up having to instead use unique "English" strings for the different situations, and translate that into proper English in the English translations.

(unrelated side note: A frequent novice mistake in localisation is to treat US English and UK English as the same language. Don't do that!)

\$\endgroup\$
5
  • \$\begingroup\$ "OK" is actually a bad example, cause this should be fine in most instances. "Close" would be far better as based on the context it could be "close the window", "the result has been close" or "he is close by". \$\endgroup\$
    – Mario
    Jan 18, 2013 at 11:44
  • \$\begingroup\$ "OK" was one from personal experience. But there are lots of potential examples. \$\endgroup\$ Jan 18, 2013 at 11:56
  • \$\begingroup\$ You seem to be addressing the code side but I thought the question was about the data side. \$\endgroup\$
    – Kylotan
    Jan 18, 2013 at 12:07
  • \$\begingroup\$ @Kylotan My explanation of the data side takes up the entirety of paragraph 3. The rest of the explanation of how to use the data, and why it's a good way to do it. Code will be involved in any full answer to this question. Translations don't happen magically just by creating data files -- something has to use those files! \$\endgroup\$ Jan 18, 2013 at 12:13
  • \$\begingroup\$ @TrevorPowell: but the OP is really asking about where the data is stored, ie. in which file or files. It sounds like he or she has already worked out how to look up a string and translate it. (In particular I think strings.xml is part of an Android specific localization system.) \$\endgroup\$
    – Kylotan
    Jan 18, 2013 at 12:42

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .