Como alterar o idioma do aplicativo quando o usuário seleciona o idioma?


106

Quero que meu aplicativo ofereça suporte a três idiomas: espanhol, português e inglês. E dê a opção de selecionar o idioma no aplicativo. Eu fiz

1) 3 pastas drawable drawable-es, drawable-pt, drawable.

2) pasta de 3 valores valores-es, valores-pt, valores. Altere os valores String.xml de acordo com os idiomas.

Tenho imageView para selecionar o idioma.Ao clicar nele, abra o menu que consiste na opção Inglês, Espanhol, Português.

Eu defino Locale dentro do aplicativo na seleção de opções por este código

public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.en:
             Locale locale = new Locale("en"); 
             Locale.setDefault(locale);
             Configuration config = new Configuration();
             config.locale = locale;
             getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
             Toast.makeText(this, "Locale in English !", Toast.LENGTH_LONG).show();
             break;

        case R.id.pt:
             Locale locale2 = new Locale("pt"); 
             Locale.setDefault(locale2);
             Configuration config2 = new Configuration();
             config2.locale = locale2;
             getBaseContext().getResources().updateConfiguration(config2, getBaseContext().getResources().getDisplayMetrics());

             Toast.makeText(this, "Locale in Portugal !", Toast.LENGTH_LONG).show();
             break;

        case R.id.es:
             Locale locale3 = new Locale("es"); 
             Locale.setDefault(locale3);
             Configuration config3 = new Configuration();
             config3.locale = locale3;
             getBaseContext().getResources().updateConfiguration(config3, getBaseContext().getResources().getDisplayMetrics());

             Toast.makeText(this, "Locale in Spain !", Toast.LENGTH_LONG).show();
             break;     
    }
    return super.onOptionsItemSelected(item);
}

Eu declarei no Manifest- android: configChanges = "locale"

Funciona, mas tem algum problema.

Problema:-

1) Quando o idioma é selecionado, a tela que consiste na imagem da seleção do idioma não muda, mas as outras telas são alteradas.

2) Após a mudança de orientação, restaurar o idioma do aplicativo de acordo com a localidade do telefone.


1
Para o segundo problema, tente adicionar: android:configChanges="locale"for your Activity dentro do AndroidManifest.xml
— Parth Doshi

já adicionei todas as atividades em meu manifesto.
— mukesh

Você pode usar a seguinte biblioteca, que fornece a lista de idiomas, a preferência para sua tela de configurações e substitui o idioma em seu aplicativo: github.com/delight-im/Android-Languages
— caw

Respostas:


172

É um trecho da página da web: http://android.programmerguru.com/android-localization-at-runtime/

É simples alterar o idioma do seu aplicativo após o usuário selecioná-lo na lista de idiomas. Tenha um método como o abaixo, que aceita o local como String (como 'en' para inglês, 'hi' para hindi), configure o local para seu aplicativo e atualize sua atividade atual para refletir a mudança no idioma. A localidade que você aplicou não será alterada até que você a altere manualmente novamente.

public void setLocale(String lang) { 
    Locale 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); 
    finish();
    startActivity(refresh); 
} 

Certifique-se de importar os seguintes pacotes:

import java.util.Locale; 
import android.os.Bundle; 
import android.app.Activity; 
import android.content.Intent; 
import android.content.res.Configuration; 
import android.content.res.Resources; 
import android.util.DisplayMetrics; 

adicione o manifesto à atividade android: configChanges = "locale |idance"


2
Sim claro. Posso fornecer o trecho da página da web. Onde eu preciso fornecer, por favor me avise. Obrigado.
— Udhay

3
Certifique-se de adicionar terminar () para que você não tenha duas cópias de sua atividade na pilha de navegação.
— Joel Teply

6
finish()precisa ser chamado antes startActivity(refresh). Caso contrário, o aplicativo pode sair em vez de a atividade ser reiniciada.
— Mohammed Ali,

10
Olá, consegui, funciona, mas quando eu reinicio o app, ele volta para o idioma padrão.
— Sofiane Hassaini

5
Configuração config = nova configuração (newConfig); config.locale = locale; No meu caso, recebendo esta mensagem. localidade obsoleta na API de nível 25
— Milon

9

Boas soluções explicadas muito bem aqui. Mas aqui está mais um.

Crie sua própria CustomContextWrapperextensão de classe ContextWrappere use-a para alterar a configuração Locale para o aplicativo completo. Aqui está um GIST com o uso.

E então ligue para o CustomContextWrapper com identificador de localidade salvo, por exemplo, 'hi'para o idioma Hindi no método de ciclo de vida da atividade attachBaseContext. Use aqui:

@Override
protected void attachBaseContext(Context newBase) {
    // fetch from shared preference also save the same when applying. Default here is en = English
    String language = MyPreferenceUtil.getInstance().getString("saved_locale", "en");
    super.attachBaseContext(MyContextWrapper.wrap(newBase, language));
}

Obrigado pelo link está funcionando, mas não entendi algumas coisas, apenas chamei o MyContextWrapper.warpin onAttachde apenas um fragmento do meu aplicativo, mas o idioma foi alterado para todo o aplicativo, mas os títulos das atividades não foram alterados, acho que é porque os títulos do manifesto têm precedência, mas se eu chamar o mesmo método em onAttachBaseContexminha subclasse de aplicação, os títulos das atividades também mudam para o idioma selecionado, mas então as mudanças são aplicadas apenas ao fragmento que chamei no método warp, por que isso ?
— Abhinav Chauhan

@AbhinavChauhan Não tenho certeza se isso é verdade. Eu preciso verificar aquele. Nunca enfrentei esse problema quando implementei essa solução. No entanto, já se passou muito tempo e pode haver algumas mudanças na implementação do Android para versões mais recentes. Como alternativa, tente algumas respostas mais recentes neste post.
— sud007

Eu tentei muitas soluções, mas nenhuma funcionou ou talvez eu as implementei incorretamente, sua classe funciona bem com as atividades, estou usando o warpmétodo no onAttachdo fragmento, anteriormente eu disse que só precisava fazer isso com o fragmento de atividade principal e a linguagem alterada em Todo o aplicativo é verdade, mas para todas as outras alterações de linguagem de fragmentos para inglês na mudança de configuração, então eu preciso colocar onattachtodos os fragmentos e em vez de manifestar eu defini os títulos da barra de ação no código, agora o aplicativo está funcionando como esperado. obrigado
— Abhinav Chauhan

OK! Tenho certeza de que você não precisa fazer isso para todas as telas, apenas para a primeira atividade que é iniciada e apenas dentro da attachBaseContextfunção. E isso serve para todas as telas. Você criou uma `BaseActivity 'para todas as atividades em seu aplicativo?
— sud007

Não, eu estava tentando fazer isso na minha subclasse de aplicativo pensando que será aplicado em todo o aplicativo, depois em todos os fragmentos, mas acontece que o wrap()código precisa ser executado a cada alteração de configuração, então coloquei no Atividade abstrata da qual todas as outras atividades se estendem, agora está funcionando
— Abhinav Chauhan

6

Você deve remover android:configChanges="locale"do manifesto, o que fará com que a atividade seja recarregada, ou substituir o onConfigurationChangedmétodo:

@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
    // your code here, you can use newConfig.locale if you need to check the language
    // or just re-set all the labels to desired string resource
}

Remover android: configChanges = "locale" do manifesto não impede o aplicativo de reiniciar. Ele será reiniciado independentemente de ser adicionado ao manifesto ou não.
— portfólio de

Não estou dizendo que remover android: configChanges = "locale" do manifesto impede o aplicativo de reiniciar, estou dizendo exatamente o contrário. Agora, para o caso em que temos android: configChanges = "locale" no manifesto, costumava impedir o aplicativo de recarregar no momento em que escrevi esta resposta, não posso dizer com certeza se é o caso agora.
— Frane Poljak de

6

todo o código de @ Uday acima é perfeito, mas apenas uma coisa está faltando (configuração padrão em build.gradle)

public void setLocale(String lang) { 
Locale 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); 
finish();
startActivity(refresh); 

}

O meu não estava funcionando apenas porque os idiomas não foram mencionados no arquivo de configuração (build.gradle)

 defaultConfig {
    resConfigs "en", "hi", "kn"
}

depois disso, todos os idiomas começaram a funcionar


3
NÃO ESTÁ FUNCIONANDO
— Krunal Shah

É realmente necessário?
— JCarlosR

1
@JCarlosR sim. quando adicionei idiomas no arquivo de configuração, o código de Udhay começou a ser executado
— Lokesh Tiwari

3

Aqueles que estão obtendo o problema de versão tentam este código.

public static void switchLocal(Context context, String lcode, Activity activity) {
        if (lcode.equalsIgnoreCase(""))
            return;
        Resources resources = context.getResources();
        Locale locale = new Locale(lcode);
        Locale.setDefault(locale);
        android.content.res.Configuration config = new 
        android.content.res.Configuration();
        config.locale = locale;
        resources.updateConfiguration(config, resources.getDisplayMetrics());
        //restart base activity 
        activity.finish();
        activity.startActivity(activity.getIntent());
    }

2

O código de amostra do Udhay funciona bem. Exceto a pergunta de Sofiane Hassaini e Chirag SolankI, para a reentrada não dá certo. Tento chamar o código de Udhay sem reiniciar a atividade em onCreate (), antes de super.onCreate (savedInstanceState) ;. Então está tudo bem! Apenas um pequeno problema, as strings do menu ainda não mudaram para o Locale definido.

    public void setLocale(String lang) { //call this in onCreate()
      Locale 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); 
      //finish();
    } 

mesmo problema com strings de menu. Você resolve o problema?
— AlexS

@AlexS, não encontrei maneiras de consertar o problema na string de menu. Porém, quando sai do aplicativo e depois entra novamente, as strings do menu podem ser normalmente alteradas para o novo Locale.
— Fisher

você quer dizer Intent refresh = new Intent(this, ThisActivity.class); startActivity(refresh); ?
— AlexS

2
@AlexS, não! adicionar o novo Intent () e startActivity () pode fazer com que ele retorne ao idioma padrão ao reiniciar o aplicativo. O que quero dizer é que se os usuários saírem do aplicativo e entrarem novamente no aplicativo, as strings do menu podem ser alteradas para o novo Locale.
— Fisher
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.