Aplikasi yang dipakai lintas negara tidak bisa menganggap format angka, tanggal, dan urutan abjad sama di mana pun. Objek Intl milik JavaScript menyerahkan penyesuaian itu ke data locale yang tersedia pada runtime, mulai dari NumberFormat, DateTimeFormat, sampai Collator. Topik ini juga menyentuh Unicode di balik string, karena panjang string dan perbandingannya ternyata tidak sesederhana kelihatannya.
Intl.NumberFormat mengikuti locale#
Intl.NumberFormat memformat angka mengikuti aturan locale, sehingga angka yang sama tampil berbeda bagi pembaca yang berbeda. Tag locale ditulis sebagai kode bahasa dan negara, misalnya id-ID untuk Indonesia dan en-US untuk Inggris Amerika, dan formatter juga menerima opsi gaya seperti percent.
const angka = 1234567.89;
for (const locale of ["id-ID", "en-US", "de-DE"]) {
console.log(locale, new Intl.NumberFormat(locale).format(angka));
}
const persen = 0.245;
console.log(new Intl.NumberFormat("id-ID", { style: "percent" }).format(persen));id-ID 1.234.567,89
en-US 1,234,567.89
de-DE 1.234.567,89
25%Angka yang sama menjadi 1.234.567,89 pada id-ID dengan titik sebagai pemisah ribuan dan koma sebagai pemisah desimal, sedangkan en-US menukarkan keduanya. de-DE kebetulan memakai bentuk yang sama dengan id-ID untuk angka polos. Pemilihan pemisah ini bukan soal estetika, melainkan kebiasaan baca, sehingga memaksakan satu bentuk untuk semua pembaca berisiko menimbulkan salah tafsir. Formatter sebaiknya dibuat sekali lalu dipakai ulang, karena pembuatannya mengolah data locale yang memakan waktu bila diulang di dalam perulangan.
Gaya currency melengkapi gaya persen untuk kebutuhan uang, dengan opsi currency berisi kode mata uang tiga huruf seperti IDR atau USD. Formatter menambahkan simbolnya di tempat yang lazim bagi locale terkait, sehingga mata uang yang sama bisa tampil di depan atau di belakang angkanya tergantung kebiasaan setempat. Karena kode mata uangnya ditulis lewat opsi, satu formatter tidak terikat satu negara. Kombinasi locale en-US dengan kode IDR pun sah bila konteksnya memang menampilkan rupiah pada antarmuka berbahasa Inggris.
Intl.DateTimeFormat untuk tanggal#
Intl.DateTimeFormat memformat object Date menjadi teks yang lazim bagi locale-nya, dengan opsi dateStyle untuk format siap pakai dan opsi komponen untuk susunan sendiri. Pemformatan mengikuti locale pada bahasa nama bulan dan hari, urutan komponen, serta pemisahnya.
const tanggal = new Date(2026, 2, 15);
for (const locale of ["id-ID", "en-US", "de-DE"]) {
console.log(locale, new Intl.DateTimeFormat(locale, { dateStyle: "long" }).format(tanggal));
}
console.log(new Intl.DateTimeFormat("id-ID", { weekday: "long", day: "numeric", month: "long", year: "numeric" }).format(tanggal));id-ID 15 Maret 2026
en-US March 15, 2026
de-DE 15. März 2026
Minggu, 15 Maret 2026Tiga baris pertama memperlihatkan kebiasaan yang berbeda untuk tanggal yang sama, yaitu urutan hari-bulan-tahun pada id-ID dan de-DE serta urutan bulan lebih dulu pada en-US, dengan nama bulan dalam bahasa masing-masing. Baris terakhir menyusun komponen sendiri lewat opsi, dan hari Minggu pun muncul tanpa menghitung manual. Satu hal yang sering menjebak adalah bulan pada konstruktor Date yang berbasis nol, sehingga new Date(2026, 2, 15) adalah 15 Maret, bukan 15 Februari. Untuk penanda waktu yang dibaca lintas zona, opsi timeZone tersedia agar tanggal dicetak mengikuti zona tertentu, bukan zona mesin pembacanya.
Intl.Collator untuk urutan yang benar#
Intl.Collator membandingkan string menurut aturan abjad locale, bukan menurut urutan kode karakternya. Perbedaannya baru terlihat ketika daftar memuat huruf beraksen, karena pengurutan bawaan sort membandingkan unit kode UTF-16 satu per satu.
const nama = ["Citra", "Clara", "Céline", "Cahya"];
console.log([...nama].sort().join(", "));
const collator = new Intl.Collator("id");
console.log([...nama].sort(collator.compare).join(", "));Cahya, Citra, Clara, Céline
Cahya, Céline, Citra, ClaraPengurutan bawaan menempatkan Céline paling akhir karena kode karakter é berada di atas semua huruf tanpa aksen, sedangkan Collator menempatkannya tepat setelah Cahya dengan memperlakukan é sebagai variasi huruf e. Untuk daftar nama pengguna atau kata dalam kamus, urutan hasil Collator yang terasa benar bagi pembaca. Metode compare milik collator dipakai langsung sebagai fungsi pembanding sort karena parameternya sama dengan fungsi comparator biasa. Kode wilayah pada tag locale juga boleh dilepas bila perbedaannya tidak relevan, dan Intl.Collator("id") tanpa kode negara tetap bekerja dengan aturan yang sama.
Unicode di balik string#
String JavaScript disimpan sebagai urutan unit kode UTF-16, dan karakter dengan titik kode di luar rentang dasar diwakili dua unit sekaligus yang disebut surrogate pair. Properti length menghitung unit, bukan karakter yang tampak, sehingga angkanya bisa mengejutkan pada emoji.
const emoji = "🐍";
console.log(emoji.length);
console.log(emoji.codePointAt(0));
console.log(emoji.codePointAt(0).toString(16));
console.log(String.fromCodePoint(0x1f40d));2
128013
1f40d
🐍Emoji ular itu hanya satu karakter bagi pembaca, tetapi length melaporkan 2 karena satu emoji diwakili dua unit kode. Sementara itu, codePointAt membaca kedua unit sekaligus menjadi satu titik kode penuh, yang dalam contoh ini bernilai heksadesimal 1f40d. String.fromCodePoint menjadi kebalikannya, menyusun karakter kembali dari titik kodenya. Permasalahan serupa muncul pada huruf beraksen yang bisa ditulis dua cara berbeda, satu titik kode tunggal atau huruf dasar diikuti tanda aksen, dan dua bentuk itu dihitung berbeda padahal tampak sama.
const teks1 = "café";
const teks2 = "cafe\u0301";
console.log(teks1.length, teks2.length);
console.log(teks1 === teks2);
console.log(teks1.normalize("NFC") === teks2.normalize("NFC"));4 5
false
trueKedua string itu tampak identik bagi pembaca, tetapi length keduanya 4 dan 5, dan perbandingan === menyatakan keduanya berbeda. Metode normalize("NFC") menyatukan kedua bentuk ke bentuk komposisinya, dan perbandingan menjadi true. Normalisasi ini penting sebelum membandingkan masukan pengguna, misalnya mencocokkan nama yang diketik dengan data yang tersimpan, karena kedua bentuk penulisan sama-sama sah pada data nyata.
Perulangan dan Array.from bekerja pada tingkat titik kode, bukan unit, sehingga keduanya menjadi cara menelusuri string tanpa membelah surrogate pair. Array.from("🐍") menghasilkan array berisi satu elemen, kebalikan dari length yang melaporkan dua, dan for...of memberikan satu karakter per langkahnya. Kombinasi keduanya cukup untuk penghitungan karakter yang tampak, sedangkan length tetap tepat untuk kebutuhan penyimpanan karena unit itulah yang benar-benar disimpan.
Ringkasan#
Intl.NumberFormat,Intl.DateTimeFormat, danIntl.Collatormemformat serta membandingkan mengikuti locale, dengan hasil yang bergantung data ICU pada runtime.- Formatter sebaiknya dibuat sekali lalu dipakai ulang, dan bulan pada konstruktor
Dateberbasis nol. lengthmenghitung unit kode UTF-16, sehingga emoji dihitung dua, sedangkancodePointAtdanfromCodePointbekerja pada titik kode penuh.normalize("NFC")menyatukan dua bentuk penulisan huruf beraksen sehingga perbandingannya menyatakan sama.
Referensi#
- Intl — MDN Web Docs — Sekilas API pelokalan beserta daftar konstruktorinya.
- Intl.NumberFormat — MDN Web Docs — Opsi format angka, persen, dan pemilihan locale.
- Intl.Collator — MDN Web Docs — Perbandingan string menurut aturan abjad locale.
- String.prototype.normalize() — MDN Web Docs — Bentuk normalisasi Unicode dan penggunaannya.