FOSS 本地化/附錄 B:技術方面
前言 — 致謝 — 介紹 — 亞太地區的本地化工作 — 建議 — 附錄 A:關鍵概念 — 附錄 B:技術方面 — 進一步閱讀 — 資源和工具 — 詞彙表 — 關於作者 — 關於 APDIP — 關於 IOSN
在本附錄中,我們將討論更多技術細節。 目的是為實施者提供開始本地化的必要資訊。 但是,這並非旨在成為動手操作的食譜。
作為一種包含世界所有字元的通用字元集,Unicode 透過 16 位整數為其字元分配程式碼點,這意味著最多可以編碼 65,536 個字元。 然而,由於 CJK 字元集龐大,這已變得不夠用,Unicode 3.0 將索引擴充套件到 21 位,這將支援多達 1,114,112 個字元。
Unicode 程式碼點是介於 0 和 10FFFF 之間的數值,被劃分為 64K 個字元的平面。 在 Unicode 4.0 中,已分配的平面是平面 0、1、2 和 14。
平面 0,範圍從 0000 到 FFFF,稱為基本多語言平面 (BMP),這是先前 16 位方案分配的字元集。
平面 1,範圍從 10000 到 1FFFF,稱為補充多語言平面 (SMP),專門用於使用較少的歷史文字、專用發明文字和特殊符號。 這些包括哥特式、蕭伯納式和音樂符號。 未來,許多歷史文字可能會在這個平面中編碼。
平面 2,範圍從 20000 到 2FFFF,稱為補充表意文字平面 (SIP),是那些無法放入 BMP 中常用 CJK 字元塊的 CJK 字元的溢位分配區域。
平面 14,範圍從 E0000 到 EFFFF,稱為補充專用平面 (SSP),用於一些無法放入 BMP 中分配的小區域的控制字元。
還有兩個保留的平面:平面 15 和平面 16,供私人使用,其中沒有分配程式碼點。
基本多語言平面 (BMP) 或平面 0 最常見於通用文件。 程式碼點為當代文字中的常用字元分配,與 ISO/IEC 10646-1 的集合完全相同,如第 ý0 節中的圖 2 所示。請注意,E000 到 F900 之間的程式碼點保留供供應商私人使用。 此區域中未分配任何字元。
有幾種方法可以對 Unicode 字串進行編碼以進行資訊交換。 一個人可以使用固定大小的整數(稱為寬字元)簡單地表示每個字元,這是由 ISO/IEC 10646 定義的 UCS-2 和 UCS-4,分別使用 2 位元組和 4 位元組整數 [1],其中 UCS-2 僅適用於 BMP。 但常見的做法是使用稱為 UTF-8、UTF-16 和 UTF-32 的可變長度整數序列對字元進行編碼,分別用於 8 位、16 位和 32 位整數。 [2] 還有 UTF-7 用於 7 位嚴格的電子郵件傳輸,但 UTF-8 在大多數情況下是安全的。
UTF-32 是最簡單的 Unicode 編碼形式。 每個 Unicode 程式碼點都由單個 32 位無符號整數直接表示。 因此,它是一種固定寬度字元編碼形式。 這使得 UTF-32 成為傳遞單個字元值的 API 的理想形式。 但是,它在 Unicode 字串的儲存方面效率低下。

UTF-16 將範圍為 0000 到 FFFF(即 BMP)的程式碼點編碼為單個 16 位無符號整數。
補充平面中的程式碼點則表示為一對 16 位無符號整數。 這些程式碼單元對稱為代理對。 用於代理對的值在範圍 D800 - DFFF 之內,它們未分配給任何字元。 因此,UTF-16 閱讀器可以輕鬆區分單個程式碼單元和代理對。 Unicode 標準 [3] 提供了有關代理的更多詳細資訊。
UTF-16 是儲存通用 Unicode 字串的不錯選擇,因為它針對 BMP 中的字元進行了最佳化,BMP 用於 99% 的 Unicode 文字中。 它消耗的儲存量約為 UTF-32 所需儲存量的一半。
為了滿足傳統位元組取向的基於 ASCII 的系統的需求,UTF-8 被定義為一種可變寬度編碼形式,它保留了 ASCII 相容性。它使用 1 到 4 個 8 位程式碼單元來表示一個 Unicode 字元,具體取決於程式碼點值。程式碼點在 0000 到 007F 之間用一個位元組編碼,使任何 ASCII 字串成為有效的 UTF-8。超出 Unicode 的 ASCII 範圍,一些非表意字元在 0080 到 07FF 之間用兩個位元組編碼。然後,印度文字和 0800 到 FFFF 之間的 CJK 表意文字用三個位元組編碼。BMP 之外的補充字元需要四個位元組。Unicode 標準 [4] 提供了有關 UTF-8 的更多詳細資訊。
UTF-8 通常是網際網路首選的編碼形式。ASCII 相容性在從舊系統遷移中幫助很大。UTF-8 還具有位元組序列化和對 C 或其他程式語言 API 友好的優點。例如,使用位元組比較的傳統字串排序在 UTF-8 中有效。
簡而言之,UTF-8 是 Unicode 最廣泛採用的編碼形式。
字元屬性
[edit | edit source]除了程式碼點之外,Unicode 還提供了一個稱為 _Unicode 字元資料庫 (UCD)_ 的字元屬性資料庫,[5] 它包含一組描述以下屬性的檔案
- 名稱。
- 一般類別(分類為字母、數字、符號、標點符號等)。
- 其他重要的一般特徵(空格、連字元、表意文字、字母、非字元、已棄用等)。
- 字元整形(雙向類別、整形、映象、寬度等)。
- 大小寫(大寫、小寫、標題、摺疊;簡單和完整)。
- 數字值和型別(用於數字)。
- 指令碼和塊。
- 規範化屬性(分解、分解型別、規範組合類、組合排除等)。
- 年齡(標準中首次指定程式碼點的版本)。
- 邊界(音節簇、單詞、行和句子)。
- 標準化變體。
該資料庫對 Unicode 實現通常很有用。它可以在 Unicode.org 網站上找到。Unicode 標準 [6] 提供了有關該資料庫的更多詳細資訊。
技術報告
[edit | edit source]除了程式碼點、編碼形式和字元屬性之外,Unicode 還提供了一些技術報告,可作為實現指南。其中一些報告已作為附件包含在 Unicode 標準中,另一些則作為技術標準單獨釋出。
在 Unicode 4.0 中,標準附件是
- UAX 9:雙向演算法
- 從右到左流動的字元(如阿拉伯語或希伯來語)的定位規範。
- UAX 11:東亞寬度
- 與東亞傳統字元集互動時有用的 Unicode 字元資訊屬性規範。
- UAX 14:換行屬性
- Unicode 字元換行屬性規範以及確定換行機會的模型演算法。
- UAX 15:Unicode 規範化形式
- Unicode 文字四種規範化形式規範。使用這些形式,等效文字(規範或相容)將具有相同的二進位制表示。當實現將字串保留在規範化形式時,可以確保等效字串具有唯一的二進位制表示。
- UAX 24:指令碼名稱
- 將指令碼名稱分配給所有 Unicode 程式碼點。此資訊在正則表示式等機制中很有用,因為它比簡單地匹配塊名稱產生更好的結果。
- UAX 29:文字邊界
- 確定某些重要文字元素之間的預設邊界的指南:音節簇(“使用者字元”)、單詞和句子。
各個技術標準是
- UTS 6:Unicode 標準壓縮方案
- Unicode 壓縮方案規範和示例實現。
- UTS 10:Unicode 排序演算法
- 在符合 Unicode 標準要求的情況下,如何比較兩個 Unicode 字串的規範。UCA 還提供了預設 Unicode 排序元素表 (DUCET) 作為資料,指定所有 Unicode 字元的預設排序順序。
- UTS 18:Unicode 正則表示式指南
- 關於如何調整正則表示式引擎以使用 Unicode 的指南。
所有 Unicode 技術報告都可以從 Unicode.org 網站訪問。[7]
字型
[edit | edit source]字型開發工具
[edit | edit source]有一些用於開發字型的 FOSS 工具可用。雖然數量不如專有工具多,但它們足以完成工作,並且正在不斷改進。以下是一些有趣的例子
- _XmBDFEd_。[8]
- XmBDFEd 由 Mark Leisher 開發,是一款基於 Motif 的 BDF 字型開發工具。它允許編輯字型的點陣圖字形,對字形進行一些簡單的變換,在不同的字型之間傳輸資訊等。
- FontForge(以前稱為 PfaEdit [9]).
- FontForge 由 George Williams 開發,是一款用於開發輪廓字型的工具,包括 Postscript Type1、TrueType 和 OpenType。可以匯入字母的掃描影像並自動跟蹤它們的輪廓向量。可以編輯樣條線,並且可以應用諸如傾斜、縮放、旋轉、加厚等變換,以及更多操作。它提供了足夠的編輯 Type1 和 TrueType 字型屬性的功能。在最近的版本中,還可以編輯 OpenType 表格。但是,一個弱點是提示。它保證了 Type1 提示的質量,但不保證 TrueType 的質量。
- _TTX/FontTools_ [10]
- Just van Rossum 的 TTX/FontTools 是一種將 OpenType 和 TrueType 字型轉換為 XML 的工具,反之亦然。FontTools 是一個用於操作字型的庫,用 Python 編寫。它支援 TrueType、OpenType、AFM,並在一定程度上支援 Type 1 和某些 Mac 特定的格式。它允許轉儲 OpenType 表格,使用 XML 或純文字編輯器檢查和編輯它們,並將它們合併回字體。
字型配置
[edit | edit source]GNU/Linux 桌面中已有多個字型配置系統可用。最基本的是 X 視窗字體系統本身。但是,由於最近的一些發展,另一個名為 fontconfig 的字型配置已經開發出來,以滿足現代桌面的某些特定要求。這兩個字型配置將簡要討論。
首先,讓我們簡要討論一下 X 視窗架構,以瞭解字體系統。X 視窗 [11] 是一個客戶端-伺服器系統。_X 伺服器_ 是提供服務的代理,以控制硬體裝置,例如影片卡、顯示器、鍵盤、滑鼠或觸控板,以及將使用者輸入事件從裝置傳遞給客戶端。_X 客戶端_ 是 GUI 應用程式,它們請求 X 伺服器在螢幕上繪製圖形物件,並透過 X 伺服器饋送的事件接受使用者輸入。請注意,使用這種架構,X 客戶端和伺服器可以在網路中的不同機器上。在這種情況下,X 伺服器是使用者操作的機器,而 X 客戶端可以是執行在同一機器或網路中的遠端機器上的程序。
在這種客戶端-伺服器架構中,字型在伺服器端提供。因此,安裝字型意味著透過安裝字型並將它們註冊到其字型路徑來配置 X 伺服器。
然而,由於 X 伺服器有時用於在某些部署中提供瘦客戶端訪問,其中 X 伺服器可能在由軟盤引導或透過網路引導的廉價 PC 上執行,甚至從 ROM 中執行,因此並非總是適合在每個 X 伺服器上安裝字型。因此,字型服務已被委託給一個名為 _X 字型伺服器 (XFS)_ 的單獨服務。網路中的另一臺機器可以專門用於字型服務,以便所有 X 伺服器都可以請求字型資訊。因此,使用這種結構,X 伺服器可以配置為自行管理字型或使用字型伺服器中的字型,或兩者兼而有之。
但是,XFree86 中的最新更改已經解決了一些在客戶端管理字型的需求。Xft 擴充套件透過 X 客戶端提供的字型資訊提供了抗鋸齒字形影像。為此,Xft 擴充套件還在其第一個版本中為 X 客戶端提供了字型管理功能。這後來從 Xft2 中拆分出來,成為一個名為 fontconfig 的單獨庫。_fontconfig_ 是一個獨立於 X 的字型管理系統,這意味著它也可以應用於非 GUI 應用程式,例如列印服務。現代桌面,包括 KDE 3 和 GNOME 2,已將 fontconfig 作為其字型管理系統,並且得益於更緊密的整合,提供了簡單的字型安裝流程。此外,客戶端字型還允許應用程式進行所有字形操作,例如製作特殊效果,同時在螢幕和列印輸出中享受一致的外觀。
X 客戶端-伺服器架構的拆分不是獨立桌面上的標準做法。但是,重要的是要始終記住拆分,以啟用特定功能。
輸出方法
[edit | edit source]由於 XOM 的實用性仍在討論中,我們將只討論在兩個主要工具包中已實現的輸出方法:Pango of GTK+ 和 Qt。
Pango 文字佈局引擎
[edit | edit source]Pango ['Pan' 在英語中意為“所有”,而 'go' 在日語中意為“語言”] [12] 是一個為高質量文字排版而設計的多種語言文字佈局引擎。雖然它是 GTK+ 的文字繪製引擎,但它也可以在 GTK+ 之外用於其他目的,例如列印。[13] 本節將為本地化人員提供對 Pango 的概覽。有關更多詳細資訊,請參考 Pango 參考手冊。[14]
PangoLayout
[edit | edit source]從較高層次上講,Pango 提供了 PangoLayout 類,它負責在給定寬度的一列中排版文字,以及其他編輯所需的資訊,例如游標位置。其功能可概括如下
段落屬性
- 縮排
- 間距
- 對齊
- 對齊方式
- 字詞/字元換行模式
- 製表符
文字元素
- 獲取行及其範圍
- 獲取執行及其範圍
- 在 (x, y) 位置進行字元搜尋
- 字元邏輯屬性(是否換行,是否游標位置等)
- 游標移動
文字內容
- 純文字
- 標記文字
中級處理
[edit | edit source]Pango 還提供了一些中級文字處理函式的訪問許可權,儘管大多數客戶端通常不會直接使用它們。為了簡要了解 Pango 內部機制,這裡將討論一些重點內容。
- 專案化。 將輸入文字分解成方向和整形引擎一致的塊(專案)。這通常意味著相同語言、使用相同字型的文字塊。相應的整形和語言引擎也與這些專案相關聯。
- 斷行。 在給定文字專案中確定可能的行、字詞和字元斷點。它會呼叫專案中的語言引擎(或基於 Unicode 資料的預設引擎,如果不存在語言引擎)來分析字元的邏輯屬性(是否換行,是否字元斷點等)。
- 整形。 將文字專案轉換為字形,並進行適當的定位。它會呼叫專案中的整形引擎(或當前適合歐洲語言的預設整形引擎)來獲取字形字串,該字串提供渲染字形所需的資訊(程式碼點、寬度、偏移量等)。
Pango 引擎
[edit | edit source]Pango 引擎是在可載入模組中實現的,這些模組提供用於查詢和建立所需引擎的入口函式。在初始化期間,Pango 會查詢記憶體中所有已安裝引擎的列表。然後,當它對輸入文字進行專案化時,它也會搜尋列表中針對每個專案指令碼可用的語言和整形引擎,並建立它們以與相關的文字專案關聯。
Pango 語言引擎
[edit | edit source]如上所述,Pango 語言引擎被呼叫以確定特定語言文字專案中可能的斷點位置。它提供了一種方法來分析文字中每個字元的邏輯屬性,如表 3 所列。
| 標誌 | 描述 |
|---|---|
| is_line_break | 可以在字元前面斷行 |
| is_mandatory_break | 必須 在字元前面斷行 |
| is_char_break | 在進行字元換行時可以在這裡斷行 |
| is_white | 是空格字元 |
| is_cursor_position | 游標可以出現在字元前面 |
| is_word_start | 是單詞中的第一個字元 |
| is_word_end | 是單詞後第一個非單詞字元 |
| is_sentence_boundary | 是句子間空格 |
| is_sentence_start | 是句子中的第一個字元 |
| is_sentence_end | 是句子後第一個非句子字元 |
| backspace_deletes_character | 退格鍵會刪除一個字元,而不是整個字簇(Pango 1.3.x 中的新功能) |
Pango 整形引擎
[edit | edit source]如上所述,Pango 整形引擎會將特定語言文字專案中的字元轉換為字形,並根據指令碼約束對其進行定位。它提供了一種方法,將給定的文字字串轉換為一系列字形資訊(字形程式碼、寬度和定位)以及邏輯對映,該對映將字形映射回原始文字中的字元位置。有了所有提供的資訊,文字就可以在輸出裝置上正確渲染,並且游標也可以訪問它,儘管某些指令碼(如印度語、希伯來語和阿拉伯語)中邏輯順序和渲染順序有所不同。
Qt 文字佈局
[edit | edit source]Qt 3 的文字渲染與 GTK+/Pango 的文字渲染不同。它不是進行模組化,而是在一個名為 QComplexText 的類中處理所有複雜的文字渲染,該類主要基於 Unicode 字元資料庫。這等效於 Pango 提供的預設例程。由於 Unicode 資料庫的不完整性,此類有時需要額外的變通方法來覆蓋某些值。如果指令碼渲染不正確,開發人員應該檢查此類。
雖然依賴 Unicode 資料庫似乎是一種渲染 Unicode 文字的直接方法,但這使得該類變得僵化且容易出錯。建議定期檢查 Qt 網站以檢視最新版本中是否存在錯誤。但是,Qt 4 計劃進行一項重大更改,即 Scribe 文字佈局引擎,類似於 GTK+ 的 Pango。
輸入法
[edit | edit source]第 37 頁討論了鍵盤對映和輸入法的需求。本節將進一步討論如何實現它們,從鍵盤佈局開始。第 37-38 頁還提到,XIM 是當前 X Window 的基本輸入法框架。只有 Qt 3 依賴它,而 GTK+ 2 定義了自己的輸入法框架。XIM 和 GTK+ IM 都將在本文中討論。
鍵盤佈局
[edit | edit source]為特定語言提供文字輸入的第一步是準備鍵盤對映。X Window 使用 X 鍵盤 (XKB) 擴充套件來處理鍵盤對映。當您在 GNU/Linux 上啟動 X 伺服器時,一個虛擬終端會以原始模式連線到它,這樣鍵盤事件就會從核心傳送,沒有任何轉換。
然後,按鍵的 原始掃描碼 會根據鍵盤型號轉換為 鍵碼。對於 PC 上的 XFree86,鍵碼對映通常為 "xfree86",如 /etc/X11/xkb/keycodes 目錄中所儲存的那樣。鍵碼只是以符號形式表示鍵的位置,用於進一步引用。
然後,根據指定的佈局(例如 qwerty、dvorak 或特定語言的佈局),從 /etc/X11/xkb/symbols 目錄下的資料中選擇,將keycode 轉換為鍵磁碟機代號號(keysym)。Keysym 尚未表示字元。它需要一個輸入法來將一系列鍵事件轉換為字元,這將在後面介紹。對於 XFree86,所有上述設定都是透過setxkbmap 命令完成的。(在/etc/X11/XF86Config 中設定值意味著在 X 伺服器啟動時為setxkbmap 設定引數。)有很多方法可以描述配置,如 Ivan Pascal 的 XKB 說明中所述。[16] XFree86 4.x 的預設方法是 "xfree86" 規則(XKB 規則儲存在/etc/X11/xkb/rules 下),並帶有其他引數
- model - pc104、pc105、microsoft、microsoftplus、...
- mlayout - us、dk、ja、lo、th、...
- (對於 XFree86 4.0+,最多可以提供 64 個組作為佈局定義的一部分)
- variant - (主要用於拉丁語)nodeadkeys
- option- 組切換鍵、交換大小寫、LED 指示燈等。
- (請參閱/etc/X11/xkb/rules/xfree86 以瞭解所有可用選項。)
例如
$ setxkbmap us,th -option grp:alt_shift_toggle,grp_led:scroll
使用 US 符號作為第一個組,泰語符號作為第二個組來設定佈局。Alt-Shift 組合用於在兩個組之間切換。滾動鎖定 LED 將作為組指示器,噹噹前組不是第一個組時,它將處於開啟狀態,即對於泰語,開啟,對於 US,關閉。
你甚至可以混合兩種以上的語言
$ setxkbmap us,th,lo -option grp:alt_shift_toggle,grp_led:scroll
這將載入三語種佈局。Alt-Shift 用於在三個組之間迴圈;也就是說,Alt-RightShift 選擇下一個組,而 Alt-LeftShift 選擇上一個組。滾動鎖定 LED 將在泰語或寮國語組處於活動狀態時亮起。
可以透過在/etc/X11/XF86Config 中指定setxkbmap 的引數來在 X 伺服器啟動時進行初始化,方法是描述鍵盤的 "InputDevice" 部分,例如
Section "InputDevice"
Identifier "Generic Keyboard"
Driver "keyboard"
Option "CoreKeyboard"
Option "XkbRules" "xfree86"
Option "XkbModel" "microsoftplus"
Option "XkbLayout" "us,th_tis"
Option "XkbOptions grp:alt_shift_toggle,lv3:switch,grp_led:scroll"
EndSection
注意最後四行選項。它們告訴setxkbmap 使用 "xfree86" 規則,使用 "microsoftplus" 模型(帶有網際網路鍵),混合了 US 和泰語 TIS-820.2538 的佈局,以及一些用於組切換鍵和 LED 指示燈的更多選項。"lv3:switch" 選項僅適用於需要第三級換檔(即比普通換檔鍵多一級)的鍵盤佈局。在本例中,對於 XFree86 4.4.0 中的 "th_tis",此選項將RightCtrl 設定為第三級換檔。
提供鍵盤對映
[edit | edit source]如果一種語言的鍵盤對映不可用,則需要準備一個新的鍵盤對映。在 XKB 術語中,需要準備一個symbols 對映,將keysyms 與可用的 keycode 關聯起來。
最快的入門方法是閱讀/etc/X11/xkb/symbols 目錄下可用的 symbols 檔案。特別是,XFree86 4.3.0 預設規則使用的檔案位於pc/ 子目錄下。這裡,每個檔案只定義一個組,這與父目錄下的舊檔案不同,舊檔案中的組是預先組合的。這是因為 XFree86 4.3.0 提供了一種靈活的方法來混合鍵盤佈局。
因此,除非你需要支援舊版本的 XFree86,否則你只需要在pc/ 子目錄下準備一個單組符號檔案。
以下是th_tis 符號檔案的摘錄
partial default alphanumeric_keys
xkb_symbols "basic" {
name[Group1]= "Thai (TIS-820.2538)";
// The Thai layout defines a second keyboard group and changes
// the behavior of a few modifier keys.
key <TLDE> { [ 0x1000e4f, 0x1000e5b ] };
key <AE01> { [ Thai_baht, Thai_lakkhangyao] };
key <AE02> { [ slash, Thai_leknung ] };
key <AE03> { [ minus, Thai_leksong ] };
key <AE04> { [ Thai_phosamphao, Thai_leksam ] };
...
};
xkb_symbols 資料中的每個元素(第一個元素除外)都是 keysyms 與 keycode 的關聯,分別對應於未按 shift 和按 shift 版本。這裡,一些 keysyms 在 Xlib 中是預定義的。你可以在 <X11/keysymdef.h> 中找到完整的列表。如果一種語言的 keysyms 在那裡沒有定義,可以使用 Unicode keysyms,如<TLDE> 鍵條目所示。(事實上,這可能是新增新 keysyms 的一種更有效的方法。)Unicode 值必須以 "0x100" 為字首來描述單個字元的 keysym。
有關檔案格式的更多詳細資訊,請參閱 Ivan Pascal 的 XKB 說明。[17] 完成後,應重新生成 symbols.dir 檔案,以便列出 symbols 檔案
# cd /etc/X11/xkb/symbols # xkbcomp -lhlpR '*' -o ../symbols.dir
然後,可以按照上一節中描述的方法測試新的佈局。
此外,還可以向/etc/X11/xkbcomp/rules/xfree86.lst 新增條目,以便某些 GUI 鍵盤配置工具可以檢視佈局。
完成新的鍵盤對映後,還可以將其包含在 XFree86 原始碼中,其中 XKB 的資料儲存在xc/programs/xkbcomp 子目錄下。
XIM - X 輸入法
[edit | edit source]對於某些語言,文字輸入與從 keysyms 到字元的一對一對映一樣簡單,例如英語。對於歐洲語言來說,這稍微複雜一些,因為有重音符號。但對於中文、日文和韓文(CJK),一對一對映是不可能的。它們需要一系列擊鍵解釋才能獲得每個字元。
X 輸入法(XIM) 是一個基於區域設定的框架,旨在滿足任何語言的文字輸入需求。它是一個獨立的服務,用於處理 X 客戶端請求的輸入事件。X 客戶端中的所有文字輸入都由X 輸入上下文(XIC)表示。所有鍵盤事件都將傳播到 XIM,XIM 根據 XIC 的當前狀態確定對事件的適當操作,並將生成的字元傳回。
在內部,每個 XIM 的通用過程是透過呼叫 XKB 將鍵盤掃描程式碼轉換為 keycode,然後轉換為 keysym,其過程細節已在前面的章節中介紹。將 keysyms 轉換為字元的後續過程因不同的區域設定而異。
在一般情況下,XIM 通常使用客戶端-伺服器模型實現。XIM 實現的更詳細討論超出了本文件的範圍。有關更多資訊,請參閱 Xlib 文件[18] 的第 13.5 節和 XIM 協議[19] 。
通常情況下,使用者可以透過設定系統環境變數 XMODIFIERS 來選擇他們喜歡的 XIM 伺服器,如下所示
$ export LANG=th_TH.TIS-620 $ export XMODIFIERS="@im=Strict"
這指定了泰語區域設定的Strict 輸入法。
GTK+ IM
[edit | edit source]作為跨平臺工具包,GTK+ 2 定義了自己的框架,使用純 GTK+ API,而不是依賴於每個作業系統的輸入法。這提供了高階抽象,使輸入法開發比編寫 XIM 伺服器更容易。無論如何,GTK+ 仍然可以透過imxim 橋接模組使用現有的幾個 XIM 伺服器。此外,開發的輸入法會立即在它支援的所有平臺上對 GTK+ 可用,包括 XFree86、Windows 和 GNU/Linux 幀緩衝控制檯。唯一的缺點是輸入法無法與非 GTK+ 應用程式共享。
客戶端
[edit | edit source]一個普通的基於 GTK+ 的文字輸入小部件將提供一個 "輸入法" 上下文選單,可以透過在文字區域內右鍵單擊來開啟。此選單提供了所有已安裝的 GTK+ IM 模組的列表,使用者可以從中選擇。選單透過查詢所有已安裝的模組來初始化它們提供的引擎。
從客戶端的角度來看,每個文字輸入都由一個IM 上下文表示,它在每次按鍵事件後透過呼叫模組提供的鍵過濾器函式與 IM 模組進行通訊。這允許 IM 攔截按鍵並將它們轉換為字元。非字元鍵(例如功能鍵或控制鍵)通常不會被攔截。這允許客戶端處理特殊鍵,例如快捷鍵。
還有一些用於其他方向的介面。IM 還可以透過發出 GLib 訊號來呼叫客戶端執行某些操作,客戶端可以透過將回調連線到這些訊號來提供處理程式
- "preedit_changed"
- 未提交的(預編輯)字串已更改。客戶端可以更新顯示,但不更新輸入緩衝區,以便讓使用者看到按鍵。
- "commit"
- 一些字元已從 IM 提交。提交的字串也被傳遞,以便客戶端可以將其包含到其輸入緩衝區中。
- "retrieve_surrounding"
- IM 希望檢索游標周圍的一些文字。
- "delete_surrounding"
- IM 希望刪除游標周圍的文字。客戶端應該按要求刪除游標周圍的文字部分。
IM 模組
[edit | edit source]GTK+ 輸入法是使用可載入模組實現的,這些模組提供用於查詢和建立所需 IM 上下文的入口函式。這些用作文字輸入區域中 "輸入法" 上下文選單的介面。
IM 模組定義了一個或多個新的 IM 上下文類,並提供過濾器函式,供客戶端在按鍵事件發生時呼叫。它可以確定對鍵的適當操作,並在攔截事件時返回 TRUE,或在將事件傳回客戶端時返回 FALSE。
某些 IM(例如 CJK 和歐洲)可能執行狀態轉換,該轉換會將輸入字串與預定義的模式進行增量匹配,直到每個唯一的模式都匹配,然後才提交轉換後的字串。在部分匹配期間,IM 為每次更改向客戶端發出 "preedit_changed" 訊號,以便它可以將預編輯字串更新到顯示。最後,要提交字元,IM 向 IM 上下文發出 "commit" 訊號,並將轉換後的字串作為引數傳遞。某些 IM(例如泰語)是上下文敏感的。它需要檢索游標周圍的文字以確定適當的操作。這可以透過 "retrieve_surrounding" 訊號來實現。
此外,IM 可能會根據泰國高階 IM 的要求請求刪除客戶端輸入緩衝區中的部分文字。這也用於更正非法序列。可以透過“delete_surrounding”訊號完成此操作。
如前所述,GNU C 庫 根據 POSIX 和 ISO/IEC 14652 國際化。本節將討論這兩個語言環境。
一個語言環境 由其語言、國家和字元集描述。OpenI18N 指南[20] 中給出的命名約定為
lang_territory.codeset[@modifiers]
其中
- lang 是 ISO 639:1988 中定義的兩位字母語言程式碼。在沒有兩位字母版本的情況下,ISO 639-2 中的三位字母程式碼也被允許。美國國會圖書館的 ISO 639-2 註冊機構[21] 有一個完整的語言程式碼列表。
- territory 是 ISO 3166-1:1997 中定義的兩位字母國家程式碼。兩位字母國家程式碼列表可從 ISO 3166 維護機構網站線上獲取。[22]
- codeset 描述了語言環境中使用的字元集。
- modifiers 透過設定選項(開啟標誌或使用等號設定值)為語言環境新增更多資訊。選項用逗號分隔。這部分是可選的,並且依賴於實現。不同的 I18N 框架提供不同的選項。
例如
- fr_CA.ISO-8859-1= 使用 ISO-8859-1 字元集的加拿大法語
- th_TH.TIS-620 = 使用 TIS-620 編碼的泰國泰語
如果省略territory 或codeset,通常透過語言環境別名解析預設值。
請注意,對於GNU/Linux 桌面,目前不支援modifiers 部分。X Window 的語言環境修改器需要透過 XMODIFIERS 環境設定。
字元集是語言環境定義的一部分。它定義了字元集中的所有字元以及它們如何在資訊交換中進行編碼。在 GNU C 庫 (glibc) 中,語言環境是用 Unicode 描述的。
新的字元集被描述為 Unicode 子集,其中每個元素透過一個位元組字串與目標字元集中要編碼的位元組字串相關聯。例如,UTF-8 編碼的描述如下
... <U0041> /x41 LATIN CAPITAL LETTER A <U0042> /x42 LATIN CAPITAL LETTER B <U0043> /x43 LATIN CAPITAL LETTER C ... <U0E01> /xe0/xb8/x81 THAI CHARACTER KO KAI <U0E02> /xe0/xb8/x82 THAI CHARACTER KHO KHAI <U0E03> /xe0/xb8/x83 THAI CHARACTER KHO KHUAT ...
第一列是 Unicode 值。第二列是編碼的位元組字串。其餘的是註釋。
另一個例子是泰語的 TIS-620 編碼,它是一個簡單的 8 位單位元組編碼。程式碼表的前半部分與 ASCII 相同,後半部分從 0xA1 開始編碼第一個字元。因此,字元對映看起來像
... <U0041> /x41 LATIN CAPITAL LETTER A <U0042> /x42 LATIN CAPITAL LETTER B <U0043> /x43 LATIN CAPITAL LETTER C ... <U0E01> /xa1 THAI CHARACTER KO KAI <U0E02> /xa2 THAI CHARACTER KHO KHAI <U0E03> /xa3 THAI CHARACTER KHO KHUAT ...
根據POSIX,標準 C 庫函式根據以下類別進行國際化
| 類別 | 描述 |
|---|---|
| LC_CTYPE | 字元分類 |
| LC_COLLATE | 字串排序 |
| LC_TIME | 日期和時間格式 |
| LC_NUMERIC | 數字格式 |
| LC_MONETARY | 貨幣格式 |
| LC_MESSAGES | 語言環境語言的訊息 |
C 應用程式可以使用setlocale() 函式(在<locale.h>中宣告)設定當前語言環境。第一個引數表示要設定的類別;或者,LC_ALL 用於設定所有類別。第二個引數是要選擇的語言環境名稱,或者使用空字串("")來依賴系統環境設定。
因此,典型的國際化 C 程式的程式初始化可能如下所示
#include <locale.h> ... const char *prev_locale; prev_locale = setlocale (LC_ALL, "");
系統環境將被查詢以確定相應的語言環境,如下所示
- 如果定義了 LC_ALL,則將其用作語言環境名稱。
- 否則,如果定義了 LC_CTYPE、LC_COLLATE、LC_MESSAGES 的對應值,則將其用作對應類別的語言環境名稱。
- 對於上面檢查尚未定義的類別,如果定義了 LANG,則將其用作語言環境名稱。
- 對於上面檢查尚未定義的類別,將使用“C”(或“POSIX”)語言環境。
“C”或“POSIX”語言環境是一個虛擬語言環境,其中所有行為都是 C 預設值(例如,LC_COLLATE 的 ASCII 排序)。
LC_CTYPE 為在 <ctype.h> 中宣告的函式定義字元分類
- iscntl()
- isspace()
- isalpha()
- islower()
- toupper()
- isgraph()
- ispunct()
- isdigit()
- isupper()
- isprint()
- isalnum()
- isxdigit()
- tolower()
由於 glibc 基於 Unicode,並且所有字元集都被定義為 Unicode 子集,因此在每個語言環境中重新定義字元屬性毫無意義。通常,大多數語言環境定義中的 LC_CTYPE 類別引用預設定義(稱為“i18n”)。
受 LC_COLLATE 影響的 C 函式是strcoll() 和strxfrm()。
- strcoll() 以類似於strcmp() 的方式比較兩個字串,但在語言環境相關的方式下。請注意,strcmp() 的行為在不同的語言環境下絕不會改變。
- strxfrm() 將字串轉換為可以使用普通的strcmp() 進行比較的形式,以獲得與直接使用strcoll() 進行比較時相同的結果。
LC_COLLATE 規範是所有語言環境類別中最複雜的。有一個用於對 Unicode 字串進行排序的單獨標準,稱為ISO/IEC 14651 國際字串排序。[23] glibc 預設語言環境定義基於此標準。語言環境開發人員在開始建立自己的語言環境定義之前,可以考慮調查其中定義的通用可定製模板 (CTT)。
在 CTT 中,排序透過多個步驟完成。字元權重在多個級別(ISO/IEC 14651 有四個級別)中定義。一些字元可以在最初的步驟中被忽略(透過使用“IGNORE”作為權重),並在後面的步驟中被納入考慮以進行更精細的調整。有關詳細資訊,請參閱 ISO/IEC 14651 文件。
LC_TIME 允許對由 strftime() 函式格式化的日期/時間字串進行本地化。星期幾和月份可以翻譯成語言環境語言,並使用適當的日期。
每個文化都使用不同的約定來編寫數字,即小數點、千位分隔符和分組。這是由 LC_NUMERIC 涵蓋的。
LC_MONETARY 根據 ISO 4217 定義了語言環境中使用的貨幣符號,以及貨幣金額的書寫格式。<locale.h> 中定義了一個單一函式localeconv() 用於從兩個語言環境類別中檢索資訊。Glibc 在<monetary.h> 中提供了一個額外的函式strfmon() 用於根據 LC_MONETARY 格式化貨幣金額,但這不是標準 C 函式。
LC_MESSAGES 主要用於訊息翻譯。POSIX 本地化中唯一的使用是在本地化中描述是/否答案。
ISO/IEC 14652 文化約定規範方法 基本上是 POSIX 本地化規範的擴充套件。除了六個類別中的詳細資訊外,它還引入了六個新的類別
| 類別 | 描述 |
|---|---|
| LC_PAPER | 紙張尺寸 |
| LC_NAME | 個人姓名格式 |
| LC_ADDRESS | 地址格式 |
| LC_TELEPHONE | 電話號碼 |
| LC_MEASUREMENT | 計量單位 |
| LC_VERSION | 本地化版本 |
所有上述類別都已得到 glibc 的支援。C 應用程式可以使用 nl_langinfo() 函式檢索所有本地化資訊。
要構建本地化,必須準備一個 本地化定義 檔案,用於描述 ISO/IEC 14652 本地化類別的資料。(有關檔案格式,請參閱標準文件。)此外,在定義新的字元集時,必須為其建立一個 charmap 檔案;這會為每個字元提供一個符號名稱並描述編碼的位元組字串。
通常,glibc 在本地化定義中使用 UCS 符號名稱(<Uxxxx>),方便為任何 charmap 生成本地化資料。C 程式使用的實際本地化資料採用二進位制形式。本地化定義必須使用 localedef 命令進行編譯,該命令接受類似以下引數
localedef [-f <charmap>] [-i <input>] <name>
例如,要使用 TIS-620 charmap 從本地化定義檔案 th_TH 構建 th_TH 本地化
# localedef -f TIS-620 -i th_TH th_TH
charmap 檔案可以安裝在 /usr/share/i18n/charmaps 目錄中,本地化定義檔案可以安裝在 /usr/share/i18n/locales 目錄中,以便進一步參考。
locale 命令可以使用 “-a” 選項來檢查所有已安裝的本地化,並使用 “-m” 選項來列出支援的 charmap。不帶引數執行該命令將顯示環境設定選擇的本地化類別。
FOSS 中最常用的翻譯框架是 GNU gettext,儘管一些跨平臺 FOSS,例如 AbiWord、Mozilla 和 OpenOffice.org 由於跨平臺抽象的原因使用了自己的框架。在本節中,我們將簡要討論 GNU gettext,它涵蓋了超過 90% 的 GNU/Linux 桌面。但是,此處討論的概念也適用於其他框架。
程式原始碼中的訊息被放置在一個簡短的宏中,該宏呼叫 gettext 函式來檢索翻譯後的版本。在程式初始化時,將載入與 LC_MESSAGES 本地化類別對應的雜湊訊息資料庫。然後,在程式執行期間,透過快速查詢來翻譯宏涵蓋的所有訊息。因此,翻譯的任務是為特定語言構建訊息翻譯資料庫,並將其安裝在本地化的適當位置。有了這種準備,gettext 程式將根據本地化設定自動翻譯,無需修改原始碼。
GNU gettext 還提供用於建立訊息資料庫的工具。此過程中涉及兩種檔案
- PO(可移植物件)檔案。
- 這是一個人類可讀的格式檔案,供翻譯人員使用。它之所以命名為“可移植物件”,是因為它具有純文字性質,使其可以移植到其他平臺。
- MO(機器物件)檔案。
- 這是一個供機器讀取的雜湊資料庫。它是最終格式,將由 gettext 程式載入。商業 Unices 中有許多翻譯框架,這些 MO 檔案不相容。您還可能會發現一些 GMO 檔案作為 GNU gettext 工具的直接輸出。它們是包含一些 GNU gettext 增強功能的 MO 檔案。
我們將透過描述從頭開始翻譯的彙總步驟來討論重要的 GNU gettext 工具(參見圖 3)

- 使用 xgettext 實用程式提取訊息。您將獲得“package.pot”檔案作為 PO 檔案的模板。
- 從模板建立您語言的 PO 檔案,方法是將其複製到 “xx.po”(其中 xx 是您的本地化語言)並使用您的資訊填寫其標頭資訊,或者使用 msginit 實用程式。
- 透過使用您喜歡的文字編輯器編輯 PO 檔案來翻譯訊息。還可以使用一些專用於 PO 檔案的編輯器,例如 kbabel 和 gtranslator。
- 使用 msgfmt 實用程式將 PO 檔案轉換為 MO 檔案。
- 將 MO 檔案安裝到本地化的 LC_MESSAGES 目錄下。
- 當程式開發時,會引入新的字串。您不必從頭開始。相反,您像往常一樣使用 xgettext 實用程式提取新的 PO 模板,然後使用 msgmerge 實用程式將模板與當前的 PO 合併。然後,您可以繼續翻譯新訊息。
GNU/Linux 桌面需要翻譯的東西比 C/C++ 原始碼中的訊息更多。例如,系統選單項、事件的聲音列表也包含訊息,這些訊息大多采用 XML 格式,GNU gettext 不支援這些格式。您可以深入研究這些單個檔案來翻譯訊息,但這在維護上非常不方便,而且容易出錯。
KDE 擁有嚴格的翻譯策略。所有 KDE 核心應用程式的 PO 檔案都被提取到每個語言的單個目錄中,以便翻譯人員可以在一個地方翻譯桌面,而無需原始碼副本。但實際上,您有時需要檢視原始碼以驗證某些訊息的確切含義,尤其是錯誤訊息。這已經包含了上述 C++ 原始碼之外的所有訊息。
GNOME 採用了一種不同的方法。PO 檔案仍然像往常一樣放置在原始碼的“po”子目錄下。但是,GNOME 專案並沒有直接使用 xgettext 從原始碼中提取訊息,而是開發了一個名為 intltool 的自動化工具。該工具將從 XML 檔案中提取訊息到 PO 模板中,以及 xgettext 通常執行的操作,並將翻譯合併回去。因此,儘管翻譯系統異構,但翻譯人員仍然只需要為特定語言編輯單個 PO 檔案。
intltool 的使用很簡單。要生成 PO 模板,請將目錄更改為“po”子目錄並執行
$ intltool-update—pot
要生成新的 PO 檔案並與現有翻譯合併
$ intltool-update xx
其中 xx 是語言程式碼。這就是所需的一切。然後可以像往常一樣編輯 PO 檔案。
完成 PO 編輯後,典型的 GNOME 原始碼的常規安裝過程將自動呼叫適當的 intltool 命令,在安裝之前將翻譯合併回這些 XML 檔案中。請注意,在這個自動化系統中,您不應該再直接呼叫 xgettext 和 msgmerge 命令。
以下網站和文件提供了有關 KDE 和 GNOME 翻譯的更多資訊
- KDE 國際化主頁(http://i18n.kde.org)
- KDE 翻譯 HOWTO(http://i18n.kde.org/translation-howto/)
- GNOME 翻譯專案(http://developer.gnome.org/projects/gtp/)
- 本地化 GNOME 應用程式(http://developer.gnome.org/projects/gtp/l10n-guide/)
- 如何使用 GNOME CVS 作為翻譯人員(http://developer.gnome.org/doc/tutorials/gnome-i18n/translator.html)
PO 檔案是純文字檔案。可以使用您喜歡的文字編輯器對其進行編輯。但是,如前所述,翻譯是一項勞動密集型任務。值得考慮使用一些便捷的工具來加快工作速度。
通常,需要編輯器才能編輯UTF-8,因為KDE和GNOME現在都將其用作標準文字編碼。但是,以下工具具有許多其他功能。
KBabel是KDE軟體開發工具包的一部分,它是一個高階且易於使用的PO檔案編輯器,具有完整的導航和編輯功能、語法檢查和統計資訊。該編輯器將已翻譯、未翻譯和模糊的訊息分開,以便於查詢和編輯未完成的部分。
KBabel還提供CatalogManager,它允許同時跟蹤多個PO檔案,以及KBabelDict用於維護詞彙表,這對於翻譯一致性非常重要,尤其是在來自不同背景的團隊成員之間。
Gtranslator是GNOME桌面環境的PO檔案編輯器。它在核心功能上與Kbabel非常相似。
Gtranslator還支援自動翻譯,它可以學習並儲存翻譯,並可以使用熱鍵將其應用於以後的翻譯中。
- ↑ UCS是通用多八位位元組編碼字元集的縮寫
- ↑ UTF是Unicode(UCS)轉換格式的縮寫
- ↑ Unicode聯盟。Unicode標準,版本4.0。,第76-77頁。
- ↑ Unicode聯盟。Unicode標準,版本4.0。,第77-78頁。
- ↑ 同上,第95-104頁。
- ↑ Unicode.org,'Unicode技術報告';可從http://www.unicode.org/reports/index.html獲取。
- ↑ Unicode.org,'Unicode技術報告';可從http://www.unicode.org/reports/index.html獲取。
- ↑ Leisher,M.,'XmBDFEd字型編輯器';可從crl.nmsu.edu/~mleisher/xmbdfed.html獲取。
- ↑ Williams,G.,'PfaEdit';可從http://pfaedit.sourceforge.net獲取。
- ↑ Just van Rossum,J.,S 'TTX/FontTools';可從http://fonttools.sourceforge.net/獲取。
- ↑ 請注意與微軟的“Windows”商標的區別。X Window 沒有's'。
- ↑ Taylor,O.,'Pango';可從http://www.pango.org獲取。
- ↑ Taylor,O.,'Pango - 設計';可從http://www.pango.org/design.shtml獲取。
- ↑ GNOME開發網站,'Pango參考手冊';可從http://developer.gnome.org/doc/API/2.0/pango/獲取。
- ↑ 這是一個非常粗略的分類。顯然,還有進一步的步驟,例如斷行、對齊和對齊。這裡不需要討論它們,因為它們超出了本地化範圍。
- ↑ Pascal,I.,X鍵盤擴充套件;可從http://pascal.tsu.ru/en/xkb/獲取。
- ↑ Pascal,I.,X鍵盤擴充套件;可從http://pascal.tsu.ru/en/xkb/獲取。
- ↑ Gettys,J.,Scheifler,R.W.,Xlib-C語言X介面,X聯盟標準,X版本11發行版6.4。
- ↑ Narita,M.,Hiura,H.,輸入法協議版本1.0。X聯盟標準,X版本11發行版6.4。
- ↑ OpenI18N.org。OpenI18N語言環境名稱指南,版本1.1 - 2003-03-11;可從http://www.openi18n.org/docs/text/LocNameGuide-V11.txt獲取。
- ↑ 國會圖書館,ISO 639-2註冊機構;可從http://lcweb.loc.gov/standards/iso639-2獲取。
- ↑ ISO,ISO 3166維護機構(ISO 3166/MA) - ISO的國家程式碼聯絡點;可從http://www.iso.org/iso/en/prodsservices/iso3166ma/index.html獲取。
- ↑ ISO/IEC 14651 國際字串排序。ISO/IEC,ISO/IEC JTC1/SC22/WG20 - 國際化;可從http://anubis.dkuug.dk/jtc1/sc22/wg20獲取。