最近在參與PostgreSQL中國社群的文檔中文化。PG的文檔是一堆基于docbook的sgml檔案。這些sgml可以通過工具轉成html,pdf等各種不同格式。
這即是docbook所倡導的“内容和格式的分離”。然而當我嘗試把翻譯好的一個sgml檔案用openjade轉成html時,發現openjade報一堆類似的錯誤:"non SGML character number nnn"。
針對這一問題,經過調查,得到下面這些線索。
類似于xml的 <?xml version="1.0" encoding="UTF-8" ?>,sgml也可以指定字元集,但形式上要複雜的多。
以下是docbook 4.2預設的字元集定義:
docbook.dcl
...
BASESET
"ISO 646:1983//CHARSET International Reference Version (IRV)//ESC 2/5 4/0"
DESCSET
0 9 UNUSED
9 2 9
11 2 UNUSED
13 1 13
14 18 UNUSED
32 95 32
127 1 UNUSED
"ISO Registration Number 100//CHARSET ECMA-94 Right Part of Latin Alphabet Nr. 1//ESC 2/13 4/1"
128 32 UNUSED
160 96 32
在上面标有"UNUSED"的code範圍的字元為非法字元,遇到這些字元sgml解釋器就會報錯:"non SGML character number nnn"。
這也就是前面提到的錯誤的原因。
http://www.postgresql.org/message-id/[email protected]
we cannot use UTF8 because SGML Docbook
does not support it
http://www.pemberley.com/janeinfo/latin1.html#latexta
我一開始沒充分了解它的含義,我以為它絕了中文字元在sgml中出現可能性,我覺得這不太可能,于是沒有太理會。
linux 中文doc計劃使用字元替換的方式回避中文字元問題。
http://www.linux.org.tw/CLDP/OLD/zh-sgmltools-1.html
套件中包含一工具程式 mb2a, 可自標準輸入或檔案中讀取資料,將其中的 BIG5 或 GB 字元編碼成 @=XXXX
的形式,其中 XXXX 就是該字的 BIG5 或 GB 碼。 這個程式同時也能將這種編碼的資料予以解碼。
我相信這個方法一定可以回避中文不能識别的問題,但我覺得這個方法有點土,應該有更優雅的方法。
而且我查到的資料比較老了,也許他們現在也不這麼幹了。
看到有日本人嘗試使用環境變量SP_ENCODING=utf-8,加上包含日文字元集自定義SGML聲明實作轉換,但是對某些SP_ENCODING=utf-8 處理不了的字元仍然會出錯。
http://listserv.linux.or.jp/pipermail/vine-users/2010-October/000330.html
環境変數 SP_ENCODING に utf-8 をセットして,
添付ファイルを文書型(DOCTYPE)が書いてある
ファイルの先頭に挿入すると,日本語で書いてある
UTF-8のDocBook SGML文書をjadeで処理できました.
いくつか警告が表示されます.またリリースノートなどに
書いてある人名のいくつかに SP_ENCODING=utf-8 では
扱えない文字があるようです.その部分を直さないと日本語の
有無に関わらず"非SGML數字"と表示されてエラーになりました.
japan-docbook.dcl
CHARSET
BASESET
"ISO Registration Number 1//CHARSET C0 set of ISO 646//ESC 2/1 4/0"
DESCSET 0 9 UNUSED
9 2 9
11 2 UNUSED
13 1 13
14 18 UNUSED
"ISO Registration Number 14//CHARSET ISO 646 Japanese Version//ESC 2/8 4/10"
DESCSET
32 95 32
127 1 UNUSED
"ISO Registration Number 87//CHARSET JIS X 0208-1990//ESC 2/6 4/0 ESC 2/4 4/2"
41344 33 UNUSED
41377 94 8481
這個方法似乎是一條不錯的思路。我做了些嘗試,試圖修改字元集的定義去欺騙openjade,最終發現這不太容易(也許這條路可行,誰知道呢?)。
最後的最後,無意中用GBK編碼(之前一直使用UTF8編碼)的sgml檔案嘗試,驚訝的發現openjade居然安靜地完成了到html的轉換。
什麼個情況?再研究一下GBK的字元集定義,發現了其中的奧秘。
GBK的編碼範圍見下表,其中的GBK/1和GBK/2水準的漢字,即GB 2312-80用通常方法編碼的區域,
正好落在docbook預設字元集的合法編碼範圍内。是以在GBK編碼下這部分漢字會被openjade誤以為是合法的擴充ACSII碼,而欣然接受。
但是其他漢字就唬弄不了openjade了。幸運的是我們常用的漢字都在GBK/1和GBK/2(或者說gb2312)範圍内,GBK相對于gb2312擴充的
漢字沒那麼常用,比如繁體字。至少對于PG文檔的中文化,這些漢字應該夠用了。
GBK的編碼範圍:
範圍
第1位元組
第2位元組
編碼數
字數
水準 GBK/1
A1–A9
A1–FE
846
717
水準 GBK/2
B0–F7
6,768
6,763
水準 GBK/3
81–A0
40–FE (7F除外)
6,080
水準 GBK/4
AA–FE
40–A0 (7F除外)
8,160
水準 GBK/5
A8–A9
192
166
使用者定義
AA–AF
564
F8–FE
658
A1–A7
672
合計:
23,940
21,886
問題算是解決,翻好的sgml檔案使用GBK(或gb2312)編碼而不是utf8存檔,隻要是gb2312編碼範圍内的字元都沒有問題。
到此我突然明白了日本PG社群翻譯後的sgml檔案為什麼是euc_jp編碼而不是sjis或utf8,原來他們也是這麼幹的呀!
此外,最新的docbook5.0已經隻有xml格式了,也許什麼時候pg社群也會與時俱進放棄sgml改用xml。
我們知道xml要支援不同編碼很容易,如果使用xml格式的docbook的話,中文字元的支援就簡單了。
http://xml.coverpages.org/wlw11.html
http://zh.wikipedia.org/wiki/GBK
http://www.worldhello.net/doc/docbook_howto/
http://www.study-area.org/tips/docw/docwrite.html