發新話題

[分享] Linux 國際化本地化和中文化

Linux 國際化本地化和中文化

一 國際化、本地化和中文化
  • 國際化、本地化和多語言化的概念
       一般來說, "國際化"是指把原來為英文設計的計算機系統或應用 軟件改寫為同時支持多種語言和文化習俗的過程.在軟件創作的初期,一般的編程語言,編譯,開發都是只支持英文的, 為了適應更廣的語言 和文化習俗,軟件有必要在設計結構和機制上支持多語言的擴展特性, 這一過程稱為國際化.國際化僅僅是在軟件設計上提供了使用多語 言的可能. "本地化"是指把計算機系統或者應用軟件轉變為使用並兼容某種 特定語言的過程.比如,把原來為英文設計軟件製作為支持中文的軟 件就是本地化的一種.它主要包括翻譯文本信息,界面信息,重新設計圖標等等. 語言和文化習俗因地域不同而差別很大.對某一特定的地域的 語言環境稱為"locale".它不僅包括語言和貨幣單位,而且還包括 數字標示格式, 日期和時間格式.國際化了的軟件含有一個"locale" 的"參量", 使用該"locale"參量便可以設置某一區域所用的語言環境. 在國際化部分中只處理語言的部分叫"多語言化".比如, 一個 "多語言化"的軟件可以同時管理諸如英語,法語,中日韓文,阿拉伯語等. 在英文中, 國際化(Internationalization)被縮寫為I18N, 即只 取首尾兩個字母,中間字母為18個.同樣地, 本地化(Localization) 縮寫為L10N, 多語言化(Multilingualization)縮寫為M17N. 在今天, Internet把世界各地的計算機聯接了起來, 共享信息和 技術是必然的趨勢和需要.因此各地的計算機系統可以互相交流變得越來越重要.在Linux系統向桌面普及的過程中, Linux軟件也需要國 際化和本地化.
  • 中文化
       "中文化"是一個很模糊的概念.在Linux上的"中文化"它既包含使 軟件或系統國際化,又包含使軟件本地化.也就是說, "中文化"不僅僅 是只把軟件本地化這麼簡單的事情, 更重要的是因為Linux直接支持中文的軟件太少, 做"中文化"必須先做"國際化". 由於歷史的原因, 現階段使用的中文又有簡體中文和繁體中文之 分.所使用的編碼也不同.支持中文的軟件應該同時支持簡體中文和繁體中文, 這對軟件的國際化提出了更高的要求. 1999年是中國Linux發展和普及過程中最重要的一年, 其中湧現了 許多製作中文Linux發佈版本的公司.中文Linux的技術都是採取了中文化的捷徑----中文平台.儘管都是中文平台, 但是具體實現的技術特點 各不相同.充分展示了中文平台在Linux中文化過程中的魅力.中文平台在短期內發揮了巨大的作用, 加速Linux的中文化過程並推動Linux在中 國的普及. 中文平台的主要技術特點是不用修改西文應用軟件, 便可以顯示和 輸入中文(有的情況下會失效).具體地說,就是利用自己的規範去修改 X系統的底層函數.從修改的層次上分為(1)修改函數庫libX11.so,這種 方式是動態修改, 又稱外掛方式.外掛方式的實現可以是直接修改X11庫 或使用LD_PRELOAD載入動態庫修改.(2)修改X Server部分, 又稱內嵌方式, 它的實現也分為兩種, 直接修改X Server部分和建立虛擬Display(X傳輸協議的部分代理).
  • X11 國際化的歷史和級別
       早期的X11R4版本中, 僅僅含有支持單字節和雙字節字體的函數, 所以它不能算是國際化的函數庫.此後,一個叫做"mltalk"的X協會 成立並著手研究X窗口系統的國際化問題.眾多的X窗口系統供應商也參與了該組織.因為對國際化的研究剛剛開始, 所以mltalk提出的了 一個基本問題:什麼是X窗口系統的國際化? 對它的解釋也各不相同. 實際上, 即使是現在,人們對國際化的定義仍然存在分歧, 分歧的焦點 主要集中於對軟件或系統怎樣程度的國際化才算是真正的國際化. 按國際化的級別來分, 下列幾種情況都屬於國際化:
    • 語言可以切換.在系統啟動時可以設置某種語言
    • 使用不同語言的軟件可以同時使用, 在應用軟件啟動時可以 設置某種語言
    • 使用不同語言的軟件可以同時使用, 而且應用軟件的語言可 以動態切換
    • 使用不同語言的軟件可以同時使用, 而且在應用軟件中可以 同時使用不同語言
    顯然, 第(4)種國際化方式是最完善的方式, 其次是第(3)種,第(2)種 和第(1)種.mltalk 最終決定使用第(3)種, 原因是需要支持第(4)種的 X窗口系統供應商是少數的.從目前Linux上的國際化情況看,支持第(2), (3)種的國際化軟件是最常見的, 但是第(4)種軟件比較少見,而且應用的 意義不是很大. 基於上述觀點, X11R5 的目的是, 創建支持不用重新編譯源代碼 就可以適應於語言環境的應用軟件開發平台.確切地說,就是國際化 的結構是基於標準C函數setlocale的.X11R5 確立了以下規範:
    • 切換語言的機制
    • 與語言無關的輸出接口
    • 與語言無關的輸入接口
    • 資源文件的國際化
    • X工具(Xt)的國際化
    此後, 以X11R5 為基礎, OSF/Motif 完成了國際化改造, 並且成為 被用戶廣泛接受的高層圖形軟件庫,直到今天, 一些大型的軟件仍然使用 Motif 作為基礎庫使用, 如Java, Netscape等.X11R5的規範在制定的同時,為了檢測規範的實用性, 開發了兩套樣本應用, 即 Xsi 和 Ximp.兩套應用 在輸入協議上和對locale的支持上都不同,從而為開發商帶來了不便. X11R6 解決了X11R5中存在的問題, 主要的變化有,
    • 定義了標準的輸入協議
    • Locale數據格式定義
    • 只採用了一種國際化工具的樣本應用模塊
    在輸出上, X11R6增加了從右到左的的書寫方式, 以支持阿拉伯語和 希伯來語等,增加了從上到下的書寫方式, 以支持中文和日文等的書寫.
  • 國際化標準組織
       這裡所說的國際化標準是國際化標準組織或一些相關組織制定的一些標準, 而且這些標準也會隨時間不同而經常更新.國際化標準涉及到字符集,編碼,字體處理,打印,文本繪製, 用戶界面, 語言輸入方法, 數據交換, 文化習俗,等方方面面. 下面列出一些制定國際化標準的組織:
    • Li18nux(Linux I18n)
    • ANSI(American National Standards Institute)
    • POSIX(Portable Operating System Interface for Computer Environments)
    • ISO(International Standards Organization)
    • IEEE(Institute of Electrical and Electronics Engineers)
    • Unicode Consortium
    • Open Group(X Consortium and OSF)
    • X/Open and XPG
其中, ANSI/ISO 制定了使用C編程語言編寫國際化軟件的通用接口.ISO 制定了字符集標準和其它影響locale名字的標準.IEEE提供了一些國際化的通用庫函數和設置管理不同locale的用戶命令. Open Group是Unix和X窗口 系統的國際化標準設立組織.Li18nux 是一個專門從事Linux上的軟件國際化 規範制定的組織. 國際化的意義
   國際化,特別是國際化中制定的標準,是當今開發國際化軟件所必須 的.它也是軟件開發的必然趨勢.遵循國際化標準,可以更高效地開發和 調試軟件和移植軟件, 降低軟件的開發費用, 使用戶更方便地使用軟件.從國際環境來看, 新開發的基本的庫函數都會支持國際化標準, 基於這些 函數庫所開發的應用軟件理所當然地支持國際化標準,同時有大批的Linux 愛好者把以前不符合國際化標準的軟件進行了改造, 使它們在一定程度上符合國際化標準.使用國際化標準的軟件, 淘汰非國際化標準的軟件已成為 一種趨勢. 從國際化的發展歷史看, 其中許多標準都有日本的商業機構參與, 支持 日文的軟件變得越來越多,而從日語軟件移植為中文軟件相對於直接移植 西文軟件相當容易, 有時甚至不用改動,這樣就節省了許多不必要的勞動. 反過來, 符合國際化標準的中文軟件又影響日語和韓語軟件,成滾雪球之 勢向前發展.其次, 軟件商的開發比較看好亞洲市場中的日本市場,在 Unix/Linux上的日語軟件或操作系統一般是符合國際化標準的, 所以兼容 這一標準是十分必要的.當然,目前的國際化標準也存在不足之處, 特別是 對中文這一特殊語言(因為含有GB和Big5兩種不能共存的編碼)的處理上,應該由中國人在原來的基礎上作相應的擴展. 對中文Linux來說, 遵循國際化也是必然的趨勢.在以中文平台為基礎 的中文Linux上,軟件移植已成為必須解決的問題, 這個問題的最終解決 方法就是遵循同一標準,就目前來說遵循國際化標準是唯一的方法.鑒於 目前中文Linux上的中文平台的混亂狀態,國際化標準是從無序到有序過渡 的必然途徑. 軟件的國際標準化也為最終用戶帶來極大的好處, 如同時支持簡體中文 和繁體中文,中文操作為雙字節操作, 中文輸入能夠在更大的程度上使用 標準輸入接口帶來的好處,如輸入服務器的定位等交互式操作. 國際化的另一個特點是工作在應用軟件級別, 所以國際化不會給X窗口 系統帶來不穩定性.

參考資料:Linux I18N: http://www.li18nux.org/

本帖最近評分記錄
  • 蔡逸竹 經驗 +50 感謝您對論壇的貢獻 2007-3-31 19:42
  • 蔡逸竹 金幣 +50 感謝您對論壇的貢獻 2007-3-31 19:42

TOP

二 Locale
  • Locale 的概念
       Locale 是ANSI C語言中最基本的支持國際化的標誌, 對中文Linux來說, 如果它支持國際化,那麼支持中文Locale是最基本的要求. Locale 是軟件在運行時的語言環境, 它包括語言(Language), 地域 (Territory)和字符集(Codeset).其格式為: 語言[_地域[.字符集]]. 如對中文GBK字符集, locale的格式是:zh_CN.GBK. 目前Linux上的中文 Locale還不完善, glibc2.1.x中的許多涉及Locale的C函數還不正確.如果用戶需要安裝中文GBK Locale, 可以直接使用TLC6.0中的:
    • glibc-2.1.2(含有GBK模塊)
    • localedata-zh-0.07
    • /usr/X11R6/lib/X11/locale/zh_CN.GBK/XLC_LOCALE(X 下的 GBK Locale)
    Locale 包含了以下分類:
    • LC_COLLATE, 用於比較和排序.排序對中文來說也比較重要, 但是現在的glibc中的locale對中文支持有些問題.漢字排序的的方式有許多種, 按照發音(漢語拼音)或者漢字筆畫來排序 是比較容易被接受的.
    • LC_CTYPE, 用於字符分類
    • LC_MONETORY, 用於貨幣單位
    • LC_NUMERIC, 用於數字顯示格式.下面是不同國家的在貨幣符號 和數字格式上的不同:
      • 中國大陸: 1,234.56RMB
      • 美國: $1,234.56
      • 德國: 1.234,56DM
    • LC_TIME, 用於時間和日期.時間可以用12小時或者24小時的 格式來計算.在小時和分鐘之間可以用逗點或者冒號隔開.下面是一些Locale設置的時間和日期的格式:
      • 中國: 14點20分 2000年三月十四號
      • 英國: 02:20pm 14/03/2000
      • 美國: 02:20pm 03/14/2000
      • 芬蘭: 14.20 14.03.2000
    • LC_MESSAGES, 用於國際化信息, 主要是提示信息,錯誤信息, 狀態信息, 標題,標籤, 按鈕和菜單等.
    Locale 通過ANSI C 函數setlocale(分類, locale)來初始化locale 數據.當locale設置為空時, locale的值便從系統的環境變量中取得.為了 方便應用軟件, 設置所有的分類,可以採用下述方式: setlocale(LC_ALL, "");
       如果不成功, 該函數返回NULL.函數應該回落到setlocale(LC_ALL,"C").
  • 在X中使用Locale
       在X的客戶程序中使用Locale的機制和在標準C函數中使用Locale的方式一樣,除此之外, 在X庫中還定義了另外兩個函數來判斷X的locale支持和設置locale 的修飾(XModifier),在X中使用Locale和libX11的基本步驟如下:
    • setlocale(): 設置當前的locale
    • XSupportLocale(): 用來判斷X是否支持目前設置的locale.
    • XSetLocaleModifier(): 它用來指定一系列的locale修正值. 它的參量的格式是@分類=賦值.目前唯一可用的是輸入服務器的名稱"im".如果參量為空, 則根據系統的環境 變量XMODIFIERS查找.比如在系統上設置了環境變量:
         % setenv XMODIFIERS @im=Chinput (csh) 或
      % export XMODIFIERS=im=Chinput (bash) 則客戶程序將查找到輸入服務器Chinput, "Chinput"是 輸入服務器所設置的名稱.
        

  • 文化習俗的差別
       下面是在國際化和本地化過程中常常遇到的並且應當注意的地方, 對國際化軟件的開發, 應該充分注意到各個地域的文化和習慣, 開發出通用的軟件, 對於本地化過程,則應選擇與本地域相符的習慣.
    • 姓名,地址等特殊信息
      姓名中的"姓"和"名"的先後次序, 地址書寫的先後次序 電話號碼的長度等等
    • 圖標的通用性
      圖標是易於接受的用戶界面, 設計時應考慮到地域習慣, 而且圖標上不能有圖形文字,否則需要重新設計本地圖標, 並翻譯圖標上的文字.
    • 聲音使用
      不適當的聲音或提示可能會引起人的反感.另外, 聲音 的性別對某些國家是敏感的.
    • 顏色使用
      顏色和色調與民俗有關, 比如紅色在美國表示危險, 在中國 表示喜慶.
    • 紙張尺寸
      打印紙的尺寸因地域而不同, 在選擇缺省尺寸時應注意.
    • 鍵盤差別
      在鍵盤上的鍵可能因國家而異, 鍵的個數也可能不一樣.
    • 政治因素
      在產品設計上, 盡量不要有政治敏感性部分.
  • 參考資料:
    • Linux 上的Locale
      http://www.ping.be/linux/locales/index.shtml
    • GBK Locale
      ftp://ftp.turbolinux.com.cn/pub/turbolinux/TurboLinuxC-6.0/SRPMS/SRPMS/localedata-zh-0.07-1.src.rpm

TOP

三 X 窗口系統的國際化在 X 窗口系統上的國際化, 特別是中文化, 主要體現在顯示,輸入和打印三個方面.
  • 顯示的國際化
    • 字符集和編碼
         在Linux上經常使用的字符集是ISO 8859系列的字符集.它包含了10個 多語言的單字節編碼字符集.它們分別是,
      字符集涵蓋語言
      ISO 8859-1(Latin1)拉丁一字符集, 包含絕大多數的歐洲語言, 例如French(fr), Spanish (es), Catalan (ca), Basque (eu), Portuguese (pt), Italian (it), Albanian (sq), Rhaeto-Romanic (rm), Dutch (nl), German (de), Danish (da), Swedish (sv), Norwegian (no), Finnish (fi), Faroese (fo), Icelandic (is), Irish (ga), Scottish (gd), English (en), Afrikaans (af) 和 Swahili (sw).影響了美洲, 澳洲和非洲.
      ISO 8859-2(Latin2)拉丁二字符集, 包含了中歐和東歐的語言:Czech (cs), Hungarian (hu), Polish (pl), Romanian (ro), Croatian (hr), Slovak (sk), Slovenian (sl), Sorbian.
      ISO 8859-3(Latin3)拉丁三字符集, 包括: Esperanto (eo) and Maltese (mt)
      ISO 8859-4(Latin4)拉丁四字符集, 包括: Estonian (et), 巴爾地克 Latvian (lv) 和 Lithuanian (lt), Greenlandic (kl) , Lappish.
      ISO 8859-5(西裡爾語)Bulgarian (bg), Byelorussian (be), Macedonian (mk), Russian (ru), Serbian (sr)
      ISO 8859-6(阿拉伯語)阿拉伯語(ar)
      ISO 8859-7(希臘語)希臘語(el)
      ISO 8859-8(希伯來語)Hebrew (iw) 和Yiddish (ji)
      ISO 8859-9(Latin5)重排了Latin1, 用土耳其語的幾個字母做了替換
      ISO 8859-9(Latin6)重排了Latin4, 去掉了某些符號, 增加了Inuit等
      ISO 8859-11(泰國語)泰國語(th)
      ISO 8859-12Celtic
      ISO 8859-13(Latin7)Baltic Rim 和 Lativian(lv)
      ISO 8859-14(Latin8)Gaelic 和 Welsh (cy)
      ISO 8859-15(Latin9)Latin1的變種, 修改了某些字母
      雙字節字符集主要包含中文,日文和韓文.它由前導字節(Lead Byte) 和尾部字節(Trail Byte)構成, 由於一個字符採用了兩個字節, 在軟件的 國際化方面又增加了一些麻煩,比如在顯示上, 光標的位置不能位於漢字 之間, 刪除和移動時必須是整字操作等,在輸入上, 一般需要預編輯服務器 才能輸入漢字. 下表列出了中日韓語言編碼的有關信息:
      語言字符集代碼頁前導字節範圍尾部字節範圍
      簡體中文GB2312-1980CP9360xA1-0xF70xA1-0xFE
      GBK0x81-0xFE0x40-0x7E, 0x80-0xFE
      中文繁體BIG-5CP9500x81-0xFE0x40-0x7E, 0xA1-0xFE
      日文Shift-JISCP9320x81-0x9F, 0xE0-0xFC0x40-0xFC(0x7F除外)
      韓文KSC-5601-1987CP9490x81-0xFE0x41-0x5A,0x61-0x7A,0x81-0xFE
      KSC-5601-1992CP13610x84-0xD3
      0xD8
      0xD90-0xDE
      0xE0-0xF9
      0x41,0xFE
      0x41-0x7E
      0x81-0xFE
      0x31-0x7E
      最近, 信息產業部和國家質量技術監督局聯合發佈了兩項新的中文信息 處理基礎性國家標準,為解決偏、生漢字的輸入提供了方案。其中GB18030- 2000《信息技術和信息交換用漢字編碼字符集、基本集的擴充》,為強制性 國家標準.它收錄了2.7萬多個漢字,總編碼空間超過150萬個碼位,為徹底解決郵政、戶政、金融、 地理信息系統等迫切需要的人名、地名用字問題 提供了解決方案,也為漢字研究、古籍整理等領域提供了統一的信息平台基礎。這項標準還同時收錄了藏文、蒙文、維吾爾文等主要的少數民族文字.字符 集編碼範圍是: 字節數編碼空間碼位數目單字節0x00-0x80129雙字節第一字節:0x81-0xFE
      第二字節:0x40-0x7E,0x80-0xFE23940四字節四字節範圍分別是:
      0x80-0xFE,0x30-0x39,0x81-0xFE,0x30-0x391587600香港特別行政區也對Big5編碼提出了"香港增補字符集", 其目的,是 收納香港特區政府及市民在中文電子通訊中有需要使用的字符,來補充目前大五碼和ISO10646編碼標準內並未包含的字符,以作為一個通用的中文界面, 方便大家能準確地以中文進行電子通訊。香港增補字符集有兩套編碼方案,一套適用於大五碼系統,另一套適用於ISO10646平台。香港增補字符集的大 五碼版本,實際上是政府通用字庫的增訂版。ISO10646國際編碼標準目前並未包含香港增補字符集內的所有字符。目前尚未收納在ISO10646內的香港增 補字符集字符,均已提交國際標準化組織管轄下的表意文字小組,以考慮是否納入ISO10646日後的新增版本內. 上述標準和草案應該是以後的中文Linux所應該遵循的.
    • 多字節字符(Multibyte)和寬字符(WideChar)的使用
         我們平時見到的以文本方式存在的字符都是多字節字符, 它主要用於 文件存儲和網絡上的以流(Stream)的方式傳輸.一個GB編碼的漢字需要兩個字節.多字節字符的缺點是在中文處理上不方便, 比如漢字的刪除和光標的 移動都會有半漢字問題.為了文本處理的方便,在內部操作上通常是把漢字 與英文的混和字符串先轉換成等寬度的字符串, 即寬字符,為軟件的內部處理 提供方便. glibc2.1.x中多字節字符串和寬字符串的轉換有時有問題.在X下還可以 使用另外一種方式完成轉換,即使用XmbTextListToTextProperty()和 XwcTextPropertyToTextList() 聯合完成轉換.
    • Unicode
         目前所使用的Unicode 是一種16位字寬的字符編碼, 它由非贏利的計算機 組織Unicode研討會維護和改進.它起源於Xerox和Apple之間的合作研究.幾個公司組成了一個非正式的論壇, 接著IBM, Microsoft等公司迅速加入. Unicode研討會在1990年發表了Unicode標準版本1,同時國際標準化組織完成 了一種類似的編碼----ISO 10646.因為沒有必要存在兩套標準,所以Unicode 研討會和國際標準化組織在1991到1992合二為一. 1994年, 中國和日本開始了基於ISO10646上的國家標準進行工作.現在, Unicode 開始用在許多產品中. Unicode包含了當今計算機領域中廣泛使用的所由字符, 如世界上大部分 的書面語言,印刷字符, 數字和技術符號, 地理圖形和標點符號.由於Unicode 的一致性,它在大多數情況下都可能簡化軟件的國際化過程.它取消了處理 多種代碼頁的必要,並且由於是16位編碼, 因此由雙字節字符集所引起的額外 處理也不必要了. 但是, Unicode作為一種編碼也有它的缺陷, 比如編碼的位置與排序無關,所以使軟件支持Unicode僅僅是國際化的第一步, 實際情況中還需要與語言相關的信息和規則.所以Unicode一般作為程序的內部處理編碼, 必須提供與其它 編碼的雙向轉換表. 最後需要說明的是, 雖然使用Unicode會使普通的英文文本大兩倍, 但是 使用Unicode的整個系統卻不會增加太大,因為系統存放的文件大部分是二進制 文件格式, 同時, 使用針對Unicode的壓縮方式,可以把文件壓縮成和使用對應 的8位正文一樣大小.
    • 字體(Font)和字體集(FontSet)
         在X窗口系統下使用的字體都必須在X服務器中註冊X邏輯字體描述(X Logical Font Description)名.它包括了字體的許多信息, 例如以下為西文字體和中文字體的兩個例子.
      • -adobe-times-medium-r-normal--14-140-75-75-p-74-iso8859-1
      • -tlc-song-medium-r-normal--24-240-75-75-c-240-gbk-0
      為了方便使用, 用戶還可以給每一個字體加一個或多個別名, 別名文件 fonts.alias 放在字體目錄下, 可以手工編輯.當字體目錄變更或別名變更 後, 必須使用命令 "xset fp rehash"或重新啟動X才起作用. X 字體也可以通過字體服務器(Font Server)加載.這對於本地不放字體 的系統或X終端特別有用.加載的協議可以是TCP或DECNET. X 窗口系統的字體在X Server中之存在一份, 當所由軟件都不使用它時, 字體的內存自動施放. 字體中包含了製造商名, 字體類型, 權重, 字體大小, 字符集等信息.它們也可以縮寫, 省去的部分用星號代替, 比如對上面的中文字體, 可以縮寫為: -*-song-*-24-*-gbk-0
         在實際應用中, 字符串往往是中文和英文的混和字符串, 所以必須使用兩種字體來繪出該字符串, 這種指定兩種或兩種以上的字體的描述就是字體集.字體集一般的格式是把多種字體用逗號隔開, 比如, 指定下列字體集:
      "-adobe-helvetica-medium-r-normal--14-*-*-*-*-*-iso8859-*,\ -tlc-song-medium-r-normal--14-*-*-*-*-*-gbk-0"
         令人遺憾的是, 中文的GB編碼和Big5編碼有重疊區域, 不能區分開來, 所以字體集並不能同時指定GB和Big5的字體. 字體集的具體載入受到Locale的影響. 在許多已經國際化的軟件和圖形庫中, 一般通過資源文件讓用戶指定字體集,比如gtk的簡體中文資源文件為/etc/gtk/gtkrc.zh_CN, qt-1.44(國際化的)的資源文件是 ~/.qti18nrc 等等.

TOP

  • 信息的國際化
  • 信息(Message)國際化是軟件國際化中比較重要的一環, 如果使軟件可以 支持多種語言,在設計時就應當考慮到信息的國際化問題.現在的絕大多數 軟件使用GNU的gettext作為基本工具.信息國際化的基本步驟是:
  • 在軟件初始化時設置使用setlocale()設置Locale
  • 使用gettext宏定義, 使程序看上去比較方便:
  • 指定信息的位置:
  • 指定翻譯信息: _("Some Strings");
  • 在軟件完成後,使用 xgettext 提取信息並翻譯
  • 使用msgfmt把信息文件轉換為.mo文件, 安裝到locale目錄下
  •         /* file this_app.c */
            #include <locale.h>
            #include <libintl.h>
            #define _(String)  gettext(String)
            #define N_(String)  gettext(String)
            #define __(String) (String)

            int main(){
                    //由環境變量決定locale
                    setlocale(LC_ALL, "");               

                    //設置message的位置和文件名
                    bindtextdomain("this_app", "/usr/share/locale");
                    textdomain("this_app");
                   
                    printf(_("Some String"));
            }
            

                至此, 本程序的國際化過程已完成.編譯並聯接成可執行文件this_app.
  • gcc -o this_app this_app.c
  • 下面是本地化的過程.
      
  • 提取要翻譯的信息: xgettext -a -o this_app.po this_app.c
  • 翻譯信息
        在文件this_app.po 中含有"Some String":
      
      msgid "Some String" msgstr ""
        翻譯成:
      
      
    msgid "Some String" msgstr "一些字符串"
       
      
      
  • 格式化信息文件: msgfmt -o this_app.mo this_app.po
  • 拷貝信息文件到locale的目錄下, 比如對於中文zh_CN, cp this_app.mo /usr/share/locale/zh_CN/LC_MESSAGES
  • 執行文件: LC_ALL=zh_CN ./this_app
輸入的國際化
   在X窗口系統下輸入主要有三種方式:
  • 單次擊鍵輸入單字符
  • 兩個或多個組合鍵輸入單字符
  • 除鍵輸入外, 還需要轉換服務器
其中前兩種用於輸入西文字符, 比如對於歐洲語言的特殊字符的輸入, 通常採用重映射鍵盤的方法.或者使用"加速鍵"的方法輸入,加速鍵是鍵盤 上的特殊鍵, 按下後不會使光標向後移動. 在Linux下, 使用軟件xkeycaps可以把鍵盤重新映射並且保存整個鍵盤 在映射後的對照表,使用命令xmodmap可以加載映射表. 對於中文輸入, 主要使用第三種輸入方式.針對各種語言的綜合考慮, X 窗口系統在輸入上定義了下列區域:
  • 預編輯區域(Preedit Area), 用於顯示輸入的過程, 當用戶輸入 字符時, 應立即顯示在該區域
  • 狀態區域(Status Area), 用於顯示輸入狀態, 對中文來說, 用於顯示輸入方法,全角/半角狀態, 中文/西文標點符號狀態.
  • 輔助區域(Auxiliary Area), 顯示可供選擇的列表, 又稱選擇 區域, 它由輸入服務器控制.
根據預編輯區域和狀態區域的不同組合, X 窗口系統共定義了四種輸入 的風格(Input Style):
  • Root風格: 預編輯區域和選擇區域都在應用軟件之外, 它們都是 由輸入服務器完成的,輸入服務器所顯示的界面是根窗口的子 窗口.如類似"中文之星"的獨立的輸入條模式.
  • OffTheSpot風格: 預編輯區域和選擇區域在應用軟件之內, 通常 是在窗口下方的某個固定區域內.如XEmacs的缺省輸入模式.
  • OverTheSpot風格: 預編輯區域在當前的輸入位置, 狀態區域 在應用程序的某一固定區域.它通常又稱為光標跟隨模式,類似 於Windows下的智能ABC輸入方法
  • OnTheSpot風格: 預編輯區域和選擇區域都在應用軟件之內, 內容是由輸入服務器發送的,應用程序負責顯示.
對中文輸入來說, 最好的風格是(3),(4),(1).對大部分中文輸入方法,必須彈出輔助區域, 供用戶選擇, 只有少數的中文輸入方法, 如五筆字型, 比較適合(4).對於狀態區域,中文輸入多數選用在Root風格的窗口的某個 位置或使用專用的控制條.在MS Windows下比較常用的光標跟隨模式,可以 用(3),(4)來實現.鑒於Linux下有的用戶把X Window設置成為虛屏模式,選 擇上述的任何一種模式都不盡滿意. 對應用軟件來說, 最簡單的輸入接口是Root風格, 它把顯示部分交給 輸入服務器去做.編寫軟件時所用的代碼量少,是對軟件初步使用國際化 標準的最佳選擇.從方便用戶的角度來看, 應用軟件,特別是高層的庫函數 應該同時支持四種輸入風格.令人遺憾的是, 一般軟件僅支持兩到三種輸入風格.所以在現在的輸入服務器(IM Server)也很少支持四種風格, 這似乎 成了雞和蛋的問題. 下面列出幾種常用軟件和圖形庫的XIM支持情況:
NetscapeRoot,OffTheSpot,OverTheSpot
Java Root,OnTheSpot
Qt Root,OverTheSpot
gtk+ Root,OverTheSpot
rxvt Root,OffTheSpot,OverTheSpot
中文輸入需要客戶軟件和服務器軟件的的密切配合, 它們之間是通過 XIM(X Input Method)協議來通訊的.輸入服務器首先起動, 在X Server裡 註冊自己,服務器的名字也被註冊.當客戶程序起動時, 到X Server裡查尋 有沒有符合自己locale類型的輸入服務器(如果用XMODIFIERS指定服務器名,則同時用locale和名字區分).找到後, 根據輸入服務器提供的風格種類 選擇一個最適合自己的風格.然後客戶程序為每一個需要輸入的窗口都建立一個自己的標示IC(Input Context), 裡面含有客戶程序的信息, 以後的通訊則一直使用該標示. 下面是直接使用X Lib和服務器聯接的過程, 在高層函數庫中, 把這一 過程隱藏了起來:                      XIM im;             XIC ic;             ...             if( (im = XOpenIM(display, NULL, NULL, NULL)) == NULL ) {                     printf("Error : XOpenIM !\n");                     exit(0);             }             //指定預編輯的類型等...             if( (ic = XCreateIC(im,                      XNInputStyle,   XIMPreeditPosition | XIMStatusNothing,                     XNClientWindow, window,                      NULL)) == NULL ) {                     printf("Error : XCreateIC() ! \n");                     XCloseIM(im);                     exit(0);             }             ...             for(;;) {                     XNextEvent(display, &event);                     //如果輸入服務器接收並處理...繼續                     if (XFilterEvent(&event, None) == True)                             continue;                     switch(event.type) {                             case Expose:                                     XmbDrawString(...);                             case KeyPress:                                     count = XmbLookupString(ic,                                              (XKeyPressedEvent *) &event,                                             string, len, &keysym, &status);                             ...                     }             }        目前使用比較廣泛的XIM輸入服務器有Chinput(簡體中文, 同時支持繁體), xcin(繁體中文), kinput2(日文) 和 hanIM/ami(韓文). 中文輸入服務器Chinput 選擇了OverTheSpot風格作為缺省的輸入模式, 它與標準的輸入風格略有不同,即把預編輯區域偏離輸入位置, 使輸入區 域同時作為狀態區域, 在很大程度滿足了用戶的輸入習慣.同時它還使用輔助工具條顯示和改變輸入狀態.Chinput還解決了同時使用GB和Big5編碼 的問題,被動輸入(Passive Input)問題等.對於普通用戶, 除了使用鍵盤 輸入外, 還可以使用手寫識別輸入和語音識別輸入方式.目前的輸入架構基本能夠滿足它們的要求.筆者在手寫識別輸入方面做了一些嘗試, 發 現對絕大部分軟件是能夠適合被動輸入的.
打印的國際化
   在X窗口系統下的打印是一個很難解決的問題, 所以到目前為止沒有形成 一個統一的打印標準.其原因之一就是X窗口系統在設計上把顯示和打印完全分開了. 在Linux最常見的需要打印的文件格式是普通文本文件和PostScript文件. 對於中文的普通文本文件的打印一般需要先轉換為PostScript文件再打印.對於PostScript文件, 如果應用軟件在生成時含有中文字體信息, 則打印 比較容易實現,反之, 則很難實現甚至不可能打印. 目前中文文本文件常用的打印方法通常是,使用gb2ps/bg2ps/cnprint 等 軟件轉換成PS文件打印,轉換過程使用了中文的點陣字體.對已經形成的PS 文件的打印, 如果不包含中文字體,直接打印就會輸出亂碼, 通常使用的方法 是將這一類PS文件過濾一下, 改為使用中文字體,然後再打印.如陳向陽先生 的過濾軟件ps2cps可以打印Netscape的存儲文件.這種打印的缺點是有時輸出的PS中漢字字符串和英文字符串對不齊.最好的方法是在PostScript一級實現 中文打印,陳向陽先生對ghostscript進行了中文化, 可以直接使用TTF輕鬆打 印Netscape, Qt/KDE, lyx等軟件輸出的PS文件.這種從底層實現打印的方法 也是日文和韓文所採用的方法. 使用CID(adobe)字體打印的方法也在嘗試之中. 總之, 目前的中文打印缺乏統一標準, 應用軟件在輸出打印PS文件時多數 不考慮雙字節語言的問題,使打印變得更加複雜化, 所以當前的中文Linux發 布版本多數不支持中文打印,
客戶程序間通訊的國際化
   客戶程序間通訊(Interclient Communications Conventions, 簡稱ICCC)是客戶程序之間共享資源的手段之一.最常見的應用是文本的拷貝和粘貼和與窗口管理器通訊.但是如果兩個應用程序之間所使用的字符集不同, 粘貼就會出現問題, 甚至粘貼的內容會丟失.所以客戶程序之間必須國際化了的通訊協議. 應用程序和窗口管理器之間的通訊也屬於客戶程序間通訊. 如果客戶程序之間使用的字符集相同, 但是編碼不同, 則不會丟失數據, 這時應該使用復合文本(COMPOUND TEXT)傳輸.X內部定義了COMPOUND_TEXT 的原子(Atom)用於傳輸中英文混和的字符串.對7字節編碼, ASCII或者其它 ISO8859-1字符集, 客戶程序通訊可以不用轉換而直接使用XA_STRING原子傳輸.

TOP

四 開發符合國際化標準的軟件在X窗口系統下開發軟件, 應盡量符合國際化標準.它包括, 設置合適 的locale(見前面講述的在X下使用locale),注意選擇字符集和字體集, 本地化文本的處理, 輸入方法等等.這裡推薦用戶盡量使用在國際化方面已經比較完善的高層圖形庫, 如Qt, gtk+, Java等, 這樣可以避免考慮以 上問題.選擇Motif時需要考慮資源的國際化問題和FontList等.
  • 開發國際化軟件
       使用已經支持國際化的高層圖形庫開發支持國際化的軟件基本上可以不用 考慮國際化問題.特別是輸入問題,在標準的輸入區內(單行輸入和多行輸入), 都可以自動輸入漢字.在字體處理上,注意使用字體集.許多軟件需要在資源 文件中指定字體和字體集, 所以開發的軟件應提供一個缺省支持字體集的資源文件. 下面所介紹的開發國際化的軟件是基於libX11的開發方法.除了前面所說的 在軟件初始化時調用一些Locale的函數外,在實際編程時, 還應注意以下問題:
    • 字體載入: 在處理字符串時, 使用FontSet, 而不是Font:
         XCreateFontSet() - 建立字體集
      XFreeFontSet() - 釋放字體集內存
      XFontsOfFontSet() - 返回XFontStruct和字體名
      XBaseFontNameListOfFontSet() - 返回字體集的名稱
      XLocaleOfFontSet() - 返回XFontSet的locale名
      XExtentsOfFontSet() - 獲得FontSet的最大Extents
    • 計算字符串的屏幕尺寸並畫字符串:
         Xmb/XwcDrawString() - 只畫字型(glyphs)的前景
      Xmb/XwcDrawImageString() - 畫前景和背景
      Xmb/XwcDrawText() - 複雜的間隔和字體集
      Xmb/XwcTextEscapement() - X 方向像素
      Xmb/XwcTextExtents() - 字符串輪廓
    • 客戶程序間通訊:
         Xmb/wcTextListToTextProperty() - 根據locale的文本轉換
      Xmb/wcTextPropertyToTextList() - 根據locale的文本轉換
      XFreeStringList()
      Xmb/wcFreeStringList() - 釋放StringList
      XSetWMProperties() - 設置窗口管理器屬性
      XSetWMName() - 設置窗口窗口名
      XSetWMIconName() - 設置窗口圖標名
    • 輸入:
         XOpenIM()/XCloseIM() - 打開/關閉輸入服務器
      XDisplayOfIM()/XLocaleOfIM()
      XSetIMValues()/XGetIMValues() - 設置/獲取輸入服務器屬性
      XCreateIC()/XDestroyIC() - 建立/釋放IC
      XIMOfIC()
      XSetICValues()/XGetICValues() - 設置/獲取IC的值
      XSetICFocus()/XUnsetICFocus() - 聚焦/取消聚焦
      XmbResetIC()/XwcResetIC() - 重設IC
      XFilterEvent() - 過濾事件
      Xmb/wcLookupString() - 查找字符串
      XRegister/UnregisterIMInstantiateCallback() - 註冊/取消回調
        

  • 使非國際化軟件國際化
       修改已經存在的非國際化軟件, 應根據具體情況採用不同的補丁.需要 注意的是修改後的軟件應與原來的軟件兼容,不會對軟件以前在西文和其它 語言的支持造成影響.Locale應該是軟件的語言切換中心點.下面是筆者在修改軟件的過程中一些經驗, 僅供參考.
    • 在軟件初始化時設置Locale.
    • 定義gettext的宏, 並且把它與信息文件綁定.
    • 對所有靜態信息使用gettext
    • 對文本繪製使用字體集代替字體
    • 繪製函數使用X下的多字節或寬字符函數
    • 初始化和XIM服務器的聯接
    • 在事件循環中用XFilterEvent()過濾事件到XIM服務器
    • 使用Xmb/wcLookupString()查找字符串

TOP

五 目前中文化中存在的問題現有的國際化標準中存在許多問題, 問題的原因主要出自目前的 國際化架構.對於中文化來說,這些問題顯得更加突出.
  • 編碼動態切換的問題
       對中文軟件來說, 同時支持多內碼(GB和Big5)是比較完善的中文軟件, 但是動態切換內碼,特別是切換軟件界面(如菜單項)的內碼, 是受到信息 (Message)國際化中 gettext 的限制的.一般來說, 一旦軟件載入, 所有 文本信息便被初始化, 而且在整個過程中不會再重新裝載信息.退一步說,即使重新裝載了信息, 由於所裝載信息的長度發生了變化, 軟件界面調整 佈局也是十分困難的. 所以現有軟件的動態編碼切換僅僅是在部分區域實現, 例如Netscape. 遺憾的是, Netscape的編碼切換並不徹底, 它切換的僅僅是顯示部分, 輸入 部分仍然有問題.比如在zh_CN.GBK的環境下啟動Netscape,當切換到有 輸入條的繁體中文頁面時, 如果採用輸入軟件自動識別Input Context的編碼的方式, 仍然會認為Netscape是GB編碼, 輸入結果不正確.如果輸入 Big5編碼,必須縮定輸出的編碼為Big5.Chinput在這方面做了一些嘗試, 結論是可以輸入Big5編碼,但是在輸入條中的顯示不正確. 一般來說, 使用中文平台來動態切換編碼更容易實現.在中文Linux 的發佈版本中,有幾個是可以使用中文平台來實現動態切換編碼的, 其原理 十分簡單, 只要在應用程序或X服務器把某個窗口的編碼狀態記住就行了,以後的文本顯示和輸入都以此編碼為標準.這種方法的缺點是, 應用程序 初始界面上的中文由於轉化了編碼變成了亂碼.
  • 中文編碼自動識別問題
       在文本瀏覽,網頁瀏覽或網頁翻譯時, 通常需要自動識別漢字的內碼, 但是中文的GB編碼和Big5編碼有重疊區域,所以很難區分開.目前公開 源代碼的識別軟件很少, 識別結果不能令人滿意,遠沒有達到目前商業軟件 的識別水平.
  • Linux上的中文平台到國際化的過渡
       但是從長遠的角度看, 因為中文在對中文顯示和輸入上與國際化標準 存在很大差異,所以亟需一種從中文平台到國際化標準的過渡性方案.在 過渡的過程中, 中文平台可能會和國際化標準共同存在一段時間. 以CLE和TurboLinux為例, 它們在早期的版本中都採用了中文平台來 支持中文的顯示和輸入,隨著支持國際化標準的軟件的增多, 逐步採用了 中文平台和國際化標準共同存在的版本作為過渡性版本.到目前為止,已經 在缺省情況下放棄中文平台的使用.中文平台只是作為殘留物包含在發佈 版本中.
  • Linux 文檔中文化
       Linux文檔, 主要是指Linux上的一些命令幫助文檔(man文件), 軟件 手冊和說明,軟件本身的Message文件(po).目前在這方面的工作還缺乏 統一的管理和廣大Linux愛好者的參與.
參考資料
  • Unicode: http://www.unicode.org/
  • 香港增補字符集: http://www.digital21.gov.hk/chi/hkscs/introduction.html
  • CJK 有關信息: ftp://ftp.ora.com/pub/examples/nutshell/ujip/doc/cjk.inf
  • Linux國際化資料: http://i18n.linux.org.tw/
  • Linux國際化標準: http://www.li18nux.org/
  • MicroSoft 國際化: http://www.microsoft.com/globaldev/

TOP

六 附錄
  • 寬字符處理函數函數與普通函數對照表
       字符分類: 寬字符函數普通C函數描述iswalnum()isalnum()測試字符是否為數字或字母iswalpha()isalpha()測試字符是否是字母iswcntrl()iscntrl()測試字符是否是控制符iswdigit()isdigit()測試字符是否為數字iswgraph()isgraph()測試字符是否是可見字符iswlower()islower()測試字符是否是小寫字符iswprint()isprint()測試字符是否是可打印字符iswpunct()ispunct()測試字符是否是標點符號iswspace()isspace()測試字符是否是空白符號iswupper()isupper()測試字符是否是大寫字符iswxdigit()isxdigit()測試字符是否是十六進制的數字大小寫轉換: 寬字符函數普通C函數描述towlower()tolower()把字符轉換為小寫towupper()toupper()把字符轉換為大寫字符比較: 寬字符函數普通C函數描述wcscoll()strcoll()比較字符串日期和時間轉換: 寬字符函數描述strftime()根據指定的字符串格式和locale設置格式化日期和時間wcsftime()根據指定的字符串格式和locale設置格式化日期和時間, 並返回寬字符串strptime()根據指定格式把字符串轉換為時間值, 是strftime的反過程打印和掃瞄字符串: 寬字符函數描述fprintf()/fwprintf()使用vararg參量的格式化輸出fscanf()/fwscanf()格式化讀入printf()使用vararg參量的格式化輸出到標準輸出scanf()從標準輸入的格式化讀入sprintf()/swprintf()根據vararg參量表格式化成字符串sscanf()以字符串作格式化讀入vfprintf()/vfwprintf()使用stdarg參量表格式化輸出到文件vprintf()使用stdarg參量表格式化輸出到標準輸出vsprintf()/vswprintf()格式化stdarg參量表並寫到字符串

TOP

  • 數字轉換:
  • 寬字符函數
普通C函數描述wcstod()strtod()把寬字符的初始部分轉換為雙精度浮點數wcstol()strtol()把寬字符的初始部分轉換為長整數wcstoul()strtoul()把寬字符的初始部分轉換為無符號長整數
  • 多字節字符和寬字符轉換及操作:
    • 寬字符函數
    描述mblen()根據locale的設置確定字符的字節數mbstowcs()把多字節字符串轉換為寬字符串mbtowc()/btowc()把多字節字符轉換為寬字符wcstombs()把寬字符串轉換為多字節字符串wctomb()/wctob()把寬字符轉換為多字節字符
  • 輸入和輸出:
  • 寬字符函數
普通C函數描述fgetwc()fgetc()從流中讀入一個字符並轉換為寬字符fgetws()fgets()從流中讀入一個字符串並轉換為寬字符串fputwc()fputc()把寬字符轉換為多字節字符並且輸出到標準輸出fputws()fputs()把寬字符串轉換為多字節字符並且輸出到標準輸出串getwc()getc()從標準輸入中讀取字符, 並且轉換為寬字符getwchar()getchar()從標準輸入中讀取字符, 並且轉換為寬字符Nonegets()使用fgetws()putwc()putc()把寬字符轉換成多字節字符並且寫到標準輸出putwchar()getchar()把寬字符轉換成多字節字符並且寫到標準輸出Noneputs()使用fputws()ungetwc()ungetc()把一個寬字符放回到輸入流中
  • 字符串操作:
  • 寬字符函數
普通C函數描述wcscat()strcat()把一個字符串接到另一個字符串的尾部wcsncat()strncat()類似於wcscat(), 而且指定粘接字符串的粘接長度.wcschr()strchr()查找子字符串的第一個位置wcsrchr()strrchr()從尾部開始查找子字符串出現的第一個位置wcspbrk()strpbrk()從一字符字符串中查找另一字符串中任何一個字符第一次出現的位置wcswcs()/wcsstr()strchr()在一字符串中查找另一字符串第一次出現的位置wcscspn()strcspn()返回不包含第二個字符串的的初始數目wcsspn()strspn()返回包含第二個字符串的初始數目wcscpy()strcpy()拷貝字符串wcsncpy()strncpy()類似於wcscpy(), 同時指定拷貝的數目wcscmp()strcmp()比較兩個寬字符串wcsncmp()strncmp()類似於wcscmp(), 還要指定比較字符字符串的數目wcslen()strlen()獲得寬字符串的數目wcstok()strtok()根據標示符把寬字符串分解成一系列字符串wcswidth()None獲得寬字符串的寬度wcwidth()None獲得寬字符的寬度
  • 另外還有對應於memory操作的 wmemcpy(), wmemchr(), wmemcmp(), wmemmove(), wmemset().
  • X 窗口系統下支持中文的函數
  • 支持西文的函數
支持中文的函數描述
XLoadFontXCreateFontSet載入字體集
XTextExtents(16)Xmb/wcTextExtents
Xmb/wcTextPerCharExtents
返回文本的限制框
XDrawStringXmb/wcDrawString在窗口中畫字符串, 背景填充
XDrawImageStringXmb/wcDrawImageString在窗口中畫字符串
XDrawTextXmb/wcDrawText在窗口中畫字符串
XLookupStringXmb/wcLookupString查找字符串
  • 支持國際化的高層庫
  • OSF/Motif
  • Qt/kdelib
  • gtk+/gnome-lib
  • Perl
  • Java
  • 支持多語言的典型軟件
  • 瀏覽器 Netscape
  • 編輯器 XEmacs
  • 編輯器 Mule
  • 編輯器 vim
  • 終端 rxvt
  • 排版軟件 LaTeX/lyx
  • PostScript/PDF: gs/acroread
  • 圖像處理: gimp
  • 幻燈片製作 mgp
  • 即將完成: StarOffice, KOffice
  • 支持Unicode的軟件
  • 高級圖形庫函數 Qt 2.x
  • Java 語言開發工具 JDK
  • 編輯器 yudit
  • 專用的支持Unicode的 X 終端
  • 基於GTK+的文本處理器 GScript

TOP

發新話題

本站所有圖文均屬網友發表,僅代表作者的觀點與本站無關,如有侵權請通知版主會盡快刪除。