
Ada cara mudah untuk menerapkan alih bahasa dalam aplikasi Aktivitas Tunggal. Tumpukan layar dalam pendekatan ini tidak diatur ulang, pengguna tetap berada di tempat ia beralih bahasa. Ketika pengguna pergi ke layar sebelumnya, mereka segera ditampilkan diterjemahkan. Dan hasil lokalisasi angka, jumlah uang, dan bunga mungkin mengejutkan para desainer.

Apa yang akan dibahas dan apa yang tidak akan dibahas?
Lebih lanjut tidak akan ada tentang:
- Teori yang mendasari output string diformat, dan rincian implementasi perpustakaan yang berurusan dengan ini. Yaitu, sesuatu yang akan membantu Anda menulis perpustakaan Anda.
- Sumber string, vektor dan lainnya. Tentang kualifikasi sumber daya mana yang akan digunakan, gambar mana dalam bahasa Arab yang harus ditampilkan dari kanan ke kiri, dan yang tidak, serta seluk-beluk lainnya.
- Proses terjemahan sumber daya terpusat untuk semua platform. Bagaimana mengaturnya agar semua orang hidup dengan baik, bahkan nama panggilan iOS.
Dan kita akan berbicara tentang:
- Berlatih. Pertimbangkan masalah, keterbatasannya, dan solusinya dengan diagram, contoh, dan fragmen kode.
- API SDK yang digunakan untuk solusi ini.
- Fitur pemformatan nilai numerik untuk standar regional yang berbeda, yang harus diketahui oleh desainer.
Apa yang ingin kita lakukan?
Biarkan ada layar dengan pengaturan di aplikasi kami, dan kami ingin menambahkan beberapa item baru ke dalamnya, salah satunya akan memungkinkan Anda untuk beralih bahasa aplikasi, dan yang lainnya untuk mengubah mata uang di mana jumlah uang ditampilkan. Berikut adalah beberapa contoh bagaimana ini terlihat.


Selain menerjemahkan teks dan menampilkan pengaturan huruf dari kanan ke kiri, pengaturan ini harus memengaruhi format tampilan nilai numerik. Perlu bahwa semuanya ditampilkan sesuai dengan lokal yang dipilih.

Solusi arsitektur
Bayangkan aplikasi kita ditulis sesuai dengan pendekatan Aktivitas Tunggal . Kemudian mekanisme alih bahasa dapat diimplementasikan sebagai berikut.

SettingsInteractor
adalah sumber nilai bahasa saat ini. Ini memungkinkan Anda untuk berlangganan nilai ini, menerimanya secara sinkron dan hanya berlangganan pembaruan. Jika perlu, Anda dapat memperkenalkan abstraksi tambahan pada SettingsInteractor
sesuai dengan prinsip pemisahan antarmuka . Dalam diagram, detail yang tidak relevan dihilangkan.
AppActivity
at creation mengganti konteks dengan yang baru sehingga aplikasi menggunakan sumber daya untuk bahasa yang dipilih.
override fun attachBaseContext(base: Context) { super.attachBaseContext(applySelectedAppLanguage(base)) } private fun applySelectedAppLanguage(context: Context): Context { val locale = settingsInteractor.getUserSelectedLanguageBlocking() val newConfig = Configuration(context.resources.configuration) Locale.setDefault(locale) newConfig.setLocale(locale) return context.createConfigurationContext(newConfig) }
AppPresenter
pada gilirannya, berlangganan pembaruan bahasa dan memberitahukan Tampilan perubahan.
override fun onFirstViewAttach() { super.onFirstViewAttach() subscribeToLanguageUpdates() } private fun subscribeToLanguageUpdates() { settingsInteractor .getUserSelectedLanguageUpdates() .subscribe( { newLang -> viewState.applyNewAppLanguage(newLang) }, { error -> errorHandler.handle(error) } ) .disposeOnDestroy() }
AppActivity
kembali ketika pemberitahuan perubahan bahasa diterima.
override fun applyNewAppLanguage(lang: Locale) = recreate()

AppActivity
adalah satu-satunya di aplikasi. Semua layar lain diimplementasikan dalam fragmen. Oleh karena itu, saat membuat ulang aktivitas, tumpukan layar disimpan oleh sistem. Jika Anda kembali ke layar sebelumnya, layar akan diinisialisasi ulang dan ditampilkan. Pengguna akan tetap berada di daftar pilihan bahasa dan melihat hasil pilihannya secara instan.
Selain mengganti konteks, perlu untuk memformat data - angka, uang, bunga. Biarkan setiap View mendelegasikan tugas ini ke komponen terpisah, sebut saja UiLocalizer
.

UiLocalizer
menggunakan instance NumberFormat
sesuai untuk mengonversi angka menjadi string.
private var numberFormat = NumberFormat.getNumberInstance(lang) private var percentFormat = NumberFormat.getPercentInstance(lang) private fun getNumberFormatForCurrency(currency: Currency) = NumberFormat .getCurrencyInstance(lang) .also { it.currency = currency }
Harap dicatat bahwa mata uang harus diatur secara terpisah.
Jika Anda menghemat siklus CPU dan bit memori, dan beralih mata uang dan bahasa adalah fungsi utama dan sering digunakan aplikasi Anda, maka, tentu saja, Anda perlu cache.
Representasi bahasa dan mata uang
Contoh kelas Locale
dibuat oleh tag bahasa , yang terdiri dari kode bahasa dua huruf dan kode wilayah dua huruf. Dan contoh dari kelas Currency
didasarkan pada kode ISO tiga huruf . Dalam bentuk ini, bahasa dan mata uang harus diserialisasi untuk disimpan ke disk atau transfer melalui jaringan, dan itu akan menjadi baik. Berikut ini beberapa contohnya.
Hasil memformat angka sesuai dengan standar regional mungkin berbeda dari yang diharapkan. Simbol mata uang atau kode tiga huruf dalam berbagai bahasa akan ditampilkan dengan cara yang berbeda. Tanda minus untuk nilai moneter negatif akan muncul di tempat yang tidak terduga, dan di beberapa tempat tanda kurung akan ditampilkan. Tanda persen mungkin bukan tanda yang biasa kita gunakan.
Faktanya adalah bahwa, dari sudut pandang pola regional, garis akhir terdiri dari awalan dan akhiran untuk angka positif dan negatif, seribu pemisah dan pemisah desimal, dan mereka berbeda untuk lokal yang berbeda.
Angka-angka
Mata uang
Bunga
Selain itu, hasil pemformatan untuk Android SDK dan JDK mungkin berbeda. Selain itu, semua opsi sudah benar, masing-masing digunakan dalam konteks tertentu.

Ketika kita membuat NumberFormat
untuk memformat nilai-nilai tertentu, kita mendapatkan objek dari kelas DecimalFormat
yang hanya dikonfigurasikan oleh templat yang berbeda. Dengan DecimalFormat
objek ke tipe DecimalFormat
dan menggunakan antarmuka, Anda dapat mengubah bagian-bagian template untuk menghancurkan semuanya. Tetapi lebih baik menyembah pemberian.

Anda juga dapat menulis tes untuk menikmati variasi. Tidak untuk semua lokal, mata uang yang sama ditampilkan dengan simbol.

Pada akhirnya
Skema umum dari solusinya adalah sebagai berikut.

Siklus Hidup AppActivity
adalah siklus hidup seluruh aplikasi. Oleh karena itu, cukup membuatnya ulang untuk me-restart seluruh aplikasi dan menerapkan bahasa yang dipilih. Dan karena hanya ada satu aktivitas, itu cukup untuk menjaga langganan untuk mengubah bahasa di satu tempat - di AppPresenter
.
Seperti yang kita lihat, format regional untuk menghasilkan angka bukanlah hal sepele. Anda tidak boleh secara kaku mengatur satu templat untuk semua kesempatan. Lebih baik mempercayakan pemformatan SDK dan setuju bahwa angka-angka akan ditampilkan sesuai dengan standar, dan tidak seperti yang digambarkan pada layout.
Apa yang lebih mudah untuk diuji? (bonus)
Untuk menghemat waktu, Anda dapat menggunakan bendera berikut.
android { ... buildTypes { debug { pseudoLocalesEnabled true } } ... }
Pilih pseudo-lokal yang diinginkan dalam pengaturan telepon.

Dan perhatikan bagaimana tata letak karena teks yang panjang, dan beberapa elemen UI terus-menerus tidak ingin ditampilkan dari kanan ke kiri.

Informasi lebih lanjut dapat ditemukan di dokumentasi .
Perlu dicatat bahwa pseudo-locales tidak akan berfungsi jika Anda mengubah konteksnya, seperti pada solusi di atas. Anda mengubah konteksnya. Oleh karena itu, Anda harus menambahkan en-XA
dan ar-XB
ke daftar pemilihan bahasa di dalam aplikasi.
Itu saja. Miliki lokalisasi yang baik dan suasana hati yang baik!
