Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing Locale within the app itself

My users can change the Locale within the app (they may want to keep their phone settings in English but read the content of my app in French, Dutch or any other language ...)

Why is this working perfectly fine in 1.5/1.6 but NOT in 2.0 anymore ???

@Override public boolean onOptionsItemSelected(MenuItem item) {     switch(item.getItemId()) {     case 201:         Locale locale2 = new Locale("fr");          Locale.setDefault(locale2);         Configuration config2 = new Configuration();         config2.locale = locale2;         getBaseContext().getResources().updateConfiguration(             config2, getBaseContext().getResources().getDisplayMetrics());         // loading data ...         refresh();         // refresh the tabs and their content         refresh_Tab ();         break;      case 201: etc... 

The problem is that the MENU "shrinks" more and more everytime the user is going through the lines of code above ...

This is the Menu that gets shrunk:

@Override public boolean onCreateOptionsMenu(Menu menu) {     menu.add(0, 100, 1, "REFRESH").setIcon(android.R.drawable.ic_menu_compass);     SubMenu langMenu = menu.addSubMenu(0, 200, 2, "NL-FR").setIcon(android.R.drawable.ic_menu_rotate);         langMenu.add(1, 201, 0, "Nederlands");         langMenu.add(1, 202, 0, "Français");     menu.add(0, 250, 4, R.string.OptionMenu2).setIcon(android.R.drawable.ic_menu_send);     menu.add(0, 300, 5, R.string.OptionMenu3).setIcon(android.R.drawable.ic_menu_preferences);     menu.add(0, 350, 3, R.string.OptionMenu4).setIcon(android.R.drawable.ic_menu_more);     menu.add(0, 400, 6, "Exit").setIcon(android.R.drawable.ic_menu_delete);      return super.onCreateOptionsMenu(menu); } 

What should I do in API Level 5 to make this work again ?

HERE IS THE FULL CODE IF YOU WANT TO TEST THIS :

import java.util.Locale;  import android.app.Activity; import android.content.res.Configuration; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.SubMenu; import android.widget.Toast;  public class Main extends Activity {     /** Called when the activity is first created. */       @Override     public void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.main);      }      @Override     public boolean onCreateOptionsMenu(Menu menu) {          SubMenu langMenu = menu.addSubMenu(0, 200, 2, "NL-FR").setIcon(android.R.drawable.ic_menu_rotate);             langMenu.add(1, 201, 0, "Nederlands");             langMenu.add(1, 202, 0, "Français");          return super.onCreateOptionsMenu(menu);     }      @Override     public boolean onOptionsItemSelected(MenuItem item) {         switch(item.getItemId()){          case 201:              Locale locale = new Locale("nl");              Locale.setDefault(locale);             Configuration config = new Configuration();             config.locale = locale;             getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());             Toast.makeText(this, "Locale in Nederlands !", Toast.LENGTH_LONG).show();             break;          case 202:              Locale locale2 = new Locale("fr");              Locale.setDefault(locale2);             Configuration config2 = new Configuration();             config2.locale = locale2;             getBaseContext().getResources().updateConfiguration(config2, getBaseContext().getResources().getDisplayMetrics());              Toast.makeText(this, "Locale en Français !", Toast.LENGTH_LONG).show();             break;            }         return super.onOptionsItemSelected(item);     } } 

AND HERE IS THE MANIFEST :

<?xml version="1.0" encoding="utf-8"?>     <manifest xmlns:android="http://schemas.android.com/apk/res/android"           package="com.cousinHub.ChangeLocale"           android:versionCode="1"           android:versionName="1.0">         <application android:icon="@drawable/icon" android:label="@string/app_name">             <activity android:name=".Main"                       android:label="@string/app_name">                 <intent-filter>                     <action android:name="android.intent.action.MAIN" />                     <category android:name="android.intent.category.LAUNCHER" />                 </intent-filter>             </activity>         </application>         <uses-sdk android:minSdkVersion="3" />      </manifest> 

THIS IS WHAT I FOUND :

<uses-sdk android:minSdkVersion="5" /> 

=> IT WORKS JUST FINE ...

<uses-sdk android:minSdkVersion="3" /> 

=> Menu shrinks every time you change the locale !!!

as I want to keep my application accessible for users on 1.5, what should I do ??

like image 474
Hubert Avatar asked Feb 15 '10 09:02

Hubert


People also ask

How do I change my locale application?

Go to app > res > values > right-click > New > Value Resource File and name it as strings. Now, we have to choose qualifiers as Locale from the available list and select the language as Hindi from the drop-down list. Below is the picture of the steps to be performed. Now, In this resource file string.

How do I change the default locale in Android?

Configuration config = new Configuration(); config. locale = selectedLocale; // set accordingly // eg. if Hindi then selectedLocale = new Locale("hi"); Locale.

What is locale Android?

A Locale object represents a specific geographical, political, or cultural region. An operation that requires a Locale to perform its task is called locale-sensitive and uses the Locale to tailor information for the user.


2 Answers

Through the original question is not exactly about the locale itself all other locale related questions are referencing to this one. That's why I wanted to clarify the issue here. I used this question as a starting point for my own locale switching code and found out that the method is not exactly correct. It works, but only until any configuration change (e.g. screen rotation) and only in that particular Activity. Playing with a code for a while I have ended up with the following approach:

I have extended android.app.Application and added the following code:

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());         }     } } 

This code ensures that every Activity will have custom locale set and it will not be reset on rotation and other events.

I have also spent a lot of time trying to make the preference change to be applied immediately but didn't succeed: the language changed correctly on Activity restart, but number formats and other locale properties were not applied until full application restart.

Changes to AndroidManifest.xml

Don't forget to add android:configChanges="layoutDirection|locale" to every activity at AndroidManifest, as well as the android:name=".MyApplication" to the <application> element.

like image 119
Andrey Novikov Avatar answered Oct 20 '22 14:10

Andrey Novikov


After a good night of sleep, I found the answer on the Web (a simple Google search on the following line "getBaseContext().getResources().updateConfiguration(mConfig, getBaseContext().getResources().getDisplayMetrics());"), here it is :

link text => this link also shows screenshots of what is happening !

Density was the issue here, I needed to have this in the AndroidManifest.xml

<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true" /> 

The most important is the android:anyDensity =" true ".

Don't forget to add the following in the AndroidManifest.xml for every activity (for Android 4.1 and below):

android:configChanges="locale" 

This version is needed when you build for Android 4.2 (API level 17) explanation here:

android:configChanges="locale|layoutDirection" 
like image 34
Hubert Avatar answered Oct 20 '22 16:10

Hubert