分類:程式設計 × 語言
處理 CJK(Chinese–Japanese–Korean)文字時,開發者會遇到許多不同於一般 ASCII 或拉丁字母的問題,例如字元編碼(Encoding)、Surrogate Pair、Unicode Normalization,以及資料庫排序(Collation)等。
本文整理程式設計中處理 Unicode CJK 所需的重要觀念。
1. Unicode 中的 CJK 區塊
Unicode 將 CJK 字元分散於多個不同區塊:
目前 Unicode 已收錄超過 103,000 個 CJK 漢字。
2. Surrogate Pair:JavaScript 與 Java 最常見的陷阱
自 Extension B(U+20000) 起,所有字元皆位於 BMP(Basic Multilingual Plane) 之外。
UTF-16 必須使用 兩個 Code Unit 才能表示一個字元。
const char = '𠀀'; // U+20000console.log(char.length); // 2(不是 1)console.log([...char].length); // 1console.log(char.codePointAt(0)); // 131072 = 0x20000因此:
使用 codePointAt(),不要使用 charCodeAt()
使用 [...str] 或 for...of 遍歷字串
- 避免使用
split('')處理 CJK 字元
這些都是避免 UTF-16 錯誤的重要做法。
3. 判斷 CJK 字元
可以依照 Unicode Code Point 判斷是否屬於 CJK:
function isCJKcodePoint { return ( codePoint >= 0x4E00 && codePoint <= 0x9FFF || codePoint >= 0x3400 && codePoint <= 0x4DBF || codePoint >= 0x20000 && codePoint <= 0x2A6DF || codePoint >= 0x2A700 && codePoint <= 0x2B73F || codePoint >= 0x2B740 && codePoint <= 0x2B81F || codePoint >= 0x2B820 && codePoint <= 0x2CEAF || codePoint >= 0x2CEB0 && codePoint <= 0x2EBEF || codePoint >= 0x30000 && codePoint <= 0x3134F || codePoint >= 0x31350 && codePoint <= 0x323AF || codePoint >= 0xF900 && codePoint <= 0xFAFF );}其中包含:
- CJK Unified Ideographs
- Extension A–H
- CJK Compatibility Ideographs
4. 資料庫中的 CJK:Collation 與索引
在 PostgreSQL 或 MySQL 儲存 CJK 時,常見注意事項包括:
Collation(排序規則)
建議使用 und-x-icu 或 zh-x-icu,避免使用 C 排序規則,以獲得較合理的漢字排序。
Indexing(索引)
PostgreSQL 可搭配 pg_trgm 建立 CJK 搜尋索引。
- Encoding(編碼)
建議全程使用 UTF-8,並確認資料庫連線的 Encoding 設定一致。
- Full-text Search(全文搜尋)
CJK 並沒有空格分詞,因此通常需要使用專門的斷詞器,例如:
- jieba
- MeCab
- ICU Tokenizer
5. 簡體與繁體轉換
簡體與繁體之間並不是一對一對應。
同一個簡體字可能依語境對應不同繁體字。
例如:
发可能轉換為:
發(發展、發現)或:
髮(頭髮)因此,
簡繁轉換不能只依靠單純字典映射,
還需要考慮上下文語意。
目前 OpenCC 是處理簡繁轉換最成熟且廣泛使用的開源工具之一。