GNU gettext 汉化

po文件是GNU gettext项目的一套应用规范,属于L10n方案。

po Portable Object (可移植对象)的缩写形式;mo Machine Object (机器对象) 的缩写形式。

po文件是面向翻译人员的、提取于源代码的一种资源文件。当软件升级的时候,通过使用 gettext 软件包处理po文件,可以在一定程度上使翻译成果得以继承,减轻翻译人员的负担。

mo文件是面向计算机的、由po文件通过gettext软件包编译而成的二进制文件。程序通过读取mo文件使自身的界面转换成用户使用的语言。 

GNU gettext 是一个软件包,是为了使软件实现国际化支持而产生的。

汉化流程(适用于程序首次汉化)

hardinfo程序为例介绍

1、创建一个po.h的文件。

文件中做gettext字符串的定义: #define _(STRING)   gettext(STRING)

2、修改hardinfo.c主程序,声明po.h头文件:#include po.h

3、首先声明头文件po.h

然后修改需要汉化的字符串。

例如需要将菜单栏中的 “Help”,需要将原有代码

{“HelpMenuAction”,NULL,”_Help”},

修改为

{“HelpMenuAction”,NULL,_(”_Help”},

制作mo文件,修改需要汉化的内容。

 

附链接 gettext实现汉化的原理:

http://twpug.net/modules/smartsection/item.php?itemid=29

gettext 簡介

前言:

gettext 套件是 GNU 對訊息國際化 (i18n) 提出的解決方案;有寫過程式的人都知道,過去大家寫程式的時候都把程式的訊息寫死在程式碼裡面,例如說:

printf(&quotHello World!!");

假如要把程式的訊息改成其他的語言的話,必須要取改原始碼,然後再重新編譯,這樣的作法在國際化的時候就行不通了;GNU gettext 套件就是提出了一套標準的方法,讓程式不須重新編譯就能顯示多國的訊息,讓國際化 (i18n) 的工作可以更簡單的達成。

gettext 現在的版本是 0.10 版,雖然說還不是 1.0 版,但是對於訊息國際化的支援 (LC_MESSAGES) 已經算是穩定了,幾乎所有的 GNU 程式也都支援 gettext ,因此現在把它當作一個標準,來作 Linux 上訊息中文化的工作,應該是一個適當的時機。

工作原理

底下這個流程圖可以總括 gettext 套件的工作原理:

參照:

Original C Sources ---> PO mode ---> Marked C Sources ---.
|
.---------<--- GNU gettext Library |
.- - make <---+ |
| `---------<--------------------+-----------'
| |
| .-----<--- PACKAGE.pot <--- xgettext <---' .---<--- PO Compendium
| | | ^
| | `---. |
| `---. +---> PO mode ---.
| +----> tupdate -------> LANG.pox --->--------' |
| .---' |
| | |
| `-------------<---------------. |
| +--- LANG.po <--- New LANG.pox <----'
| .--- LANG.gmo <--- msgfmt <---'
| |
| `---> install ---> /.../LANG/PACKAGE.mo ---.
| +---> "Hello world!"
`-------> install ---> /.../bin/PROGRAM -------'

這個圖是從 GNU info page 剪下來的,它說的比較複雜;我底下再用簡單的程序說明:

要讓你的程式支援國際化,程式設計師在寫程式時必須標出要國際化的訊息,就是要被翻譯成他國文字的訊息;比如說,"%s %d" 這樣的字串是不必被翻譯的,而 "Hello World!!" 就需要標示出來,標示方法如下:

printf(gettext("Hello World"));

在這裡懂 C 的朋友就可以看出來,程式在印出訊息時,並不是直接取得訊息的字串,而是透過一個 gettext 函式來獲得字串;這個 gettext 函式在程式真正被執行時,會檢查 locale 的情況 (事實上是檢查 LC_ALL LC_MESSAGES LANG 這環境變數),然後以 gettext 的參數 ( "Hello World" )作為一個 id key,去訊息資料庫裡面抓合乎 locale 設定的訊息,這樣子同一個程式,就可以 show 出許多不同語言的訊息了!!
這就是上面 Original C Sources -> PO mode ---> Marked C Sources ----> make --> install ---> /.../bin/PROGRAM ---> "Hello world!"

這一段流程,是程式設計師的工作,也是程式 i18n 的過程。

那訊息資料庫是甚麼??要怎麼作呢??

gettext 套件裡面有一個程式叫 xgettext,他可以用來處理 Marked C Sources,把原始碼裡面有標記的訊息抓出來,產生一個.pot (Portable Object Template),它的格式大約如下: 

#: hello.c:22

msgid "Hello, World!!"

msgstr ""

'#' 開頭的行是註解,msgid 欄位是原先的訊息,msgstr 就是用來填翻譯過的訊息的,我們可以把翻譯過的訊息填進去,製造出一個 po 檔;在上面的流程裡面,大家可以看到有一個 .pox 檔;這是GNU 建議對還沒完全翻譯好的 po 檔的稱呼,.pox 是施工中的,等到完工定案了,再把它改成 .po 檔。

另外,或許你想要動手翻譯的程式已經有舊版的 .po 訊息檔了,我們當然不希望把已經翻譯過的訊息再打一次,這時就可以用 "tupdate" 這個程式來把舊的 .po 檔裡面的訊息合併進來。

作好 .po 檔以後,就可以用 "msgfmt" 這個程式來把 .po 檔變成真正的機器可以處理的 .mo (Machine Object)

#msgfmt ./out.po –o ./out.mo

如果只有.mo文件,则需要在.mo文件所在目录执行

#msgfmt ./*.mo –o ./out.po

即可反汇编生成.po文件,然后用vi打开该.po文件进行编辑。编辑好后,再执行以下命令进行重新打包:

#msgfmt ./out.po –o ./out.mo

這個 .mo 檔就是真正的訊息資料庫檔案,它會被放到你的 LOCALEDIR 裡面去,RedHat-5.0 的話,就是在 /usr/share/locale/*/LC_MESSAGES/ * 就是 locale 的名稱,也就是你在環境變數 LC_ALL or LANG or LC_MESSAGES 裡面指定的字串,比如說你 export LC_ALL=zh_TW.BIG5 的話,那程式執行時,gettext 就會去/usr/share/locale/zh_TW.BIG5/LC_MESSAGES/ 底下找訊息檔,找到的話,你就可以看到中文啦!!... :) 
這個部份可以慨括如下:

xgettext editor msgfmt (install)

source code --> .pot --> .pox --> .gmo --> .mo --> <run time>

.gmo 就是 .mo 檔,他是 GNU 建議用來稱呼還沒安裝到定位的 .mo 檔,表示是由 Gnu gettext 套件產生的。

這一段工作不必要由程式設計師來完成,是屬於L10n 的工作,理論上該由世界各地使用不同語言的人來自願當翻譯的工作。