Android how to change the application language at runtime - android

I want to let the user change the language of my application using spinner (or any way).
I tried many ways but they change the language of this activity not all activities, and I want to save it so when the user restart the app he will find the last choosed language.

you can use this code in spinner or any way you want
String languageToLoad = "en"; // your language
Locale locale = new Locale(languageToLoad);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
then you should save the language like this
SharedPreferences languagepref = getSharedPreferences("language",MODE_PRIVATE);
SharedPreferences.Editor editor = languagepref.edit();
editor.putString("languageToLoad",languageToLoad );
editor.commit();
and use the same code in every activity in onCreate() to load the languageToLoad from the SharedPreferences

This is an old question, but I'll answer it anyway :-)
You can extend Application class to apply Abol3z's solution on every Activity. Create class:
public class MyApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
String lang = preferences.getString("lang", "en");
Locale locale = new Locale(lang);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
}
}
And set MyApplication as application class in manifest:
<application
android:name=".MyApplication"
...
/>
You can set the lang value (in your spinner):
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getContext());
preferences.edit().putString("lang", "en").commit();

Use SharedPreferences to keep track of the language the user chose, and then set the activities to use that language in the onCreate (), and maybe onResume() method. This way it will persist across app restarts etc.

btnChange.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mContext);
//preferences.edit().putString("lang", "bn").commit();
String lang = preferences.getString("lang", "en");
//Log.e("lang", "lang in Main Activity:"+lang);
if (lang.equalsIgnoreCase("en")){
setLocale("bn");
preferences.edit().putString("lang", "bn").commit();
btnChange.setText("Eng");
}else if(lang.equalsIgnoreCase("bn")){
setLocale("en");
preferences.edit().putString("lang", "en").commit();
btnChange.setText("বাংলা");
}
}
});
public void setLocale(String lang) {
myLocale = new Locale(lang);
Resources res = getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
conf.locale = myLocale;
res.updateConfiguration(conf, dm);
Intent refresh = new Intent(this, MainActivity.class);
startActivity(refresh);
finish();
}
we use two language for test purpose. keep all string in different folder named values and values-bn.

Related

How to Refresh App with onConfigChanges without loosing instance

protected void onResume() {
super.onResume();
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
Configuration config = getBaseContext().getResources().getConfiguration();
String lang = settings.getString("lang_list", "");
// Log.d("Lang",lang);
if (!"".equals(lang) && !config.locale.getLanguage().equals(lang)) {
recreate();
Locale locale = new Locale(lang);
Locale.setDefault(locale);
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
}
if (AppController.getInstance().isPreferenceChanged()) {
setupViewPager(viewPager);
adapter.notifyDataSetChanged();
}
}
I want to change the app language without recreate the app. I mean I want to do it when user select any language from the setting then it Should change the Setting Activity language without using recreate();, because when I use recreate(); it blinks the App once.
So I am not using recreate();. Instead I wrote below code in Setting Activity in AndroidManifest.xml
<activity
android:name=".activity.SettingsActivity"
android:label="#string/title_activity_settings"
android:configChanges="orientation|keyboardHidden|screenSize|locale|layoutDirection"/>
As in below screenshot you can see that I have selected "Hindi" for the language but it is not updating the Activity to Hindi. I mean "Select Country", "Select Your Language" and "Select Categories" should be display in Hindi instead of English. I have wrote String in both languages.
Can Anybody know How to change it when Change the language ?
OR
Why onConfigChanges is not working for locale as it is working for Orientation.
Thank you !
In your MainActivity call sharedPrefrences on onStart callback insted of calling in onCreate
Example:-
protected void onStart() {
SharedPreferences sharedPreferences = this.getSharedPreferences("selectedLanguage", Context.MODE_PRIVATE);
String pine = sharedPreferences.getString("language", DEFAULT);
String languageToLoad = pine;
Locale locale = new Locale(languageToLoad);//Set Selected Locale
Locale.setDefault(locale);//set new locale as default
Configuration config = new Configuration();//get Configuration
config.locale = locale;//set config locale as selected locale
this.getResources().updateConfiguration(config, this.getResources().getDisplayMetrics());
invalidateOptionsMenu(); //This changes language in OptionsMenu too
setTitle(R.string.app_name); //calling app name according to language selected by user
super.onStart();
}
You can use a singleton class that will handle the language change without restarting the activity,
public class MyApplication extends Application
{
private Locale locale = null;
#Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
if (locale != null)
{
newConfig.locale = locale;
Locale.setDefault(locale);
getBaseContext().getResources().updateConfiguration(newConfig, getBaseContext().getResources().getDisplayMetrics());
}
}
#Override
public void onCreate()
{
super.onCreate();
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
Configuration config = getBaseContext().getResources().getConfiguration();
String lang = settings.getString(getString(R.string.pref_locale), "");
if (! "".equals(lang) && ! config.locale.getLanguage().equals(lang))
{
locale = new Locale(lang);
Locale.setDefault(locale);
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
}
}
}

Android - Change app locale manually on button click

I want to change the application's Locale (language) to change programmatically when user wants to switch between Hindi and English using change language button.
I have a code to change language in place but it works only when I call in in the onCreate() of an activity before setContentView() method.
Any help is much appreciated.
See here my answer
Android Font in more then one langauge on single screen
for example if you want your application to support both English
and Arabic strings (in addition to the default strings),
you can simply create two additional
resource directories called /res/values-en (for the English strings.xml) and
/res/values-ar (for the Arabic strings.xml).
Within the strings.xml files, the
resource names are the same.
For example, the /res/values-en/strings.xml file could
look like this:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello in English!</string>
</resources>
Whereas, the /res/values-ar/strings.xml file would look like this:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">مرحبا في اللغة الإنجليزية</string>
</resources>
also , the /res/values-ur_IN/strings.xml file would look like this for urdu:
ur_IN for india ur_PK for pakisthan
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">انگریزی میں خوش!!</string>
</resources>
A default layout file in the /res/layout directory that displays the string refers to the
string by the variable name #string/hello, without regard to which language or directory
the string resource is in.
The Android operating system determines which version of
the string (French, English, or default) to load at runtime.A layout with a TextView control
to display the string might look like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="#string/hello" >
</LinearLayout>
The string is accessed programmatically in the normal way:
String str = getString(R.string.hello);
For change the language you need to like that change lang..
btn_english.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Locale locale = new Locale("en");
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
Toast.makeText(this, getResources().getString(R.string.lbl_langSelectEnglis), Toast.LENGTH_SHORT).show();
}
});
btn_arbice.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Locale locale = new Locale("ar");
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
Toast.makeText(this, getResources().getString(R.string.lbl_langSelecURdu), Toast.LENGTH_SHORT).show();
}
});
btn_urdu.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Locale locale = new Locale("ur_IN");
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
Toast.makeText(HomeActivity.this, getResources().getString(R.string.lbl_langSelectEnglis), Toast.LENGTH_SHORT).show();
}
});
Try this function when click button.
public void changeLocale()
{
Resources res = getResources();
// Change locale settings in the app.
DisplayMetrics dm = res.getDisplayMetrics();
android.content.res.Configuration conf = res.getConfiguration();
conf.locale = new Locale("hi_IN");
res.updateConfiguration(conf, dm);
setContentView(R.layout.xxx);
}
Use SharedPrefrences to save the user prefrences and call locale in onStart() not on onCreate(). This worked fine for me
Define DEFAULT value, so that your app wont cash
public static final String Default="en"; //so if value isn't found then english language will be used.
protected void onStart() {
SharedPreferences sharedPreferences = this.getSharedPreferences("selectedLanguage", Context.MODE_PRIVATE);
String pine = sharedPreferences.getString("language", DEFAULT);
String languageToLoad = pine;
Locale locale = new Locale(languageToLoad);//Set Selected Locale
Locale.setDefault(locale);//set new locale as default
Configuration config = new Configuration();//get Configuration
config.locale = locale;//set config locale as selected locale
this.getResources().updateConfiguration(config, this.getResources().getDisplayMetrics());
invalidateOptionsMenu();
setTitle(R.string.app_name);
super.onStart();
}
Where I set sharedPrefrences value to hindi or english as per user choice. I used switch in this case. below you can see code.
aSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if (aSwitch.isChecked()) {
SharedPreferences hisharedPreferences = getSharedPreferences("selectedLanguage", Context.MODE_PRIVATE);
SharedPreferences.Editor hieditor = npsharedPreferences.edit();
npeditor.putString("language","hi");
npeditor.commit();
aSwitch.setChecked(true);
Toast.makeText(Settings.this, "Hindi Language Selected", Toast.LENGTH_LONG).show();
} else {
SharedPreferences ensharedPreferences = getSharedPreferences("selectedLanguage", Context.MODE_PRIVATE);
SharedPreferences.Editor eneditor = ensharedPreferences.edit();
eneditor.putString("language","en");
eneditor.commit();
Toast.makeText(Settings.this, "English Language Selected", Toast.LENGTH_LONG).show();
aSwitch.setChecked(false);
}
}
});
Hope this helped!! Feel free to ask me if you got stuck in any step!!
You can refresh activity as below sample to change user interface after updating locale language of app on click of button:
OnButtonClicked(){
//it will check for android version.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return updateResources(context, language);
}
return updateResourcesLegacy(context, language);
}
//after setting language it will update ui
refreshActivity();
}
public void refreshActivity() throws Exception {
try {
// refresh activity for language changes
Intent intent = getIntent();
YOUR_ACTIVITY_NAME.this.finish();
System.out.println("activity finished");
startActivity(intent);
System.out.println("starting activity");
} catch (Exception e) {
Log.d("RegistrationForm", "application crashed...");
e.printStackTrace();
}
}
#TargetApi(Build.VERSION_CODES.N)
private static Context updateResources(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Configuration configuration = context.getResources().getConfiguration();
configuration.setLocale(locale);
configuration.setLayoutDirection(locale);
context.getResources().updateConfiguration(configuration,
context.getResources().getDisplayMetrics());
return context.createConfigurationContext(configuration);
}
#SuppressWarnings("deprecation")
private static Context updateResourcesLegacy(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
configuration.locale = locale;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
configuration.setLayoutDirection(locale);
}
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
return context;
}
Complete Steps:
On button click check Android Version if Android version is below N then it will execute legacy code for locale language change that is updateResourcesLegacy. Else if Android Version is N or above N then it will execute updateResources() method.
After setting language refresh activity by calling refreshActivity() method, this method will update the user interface.

Use custom locale for plurals

I am trying to override the locale to use Czech locale no matter what is set in the phone. However, although when I try to get the current locale, it returns czech, but for plurals, it acts like it still takes the real phone locale.
Here is my code:
<application
android:name=".xxx"
android:allowBackup="true"
android:icon="#drawable/logo"
android:label="#string/app_name"
android:theme="#style/Theme.mystyle"
android:configChanges="locale"
>
In application:
String lang = settings.getString("cs", "");
locale = new Locale(lang);
Locale.setDefault(locale);
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
I posted on GitHub simple LocaleAssistant class I just tested with plurals for Slovak and also Czech language, and it worked on the device with default locale set to EN. Just call those two methods from within your custom Application on the member instance of LocaleAssistant.
In the end I found the correct solution. Gray Wolf's solution did not work for me for some reason. Maybe it is all about the API level you develop your app for.
This is the working code. Besides that, it is also necessary to add configChanges:locale to AndroidManifest. This should work on Android 4.0.1 and above.
public class MyApplication extends Application
{
private Locale locale = null;
#Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
if (locale != null)
{
newConfig.locale = locale;
Locale.setDefault(locale);
getBaseContext().getResources().updateConfiguration(newConfig, getBaseContext().getResources().getDisplayMetrics());
}
}
#Override
public void onCreate()
{
super.onCreate();
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
Configuration config = getBaseContext().getResources().getConfiguration();
String lang = "cs";
if (!"".equals(lang) && !config.locale.getLanguage().equals(lang))
{
locale = new Locale(lang);
Locale.setDefault(locale);
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
}
}
}

Android - App locale changes and displayed orientation

I'm having a headache with the locale thing in my app. So basically my app supports two languages, English and Vietnamese, and user can choose to change the language to be displayed. So I have a SettingActivity like this:
public class SettingsActivity extends SherlockPreferenceActivity implements OnPreferenceChangeListener{
private ListPreference langPref;
private SharedPreferences languagepref;
private String language;
private Locale locale;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
languagepref = PreferenceManager.getDefaultSharedPreferences(this);
Configuration config = getBaseContext().getResources().getConfiguration();
language = languagepref.getString("languageToLoad","en");
locale = new Locale(language);
Locale.setDefault(locale);
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
addPreferencesFromResource(R.xml.preferences_login);
langPref = (ListPreference) findPreference("lang_pref");
if (language.equalsIgnoreCase("vi")){
langPref.setValueIndex(1);
}
else{
langPref.setValueIndex(0);
}
langPref.setOnPreferenceChangeListener(this);
}
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
String key = preference.getKey();
if (key.equals("lang_pref")){
String languageToLoad = (String) newValue;
Locale locale = new Locale(languageToLoad);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
SharedPreferences.Editor editor = languagepref.edit();
editor.putString("languageToLoad",languageToLoad );
editor.commit();
recreate();
}
return false;
}
}
In every other activity, I add this in their onCreate method:
SharedPreferences languagepref = PreferenceManager.getDefaultSharedPreferences(this);
Configuration config = getBaseContext().getResources().getConfiguration();
String language = languagepref.getString("languageToLoad","en");
Locale locale = new Locale(language);
Locale.setDefault(locale);
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
And now my app is acting weird: in the SettingActivity, the language is displayed properly whenever I rotate my device, even without the need of adding android:configChanges="locale" in the activity's manifest. However, in every other activity, the language is changed back to English when I rotate the device. I've try adding android:configChanges="locale" in their manifest but it doesn't work. Also, I've tried every solution found on Stackoverflow but none of them works for me, so I'm basically clueless now. Could anyone of you help me point out the mistake I made here? Please do and thanks in advance.
Try adding
android:configChanges="orientation|keyboard|keyboardHidden"
in the manifest for each activity.
Then you should override onConfigurationChanged in your activities, and in this method reload layout (depending orientation). If you still have problems with locale, reload the appropriate locale in onConfigurationChanged.

Change the locale at runtime?

We have an Android app that functions as a client for a remote PC program. We'd like to add a feature so the PC can instruct the Android app to change its locale at runtime, i.e., start the app; put it in communication with the PC; sometime later the PC tells the app to switch to, say, Spanish or Chinese.
We already have all the layout and string resources set up for their respective locales. Our app is the only app the user sees so it doesn't matter if the rest of the device stays in English.
There is another thread on this at Change language programmatically in Android but it doesn't seem to reach a conclusion.
I can put . . .
Locale locale = new Locale(sTheNewLocale);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
. . . in onCreate() before the setContentView() but that doesn't really help if I want to change the locale after my screen is up and running. Is there a way to REload the content view after the Activity is already running? So is there any practical way to change locales on-the-fly reliably or do I have to tell my boss it can't be done except for setting the whole device to the new locale before starting the app?
Since API 11 you can use recreate so can make this method in your activity:
private void restartInLocale(Locale locale)
{
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
Resources resources = getResources();
resources.updateConfiguration(config, resources.getDisplayMetrics());
recreate();
}
You can start a new instance of your activity and exit the old one. Here is a full (untested) example how you can store any desired language and restart your app. You just need to call restartInLanguage with your prefered language.
public class YourMainActivity extends Activity {
private static final String APP_SHARED_PREFS = "com.example.test";
private SharedPreferences settings;
private Editor editor;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
settings=getSharedPreferences(APP_SHARED_PREFS, Activity.MODE_PRIVATE);
editor=settings.edit();
Locale locale = new Locale(settings.getString("lang", "default-lang"));
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getResources().updateConfiguration(config, getResources().getDisplayMetrics());
// your stuff...
}
public void restartInLanguage(String lang) {
editor.putString("lang", lang);
editor.commit();
Intent intent = getIntent();
finish();
startActivity(intent);
}
// ...
}
I have combined #weston and #rekire (both +1) and extendet it to handle this use-case:
ActivityA => ActivityB => SettingsActivity-changeLocale
After changeLocale in SettingsActivity the parent activities ActivityA and ActivityB should also be recreated to reflect the new locale.
My solution: ActivityA and ActivityB inherit from LocalizedActivity which checks in onResume if the locale has changed and trigger a recreate() if necessary
So every activity that inherits from LocalizedActivity automatically handles app specific locale change.
/**
* An activity that can change the locale (language) of its content.
*
* Inspired by http://stackoverflow.com/questions/13181847/change-the-locale-at-runtime
*
* Created by k3b on 07.01.2016.
*/
public class LocalizedActivity extends Activity {
/** if myLocale != Locale.Default : activity must be recreated in on resume */
private Locale myLocale = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
fixLocale(this);
super.onCreate(savedInstanceState);
}
#Override
protected void onResume() {
super.onResume();
// Locale has changed by other Activity ?
if ((myLocale != null) && (myLocale.getLanguage() != Locale.getDefault().getLanguage())) {
myLocale = null;
recreate();
}
}
/**
* Set Activity-s locale to SharedPreferences-setting.
* Must be called before onCreate
* #param context
*/
public static void fixLocale(Context context)
{
final SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(context);
String language = prefs.getString(Global.PREF_KEY_USER_LOCALE, "");
Locale locale = Global.systemLocale; // in case that setting=="use android-locale"
if ((language != null) && (!language.isEmpty())) {
locale = new Locale(language); // overwrite "use android-locale"
}
if (locale != null) {
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
Resources resources = context.getResources();
resources.updateConfiguration(config, resources.getDisplayMetrics());
// recreate();
if (context instanceof LocalizedActivity) {
((LocalizedActivity) context).myLocale = locale;
}
}
}
}
Here is the source of LocalizedActivity.java and SettingsActivity.java that are used in my A Photo Manager project
The solution is to use setContentView and controlLanguage (you can also call this method from a Global class) methods in EVERY activity in onResume method after setting your locale.
Example:
#Override
public void onClick(View v) {
SharedPreferences.Editor editor;
editor = sharedPref.edit();
Configuration config = new Configuration(getBaseContext().getResources().getConfiguration());
String language = "";
switch (v.getId()){
case R.id.turkceButton:
editor.putString("language", "tr");
language="tr";
break;
case R.id.englishButton:
editor.putString("language", "en");
language="en";
break;
}
Locale locale = new Locale(language);
Locale.setDefault(locale);
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
editor.commit();
#Override
protected void onResume() {
super.onResume();
controlLanguage(getApplicationContext(), getResources());
setContentView(R.layout.main);
}
public void controlLanguage(Context context, Resources res){
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context);
String language = sharedPref.getString("language","en");
Locale locale = new Locale(language);
Locale.setDefault(locale);
res.getConfiguration().locale = locale;
res.updateConfiguration(res.getConfiguration(), res.getDisplayMetrics());
}

Categories

Resources