Изменение языка в самом приложении

Мои пользователи могут изменить Locale в приложении (они могут захотеть сохранить свои настройки телефона на английском языке, но прочитать содержимое моего приложения на французском, голландском или любом другом языке …)

Почему это работает отлично в 1.5 / 1.6, но НЕ в 2.0 больше ???

@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... 

Проблема в том, что МЕНЮ «сжимается» все больше и больше каждый раз, когда пользователь проходит строки кода выше …

Это меню, которое сокращается:

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

Что я должен сделать в API Level 5, чтобы сделать эту работу еще раз?

ЗДЕСЬ – ПОЛНЫЙ КОД, ЕСЛИ ВЫ ХОТИТЕ ИСПЫТАТЬ ЭТО:

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

И ЗДЕСЬ МАНЖЕТ:

 <?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> ? <?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> 

ЭТО ЧТО Я НАЙТИ:

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

=> ЭТО РАБОТАЕТ ТОЛЬКО ПЯТЬ …

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

=> Меню сжимается каждый раз, когда вы меняете язык!

Как я хочу, чтобы мое приложение было доступно для пользователей на 1,5, что мне делать?

Solutions Collecting From Web of "Изменение языка в самом приложении"

В оригинальном вопросе речь идет не только о самой локали, все другие вопросы, связанные с локальностью, ссылаются на этот вопрос. Вот почему я хотел прояснить этот вопрос. Я использовал этот вопрос в качестве отправной точки для своего кода переключения локалей и выяснил, что метод не совсем корректен. Он работает, но только до тех пор, пока не произойдет изменение конфигурации (например, вращение экрана) и только в этом конкретном действии. Играя с кодом на некоторое время, я получил следующий подход:

Я расширил android.app.Application и добавил следующий код:

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

Этот код гарантирует, что каждое действие будет иметь пользовательский набор локалей, и он не будет сброшен при вращении и других событиях.

Я также потратил много времени, пытаясь немедленно применить изменение предпочтений, но не получилось: язык правильно изменился при перезагрузке активности, но числовые форматы и другие языковые свойства не были применены до полного перезапуска приложения.

Изменения в AndroidManifest.xml

Не забудьте добавить android:configChanges="layoutDirection|locale" к каждому действию в AndroidManifest, а также android:name=".MyApplication" в элемент <application> .

После хорошей ночи сна я нашел ответ в Интернете (простой поиск Google в следующей строке: getBaseContext().getResources().updateConfiguration(mConfig, getBaseContext().getResources().getDisplayMetrics()); ), вот :

Link text => эта ссылка также показывает screenshots того, что происходит!

Плотность была проблема здесь , мне нужно было это в AndroidManifest.xml

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

Самым важным является андроид: anyDensity = "true" .

Не забудьте добавить следующее в AndroidManifest.xml для каждого действия (для Android 4.1 и ниже):

 android:configChanges="locale" 

Эта версия необходима, когда вы создаете объяснение для Android 4.2 (API уровня 17) здесь :

 android:configChanges="locale|layoutDirection" 

В Android M главное решение не будет работать. Я написал вспомогательный класс, чтобы исправить то, что вы должны вызывать из своего класса приложения и всех действий (я бы предложил создать BaseActivity, а затем сделать все Наследование наследованием от него.

Примечание . Это также будет поддерживать правильное расположение макета RTL.

Класс помощника:

 public class LocaleUtils { private static Locale sLocale; public static void setLocale(Locale locale) { sLocale = locale; if(sLocale != null) { Locale.setDefault(sLocale); } } public static void updateConfig(ContextThemeWrapper wrapper) { if(sLocale != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { Configuration configuration = new Configuration(); configuration.setLocale(sLocale); wrapper.applyOverrideConfiguration(configuration); } } public static void updateConfig(Application app, Configuration configuration) { if (sLocale != null && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { //Wrapping the configuration to avoid Activity endless loop Configuration config = new Configuration(configuration); // We must use the now-deprecated config.locale and res.updateConfiguration here, // because the replacements aren't available till API level 24 and 17 respectively. config.locale = sLocale; Resources res = app.getBaseContext().getResources(); res.updateConfiguration(config, res.getDisplayMetrics()); } } } 

Заявка:

 public class App extends Application { public void onCreate(){ super.onCreate(); LocaleUtils.setLocale(new Locale("iw")); LocaleUtils.updateConfig(this, getBaseContext().getResources().getConfiguration()); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); LocaleUtils.updateConfig(this, newConfig); } } 

BaseActivity:

 public class BaseActivity extends Activity { public BaseActivity() { LocaleUtils.updateConfig(this); } } 

Это для моего комментария к ответу Андрея, но я не могу включить код в комментарии.

Вы отвлекаете себя от основной деятельности? Вы можете разместить это в своём резюме …

 @Override protected void onResume() { if (!(PreferenceManager.getDefaultSharedPreferences( getApplicationContext()).getString("listLanguage", "en") .equals(langPreference))) { refresh(); } super.onResume(); } private void refresh() { finish(); Intent myIntent = new Intent(Main.this, Main.class); startActivity(myIntent); } 

Я не мог использовать андроид: anyDensity = "true", потому что объекты в моей игре были бы совершенно разными … кажется, это тоже делает трюк:

 // создание локали
 Locale locale2 = новый Locale (loc); 
 Locale.setDefault (locale2);
 Конфигурация config2 = new Configuration ();
 Config2.locale = locale2;

 // обновление локали
 MContext.getResources (). UpdateConfiguration (config2, null);

Если вы хотите немедленно изменить параметры меню для изменения локали. Вы должны сделать это.

 //onCreate method calls only once when menu is called first time. public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); //1.Here you can add your locale settings . //2.Your menu declaration. } //This method is called when your menu is opend to again.... @Override public boolean onMenuOpened(int featureId, Menu menu) { menu.clear(); onCreateOptionsMenu(menu); return super.onMenuOpened(featureId, menu); }