iT邦幫忙

2023 iThome 鐵人賽

DAY 5
1

在混亂的背景下,1987 年,任職於 Xerox 的 Joe Becker、Lee Collins 和任職於 Apple 的 Mark Davis 萌生了統一字元編碼的想法並開始傳教,促使當時電腦界的大佬們(例如 Microsoft、IBM、昇陽)成立了 Unicode 聯盟(Unicode Consortium),希望能解決目前各國文字編碼標準不一的問題。

起初,整合小組將 ASCII 失敗的原因歸咎為擴充性不足——1 Byte、共 8 bit、總計 256 個格子實在太少了,不如改用 2 個 Byte 共 16 bit,這樣就能放下 2^16 = 65,536 個字符了,這個數字已經是原本容量的 256 倍,用來收錄文字應該已經很夠了!

——嗎?

1991 年,Unicode 1.0 正式釋出,其中共收錄了 24 種書寫文字、共 7,129 個字符。當時漢字的整理還沒結束,所以這個最初的版本並沒有收錄漢字。

不過很快地,東亞各國不斷提交的新的漢字來源,眾多的學術與文化單位打算將歷史文本給電子化,希望連已經消亡的古代文字都收錄進來。面對大家爭先恐後提交、深怕晚了就沒位置放的態度,Unicode 聯盟發現他們輕忽了工作所需的數量級。

於是,在不改動原本規劃的 65,536 格子——後來這一區被稱作第 0 基本平面(Basic Multilingual Plane, BMP)——之外,額外規劃了第 1 到第 16 輔助平面(Supplementary Planes),總共 17 個平面(plane),每個平面都可以放入 65,536 個字符,將字符由原訂的 16 bit 表示法改為 21 bit,至多可以容納 1,114,112 個字符——藉此來收錄那些或許你曾聽過的、也或許沒聽過,目前人類正在使用的、或是曾經在歷史上被使用過的文字。

在經過 30 餘年的搜羅後,在 2023 年 9 月公告(也就是這個月!)的最新版 Unicode 15.1 中,已經收錄了多達 161 種書寫文字,其中包含 94 種當代文字、以及 67 種歷史曾使用的文字,共 149,813 個字符。

表示方法

Unicode 習慣透過十六進位的方式表示對應的碼位,並帶有 U+ 的前綴。

在 BMP 上的字符對應編號為 U+0000U+FFFF。而為了向下兼容 ASCII,前 128 個碼位與 ASCII 相同。基本上,我們日常生活中會看到的文字,像是拉丁文字、阿拉伯數字、符號、常見漢字、日文假名、韓文、希臘字母、西里爾字母都是放在這一區。

而輔助平面則對應 U+10000U+10FFFF。其中第一輔助平面除了用來放置了一些已經消亡的古代字母(像是楔形文字、埃及聖書體、西夏文),比較特別的是 Emoji 也被放在這一區。

第二與第三輔助平面基本上都是一些極為罕見的漢字,提交源頭基本上都是姓名罕用字、地名罕用字、宗教用字(佛經、道教、或神道教經書)、甲骨文隸定字、或是古典裡的訛字。

第四到第十三輔助平面目前都是空的(好消息是至少還有這麼多的空間),第十四輔助平面則是用來放置控制字元。

PUA(私人使用區)

考慮到 Unicode 已經明定不會收錄人造或虛構的文字,像是《魔戒( The Lord of the Rings )》裡的談格瓦(Tengwar)字母、《星艦迷航記( Star Trek )》的克林貢(Klingon)字母、流傳於文藝復興時期歐洲的底比斯(Theban)女巫字母就不在 Unicode 的收錄範圍等。

但這些「文字」,在學術界或是同好圈子裡,仍然會有需要「交換」的時機呀。因此,Unicode 將 BMP 後半部的 U+E000U+F8FF(共 6,400 個)、以及第十五、十六輔助平面(分別為 U+F0000 - U+FFFFFU+100000 - U+10FFFF,各 65,534 個)定為「私人使用區(Private Use Area, PUA)」。

PUA 裡的碼位都有定義編號,但該長成什麼樣子可以由使用者、組織、或是國家自行規劃。

舉例來說,愛沙尼亞語言研究院(Eesti Keele Instituut,EKI)便曾經使用該區放置那些還沒有被納入標準的衍生拉丁字符,例如在 U+E00A 放置 M with Cedilla;台灣的教育部萌典也曾將 U+FF545 定義為客語用字 𱱿(⿰皮卜,該字後來被正式收錄到 Unicode Ext-H,碼位為 U+31C7F)。

碼位排序 = 字母順序...嗎?

Unicode 的碼位順序為排序帶來了一定程度的方便,舉例來説,想要讓幾個詞按照英文字母的順序,只要由前往後,逐字比較 Unicode 碼位大小即可,但如果有擴充拉丁字母怎麼辦?

許多程式語言內建的 sort() 函數其實都是基於 Unicode 碼位的順序,也因此常常會出現變音符號順序在後的問題,例如:

# python

words = ['cafeteria', 'caffeine', 'café', 'cafe']
words.sort()
print(words)

> ['cafe', 'cafeteria', 'caffeine', 'café'] # 實際輸出
> ['cafe', 'café', 'cafeteria', 'caffeine'] # 理想輸出

caff 居然會比 café 還要更前面——因為 f (U+0066) 比 é (U+00E9) 還要前面,但在法文裡,é 不被當成獨立字母看待,而是 e 加上尖音符,所以位置應該要和 e 相同位階。

另外一個子是,在英文中 n 的後面接的是 o,但在西班牙文中,n 的後面是 ñ(西班牙語就是 español),再來才是 o。如果直接排序,因為 ñ (U+00F1) 的碼位在 n (U+006E) 跟 o (U+006F) 的後面,所以位置會被放到最後面。

# python

# pintar = 畫畫 / piocha = 鋤頭 / piña = 鳳梨
words = ['piocha', 'pintar', 'piña']
words.sort()
print(words)

> ['pintar', 'piocha', 'piña'] # 實際輸出
> ['pintar', 'piña', 'piocha'] # 理想輸出

對於某些有跨國客群的應用程式,這部分的順序要特別注意。

收錄原則

最後,讓我們來看看 Unicode 的設計原則:

  • Universality:提供單一且通用的字元集,將正在使用或歷史曾使用的字進行編碼。
  • Efficiency:易於處理與分析。
  • Characters, not glyphs:對抽象的字符進行編碼,而不是對於字形編碼。
    • 換句話說,這個這個字長怎樣是由字型檔案所決定,Unicode 只管理抽象意義的編碼。
  • Semantics:字元要有對應定義的語意。
  • Plain text:僅收錄於文字。
    • 話雖如此,卻有種符號越收越多的感覺...
  • Logical order:以邏輯順序保存。
  • Unification:統一不同語言中、同一種書寫系統中的相同字元。
  • Dynamic composition:允許附加符號與變音符號的動態組合。
  • Stability:字符一但被分配了碼位,就不會變動、移除、釋出,或是重分配。
    • 理論上應該要這樣,但歷史上因為各種 大人的因素 ,還是有編碼搬過家,不過那都是很久以前的事情了,現在已經不會再出現類似的抓馬了。
  • Convertibility:與其他常見的字元編碼集(例如 ASCII)可以互相轉換。

其中的 Characters, not glyphsUnificationDynamic compositionStability 原則至關重要,我們在接下來會陸續提到他們。


上一篇
DAY 04|字元集的難題:在 Unicode 之前
下一篇
DAY 06|Unicode 的實現:UTF
系列文
一起成為新世紀文字藝術師:深入玩轉 Unicode 和 OpenType30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言