Bagaimana cara mengubah bahasa aplikasi saat pengguna memilih bahasa?

106

Saya ingin aplikasi saya mendukung tiga bahasa Spanyol, Portugis & Inggris. Dan berikan opsi untuk memilih bahasa di app. Saya telah membuat

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

2) 3 nilai folder values-es, values-pt, values ​​Ubah nilai String.xml menurut bahasa.

Saya memiliki imageView untuk memilih bahasa. Saat klik menu terbuka yang terdiri dari pilihan bahasa Inggris, Spanyol, Portugis.

Saya mengatur Lokal di dalam aplikasi pada pemilihan opsi dengan kode ini

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

Saya telah mendeklarasikan di Manifest- android: configChanges = "locale"

Ini berfungsi tetapi memiliki beberapa masalah.

Masalah:-

1) Ketika bahasa dipilih, layar yang berisi gambar pemilihan bahasa tidak berubah tetapi layar lain berubah.

2) Setelah orientasi mengubah bahasa pemulihan aplikasi sesuai dengan lokal telepon.

mukesh
sumber
1
Untuk masalah kedua, coba tambahkan: android:configChanges="locale"untuk Aktivitas Anda di dalam AndroidManifest.xml
Parth Doshi
Saya sudah menambahkan setiap kegiatan dalam manifest saya.
mukesh
Anda dapat menggunakan perpustakaan berikut, yang menyediakan daftar bahasa, preferensi untuk layar pengaturan Anda, dan menimpa bahasa dalam aplikasi Anda: github.com/delight-im/Android-Languages
gak

Jawaban:

172

Ini kutipan untuk halaman web: http://android.programmerguru.com/android-localization-at-runtime/

Sangat mudah untuk mengubah bahasa aplikasi Anda setelah pengguna memilihnya dari daftar bahasa. Miliki metode seperti di bawah ini yang menerima lokal sebagai String (seperti 'en' untuk bahasa Inggris, 'hi' untuk hindi), konfigurasikan lokal untuk Aplikasi Anda dan segarkan aktivitas Anda saat ini untuk mencerminkan perubahan bahasa. Lokal yang Anda terapkan tidak akan diubah hingga Anda mengubahnya lagi secara manual.

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

Pastikan Anda mengimpor paket berikut:

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; 

tambahkan manifes ke aktivitas android: configChanges = "locale | orientasi"

Udhay
sumber
2
Ya, tentu. Saya bisa memberikan kutipan dari halaman web. Jika saya perlu memberikan, beri tahu saya. Terima kasih.
Udhay
3
Pastikan untuk menambahkan finish () sehingga Anda tidak memiliki dua salinan aktivitas Anda di tumpukan navigasi.
Joel Teply
6
finish()perlu dipanggil sebelumnya startActivity(refresh). Jika tidak, Aplikasi dapat keluar daripada Aktivitas yang dimulai ulang.
Mohammed Ali
10
Hai, saya berhasil, berhasil, tetapi ketika saya memulai ulang aplikasi, itu kembali ke bahasa default ..
Sofiane Hassaini
5
Konfigurasi config = Konfigurasi baru (newConfig); config.locale = lokal; Dalam kasus saya mendapatkan pesan ini. lokal tidak digunakan lagi di API level 25
Milon
9

Solusi yang bagus dijelaskan dengan cukup baik di sini. Tapi ini satu lagi.

Buat CustomContextWrapperkelas Anda sendiri memperluas ContextWrapperdan gunakan untuk mengubah pengaturan Lokal untuk aplikasi lengkap. Berikut adalah GIST dengan penggunaan.

Dan kemudian panggil CustomContextWrapperdengan pengenal lokal tersimpan misalnya 'hi'untuk bahasa Hindi dalam metode siklus hidup aktivitas attachBaseContext. Penggunaan di sini:

@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));
}
sud007
sumber
Terima kasih untuk link itu bekerja tetapi saya tidak mengerti beberapa hal, saya hanya disebut MyContextWrapper.warpdalam onAttachhanya satu fragmen dari aplikasi saya tapi bahasa itu diubah untuk seluruh aplikasi, tetapi judul aktivitas tidak berubah, saya pikir itu karena judul manifes lebih diutamakan, tetapi jika saya memanggil metode yang sama di onAttachBaseContexsubkelas aplikasi saya, judul aktivitas juga berubah ke bahasa yang dipilih, tetapi kemudian perubahan hanya diterapkan ke fragmen yang saya panggil dalam metode warp, mengapa demikian? ?
Abhinav Chauhan
@AbhinavChauhan Saya tidak yakin ini benar. Saya perlu memeriksa yang itu. Saya tidak pernah menghadapi masalah ini ketika saya menerapkan solusi ini. Namun, sudah lama dan mungkin ada beberapa perubahan dalam implementasi Android untuk versi yang lebih baru. Atau coba beberapa jawaban terbaru di posting ini.
sud007
Saya mencoba banyak solusi tetapi tidak ada yang berhasil atau mungkin saya menerapkannya secara tidak benar, semoga kelas Anda berfungsi dengan baik dengan aktivitas, saya menggunakan warpmetode itu di onAttachdalam fragmen, sebelumnya saya mengatakan saya hanya perlu melakukannya dengan fragmen aktivitas utama dan bahasa diubah di seluruh aplikasi itu benar, tetapi untuk semua fragmen lain bahasa berubah menjadi bahasa Inggris pada perubahan konfigurasi jadi saya perlu memasukkan onattachsemua fragmen dan alih-alih manifes saya menetapkan judul bilah tindakan dalam kode, sekarang aplikasi berfungsi seperti yang diharapkan. terima kasih
Abhinav Chauhan
Baik! Saya yakin Anda tidak harus melakukan ini untuk setiap layar, cukup aktivitas pertama yang diluncurkan dan di dalam attachBaseContextfungsinya saja. Dan itu melakukannya untuk semua layar. Sudahkah Anda membuat 'BaseActivity' untuk semua aktivitas di aplikasi Anda?
sud007
Tidak, saya mencoba melakukannya di subkelas aplikasi saya berpikir bahwa itu akan diterapkan ke seluruh aplikasi, lalu di semua fragmen, tetapi ternyata wrap()kode tersebut perlu dijalankan pada setiap perubahan konfigurasi, jadi saya memasukkannya ke dalam Kegiatan abstrak dari mana semua kegiatan lain meluas, sekarang bekerja
Abhinav Chauhan
6

Anda harus menghapus android:configChanges="locale"dari manifes, yang akan menyebabkan aktivitas dimuat ulang, atau mengganti onConfigurationChangedmetode:

@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
}
Frane Poljak
sumber
Menghapus android: configChanges = "locale" dari manifes tidak mencegah aplikasi dimulai ulang. Ini akan dimulai ulang terlepas dari apakah itu ditambahkan ke manifes atau tidak.
portofolio
Saya tidak mengatakan bahwa menghapus android: configChanges = "locale" dari manifes mencegah aplikasi memulai ulang, saya mengatakan sebaliknya. Sekarang, untuk kasus ketika kita memiliki android: configChanges = "locale" dalam manifes, ini digunakan untuk mencegah aplikasi memuat ulang pada saat saya menulis jawaban ini, saya tidak dapat mengatakan dengan pasti itu masalahnya sekarang.
Frane Poljak
6

semua kode @ Uday di atas sempurna tetapi hanya satu hal yang hilang (konfigurasi default di 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); 

}

Milik saya tidak berfungsi hanya karena bahasanya tidak disebutkan di file konfigurasi (build.gradle)

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

setelah itu, semua bahasa mulai berjalan

Lokesh Tiwari
sumber
3
TIDAK BEKERJA
Krunal Shah
Apakah itu benar-benar dibutuhkan?
JCarlosR
1
@JCarRah ya. ketika saya menambahkan bahasa dalam file konfigurasi, kode Udhay mulai berjalan
Lokesh Tiwari
3

Mereka yang mendapatkan masalah versi mencoba kode ini ..

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());
    }
Wahab Khan Jadon
sumber
2

Kode sampel Udhay berfungsi dengan baik. Kecuali soal Sofiane Hassaini dan Chirag SolankI, untuk masuk kembali, tidak berhasil. Saya mencoba memanggil kode Udhay tanpa memulai ulang aktivitas di onCreate (), sebelum super.onCreate (storedInstanceState) ;. Maka tidak apa-apa! Cuma sedikit masalah, menu string masih belum diubah ke set Locale.

    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();
    } 
Nelayan
sumber
masalah yang sama dengan string menu. Apakah Anda memecahkan masalah?
AlexS
@AlexS, saya tidak menemukan cara untuk memperbaiki masalah dalam string menu. Tetapi ditemukan untuk keluar dari aplikasi dan kemudian masuk kembali, string menu biasanya dapat diubah ke Lokal baru.
Fisher
Anda maksud Intent refresh = new Intent(this, ThisActivity.class); startActivity(refresh); ?
AlexS
2
@AlexS, Tidak! menambahkan Intent () dan startActivity () baru dapat membuatnya kembali ke bahasa default saat memulai ulang aplikasi. Yang saya maksud adalah jika pengguna keluar dari aplikasi dan masuk kembali ke aplikasi, string menu dapat diubah ke Lokal baru.
Fisher