Kullanıcı dili seçtiğinde uygulamanın dili nasıl değiştirilir?


107

Uygulamamın İspanyolca, Portekizce ve İngilizce olarak üç dili desteklemesini istiyorum. Ve uygulamada dil seçme seçeneği verin.

1) 3 adet çekmeceli klasör çekmeceli, çekmeceli, çekmeceli.

2) 3 değer klasör değerleri-es, değerler-pt, değerler. String.xml değerlerini dillere göre değiştirin.

Dil seçmek için imageView'ım var. Tıklandığında, İngilizce, İspanyolca, Portekizce seçeneklerinden oluşan menüyü açın.

Bu kodla seçenek seçiminde yerel ayarı uygulama içinde ayarladım

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

Manifest'te beyan ettim- android: configChanges = "locale"

İşe yarıyor ama bazı sorunları var.

Sorun:-

1) Dil seçildiğinde, dil seçimi görüntüsünü içeren ekran değişmez ancak diğer ekranlar değişir.

2) Oryantasyondan sonra, telefonun yerel ayarına göre uygulama geri yükleme dilini değiştirin.


1
2. problem için şunu eklemeyi deneyin: android:configChanges="locale"Aktiviteniz için AndroidManifest.xml
Parth Doshi

manifestomdaki her faaliyeti zaten ekledim.
mukesh

Dil listesini, ayarlar ekranınız için tercihi sağlayan ve uygulamanızdaki dili geçersiz kılan aşağıdaki kitaplığı kullanabilirsiniz: github.com/delight-im/Android-Languages
caw

Yanıtlar:


172

Web sayfası için alıntı: http://android.programmerguru.com/android-localization-at-runtime/

Uygulamanızın dilini, kullanıcı dil listesinden seçtikten sonra değiştirmek çok kolaydır. Aşağıdaki gibi yerel ayarı String olarak kabul eden bir yönteme sahip olun (İngilizce için "en", Hintçe için "merhaba" gibi), Uygulamanız için yerel ayarı yapılandırın ve dildeki değişikliği yansıtmak için mevcut etkinliğinizi yenileyin. Uyguladığınız yerel ayar, siz manuel olarak yeniden değiştirene kadar değiştirilmeyecektir.

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

Aşağıdaki paketleri aldığınızdan emin olun:

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; 

android: configChanges = "locale | orientation" etkinliğine manifest ekleyin


2
Evet tabi. Web sayfasından alıntı sağlayabilirim. Sağlamam gereken yer lütfen bana bildirin. Teşekkürler.
Udhay

3
Gezinti yığınında etkinliğinizin iki kopyasına sahip olmamak için finish () eklediğinizden emin olun.
Joel Teply

6
finish()önceden çağrılması gerekiyor startActivity(refresh). Aksi takdirde, Aktivitenin yeniden başlatılması yerine Uygulamadan çıkılabilir.
Muhammed Ali

10
Merhaba, yaptım, işe yarıyor, ancak uygulamayı yeniden başlattığımda varsayılan dile geri dönüyor ..
Sofiane Hassaini

5
Konfigürasyon konfigürasyonu = yeni Konfigürasyon (newConfig); config.locale = yerel ayar; Benim durumumda bu mesajı alıyorum. yerel ayar API seviyesi 25'te kullanımdan kaldırıldı
Milon

9

İyi çözümler burada oldukça iyi açıklanmıştır. Ama işte bir tane daha.

Kendi CustomContextWrappersınıf genişletmenizi oluşturun ContextWrapperve tam uygulama için Yerel Ayar ayarını değiştirmek için kullanın. İşte kullanımlı bir GIST .

Ve sonra, CustomContextWrapperörneğin 'hi', etkinlik yaşam döngüsü yönteminde Hintçe dili için kaydedilmiş yerel tanımlayıcıyı çağırın attachBaseContext. Burada kullanım:

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

Bağlantı için teşekkürler çalışıp çalışmadığını ama birkaç şey anlamadı, ben sadece denilen MyContextWrapper.warpiçinde onAttachbenim app sadece bir parçanın ama dil bütün uygulama için değiştirildi ancak etkinlik başlıkları değiştirilmedi, bunu düşünmek çünkü manifest başlıkları önceliklidir, ancak aynı yöntemi onAttachBaseContexuygulama alt sınıfımda çağırırsam, etkinlik başlıkları da seçilen dile değişir, ancak daha sonra değişiklikler yalnızca warp yönteminde çağırdığım parçaya uygulanır, neden bu ?
Abhinav Chauhan

@AbhinavChauhan Bunun doğru olduğundan emin değilim. Bunu kontrol etmem gerek. Bu çözümü uygularken bu sorunla hiç karşılaşmadım. Ancak, uzun zaman oldu ve daha yeni sürümler için Android uygulamasında bazı değişiklikler olabilir. Alternatif olarak bu yazıdaki en yeni cevapları deneyin.
sud007

pek çok çözümü denedim ama hiçbiri işe yaramadı veya belki yanlış uyguladım, sınıfınız aktivitelerle iyi çalışıyor mu, bu warpmetodu onAttachparçanın içinde kullanıyorum , daha önce sadece anaaktivite parçası ve dil değiştirilerek yapmam gerektiğini söyledim. tüm uygulama doğru, ancak diğer tüm parçalar için dil, yapılandırma değişikliğinde İngilizce olarak değişir, bu yüzden onattachtüm parçaları koymam gerekiyor ve manifest yerine eylem çubuğu başlıklarını kodda ayarlıyorum, şimdi uygulama beklendiği gibi çalışıyor. teşekkürler
Abhinav Chauhan

Tamam! Bunu her ekran için yapmanız gerekmediğinden eminim, sadece ilk etkinlikte ve attachBaseContextsadece işlevin içinde . Ve bu, tüm ekranlar için yapar. Uygulamanızdaki tüm etkinlikler için bir `` BaseActivity '' oluşturdunuz mu?
sud007

Hayır, tüm uygulamaya, sonra tüm fragmanlara uygulanacağını düşünerek uygulama alt sınıfımda yapmaya çalışıyordum, ancak wrap()kodun her yapılandırma değişikliğinde yürütülmesi gerektiği ortaya çıktı , bu yüzden onu Diğer tüm etkinliklerin uzandığı soyut etkinlik, şimdi çalışıyor
Abhinav Chauhan

6

android:configChanges="locale"Etkinliğin yeniden yüklenmesine neden olacak şekilde manifest'ten kaldırmanız veya onConfigurationChangedyöntemi geçersiz kılmanız gerekir:

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

Android: configChanges = "locale" dosyasının manifest'ten kaldırılması, uygulamanın yeniden başlatılmasını engellemez. Bildirime eklenip eklenmemesine bakılmaksızın yeniden başlayacaktır.
portfoliobuilder

Manifest'ten android: configChanges = "locale" kaldırmanın uygulamanın yeniden başlatılmasını engellediğini söylemiyorum, tam tersini söylüyorum. Şimdi, manifest'te android: configChanges = "locale" olduğu durumda, bu cevabı yazdığım sırada uygulamanın yeniden yüklenmesini önlemek için kullanıldı, şimdi durumun bu olduğundan emin olamıyorum.
Frane Poljak

6

yukarıdaki @ Uday'ın kodu mükemmel ancak tek bir şey eksik (build.gradle'da varsayılan yapılandırma)

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

}

Benimki sadece yapılandırma dosyasında (build.gradle) dillerden bahsedilmediği için çalışmıyordu

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

bundan sonra tüm diller çalışmaya başladı


3
ÇALIŞMIYOR
Krunal Shah

Gerçekten gerekli mi?
JCarlosR

1
@JCarlosR evet. yapılandırma dosyasına diller eklediğimde Udhay'ın kodu çalışmaya başladı
Lokesh Tiwari

3

Sürüm sorununu alanlar bu kodu deneyebilirler.

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

3

Udhay'in örnek kodu iyi çalışıyor. Sofiane Hassaini ve Chirag SolankI'nın sorusu dışında, yeniden giriş için işe yaramıyor. Super.onCreate (SavedInstanceState); öncesinde onCreate () içindeki etkinliği yeniden başlatmadan Udhay'in kodunu çağırmaya çalışıyorum. O zaman tamam! Sadece küçük bir sorun, menü dizileri hala yerel ayar olarak değiştirilmedi.

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

menü dizileriyle aynı sorun. Problemi çözüyor musunuz?
AlexS

@AlexS, menü dizisindeki sorunu çözmenin yollarını bulamadım. Ancak uygulamadan çıkıp yeniden girildiği görüldüğünde, menü dizeleri normalde yeni Yerel Ayar olarak değiştirilebilir.
Fisher

demek Intent refresh = new Intent(this, ThisActivity.class); startActivity(refresh); istiyorsun
AlexS

2
@AlexS, Hayır! yeni Intent () ve startActivity () eklemek, uygulamayı yeniden başlattığınızda varsayılan dile dönmesine neden olabilir. Demek istediğim, kullanıcılar uygulamadan çıkıp uygulamaya yeniden girerse, menü dizeleri yeni Yerel Ayar olarak değiştirilebilir.
Fisher
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.