Is it possible to change the language of an app programmatically while still using Android resources?
If not, is it possible to request a resource in an specific lan
It's possible. You can set the locale. However, I would not recommend that. We've tried it at early stages, it's basically fighting the system.
We have the same requirement for changing the language but decided to settle to the fact that UI should be same as phone UI. It was working via setting locale but was too buggy. And you have to set it every time you enter activity (each activity) from my experience. here is a code if you still need this (again, I don't recommend that)
Resources res = context.getResources();
// Change locale settings in the app.
DisplayMetrics dm = res.getDisplayMetrics();
android.content.res.Configuration conf = res.getConfiguration();
conf.setLocale(new Locale(language_code.toLowerCase())); // API 17+ only.
// Use conf.locale = new Locale(...) if targeting lower versions
res.updateConfiguration(conf, dm);
If you have language specific content - you can change that base on the setting.
update on 26th of march 2020
public static void setLocale(Activity activity, String languageCode) {
Locale locale = new Locale(languageCode);
Locale.setDefault(locale);
Resources resources = activity.getResources();
Configuration config = resources.getConfiguration();
config.setLocale(locale);
resources.updateConfiguration(config, resources.getDisplayMetrics());
}
Just adding an extra piece that tripped me up.
While the other answers work fine with "de" for example
String lang = "de";
Locale locale = new Locale(lang);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
The above wont work with for example "fr_BE"
locale so it would use the values-fr-rBE
folder or similar.
Needs the following slight change to work with "fr_BE"
String lang = "fr";
//create a string for country
String country = "BE";
//use constructor with country
Locale locale = new Locale(lang, country);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
If you write
android:configChanges="locale"
In every activity (in the manifest file) then no need to set it every time you enter Activity
.
https://stackoverflow.com/a/48531811/9609776
This is ok but do not split the updateResources into different versions, just use the solution below (kotlin). Key is in "Configuration(context.resources.configuration)" it makes deep copy.
100% solution for API 21+. I have not tested for lower ones, but should work.
private fun updateResources(context: Context, language: String): Context {
return Configuration(context.resources.configuration).run {
Locale.setDefault(Locale(language).also { locale ->
setLocale(locale)
}).let {
context.createConfigurationContext(this)
}
}
}
First you create directory name values-"Language name" like hindi than write "hi" and same string file name copy in this directory and change value do not change parameter after set below code in your action like button etc....
Locale myLocale = new Locale("hi");
Resources res = getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
conf.locale = myLocale;
res.updateConfiguration(conf, dm);
Intent refresh = new Intent(Home.this, Home.class);
startActivity(refresh);
finish();
Locale locale = new Locale("en");
Locale.setDefault(locale);
Configuration config = context.getResources().getConfiguration();
config.setLocale(locale);
context.createConfigurationContext(config);
Important update:
context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());
Note, that on SDK >= 21, you need to call 'Resources.updateConfiguration()', otherwise resources will not be updated.