Salam, peretas yang budiman!
Hari ini saya ingin berbagi pengalaman menarik dalam menyelesaikan masalah pelokalan. Di iOS, pelokalan diatur dengan cukup nyaman dari sudut pandang satu target, atau beberapa target, di mana kunci dalam localizable.strings tidak terlalu diulang. Tetapi semuanya menjadi lebih rumit ketika Anda memiliki belasan target, di mana lebih dari setengah kunci diulang, tetapi pada saat yang sama memiliki arti yang berbeda, dan ada juga sekumpulan kunci yang unik untuk target tertentu.
Bagi yang belum mengalami ini, saya akan menjelaskan masalahnya secara lebih rinci dengan sebuah contoh.
Katakanlah kita memiliki proyek besar di mana 90% dari kode umum dan 3 target : MyApp1 , MyApp2 , MyApp3 , yang memiliki sejumlah layar tertentu, serta masing-masing memiliki nama dan teksnya sendiri. Intinya, target adalah aplikasi independen. Masing-masing harus diterjemahkan ke dalam 10 bahasa. Namun, kami TIDAK ingin menambahkan kunci lokalisasi seperti app1_localizable_key1 , app2_localizable_key1 , dll. Kami ingin semuanya indah dalam kode dan dilokalkan dalam satu baris
NSLocalizedString(@"localizable_key1", nil)
Tanpa if dan ifdef , sehingga saat menambahkan target baru, kita tidak perlu mencari tempat dengan NSLocalizedString di seluruh kode proyek besar dan mendaftarkan kunci baru di sana. Kami juga ingin beberapa kunci diikat ke layar target tertentu, mis. ada kunci app2_screen1_key , app3_screen2_key .
Sekarang Anda dapat melakukan hal berikut menggunakan alat Xcode standar:
- Salin bagian umum localizable.strings ke setiap target, dan kita akan mendapatkan 3 salinan dari file-file ini.
- Tambahkan kunci khusus target ke localizable.strings yang sesuai.
Masalah apa yang kita dapatkan:
- Cukup mahal untuk menambahkan kunci bersama baru ke sebuah proyek. Jumlah kursi sama dengan jumlah target dikalikan jumlah bahasa. Dalam contoh kami, ini adalah 30 tempat.
- Ada kemungkinan kesalahan saat kami menambahkan baris ke 1-2 target saat ini yang sedang kami kerjakan secara aktif, dan setahun kemudian mereka memutuskan untuk menghidupkan kembali satu atau lebih target. Anda harus menyinkronkan pelokalan satu sama lain secara manual, atau menulis skrip untuk ini. Dan jika beberapa kecerobohan ditunjukkan saat menambahkan atau menggabungkan cabang, dan kunci umum dicampur dengan yang spesifik, maka akan ada pencarian nyata.
- Volume file pelokalan. Mereka semua terus tumbuh, ini membuat sulit untuk bekerja dengan mereka dan meningkatkan kemungkinan konflik saat menggabungkan cabang.
Yang saya mau:
- Sehingga semua kunci publik disimpan dalam file terpisah.
- Untuk setiap target, ada file yang hanya menyimpan kunci khusus untuk itu, serta kunci umum dengan nilai untuk target ini.
Sebagai contoh, memiliki file umum localizable.strings dengan string
"shared_localizable_key1" = "MyApp title"
"shared_localizable_key2" = "MyApp description"
"shared_localizable_key3" = "Shared text1"
"shared_localizable_key4" = "Shared text2"
Saya ingin memiliki file localizable_app2.strings dengan kuncinya
"shared_localizable_key1" = "MyApp2 another title"
"shared_localizable_key2" = "MyApp2 another description"
"app2_screen1_key" = "Profile screen title"
Itu. mengatur prinsip warisan dalam file lokalisasi .
Sayangnya, Xcode tidak disesuaikan untuk ini, jadi saya harus menemukan kembali "sepeda" saya sendiri, yang tidak mau pergi lama karena fakta bahwa Xcode di sana-sini meletakkan tongkat di roda.
Kami memiliki proyek dengan 18 target dan 12 bahasa. Dan ini bukan lelucon, proyek ini sangat besar dan dibutuhkan banyak target di sana. Setiap kali kita perlu menambahkan kunci publik baru untuk terjemahan, kita berurusan dengan 216 file pelokalan. Butuh banyak waktu. Dan menambahkan target baru mengarah pada fakta bahwa Anda perlu menyalin 12 string yang dapat dilokalkan ke dalamnya . Secara umum, pada titik tertentu kami menyadari bahwa tidak mungkin untuk hidup seperti ini lagi dan kami harus mencari solusi.
Saya tidak akan berbicara lama tentang semua metode yang berhasil saya uji dalam prosesnya, saya akan langsung ke solusi yang berfungsi.
Jadi, pertama-tama kami perlu menemukan semua kunci bersama. Ini dapat dilakukan dengan menggunakan skrip, saya tidak akan menjelaskan secara detail, ini adalah tugas yang agak sepele.
Selanjutnya, ketika kami menerima file lokalisasi (basis) umum, atau lebih tepatnya 12 file fisik, serta satu set file untuk setiap target, kami pergi ke Xcode, tambahkan semua file di sana. Pada saat yang sama, kami tidak melampirkan file ke target mana pun, mis. panel kanan di bawah Keanggotaan Target harus tidak dicentang.
Kami akan menetapkan tanda ini hanya untuk file, yang akan menjadi hasil kerja skrip untuk merakit file.
Kemudian "sepeda" yang sama dimulai:
- Localization, build_localization.py.
- Localizable. localizable.strings.
- Localizable .
Kami hanya membutuhkannya untuk menambahkan tautan ke file proyek dengan benar, dan agar Xcode dapat mengenalinya dengan benar. Jika tidak, itu tidak akan menggunakannya untuk menemukan kunci. Misalnya, jika Anda membuat folder yang dapat dilokalkan dengan file localizable.strings yang benar di dalamnya, dan menambahkannya ke proyek sebagai referensi folder , maka Xcode tidak akan mengerti bahwa kami memberikan kunci pelokalan. Oleh karena itu, ambil folder Localizable , seret sebagai grup ( buat grup ) dan hapus centang pada kotak centang item salin jika diperlukan untuk mendapatkannya seperti gambar di bawah ini.
Hapus folder yang Dapat Dilokalkandan menambahkannya ke pengecualian untuk gita. Karena kita tidak membutuhkan hasil skrip di gita, itu akan berubah untuk setiap target dan menyumbat komit.
Sekarang kita perlu menambahkan skrip ke fase build. Untuk melakukan ini, di Build Phases, klik New Run Script Phase dan tulis skrip kami dengan parameter.
python3 ${SRCROOT}/Localization/build_localization.py -b “${SRCROOT}/BaseLocalization" -s "${SRCROOT}/Target1Localization" -d "${SRCROOT}/Localization/Localizable"
b adalah folder dengan lokalisasi dasar, s adalah lokalisasi target saat ini, d adalah folder hasil.
Pindahkan fase baru ke atas, itu tidak boleh lebih rendah dari fase Salin Sumber Daya Bundel . Itu. pertama, skrip menghasilkan file, dan baru kemudian file tersebut dimasukkan ke dalam bundel.
Sekarang penting untuk memberi tahu Xcode bahwa selama eksekusi skrip, file diubah, jika tidak selama pembuatan, itu akan menimbulkan kesalahan sehingga tidak dapat menemukan file. Selain itu, kesalahan hanya akan terjadi pada perakitan yang bersih, dan tidak akan segera jelas apa masalahnya. Dalam fase build, tambahkan semua file lokalisasi ke file output
Ini perlu dilakukan untuk setiap target. Cara termudah untuk melakukannya adalah dengan membuka proyek dengan editor teks, karena Xcode tidak akan dapat menyalin / menempelkan fase di antara target. Karenanya, parameter skrip -s untuk setiap target akan berbeda.
Sekarang, dengan setiap build, skrip akan mengambil file pelokalan dasar, menggulung perubahan dari file target (menambah, menimpa kunci) dan menghasilkan pelokalan di folder yang Dapat Dilokalkan , yang akan digunakan iOS untuk menemukan kunci.
Secara umum, kami mendapatkan apa yang direncanakan saat menerapkan mekanisme pewarisan:
- Kunci bersama berada dalam satu file dan tidak mengganggu yang lain. Waktu untuk proses memasukkan kunci baru telah dikurangi sebanyak 18! waktu.
- Kunci yang terkait dengan target tertentu ada di file yang sesuai.
- Ukuran file turun drastis. Kami menyingkirkan kekacauan baris yang berulang.
- Proses penambahan bahasa baru ke proyek juga sangat disederhanakan.
- Saat membuat target baru, Anda tidak perlu menyalin pelokalan dengan banyak baris yang tidak perlu. Buat file baru bernama localizable.strings dan tambahkan hanya yang diperlukan untuk target ini.
- Jika Anda memutuskan untuk menghidupkan kembali target lama, maka Anda tidak perlu melakukan apa pun dengan garis sama sekali, semuanya akan ditarik dari file dasar.
- Skrip tidak mengotori git, hasil pekerjaan tetap secara lokal dan dapat dihapus tanpa rasa sakit.
→ Skrip yang sudah selesai dapat diambil di sini
Saya tidak berpura-pura menjadi skrip yang sempurna, permintaan tarik dipersilakan.