Программное изменение языка приложения в Android

Можно ли программно изменить язык приложения, продолжая использовать ресурсы Android?

Если нет, можно ли запросить ресурс на определенном языке?

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


person hpique    schedule 24.05.2010    source источник
comment
Вы можете использовать следующую библиотеку, которая предоставляет список языков, предпочтения для экрана настроек и переопределяет язык в вашем приложении: github.com/delight-im/Android-Languages ​​   -  person caw    schedule 24.03.2014
comment
@MarcoW. Вы знаете, работает ли Android-Languages ​​с Android 5.0 Lollipop?   -  person neu242    schedule 08.01.2015
comment
@ neu242 Да, на Android 5.0 работает без проблем.   -  person caw    schedule 08.01.2015
comment
Я уже ответил на этот вопрос в другом потоке, проверьте здесь: stackoverflow.com/a/33079919/2612536   -  person Sindri Þór    schedule 12.10.2015
comment
Вы можете использовать следующую библиотеку: github.com/zeugma-solutions/locale-helper-android   -  person josue.0    schedule 12.06.2019
comment
@ josue.0 эта библиотека действительно является самым чистым решением для этого   -  person amitavk    schedule 30.08.2019
comment
@hpique Если мы изменили язык приложения, тогда, если у нас есть какая-то опция поиска в приложении, и если мы будем искать в этом, то как приложение будет отображать данные, должны ли мы разработать другую базу данных для каждого языка или какой-то параметр кода Android, так что это приложение могло отображать данные в соответствии с поиском?   -  person Vishwa Pratap    schedule 16.09.2019
comment
Перейдите по этой ссылке. developine.com/   -  person Developine    schedule 27.02.2020


Ответы (29)


Возможно. Вы можете установить языковой стандарт. Однако я бы не рекомендовал этого. Мы пробовали это на ранних стадиях, это в основном борьба с системой.

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

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());
    }
person Alex Volovoy    schedule 24.05.2010
comment
он возвращается обратно через некоторое время. - person Mikey; 31.08.2011
comment
Это должно вызываться всеми действиями в методе onCreate? Или, если мы дадим приложению Context, достаточно будет вызываться только один раз, а не во всех действиях? - person Paul; 13.06.2012
comment
Я пробовал @Paul. но возвращение языка после некоторой активности, и это тоже не исправлено. Он отлично работает в эмуляторе, но бот в устройстве. Так что позвольте мне попробовать позвонить во все мероприятия. - person Narendra Pal; 17.09.2012
comment
Не могу поверить, что Android так усложняет задачу. Я действительно не понимаю, почему должна быть СТРОГОА связь между языковым стандартом телефона и приложением. В моем телефоне всегда используется английский язык, хотя я не являюсь носителем английского языка. Причина в том, что переведенные полутехнические слова становятся слишком странными на моем родном языке, поэтому английский намного проще. Это также помогает мне следовать советам из Интернета. Но это не значит, что я хочу, чтобы В КАЖДОМ приложении на моем телефоне использовался английский язык (хотя это нормально по умолчанию). Я хочу иметь возможность выбирать !!! - person peterh; 29.04.2013
comment
И вы должны устанавливать его каждый раз, когда вы вводите действие (каждое действие). Вот почему вы создаете подкласс Activity и строите действия своего приложения на основе этого подкласса. Что, по общему признанию, может быть непросто, если вы используете много предустановленных подклассов Android Activity, но это не так много работы, как вы думаете. - person JAB; 09.04.2014
comment
@ nolan6000 Не похоже, что Android - единственная система, в которой это так. Большинство операционных систем с поддержкой локали работают аналогичным образом, и приложения с внутренним выбором локали / языка должны быть специально разработаны для работы таким образом (хотя я уверен, что в некоторых инструментах пользовательского интерфейса есть библиотеки для такого рода вещей, но их нужно было запрограммировать. также). - person JAB; 09.04.2014
comment
О, похоже, API уровня 17 представил Context.createConfigurationContext(), который можно использовать для обертывания контекста по умолчанию с конфигурацией, зависящей от локали, а затем вызвать getResources для этого без необходимости обновлять конфигурацию на самих объектах ресурсов. - person JAB; 09.04.2014
comment
Я использую похожий метод. но вместо вызова метода updateConfiguration я просто завершаю и перезапускаю свое приложение. Оно работает - person Phantômaxx; 03.06.2014
comment
Разве Google не была той крутой компанией, которая писала крутой код? Я не могу поверить, что для изменения языка приложения не нужны ни 5 строк кода. - person Claudix; 16.06.2014
comment
Чему равен language_code? Как проверить текущий language_code в приложении? - person IgorGanapolsky; 17.06.2014
comment
Вам нужно поместить это в onCreate () каждого действия. В противном случае он может быть переопределен системой - например, когда вы переключаете устройство в горизонтальный режим, и ваша деятельность воссоздается с новой (предоставленной системой) конфигурацией. - person Zsolt Safrany; 29.06.2014
comment
Мне нравится это решение, но у меня с ним одна проблема. Если я изменю локаль на локаль RTL, например ar, тогда, хотя квалификатор языковых ресурсов (-ar) работает (например, в моем приложении используются арабские строки), квалификатор res направления макета (-ldrtl) не работает. Android извлекает ресурсы из RESFOLDER, а не из RESFOLDER-ldrtl. :( Любое решение для этого? - person Zsolt Safrany; 29.06.2014
comment
Если вы установили языковой стандарт RTL, например ar, и хотите, чтобы ваши папки ресурсов -ldrtl также работали, тогда также вызовите conf.setLayoutDirection (locale); - person Zsolt Safrany; 29.06.2014
comment
@ZsoltSafrany - вместо того, чтобы добавлять вызов к conf.setLayoutDirection(locale), вы можете заменить conf.locale = new Locale(...)) на conf.setLocale(new Locale(...)). Он вызовет внутренний setLayoutDirection. - person Ted Hopp; 01.09.2015
comment
Если вы используете context.getApplicationContext (). GetResources (), вам нужно установить язык только один раз для всего приложения. - person Aster; 11.09.2015
comment
Обратите внимание, что при вызове этого кода после setContentView в onCreate конфигурация не сохраняется при изменении ориентации. - person Piyush; 21.02.2016
comment
вы должны устанавливать его каждый раз, когда вы вводите очень важное действие (каждое действие). Спасибо - person ashishdhiman2007; 26.04.2017
comment
не забудьте воссоздать (); активность после настройки в случае другого языка ориентации, например арабского - person Muhammed Refaat; 20.06.2017
comment
Лучше всего было бы создать класс приложения (класс, расширяющий android.app.Application) и в его функции onCreate установить язык с помощью вышеуказанного метода, сохранив предпочтительный язык в общих предпочтениях или где-либо еще. И, очевидно, в вашем файле манифеста Android добавьте android: name = ваш класс приложения в тег приложения. Таким образом, вам не нужно устанавливать язык для каждого действия. Надеюсь, это поможет. - person Sanju; 21.06.2017
comment
Незначительная проблема с этим кодом: @deprecated See {@link android.content.Context#createConfigurationContext(Configuration)}. - updateConfiguration устарела - person Zoe; 19.07.2017
comment
@Alex Я не хочу перезапускать свое приложение, потому что приложение выполняет какую-то задачу, например, экран записи. так что без перезапуска приложения есть ли решение для Android 7.0 - person PriyankaChauhan; 06.10.2017
comment
Мне было недостаточно добавить это в onCreate, мне пришлось добавить это в onResume. Не знаю почему. - person AliAvci; 30.08.2018
comment
Recreate () можно вызвать после этого кода, чтобы одновременно увидеть изменения. Иногда повторное создание может не работать, тогда используйте его под обработчиком, например, с этим new Handler (). Post (new Runnable () {@Override public void run () {reconate ();}}); - person Anand Kumar Jha; 01.10.2018
comment
Метод updateConfiguration устарел, есть ли решение вместо этого? - person zeleven; 17.04.2019
comment
Я использую решение из выбранного здесь ответа: stackoverflow.com/questions/4985805 / set-locale-programmatic Я перейду сюда, чтобы помочь другим. - person Jack; 16.05.2020
comment
Настоятельно рекомендую использовать новый объект Configuration, как объявлено в обновленном ответе, но на последнем шаге я использовал context.createConfigurationContext (конфигурация), потому что context.updateConfiguration () теперь устарел. - person Mina Samir; 07.09.2020
comment
При попытке этого в эмуляторе он работает нормально (как отладка, так и выпуск), но не на моем устройстве. Я подумал, может быть, часть пакета приложений лишает языковые ресурсы, но я не вижу никаких разделений или чего-то подобного. Любые идеи? - person StainlessSteelRat; 30.01.2021
comment
@StainlessSteelRat, добавив это, я решил проблему пакета {language {// Указывает, что пакет приложения не должен поддерживать // конфигурационные APK-файлы для языковых ресурсов. Эти ресурсы // вместо этого упаковываются с каждым // APK базового и динамического функций. enableSplit = false}} - person Shahzain ali; 10.02.2021
comment
На каком уровне API вы это тестировали? Моя реализация этого работает с 26 года, но не ниже - person mashedpotatoes; 12.03.2021

Этот код действительно работает:

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)
    }
}
person AliSh    schedule 07.02.2012
comment
Я хочу изменить локаль во время выполнения, в вашем коде вы помещаете свой код перед методом setContentView (). Итак, ваш код для меня бесполезен. Итак, как изменить язык во время выполнения. В моем приложении есть два переключателя: для английского и другого для арабского, - person Dwivedi Ji; 14.09.2012
comment
просто поместите setContentView (R.layout.main); после щелчка по радиокнопке это сработает. - person AliSh; 05.10.2012
comment
Но он сбросил поле обновления и не лучшим образом, @AliSh - person Dwivedi Ji; 05.10.2012
comment
getBaseContext (). getResources (). getDisplayMetrics ()); - какова цель этой линии? - person Buffalo; 22.10.2012
comment
@Buffalo, это просто второй аргумент для метода Resources.updateConfiguration. Я сделал отступ в коде, чтобы было понятнее. - person Czechnology; 17.02.2013
comment
Хех, хорошо, извини. В то время я работал (Android), отсюда и меньшее внимание к деталям. - person Buffalo; 18.02.2013
comment
но язык клавиатуры не меняется - person Ravi; 13.06.2013
comment
Но это работает только в методе onCreate. Если я изменю язык при нажатии кнопки, меню не изменится. Если кто подскажет, как обновить тексты меню? - person Sergey Dirin; 12.08.2015
comment
Это хорошо работает для всех действий при настройке в стартовом действии. Но заголовок панели действий не изменился и по-прежнему продолжает отображать язык по умолчанию. Есть идеи, что я мог пропустить? - person AndroidMechanic - Viral Patel; 30.10.2015
comment
Config.locale устарел - person Zoe; 19.07.2017
comment
вместо config.locale = locale; используйте if (Build.VERSION.SDK_INT ›= 17) {config.setLocale (locale); } еще {config.locale = locale; } - person roghayeh hosseini; 25.08.2018
comment
Спасибо, помощь полная - person Bipin Bharti; 24.12.2019
comment
Как мы можем установить это с помощью диалога или чего-то еще? как пользователь меняет язык без изменения языка из системы divace? - person Sirwan Rahimi; 07.08.2020
comment
Можно ли перечислить все языковые стандарты, на которые приложение переведено? - person android developer; 08.04.2021

Искал способ программно изменить язык системы. Хотя я полностью понимаю, что обычное приложение никогда не должно этого делать, а вместо этого:

  • пользователю следует указать (через намерение) на системные настройки, чтобы изменить их вручную
  • приложение должно обрабатывать свою локализацию самостоятельно, как описано в ответе Алекса.

возникла необходимость действительно программно изменить язык системы.

Это недокументированный 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);
person icyerasor    schedule 13.01.2011
comment
дать исключение invocationtarget исключение - person Ravi; 13.06.2013
comment
На какой версии андроида? Поскольку это недокументированный API, они могли изменить имена или полностью удалить его ... Думаю, вам придется проверить источник Android. - person icyerasor; 13.06.2013
comment
андроид 4.2, а в каком пакете? - person Ravi; 13.06.2013
comment
Хорошо, это зависит от того, где выбрасывается invocationTargetException. Тогда вы должны знать класс, который был изменен. - person icyerasor; 13.06.2013
comment
@icyerasor Привет, я использую этот код в своем приложении, но недавно я столкнулся с проблемами, поскольку я тестирую его на версиях 4.2 и 4.3, я получаю исключение цели вызова, даже если разрешение было указано. Любой обходной путь? - person Rat-a-tat-a-tat Ratatouille; 30.11.2013
comment
@ Ratatouille, начиная с Android 4.2, android.permission.CHANGE_CONFIGURATION может быть предоставлен только приложением, подписанным с помощью ключа выполнения. - person Yeung; 05.05.2014
comment
Это решение по-прежнему работает на ОС Android версии 5.0. Вы можете предоставить необходимое разрешение CHANGE_CONFIGURATION через adb. Я сделал для этого вспомогательное приложение: play.google.com/ store / apps / - person Juuso Ohtonen; 08.03.2015
comment
Вы больше не можете предоставить необходимое разрешение CHANGE_CONFIGURATION через adb в ОС Android 6.0: Operation not allowed: java.lang.SecurityException: Permission android.permission.CHANGE_CONFIGURATION is not a changeab le permission type - person Juuso Ohtonen; 24.08.2015
comment
Я поместил свое приложение в / system / priv-app, чтобы обойти проблему с Android 6.0. Подробности здесь. - person weiyin; 26.08.2015
comment
Уровень API 24 и выше, есть возможность установить несколько языков с помощью setLocales - person Juuso Ohtonen; 28.03.2017
comment
@Ravi Мне пришлось переместить свое приложение из / system / app в / system / priv-app, чтобы оно работало - person alexislg; 21.07.2018
comment
@icyerasor, если мы изменили язык приложения, тогда, если у нас есть какая-то опция поиска в приложении, и если мы будем искать в этом, то как приложение будет отображать данные, должны ли мы разработать другую базу данных для каждого языка или есть какой-то параметр кода Android чтобы это приложение могло отображать данные в соответствии с поиском? - person Vishwa Pratap; 16.09.2019
comment
getConfiguration метод удален - person nima moradi; 22.12.2020
comment
@nimamoradi Необходимые для этого изменения показаны здесь. 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 () это то же самое, что и выше.

Это все! Надеюсь, это кому-нибудь поможет.

person Daniel S.    schedule 25.02.2016
comment
Активность приложения - это основная деятельность, такая как MainActivity? например, я могу решить эту проблему в setLocale () в моем методе onCreate ()? - person Morozov; 15.02.2017
comment
Приложение является расширением приложения, а не действием. Я не понимаю, что вам нужно, извините. Может, ты попробуешь мне еще раз объяснить :) - person Daniel S.; 16.02.2017
comment
для таких новичков Android, как я, приходите сюда, чтобы узнать, что такое Application и как его использовать. mobomo.com/2011/05/how -to-use-application-object-of-android - person Siwei; 05.03.2017
comment
configuration.locate устарел, setLocale требует API 17+, а updateConfiguration не рекомендуется - person Zoe; 19.07.2017

Согласно этой статье. Вам нужно будет загрузить LocaleHelper.java, упомянутый в этой статье.

  1. Создайте MyApplication класс, который будет расширять Application
  2. Переопределите attachBaseContext(), чтобы обновить язык.
  3. Зарегистрируйте этот класс в манифесте.

    public class MyApplication extends Application {
       @Override
       protected void attachBaseContext(Context base) {
        super.attachBaseContext(LocaleHelper.onAttach(base, "en"));
       }
    }
    
    <application
         android:name="com.package.MyApplication"
         .../>
    
  4. Создайте BaseActivity и переопределите onAttach(), чтобы обновить язык. Требуется для Android 6+

    public class BaseActivity extends Activity {
      @Override
      protected void attachBaseContext(Context base) {
        super.attachBaseContext(LocaleHelper.onAttach(base));
      }
    }
    
  5. Сделайте так, чтобы все действия в вашем приложении продолжались с 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;
    }
    }
    
person Khaled Lela    schedule 30.01.2018
comment
не могу использовать super.attachBaseContext (LocaleHelper.onAttach (newBase)), потому что я уже использую super.attachBaseContext (CalligraphyContextWrapper.wrap (newBase)) - person Rasel; 02.12.2019
comment
можно обернуть одно другим. super.attachBaseContext (CalligraphyContextWrapper.wrap (LocaleHelper.onAttach (newBase))) - person Yeahia2508; 08.04.2020

Просто добавила лишнюю деталь, которая меня сбила с толку.

В то время как другие ответы отлично работают с "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());
person triggs    schedule 25.09.2013
comment
если вы хотите применить изменение локали к текущему открытому вызову действия activity.recreate() - person To Kra; 30.03.2015
comment
Я знаю, что опаздываю на вечеринку, но новый язык (язык, страна) был всем, что мне было нужно! - person Jacob Holloway; 22.04.2015
comment
activity.recreate (), как это работает, или если мы называем это, то String lang = fr; String country = BE; никогда не переопределит, как он будет работать - person Amitsharma; 02.06.2015
comment
Как насчет использования 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);
}
person harikrishnan    schedule 19.02.2013
comment
@harikrishnan У меня это не работает, и клавиатура не переключается на указанный язык .. Как вы объявили активность в манифесте? - person Avadhani Y; 02.04.2013

Создайте класс 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);
}
person Behzad Taghipour    schedule 17.06.2015

Я знаю, что поздно отвечать, но я нашел здесь эту статью. Это очень хорошо объясняет весь процесс и предоставляет вам хорошо структурированный код.

Класс 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");

везде, где вы хотите изменить языковой стандарт.

person Anirudh Sharma    schedule 02.02.2016
comment
LocaleHelper - это класс из статьи. Любые ссылки могут быть удалены. Пожалуйста, добавьте код в свой ответ. - person Zoe; 19.07.2017
comment
Я не хочу перезапускать приложение, потому что приложение выполняет какую-то задачу, например, экран записи. так что без перезапуска приложения есть ли решение для Android 7.0 - person PriyankaChauhan; 06.10.2017
comment
@PriyankaChauhan Я думаю, что статья охватывает этот случай: у вас есть два варианта обновления видимого в данный момент макета: Во-первых, вы можете просто обновлять текст или любые другие ресурсы, зависящие от языка, один за другим. - person Maksim Turaev; 10.10.2017
comment
спасибо за добавление нового createConfigurationContext, это было полезно - person jacoballenwood; 16.01.2019
comment
onCreate или onAttach для вызова? - person vanste25; 03.03.2019

Для Android 7.0 Nougat (и ниже) следуйте этой статье:

Программное изменение языка в 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());
}
person Duda    schedule 31.08.2016
comment
updateConfiguration устарел. Ссылка полезная, пожалуйста, добавьте ее в свой ответ. (Ответы только по ссылке не подходят, так как ссылка может быть удалена. Если это произойдет, этот ответ бесполезен) - person Zoe; 19.07.2017

Время для своевременного обновления.

Во-первых, список устаревших с 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() в действии, чтобы обновить содержимое. Ярлык, чтобы не создавать намерение обновления.

person Zoe    schedule 19.07.2017
comment
Некоторые могут задаться вопросом, не будет ли стоимость созданного контекста вашей памяти. Однако согласно официальной документации Android: каждый вызов этого метода возвращает новый экземпляр объекта Context; Объекты контекста не являются общими, однако общее состояние (загрузчик классов, другие ресурсы для той же конфигурации) может быть таким, что сам контекст может быть довольно легким. Поэтому я думаю, что Android действительно ожидает, что вы будете использовать отдельный объект контекста для вещей локали. - person Sira Lam; 18.09.2017

Единственное решение, которое у меня полностью работает, - это комбинация кода Алекса Волового с механизмом перезапуска приложения:

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);         
    }
}
person Misha    schedule 29.04.2013
comment
после изменения локали вы также можете позвонить activity.recreate() - person To Kra; 30.03.2015
comment
Я не хочу перезапускать приложение, потому что приложение выполняет какую-то задачу, например, экран записи. так что без перезапуска приложения есть ли решение для Android 7.0 - person PriyankaChauhan; 06.10.2017

Я столкнулся с той же проблемой. На 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");
        }
    }
}
person Rockney    schedule 15.04.2016

Если вы напишете

android:configChanges="locale"

В каждом действии (в файле манифеста) нет необходимости устанавливать его каждый раз, когда вы вводите Activity.

person Brijesh Masrani    schedule 20.07.2010
comment
Если это в манифесте, то как это означает изменение во время выполнения, которое, по-видимому, было тем, что хотел O.P.? - person user316117; 01.11.2012
comment
@ user316117 Он указывает Android, что приложение будет обрабатывать все вопросы, касающиеся конфигурации локали, внутри, а не то, что языковой стандарт является статическим. Я не уверен, что это помешает Android установить языковой стандарт при переключении между Activity, поскольку я видел только configChanges, используемый для взлома, чтобы сохранить состояние Activity при поворотах и ​​т. Д. - person JAB; 09.04.2014
comment
как установить язык только на английский? - person Kaveesh Kanwal; 02.06.2016
comment
... пока Android не убьет вашу активность, потому что ему нужно больше оперативной памяти - person Louis CAD; 29.08.2016
comment
@Brijesh Если мы изменили язык приложения, тогда, если у нас есть какая-то опция поиска в приложении, и если мы будем искать в этом, то как приложение будет отображать данные, должны ли мы разработать другую базу данных для каждого языка или какие-то настройки кода Android, так что это приложение могло отображать данные в соответствии с поиском? - person Vishwa Pratap; 16.09.2019

Для арабского языка / RTL

  1. Вы должны обновить свои языковые настройки с помощью - attachBaseContext ()
  2. Для версии Android N и выше вы должны использовать createConfigurationContext () и updateConfiguration () - иначе макет 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;
    }

person Ranjith Kumar    schedule 18.05.2020
comment
Это должен быть правильный ответ. Просто протестируйте и работает (22.02.2021). Спасибо, мой друг. - person Ramiro G.M.; 23.02.2021

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 ()', иначе ресурсы не будут обновлены.

person Максим Петлюк    schedule 12.05.2017
comment
updateConfiguration устарел. AFAIK вы используете createConfigurationContext и применяете к нему контекст, который у вас есть (Context ctx = createConfigurationContext(args); и получаете ресурсы из этого - person Zoe; 19.07.2017
comment
Я знаю, что это устарело. Но в любом случае я не знаю ни одного решения, которое могло бы работать на android 5 и выше. - person Максим Петлюк; 19.07.2017
comment
Тогда вы явно не проверяли javadoc. вы вызываете контекст, созданный из createConfigurationContext - person Zoe; 19.07.2017
comment
Хорошо, но в любом случае мы должны вызвать updateConfiguration (), верно? - person Максим Петлюк; 19.07.2017
comment
Не используйте устаревший вызов, что означает отсутствие вызова updateConfiguration - person Zoe; 19.07.2017
comment
Даже если мы вызовем метод активности Recreate (), он не обновит язык на устройствах ›= 21. Вы пытались вызвать повторное создание после ваших вариантов на устройствах› = 21? Это работает? - person Максим Петлюк; 19.07.2017

Locale configuration должен быть установлен в каждом activity перед настройкой содержимого - this.setContentView(R.layout.main);

person cheskapac    schedule 13.11.2012
comment
Но что, если вы хотите переключить его на лету после вызова setContentView ()? - person IgorGanapolsky; 17.06.2014
comment
после изменения локали вы также можете позвонить 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);
person Mohsen mokhtari    schedule 06.02.2017
comment
Спасибо, этот код отлично работает, тестировал на Android 5.x и 6.x без проблем - person innovaciones; 03.05.2017

Вот код, который мне подходит:

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

Источник: здесь

person Til Schweiger    schedule 29.07.2018

Ни одно из перечисленных здесь решений мне не помогло.

Язык не переключался на 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);
    }
}
person Pavel Shirokov    schedule 01.07.2019
comment
Это работает, спасибо. Кроме того, это не имеет ничего общего с библиотекой каллиграфии при изменении шрифта, что так здорово. - person ʍѳђઽ૯ท; 08.07.2020

Я наконец понял, как настроить его для работы на обеих = 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);
    }

}
person RuSsCiTy    schedule 18.08.2020

Вот несколько шагов, которые вы должны выполнить

Во-первых, вам нужно изменить локаль вашей конфигурации

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

person Gunhan    schedule 08.10.2015
comment
@LunarWatcher Да, если вы действительно проверяете код на github или gist, он уже обработан. - person Gunhan; 19.07.2017

Это работает, когда я нажимаю кнопку, чтобы изменить язык текста моего 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();
person ashishdhiman2007    schedule 03.04.2017

Добавить класс 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));
person Baljinder Maan    schedule 18.10.2019

Для меня лучшее решение - это: 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);
    }
}
person Kamran Gasimov    schedule 27.08.2020
comment
Понятно, найдя лучшее решение, я опубликую здесь - person Kamran Gasimov; 15.09.2020

Для пользователей androidx.appcompat: appcompat указанные выше решения будут работать после версии 1.3.0. Как упоминалось в здесь.

person zgr    schedule 17.06.2021

Вы можете попросить пользователя выбрать язык на первом экране и сохранить его в 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;

    }
}
person Lakpriya Senevirathna    schedule 21.06.2021

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")))
}
person CodeCameo    schedule 26.06.2021

person    schedule
comment
не нужно начинать новую деятельность, просто обновите фактическое activity.recreate() - person To Kra; 30.03.2015