Hi, what should be the best approach to make strings for different languages? I have this problem, I am trying to display strings such as 'month', 'months', 'year', 'years'. Currently I am working on 3 languages I know: spanish, english and polish. For english and spanish this is straight forward. But for instance, in polish 'years' can become 'lata' (after numbers 2 - 4) or 'lat' (after numbers from 5). I was thinking on adding an extra string for this, and making it empty in the other languages. However this made me think about the other languages I don't know, which might have even more differences. Which should be the best approach in this case, if I am considering adding more languages in the future?
Sounds like you want a ChoiceFormat
, or at least using one through a MessageFormat
:
public static void main(String... args) {
// CAVEAT: I speak neither spanish nor polish :)
String[] formats = {
"{0,number} {0,choice,0#years|1#year|1<years}", // english
"{0,number} {0,choice,0#años|1#año|1<años}", // spanish
"{0,number} {0,choice,1#[fewer than 2]|2#lata|4<lat}", // polish
"{0,number} år", // swedish - singular and plural forms look the same!
};
int[] years = {0, 1, 2, 3, 4, 5, 6};
for (int year : years) {
for (String format : formats) {
System.out.println(MessageFormat.format(format, year));
}
System.out.println();
}
}
In your program, you would of course get the format
string from your string file.
Note that I don't have any android specific experience... but I usually opt for having separate view files for each language i'm going to support, this allows for broader localisation than language alone, you can now also have slightly altered layouts if you know text in some other language can require for example wider buttons, or even different images.
There's a built-in "plurals" support which is not well documented.
Mentioned here and you can see it in the Browser sources.
Thanks to the answers I have got, I am writing 2 Android based solutions. The first one I used was having plurals. At first glance checking the Plurals docs/examples, you could think that there is a quantity="few" (for 2-4 plurals) which checking at the sources only works for locale 'cs'. For the rest of locales, only "one" and "other" are working. So in your strings.xml files:
<plurals name ="years">
<item quantity="one">1 year</item>
<item quantity="other"><xliff:g id="number">%d</xliff:g> years</item>
</plurals>
So for polish I would have:
<plurals name ="years">
<item quantity="one">1 rok</item>
<item quantity="other"><xliff:g id="number">%d</xliff:g> lat</item>
</plurals>
Then I would have on my code:
int n = getYears(...);
if (Locale.getDefault().getLanguage().equalsIgnoreCase("pl") && n >= 2 && n <= 4) {
return getString(R.string.years_pl, n);
} else {
return getResources().getQuantityString(R.plurals.years, n, n);
}
And in my strings.xml file for the polish locale I would add the missing string:
<string name="years_pl"><xliff:g id="number">%d</xliff:g> lata</string>
My second solution has the plurals element for english, spanish, and other languages that don't have too many plural changes. Then for the rest of the languages that have this kind of changes I would use ChoiceFormat. So in my code:
...
private static final int LANG_PL = 0;
// add more languages here if needed
...
String formats[] = {
"{0,number} {0,choice,1#" + getString(R.string.year_1) + "|2#" + getString(R.string.years_2_4) + "|4<" + getString(R.string.years_lots) +"}", // polish
// more to come
};
...
// Here I would add more for certain languages
if (Locale.getDefault().getLanguage().equalsIgnoreCase("pl")) {
return MessageFormat.format(formats[LANG_PL], n);
} else {
return getResources().getQuantityString(R.plurals.years, n, n);
}
I don't know if these ways are the best way, but for the moment, or until Google makes something better, this works for me.