Saya menggunakan angular-translate untuk i18n di aplikasi AngularJS.
Untuk setiap tampilan aplikasi, ada pengontrol khusus. Di pengontrol di bawah ini, saya menetapkan nilai yang akan ditampilkan sebagai judul halaman.
Kode
HTML
<h1>{{ pageTitle }}</h1>
JavaScript
.controller('FirstPageCtrl', ['$scope', '$filter', function ($scope, $filter) {
$scope.pageTitle = $filter('translate')('HELLO_WORLD');
}])
.controller('SecondPageCtrl', ['$scope', '$filter', function ($scope, $filter) {
$scope.pageTitle = 'Second page title';
}])
Saya memuat file terjemahan menggunakan ekstensi angular-translate-loader-url .
Masalah
Pada pemuatan halaman awal, kunci terjemahan yang ditampilkan, bukan terjemahan untuk kunci itu. Terjemahan adalah Hello, World!
, tapi saya melihat HELLO_WORLD
.
Kedua kalinya saya membuka halaman, semuanya baik-baik saja dan versi terjemahan ditampilkan.
Saya berasumsi bahwa masalahnya ada hubungannya dengan fakta bahwa mungkin file terjemahan belum dimuat saat pengontrol menetapkan nilainya $scope.pageTitle
.
Ucapan
Saat menggunakan <h1>{{ pageTitle | translate }}</h1>
dan $scope.pageTitle = 'HELLO_WORLD';
, terjemahan berfungsi sempurna sejak pertama kali. Masalahnya adalah saya tidak selalu ingin menggunakan terjemahan (misalnya untuk pengontrol kedua saya hanya ingin meneruskan string mentah).
Pertanyaan
Apakah ini masalah / batasan yang diketahui? Bagaimana ini bisa diselesaikan?
sumber
$scope.$watch
agak berlebihan karena Angular Translate menawarkan Layanan untuk digunakan dalam pengontrol. Lihat jawaban saya di bawah.$translate.instant()
menawarkan sama seperti layanan. Selain itu, perhatikan juga jawaban Pascal.Disarankan: jangan terjemahkan di pengontrol, terjemahkan dalam tampilan Anda
Saya akan merekomendasikan untuk menjaga pengontrol Anda bebas dari logika terjemahan dan menerjemahkan string Anda langsung di dalam tampilan Anda seperti ini:
Menggunakan layanan yang disediakan
Angular Translate menyediakan
$translate
layanan yang dapat Anda gunakan di Pengontrol Anda.Contoh penggunaan
$translate
layanan dapat berupa:Layanan terjemahan juga memiliki metode untuk menerjemahkan string secara langsung tanpa perlu menangani promise, dengan menggunakan
$translate.instant()
:Kelemahan dengan menggunakan
$translate.instant()
mungkin file bahasa belum dimuat jika Anda memuatnya async.Menggunakan filter yang disediakan
Ini adalah cara yang saya sukai karena saya tidak harus menangani janji dengan cara ini. Output dari filter dapat langsung disetel ke variabel cakupan.
Menggunakan direktif yang disediakan
Karena @PascalPrecht adalah pencipta perpustakaan yang luar biasa ini, saya akan merekomendasikan untuk mengikuti sarannya (lihat jawabannya di bawah) dan menggunakan petunjuk yang disediakan yang tampaknya menangani terjemahan dengan sangat cerdas.
sumber
Sebenarnya, Anda harus menggunakan direktif terjemahan untuk hal semacam itu.
Direktif menangani eksekusi asynchronous dan juga cukup pintar untuk membuka id terjemahan pada lingkup jika terjemahan tidak memiliki nilai dinamis.
Namun, jika tidak ada jalan lain dan Anda benar - benar harus menggunakan
$translate
layanan di pengontrol, Anda harus menggabungkan panggilan dalam$translateChangeSuccess
acara menggunakan$rootScope
kombinasi$translate.instant()
seperti ini:Jadi kenapa
$rootScope
dan tidak$scope
? Alasannya adalah, bahwa di angular-translate, acara$emit
diedit$rootScope
daripada$broadcast
diedit$scope
karena kami tidak perlu menyiarkan melalui seluruh hierarki cakupan.Mengapa
$translate.instant()
dan tidak hanya asinkron$translate()
? Saat$translateChangeSuccess
peristiwa dipicu, dipastikan bahwa data terjemahan yang diperlukan ada dan tidak ada eksekusi asinkron yang terjadi (misalnya eksekusi loader asinkron), oleh karena itu kita dapat menggunakan$translate.instant()
yang sinkron dan hanya mengasumsikan bahwa terjemahan tersedia.Sejak versi 2.8.0 ada juga
$translate.onReady()
, yang mengembalikan janji yang diselesaikan segera setelah terjemahan siap. Lihat changelog .sumber
{{::'HELLO_WORLD | translate}}'
.Untuk membuat terjemahan di pengontrol, Anda dapat menggunakan
$translate
layanan:Pernyataan itu hanya menerjemahkan pada aktivasi pengontrol tetapi tidak mendeteksi perubahan runtime dalam bahasa. Untuk mencapai perilaku itu, Anda dapat mendengarkan
$rootScope
acara tersebut:$translateChangeSuccess
dan melakukan terjemahan yang sama di sana:Tentu saja, Anda dapat merangkum
$translate
layanan dalam sebuah metode dan memanggilnya di pengontrol dan$translateChangeSucess
pendengar.sumber
Apa yang terjadi adalah Angular-translate mengamati ekspresi dengan sistem berbasis peristiwa, dan seperti dalam kasus pengikatan atau pengikatan dua arah lainnya, peristiwa dijalankan ketika data diambil, dan nilainya berubah, yang mana jelas tidak berfungsi untuk terjemahan. Data terjemahan, tidak seperti data dinamis lain di halaman, tentu saja harus segera ditampilkan kepada pengguna. Itu tidak bisa muncul setelah halaman dimuat.
Bahkan jika Anda berhasil men-debug masalah ini, masalah yang lebih besar adalah bahwa pekerjaan pengembangan yang terlibat sangat besar. Pengembang harus mengekstrak setiap string di situs secara manual, memasukkannya ke dalam file .json, mereferensikannya secara manual dengan kode string (misalnya, 'pageTitle' dalam kasus ini). Sebagian besar situs komersial memiliki ribuan string yang perlu dilakukan. Dan itu baru permulaan. Anda sekarang memerlukan sistem untuk menjaga terjemahan tetap selaras ketika teks yang mendasarinya berubah di beberapa di antaranya, sistem untuk mengirim file terjemahan ke berbagai penerjemah, mengintegrasikannya kembali ke dalam build, menerapkan ulang situs sehingga penerjemah dapat melihat perubahan mereka dalam konteks, dan seterusnya.
Selain itu, karena ini adalah sistem berbasis peristiwa yang 'mengikat', peristiwa dijalankan untuk setiap string tunggal di halaman, yang tidak hanya merupakan cara yang lebih lambat untuk mengubah halaman tetapi juga dapat memperlambat semua tindakan di halaman, jika Anda mulai menambahkan banyak acara ke dalamnya.
Bagaimanapun, menggunakan platform terjemahan pasca-pemrosesan lebih masuk akal bagi saya. Misalnya, menggunakan GlobalizeIt, penerjemah dapat langsung membuka halaman di situs dan mulai mengedit teks langsung di halaman tersebut untuk bahasa mereka, dan hanya itu: https://www.globalizeit.com/HowItWorks . Tidak diperlukan pemrograman (meskipun dapat dikembangkan secara terprogram), ini terintegrasi dengan mudah dengan Angular: https://www.globalizeit.com/Translate/Angular , transformasi halaman terjadi dalam sekali jalan, dan selalu menampilkan teks yang diterjemahkan dengan render awal halaman.
Pengungkapan penuh: Saya adalah salah satu pendiri :)
sumber