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:
- 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.
- 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.
- 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!)