Android ignoring Locale change, using default strings.xml - android

My app supports two languages, default is English and other one is simplified-chinese. I have created two values folder (values and values-zh-rSG) and have placed strings.xml files that contains strings respective to language.
In One of my Activity , user can change default language from English to chinese or chinese to English and than I reload the MainActivity again.
Locale is changed as when I check in MainActivity it displays simplified-chinese using following code:
Configuration config = getResources().getConfiguration();
Log.d("checknl",config.getLocales().get(0).getDisplayName()) ;
But somehow, strings.xml from values-zh-rSG is ignored. It is always loading in English.
Please See: My build.gradle file doesn't contain "resConfigs "en"" in build.gradle (app) file.
I have tested this app on Android api 22 to 26. But it doesnt work in any.

Related

Android app chooses default language regardless language preference order config in settings

Starting with Android 7.0 (API level 24) user is able to set preferred languages on his device (source: LocaleList API). My problem is that my app does not respect this setting - it does not take the second language into account.
In Settings -> languages I have chosen my language preferences as:
1. Polish (preferred)
2. French
In Android app I have two languages supported (en as default, and fr):
values/strings.xml (English as default)
values-fr/strings.xml (French)
With this config, App is starting in English (which is default) while on my list of language preferences there is French (which is supported in my app, and should be used).
Why Android chooses English in this case? How to fix that?
Note: French language is set properly when I choose FR language as preferred in settings
EN strings.xml file sample:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE resources [<!ENTITY applicationName "app\'s name">]>
<resources>
<string name="application_name">&applicationName;</string>
<string name="dialog_ok">OK</string>
...
</resources>
FR strings.xml file sample:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE resources [<!ENTITY applicationName "french name">]>
<resources>
<string name="application_name">&applicationName;</string>
<string name="dialog_ok">Oui</string>
...
</resources>
The solution is to add resConfigs in the android.defaultConfig of the app/build.gradle to contain your exact locale list (what you have in your app):
android {
defaultConfig {
resConfigs "nb", "nn", "in", "iw", "fr", ...
}
}
See the slides for the "Android Internationalization" tutorial at http://www.unicodeconference.org/presentations/
(direct link: http://www.unicodeconference.org/presentations/TS1T3-Nita-Pournader.pdf)
Also https://gist.github.com/amake/0ac7724681ac1c178c6f95a5b09f03ce
The explanation: the fallback through the locale list happens at start time, not when loading the strings.
Most applications these days use some kind of support libraries. The Google support libraries are localized in about 80 languages, and the resources from the libraries are merged into your application.
At load time the system checks for localized resources in the order in the list, finds some "traces" of Polish from the support libraries, and decides that your application is translated into Polish.
So it decides that in fact you have Polish, sets the default locale to Polish (so you get dates, times, etc. formatted for Polish). But when it tries to load the strings there is nothing to be found, the and loads the strings from the default folder (in values), which are English.
By using resConfigs you are telling the resource compiler to only include the locales you want in the apk. So it will drop the few Polish strings from the support libraries. Now the loader will check, there are no Polish strings, goes to French, and all is good.
This not only solves your problem, but also results in a (slightly) smaller apk.

Multi languages resources with proper language code

I want to make application, that will support languages with resources depending of actual localization and country code. According to Documentation I need to change resources to format i.e. values-en-rUS, and in that configuration app sucessful compile and proper flag image in resources is set it up but I dont know what format should be write in Locale variable to change resources. I try en_US , en-rUS , en-US but does doesnt work correctly. In my previous version with resources like values-en changing Locale of the app language to en the resources are updating correctly.
Locale for values-en-rUS can be obtained by new Locale("en", "US"), this will get instance of "en_US" locale (matching values-en-rUS).
Don't use new Locale("en_US") this will produce "en_us". That doesn't match values-en-rUS. Also new Locale("en-US") will not work.
From API level 21, there's handy Locale.forLanguageTag(String) method. It returns a locale for the specified IETF BCP 47 language tag string, which is "en-US" in this case. So you can use Locale.forLanguageTag("en-US).
Not totaly sure of what you asking but if you want to add languages you need to create indeed to create the write folder but in that format : <resource type>-b+<language code>[+<country code>]
example : value-b+en+US
Then you can add the strings.xml file in each folder to what you want to display. You can find all the documentation here.

Android pseudolocalization not working

I have added an ar-rXB localization (placed in res/values-ar-rXB/) to help me find unlocalized strings, and replaced each string resource with "木村 政彦" in the Android studio translation editor. Android Studio Preview is showing me the correct strings when I change localization.
I have also placed "pseudoLocalesEnabled true" in the end of app/build.gradle's debug buildType.
When I change my phone's language to arabic and country to XB in MoreLocale 2, all the strings are simply the default value written backwards. Uninstalling the app and reinstalling it with the locale set do not help. I have also tried this with the locale "zz_ZZ"
Is this a problem with MoreLocale 2, my phone or have I missed some part of enabling pseudolocales?
This issue was caused by my misunderstanding of how the en_XA and ar_XB pseudolocalizations work. The compilation process autogenerates strings for the pseudolocales, overwriting my translation.

Android. How to use the same localizable messages for all the languages in a country?

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.
I think that you should have only 2 folders with 1 strings.xml for each other:
res/values/strings.xml this resource will contains your text in English ;
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:
right-click on res folder
go to New > Android resource directory
a window will show you some options; pick Locale and then click on the button with those symbols "> >"
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!)
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).
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.
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)
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.
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
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.

App not using the loacal resource it needs

I am trying to get my app to use a different String for hebrew.
what I did was I created a different filder in "res" calles "values-iw" and places a "strings.xml" file in there.
when i do Locale.getDefault(); i get "heb-il" which by google is ok "Java uses several deprecated two-letter codes. The Hebrew ("he") language code is rewritten as "iw".
but when I am doing getResources().getString(R.string.deafult_sleeping); I am getting the default string and not the one in "values-iw".
Why is that?+
Most Devices still use "he". I think alot of Android uses "he" and it is mapped to "iw" in the compiler. You should make both Folders to be safe.
Ps. you can check which Code you are getting with
Locale.getDefault().getLanguage();
Also see Locale code for Hebrew / Reference to other locale codes?
Maybe this will help sombody with changes of Local:
Locale.getDefault().getLanguage().equals(new Locale("he").getLanguage())

Categories

Resources