Internationalization (i18n) — Desain untuk Dunia, Bukan Hanya Jakarta
i18n (i-18 huruf-n, singkatan internationalization) adalah proses mempersiapkan UI agar bisa mendukung berbagai bahasa, budaya, dan konvensi regional tanpa perlu redesign. Ini bukan sekedar translate teks — ini tentang arsitektur UI yang fleksibel.
Untuk developer Indonesia yang target pasar regional (Malaysia, Filipina, Thailand) atau internasional, memahami i18n dari awal menghemat puluhan jam refactor di masa depan.
Masalah yang Sering Terabaikan
1. Text expansion / contraction
Teks bahasa berbeda punya panjang berbeda:
- English → Indonesian: biasanya 20–30% lebih panjang ("Submit" → "Kirim" = lebih pendek, tapi "Delete" → "Hapus" sama, "Settings" → "Pengaturan" lebih panjang)
- English → German: 30–40% lebih panjang ("Settings" → "Einstellungen")
- English → Chinese/Japanese: 40–50% lebih pendek
- English → Arabic: variable, tapi RTL (right-to-left)
Dampak ke UI:
- Button dengan
width: 80px— pas di English, overflow di German - Navigation dengan item fixed-width — patah di bahasa panjang
- Card title yang potong dengan ellipsis setelah 20 karakter — bisa hilang info penting
Solusi:
- Gunakan
min-widthbukanwidthuntuk tombol - Biarkan container tumbuh (
width: autoataufit-content) - Test dengan pseudo-translation — generate teks palsu yang 40% lebih panjang
// Pseudo-localization: tambah karakter untuk simulate panjang
function pseudo(text) {
return `[!! ${text} ${"xxxxx".repeat(Math.ceil(text.length / 15))} !!]`;
}
2. Right-to-Left (RTL) — Arab, Ibrani, Persia
Bukan cuma membalik teks — seluruh layout di-mirror.
/* Jangan pakai `left` / `right` — pakai logical properties */
.container {
/* ❌ padding-left: 16px; */
/* ✅ */
padding-inline-start: 16px;
}
/* Browser + HTML dir="rtl" otomatis membalik */
html[dir="rtl"] .icon-arrow {
transform: scaleX(-1); /* ikon panah dibalik */
}
Yang harus di-flip:
- Layout horizontal (sidebar kiri → kanan)
- Ikon directional (arrow, chevron, undo/redo)
- Text alignment
- Progress bar
Yang tidak di-flip:
- Ikon non-directional (heart, check, warning)
- Clock hands (waktu selalu clockwise)
- Media playback button (play/pause)
- Angka (selalu ditulis LTR bahkan di bahasa RTL)
3. Makna Warna Berbeda-beda
| Warna | Barat | China | India | Arab |
|---|---|---|---|---|
| Merah | bahaya, marah | keberuntungan, perayaan | kesucian, pernikahan | bahaya |
| Putih | kesucian, pernikahan | dukacita, kematian | dukacita | netral |
| Hijau | sukses, alam | selingkuh, kehilangan kehormatan | kesuburan | Islam, sakral |
| Kuning | peringatan, ceria | royal, suci | perdagangan | dukacita |
Contoh kasus: desainer barat pakai amplop putih + pita ungu untuk e-card Tahun Baru China — di China itu asosiasi dengan pemakaman. Audit warna dengan stakeholder lokal untuk pasar utama.
4. Format Data Lokal
const angka = 1234567.89;
// ❌ hardcode
`Rp ${angka.toLocaleString()}` // "Rp 1,234,567.89" — pakai koma (English)
// ✅ lokal-aware
new Intl.NumberFormat("id-ID", {
style: "currency",
currency: "IDR"
}).format(angka);
// "Rp 1.234.567,89" — pakai titik sebagai thousand separator (Indonesia)
new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" }).format(angka);
// "$1,234,567.89"
new Intl.DateTimeFormat("id-ID", { dateStyle: "long" }).format(new Date());
// "15 April 2026"
new Intl.DateTimeFormat("en-US", { dateStyle: "long" }).format(new Date());
// "April 15, 2026"
Arsitektur i18n-Ready Sejak Hari Pertama
1. Pisahkan teks dari kode
// ❌ Hardcode
<button>Simpan Perubahan</button>
// ✅ Key-based dengan library (react-i18next, next-intl, formatjs)
<button>{t("actions.saveChanges")}</button>
File locale:
// locales/id.json
{ "actions": { "saveChanges": "Simpan Perubahan" } }
// locales/en.json
{ "actions": { "saveChanges": "Save Changes" } }
2. Pluralisasi
t("cart.itemCount", { count: 1 }) // "1 item"
t("cart.itemCount", { count: 5 }) // "5 items" (English) / "5 item" (Indonesia)
Bahasa Rusia/Polish punya 3+ aturan plural — library harus handle ini, jangan bikin sendiri.
3. Image & Illustration
- Jangan embed teks di gambar (susah translate)
- Gambar orang: pastikan representatif (bukan cuma Kaukasian)
- Gesture: thumbs-up positive di barat, ofensif di Timur Tengah
- Foto makanan: babi/anjing tidak sesuai di pasar Muslim/Hindu
Checklist i18n untuk Developer
- Semua teks via
t("key"), bukan hardcode - Container bisa grow — pakai
min-width, bukan fixedwidth - CSS pakai logical properties (
padding-inline,margin-block) - Currency/date pakai
Intl.NumberFormat/Intl.DateTimeFormat - Test dengan bahasa terpanjang (German) & bahasa RTL (Arab)
- Ikon directional punya varian flipped
- Warna sudah divalidasi stakeholder lokal
-
<html lang="id">dandir="..."ter-set
Kapan i18n Worth It?
- Ya: kalau ada roadmap expand ke pasar regional/global, bahkan kalau belum besok
- Ya: kalau produk SaaS dengan target international customer
- Tidak yet: MVP lokal dengan < 1000 user, validasi produk dulu
Aturan: i18n-ready ≠ i18n-complete. Arsitektur siap (pakai
t(), logical CSS) = murah. Translate 1000+ string = mahal. Siapkan arsitekturnya, translate-nya menunggu sampai ada pasar yang real.