Android how to make localization to range languages? - android

I have three languages on my app: English, Russian, Spanish being English the default language.
Now I want to use the Russian language in some other countries in like: Ukraine and Belarus.
It's possible to use the russian language file the countrys that I mentioned or it's mandatory to create separated files for each one of them?

If you want to use same Russian translations for all three countries just add:
res/values-ru/
folder, and place strings.xml translation file in it with general Russian translations, it will display the same text for all Russian variants.
If you want to use different syntax, as I guess Russian is not 100% the same in all three countries create:
res/values-ru/ /* General Russian */
res/values-ru-rRU/ /* Russian Russian */
res/values-ru-rUA/ /* Ukrainian Russian */
res/values-ru-rBY/ /* Belorussian Russian */
folders, and place strings.xml translation file in each of them with localised translations. It will show translations to user based on their localised setting on the device: for Ukrainian, Belorussian, and Russian it will display the respective translation. For any other Russian region it will display the content from values-ru/
Cheers

You need to create a strings.xml file for each language and add it into a folder called values-es, values-de etc.
http://developer.android.com/guide/topics/resources/localization.html

You need to follow format for same language with different countries/regions.
For only locales
values-[locale]
For only locales with regions
values-[locale]-r[region]
In Your case
values-ru,
values-ru-rRU,
values-ru-rUA,
values-ru-rBY,

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.

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.

What is "values" folder name for Danish Language?

I read the localization in Android. Here for we need to create different values's folder for each language.
for e.g.
res/values/strings.xml : Contains English text for all the strings that the application uses, including text for a string named title.
res/values-fr/strings.xml : Contain French text for all the strings, including title.
res/values-ja/strings.xml : Contain Japanese text for all the strings except title.
Now I want to give support for Danish language then what should I name to value's folder ?
For Danish, you got to use values-da folder.
Edit: It turns out, according to this post that it is values-da.
Plus, according to the Android Locale class documentation:
The language codes are two-letter lowercase ISO language codes (such as "en") as defined by ISO 639-1.
The country codes are two-letter uppercase ISO country codes (such as "US") as defined by ISO 3166-1.
The variant codes are unspecified.
For Danish generally, you would want to use res/values-da/strings.xml.
To have strings specific to a country as well as a language you would use res/values-da-rDK/strings.xml for Denmark, res/values-da-rGL/strings.xml for Greenland, res/values-da-rDE/strings.xml for Germany (there being a sizable Danish-speaking community in Southern Schleswig along with a few elsewhere in Germany), res/values-da-rFO/strings.xml for the Faroe Islands, and so on. You can even have something like res/values-da-rFR/strings.xml as while there isn't a large Danish-speaking population in France, nothing stops you doing something like that anyway.
You can mix these, e.g. being specific to country only for a handful of values, falling back to res/values-da/strings.xml for everything else.
Via http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes, you would use res/values-da/strings.xml.
Android value's folder is following the locale naming specified by ISO-639-1.
Danish language, according to the standard, have the locale da, so your folder will be values-da.
The same rule applies to all languages.
Reference: http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes

Android localization values-** folder names

I have seen several conflicting tables that show localizations and what names they should take
A lot of them suggest that there are versions of the language for each country, which is fine, for languages like English, Spanish and Chinese, where I can choose to make a values-en folder or a values-en_US folder if I want to make it more specific
but some other languages like greek have a locale name el_GR , can I just make a folder names values-el or does it HAVE to be values-el_GR
thats just an example and I don't trust the tables I have read, and the android developer guide does not nearly list the available locales
The folder name of Android string files is formatted as the following:
without region variant: values-[locale]
with region variant: values-[locale]-r[region]
For example: values-en, values-en-rGB, values-el-rGR.
In your case, you just need to create a folder values-el for the Greek translation, and values-el-rGR for the country-specific Greek translation.
Also, you can make use of the resources fallback mechanism in Android, to allow particular strings to be further translated locally.
For example, suppose you have a string called “R.string.title” and the locale is ‘el-GR’, Android will look for a value of “R.string.title” by searching the files in the following order:
res/values-el-rGR/strings.xml
res/values-el/strings.xml
res/values/strings.xml
Therefore, you can just put the country-specific translation inside the res/values-el-rGR/strings.xml, and let the res/values-el/strings.xml stores the general translations.
It can avoid duplicating your strings in different language files by utilizing this fallback mechanism.
Right click "res" folder in your project. Pick > New > Android resource file > Localization - and it will offer you all the possible Language and Locales options and even create required folders.
all can find in https://developer.android.com/index.html
in https://developer.android.com/guide/topics/resources/providing-resources.html#AlternativeResources
the page descript multiple resouce define, like drawable , value
in https://developer.android.com/training/basics/supporting-devices/languages.html
the page provide Language res define,
it‘s import How Create Locale Directories and Resource Files .
the format is <resource type>-b+<language code>[+<country code>].
and the language code country code reference https://developer.android.com/reference/java/util/Locale.html
language
ISO 639 alpha-2 or alpha-3 language code, or registered language subtags up to 8 alpha letters (for future enhancements). When a language has both an alpha-2 code and an alpha-3 code, the alpha-2 code must be used.
You can find a full list of valid language codes in the IANA Language Subtag Registry (search for "Type: language").
https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry
country (region)
ISO 3166 alpha-2 country code or UN M.49 numeric-3 area code. You can find a full list of valid country and region codes in the IANA Language Subtag Registry (search for "Type: region").
https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry
Other reference: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2

Android localize es-r419

I'm localizing my app and one of the language/region supported is Espanol-419. Android doesn't support the naming convention values-es-r419 but it does accept values-en-rGB.
What name should I use to make it work?
I don't know where r419 comes from. The only thing I could think that it would be is an LCID but 419 is for Russian, or a country code, but there's nothing for 419. Here are a list of locale codes for Spanish, perhaps the one you want is in here:
es-ar Spanish - Argentina
es-bo Spanish - Bolivia
es-cl Spanish - Chile
es-co Spanish - Colombia
es-cr Spanish - Costa Rica
es-do Spanish - Dominican Republic
es-ec Spanish - Ecuador
es-sv Spanish - El Salvador
es-gt Spanish - Guatemala
es-hn Spanish - Honduras
es-mx Spanish - Mexico
es-ni Spanish - Nicaragua
es-pa Spanish - Panama
es-py Spanish - Paraguay
es-pe Spanish - Peru
es-pr Spanish - Puerto Rico
es-es Spanish - Spain (Traditional)
es-uy Spanish - Uruguay
es-ve Spanish - Venezuela
References:
Microsoft's LCID table
ISO 3166-1
ISO 3166-1 Numeric
Update:
So apparently 419 is from the UN M.49 standard taken up by BCP 47 for the IETF language tag. Google's documentation on alternative resources says:
The language is defined by a two-letter ISO 639-1 language code, optionally followed by a two letter ISO 3166-1-alpha-2 region code (preceded by lowercase "r").
Clearly (by the "r" alone) you can see that these are not standard IETF language tags. Unfortunately, I believe this also means that you won't be able to find a suitable two letter region equivalent to 419. You can also check the official ISO list. It's not on there, there are only two letter tags for countries. Apparently it's very common not to support the 3-digit tags.
The only solution I can think of is to provide a default set for es and then a more specific set for a subdivision of es countries. You could provide resources for each region (like es-rAR) that you think matches up with 419, but looking at that list, I think it'd be easier to do the opposite and use es to provide resources for Latin American Spanish, and then provide resources for es-rES for Spain. As es-rES is more specific than es, it should take precedence (if the locale matches).
es-r419 = es-rUS.
change the folder name to values-es-rUS for consistency with runtime user options.
When using Google Translation services, when you request translation to Spanish for Latin America, you will receive es-r419 folder returned.
When looking at AOSP source, or in the settings->language and input->language, you will see Spanish and Spanish (United States).
At runtime, selecting language = Spanish (United States), you will not see strings pulled from values-es-r419, and of course you will see strings pulled from values-es-rUS
Android 7.0 (API level 24) brings more robust resource resolution, and finds better fallbacks automatically. However, to speed up resolution and improve maintainability, you should store resources in the most common parent dialect. For example, if you were storing Spanish resources in the values-es-rUS directory before, move them into the values-b+es+419 directory, which contains Latin American Spanish.
Source: https://developer.android.com/guide/topics/resources/multilingual-support.html
We offered language selection in-app, so to work well on new and old phones we kept duplicate resources in values-es-rUS Español (Estados Unidos) as well as values-b+es+419 Español (Latinoamérica)
419 comes from here, and is for any LatinoAmérica (Spanish) regions.
Español (Colombia), Español (México), etc, will use values-es-r419
We can also use this for each region instead of names, although it is more difficult
values-en-r840 intead of values-en-rUS
But, if we want a language for each region, the file must have the language followed by "-r" and the country code. The name is added automatically when choosing the region.
To do that, create a "value resource file", choose the "Locale" option and choose the region.
If the device language is "English (United States)" will take values-en-rUS/strings.xml.
If the device has a language with a country that we do not support, will use values-en/strings.xml (is used by any region).
Now, if you want to programmatically add the language, you cannot set the language as "en_US" or "en-rUS" because it doesn't exists, "en_US" is still "en".
That's why you need to add the country to the Locale language (android supports upper or lower case)
//Example language = "en" country = "US"
private void setLanguage(Context context, String language, String country) {
Configuration config = new Configuration(context.getResources().getConfiguration());
config.setLocale(new Locale(language, country));
//Copies the fields from delta into this Configuration object, keeping track of which ones have changed.
config.updateFrom(new Resources(context.getResources().getAssets(),
context.getResources().getDisplayMetrics(), config).getConfiguration());
context.createConfigurationContext(config);
}

Categories

Resources