views:

197

answers:

3

I would like to change language (locale of application) programmatically.

The main problem for me is updating menu labels.

I tried the following method:

 @Override
public boolean onMenuOpened(int featureId, Menu menu) {
    if (shouldChangeMenuLabels) {
        for (int i = 0; i < menu.size(); i++) {
            MenuItem menuItem = menu.getItem(i);
            switch (menuItem.getItemId()) {
                case R.id.menu_main_about:
                    menuItem.setTitle(R.string.menu_about);
                    break;
                case R.id.menu_main_preferences:
                    menuItem.setTitle(R.string.menu_prefs);
                    break;
            }
        }
        shouldChangeMenuLabels = false;
    }

But I'm sure it bad idea. I want to avoid using switch-case statement as this is not universal method (I can't simply port the snipped to other activities / I can't make abstract class which would do that).


BTW, all menus have been described into menu/*.xml files so I don't want duplicating the code. Anybody has ideas?

Concerned to first answer: I hae changed locale with the following code:

            Locale locale = new Locale((String)newValue);
            Locale.setDefault(locale);
            Configuration config = new Configuration();
            config.locale = locale;
            getApplication().getResources().updateConfiguration(config, getApplication().getResources().getDisplayMetrics());

But as I want to control rotating for each activity, they are never finished. Maybe I did something wrong?

A: 

Have you read through the documentation on Android Localization? Typically you create a different strings file for each language/locale that you want to support. In your menu.xml file you can reference the string id's, and the proper value will be selected based on the current locale settings.

Mayra
I did it. (I mean values-xx/string.xml and values/string.xml). Do you mean to create menu-xx/mymenu.xml ?
davs
So you have values-xx/string.xml with a string, menu_about, and values-yy/string.xml with a string, menu_about. You set the locale of your phone to that of yy, and the string value does not change to yy? Which locales are you testing with? http://developer.android.com/guide/topics/resources/providing-resources.html#BestMatch talks about how it decides which value to use, you might not have your locale configured correctly.
Mayra
I'm testing with en/ru locales. But As I didn't destroy activities, menu hasn't been updated. So, I decided to clear menu and create it from the scratch
davs
Ah, ok, so if you totally exit the activity and come back in, then it is correct, but you want it to update while sitting on it? It sounds like your system of refreshing the menu on locale change would make sense then.
Mayra
I have main screen with menu and preferences page. On preferences page I'm have option to change locale. The snippet of changing locale I posted into question.Lifecycle: starting main screen with correspond locale --> open preferences screen (but main screen hasn't been finished) --> changing locale --> returning to non-finished main screens (method onResume calls for main screen). And I need to refresh menu if it needs
davs
A: 

menu.add(0, MENU_ABOUT, 0, _mContext.getResources().getString(R.string.mymenu)).setIcon(R.drawable.ic_menu);

While creating menu insert you string and localize it.

Eby
As I know menu creates only ones for each activity due its lifecycle. I have no problem with localization due creating .. I have problem when menu has been created, then I've change locale of application and I want to reload menu (maybe destroy it and create it again. But I don't know how to destroy it)
davs
you can use shared preference and change it on each selection of your menu item if (preferences.getBoolean("Sound", true)) { menu.add(0, MENU_SOUND, 0, "Sound").setIcon(R.drawable.on); } else { menu.add(0, MENU_SOUND, 0, "Sound").setIcon(R.drawable.off); }
Eby
I don't want to create menu such way as I believe its a bad practice
davs
A: 

I don't know is it a good idea, but I've found following way:

 @Override
public boolean onMenuOpened(int featureId, Menu menu) {
    if (shouldChangeLocale) {
        menu.clear();
        MenuInflater inflater = getMenuInflater(); // -->onCreateMenu (Menu) 
        inflater.inflate(R.menu.menu_main, menu);  // /
        shouldChangeLocale=false;
    }

    return super.onMenuOpened(featureId, menu);
}

I need your advice, should I do this such way?

davs