Как изменить язык приложений Android O/Oreo/api 26
Я хочу изменить язык приложения, и это прекрасно работает до API 26.
Для api> 25 я поставил Locale.setDefault(Locale.Category.DISPLAY, mynewlanglocale);
перед setContentView(R.layout.activity_main);
но ничего не меняется.
Документы не слишком много объясняют по этому поводу.
Ответы
Ответ 1
Да, в Android Oreo локализация не работает нормально с обновлением конфигурации. Но это устарело в самом Android N. Вместо updateconfiguration используйте createconfiguration в каждом attachcontext. это работает нормально для меня. Попробуй это...
В вашей деятельности добавить это..
@Override
protected void attachBaseContext(Context newBase) {
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) {
super.attachBaseContext(MyContextWrapper.wrap(newBase, "ta"));
}
else {
super.attachBaseContext(newBase);
}
}
В MyContextWrapper.java
public static ContextWrapper wrap(Context context, String language) {
Resources res = context.getResources();
Configuration configuration = res.getConfiguration();
Locale newLocale = new Locale(language);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
configuration.setLocale(newLocale);
LocaleList localeList = new LocaleList(newLocale);
LocaleList.setDefault(localeList);
configuration.setLocales(localeList);
context = context.createConfigurationContext(configuration);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
configuration.setLocale(newLocale);
context = context.createConfigurationContext(configuration);
} else {
configuration.locale = newLocale;
res.updateConfiguration(configuration, res.getDisplayMetrics());
}
return new ContextWrapper(context);
}
Ответ 2
У меня была та же проблема: начиная с Android 8. 0+ некоторые части моего приложения больше не меняли свой язык. Мне помогает обновление контекста приложения и активности. Вот пример функции MainActivity:
private void setApplicationLanguage(String newLanguage) {
Resources activityRes = getResources();
Configuration activityConf = activityRes.getConfiguration();
Locale newLocale = new Locale(newLanguage);
activityConf.setLocale(newLocale);
activityRes.updateConfiguration(activityConf, activityRes.getDisplayMetrics());
Resources applicationRes = getApplicationContext().getResources();
Configuration applicationConf = applicationRes.getConfiguration();
applicationConf.setLocale(newLocale);
applicationRes.updateConfiguration(applicationConf,
applicationRes.getDisplayMetrics());
}
Ответ 3
updateConfiguration
устарел, и вы должны использовать createConfigurationContext
. Я решил это так:
@Override
protected void attachBaseContext(Context newBase) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Configuration config = newBase.getResources().getConfiguration();
//Update your config with the Locale i. e. saved in SharedPreferences
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(newBase);
String language = prefs.getString(SP_KEY_LANGUAGE, "en_US");
Locale.setDefault(locale);
config.setLocale(new Locale(language));
newBase = newBase.createConfigurationContext(config);
}
super.attachBaseContext(newBase);
}
Ответ 4
Обновлено для всех версий Android до Oreo
Создайте класс, подобный этому
public class LocaleUtils {
@Retention(RetentionPolicy.SOURCE)
@StringDef({ENGLISH, FRENCH, SPANISH})
public @interface LocaleDef {
String[] SUPPORTED_LOCALES = {ENGLISH, FRENCH, SPANISH};
}
public static final String ENGLISH = "en";
public static final String FRENCH = "fr";
public static final String SPANISH = "es";
public static void initialize(Context context) {
setLocale(context, ENGLISH);
}
public static void initialize(Context context, @LocaleDef String defaultLanguage) {
setLocale(context, defaultLanguage);
}
public static boolean setLocale(Context context, @LocaleDef String language) {
return updateResources(context, language);
}
private static boolean updateResources(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
context.createConfigurationContext(configuration);
configuration.locale = locale;
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
return true;
}
}
Теперь, когда вы выбираете язык из своего приложения, сохраните код языка в разделе "Общие предпочтения", как показано ниже
private static SharedPreferences getDefaultSharedPreference(Context context) {
if (PreferenceManager.getDefaultSharedPreferences(Application.getInstance().getApplicationContext()) != null)
return PreferenceManager.getDefaultSharedPreferences(Application.getInstance().getApplicationContext());
else
return null;
}
public static void setSelectedLanguageId(String id){
final SharedPreferences prefs = getDefaultSharedPreference(Application.getInstance().getApplicationContext());
SharedPreferences.Editor editor = prefs.edit();
editor.putString("app_language_id", id);
editor.apply();
}
public static String getSelectedLanguageId(){
return getDefaultSharedPreference(Application.getInstance().getApplicationContext())
.getString("app_language_id", "en");
}
Эти три функции должны быть написаны внутри класса Utiltiy (ваши предпочтения). Затем, когда вы выбираете язык приложения из приложения, вызовите функцию setSelectedLanguageId() и передайте идентификатор языка в качестве параметра.
Таким образом, вы сохранили выбранный язык в своем приложении. Теперь в вашем классе приложения напишите функцию, подобную этой
public void initAppLanguage(Context context){
LocaleUtils.initialize(context, PreferenceUtil.getSelectedLanguageId() );
}
Здесь PreferenceUtil - мой класс Utiltiy. Вы должны заменить его на свою функцию класса утилит.
Вы также должны создать переменную в классе приложения
private static Application applicationInstance;
и в вашем методе класса приложения onCreate инициализируйте applicationInstance как контекст приложений, подобный этому
applicationInstance = this;
Теперь напишите функцию getter в классе приложения
public static synchronized Application getInstance() {
return applicationInstance;
}
И теперь, когда вы начинаете свое первое действие, вызовите этот метод в своей активности onCreate
Application.getInstance().initAppLanguage(this);
Помните, что мы передаем контекст активности функции initAppLanguage(), а не контексту приложения. Передача контекста приложения не заставит его работать в Oreo (по крайней мере для меня).
Поэтому, когда вы выбираете язык, попробуйте полностью перезапустить приложение.
Вы можете добиться этого с помощью
Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage(getBaseContext().getPackageName());
startActivity (я);
Надеюсь, это поможет вам!
Ответ 5
Возможно, однако я бы не рекомендовал программировать язык
Android разработан таким образом, что системный интерфейс и ваше приложение имеют один и тот же язык, если вы его программным образом измените, вы будете бороться с системой
Вместо этого вы можете активировать поддержку нескольких языков, добавив разные языки strings.xml, это автоматически изменит язык.
Я рекомендую прочитать эту статью Google Developers:
Поддержка разных языков и культур
Если вам действительно нужно изменить его программно, вы можете сделать следующее
Locale locale = new Locale("en");
Locale.setDefault(locale);
Configuration config = context.getResources().getConfiguration();
config.setLocale(locale);
context.createConfigurationContext(config);
context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());
В SDK >= 21 вам нужно вызвать "Resources.updateConfiguration()", иначе ресурсы не будут обновлены.
Надеюсь, что это поможет.
Ответ 6
Вот комплексное решение, работающее для kitkat, Lollipop, Marshmallow, Nougat и Oreo. Просто следуйте всем ниже.
Сначала создайте класс java, как показано ниже
import android.content.Context;
import android.content.res.Configuration;
import java.util.Locale;
public class LocaleUtils {
public static void updateConfig(Context mContext, String sLocale) {
Locale locale = new Locale(sLocale);
Locale.setDefault(locale);
Configuration config = mContext.getResources().getConfiguration();
config.locale = locale;
mContext.getResources().updateConfiguration(config,
mContext.getResources().getDisplayMetrics());
}
}
Теперь добавьте этот фрагмент на кнопку "Щелчок", где вы хотите изменить локаль
String lang="hi";//pass your language here
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mContext);
SharedPreferences.Editor editor = preferences.edit();
editor.clear();
editor.putString("lang", lang");
editor.putBoolean("langSelected", true);
editor.apply();
LocaleUtils.updateConfig(mContext,lang);
Intent intent = mContext.getIntent();
mContext.overridePendingTransition(0, 0);
mContext.finish();
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
mContext.overridePendingTransition(0, 0);
mContext.startActivity(intent);
Наконец, вставьте приведенный ниже код в действие Splash или в действие запуска.
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
String lang = preferences.getString("lang", "");
boolean langSelected = preferences.getBoolean("langSelected", false);
SharedPreferences.Editor editor = preferences.edit();
if (langSelected) {
editor.clear();
editor.putString("lang", lang);
editor.putBoolean("langSelected", true);
editor.apply();
LocaleUtils.updateConfig(this,lang);
} else {
LocaleUtils.updateConfig(this, Locale.getDefault().getLanguage());
editor.clear();
editor.putString("lang", Locale.getDefault().getLanguage());
editor.putBoolean("langSelected", false);
editor.apply();
}
Ответ 7
Вам нужно использовать getApplicationContext()
вместо getContext()
Ответ 8
После использования всех решений во всех источниках, наконец, я нашел свою проблему. Это злит меня на 2 дня.
Все знают, что в Android Oreo (API 26) мы должны использовать createConfigurationContext
, но моя проблема заключается в использовании названия страны с локальным.
замещать
en_US с en
ar_AE с ar
fa_IR с fa
И моя проблема решена.
Надеюсь помочь кому-нибудь