views:

127

answers:

3

I would like to know what is the right way to handle internationalization for statements with runtime data added to it. For example 1) Your input "xyz" is excellent! 2) You were "4 years" old when you switched from "Barney and Freinds" to "Spongebob" shows.

The double quoted values are user data obtained or calculated at run time. My platforms are primarily Java/Android. A right solution for Western languages are preferred over weaker universal one.

+8  A: 

Java

To reteive localized text (messages), use the java.util.ResourceBundle API. To format messages, use java.text.MessageFormat API.

Basically, first create a properties file like so:

key1 = Your input {0} is excellent!
key2 = You were {0} old when you switched from {1} to {2} shows.

The {n} things are placeholders for arguments as you can pass in by MessageFormat#format().

Then load it like so:

ResourceBundle bundle = ResourceBundle.getBundle("filename", Locale.ENGLISH);

Then to get the messages by key, do:

String key1 = bundle.getString("key1");
String key2 = bundle.getString("key2");

Then to format it, do:

String formattedKey1 = MessageFormat.format(key1, "xyz");
String formattedKey2 = MessageFormat.format(key2, "4 years", "Barney and Friends", "Spongebob");

See also:


Android

With regards to Android, the process is easier. You just have to put all those String messages in the res/values/strings.xml file. Then, you can create a version of that file in different languages, and place the file in a values folder that contains the language code. For instance, if you want to add Spanish support, you just have to create a folder called res/values-es/ and put the Spanish version of your strings.xml there. Android will automatically decide which file to use depending on the configuration of the handset.

See also:

BalusC
To be clear: you would provide the string `Your input '{0}' is excellent"` to your translators, and pass the translation (stored in the `ResourceBundle` to `MessageFormat`, which will then replace `{0}` with the content you provide.
Jan Fabry
The suggested way to do this on android is to do what BalusC suggested and put the strings into res/values-xx/strings.xml files. But instead of using {0}, you can use the version of Context.getString() that takes a format string. (See http://d.android.com/reference/android/content/Context.html )It takes the standard java Formatter-style strings. So your value would look like "Your input '%1$s' is excellent"
joeo
+3  A: 

One non-technical consideration. Embedding free data inside English phrases isn't going to look very smooth in many cultures (including Western ones), where you need grammatical agreement on e.g. number, gender or case. A more telegraphic style usually helps (e.g. Excellent input: "xyz") -- then at least everybody gets the same level of clunkiness!

Pontus Gagge
This is a non issue if you use parameterized placeholders. You can position it grammatically everywhere you want.
BalusC
I don't think you see what I'm getting at. English grammar is simple compared to most Western (and other) languages. When writing string templates in English, you **may** remember to provide alternates for singulars and plurals ("{0} is ..." vs "{0} are ..."), but you're still not going to be able to meet constraints on what word forms to use for different genders or cases among nouns, **for starters**. This is something to keep in mind when writing the English original texts: as telegraphically as possible, in order to avoid having the translations sound **too** deranged.
Pontus Gagge
BTW, @BalusC, your answer is quite correct, and the best we realistically can do. I merely suggest that by **also** working on the English phrasing, the application can make a slightly more professional impression in its localized variants.
Pontus Gagge
I see what you mean. That's indeed something to take carefully into account.
BalusC
@Pontus: An excellent point. Consider "I love my {pet}" and "My {pet} loves me". In English if I substitute "dog" for "{pet}", both sentences work fine. But if, say, I try to do this in Latin and substitute "canis" into "Amo {pet} mei" and "{pet} meum amat" ... well "canis" is the subject form, so the second sentence will work fine. But in the first sentence we get "Amo canis mei". "canis" is still the subject form, so this would would translate to something like "I, a dog, love". We would really want to change it to the object form, "canem". That's not easy to do with a template.
Jay
A: 

I think one will probably have to define one's format string to include a "1-of-N" feature, preferably defined so as to make common cases easy (e.g. plurals). For example, define {0#string1/string2/string3} to output string1 if parameter 0 is zero or less, string2 if it's precisely 1, and string3 if it's greater than 1}. Then one could say "You have {0} {0#knives/knife/knives} in the drawer."

supercat
At least, for Western European languages, I don't think dualis is required... (comes between singular and plural, for two objects!).
Pontus Gagge