Можно ли программно изменить язык приложения, продолжая использовать ресурсы Android?
Если нет, можно ли запросить ресурс на определенном языке?
Я хочу, чтобы пользователь мог изменить язык приложения из приложения.
Можно ли программно изменить язык приложения, продолжая использовать ресурсы Android?
Если нет, можно ли запросить ресурс на определенном языке?
Я хочу, чтобы пользователь мог изменить язык приложения из приложения.
Возможно. Вы можете установить языковой стандарт. Однако я бы не рекомендовал этого. Мы пробовали это на ранних стадиях, это в основном борьба с системой.
У нас такое же требование к изменению языка, но мы решили ограничиться тем, что пользовательский интерфейс должен быть таким же, как пользовательский интерфейс телефона. Он работал через установку локали, но был слишком глючным. И вы должны устанавливать его каждый раз, когда входите в действие (каждое действие), исходя из моего опыта. вот код, если он вам все еще нужен (опять же, я не рекомендую)
Resources res = context.getResources();
// Change locale settings in the app.
DisplayMetrics dm = res.getDisplayMetrics();
android.content.res.Configuration conf = res.getConfiguration();
conf.setLocale(new Locale(language_code.toLowerCase())); // API 17+ only.
// Use conf.locale = new Locale(...) if targeting lower versions
res.updateConfiguration(conf, dm);
Если у вас есть контент для конкретного языка - вы можете изменить эту основу в настройках.
обновление 26 марта 2020 г.
public static void setLocale(Activity activity, String languageCode) {
Locale locale = new Locale(languageCode);
Locale.setDefault(locale);
Resources resources = activity.getResources();
Configuration config = resources.getConfiguration();
config.setLocale(locale);
resources.updateConfiguration(config, resources.getDisplayMetrics());
}
Activity
и строите действия своего приложения на основе этого подкласса. Что, по общему признанию, может быть непросто, если вы используете много предустановленных подклассов Android Activity
, но это не так много работы, как вы думаете.
- person JAB; 09.04.2014
Context.createConfigurationContext()
, который можно использовать для обертывания контекста по умолчанию с конфигурацией, зависящей от локали, а затем вызвать getResources
для этого без необходимости обновлять конфигурацию на самих объектах ресурсов.
- person JAB; 09.04.2014
updateConfiguration
я просто завершаю и перезапускаю свое приложение. Оно работает
- person Phantômaxx; 03.06.2014
conf.setLayoutDirection(locale)
, вы можете заменить conf.locale = new Locale(...))
на conf.setLocale(new Locale(...))
. Он вызовет внутренний setLayoutDirection
.
- person Ted Hopp; 01.09.2015
@deprecated See {@link android.content.Context#createConfigurationContext(Configuration)}.
- updateConfiguration устарела
- person Zoe; 19.07.2017
onCreate
, мне пришлось добавить это в onResume
. Не знаю почему.
- person AliAvci; 30.08.2018
updateConfiguration
устарел, есть ли решение вместо этого?
- person zeleven; 17.04.2019
Этот код действительно работает:
fa = персидский, en = английский
Введите код вашего языка в languageToLoad
переменную:
import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;
public class Main extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String languageToLoad = "fa"; // your language
Locale locale = new Locale(languageToLoad);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
this.setContentView(R.layout.main);
}
}
ОБНОВЛЕНИЕ, июнь 2021 г. (Котлин):
class Main : Activity() {
// Called when the activity is first created.
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val config = resources.configuration
val lang = "fa" // your language code
val locale = Locale(lang)
Locale.setDefault(locale)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
config.setLocale(locale)
else
config.locale = locale
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
createConfigurationContext(config)
resources.updateConfiguration(config, resources.displayMetrics)
this.setContentView(R.layout.main)
}
}
Resources.updateConfiguration
. Я сделал отступ в коде, чтобы было понятнее.
- person Czechnology; 17.02.2013
Искал способ программно изменить язык системы. Хотя я полностью понимаю, что обычное приложение никогда не должно этого делать, а вместо этого:
возникла необходимость действительно программно изменить язык системы.
Это недокументированный API, поэтому его не следует использовать в рыночных / конечных приложениях!
В любом случае вот решение, которое я нашел:
Locale locale = new Locale(targetLocaleAsString);
Class amnClass = Class.forName("android.app.ActivityManagerNative");
Object amn = null;
Configuration config = null;
// amn = ActivityManagerNative.getDefault();
Method methodGetDefault = amnClass.getMethod("getDefault");
methodGetDefault.setAccessible(true);
amn = methodGetDefault.invoke(amnClass);
// config = amn.getConfiguration();
Method methodGetConfiguration = amnClass.getMethod("getConfiguration");
methodGetConfiguration.setAccessible(true);
config = (Configuration) methodGetConfiguration.invoke(amn);
// config.userSetLocale = true;
Class configClass = config.getClass();
Field f = configClass.getField("userSetLocale");
f.setBoolean(config, true);
// set the locale to the new value
config.locale = locale;
// amn.updateConfiguration(config);
Method methodUpdateConfiguration = amnClass.getMethod("updateConfiguration", Configuration.class);
methodUpdateConfiguration.setAccessible(true);
methodUpdateConfiguration.invoke(amn, config);
android.permission.CHANGE_CONFIGURATION
может быть предоставлен только приложением, подписанным с помощью ключа выполнения.
- person Yeung; 05.05.2014
Operation not allowed: java.lang.SecurityException: Permission android.permission.CHANGE_CONFIGURATION is not a changeab le permission type
- person Juuso Ohtonen; 24.08.2015
getConfiguration
был перемещен во внутренний класс Proxy
, расширяющий ActivityManagerNative
. Изменения вносить только с API 26 и выше, проверьте версию Build
. См. Код, используемый Fastlane здесь, чтобы уточнить. Наконец, устаревшее .locale =
следует заменить на setLocale
.
- person Nicolas; 08.05.2021
Если вы хотите, чтобы язык был изменен во всем приложении, вам нужно сделать две вещи.
Во-первых, создайте базовое Activity и расширьте все свои действия от этого:
public class BaseActivity extends AppCompatActivity {
private Locale mCurrentLocale;
@Override
protected void onStart() {
super.onStart();
mCurrentLocale = getResources().getConfiguration().locale;
}
@Override
protected void onRestart() {
super.onRestart();
Locale locale = getLocale(this);
if (!locale.equals(mCurrentLocale)) {
mCurrentLocale = locale;
recreate();
}
}
public static Locale getLocale(Context context){
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
String lang = sharedPreferences.getString("language", "en");
switch (lang) {
case "English":
lang = "en";
break;
case "Spanish":
lang = "es";
break;
}
return new Locale(lang);
}
}
Обратите внимание, что я сохраняю новый язык в sharedPreference.
Во-вторых, создайте расширение Application следующим образом:
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
setLocale();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setLocale();
}
private void setLocale() {
final Resources resources = getResources();
final Configuration configuration = resources.getConfiguration();
final Locale locale = getLocale(this);
if (!configuration.locale.equals(locale)) {
configuration.setLocale(locale);
resources.updateConfiguration(configuration, null);
}
}
}
Обратите внимание, что getLocale () это то же самое, что и выше.
Это все! Надеюсь, это кому-нибудь поможет.
Application
и как его использовать. mobomo.com/2011/05/how -to-use-application-object-of-android
- person Siwei; 05.03.2017
configuration.locate
устарел, setLocale требует API 17+, а updateConfiguration не рекомендуется
- person Zoe; 19.07.2017
Согласно этой статье. Вам нужно будет загрузить LocaleHelper.java
, упомянутый в этой статье.
MyApplication
класс, который будет расширять Application
attachBaseContext()
, чтобы обновить язык.Зарегистрируйте этот класс в манифесте.
public class MyApplication extends Application {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(LocaleHelper.onAttach(base, "en"));
}
}
<application
android:name="com.package.MyApplication"
.../>
Создайте BaseActivity
и переопределите onAttach()
, чтобы обновить язык. Требуется для Android 6+
public class BaseActivity extends Activity {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(LocaleHelper.onAttach(base));
}
}
Сделайте так, чтобы все действия в вашем приложении продолжались с BaseActivity
.
public class LocaleHelper {
private static final String SELECTED_LANGUAGE = "Locale.Helper.Selected.Language";
public static Context onAttach(Context context) {
String lang = getPersistedData(context, Locale.getDefault().getLanguage());
return setLocale(context, lang);
}
public static Context onAttach(Context context, String defaultLanguage) {
String lang = getPersistedData(context, defaultLanguage);
return setLocale(context, lang);
}
public static String getLanguage(Context context) {
return getPersistedData(context, Locale.getDefault().getLanguage());
}
public static Context setLocale(Context context, String language) {
persist(context, language);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return updateResources(context, language);
}
return updateResourcesLegacy(context, language);
}
private static String getPersistedData(Context context, String defaultLanguage) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
return preferences.getString(SELECTED_LANGUAGE, defaultLanguage);
}
private static void persist(Context context, String language) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = preferences.edit();
editor.putString(SELECTED_LANGUAGE, language);
editor.apply();
}
@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);
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;
}
}
Просто добавила лишнюю деталь, которая меня сбила с толку.
В то время как другие ответы отлично работают с "de", например
String lang = "de";
Locale locale = new Locale(lang);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
Вышеупомянутое не будет работать, например, с "fr_BE"
локалью, поэтому будет использоваться папка values-fr-rBE
или что-то подобное.
Требуется следующее небольшое изменение для работы с "fr_BE"
String lang = "fr";
//create a string for country
String country = "BE";
//use constructor with country
Locale locale = new Locale(lang, country);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
activity.recreate()
- person To Kra; 30.03.2015
android.content.res.Configuration conf = res.getConfiguration();
вместо создания нового Configuration
экземпляра? Есть ли польза от использования свежего?
- person Bianca Daniciuc; 14.08.2015
Я перешел на немецкий язык, потому что мое приложение запускается само.
Вот мой правильный код. Кто-нибудь хочет использовать то же самое для меня .. (Как программно изменить язык в Android)
мой код:
Configuration config ; // variable declaration in globally
// this part is given inside onCreate Method starting and before setContentView()
public void onCreate(Bundle icic)
{
super.onCreate(icic);
config = new Configuration(getResources().getConfiguration());
config.locale = Locale.GERMAN ;
getResources().updateConfiguration(config,getResources().getDisplayMetrics());
setContentView(R.layout.newdesign);
}
Создайте класс Extends Application
и создайте статический метод. Затем вы можете вызывать этот метод во всех действиях до setContentView()
.
public class MyApp extends Application {
@Override
public void onCreate() {
super.onCreate();
}
public static void setLocaleFa (Context context){
Locale locale = new Locale("fa");
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
context.getApplicationContext().getResources().updateConfiguration(config, null);
}
public static void setLocaleEn (Context context){
Locale locale = new Locale("en_US");
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
context.getApplicationContext().getResources().updateConfiguration(config, null);
}
}
Использование в деятельности:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyApp.setLocaleFa(MainActivity.this);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
}
Я знаю, что поздно отвечать, но я нашел здесь эту статью. Это очень хорошо объясняет весь процесс и предоставляет вам хорошо структурированный код.
Класс Locale Helper:
import android.annotation.TargetApi;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.preference.PreferenceManager;
import java.util.Locale;
/**
* This class is used to change your application locale and persist this change for the next time
* that your app is going to be used.
* <p/>
* You can also change the locale of your application on the fly by using the setLocale method.
* <p/>
* Created by gunhansancar on 07/10/15.
*/
public class LocaleHelper {
private static final String SELECTED_LANGUAGE = "Locale.Helper.Selected.Language";
public static Context onAttach(Context context) {
String lang = getPersistedData(context, Locale.getDefault().getLanguage());
return setLocale(context, lang);
}
public static Context onAttach(Context context, String defaultLanguage) {
String lang = getPersistedData(context, defaultLanguage);
return setLocale(context, lang);
}
public static String getLanguage(Context context) {
return getPersistedData(context, Locale.getDefault().getLanguage());
}
public static Context setLocale(Context context, String language) {
persist(context, language);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return updateResources(context, language);
}
return updateResourcesLegacy(context, language);
}
private static String getPersistedData(Context context, String defaultLanguage) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
return preferences.getString(SELECTED_LANGUAGE, defaultLanguage);
}
private static void persist(Context context, String language) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = preferences.edit();
editor.putString(SELECTED_LANGUAGE, language);
editor.apply();
}
@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);
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;
}
}
Вам необходимо переопределить attachBaseContext и вызвать LocaleHelper.onAttach () для инициализации настроек локали в вашем приложении.
import android.app.Application;
import android.content.Context;
import com.gunhansancar.changelanguageexample.helper.LocaleHelper;
public class MainApplication extends Application {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(LocaleHelper.onAttach(base, "en"));
}
}
Все, что вам нужно сделать, это добавить
LocaleHelper.onCreate(this, "en");
везде, где вы хотите изменить языковой стандарт.
createConfigurationContext
, это было полезно
- person jacoballenwood; 16.01.2019
Программное изменение языка в Android
Старый ответ
Сюда входит поддержка RTL / LTR:
public static void changeLocale(Context context, Locale locale) {
Configuration conf = context.getResources().getConfiguration();
conf.locale = locale;
Locale.setDefault(locale);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
conf.setLayoutDirection(conf.locale);
}
context.getResources().updateConfiguration(conf, context.getResources().getDisplayMetrics());
}
Время для своевременного обновления.
Во-первых, список устаревших с API, в котором он был объявлен устаревшим:
configuration.locale
(API 17)updateConfiguration(configuration, displaymetrics)
(API 17)То, что в последнее время не удалось ответить ни на один вопрос, - это использование нового метода.
createConfigurationContext - это новый метод updateConfiguration.
Некоторые использовали его в автономном режиме вот так:
Configuration overrideConfiguration = ctx.getResources().getConfiguration();
Locale locale = new Locale("en_US");
overrideConfiguration.setLocale(locale);
createConfigurationContext(overrideConfiguration);
... но это не работает. Почему? Метод возвращает контекст, который затем используется для обработки переводов Strings.xml и других локализованных ресурсов (изображений, макетов и т. Д.).
Правильное использование выглядит так:
Configuration overrideConfiguration = ctx.getResources().getConfiguration();
Locale locale = new Locale("en_US");
overrideConfiguration.setLocale(locale);
//the configuration can be used for other stuff as well
Context context = createConfigurationContext(overrideConfiguration);
Resources resources = context.getResources();
Если вы просто скопировали это в свою среду IDE, вы можете увидеть предупреждение о том, что API требует, чтобы вы настроили таргетинг на API 17 или выше. Это можно обойти, поместив его в метод и добавив аннотацию @TargetApi(17)
Но ждать. А как насчет старых API?
Вам нужно создать другой метод с помощью updateConfiguration без аннотации TargetApi.
Resources res = YourApplication.getInstance().getResources();
// Change locale settings in the app.
DisplayMetrics dm = res.getDisplayMetrics();
android.content.res.Configuration conf = res.getConfiguration();
conf.locale = new Locale("th");
res.updateConfiguration(conf, dm);
Здесь вам не нужно возвращать контекст.
Теперь справиться с этим может быть сложно. В API 17+ вам понадобится созданный контекст (или ресурсы из созданного контекста), чтобы получить соответствующие ресурсы на основе локализации. Как ты с этим справишься?
Ну, вот как я это делаю:
/**
* Full locale list: https://stackoverflow.com/questions/7973023/what-is-the-list-of-supported-languages-locales-on-android
* @param lang language code (e.g. en_US)
* @return the context
* PLEASE READ: This method can be changed for usage outside an Activity. Simply add a COntext to the arguments
*/
public Context setLanguage(String lang/*, Context c*/){
Context c = AndroidLauncher.this;//remove if the context argument is passed. This is a utility line, can be removed totally by replacing calls to c with the activity (if argument Context isn't passed)
int API = Build.VERSION.SDK_INT;
if(API >= 17){
return setLanguage17(lang, c);
}else{
return setLanguageLegacy(lang, c);
}
}
/**
* Set language for API 17
* @param lang
* @param c
* @return
*/
@TargetApi(17)
public Context setLanguage17(String lang, Context c){
Configuration overrideConfiguration = c.getResources().getConfiguration();
Locale locale = new Locale(lang);
Locale.setDefault(locale);
overrideConfiguration.setLocale(locale);
//the configuration can be used for other stuff as well
Context context = createConfigurationContext(overrideConfiguration);//"local variable is redundant" if the below line is uncommented, it is needed
//Resources resources = context.getResources();//If you want to pass the resources instead of a Context, uncomment this line and put it somewhere useful
return context;
}
public Context setLanguageLegacy(String lang, Context c){
Resources res = c.getResources();
// Change locale settings in the app.
DisplayMetrics dm = res.getDisplayMetrics();//Utility line
android.content.res.Configuration conf = res.getConfiguration();
conf.locale = new Locale(lang);//setLocale requires API 17+ - just like createConfigurationContext
Locale.setDefault(conf.locale);
res.updateConfiguration(conf, dm);
//Using this method you don't need to modify the Context itself. Setting it at the start of the app is enough. As you
//target both API's though, you want to return the context as you have no clue what is called. Now you can use the Context
//supplied for both things
return c;
}
Этот код работает, имея один метод, который вызывает соответствующий метод в зависимости от того, какой API. Это то, что я сделал с множеством разных устаревших вызовов (включая Html.fromHtml). У вас есть один метод, который принимает необходимые аргументы, который затем разделяет его на один из двух (или трех или более) методов и возвращает соответствующий результат в зависимости от уровня API. Он гибкий, так как вам не нужно проверять несколько раз, метод «входа» сделает это за вас. Метод входа здесь setLanguage
ПОЖАЛУЙСТА, ПРОЧИТАЙТЕ ЭТО ПЕРЕД ИСПОЛЬЗОВАНИЕМ
Вам нужно использовать контекст, возвращаемый при получении ресурсов. Почему? Я видел здесь другие ответы, которые используют createConfigurationContext и не используют контекст, который он возвращает. Чтобы заставить его работать так, необходимо вызвать updateConfiguration. Что устарело. Используйте контекст, возвращаемый методом, для получения ресурсов.
Пример использования:
Конструктор или что-то подобное:
ctx = getLanguage(lang);//lang is loaded or generated. How you get the String lang is not something this answer handles (nor will handle in the future)
А затем, где бы вы ни хотели получить ресурсы, вы делаете:
String fromResources = ctx.getString(R.string.helloworld);
Использование любого другого контекста (теоретически) нарушит это.
AFAIK вам все равно нужно использовать контекст активности для отображения диалогов или тостов. для этого вы можете использовать экземпляр активности (если вы находитесь вне)
И, наконец, используйте recreate()
в действии, чтобы обновить содержимое. Ярлык, чтобы не создавать намерение обновления.
Единственное решение, которое у меня полностью работает, - это комбинация кода Алекса Волового с механизмом перезапуска приложения:
void restartApplication() {
Intent i = new Intent(MainTabActivity.context, MagicAppRestart.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainTabActivity.context.startActivity(i);
}
/** This activity shows nothing; instead, it restarts the android process */
public class MagicAppRestart extends Activity {
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
finish();
}
protected void onResume() {
super.onResume();
startActivityForResult(new Intent(this, MainTabActivity.class), 0);
}
}
activity.recreate()
- person To Kra; 30.03.2015
Я столкнулся с той же проблемой. На GitHub я нашел библиотеку Android-LocalizationActivity.
Эта библиотека позволяет очень просто изменить язык вашего приложения во время выполнения, как вы можете видеть в примере кода ниже. Образец проекта, включающий приведенный ниже образец кода и дополнительную информацию, можно найти на странице github.
LocalizationActivity расширяет AppCompatActivity, поэтому вы также можете использовать его при использовании фрагментов.
public class MainActivity extends LocalizationActivity implements View.OnClickListener {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_simple);
findViewById(R.id.btn_th).setOnClickListener(this);
findViewById(R.id.btn_en).setOnClickListener(this);
}
@Override
public void onClick(View v) {
int id = v.getId();
if (id == R.id.btn_en) {
setLanguage("en");
} else if (id == R.id.btn_th) {
setLanguage("th");
}
}
}
Если вы напишете
android:configChanges="locale"
В каждом действии (в файле манифеста) нет необходимости устанавливать его каждый раз, когда вы вводите Activity
.
configChanges
, используемый для взлома, чтобы сохранить состояние Activity при поворотах и т. Д.
- person JAB; 09.04.2014
Для арабского языка / RTL
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(updateBaseContextLocale(newBase));
}
public Context updateBaseContextLocale(Context context) {
String language = SharedPreference.getInstance().getValue(context, "lan");//it return "en", "ar" like this
if (language == null || language.isEmpty()) {
//when first time enter into app (get the device language and set it
language = Locale.getDefault().getLanguage();
if (language.equals("ar")) {
SharedPreference.getInstance().save(mContext, "lan", "ar");
}
}
Locale locale = new Locale(language);
Locale.setDefault(locale);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
updateResourcesLocale(context, locale);
return updateResourcesLocaleLegacy(context, locale);
}
return updateResourcesLocaleLegacy(context, locale);
}
@TargetApi(Build.VERSION_CODES.N)
private Context updateResourcesLocale(Context context, Locale locale) {
Configuration configuration = context.getResources().getConfiguration();
configuration.setLocale(locale);
return context.createConfigurationContext(configuration);
}
@SuppressWarnings("deprecation")
private Context updateResourcesLocaleLegacy(Context context, Locale locale) {
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
configuration.locale = locale;
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
return context;
}
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 ()', иначе ресурсы не будут обновлены.
Context ctx = createConfigurationContext(args);
и получаете ресурсы из этого
- person Zoe; 19.07.2017
Locale
configuration
должен быть установлен в каждом activity
перед настройкой содержимого - this.setContentView(R.layout.main);
activity.recreate()
- person To Kra; 30.03.2015
Сначала создайте multi string.xml для разных языков; затем используйте этот блок кода в onCreate()
методе:
super.onCreate(savedInstanceState);
String languageToLoad = "fr"; // change your language here
Locale locale = new Locale(languageToLoad);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
this.setContentView(R.layout.main);
Вот код, который мне подходит:
public class MainActivity extends AppCompatActivity {
public static String storeLang;
@Override
protected void onCreate(Bundle savedInstanceState) {
SharedPreferences shp = PreferenceManager.getDefaultSharedPreferences(this);
storeLang = shp.getString(getString(R.string.key_lang), "");
// Create a new Locale object
Locale locale = new Locale(storeLang);
// Create a new configuration object
Configuration config = new Configuration();
// Set the locale of the new configuration
config.locale = locale;
// Update the configuration of the Accplication context
getResources().updateConfiguration(
config,
getResources().getDisplayMetrics()
);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
Источник: здесь
Ни одно из перечисленных здесь решений мне не помогло.
Язык не переключался на android> = 7.0, если AppCompatDelegate.setDefaultNightMode (AppCompatDelegate.MODE_NIGHT_YES)
Этот LocaleUtils отлично работает: https://gist.github.com/GigigoGreenLabs/7d555c762ba2d3a810fe
LocaleUtils
public class LocaleUtils {
public static final String LAN_SPANISH = "es";
public static final String LAN_PORTUGUESE = "pt";
public static final String LAN_ENGLISH = "en";
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);
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);
}
}
Код в действии
public class BaseActivity extends AppCompatActivity {
public BaseActivity() {
LocaleUtils.updateConfig(this);
}
}
Я наконец понял, как настроить его для работы на обеих = N версиях Android.
Расширьте AppCompatActivity своим собственным абстрактным классом, например:
abstract class MLAppCompatActivity : AppCompatActivity() {
override fun attachBaseContext(newBase: Context?) {
super.attachBaseContext(LocaleHelper.wrap(newBase))
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
LocaleHelper.wrap(this)
}
}
}
attachBaseContext вызывается в версиях Android ›= N, и в этом случае операция будет использовать правильный контекст. В Android ‹N мы должны вызвать эту функцию другим способом, прежде чем настраивать просмотр содержимого. Поэтому мы переопределяем функцию onCreate, чтобы установить правильный контекст. Означает, что всякий раз, когда вы создаете новое Activity, вам нужно расширять свой абстрактный класс. Как этот:
class TermsActivity : MLAppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_terms)
}
}
И, наконец, LocaleHelper выглядит так:
import android.annotation.TargetApi;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.util.DisplayMetrics;
import com.at_zone.constants.SharedPreferencesKeys;
import java.util.Locale;
public class LocaleHelper extends ContextWrapper {
public LocaleHelper(Context base) {
super(base);
}
public static Context wrap(Context context) {
SharedPreferences sharedPreferences = context.getSharedPreferences(
SharedPreferencesKeys.SHARED_PREFERENCES, Context.MODE_PRIVATE
);
String language = sharedPreferences.getString(SharedPreferencesKeys.CURRENT_LANGUAGE, "default");
if (!language.equals("default")) {
Configuration config = context.getResources().getConfiguration();
if (!language.equals("")) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
setSystemLocale(config, locale);
} else {
setSystemLocaleLegacy(context, config, locale);
}
config.setLayoutDirection(locale);
context = context.createConfigurationContext(config);
}
return new LocaleHelper(context);
}
return context;
}
public static String getSystemLanguage(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return getSystemLocale(context).getLanguage().toLowerCase();
} else {
return getSystemLocaleLegacy(context).getLanguage().toLowerCase();
}
}
public static Locale getSystemLocaleLegacy(Context context) {
Configuration config = context.getResources().getConfiguration();
return config.locale;
}
@TargetApi(Build.VERSION_CODES.N)
public static Locale getSystemLocale(Context context) {
return context.getResources().getConfiguration().getLocales().get(0);
}
public static void setSystemLocaleLegacy(Context context, Configuration config, Locale locale) {
config.locale = locale;
Resources res = context.getResources();
DisplayMetrics dm = res.getDisplayMetrics();
res.updateConfiguration(config, dm);
}
@TargetApi(Build.VERSION_CODES.N)
public static void setSystemLocale(Configuration config, Locale locale) {
config.setLocale(locale);
}
}
Вот несколько шагов, которые вы должны выполнить
Во-первых, вам нужно изменить локаль вашей конфигурации
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
configuration.locale = new Locale(language);
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
Во-вторых, если вы хотите, чтобы ваши изменения применялись непосредственно к видимому макету, вы можете либо обновить представления напрямую, либо просто вызвать activity.recreate (), чтобы перезапустить текущее действие.
А также вы должны сохранить свои изменения, потому что после того, как пользователь закроет ваше приложение, вы потеряете изменение языка.
Я объяснил более подробное решение в своем сообщении в блоге Изменить язык программно в Android
По сути, вы просто вызываете LocaleHelper.onCreate () в своем классе приложения, и если вы хотите изменить локаль на лету, вы можете вызвать LocaleHelper.setLocale ()
Это работает, когда я нажимаю кнопку, чтобы изменить язык текста моего TextView. (Strings.xml в папке values-de)
String languageToLoad = "de"; // your language
Configuration config = getBaseContext().getResources().getConfiguration();
Locale locale = new Locale(languageToLoad);
Locale.setDefault(locale);
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
recreate();
Добавить класс LocaleHelper
public class LocaleHelper{
private static final String SELECTED_LANGUAGE = "Locale.Helper.Selected.Language";
public static Context onAttach(Context context) {
String lang = getPersistedData(context, Locale.getDefault().getLanguage());
return setLocale(context, lang);
}
public static Context onAttach(Context context, String defaultLanguage) {
String lang = getPersistedData(context, defaultLanguage);
return setLocale(context, lang);
}
public static String getLanguage(Context context) {
return getPersistedData(context, Locale.getDefault().getLanguage());
}
public static Context setLocale(Context context, String language) {
persist(context, language);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return updateResources(context, language);
}
return updateResourcesLegacy(context, language);
}
private static String getPersistedData(Context context, String defaultLanguage) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
return preferences.getString(SELECTED_LANGUAGE, defaultLanguage);
}
private static void persist(Context context, String language) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = preferences.edit();
editor.putString(SELECTED_LANGUAGE, language);
editor.apply();
}
@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);
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;
}
}
В действии или фрагменте
Context context = LocaleHelper.setLocale(this, App.getSharedPre().getLanguage());
Resource resources = context.getResources();
Теперь SetText для каждого текста
TextView tv = findViewById(R.id.tv);
tv.setText(resources.getString(R.string.tv));
Для меня лучшее решение - это: https://www.bitcaal.com/how-to-change-the-app-language-programmatically-in-android/
package me.mehadih.multiplelanguage;
import androidx.appcompat.app.AppCompatActivity;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.os.Bundle;
import android.util.DisplayMetrics;
import java.util.Locale;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setApplicationLocale("az"); // short name of language. "en" for English
setContentView(R.layout.activity_main);
}
private void setApplicationLocale(String locale) {
Resources resources = getResources();
DisplayMetrics dm = resources.getDisplayMetrics();
Configuration config = resources.getConfiguration();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
config.setLocale(new Locale(locale.toLowerCase()));
} else {
config.locale = new Locale(locale.toLowerCase());
}
resources.updateConfiguration(config, dm);
}
}
Для пользователей androidx.appcompat: appcompat указанные выше решения будут работать после версии 1.3.0. Как упоминалось в здесь.
Вы можете попросить пользователя выбрать язык на первом экране и сохранить его в SharedPreferences
SharedPreferences.Editor editor = getSharedPreferences("uinfo", MODE_PRIVATE).edit();
editor.putString("lang", "si");
editor.apply();
recreate();
Затем вы можете использовать его в каждом Activity
в своем приложении. Здесь я установил английский и сингальский языки.
@Override
protected void attachBaseContext(Context base) {
SharedPreferences prefs = base.getSharedPreferences("uinfo", MODE_PRIVATE);
String restoredText = prefs.getString("lang", "No name defined");
if (restoredText.equals("si")){
super.attachBaseContext(LocaleHelper.localeUpdateResources(base, "si"));
}else{
super.attachBaseContext(LocaleHelper.localeUpdateResources(base, "en"));
}
}
И это ваш localUpdateResources
метод. Поместите это в LocalHelper
класс
public class LocaleHelper {
public static Context localeUpdateResources(Context context, String languageCode) {
Context newContext = context;
Locale locale = new Locale(languageCode);
Locale.setDefault(locale);
Resources resources = context.getResources();
Configuration config = new Configuration(resources.getConfiguration());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
config.setLocale(locale);
newContext = context.createConfigurationContext(config);
} else {
config.locale = locale;
resources.updateConfiguration(config, resources.getDisplayMetrics());
}
return newContext;
}
}
Resources.updateConfiguration()
устарел, и я решил эту проблему, не создавая никаких пользовательских ContextWrapper
.
Сначала я создал функцию расширения
fun Context.setAppLocale(language: String): Context {
val locale = Locale(language)
Locale.setDefault(locale)
val config = resources.configuration
config.setLocale(locale)
config.setLayoutDirection(locale)
return createConfigurationContext(config)
}
Затем в методе attachBaseContext
действия, просто заменив контекст новым.
override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(ContextWrapper(newBase.setAppLocale("bn")))
}
activity.recreate()
- person To Kra; 30.03.2015