Localization for Canada defaults to UK; should default to US - android

I'm working on an application that has localized strings for the UK, specified in res/values-en-rGB/strings.xml. My default string implementations, for the US, are in res/values/strings.xml.
Now, I'm adding additional localizations for Canada in res/values-en-rCA/strings.xml. I would like the application to behave as follows: If a user's device is localized to Canada (or their language is set to English(Canada) or French(Canada)), check if we have a string in en-rCA, and if not, fallback to the string in my default strings.xml file. However, my application currently fallbacks to strings from en-rGB when the device is set to a Canadian locale and the string is not found in en-rCA. Therefore, I have two questions:
How can I configure my app such that a device with a Canadian locale searches for a string in en-rCA and then, if it cannot find it, defaults to the string in my default values folder rather than en-rGB?
How can I ensure that a device whose language is set to French (Canada) defaults to en-rCA rather than my default values, as it currently does?
I would be happy to provide an example if it would be helpful. Thanks!

Finale Update:
After opening a bug report on Google Incorrect resource resolution strategy above Android N, defaulting to en_GB and not default strings.xml, they mentioned that this in the intended behaviour for Android N above. en_UK is considered "a representative of International English". The strings will fall back to "International English" strings or its representative before going to default en strings. I'm quoting their reply here:
Starting in N, all English locales (except for US and US territories like Puerto Rico and American Samoa) fall back to some International English variant if such a locale is available.
So for en-CA, we would try these locales first, before falling back on en-GB (which is considered a representative of International English if there is no better International English locale): en-rCA (Canadian English), b+en+001 (International English), en (English).
If you don't want en-GB strings to be picked up for en-CA, you should put resources in one of those three directories, as they would be considered a better match for en-CA.
Update 1:
It seems this is not just limited to en_CA. There is another similar question for other English locales : Android 7.0 Nougat picks up default strings when device language is en_US. Looks like a platform bug at this stage.
Original Answer:
Not sure if its a bug or a feature. From API level 24 (Android 7.0), they've updated how Android resolves strings as mentioned Improvements to Resource-Resolution Strategy
. Taking an example from the documentation below:
Before Android 7.0:
Lets say if the user has settings of fr_CH and following are the resources available in the app i.e de_DE, es_ES, fr_FR, it_IT. For older API's before Android 7.0, Android tried to find an exact match and if an exact match isn't found it defaults to the values/strings.xml, i.e en. So for en_CA case, if a string is not found in res/values-en-rCA/strings.xml, we can expect it to default to en.
After Android 7.0
However now in Android 7.0 and above, for the situation of fr_CH, it will fall back to the closest parent dialect i.e fr_FR.
Applying the same logic to the situation of en_CA and en_GB present in the app, I'm thinking that Android thinks that en_GB is the closest dialect to en_CA and is falling back to it instead of the default en first. I am facing the issue in my app and that's the only plausible explanation I can come up with of why this issue happens only on newer API versions and not on the ones before Android N.

Should happen automatically, without you doing anything. If you have values/strings.xml, values-en-rGB/strings.xml and values-en-rCA/strings.xml with the GB and CA versions containing only those strings that differ from the baseline (values/strings.xml) and if the user has his locale as en-CA, the system will load strings from values-en-rCA/strings.xml if not found, it'll fall back to values/strings.xml, the GB version wouldn't come in the picture.
For this you'll have to locally change your app locale. Basically you get the current locale, if it is fr-CA, you manually set the locale to en-CA
Locale enCALocale = new Locale("en", "CA");
Locale.setDefault(enCALocale);
Configuration config = new Configuration();
config.locale = enCALocale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
Update
As Shobhit mentioned, starting Android N, you can now have a list of locales selected in the setting and you can decide their priority:
In the above case the system will try and look for en-rCA/strings, if not found it'll look into en-rGB/strings instead of baseline, something that happened before N.

Related

How to Properly Support English when Localizing an App?

I'm working on localizing an Android app.
For arguments sake, let's say the app will support English, Albanian, and Bengali.
Currently all English strings are listed in the "default value" column of the translations editor:
Apps on the app store generally state what locales they support.
I'm assuming when you submit an app that either a person or machine verifies your claims... so...
Is it necessary to explicitly add English (en) locale/column in addition to the default values (just as Albanian and Bengali have been added in the photo) in order for the app to be considered to officially "support" English?
You do not have to add English locale to have it in Supported Language menu. Check documentations out.
When your Java code refers to strings, the system would load strings from the default (en_US) resource file, even if the app has Spanish resources localized under es_ES. This is because when the system cannot find an exact match, it continues to look for resources by stripping the country code off the locale. Finally, if no match is found, the system falls back to the default, which is en_US.
The system would also default to en_US if the user chose a language that the app didn't support at all, like French.
Default locale is en_US.
No.
Apps on the app store generally state what locales they support.
If you are talking about Apple's App Store, Google Play won't list the supported languages in similar fashion.
However, you can localize the store listing page. According to play console help, If a user's language preference matches the translation languages you've added, they'll see your app's translated version. You can also add localized graphic assets for your store listing pages. See this for more. This feature is similar to App Store's metadata localization.
There is an easy solution to your problem.
Just find the path in your project:
res/
and add a folder named:
values-en
Then add a file named:
strings.xml
Finally, it will look like this:
res/values-en/strings.xml
And the resources in it will show when the user's language setting is English.

Android drawable is picked from drawable-en-rCA when locale is en_IN

I have an image in folder drawable-en-rCA. I do not have any folder like drawable-en-rIN, or drawable-in. When I change my app locale to en_IN, drawable is picked-up from drawable-en-rCA whereas it is expected to take from default drawable folder as there are no drawables present specific for en_IN.
Can somebody help me to understand why this is happening?
If you are experiencing this issue on device running Android N or above, I think your issue might be related to the findings mentioned on this answer: Localization for Canada defaults to UK; should default to US. Google released a documentation on the Improvements to Resource-Resolution Strategy post Android N. There was also a bug report Incorrect resource resolution strategy above Android N, defaulting to en_GB and not default strings.xml for the issue but it turns out it is not a bug but a feature. Here is their response:
Starting in Android N, all English locales (except for US and US territories like Puerto Rico and American Samoa) fall back to some International English variant if such a locale is available.
So for en-CA, we would try these locales first, before falling back on en-GB (which is considered a representative of International English if there is no better International English locale): en-rCA (Canadian English), b+en+001 (International English), en (English). If you don't want en-GB strings to be picked up for en-CA, you should put resources in one of those three directories, as they would be considered a better match for en-CA.
For your case, based on these (specially the new Resource-Resolution Strategy document), it seems that when you select en_IN, if any resource is not present in drawable-en-rIN, then it looks for the closest international english directory, which in your case in drawable-en-rCA. If its not present there, only then it default to the default drawable folder.
Hope it helps.

Add language into Android Wear 1.5/2.0

If I added Slovak (SK) language (values-sk-rSK and values-sk) to the Android Wear 1.5 apks (framework-res.apk also), language wasn't set to SK automatically even I had SK on the phone.. so for change language on the Wear watches is needed to translate also Wear app on the phone to SK lang..? Or why my translation wasn't loaded on the watches..?
I have a lot of experiences with adding translation into the Android ROM for phones, but seems it works differently on Android Wear...
Thank you for any help...
As stated in this Localization Tips: Design your application to work in any locale documentation, if your application is missing even one default resource, it will not run on a device that is set to an unsupported locale.
For example, the res/values/strings.xml default file might lack one string that the application needs: When the application runs in an unsupported locale and attempts to load res/values/strings.xml, the user will see an error message and a Force Close button.
You may also check this link which explains challenges in resolving Language resources. Be noted that when your Java code refers to strings, the system would load strings from the default (en_US) resource file, even if the app has Spanish resources localized under es_ES. This is because when the system cannot find an exact match, it continues to look for resources by stripping the country code off the locale. Finally, if no match is found, the system falls back to the default, which is en_US.
Here's a related SO thread which might help.

Android programmatically check if app is localized for a language

I have an app that needs to provide strings localized in the language of another device. As soon as my app knows the language of the other device it creates a new Resources class. Similar to this question.
The resource object just created can fall back when getting strings if the language is not supported (assume other device is set to en_US):
values-en-rUS/strings.xml
values-en/strings.xml
values/strings.xml
Instead of the third fallback I want to fall back to the language of my own device (assume my device is set to es_ES it would then be):
values-en-rUS/strings.xml
values-en/strings.xml
values-es-rES/strings.xml
values-es/strings.xml
values/strings.xml
I could achieve that very easy if I could programmatically check if a language/region is supported by my app. Found this AssetManager.getLocales() but think it doesn't help.
Is there a way to achieve the desired fallback or a way to check if the app is localized in a specific language/region?
See here. Tested it and got the correct device locale as a two sign string. Code is:
String Language = Locale.getDefault().getLanguage() //returns eg. "de" for german

android localization doesn't work for some languages

I've created a values-he folder with strings.xml file identical to the default strings.xml with translated string values, but running the app both on a Hebrew selected real device and on a Hebrew selected AVD still shows the default English texts. Any ideas why?
EDIT: this was answered - in some cases, Hebrew included, some android devices support deprecated language codes. For Hebrew the old 'iw' code is still supported on some devices instead of 'he'.
This is known to be the case in some other languages.
From the Android Locale class it's said:
Note that Java uses several deprecated two-letter codes. The Hebrew ("he") language code is rewritten as "iw", Indonesian ("id") as "in", and Yiddish ("yi") as "ji". This rewriting happens even if you construct your own Locale object, not just for instances returned by the various lookup methods. Also some devices use he for hebrews too so to be compatible with use both values-iw and values-he
Starting Summer 2021 Google now requires you to upload the bundle (.aab) instead of the .apk file. With that change, if your device does not support a specific language, it will not be downloaded from the Play Store.
Check the solution here.

Categories

Resources