Alterar o idioma do aplicativo programaticamente no Android

448

É possível alterar o idioma de um aplicativo de forma programática enquanto ainda usa os recursos do Android?

Caso contrário, é possível solicitar um recurso em um idioma específico?

Gostaria de permitir que o usuário altere o idioma do aplicativo.

hpique
fonte
4
Você pode usar a seguinte biblioteca, que fornece a lista de idiomas, a preferência pela tela de configurações e substitui o idioma no seu aplicativo: github.com/delight-im/Android-Languages
caw
@MarcoW. Você sabe se o Android-Languages ​​funciona com o Android 5.0 Lollipop?
N
1
@ neu242 Sim, ele roda no Android 5.0 sem problemas.
caw
1
Você pode usar a seguinte biblioteca: github.com/zeugma-solutions/locale-helper-android
josue.0
1
@ josue.0 essa biblioteca realmente é o mais limpo em torno de solução para isso
amitavk

Respostas:

376

É possível. Você pode definir o código do idioma. No entanto, eu não recomendaria isso. Nós tentamos isso nos estágios iniciais, basicamente combatendo o sistema.

Temos o mesmo requisito para alterar o idioma, mas decidimos concluir que a interface do usuário deve ser a mesma do telefone. Ele estava funcionando através da configuração da localidade, mas era muito complicado. E você deve defini-lo toda vez que inserir atividade (cada atividade) da minha experiência. aqui está um código se você ainda precisar disso (novamente, eu não recomendo isso)

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

Se você tiver um conteúdo específico do idioma - poderá alterar essa base na configuração.


atualização em 26 de março de 2020

public static void setLocale(Activitycontext) {
        Locale locale;
        Sessions session = new Sessions(context);
        //Log.e("Lan",session.getLanguage());
            locale = new Locale(langCode);
        Configuration config = new Configuration(context.getResources().getConfiguration());
        Locale.setDefault(locale);
        config.setLocale(locale);

       context.getBaseContext().getResources().updateConfiguration(config,
              context.getBaseContext().getResources().getDisplayMetrics());
    }
Alex Volovoy
fonte
328
Não posso acreditar que o Android torna isso tão difícil. Realmente não vejo por que deveria haver uma associação RÍGIDA entre a localidade do telefone e a do aplicativo. Eu sempre tenho meu telefone usando o idioma inglês, embora não seja um falante nativo de inglês. O motivo é que as palavras semi-técnicas traduzidas ficam muito estranhas no meu próprio idioma, então o inglês é muito mais fácil. Também facilita para mim seguir os conselhos da Internet. Mas isso não significa que eu queira que TODOS os aplicativos do meu telefone usem inglês (embora perfeitamente ok, esse é o padrão). Eu quero poder escolher !!!
Peterh
9
Ah, parece que o nível 17 da API foi introduzido Context.createConfigurationContext(), que pode ser usado para agrupar o contexto padrão com a configuração específica do código do idioma e, em seguida, chamar getResourcesisso sem a necessidade de atualizar a configuração nos próprios objetos de recursos.
JAB
8
Você precisa colocar isso em onCreate () de todas as atividades. Caso contrário, ele poderá ser substituído pelo sistema - por exemplo, quando você desliga o dispositivo para paisagem e sua atividade é recriada com a nova configuração (fornecida pelo sistema).
Zsolt Safrany
13
Caso você defina uma localidade RTL como "ar" e deseje que suas pastas de recursos -ldrtl funcionem também, chame também conf.setLayoutDirection (locale);
Zsolt Safrany
3
@ZsoltSafrany - Em vez de adicionar uma chamada conf.setLayoutDirection(locale), você pode substituir conf.locale = new Locale(...))por conf.setLocale(new Locale(...)). Ele ligará internamente setLayoutDirection.
Ted Hopp
179

Este código realmente funciona:

fa = persa, en = inglês

Digite seu código de idioma na languageToLoadvariável:

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);
  }
}
AliSh
fonte
2
Quero alterar o código do idioma no tempo de execução, no seu código, você coloca o código antes do método setContentView (). Assim, seu código não é útil para mim, então, como para alterar o idioma em tempo de execução, Na minha aplicação, existem dois botões de rádio, por Inglês e outra para árabe,
Dwivedi Ji
2
@ Buffalo, é apenas o segundo argumento para o Resources.updateConfigurationmétodo. Recuei o código para torná-lo mais claro.
Czechnology
5
Isso está funcionando bem para todas as atividades após a configuração na atividade de lançamento. Porém, o título da barra de ação parece não ser afetado e ainda continua exibindo o idioma padrão. Alguma idéia do que eu poderia ter perdido?
AndroidMechanic - Viral Patel
8
Config.locale está obsoleto
Zoe
2
em vez de "config.locale = locale;" use "if (Build.VERSION.SDK_INT> = 17) {config.setLocale (locale);} else {config.locale = locale;}
roghayeh hosseini
36

Eu estava procurando uma maneira de alterar a linguagem do sistema programaticamente. Embora eu compreenda perfeitamente que um aplicativo normal nunca deve fazer isso e, em vez disso:

  • o usuário deve ser apontado (através de uma intenção) para as configurações do sistema para alterá-lo manualmente
  • o aplicativo deve lidar com sua localização por conta própria, como descrito na resposta de Alex

havia uma necessidade de realmente alterar o idioma do sistema programaticamente.

Esta é uma API não documentada e, portanto, não deve ser usada para aplicativos de mercado / usuário final!

Enfim, aqui está a solução que eu encontrei:

  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);
icyerasor
fonte
2
dar exceção invocationtarget exceção
Ravi
1
Bem, depende de onde a invocationTargetException é lançada. Então você deve saber a classe que foi alterada.
icyerasor
1
@ Ratatou-tat-a-tat Ratatouille, a partir do Android 4.2, android.permission.CHANGE_CONFIGURATIONsó pode ser concedido pelo aplicativo assinado com a tecla Perform.
Yeung 5/05
3
Coloquei meu aplicativo em / system / priv-app para solucionar o problema do Android 6.0. Detalhes aqui .
weiyin 26/08/2015
1
@Ravi eu tive que mudar meu aplicativo de sistema / / app para / system / priv-aplicativo para que ele funcione
alexislg
31

Se você deseja manter o idioma alterado em todo o seu aplicativo, precisa fazer duas coisas.

Primeiro, crie uma Atividade base e faça com que todas as suas atividades se estendam a partir disso:

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

Observe que eu salvo o novo idioma em uma sharedPreference.

Segundo, crie uma extensão de Aplicativo como esta:

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

Observe que getLocale () é o mesmo que acima.

Isso é tudo! Espero que isso possa ajudar alguém.

Daniel S.
fonte
Atividade de aplicativo é uma atividade principal, como uma MainActivity? por exemplo, eu posso resolver isso em setLocale () no meu método onCreate ()?
Morozov 15/02
App é uma extensão do aplicativo, não é uma atividade. Eu não entendo o que você precisa, desculpe. Talvez você pode tentar me explicar novamente :)
Daniel S.
1
para aqueles noobs do Android como eu, venha aqui para saber o que Applicationé e como usar. mobomo.com/2011/05/how-to-use-application-object-of-android
Siwei Shen 申思维
2
configuration.locateestá obsoleto, setLocale requer API 17+ e updateConfiguration está obsoleto.
Zoe
19

De acordo com este artigo . Você precisará fazer o download LocaleHelper.javamencionado nesse artigo.

  1. Crie uma MyApplicationclasse que se estendeApplication
  2. Substitua attachBaseContext()para atualizar o idioma.
  3. Registre esta classe no manifesto.

    public class MyApplication extends Application {
       @Override
       protected void attachBaseContext(Context base) {
        super.attachBaseContext(LocaleHelper.onAttach(base, "en"));
       }
    }
    
    <application
         android:name="com.package.MyApplication"
         .../>
  4. Crie BaseActivitye substitua onAttach()para atualizar o idioma. Necessário para Android 6+

    public class BaseActivity extends Activity {
      @Override
      protected void attachBaseContext(Context base) {
        super.attachBaseContext(LocaleHelper.onAttach(base));
      }
    }
  5. Faça com que todas as atividades em seu aplicativo se estendam 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;
    }
    }
Khaled Lela
fonte
não é possível usar super.attachBaseContext (LocaleHelper.onAttach (newBase)) porque eu já estou usando super.attachBaseContext (CalligraphyContextWrapper.wrap (newBase))
Rasel
1
você pode envolver um com o outro. super.attachBaseContext (CalligraphyContextWrapper.wrap (LocaleHelper.onAttach (newBase)))
Yeahia2508 08/04
15

Apenas adicionando uma peça extra que me tropeçou.

Enquanto as outras respostas funcionam bem com "de", por exemplo

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

O exemplo acima não funcionará, por exemplo, com o "fr_BE"código do idioma, para que ele use a values-fr-rBEpasta ou similar.

Precisa da seguinte pequena alteração para trabalhar com "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());
triggs
fonte
1
se você deseja aplicar a alteração de local na chamada de atividade aberta atualactivity.recreate()
Para Kra em
Eu sei que estou atrasado para a festa, mas o novo Locale (lang, country) era tudo que eu precisava!
Jacob Holloway
activity.recreate () como funciona ou, se calcularmos isso, String lang = "fr"; String country = "BE"; nunca vai substituir o modo como ele será executado tempo
Amitsharma
Que tal usar em android.content.res.Configuration conf = res.getConfiguration();vez de criar uma nova Configurationinstância? Existe algum benefício em usar um novo?
Bianca Daniciuc
14

Eu mudei para o idioma alemão, pois meu aplicativo é iniciado.

Aqui está o meu código correto. Alguém quer usar esse mesmo para mim .. (Como mudar o idioma no android programaticamente)

meu código:

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);
}
harikrishnan
fonte
1
@harikrishnan Não está funcionando para mim e o teclado não está mudando para o idioma especificado. Como você declarou a atividade em manifesto?
Avadhani Y
13

Eu sei que é tarde para responder, mas eu encontrei este artigo aqui . O que explica muito bem todo o processo e fornece um código bem estruturado.

Classe auxiliar de localidade:

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

Você precisa substituir o attachBaseContext e chamar LocaleHelper.onAttach () para inicializar as configurações de localidade no seu aplicativo.

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

Tudo o que você precisa fazer é adicionar

LocaleHelper.onCreate(this, "en");

onde quer que você queira alterar a localidade.

Anirudh Sharma
fonte
LocaleHelper é uma classe do artigo. Todos os links correm o risco de serem removidos. Por favor, adicione o código na sua resposta.
21917 Zoe
Eu não quero reiniciar meu aplicativo porque o aplicativo está executando algumas tarefas, como a tela de gravação. tão sem reiniciar aplicativo existe alguma solução para Android 7.0
PriyankaChauhan
1
@PriyankaChauhan Acho que o artigo aborda este caso: Você tem duas opções para atualizar o layout atualmente visível: Primeiro , você pode atualizar o texto ou qualquer outro recurso dependente de idioma, um por um.
Maksim Turaev 10/10
Obrigado por adicionar o novo createConfigurationContext, que foi útil
jacoballenwood
1
onCreate ou onAttach para ligar?
precisa saber é o seguinte
12

Criar uma classe Estende Applicatione cria um método estático. Em seguida, você pode chamar esse método em todas as atividades anteriores 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);
}

}

Uso em atividades:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    MyApp.setLocaleFa(MainActivity.this);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.activity_main);
}
Behzad Taghipour
fonte
10

Para o Android 7.0 Nougat (e inferior), siga este artigo:

Alterar idioma programaticamente no Android

Resposta antiga
Isso inclui suporte a 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());
}
Duda
fonte
1
updateConfiguration está obsoleto. O link é útil, adicione-o à sua resposta. (Link só respostas não são boas, como a ligação pode ser retirado Se isso acontecer, esta resposta é inútil.)
Zoe
8

A única solução que funciona totalmente para mim é uma combinação do código de Alex Volovoy com o mecanismo de reinicialização do aplicativo:

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);         
    }
}
Misha
fonte
2
após a alteração da localidade, você também pode ligaractivity.recreate()
Para Kra em
1
Eu não quero reiniciar meu aplicativo porque o aplicativo está executando algumas tarefas, como a tela de gravação. tão sem reiniciar aplicativo existe alguma solução para Android 7.0
PriyankaChauhan
7

Eu estava enfrentando o mesmo problema. No GitHub, encontrei a biblioteca Android-LocalizationActivity .

Essa biblioteca facilita muito a alteração do idioma do seu aplicativo em tempo de execução, como você pode ver no exemplo de código abaixo. Um projeto de exemplo, incluindo o código de exemplo abaixo e mais informações, pode ser encontrado na página do github.

O LocalizationActivity estende o AppCompatActivity, para que você também possa usá-lo quando estiver usando fragmentos.

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");
        }
    }
}
Rockney
fonte
7

Hora de uma atualização devida.

Primeiro, a lista preterida com a API na qual foi preterida:

  • configuration.locale (API 17)
  • updateConfiguration(configuration, displaymetrics) (API 17)

A coisa que nenhuma pergunta respondida recentemente acertou é o uso do novo método .

createConfigurationContext é o novo método para updateConfiguration.

Alguns o usaram autônomo assim:

Configuration overrideConfiguration = ctx.getResources().getConfiguration();
Locale locale = new Locale("en_US");
overrideConfiguration.setLocale(locale);
createConfigurationContext(overrideConfiguration);

... mas isso não funciona. Por quê? O método retorna um contexto, que é usado para manipular traduções Strings.xml e outros recursos localizados (imagens, layouts, qualquer que seja).

O uso adequado é assim:

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

Se você acabou de copiar e colar isso no seu IDE, poderá receber um aviso de que a API exige que você direcione a API 17 ou superior. Isso pode ser contornado, colocando-o em um método e adicionando a anotação@TargetApi(17)

Mas espere. E as APIs mais antigas?

Você precisa criar outro método usando updateConfiguration sem a anotação 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);

Você não precisa retornar um contexto aqui.

Agora, gerenciar isso pode ser difícil. Na API 17+, você precisa do contexto criado (ou dos recursos do contexto criado) para obter os recursos apropriados com base na localização. Como você lida com isso?

Bem, é assim que eu faço:

/**
 * Full locale list: /programming/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;
}

Esse código funciona com um método que faz chamadas para o método apropriado com base em qual API. Isso é algo que fiz com muitas chamadas obsoletas diferentes (incluindo Html.fromHtml). Você tem um método que aceita os argumentos necessários, que o divide em um dos dois (ou três ou mais) métodos e retorna o resultado apropriado com base no nível da API. É flexível, pois você não precisa verificar várias vezes, o método "entry" faz isso por você. O método de entrada aqui ésetLanguage

LEIA ISTO ANTES DE USAR

Você precisa usar o contexto retornado ao obter recursos. Por quê? Vi outras respostas aqui que usam createConfigurationContext e não usam o contexto que ele retorna. Para que funcione dessa maneira, é necessário chamar updateConfiguration. Qual foi preterido. Use o contexto retornado pelo método para obter recursos.

Exemplo de uso :

Construtor ou em algum lugar semelhante:

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)

E então, onde você quiser obter os recursos que você faz:

String fromResources = ctx.getString(R.string.helloworld);

Usar qualquer outro contexto (em teoria) irá quebrar isso.

AFAIK, você ainda precisa usar um contexto de atividade para mostrar diálogos ou brindes. para isso, você pode usar uma instância de uma atividade (se estiver fora)


E, finalmente, use recreate()a atividade para atualizar o conteúdo. Atalho para não precisar criar uma intenção de atualização.

Zoe
fonte
1
Alguns podem se perguntar se o contexto criado custará sua memória. No entanto, de acordo com a documentação oficial do Android: "Cada chamada para esse método retorna uma nova instância de um objeto de contexto; os objetos de contexto não são compartilhados; no entanto, o estado comum (ClassLoader, outros recursos para a mesma configuração) pode ser, portanto o próprio contexto pode ser bastante leve. " Então, eu acho que o Android espera que você use um objeto de contexto separado para as localidades.
precisa saber é o seguinte
7

Se você escrever

android:configChanges="locale"

Em todas as atividades (no arquivo de manifesto), não é necessário defini-lo toda vez que você entra Activity.

Brijesh Masrani
fonte
11
Se está no manifesto, como isso constitui uma mudança no tempo de execução, que parecia ser o que o OP queria?
user316117
1
@ user316117 Indica ao Android que o aplicativo cuidará de todos os assuntos relacionados à configuração da localidade internamente, não que a localidade seja estática. Não tenho certeza se isso impediria o Android de definir o código do idioma ao mudar entre as Atividades, como só vi configChangesusado para um hack para preservar o estado da Atividade nas rotações / etc.
JAB
como definir o idioma apenas para o inglês específico?
Kaveesh Kanwal
1
... até o Android matar sua atividade porque precisa de mais memória RAM
Louis CAD
@Brijesh Se alterarmos o idioma do aplicativo, se tivermos alguma opção de pesquisa no aplicativo, e se pesquisarmos nesse modo, como o aplicativo mostrará dados, devemos desenvolver um banco de dados diferente para cada idioma ou alguma configuração de código do Android, para que haja esse aplicativo pode mostrar dados de acordo com a pesquisa?
Vishwa Pratap
5
Locale locale = new Locale("en");
Locale.setDefault(locale);

Configuration config = context.getResources().getConfiguration();
config.setLocale(locale);
context.createConfigurationContext(config);

Atualização Importante:

context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());

Observe que, no SDK> = 21, você precisa chamar 'Resources.updateConfiguration ()' , caso contrário, os recursos não serão atualizados.

Максим Петлюк
fonte
updateConfiguration está obsoleto. AFAIK você usa createConfigurationContext e aplicar o contexto que você tem para ele ( Context ctx = createConfigurationContext(args);e obter recursos de que
Zoe
Eu sei que está obsoleto. Mas de qualquer maneira eu não conheço nenhuma solução que possa funcionar no Android 5 e superior.
Максим Петлюк
Então você claramente não verificou o javadoc. você chamar o contexto criado a partir createConfigurationContext
Zoe
Ok, mas mesmo assim devemos chamar updateConfiguration (), certo?
2171717 Максим Петлюк -
1
Não use a chamada descontinuada. Significado não updateConfiguration chamando
Zoe
4
/*change language at Run-time*/
//use method like that:
//setLocale("en");
 public void setLocale(String lang) { 
  myLocale = new Locale(lang);         
  Resources res = getResources();         
  DisplayMetrics dm = res.getDisplayMetrics();         
  Configuration conf = res.getConfiguration();         
  conf.locale = myLocale;         
  res.updateConfiguration(conf, dm);         
  Intent refresh = new Intent(this, AndroidLocalize.class);         
  startActivity(refresh); 
 }
altan yuksel
fonte
5
não há necessidade de iniciar nova atividade, basta atualizar realactivity.recreate()
Para Kra
4

Locale configurationdeve ser definido em cada um activityantes de definir o conteúdo -this.setContentView(R.layout.main);

cheskapac
fonte
Mas e se você quiser alterná-lo rapidamente, depois que setContentView () for chamado?
IgorGanapolsky
2
após a mudança de localidade você também pode ligaractivity.recreate()
Para Kra
4

Primeiro, crie multi string.xml para diferentes idiomas; então use este bloco de código no onCreate()método:

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);
Mohsen mokhtari
fonte
Obrigado, este código funciona muito bem, eu testei no Android 5.xe 6.x sem problemas
innovaciones
4

Aqui está um código que funciona para mim:

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

Fonte: aqui

Til Schweiger
fonte
3

Nenhuma das soluções listadas aqui me ajudou.

O idioma não foi ativado no android> = 7.0 se AppCompatDelegate.setDefaultNightMode (AppCompatDelegate.MODE_NIGHT_YES)

Este LocaleUtils funciona bem: 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());
    }
}
}

Adicionado este código ao aplicativo

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

Código em Atividade

public class BaseActivity extends AppCompatActivity {
    public BaseActivity() {
        LocaleUtils.updateConfig(this);
    }
}
Pavel Shirokov
fonte
2

A resposta de Alex Volovoy só funciona para mim se estiver no método onCreate da atividade.

A resposta que funciona em todos os métodos está em outro segmento

Alterar idioma programaticamente no Android

Aqui está a adaptação do código



    Resources standardResources = getBaseContext().getResources();

    AssetManager assets = standardResources.getAssets();

    DisplayMetrics metrics = standardResources.getDisplayMetrics();

    Configuration config = new Configuration(standardResources.getConfiguration());

    config.locale = new Locale(languageToLoad);

    Resources defaultResources = new Resources(assets, metrics, config);

Espero que ajude.

gmauri21
fonte
19
Você disse: "A resposta que funciona em todos os métodos é em outro segmento", mas seus pontos de ligação para esta discussão "!
user316117
1
config.locale está obsoleto
Zoe
2
resposta recursiva, possível de StackOverflow
tamtom
2

Observe que esta solução usando updateConfiguration não funcionará mais com o lançamento do Android M em algumas semanas. A nova maneira de fazer isso agora está usando o applyOverrideConfigurationmétodo da ContextThemeWrapper consulte API doc

Você pode encontrar minha solução completa aqui desde que eu enfrentei o problema: https://stackoverflow.com/a/31787201/2776572

Eric Labelle
fonte
Eu tento o código updateConfiguration no Android 6.0.1 e ele está funcionando bem, eu não sei se o Google corrigiu isso, mas eu posso usá-lo sem problemas
innovaciones
1
Os métodos descontinuados do @innovaciones estão por aí por um tempo. Eventualmente, ele será removido. Demora muito tempo, mas é melhor mudar para as novas APIs o mais rápido possível para evitar problemas
futuros
1

Existem algumas etapas que você deve implementar

Primeiro, você precisa alterar o local da sua configuração

Resources resources = context.getResources();

Configuration configuration = resources.getConfiguration();
configuration.locale = new Locale(language);

resources.updateConfiguration(configuration, resources.getDisplayMetrics());

Segundo, se você deseja que suas alterações se apliquem diretamente ao layout visível, você pode atualizar as visualizações diretamente ou simplesmente chamar activity.recreate () para reiniciar a atividade atual.

E também é necessário persistir nas alterações, pois após o usuário fechar o aplicativo, você perderia a alteração do idioma.

Expliquei uma solução mais detalhada no meu post no blog Alterar idioma programaticamente no Android

Basicamente, basta chamar LocaleHelper.onCreate () na sua classe de aplicativo e, se você quiser alterar a localidade rapidamente, pode chamar LocaleHelper.setLocale ()

Gunhan
fonte
@LunarWatcher Sim, se você realmente checar o código no github ou gist, ele já será tratado.
Gunhan
1

Isso está funcionando quando pressiono o botão para alterar o idioma do meu TextView. (Strings.xml na pasta 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();
ashishdhiman2007
fonte
1

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

Em atividade ou fragmento

Context context = LocaleHelper.setLocale(this, App.getSharedPre().getLanguage());
Resource resources = context.getResources();

Agora SetText em cada texto

TextView tv = findViewById(R.id.tv);
tv.setText(resources.getString(R.string.tv));
Baljinder Maan
fonte
0

semelhante à versão aceita respondida, mas 2017, e adicionada reinicialização (sem reiniciar, às vezes a próxima atividade ainda renderiza o inglês):

// Inside some activity...
private void changeDisplayLanguage(String langCode) {
// Step 1. Change the locale in the app's configuration
    Resources res = getResources();
    android.content.res.Configuration conf = res.getConfiguration();
    conf.setLocale(currentLocale);
    createConfigurationContext(conf);
// Step 2. IMPORTANT! you must restart the app to make sure it works 100%
    restart();
}
private void restart() {
    PackageManager packageManager = getPackageManager();
    Intent intent = packageManager.getLaunchIntentForPackage(getPackageName());
    ComponentName componentName = intent.getComponent();
    Intent mainIntent = IntentCompat.makeRestartActivityTask(componentName);
    mainIntent.putExtra("app_restarting", true);
    PrefUtils.putBoolean("app_restarting", true);
    startActivity(mainIntent);
    System.exit(0);
}
ericn
fonte
1) uso acabamento () em vez de 2) para reiniciar o aplicativo que você pode usar activity.recreate()3) o contexto voltou Eu acho que tem que ser usado para obter os recursos
Zoe
Eu não quero reiniciar meu aplicativo porque o aplicativo está executando algumas tarefas, como a tela de gravação. tão sem reiniciar aplicativo existe alguma solução para Android 7.0
PriyankaChauhan
0

Primeiro você cria valores de nome de diretório - "Nome do idioma" como hindi do que escrever "oi" e a mesma cópia de nome de arquivo de string neste diretório e alterar o valor não altera o parâmetro após definir o código abaixo em sua ação como o botão etc ...

Locale myLocale = new Locale("hi");
Resources res = getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
conf.locale = myLocale;
res.updateConfiguration(conf, dm);
Intent refresh = new Intent(Home.this, Home.class);
startActivity(refresh);
finish(); 
Dhaval Shingala
fonte
1
conf.localeestá obsoleto
Zoe
0
private void setLanguage(String language) {
    Locale locale = new Locale(language);
    Locale.setDefault(locale);
    Configuration config = new Configuration();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        config.setLocale(locale);
    } else {
        config.locale = locale;
    }
    getResources().updateConfiguration(config,
            getResources().getDisplayMetrics());

}
Adeeb karim
fonte
1
Eu não quero reiniciar meu aplicativo porque o aplicativo está executando algumas tarefas, como a tela de gravação. tão sem reiniciar aplicativo existe alguma solução para Android 7.0
PriyankaChauhan
sim em 6.0 que funciona bem para mim, sem reiniciar aplicativo, a linguagem mudou, mas eu did't testado em 7.0
Adeeb karim
0

No exemplo, definimos o idioma inglês:

 Configuration config = GetBaseContext().getResources().getConfiguration();
 Locale locale = new Locale("en");
 Locale.setDefault(locale);
 config.locale = locale;
 GetBaseContext().getResources().updateConfiguration(config, 
            GetBaseContext().getResources().getDisplayMetrics());

Lembre-se de que isso funciona apenas se o idioma for encontrado no sistema do dispositivo também, não apenas no aplicativo

Pavel Pekki
fonte
0

Para suporte árabe / RTL

  1. Você deve atualizar suas configurações de idioma através de - attachBaseContext ()
  2. Para a versão Android N e superior, você deve usar createConfigurationContext () e updateConfiguration () - caso contrário, o layout RTL não está funcionando corretamente

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

Ranjith Kumar
fonte