主要介紹在安裝程序裝入內存之後,如何啟動圖形環境並設置中文語言環境。文中除了介紹安裝程序對這兩個功能的具體編程實現,還介紹了Linux中文化的一些基本知識,包括如何定制安裝程序顯示中所需要的Locale環境(Glibc和X Window系統兩部分),po文件的處理。在安裝程序的第二階段運行結束之後,整個安裝程序已經被調入了內存,這時控制從安裝程序的加載程序轉到了安裝程序的主程序執行。這時的安裝程序就像是一個從Linux的控制台環境啟動的程序,這個程序進行自動檢測並進行基本的設備配置。為了進行圖形化安裝,安裝程序的主程序會啟動XFree86子系統並設置,同時設置當前的語言環境為中文環境。
1. 多語言環境支持
為了在Linux下實現多語言支持,必須在定制安裝程序時,引入與glibc和圖形環境兩者對應的多語言環境支持。對於glibc環境而言,它是整個 Linux中文化的基礎,我們需要在/usr/share/locale目錄下保存Locale信息,在/usr/share/consolefonts 目錄下保存字體信息,在/usr/lib/gconv目錄下保存字符轉換模塊的信息。
對於X Windows環境,我們需要在/usr/X11R6/lib/X11/locale目錄下保存X Locale的配置,同時在/usr/X11R6/lib/X11/fonts目錄下保存正常顯示所需要的字體集。
在安裝程序啟動之後,必須正確設置LC_*變量同時調用setlocale函數。為了能顯示中文,安裝程序還必須加載正確的中文字體。
1.1. 國際化的基本概念
國際化(Internationalization,簡寫為I18N)是指軟件在設計結構和機制上支持多語言的擴展特性,其功能和代碼設計不針對某一特定語言和地域。Locale是ANSI C語言中最基本的支持國際化的標志,對中文Linux來說,支持中文Locale是最基本的要求。
1.1.1. Locale環境
Locale的命名規則:<語言>_<地區名>.<字符編碼名稱>
對於zh_CN.GB2312而言,zh表示中文,CN表示大陸地區,GB2312表示使用的字符集為GB2312。
Locale使用一組分類,用戶可以獨立的操縱每一組分類。用戶既能用設置環境變量的方法,也能使用setlocale設置它們。這些分類都保存在/usr/share/locale下。它們包含了:
LC_COLLATE
用於比較和排序。
LC_CTYPE
用於字符分類和字符串處理,控制所有字符的處理方式,包括字符編碼,字符是單字節還是多字節,如何打印等。
LC_MONETORY
用於格式化貨幣單位。
LC_NUMERIC
用於格式化非貨幣的數字顯示。
LC_TIME
用於格式化時間和日期。
LC_MESSAGES
用於控制程序輸出時所使用的語言,主要是提示信息,錯誤信息,狀態信息, 標題,標簽, 按鈕和菜單等。
LC_ALL
它不是環境變量,只是一個宏,可使用setlocale設置所有的LC_*環境變量。這個變量設置之後,可以廢除LC_*和LANG的設置值,使得這些變量的設置值與LC_ALL的值一致。
LANG
它的值用於指定上面環境變量沒有設置的所有變量值。如果指定了上面任何一個變量的值,則會廢除對應的LANG值的缺省設置。
還可以包括其他的環境變量LC_ADDRESS,LC_IDENTIFICATION,LC_PAPER,LC_NAME,LC_TELEPHONE,LC_MEASUREMENT。
標准Locale:
"C"
這是標准的C Locale。它所指定的屬性和行為由ISO C標准所指定。它是程序啟動時缺省使用Locale。
"POSIX"
這是標准的POSIX Locale。它是標准的C Locale的別名。
""
空名字是讓程序選擇當前環境設置值。
設置一個中文環境需要正確的設置上述Locale變量,舉例來說,在使用zh_CN.GB2312環境時,使用locale命令,所見到的系統環境為:
LANG="zh_CN.GB2312"
LC_CTYPE="zh_CN.GB2312"
LC_NUMERIC="zh_CN.GB2312"
LC_TIME="zh_CN.GB2312"
LC_COLLATE="zh_CN.GB2312"
LC_MONETARY="zh_CN.GB2312"
LC_MESSAGES="zh_CN.GB2312"
LC_PAPER="zh_CN.GB2312"
LC_NAME="zh_CN.GB2312"
LC_ADDRESS="zh_CN.GB2312"
LC_TELEPHONE="zh_CN.GB2312"
LC_MEASUREMENT="zh_CN.GB2312"
LC_IDENTIFICATION="zh_CN.GB2312"
LC_ALL=
1.1.2. 創建Locale環境
為了建立locale環境,我們必須具備下面的描述文件:
locale-data
這個文件定義了Locale環境(LC_*)的所有細節,包括字符的分類與轉換,字符排序,區域顯示時間,貨幣顯示格式等等。通常是保存在系統的/usr/share/i18n/locales目錄下。
charmap
這個文件定義了Locale中所有字符與內碼的對應關系。通常是保存在系統的/usr/share/i18n/charmaps目錄下。
這兩個文件都是純文本文件,可以使用文本編輯器直接察看和修改。通過這兩個文件就可以生成對應的locale環境。缺省條件下,生成的locale環境是以二進制的形式保存在/usr/share/locale目錄下。把這兩個文本文件生成locale環境的工作是由localedef程序實現的。舉例來說,生成zh_CN.GB2312的locale環境:
mkdir /home/usr/share/locale/zh_CN.gb2312
localedef -I zh_CN -f GB2312 zh_CN.GB2312 --prefix=/home
cd /home/usr/share/locale/
mv zh_CN.gb2312 zh_CN.GB2312
這幾條命令在/home目錄下,生成Locale環境zh_CN.GB2312。因為按照POSIX標准,一個Locale的編碼名稱是大小寫無關的。雖然我們指定的是大寫的GB2312,但是glibc為了統一起見,它會生成一個小寫的編碼名稱。但是由於很多程序依賴於zh_CN.GB2312,因此對這個文件進行了改名。
除了Locale環境之外,您還需要gconv文件。這一組文件是用來定義glibc的gconv系統在遇到GB2312編碼的字符時,應使用哪一個模塊來處理。gconv-modules文件描述了字符編碼和處理模塊文件對應關系。例如,在/usr/lib/gconv/gonv-modules文件中,需要包含下列行:
alias GB2312// EUC-CN//
1.1.3. X Window系統的多語言環境
X Window系統的多語言環境是在系統底層libc的Locale架構的基礎上建立起來的。X函數庫需要利用libc提供的函數來進行字符之間的轉換。因此,為了使X Window應用程序的Locale正確工作,您必須首先設置一個正確的libc Locale環境,同時正確設置LC_CTYPE這個類別。
指定了編碼方式並且將字符的辨識和轉換用libc的函數處理之後,X Window系統的多語言處理的主要問題就變為圖形顯示和輸入了。在X系統下,多語言環境必須能做到多語言字符圖形化輸出和字符輸入。字符的圖形化輸出還要處理字型,這又與字型的設定方式有關。
與libc一樣,在X Window系統下也有關於Locale的設置部分,稱為X-Locale。XFree86系統都把它保留在 /usr/X11R6/lib/X11/locale目錄下。在這個目錄下的每個Locale都有一個目錄,存放各自的X-locale,一般這個文件的名字是XLC_LOCALE。這個文件裡面包含了跟該區域編碼相關的設定,而文件中以#字號開頭的是注釋。以安裝程序上簡體中文XLC_LOCALE的內容為例:
XLC_FONTSET
# fs0 class (7 bit ASCII)
fs0 {
charset {
name ISO8859-1:GL
}
font {
primary ISO8859-1:GL
vertical_rotate all
}
}
# fs1 class
fs1 {
charset {
name GB2312.1980-0:GL
}
font {
primary GB2312.1980-0:GL
}
}
END XLC_FONTSET
以上內容定義的是顯示Locale時使用的字符集。在多語言環境中,為了同時顯示中英文,系統往往需要多種字體。例如,上例中表示:在顯示簡體中文時要使用兩種不同編碼的字體,其中一個是使用了GB2312編碼的中文字體,其字體名稱以GB2312.1980-0結束,另一個是ISO8859-1編碼的英文字體,其字體名稱以ISO8859-1結束。
XLC_LOCALE的下一部分定義了Locale中的字體在X系統中的處理方式:
XLC_XLOCALE
encoding_name zh.euc
mb_cur_max 2
state_depend_encoding False
wc_encoding_mask x30000000
wc_shift_bits 7
cs0 {
side GL:Default
length 1
wc_encoding x00000000
ct_encoding ISO8859-1:GL
}
cs1 {
side GR:Default
length 2
wc_encoding x30000000
ct_encoding GB2312.1980-0:GL; GB2312.1980-0:GR
}
END XLC_XLOCALE
cs0定義的部分為iso8859-1編碼的英文字符,每個字符占用一個字節。cs1定義的部分為GB2312編碼的中文字符,每個字符占用兩個字節,這兩個字節都必須用GB2312.1980-0的字體來表示。注意,對於上面的X設置,GB2312.1980-1類型的字體是無法正常顯示的,除非用戶修改X Locale。
除此之外,/usr/X11R6/lib/X11/locale還使用locale.dir和locale.alias文件定義可用X-Locale的名稱和位置。其中,locale.dir定義了每個X-Locale文件的位置以及實際的Locale名稱。locale.alias文件則定義了每個 Locale可能的別名。
X Window 的字體存放在/usr/X11R6/lib/X11/fonts目錄下,一般使用PCF的字體。在將新的字體文件拷貝到此目錄之後,運行
mkfontdir
由這條命令更新改目錄下的fonts.dir的內容。例如,
fzs14.pcf.Z fzs14
helvR12_iso01.pcf.gz -adobe-helvetica-medium-r-normal--12-120-75-75-p-67-iso8859-1
上面兩行的信息是從字體文件中抽取出來的,比如,helvR12_iso01.pcf.gz文件中就包含iso8859-1編碼的文件。但是,字體文件 fzs14.pcf.Z就不包含類似的字體說明信息,因此我們還需要使用fonts.alias文件建立字體別名。
-hlc-song-medium-r-normal--14-140-75-75-c-140-gb2312.1980-0 fzs14
這樣在安裝程序使用下面的資源時,X Window系統就知道要加載fzs14字體了。
style "font" {
fontset="-*-helvetica-*-r-normal-*-14-*-*-*-*-*-iso8859-1, -*-medium-*-14-*-*-*-*-*-*-gb2312.1980-0"
}
1.2. 安裝程序的國際化實現
自動生成po文件
在安裝程序中,定義了兩個函數_()和__(),前者是對傳入的串進行翻譯,後者是直接返回傳入的串,凡是要進行多語言支持的串必須使用這兩個函數。它們兩者在安裝程序中的用法是不同的。前者是用於一些可以進行重建的界面控件,並且它們的值一般作為局部變量出現;而後者一般用於全局變量,為了讓這個串顯示多種語言,需要使用translate()函數進行處理。使用這兩個函數的主要目的是可以很方便的使用xgettext程序自動生成po文件。
xgettext只對c語言的源程序文件生效,因此在使用它之前必須先將perl源程序轉換為c程序,然後再運行xgettext自動提出需要進行多語言處理的文本串。下面的程序段是po目錄下Makefile文件的一部分,它可以自動生成空的po文件。
PMSFILES = $(wildcard *.pm)
PMSCFILES = $(PMSFILES:%=%_.c)
POFILES = $(shell ls *.po)
all: $(PMSCFILES) DrakX.pot
clean:
rm -f empty.po messages $(POFILES:%=%t) $(PMSCFILES)
verif:
perl -ne '/^s*#/ or $$i += my @l = /b__?(/g; END { print "$$in" }' $(PMSFILES)
perl -ne '$$i += my @l = /.c:/g; END { print "$$in" }' DrakX.pot
DrakX.pot: $(PMSFILES)
xgettext -F -n --keyword=_ --keyword=__ -o $@ $(PMSCFILES)
rm $(PMSCFILES)
$(PMSCFILES): %_.c: %
perl -pe 's|^(__?()| $$1|; s|#([^+].*)|/*1*/|; s|$$|\n\|' $< > $@