9

My country (Spain) has several languages (es-ES, ca-ES, gl-ES, eu-ES). We won't add all the languages for now so we would like to use main language in Spain, i.e. Spanish (es). We would like to display the /values-es/strings.xml when the user has selected one of the other languages in the country. How can we do that?

Oh, and we would like to use English as the default language (/values/strings.xml).

It would be great to have something like /values-ES/strings.xml, but I suppose that can't be done because the first code should be the language code.

Now we are copying the /values-es/strings.xml file to the other folders (values-ca, values-gl and values-eu) but we'd like to avoid that.

Ferran Maylinch
  • 10,919
  • 16
  • 85
  • 100
  • 1
    Your question is not clear. Are there differences between strings.xml files for the different languages or not? – greywolf82 Jun 07 '14 at 13:25
  • The simplest solution is to make Spanish be the default language, the one you use in `res/values/`. Then, any unrecognized user languages will default to Spanish, which will include all of your desired scenarios. – CommonsWare Jun 07 '14 at 13:34
  • I've clarified the question. Thanks for your help. – Ferran Maylinch Jun 07 '14 at 13:38
  • Use the **regionalized** folders: `values-es-rES` for Spain, `values-es-rUS` for Mexico (US Spanish), ... – Phantômaxx Jun 07 '14 at 13:42
  • @DerGolem: that's right. I clarified the question by adding that sentence. CommonsWare answered before that sentence was written. – Ferran Maylinch Jun 07 '14 at 13:49
  • @DerGolem: thanks for your answer. I'm trying to find information about that but get nothing. Can you provide a link? Anyway, that doesn't seem to work. When I select Catalan language (ca) I get the English default strings. – Ferran Maylinch Jun 07 '14 at 13:53
  • I digged more in depth and it seems that Mexico has it's own support (instead of the generic US Spanih) - List of "es" supported languages: es, es_AR, es_BO, es_CL, es_CO, es_CR, es_DO, es_EC, es_ES, es_GT, es_HN, **es_MX**, es_NI, es_PA, es_PE, es_PR, es_PY, es_SV, es_US, es_UY, es_VE but I don't know the minimum required API for each of them. So, I can guess: Generic, Argentina, Bolivia, ?, Colombia, ?, Dominican Republic, Ecuador, Spain, Guatemala, Honduras, Mexico, Nicaragua, paraguay, Peru, ?, ?, Sevilla, Generic US, Uruguay, Venezuela (If I'm not misinterpreting) – Phantômaxx Jun 07 '14 at 13:55
  • 2
    For the region support, see http://developer.android.com/guide/topics/resources/providing-resources.html#AlternativeResources (Table #2, "Language and region" row). However, this approach will require a fair bit of work to avoid data duplication. I'd argue that it's a cleaner approach than the override-the-locale-at-runtime technique, but whether it is worth the work is up to you. – CommonsWare Jun 07 '14 at 13:55
  • @DerGolem: Generally speaking, API level should not matter here. The Android documentation used to list supported languages by API level, but that was really documenting what Android *itself* had been translated to. The determination of what locales are available on a given device is up to the manufacturer. AFAIK, Android just looks for matches based on what the user chose from the manufacturer-supplied options – CommonsWare Jun 07 '14 at 13:57
  • @CommonsWare Dear Mark, I wish you were right. Just that I can't add Portuguese support to my apps, since my minSdkVersion is 8 (Froyo) and support for Portuguese has only been added in API Level 9 (GingerBread). So, maybe I can force the strings, but I can't use the TTS Engine, because it won't recognize the **pt** language (I'm not distinguishing between Portugal and Brazil - I just want to provide the **official** language)... – Phantômaxx Jun 07 '14 at 14:05
  • @DerGolem: "Just that I can't add Portuguese support to my apps, since my minSdkVersion is 8 (Froyo) and support for Portuguese has only been added in API Level 9 (GingerBread)" -- I fail to see how you have determined that API levels have anything to do with it. For example, it may be that the Android *emulator* for API Level 8 does not support `pt`, but that does not mean that *Android* does not support `pt`, just that the emulator did not ship with that locale. You may wish to ask a separate SO question for help with your issue. – CommonsWare Jun 07 '14 at 14:11
  • @CommonsWare Please, refer to this answer: http://stackoverflow.com/a/7989085/2649012 - or maybe (it may happen) I misunderstood? – Phantômaxx Jun 07 '14 at 14:16
  • @DerGolem: That refers to the languages Android itself has been translated to. Device manufacturers sometimes will do their own translations to other languages and not contribute those translations back to Google (or Google does not accept the contribution for one reason or another). I have no idea if any Android devices shipped for API Level 8 with manufacturer-supplied support for a `pt` locale, and without that, the user would have no way of specifying `pt`, and a `pt` translation of your strings would not get chosen (outside of your setting the locale as in popovitsj's answer). – CommonsWare Jun 07 '14 at 14:20
  • 1
    @CommonsWare Well, I prefer the "paranoid way", and keep my app crash-safe. If no **official** support has been granted by Google, then I don't even put my efforts on it. I'll remain with my German, French, Spanish, Italian and (fallback to) English. Which is enough, at the moment. Later, when Froyo will go out of the monthly DashBoard, I'll raise my minSdkVersion to **9** and add Portuguese too – Phantômaxx Jun 07 '14 at 14:23
  • And yes, I force the locale in my preferences (i.e.: a Canadian user has the phone set in French and wants to keep that setting - but he/she prefers my app in English, then he/she can do that without resetting his/her phone - I find this feature useful). – Phantômaxx Jun 07 '14 at 14:37
  • @Sergey Might [this](http://stackoverflow.com/questions/40942535/using-locale-to-force-android-to-use-a-specific-strings-xml-file-for-a-non-suppo) be of any help? – Onik May 21 '17 at 13:23
  • Do you want to have your message only for people in Spain? or only for people using those mentioned languages? I hope you are aware that these are 2 very different things. – Rahul Tiwari May 22 '17 at 12:05

6 Answers6

4

I think that you should have only 2 folders with 1 strings.xml for each other:

  1. res/values/strings.xml this resource will contains your text in English ;
  2. res/values-es/strings.xml this resource will contains your text in Spanish .

When your app is installed on a device which is configured with the Italian language, it will use the file resource on case 1.

When your app is installed on a device which is configured with a Spanish language (and there are a lot of Spanish language out there, think about South America countries), it will use the file resource on case 2.

You can do it easily with Android Studio:

  1. right-click on res folder
  2. go to New > Android resource directory
  3. a window will show you some options; pick Locale and then click on the button with those symbols "> >"
  4. then on the Language list, pick es: Spanish and then click OK, as showed in the image below (note that by default the Specific Region Only has Any Region selected!)

Add locale image guide

By experience: I never faced up a Breton, Corsican or Provençal users claiming for a full translation of the application in their language (by default the app has English as default and French).

JJ86
  • 5,055
  • 2
  • 35
  • 64
0

I would say you want to do something like this.

if (Locale.getDefault().getISO3Country().equals("ESP"))
{
    Locale[] locales = Locale.getAvailableLocales();
    for (Locale loc : locales)
        if (loc.getISO3Language().equals("SPA"))
        {
            Locale.setDefault(loc);
            break;
        }
}

Note: I'm not sure if I got the ISO3 language and country codes right. And you'll also have to do something for the (rare?) situation that the es-ES locale is not available.

wvdz
  • 16,251
  • 4
  • 53
  • 90
  • You would still have to hand-duplicate a few strings, ones that are loaded by third parties, such as those referenced in the manifest. I get queasy with the "change the app's locale dynamically" approach, but there seem to be enough developers using it, that it's presumably working well. – CommonsWare Jun 07 '14 at 13:35
  • Thanks popovitsj. Where should I put that code? In `MyApplication.onCreate` or in `MyBaseActivity.onCreate`? – Ferran Maylinch Jun 07 '14 at 13:47
  • I think the safest place to put this would be the onResume() of your Activity. – wvdz Jun 07 '14 at 13:49
  • That code doesn't seem to work because in my case the `Locale.getDefault()` always returns `"es-ES"` even when I set other language in the preferences. Here I found the accepted way to set the Locale, although it is not recommended: http://stackoverflow.com/a/2900144/1121497 – Ferran Maylinch Jun 07 '14 at 14:24
0

If you are trying to override Catalan with Spanish, you should probably have that in the values-ca/strings.xml file.

The way to do what you are asking is to provide the resources in the appropriate mobile country code resource folder, which takes precedence over language-region resources.

Assume that you have the following situation:

The application code calls for R.string.text_a Two relevant resource files are available: res/values-mcc404/strings.xml, which includes text_a in the application's default language, in this case English. res/values-hi/strings.xml, which includes text_a in Hindi. The application is running on a device that has the following configuration: The SIM card is connected to a mobile network in India (MCC 404). The language is set to Hindi (hi). Android will load text_a from res/values-mcc404/strings.xml (in English), even if the device is configured for Hindi. That is because in the resource-selection process, Android will prefer an MCC match over a language match.

The MCC for Spain is 214.

(See Localization)

Eran Goldin
  • 980
  • 12
  • 21
  • Thanks Eran. I suppose that, with MCC, an English user in Spain would see our app in Spanish regardless the language she set in her device (most probably English). – Ferran Maylinch Jun 07 '14 at 13:45
  • 1
    Yes, that is true. I still think duplicating the resource file four times is the best solution as it does exactly what you need and doesn't hide what you are doing, which is overriding the three other languages with Spanish strings. – Eran Goldin Jun 07 '14 at 15:01
  • Another possibility is detecting the current locale, and if it matches any of the Spanish locales you want to override, you change the default locale to the one you want to use instead. (which is what I see popovitsj is stating below) – Eran Goldin Jun 07 '14 at 15:02
0

I found another tricky solution: hard links. Although it doesn't remove whole problem completely, at least it protects you from routine task of copying file across multiple directories or making equal changes in all existed files with risk of miss something.

But I must admit that there is some caveats:

1) Some IDE does not support working with hard links by-default. Intellij IDEA and Android Studio will break your hard links if you don't disable "safe write" option in settings.

2) Most version control systems also doesn't support hard links by default. Let's take git for example. It will break existing hard links after reverting or merging changes.

Currently, I'm using batch file for restoring hard links after they get broken by git.

ITurchenko
  • 1,828
  • 2
  • 17
  • 24
0

In a general term, there should be only one strings.xml file under values folder containing the relevant data. If we explicitly specify different values folder like values-ca,values-es, whenever there are setting changes in the android device, it will look to the particular folder and take the appropriate strings value. If the requirement is keep uniform text means better have only values->strings.xml file alone with the required data. But with this approach multilingual apk is not possible i.e. for other country different language is expected, there will be variations again. So wherever we need uniform language, lets go with single folder alone and wherever multilingual is preferred, we can have multiple values-es,values-ca folder like that. Hope that helps

this.girish
  • 1,296
  • 14
  • 17
priya raj
  • 362
  • 2
  • 8
0

How about trying to set it in java, instead of using strings.xml. As doing it programatically gives you more flexibility at run-time.

    Configuration config = new Configuration(getResources().getConfiguration());

    Locale locale = Locale.getDefault();
    String country = locale.getCountry();
    String language = locale.getLanguage();
    if (country.equalsIgnoreCase("ES") && (language.equalsIgnoreCase("ca") || language.equalsIgnoreCase("gl") || language.equalsIgnoreCase("eu"))) {
        locale = new Locale("es");
    }
    config.setLocale(locale);

And then you can simply have one /values-es/strings.xml for all the ES country languages.

Anmol
  • 448
  • 2
  • 6