Unicode & Character Encoding — i18n

Unicode & Character Encoding Sebelum Unicode, setiap bahasa punya encoding sendiri (ASCII, ISO-8859-1, Shift-JIS, dll). Ini menyebabkan "mojibake" — teks yang t

Unicode & Character Encoding

Sebelum Unicode, setiap bahasa punya encoding sendiri (ASCII, ISO-8859-1, Shift-JIS, dll). Ini menyebabkan "mojibake" — teks yang tampil sebagai karakter acak karena encoding tidak cocok.

Unicode adalah standar universal yang memberikan code point unik untuk setiap karakter dari semua bahasa di dunia — lebih dari 150.000 karakter.

Code Points

// Setiap karakter punya code point unik
"A"  → U+0041
"Ω"  → U+03A9
"あ" → U+3042
"🎉" → U+1F389
"中" → U+4E2D

// JavaScript: melihat code point
"A".codePointAt(0)    // 65 (0x41)
"🎉".codePointAt(0)  // 127881 (0x1F389)

UTF-8: Encoding Dominan di Web

UTF-8 adalah cara meng-encode code point Unicode ke bytes. Dia variable-length: 1-4 bytes per karakter.

// UTF-8 byte lengths
"A"  → 1 byte   (0x41)
"Ω"  → 2 bytes  (0xCE 0xA9)
"あ" → 3 bytes  (0xE3 0x81 0x82)
"🎉" → 4 bytes  (0xF0 0x9F 0x8E 0x89)

// Backward compatible dengan ASCII!
// Karakter ASCII (0-127) tetap 1 byte di UTF-8

Deklarasi di HTML

<!-- SELALU set charset di awal <head> -->
<meta charset="UTF-8">

<!-- HTTP header juga penting -->
Content-Type: text/html; charset=utf-8

BOM (Byte Order Mark)

BOM (U+FEFF) adalah karakter invisible di awal file yang menandai encoding. Untuk UTF-8, BOM umumnya tidak diperlukan dan bisa menyebabkan masalah.

// PHP: BOM bisa merusak header()
// ❌ File PHP dengan BOM → "Headers already sent"

// Cek BOM di terminal
hexdump -C file.txt | head -1
// BOM UTF-8: ef bb bf

// Hapus BOM
sed -i '1s/^\xEF\xBB\xBF//' file.txt

String Length Gotcha

// JavaScript: .length menghitung UTF-16 code units, bukan karakter
"Hello".length     // 5 ✅
"こんにちは".length   // 5 ✅
"🎉".length        // 2 ❌ (surrogate pair)

// Solusi: Array.from atau Intl.Segmenter
Array.from("🎉").length           // 1 ✅
[..."🎉👨‍👩‍👧‍👦"].length              // bisa lebih dari 1 (ZWJ sequence)

// Intl.Segmenter — paling akurat
const seg = new Intl.Segmenter();
[...seg.segment("👨‍👩‍👧‍👦")].length   // 1 ✅

Database & Unicode

-- MySQL: gunakan utf8mb4, BUKAN utf8 (yang cuma 3 bytes)
CREATE TABLE posts (
  title VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
);

-- PostgreSQL: default sudah UTF-8 ✅

Yang akan kamu pelajari