Ajukan pertanyaan Anda dan dapatkan ringkasan dokumen dengan merujuk halaman ini dan penyedia AI pilihan Anda
Konten halaman ini diterjemahkan menggunakan AI.
Lihat versi terakhir dari konten aslinya dalam bahasa InggrisJika Anda memiliki ide untuk meningkatkan dokumentasi ini, silakan berkontribusi dengan mengajukan pull request di GitHub.
Tautan GitHub ke dokumentasiSalin Markdown dokumentasi ke clipboard
Mengapa ICU MessageFormat Tidak Dibuat untuk JavaScript
ICU MessageFormat adalah standar yang andal. Format ini lengkap, dipahami secara luas oleh penerjemah, dan dapat diproses oleh sebagian besar sistem manajemen terjemahan (TMS). Masalah utamanya terletak pada lingkungan runtime asalnya. ICU berakar dari C++ dan Java, tempat parser dan formatter pesan lengkap hanya memerlukan biaya komputasi yang dapat diabaikan jika dibandingkan dengan keseluruhan program. Namun dalam bundle browser, biaya tersebut harus dibayar pada setiap pemuatan halaman.
Artikel ini membahas asal-usul ICU, alasan mengapa sintaksnya terasa berat untuk bentuk jamak, dan mengapa kompatibilitas penuh menambah beban pada library i18n JavaScript apa pun. Jika Anda memerlukan panduan sintaks dasarnya, silakan baca referensi ICU Message Format terlebih dahulu.
Dari IBM ke Unicode Consortium
ICU merupakan singkatan dari International Components for Unicode. Sintaks pesannya bermula di Java: Taligent, sebuah joint venture antara Apple dan IBM, mengembangkan kelas-kelas internasionalisasi untuk JDK 1.1 (1997), termasuk java.text.MessageFormat. IBM melanjutkan pengembangannya sebagai ICU4J, mem-portingnya ke C/C++ sebagai ICU4C, dan merilisnya sebagai open source pada tahun 1999. Pada tahun 2016, ICU bernaung di bawah payung Unicode Consortium, yang juga mengelola CLDR, basis data lokal yang menjadi fondasinya.
Penggunaan awalnya
Fokus utamanya adalah perangkat lunak server dan desktop: aplikasi enterprise Java, produk-produk IBM, serta kemudian sistem operasi. Pesan-pesan disimpan dalam file .properties Java yang dimuat via ResourceBundle, atau dalam format paket sumber daya bawaan ICU untuk C/C++:
Salin kode ke clipboard
Salin kode ke clipboard
Versi awal JDK belum mengenal kata kunci plural. Versi tersebut mengandalkan choice dengan rentang angka ({0,choice,0#no files|1#one file|1<{0} files}), yang hanya cocok untuk bahasa dengan aturan jamak menyerupai bahasa Inggris. ICU menambahkan fitur plural berbasis aturan CLDR pada tahun 2008 (ICU 4.0) dan menambahkan select pada tahun 2010 (ICU 4.4).
Perbedaannya dengan .po
ICU sering kali disamakan dengan gettext, padahal keduanya berasal dari tradisi yang berlainan. File .po berasal dari GNU gettext (C, Linux, lalu PHP dan Python). Sebuah entri .po memuat pasangan sederhana msgid / msgstr, dan penentuan jamak dilakukan oleh ekspresi C di header file (Plural-Forms: nplurals=2; plural=(n > 1);). Tidak ada percabangan logika di dalam string pesan itu sendiri. Sebaliknya, ICU menanamkan percabangan langsung di dalam teks, sehingga satu pesan dapat menggabungkan plural, select, dan pemformatan angka sekaligus.
Di mana ICU berjalan saat ini
ICU4C terpasang secara bawaan di Android, iOS, macOS, Windows, Node.js, serta engine JavaScript di Chrome dan Firefox. API Intl standar pada browser sebagian besar dibangun di atasnya. Dengan demikian, browser sudah memiliki aturan jamak serta logika format angka dan tanggal dari ICU. Yang tidak dimiliki oleh browser adalah parser pesannya: Intl.MessageFormat saat ini masih berupa proposal tahap awal di TC39, dirancang dengan sintaks MessageFormat 2 yang baru dan tidak kompatibel secara langsung dengan ICU MessageFormat 1.
Latar belakang historis ini memperjelas motif desainnya:
- Ditujukan untuk runtime server dan desktop. Parsing string pesan saat runtime sangat murah di lingkungan tersebut, dan library diinstal satu kali di tingkat sistem operasi, bukan diunduh oleh setiap pengunjung situs web.
- Berupa DSL di dalam string. Percabangan, format angka, tanggal, dan struktur bertingkat disatukan dalam satu sintaks yang dapat disunting penerjemah tanpa menyentuh kode aplikasi.
- Menargetkan kelengkapan mutlak. Tersedia operator khusus untuk setiap kasus gramatikal yang mungkin dihadapi penerjemah.
Semua keputusan ini bukanlah kesalahan desain. Keputusan tersebut hanya berpijak pada asumsi lingkungan kerja yang tidak sama dengan browser web.
Aturan bentuk jamak terlalu berbelit-belit
Pola yang paling sering digunakan dalam ICU justru merupakan pola dengan tingkat kompleksitas sintaks tertinggi. Sebuah penghitung yang menyertakan kasus nol ditulis seperti berikut:
Salin kode ke clipboard
Format ini memerlukan nama argumen, kata kunci plural, label untuk setiap cabang, kurung kurawal berlapis, dan tanda # sebagai token khusus yang hanya berlaku di dalam blok plural. Apabila kita menambahkan pembedaan gender subjek, tingkat percabangannya semakin dalam:
Salin kode ke clipboard
Sembilan dari lima belas baris tersebut hanyalah kerangka sintaks murni. Bahasa Polandia, misalnya, membutuhkan empat cabang jamak untuk masing-masing dari ketiga opsi gender tersebut. Akibatnya, string terjemahan menjadi labirin kurung kurawal di mana satu kurung tutup } yang terlewat dapat merusak seluruh pesan, dan sering kali baru disadari saat aplikasi berjalan di tingkat runtime.
Dalam JavaScript, struktur yang sama dapat ditulis langsung sebagai data murni: sebuah objek dengan kunci kategori jamak, yang divalidasi langsung oleh sistem tipe dan editor kode, tanpa memerlukan parser perantara antara file dan nilai akhir.
Kelengkapan fitur menghasilkan biaya ekstra
ICU mencakup banyak sekali kapabilitas:
pluraldengan pencocokan eksak (=0) dan pergeseran (offset:)selectordinaldengan tabel urutan angka CLDR mandiriselectdengan kedalaman bertingkat bebas- Argumen
number,date, dantime, baik dalam format konvensional (number, currency) maupun skeleton (::currency/EUR compact-short) - Aturan karakter escape dan tanda kutip (
'{','') - Tag format rich-text pada implementasi tertentu (
<b>…</b>)
Sebuah library yang mengklaim kompatibilitas penuh 1:1 dengan ICU wajib menyertakan semua modul tersebut, karena proses build tidak dapat memastikan fitur mana saja yang akan dipakai dalam pesan Anda. Secara teknis, ini mengharuskan hadirnya:
- Parser untuk mengonversi string menjadi AST dan menangani kesalahan kurung kurawal yang rusak.
- Parser skeleton untuk memproses sintaks
::angka dan tanggal, yang merupakan bahasa kecil tersendiri. - Formatter yang membaca AST dan memetakan setiap simpul ke
Intl.PluralRules,Intl.NumberFormat, danIntl.DateTimeFormat.
Komponen ketiga sangat ringan karena JavaScript modern telah mengintegrasikan logika CLDR ke dalam Intl. Sebaliknya, dua komponen pertama hanya ada demi menafsirkan sintaks teks. Pada intl-messageformat dari FormatJS, yang menjadi fondasi bagi react-intl dan next-intl, kedua modul ini menyumbang sekitar 10 KB JavaScript terkompresi yang dikirim ke setiap pengunjung sebelum teks aplikasi Anda sempat dimuat.
Sebagian besar aplikasi web hanya membutuhkan sebagian kecil dari kemampuan tersebut: interpolasi {name} dan beberapa blok plural. Namun, pengguna tetap dipaksa mengunduh parser lengkap untuk skeleton, bilangan ordinal, dan offset karena bundler tidak dapat melakukan tree-shaking pada string yang di-parse saat runtime.
next-intl juga menghadapi tantangan serupa
Ini bukan sekadar kekhawatiran teoretis belaka. next-intl, salah satu library berbasis ICU yang paling populer, menarik kesimpulan yang persis sama. Pada versi 4.8 (Januari 2026), mereka meluncurkan opsi eksperimental precompile. Opsi ini mem-parse pesan ICU pada tahap build menjadi AST ringkas dan mengganti parser runtime dengan evaluator minimalis. Dokumentasi proyek tersebut mencatat bahwa langkah ini berhasil menghemat sekitar 9 KB JavaScript terkompresi.
Namun kompromi ini juga memperlihatkan keterbatasan pendekatan berbasis string: fungsi t.raw tidak lagi bekerja dalam mode pra-kompilasi karena string mentah ICU sudah tidak ada lagi saat runtime. Begitu browser berhenti mem-parse string, yang Anda kirimkan sebenarnya bukan lagi format asli ICU. Anda mengirimkan hasil kompilasi, dan sintaks teks hanya menjadi format perantara saat penulisan.
Pertanyaan mendasar pun muncul: jika browser tidak pernah membaca string tersebut secara langsung, untuk apa developer dan penerjemah harus repot-repot menuliskannya dalam sintaks string yang rumit?
Wujud pendekatan native dalam JavaScript
JavaScript sudah menyelesaikan bagian tersulitnya secara native. Intl.PluralRules memahami berbagai kategori gramatikal jamak dan ordinal lintas bahasa. Intl.NumberFormat dan Intl.DateTimeFormat menangani mata uang, satuan, notasi ringkas, dan sistem penanggalan. Yang tersisa hanyalah memilih cabang kondisi dan menyisipkan nilai, yang hanya memerlukan beberapa baris kode jika strukturnya dimodelkan sebagai data dan bukan string.
Inilah arsitektur yang diusung oleh Intlayer. Percabangan diekspresikan sebagai fungsi di dalam deklarasi konten bertipe, dan setiap bahasa hanya mendeklarasikan kategori yang memang diwajibkan oleh tata bahasanya:
Salin kode ke clipboard
Salin kode ke clipboard
Keuntungan utama dibandingkan ICU:
- Bebas dari parser dalam bundle. Struktur teks sudah menjadi objek JavaScript siap pakai saat tiba di browser. Fungsi
pluralmenentukan kunci menggunakanIntl.PluralRulesbawaan sistem. - Kesalahan terdeteksi saat proses build. Cabang yang terlewat atau saltik (typo) pada properti langsung memicu pesan error TypeScript, mencegah kerusakan di tahap produksi.
- Pemisahan logika format dari teks. Angka, tanggal, dan mata uang diproses melalui hook formatter yang langsung memanfaatkan
Intl, sehingga tidak membutuhkan parser skeleton. Fitur yang tidak terpakai tidak membebani ukuran bundle. Jika tidak ada konten yang menggunakan
gender, bundler akan menghilangkannya secara otomatis melalui tree-shaking.
Tentu saja pendekatan ini memiliki konsekuensinya tersendiri: diperlukan tahapan build, file konten berupa kode alih-alih teks biasa, dan sejumlah platform TMS yang dirancang khusus untuk string ICU mungkin tidak dapat membaca file deklarasi TypeScript secara langsung.
Kapan ICU tetap menjadi pilihan yang tepat
ICU tetap menjadi alternatif terbaik jika:
- Pipeline lokalisasi Anda sudah terikat penuh dengannya. Berbagai perangkat lunak TMS mengimpor dan mengekspor string ICU, dan tim penerjemah sudah terlatih dengan sintaks tersebut.
- Pesan dibagikan lintas platform secara bersamaan. Menggunakan katalog terjemahan yang sama untuk aplikasi iOS, Android, dan web merupakan argumen kuat untuk mempertahankan format terpadu.
- Anda telah memiliki repositori pesan ICU yang sangat besar. Menulis ulang ribuan pesan secara manual jarang sebanding dengan waktu dan biaya yang dikeluarkan.
Pada skenario terakhir, Anda tidak perlu dipaksa memilih antara penulisan ulang total atau menanggung parser yang berat. Adapter kompatibilitas react-intl dari Intlayer mampu membaca string ICU yang sudah ada (plural, select, selectordinal, #, format lama number / date / time). Ini memungkinkan migrasi bertahap, sehingga beban ICU hanya terbatas pada string warisan yang masih membutuhkannya.
Kesimpulan
ICU MessageFormat telah berhasil menyelesaikan masalah nyata: aturan tata bahasa adalah wewenang penerjemah dan tidak boleh dicampuradukkan dalam logika if (count === 1) di kode aplikasi. Solusi ini bekerja luar biasa pada lingkungan di mana parsing DSL berbasis string tidak menimbulkan beban. Di browser web, kompatibilitas penuh memaksa pengiriman kode parser untuk fitur yang tidak pernah digunakan sebagian besar proyek, hingga akhirnya library berbasis ICU pun beralih ke pra-kompilasi.
JavaScript telah menyediakan aturan CLDR yang lengkap melalui Intl. Kebutuhan inti dari format i18n modern hanyalah struktur percabangan yang terorganisasi, dan hal tersebut jauh lebih optimal jika direpresentasikan sebagai data bertipe.
Bacaan lanjutan
Komentar
Belum ada komentar. Jadilah yang pertama membagikan pemikiran Anda.
