Definir localidade programaticamente

139

Meu aplicativo suporta 3 (em breve 4) idiomas. Como vários códigos de idioma são bastante semelhantes, eu gostaria de dar ao usuário a opção de alterar o código de idioma no meu aplicativo, por exemplo, uma pessoa italiana pode preferir o espanhol ao inglês.

Existe uma maneira de o usuário selecionar entre os códigos de idioma disponíveis para o aplicativo e alterar o código de idioma usado? Não vejo problema em definir o código de idioma para cada Atividade, pois é uma tarefa simples executar em uma classe base.

Roland
fonte
Se você precisar de uma maneira de restaurar o código de idioma padrão posteriormente ou se precisar de uma preferência de idioma que contenha uma lista de idiomas e se desejar alterar o código de
caw

Respostas:

114

Para as pessoas que ainda procuram essa resposta, como configuration.localefoi preterido na API 24, agora você pode usar:

configuration.setLocale(locale);

Leve em consideração que o minSkdVersion para esse método é a API 17.

Código de exemplo completo:

@SuppressWarnings("deprecation")
private void setLocale(Locale locale){
    SharedPrefUtils.saveLocale(locale); // optional - Helper method to save the selected language to SharedPreferences in case you might need to attach to activity context (you will need to code this)
    Resources resources = getResources();
    Configuration configuration = resources.getConfiguration();
    DisplayMetrics displayMetrics = resources.getDisplayMetrics();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1){
        configuration.setLocale(locale);
    } else{
        configuration.locale=locale;
    }
    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N){
        getApplicationContext().createConfigurationContext(configuration);
    } else {
        resources.updateConfiguration(configuration,displayMetrics);
    }
}

Não esqueça que, se você alterar o código do idioma com uma Atividade em execução, será necessário reiniciá-lo para que as alterações tenham efeito.

Edição 11 de maio de 2018

A partir da publicação de @ CookieMonster, você pode ter problemas para manter a alteração de localidade nas versões superiores da API. Nesse caso, adicione o seguinte código à sua Atividade Base para atualizar o código de idioma do contexto em cada criação de Atividade:

@Override
protected void attachBaseContext(Context base) {
     super.attachBaseContext(updateBaseContextLocale(base));
}

private Context updateBaseContextLocale(Context context) {
    String language = SharedPrefUtils.getSavedLanguage(); // Helper method to get saved language from SharedPreferences
    Locale locale = new Locale(language);
    Locale.setDefault(locale);

    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {
        return updateResourcesLocale(context, locale);
    }

    return updateResourcesLocaleLegacy(context, locale);
}

@TargetApi(Build.VERSION_CODES.N_MR1)
private Context updateResourcesLocale(Context context, Locale locale) {
    Configuration configuration = new 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;
}

Se você usar isso, não se esqueça de salvar o idioma em SharedPreferences quando definir o código do idioma com setLocate(locale)

EDITAR 7 DE ABRIL DE 2020

Você pode estar com problemas no Android 6 e 7, e isso ocorre devido a um problema nas bibliotecas do Androidx durante o manuseio do modo noturno. Para isso, você também precisará substituir applyOverrideConfigurationsua atividade base e atualizar o código de idioma da configuração, caso seja criado um novo código de idioma novo.

Código de amostra:

@Override
public void applyOverrideConfiguration(Configuration overrideConfiguration) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1) {
        // update overrideConfiguration with your locale  
        setLocale(overrideConfiguration) // you will need to implement this
    }
    super.applyOverrideConfiguration(overrideConfiguration);
} 
Ricardo
fonte
2
Isso funciona para atividades, mas existe uma maneira de atualizar o contexto do aplicativo?
Alekop 11/06
2
Depois de alterar androidx.appcompat:appcompat:a versão de 1.0.2que 1.1.0não trabalha em android 7, mas que trabalha em andróide 9.
Bek
4
O mesmo problema para mim e 1.1.0androidx
Alexander Dadukin
2
O mesmo problema para mim. Depois que mudei para androidx.appcompat: appcompat: 1.1.0 'lib
Rahul Jidge 9/09/19
4
Problema com appcompat:1.1.0pode ser corrigido com appcompat:1.2.0-alpha02e código Set<Locale> set = new LinkedHashSet<>(); // bring the target locale to the front of the list set.add(locale); LocaleList all = LocaleList.getDefault(); for (int i = 0; i < all.size(); i++) { // append other locales supported by the user set.add(all.get(i)); } Locale[] locales = set.toArray(new Locale[0]); configuration.setLocales(new LocaleList(locales));dentro@TargetApi(Build.VERSION_CODES.N) updateResourcesLocale()
Vojtech Pohl
178

Espero que esta ajuda (em onResume):

Locale locale = new Locale("ru");
Locale.setDefault(locale);
Configuration config = getBaseContext().getResources().getConfiguration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
      getBaseContext().getResources().getDisplayMetrics());
Rubycon
fonte
2
Então isso tem que ser definido para todas as atividades?
Tobias
6
1. é obrigatório usar getBaseContext () ou melhor usar o contexto do aplicativo? 2. esse código deve ser chamado em cada atividade? obrigado.
Paul
10
Coloquei esse código em onCreate () da Atividade do meu iniciador (e em nenhum outro lugar) e fiquei agradavelmente surpreso ao ver que a localidade se aplicava a todo o aplicativo. Este é um aplicativo direcionado para 4,3 com um minSDK de 14 (ICS).
IAmKale
8
Não há necessidade de criar um novo objeto de configuração. Você pode usar a configuração atual e atualizá-lo: getResources () getConfiguration ().
Jmart
1
Não use new Configuration () ;, ele muda textAppearance, fontSize
Jemshit Iskenderov
22

Ocorreu um problema ao definir o código de idioma de forma programática com dispositivos com o Android OS N e superior . Para mim, a solução foi escrever este código na minha atividade base:

(se você não tiver uma atividade básica, faça essas alterações em todas as suas atividades)

@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(updateBaseContextLocale(base));
}

private Context updateBaseContextLocale(Context context) {
    String language = SharedPref.getInstance().getSavedLanguage();
    Locale locale = new Locale(language);
    Locale.setDefault(locale);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        return updateResourcesLocale(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;
}

note que aqui não basta chamar

createConfigurationContext(configuration)

você também precisa obter o contexto que esse método retorna e, em seguida, definir esse contexto no attachBaseContextmétodo.

CookieMonster
fonte
Esta é a solução mais fácil e funcional! Essa deve ser a resposta aceita.
Prasad Pawar
3
Esse código funciona muito no Android acima de 7, mas nas versões abaixo de N não está funcionando. Você tem alguma solução?
Matin Ashtiani
Não tenho certeza porque está funcionando para mim. Deseja me enviar sua implementação para que eu possa dar uma olhada?
CookieMonster
2
Não funciona em versões menores Android N porque resources.updateConfiguration tem que ser chamado em onCreate () em vez de attachBaseContext ()
Chandler
@ Chandler está certo. Para o Android 6, calle o updateBaseContextLocalemétodo em onCreatesua atividade principal / base.
Azizjon Kholmatov
22

Como nenhuma resposta está completa para a maneira atual de resolver esse problema, tento dar instruções para uma solução completa. Comente se algo está faltando ou se pode ser melhorado.

Informação geral

Primeiro, existem algumas bibliotecas que desejam resolver o problema, mas todas parecem desatualizadas ou faltam alguns recursos:

Além disso, acho que escrever uma biblioteca pode não ser uma maneira boa / fácil de resolver esse problema, porque não há muito o que fazer, e o que precisa ser feito é mudar o código existente do que usar algo completamente dissociado. Portanto, eu compus as seguintes instruções que devem estar completas.

Minha solução é baseada principalmente em https://github.com/gunhansancar/ChangeLanguageExample (como já vinculado pelo localhost ). É o melhor código que encontrei para orientar. Algumas observações:

  • Conforme necessário, ele fornece implementações diferentes para alterar a localidade do Android N (e acima) e abaixo
  • Ele usa um método updateViews()em cada Atividade para atualizar manualmente todas as seqüências de caracteres após alterar a localidade (usando o habitual getString(id)), o que não é necessário na abordagem mostrada abaixo
  • Ele suporta apenas idiomas e não localidades completas (que também incluem região (país) e códigos variantes)

Mudei um pouco, dissociando a parte que persiste no código do idioma escolhido (como se pode fazer isso separadamente, conforme sugerido abaixo).

Solução

A solução consiste nas duas etapas a seguir:

  • Alterar permanentemente o código do idioma a ser usado pelo aplicativo
  • Faça com que o aplicativo use o conjunto de códigos de idioma personalizado, sem reiniciar

Etapa 1: alterar a localidade

Use a classe LocaleHelper, com base no LocaleHelper de gunhansancar :

  • Adicione um ListPreferenceem um PreferenceFragmentcom os idiomas disponíveis (deve ser mantido quando os idiomas forem adicionados posteriormente)
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;

import mypackage.SettingsFragment;

/**
 * Manages setting of the app's locale.
 */
public class LocaleHelper {

    public static Context onAttach(Context context) {
        String locale = getPersistedLocale(context);
        return setLocale(context, locale);
    }

    public static String getPersistedLocale(Context context) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        return preferences.getString(SettingsFragment.KEY_PREF_LANGUAGE, "");
    }

    /**
     * Set the app's locale to the one specified by the given String.
     *
     * @param context
     * @param localeSpec a locale specification as used for Android resources (NOTE: does not
     *                   support country and variant codes so far); the special string "system" sets
     *                   the locale to the locale specified in system settings
     * @return
     */
    public static Context setLocale(Context context, String localeSpec) {
        Locale locale;
        if (localeSpec.equals("system")) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                locale = Resources.getSystem().getConfiguration().getLocales().get(0);
            } else {
                //noinspection deprecation
                locale = Resources.getSystem().getConfiguration().locale;
            }
        } else {
            locale = new Locale(localeSpec);
        }
        Locale.setDefault(locale);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return updateResources(context, locale);
        } else {
            return updateResourcesLegacy(context, locale);
        }
    }

    @TargetApi(Build.VERSION_CODES.N)
    private static Context updateResources(Context context, Locale locale) {
        Configuration configuration = context.getResources().getConfiguration();
        configuration.setLocale(locale);
        configuration.setLayoutDirection(locale);

        return context.createConfigurationContext(configuration);
    }

    @SuppressWarnings("deprecation")
    private static Context updateResourcesLegacy(Context context, Locale 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;
    }
}

Crie SettingsFragmentcomo o seguinte:

import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import mypackage.LocaleHelper;
import mypackage.R;

/**
 * Fragment containing the app's main settings.
 */
public class SettingsFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
    public static final String KEY_PREF_LANGUAGE = "pref_key_language";

    public SettingsFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preferences);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_settings, container, false);
        return view;
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        switch (key) {
            case KEY_PREF_LANGUAGE:
                LocaleHelper.setLocale(getContext(), PreferenceManager.getDefaultSharedPreferences(getContext()).getString(key, ""));
                getActivity().recreate(); // necessary here because this Activity is currently running and thus a recreate() in onResume() would be too late
                break;
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        // documentation requires that a reference to the listener is kept as long as it may be called, which is the case as it can only be called from this Fragment
        getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
    }

    @Override
    public void onPause() {
        super.onPause();
        getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
    }
}

Crie um recurso locales.xmllistando todos os códigos de idioma com traduções disponíveis da seguinte maneira ( lista de códigos de código de idioma ):

<!-- Lists available locales used for setting the locale manually.
     For now only language codes (locale codes without country and variant) are supported.
     Has to be in sync with "settings_language_values" in strings.xml (the entries must correspond).
  -->
<resources>
    <string name="system_locale" translatable="false">system</string>
    <string name="default_locale" translatable="false"></string>
    <string-array name="locales">
        <item>@string/system_locale</item> <!-- system setting -->
        <item>@string/default_locale</item> <!-- default locale -->
        <item>de</item>
    </string-array>
</resources>

No seu, PreferenceScreenvocê pode usar a seção a seguir para permitir que o usuário selecione os idiomas disponíveis:

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <PreferenceCategory
        android:title="@string/preferences_category_general">
        <ListPreference
            android:key="pref_key_language"
            android:title="@string/preferences_language"
            android:dialogTitle="@string/preferences_language"
            android:entries="@array/settings_language_values"
            android:entryValues="@array/locales"
            android:defaultValue="@string/system_locale"
            android:summary="%s">
        </ListPreference>
    </PreferenceCategory>
</PreferenceScreen>

que usa as seguintes seqüências de caracteres de strings.xml:

<string name="preferences_category_general">General</string>
<string name="preferences_language">Language</string>
<!-- NOTE: Has to correspond to array "locales" in locales.xml (elements in same orderwith) -->
<string-array name="settings_language_values">
    <item>Default (System setting)</item>
    <item>English</item>
    <item>German</item>
</string-array>

Etapa 2: faça com que o aplicativo use a localidade personalizada

Agora configure cada atividade para usar o conjunto de localizações personalizadas. A maneira mais fácil de fazer isso é ter uma classe base comum para todas as atividades com o seguinte código (onde o código importante está attachBaseContext(Context base)e onResume()):

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;

import mypackage.LocaleHelper;
import mypackage.R;

/**
 * {@link AppCompatActivity} with main menu in the action bar. Automatically recreates
 * the activity when the locale has changed.
 */
public class MenuAppCompatActivity extends AppCompatActivity {
    private String initialLocale;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initialLocale = LocaleHelper.getPersistedLocale(this);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menu_settings:
                Intent intent = new Intent(this, SettingsActivity.class);
                startActivity(intent);
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(LocaleHelper.onAttach(base));
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (initialLocale != null && !initialLocale.equals(LocaleHelper.getPersistedLocale(this))) {
            recreate();
        }
    }
}

O que faz é

  • Substituir attachBaseContext(Context base)para usar o código de idioma persistido anteriormente comLocaleHelper
  • Detecte uma alteração do código do idioma e recrie a Atividade para atualizar suas seqüências

Notas sobre esta solução

  • A recriação de uma atividade não atualiza o título da ActionBar (como já observado aqui: https://github.com/gunhansancar/ChangeLanguageExample/issues/1 ).

    • Isso pode ser alcançado simplesmente com um método setTitle(R.string.mytitle)no onCreate()método de cada atividade.
  • Ele permite que o usuário escolha o local padrão do sistema, bem como o local padrão do aplicativo (que pode ser nomeado, neste caso, "inglês").

  • fr-rCAAté o momento, apenas códigos de idioma, nenhuma região (país) e códigos de variantes (como ) são suportados. Para oferecer suporte a especificações completas de código de idioma, pode ser usado um analisador semelhante ao da biblioteca de idiomas do Android (que suporta região, mas nenhum código de variante).

    • Se alguém encontrar ou tiver escrito um bom analisador, adicione um comentário para que eu possa incluí-lo na solução.
user905686
fonte
1
Excelente, mas rei do pesadelo
Odys
1
Inferno não, meu aplicativo já é muito complexo, essa abordagem seria um pesadelo para manter no futuro.
28718 Josh
@ Josh, você pode explicar isso um pouco mais? Na verdade, apenas algumas linhas precisam ser adicionadas a cada classe base de Atividade que você usa. Vejo que talvez não seja possível usar a mesma classe base para todas as atividades, mas projetos ainda maiores devem se dar bem com algumas. A programação orientada a aspectos pode ajudar aqui, mas a composição (mover o código de attachBaseContext(Context base)e onResume()para uma classe separada) pode fazer o truque. Então, tudo o que você precisa fazer é declarar um objeto em cada classe base de atividades e delegar essas duas chamadas.
user905686
Se o usuário alterar seu código de idioma, o código de idioma de todas as páginas de atividades anteriores também poderá ser alterado?
Raju yourPepe
Esta é a melhor resposta para esta questão. Graças bro, ele funciona
Alok Gupta
16
@SuppressWarnings("deprecation")
public static void forceLocale(Context context, String localeCode) {
    String localeCodeLowerCase = localeCode.toLowerCase();

    Resources resources = context.getApplicationContext().getResources();
    Configuration overrideConfiguration = resources.getConfiguration();
    Locale overrideLocale = new Locale(localeCodeLowerCase);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        overrideConfiguration.setLocale(overrideLocale);
    } else {
        overrideConfiguration.locale = overrideLocale;
    }

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        context.getApplicationContext().createConfigurationContext(overrideConfiguration);
    } else {
        resources.updateConfiguration(overrideConfiguration, null);
    }
}

Basta usar esse método auxiliar para forçar a localidade específica.

UDPATE 22 DE AGOSTO DE 2017. Melhor usar essa abordagem .

localhost
fonte
4

Adicione uma classe auxiliar com o seguinte método:

public class LanguageHelper {
    public static final void setAppLocale(String language, Activity activity) {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            Resources resources = activity.getResources();
            Configuration configuration = resources.getConfiguration();
            configuration.setLocale(new Locale(language));
            activity.getApplicationContext().createConfigurationContext(configuration);
        } else {
            Locale locale = new Locale(language);
            Locale.setDefault(locale);
            Configuration config = activity.getResources().getConfiguration();
            config.locale = locale;
            activity.getResources().updateConfiguration(config,
                    activity.getResources().getDisplayMetrics());
        }

    }
}

E chame-o em sua atividade de inicialização, como MainActivity.java:

public void onCreate(Bundle savedInstanceState) {
    ...
    LanguageHelper.setAppLocale("fa", this);
    ...
}
Hadid Graphics
fonte
3

simples e fácil

Locale locale = new Locale("en", "US");
Resources res = getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
conf.locale = locale;
res.updateConfiguration(conf, dm);

onde "en" é o código do idioma e "US" é o código do país.

Makvin
fonte
Conforme declarado no meu post, ele conf.locale=locale;foi descontinuado e também é updateConfiguration.
Ricardo
muito simples e menos complicado :)
Ramkesh Yadav
2

Válido para API16 a API28 Basta colocar este método em algum lugar:

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

Insira este código em todas as suas atividades usando:

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(localeUpdateResources(base, "<-- language code -->"));
    }

ou chame localeUpdateResources em fragmentos, adaptadores etc. onde você precisar do novo contexto.

Créditos: Yaroslav Berezanskyi

nnyerges
fonte
2

Existe uma maneira super simples.

em Substituição BaseActivity, Activity ou Fragment attachBaseContext

 override fun attachBaseContext(context: Context) {
    super.attachBaseContext(context.changeLocale("tr"))
}

extensão

fun Context.changeLocale(language:String): Context {
    val locale = Locale(language)
    Locale.setDefault(locale)
    val config = this.resources.configuration
    config.setLocale(locale)
    return createConfigurationContext(config)
}
Burak Dizlek
fonte
2

Eu encontrei o androidx.appcompat:appcompat:1.1.0bug também pode ser corrigido simplesmente chamando getResources()emapplyOverrideConfiguration()

@Override public void
applyOverrideConfiguration(Configuration cfgOverride)
{
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP &&
      Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
    // add this to fix androidx.appcompat:appcompat 1.1.0 bug
    // which happens on Android 6.x ~ 7.x
    getResources();
  }

  super.applyOverrideConfiguration(cfgOverride);
}
Sam Lu
fonte
1
 /**
 * Requests the system to update the list of system locales.
 * Note that the system looks halted for a while during the Locale migration,
 * so the caller need to take care of it.
 */
public static void updateLocales(LocaleList locales) {
    try {
        final IActivityManager am = ActivityManager.getService();
        final Configuration config = am.getConfiguration();

        config.setLocales(locales);
        config.userSetLocale = true;

        am.updatePersistentConfiguration(config);
    } catch (RemoteException e) {
        // Intentionally left blank
    }
}
Zbigniew Mazur
fonte
1

Para quem tentou de tudo, mas não está funcionando . Verifique se, se você definir darkmodecom AppCompatDelegate.setDefaultNightModee o sistema não estiver escuro, Configuration.setLocalenão funcionará acima do Andorid 7.0 .

Adicione este código em todas as suas atividades para resolver esse problema:

override fun applyOverrideConfiguration(overrideConfiguration: Configuration?) {
  if (overrideConfiguration != null) {
    val uiMode = overrideConfiguration.uiMode
    overrideConfiguration.setTo(baseContext.resources.configuration)
    overrideConfiguration.uiMode = uiMode
  }
  super.applyOverrideConfiguration(overrideConfiguration)
}
Yeahia2508
fonte
-1

Coloque este código em sua atividade

 if (id==R.id.uz)
    {
        LocaleHelper.setLocale(MainActivity.this, mLanguageCode);

        //It is required to recreate the activity to reflect the change in UI.
        recreate();
        return true;
    }
    if (id == R.id.ru) {

        LocaleHelper.setLocale(MainActivity.this, mLanguageCode);

        //It is required to recreate the activity to reflect the change in UI.
        recreate();
    }
Xurshid Raxmatov
fonte