I'm in the process of translating an app. Looking at this, I can see that a lot of countries have several codes for language.
I tried making a folder named values-nb, for Norwegian Bokmål. I changed the locale on my phones to Norway. This worked on my Sony Ericson Xperia 8, but not on the Samsung Galaxy Tab.
I then tried renaming the folder to values-no. It now works on the galaxy tab, but not on the xperia. I create both folders, and it works. But then I have to put the same file in each folder!
What if someone chose Norwegian Nynorsk, would I have to create yet another folder so that they don't default to English but get the Norwegian text? values-nn?
I guess my question is this:
How do I get this to work? Can I make all these folders and then make them reference the values-no? Please help :)
There's no way under the current search rules to just have a localization for a specific country and be able to search all languages. At least that's my understanding from reading the pages at http://developer.android.com/guide/topics/resources/localization.html You would need to create values-nn-rNO, values-nb-rNO, and values-no-rNO and have duplicate strings.xml entries.
I haven't tried this, but look into string aliases at http://developer.android.com/guide/topics/resources/providing-resources.html#AliasResources
I know this is an old one, but heres a trick to combine no, nb and nn as no:
Locale locale = getResources().getConfiguration().locale;
if (locale.getLanguage().equals("no") || locale.getLanguage().equals("nb") || locale.getLanguage().equals("nn")){
locale = new Locale("no","NO");
Configuration config = new Configuration();
config.locale = locale;
Resources res = getBaseContext().getResources();
res.updateConfiguration(config, res.getDisplayMetrics());
}
Not an answer for the original question, but a solution for a related issue and this is a likely destination if you search for a solution for that issue (it was for me).
In our project, we had our resource directories created but for some reason localized strings were ignored.
The issue was with Androids support for generating Pseudolocalized resources. In older versions of Android you did it with this magic in the build.gradle file:
android.applicationVariants.all { variant ->
// see http://blog.danlew.net/2014/04/16/android-localization-tips/
if (variant.buildType.isDebuggable()) {
variant.mergedFlavor.addResourceConfiguration("zz_ZZ")
}
}
This has changed in later versions of Android and if you use that then you will not get any localization. The new way is just:
buildTypes {
debug {
pseudoLocalesEnabled true
}
}
Related
I have a function to rewrite and pick app language based on system language while you install an app. This function is working as expected if you build your app from Android Studio (even release build). Also, I can confirm it is working from Play Store on all Androids except Android 10, 11 and 12.
It looks like I will correctly pick locale according to my logs and I will rewrite resource config, but after activity restart, it will jump to English as default no matter what system language is currently set (even if default locale in code is correct - in my case Czech (lang code "cs").
As I said, it is caused by the Google Play version of APK, not from Android Studio one.
Is there any undocumented change by Google Play Terms of Service, that they are blocking resource config to be read-only if uploaded on Play Store since Android 10?
Here is function:
fun applyLanguage() {
val defaultLocale = startupLocale
val langs = App.languages
val langCode = app.languageIndex.let {
if (it == 0) {
if(langs.any{ l -> l.first==defaultLocale.language }) {
defaultLocale.language
}else {
langs[App.LANGUAGE_INIT_DEFAULT].first
}
} else {
langs[it - 1].first
}
}
App.log("LangChange: MainActivity -> applyLanguage (langCodeSet) $langCode")
app.sysLog("LangChange: MainActivity -> applyLanguage (langCodeSet) $langCode")
if (resources.configuration.locale.language != langCode) {
val l = if (langCode == defaultLocale.language) {
defaultLocale
} else
Locale(langCode, "", "")
arrayOf(resources, app.resources).forEach { res ->
val cfg = res.configuration
cfg.locale = l
res.updateConfiguration(cfg, res.displayMetrics)
}
Locale.setDefault(l)
}
app.langCode = if (langs.any { it.first == langCode }) langCode else "cs"
App.log("LangChange: MainActivity -> applyLanguage (langCode) ${app.langCode}")
app.sysLog("LangChange: MainActivity -> applyLanguage (langCode) ${app.langCode}")
}
Its simple function, I have an array of available languages (in my case it's 3 of them based on available resources - translates) and if the default system language is one of them I will set the app in that language, if it's not I will set Czech as default. So if I pick English, I should have the app in English, if I pick German, I should have the app in German, if I pick Czech, I should have the app in Czech and if I pick any other language (for example French) it should be set to Czech as a fallback is there.
Also, the same function is used for language picker in App settings and it's the same issue. Default locale has langCode "cs" but if I pick any of those languages from the picker, it will always set resources to default state (string.xml file) which is of course English.
Another example, I setup default language as French in device settings. I downloaded an app from store and it correctly rewrites resources locale to Czech (language code "cs"). But app was still in English.
So, resources.configuration.locale.language was "cs" after activity restart, but this resource config was completely ignored by the system and system picked default resource xml - string.xml which is English.
So it looks like you cant rewrite the resources config anymore, or technically you can, but this altered resource config is completely ignored by the system.
UPDATE
Additional debugging.
Android 10: Default language (French): App was installed and default language was set to English(suppose to be Czech).
If you change language in settings, no matter what language you pick, it will always be set to English.
Android 11: Default language (French): App was installed and default language was set to Czech(correct).
If you change your language in settings it gets interesting:
If you change to English, app switches to English. If you change back to Czech, app switches to Czech. If you change to German, app switches to English (I dont know whats going on).
Android 12: Default language (French): App was installed and default language was set to English(suppose to be Czech).
If you change to English, app switches to English. If you change back to Czech, app switches to English. If you change to German, app switches to German.
Android 9, 8, 7, 6 (and probably lower) - working as intended.
I'm not sure whats going on but its kinda funny.
According to your description above, I got that your issue only happened in the Google Play app version.
I had faced a similar issue, all I did is adding this setting:
bundle {
language {
enableSplit = false
}
}
build.gradle(.app) within android tag
To expand Eng. OsamaYousef answer.
In Short you have to disallow bundle to remove "not needed" languages when user downloads your application.
bundle {
language {
enableSplit = false
}
}
Explanation:
The reason your language picker is working with android studio and not with play store version is because through android studio you install .apk and play store installs .aab (bundle). To test what user gets by downloading your app through play store simply go to android studio -> Run -> Edit configurations... -> Under installation Options search for Deploy and select APK from app bundle.
In addition, I would also recommend following Android guide to implement latest recommendations.
I created multi language (English, Russian, Uzbek) app. I put 4 string resoureses in 4 folders (values, values-en, values-ru, values-uz) as docs. When I change app language updates resourses configuration in App Controller like below:
Settings.LANGUAGE = prefs.getString(User.LANG, Settings.RUSSIAN);
Locale locale = new Locale(Settings.LANGUAGE);
Locale.setDefault(locale);
Configuration configuration = new Configuration();
configuration.locale = locale;
getBaseContext().getResources().updateConfiguration(configuration,
getBaseContext().getResources().getDisplayMetrics());
After that App restarts by calling App controller's method like below:
public void reStart() {
Intent i = getBaseContext().getPackageManager()
.getLaunchIntentForPackage(getBaseContext().getPackageName());
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
}
After them It works well almost all devises. But on Samsung Galaxy S6 (SM-G920F), it works as crazy. Some words are in english and others are in Uzbek and ets.
So, How to fix this error? isn't the concepts of "Supporting Different Languages" supported by (applicable to) all devices?
By the way, I have checked that all resources are given in corresponding languages (as shown in attached image):
From my observations, weird behaviour was affecting only Activity titles, and I found that I was setting translations of activity titles in Manifest file. Only these translations were misbehaving. All other dynamically set translations were working fine.
So, to fix the problem, I removed all activity labels from Manifest file, then set activity titles in onCreate method as below:
getSupportActionBar().setTitle(R.string.title_activity_followers);
Problem solved.
My app is quite simple and does not need a lot of localization.
I supply default language (in English) and German - this is all I ever want and will ever supply, as the app is completely focused in Germany.
As I recently added Google Play Services library, I face the problem that 56 (!!!) additional languages have been added to my app, as the Google Play Store tells me. Reason is: the library comes with many more language resources that I do NOT want in my app. It simply does not make any sense if a Google Play dialog pops up in French when the rest was only English/German.
I do not want to manually delete resources from the library project, this is tedious and error prone. Plus, maybe I will have another app relying on the same library and there I want more languages?
So - how can I accomplish this??
Thanks!
I understand your problem, the easy solution is to remove all extra languages from the library but, you need to do it with every new version of Google Play Services, and as you says, if you need other languages in other apps, that wouldn't be the best option.
Instead try to force to your app to use German or English as default:
You need to add this code in your Application class
#Override
public void onCreate() {
super.onCreate();
avoidOtherLanguages();
// your code here
}
#Override
public void onConfigurationChanged() {
super.onConfigurationChanged();
avoidOtherLanguages();
// your code here
}
public void avoidOtherLanguages() {
if (!Locale.getDefault().getLanguage().equals(Locale.GERMAN.getLanguage()))
{
// when other than german, use english
final Configuration configuration = getResources().getConfiguration();
configuration.locale = Locale.ENGLISH;
getResources().updateConfiguration( configuration, getResources().getDisplayMetrics() );
}
}
I hope it works for you!
** UPDATED: SOLUTION **
Hi come up with a solution after a lot of googling! If you are using gradle as build system you can do this in your build.gradle file:
.....
defaultConfig {
minSdkVersion 15
targetSdkVersion 22
versionCode 75
versionName "1.0.0"
resConfigs "en", "de"
}
...
use resConfig to tell gradle that you are only using these locales configuration, all other languages in your libraries will be stripped out of the APK bundle!
Let me know if that worked for you!
I've created a values-zh_CN directory in my res folder for Simplified Chinese localization. Eclipse does not accept that folder name, it marks it as an error, the directory itself.
The problem is definitely with the directory name, if I change the directory name to values-nl for example the error comes off.
The only name Eclipse accepts is values-zh-rCN which compiles fine but the actual locale is not loaded (Default en is loaded instead).
If you named dir for example values-zh it will be loaded only when Chinese is chosen in system language settings. You should know about that.
Value zh-rCN is correct and everything should work correctly. Read my notice above.
Use following code its working for me for traditional and simplified chinese.
if(selectedLanguage.equals("zh_CN"))
locale = Locale.SIMPLIFIED_CHINESE;
else if(selectedLanguage.equals("zh_TW"))
locale = Locale.TRADITIONAL_CHINESE;
else
locale = new Locale(selectedLanguage);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
baseContext.getResources().updateConfiguration(config, baseContext.getResources().getDisplayMetrics());
The correct locales are zh-rCN and zh-rTW,so then whatever Android software your using isn't correctly setting locale values.
Look into settings -> Language & Input to double check that Language is on Chinese, and if that fails look in the market for an application called MoreLocales2, it allows you to get around some of those stock Samsung softwares that prevent locale changing from working.
I have an android app and I want to translate to Serbian and I want both variants of the language: with Latin letters and with Cyrillic letters.
I tried this variants: value-sr-rRS-Latn , value-sr-Latn , value-sr-rRS-Cyrl , value-sr-Cyrl
but not of that is working.
I get this error: android-apt-compiler: [NAMEOFAPP] invalid resource directory name: [path]\res/value-sr-rRS-Latn
On Android documentation about res dirs and Locale I can't find this option.
Can I make 2 dirs with 2 variants of the language? And how?
Thank you
Since Android 7.0, Serbian with Latin script has officially been included. values-sr is still used for the Cyrillic script, and values-b+sr+Latn is used for the Latin script.
values-sr for Cyrillic
values-b+sr+Latn for Latin
I just tested Android localization and I found out that you can use any arbitrary region and it will work.
Add a folder to the project with name like values-sr-rZZ where ZZ is a fictitious region which never existed.
Then add the following code to the Application class, I got it from here and slightly changed:
public class MainApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
Resources res = this.getResources();
Configuration conf = res.getConfiguration();
boolean isLatinAlphabet = PreferenceManager.getDefaultSharedPreferences(this)... // get a value from the application settings
if(conf.locale.getLanguage().equals("sr") && isLatinAlphabet) {
conf.locale = new Locale("sr", "ZZ");
res.updateConfiguration(conf, res.getDisplayMetrics());
}
}
}
In this code the locale will be changed only if the user has chosen the serbian language as the default (conf.locale.getLanguage().equals("sr")) and also checked some checkbox in the app preferences (isLatinAlphabet).
You can use a different condition and change it as you like.
Also such dynamic way of changing language can have bugs with menu items on older devices, but it isn't reproduced on newer devices.