views:

255

answers:

4

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?

+2  A: 

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.

gustafc
Thanks for the example, at first I was looking a more android based solution (e.g. using only the xml to have the strings), so to tell you the truth I thought that it wasn't possible to integrate the Android strings system with ChoiceFormat, but you just gave me a great idea on how to mix both.BTW this is exactly what I wanted, the plural changes after certain numbers. The only caveat, is that adding new languages that have special plural changes would require modifications of the source code.
janfsd
A: 

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.

Kris
With Android it is possible to do this. How do you do with strings that you need to set up at runtime?
janfsd
The stuff i need to do at runtime is fairly limited but i use a "normal"i18n table through some of my own class methods like`String::stringWithLocalizedString('Good {timeofday} {username}')` and such that can be used with formatting functions.
Kris
Oh I see, thanks!
janfsd
A: 

There's a built-in "plurals" support which is not well documented.
Mentioned here and you can see it in the Browser sources.

alex
Thanks, I think this is what I need! Do you know the difference between using xliff and not? In one of the links they use this: <item quantity="one">%s thing</item> In the other they use: <item quantity="few"><xliff:g id="number" example="2">%d</xliff:g> matches</item>
janfsd
After trying this, it doesn't seem that it supports something like <item quantity="three"> (I need this because in polish the plural for quantities from 2 to 4 is different than the rest). Is there a way I can achieve this?
janfsd
I'm not using this myself, you'll need to search Android sources for examples.
alex
A: 

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.

janfsd
I don't really understand why you bother mixing plurals and `MessageFormat`? If I were you I'd either try and figure out how to do this properly with only plurals, or I'd ditch plurals altogether and just go for `MessageFormat` for all languages - saying something like `MessageFormat.format(getString(R.string.year_format), n)` seems a lot easier than what you have now.
gustafc
Yeah, I think you are right, I will be going MessageFormat only. I just didn't want to throw away the plurals code. I can't use only plurals (which would be the best). THanks for the help :)
janfsd