[譯文] 如何開始一個真正的 GTK 項目(第五部分:配置 Gettext)

原文地址:Advanced GTK Techniques


這篇教程中你將學會:

  • 使用 Gettext 完成源代碼中的翻譯工作辉懒;
  • 使用 Intltool 完成其它文件的翻譯工作拓售。

這篇文章是《如何開始一個真正的 GTK 項目》的一部分桌硫,如果你不想回看之前的章節(jié)俺叭,可以直接下載教學示例程序 app-skeleton3发魄。你也可以從頭開始铃拇。


這是我們在開始正式的代碼工作前又一個基礎準備工作钞瀑,這將實現(xiàn)程序在不同語言環(huán)境下的本地化。你可能覺得翻譯工作一般都是在應用成型后才展開慷荔,但是在編寫程序時同步開始翻譯往往更利于保持掌控翻譯的質量雕什。

你是否需要為了這項工作學習 30 門外語呢?當然不用显晶。在真實的場合中贷岸,人們用英語編寫程序(準確地說是 C locale),然后依賴一個名為 gettext 的工具將所有程序中顯示給用戶的詞句歸納到一個 翻譯模板 或一個 .pot 文件中磷雇。

之后要做的就是招募一些翻譯人員到你的項目中來(這才是最困難的部分)偿警,讓他們翻譯模板中的所有詞句,生成一個 .po 文件唯笙。通常螟蒸,你需要給你的翻譯人員向源代碼倉庫 commit 的權限盒使,這樣他們就能提交 .po 文件。之后七嫌,make install 命令會負責為用戶系統(tǒng)選擇正確的翻譯少办。

一個程序開始運行之后,它會查詢 LANG 系統(tǒng)變量抄瑟。如果程序自身存在一個與 LANG 對應的翻譯文件就會調用它凡泣,如果不存在就顯示英語。另外皮假,如果翻譯文件沒有實現(xiàn)完整的翻譯工作鞋拟,程序會調用所有已經翻譯的內容,而未被翻譯的依舊使用英語惹资。這使得翻譯工作可以逐步展開贺纲,只要翻譯者貢獻盡可能多的翻譯即可;并且褪测,如果你在程序新的版本中添加了一些新詞句猴誊,而翻譯人員度假去了,你也不用擔心整個工程前功盡棄侮措。

使用 gettext

首先懈叹,將我們現(xiàn)在的目錄拷貝一份到 app-skeleton4,或者直接重命名分扎,然后修改版本號澄成。為了將 gettext 添加到我們的編譯系統(tǒng)中,我們需要在 configure.ac 的“工具箱”部分添加如下內容:

app-skeleton4/configure.ac
AM_GNU_GETTEXT([external])
AM_GNU_GETTEXT_VERSION([0.18.1])

此外畏吓,在“輸出”部分的 AC_CONFIG_FILES 中添加一行:po/Makefile.in墨状,在 Makefile.amSUBDIRS 中將 po 添加進去(po 目錄是 gettext 文件默認存儲的地方。

Makefile.in 而非 Makefile 放入 AC_CONFIG_FILES 中可能有些令人困惑菲饼。這是因為 gettext 生成的文件名為 Makefile.in.in肾砂,我們需要把它轉換為 Makefile.in。隨后宏悦,由 AM_GNU_GETTEXT 宏生成的代碼會自動將它轉換為 Makefile镐确。當然,我們希望這種運行邏輯以后盡量少點出現(xiàn)饼煞,否則我們就可能會看到類似于 Makefile.in.in.in.in 的文件了辫塌。

我們現(xiàn)在需要運行 autoreconf -i 來安裝 gettext 相關文件。在執(zhí)行 configure 之前派哲,我們還需要在 po 文件夾中添加一些文件臼氨。第一個是 POTFILES.in,這個文件列出了 gettext 需要翻譯的所有文件芭届;第二個是 LINGUAS储矩,它列出了所有可用的翻譯語言感耙,元素之間用空格分隔。現(xiàn)在我們先創(chuàng)建這樣兩個空文件持隧,隨后我們再添加內容即硼。

最后一個需要添加的文件名為 Makevars。這個文件包含了一些可由用戶自定義的變量屡拨,這些變量將被應用于生成 po 目錄中的 Makefile只酥。剛才運行了 autoreconf 之后,目錄中應該已經有了一個模板文件 Makevars.template呀狼。我們用它拷貝出一個 Makevars 文件并修改少量內容:我把 COPYRIGHT_HOLDER 改成了自己的名字裂允,MSGID_BUGS_ADDRESS 改成了 $(PACKAGE_BUGREPORT),這樣翻譯人員就將會把 bug 匯報到我的郵箱中(再一個大型項目中哥艇,你可能需要設立不同的郵箱)绝编。

AutoconfPACKAGE_BUGREPORT 變量定義為我們在 configure.acAC_INIT 中設定的郵箱。

接下來貌踏,我們需要標記 hello-world.c 中所有需要翻譯的界面字符串十饥。首先在文件開頭加入一行:

// app-skeleton4/src/hello-world.c
#include <glib/gi18n.h>

這是 GLib 中專門定義 gettext 的庫(i18n 表示 “internationalization”,因為在首字母 “i” 和末字母 “n” 之間有 18 個字母)祖乳。這個頭文件中定義了函數(shù) _() 用于處理翻譯字符串(如果 gettext 沒有啟用逗堵,_() 就不會做任何事;程序名設計成 _ 是為了盡可能減少對讀寫代碼造成的影響)眷昆。

隨后蜒秤,我們在 main() 函數(shù)開頭添加下面這段代碼,在第 40 行輸入:

// app-skeleton4/src/hello-world.c
/* Set up internationalization */
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);

這段代碼使得程序能夠讀取翻譯文件的信息隙赁。最后垦藏,還要在 Makefile.am 中告訴程序去哪里尋找這些翻譯文件:

# app-skeleton4/src/Makefile.am
AM_CPPFLAGS = -DLOCALEDIR=\""$(localedir)"\"

目前我們有四個地方需要被標記成翻譯位置:一個在 print_hello() 中梆暖,一個在 on_delete_event() 中伞访,一個在 main()gtk_window_set_title() 的參處中,還有一個在 main()gtk_button_new_with_label() 中轰驳。我們用 _() 把這些字符串括起來厚掷,比如 "Hello World" 就變成了 _("Hello World")

注意并不是所有的字符都需要翻譯级解!例如在函數(shù) g_signal_connect() 中的信號名和 gtk_window_set_icon_name() 中的圖標名就不需要任何處理冒黑。程序內部調用的字符串均不需要翻譯,只有程序界面顯示的字符串才需要勤哗。如果你將 "destroy" 信號翻譯成德語抡爹,那程序就崩潰了,畢竟它可不知道 “zerst?ren” 信號是個什么鬼芒划。

完成上述工作后冬竟,我們需要在 POTFILES.in 中添加需要被翻譯的文件:

# app-skeleton4/po/POTFILES.in
src/hello-world.c

如果我們現(xiàn)在在 po 目錄下運行 make update-po欧穴,就會產生一個名為 app-skeleton.pot 的文件。這是翻譯人員的模板文件泵殴。

翻譯程序

我們試著將程序翻譯成其它的語言來測試上面的工作涮帘。我將以荷蘭語(語言代碼 nl)做介紹。

首先要做的是創(chuàng)建一個翻譯語言的 .po 文件笑诅,在 po 目錄下運行:

msginit -l nl

這將會基于之前的翻譯模板生成一個名為 nl.po 文件调缨。你可以用你喜歡的編輯器編輯它,在更大型的項目中吆你,你可能會需要一個專業(yè)的翻譯文件編輯器弦叶,比如 VirtaalPoedit。你可以自己翻譯早处,也可以直接用我的:

#: src/hello-world.c:11
msgid "Hello World\n"
msgstr "Hallo Wereld\n"

#: src/hello-world.c:27
msgid "delete event occurred\n"
msgstr "delete event heeft plaatsgevonden\n"

#: src/hello-world.c:52
msgid "Hello"
msgstr "Hallo"

#: src/hello-world.c:76
msgid "Hello World"
msgstr "Hallo Wereld"

翻譯完成后湾蔓,將語言代碼添加到 LINGUAS 中:

nl

隨后在 po 目錄下再一次運行 make update-po。這條命令很重要砌梆,每次有翻譯人員上傳了新的文件時默责,你都應該運行一次,否則文件就不會被應用咸包。隨后我們可以運行 make install 來安裝桃序。

你現(xiàn)在應該已經可以運行荷蘭語的程序了(或者其它你選擇的語言)。如果你的系統(tǒng)區(qū)域設定為荷蘭烂瘫,直接運行程序就能看到效果媒熊。如果是其它的區(qū)域則需要在運行程序時單獨設定 LANG 環(huán)境變量(在終端中輸入 LANG=nl app-skeleton)。

譯者注:常用的語言代碼有:

  • zh_CN:中文(中國大陸)
    zh_HK:中文(中國香港)
    zh_TW:中文(中國臺灣)
    zh_SG:中文(新加坡)
  • en_US:英語(美國)
    en_UK:英語(英國)
    en_CA:英語(加拿大)
    en_HK:英語(中國香港)

更多語言代碼請參閱 Language CodesLocale Helper坟比。

翻譯非代碼文件

gettext 有一個缺陷:它只對代碼文件有效芦鳍,可以通過調用 gettext() 讀取翻譯。而類似于 xml葛账、桌面文件等數(shù)據(jù)文件則愛莫能助柠衅。這便是引入 intltool 的原因。它將這些文件中需要翻譯的字符串也添加到了翻譯模板中籍琳。在這些詞句被翻譯后菲宴,它還會將這些翻譯整合回數(shù)據(jù)文件中。我們現(xiàn)在將 intltool 添加到我們的程序中來翻譯桌面文件趋急。

首先喝峦,intltool 有它自己的引導程序——intltoolize,它必須在 autoreconf 之后才能運行呜达。使用了 intltool 之后我們的引導過程就不能再只用一句 autoreconf -i 敷衍了事了谣蠢,我們需要制作一個引導腳本。在項目根目錄下,我們創(chuàng)建一個 autogen.sh 文件眉踱,賦予它可執(zhí)行權限勋颖,寫入:

# app-skeleton4/autogen.sh
#!/bin/bash

echo "Regenerating autotools files"
autoreconf --force --install || exit 1

echo "Setting up Intltool"
intltoolize --copy --force --automake || exit 1

我們需要用到 --force 選項,因為 autoreconfintltoolize 會覆蓋掉彼此的 po/Makefile.in.in 文件勋锤。寫好之后我們就可以運行一次引導腳本饭玲。

隨后,在 configure.ac 的 “工具箱” 部分添加如下內容:

# app-skeleton4/configure.ac
IT_PROG_INTLTOOL([0.40])

在 “庫” 部分叁执,我們添加一個新的 “變量” 部分茄厘。為了能夠正常使用 intltool,我們需要定義一個名為 GETTEXT_PACKAGE 的變量谈宛,它指向程序在 gettext 中被定義的名字次哈。

# app-skeleton4/configure.ac
# Needed by intltool
GETTEXT_PACKAGE=${PACKAGE_TARNAME}
AC_SUBST([GETTEXT_PACKAGE])

AC_SUBST 宏會確保所有 Makefile 中的 @GETTEXT_PACKAGE@ 變量都會被替換成變量指代的實際內容。現(xiàn)在再運行一次 make吆录。

接下來窑滞,我們需要告訴 intltool 哪些數(shù)據(jù)文件包含了需要被翻譯的語句。慶幸的是恢筝,有一個叫作 intltool-prepare 的腳本會自動幫我們完成這些工作哀卫。在項目根目錄下運行 intltool-prepare,你會注意到它自動將桌面文件添加到了 po/POTFILES 中并且修改了 Makefile.am 中桌面文件的安裝規(guī)則撬槽。

它還新建了一個文件此改,app-skeleton.desktop.in。如果你使用了代碼控制系統(tǒng)的話侄柔,最好遵循它給出的建議從倉庫中移除你的 app-skeleton.desktop 文件 —— 它現(xiàn)在可以由編譯系統(tǒng)根據(jù) app-skeleton.desktop.in 自動創(chuàng)建出來共啃。從現(xiàn)在起,如果你想編輯桌面文件暂题,請在 app-skeleton.desktop.in 中做修改移剪。

如果需要翻譯桌面文件,我們需要在 po 目錄下再運行一次 make update-po 命令薪者。你將會看到 .pot.po 文件中新添加了兩句未翻譯的語句纵苛。你可以自行翻譯它們,也可以用我的翻譯:

#: ../app-skeleton.desktop.in.h:1
msgid "A sample application from the Advanced GTK+ Techniques tutorial"
msgstr "Een voorbeeldapplicatie uit de cursus Gevorderde GTK+ Technieken"

#: ../app-skeleton.desktop.in.h:2
msgid "App Skeleton"
msgstr "Skeletapplicatie"

接著啸胧,再運行一次 make update-po赶站,然后是 make幔虏。你可以看到在生成的 app-skeleton.desktop 中你的翻譯已經被整合進去了纺念。如果你現(xiàn)在運行 make install,翻譯文件就會被安裝想括。

以上就是全部編譯基礎構建的內容∠萜祝現(xiàn)在我們可以正式開始寫代碼了。:-)


文章許可協(xié)議:Attribution-NonCommercial-ShareAlike 3.0 Unported

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市烟逊,隨后出現(xiàn)的幾起案子渣窜,更是在濱河造成了極大的恐慌,老刑警劉巖宪躯,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件乔宿,死亡現(xiàn)場離奇詭異,居然都是意外死亡访雪,警方通過查閱死者的電腦和手機详瑞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來臣缀,“玉大人坝橡,你說我怎么就攤上這事【茫” “怎么了计寇?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長脂倦。 經常有香客問我番宁,道長,這世上最難降的妖魔是什么赖阻? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任贝淤,我火速辦了婚禮,結果婚禮上政供,老公的妹妹穿的比我還像新娘播聪。我一直安慰自己,他們只是感情好布隔,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布离陶。 她就那樣靜靜地躺著,像睡著了一般衅檀。 火紅的嫁衣襯著肌膚如雪招刨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天哀军,我揣著相機與錄音沉眶,去河邊找鬼。 笑死杉适,一個胖子當著我的面吹牛谎倔,可吹牛的內容都是我干的。 我是一名探鬼主播猿推,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼片习,長吁一口氣:“原來是場噩夢啊……” “哼捌肴!你這毒婦竟也來了?” 一聲冷哼從身側響起藕咏,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤状知,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后孽查,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體饥悴,經...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年盲再,在試婚紗的時候發(fā)現(xiàn)自己被綠了铺坞。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡洲胖,死狀恐怖济榨,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情绿映,我是刑警寧澤擒滑,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站叉弦,受9級特大地震影響丐一,放射性物質發(fā)生泄漏。R本人自食惡果不足惜淹冰,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一库车、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧樱拴,春花似錦柠衍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至正罢,卻和暖如春阵漏,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背翻具。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工履怯, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人裆泳。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓叹洲,卻偏偏與公主長得像,于是被迫代替她去往敵國和親晾虑。 傳聞我的和親對象是個殘疾皇子疹味,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內容