國際化複數形式的支持與pygettext的補丁

國際化複數形式的支持與pygettext的補丁

今天把plugs中的論壇進行了一些優化,其中想使用uliweb中早就內置的timesince.py模塊。這塊須要i18n的支持。因而使用:html

uliweb i18n -l zh_CN --uliweb前端

來運行。結果報錯。其主要緣由是timesince中使用了複數形式的i18n函數ungettext。而uliweb使用的pygettext.py不支持。python

pygettext.py 是python在tools目錄下自帶的一個模塊,能夠用它來從python源碼中抽取翻譯字符串,它支持命令行,代碼也不算很複雜。因此在uliweb 中提供了純python的命令行工具。不過uliweb爲了讓其能夠支持模板和ini文件,修改了pygettext源碼,因此和python自帶的還不 徹底同樣。許多其它的python項目是使用xgettext工具來處理。由於pygettext.py不支持複數的翻譯串,我查了一下,主要區別就是對 於複數,在po文件中是這樣的:linux

msgid "month"web

msgid_plural "months"app

msgstr[0] "月"dom

msgstr[1] ""而不帶複數的形式是這樣的:

msgid "month"ide

msgstr "月"函數

原本想自已修改的,不過仍是先google一下吧,萬一有人解決了呢。結果還真找到了。有人在python的bugs網站上提交過這樣的問題,而後有人給出了一個 補丁。從pygettext.py的源碼能夠看到,它已經不少看沒有被修改過了。因而我下載了補丁,先在python帶的版本上打補丁,而後使用代碼比較工具將我須要的修改再加進去。後來還修改了po_merge.py程序。最終把這個問題基本上算是解決了。工具

 

python使用gettext來實現i18n支持。具體參數信息請看gettext
module幫助。

python中對於國際化的字符串,只須要外加_()便可。

如: print(_('hello world'))
而後根據user選擇的語言,建立translation對象,而後調用install方法install_()函數
到Python’s builtins namespace。如:
1 import gettext
2 en_trans = gettext.install('messages', locale='i18n_path', languages=['default_language'])
3 zh_trans = gettext.install('messages', locale'i18n_path', languages=['zh_CH'])
4 print(_('hello world'))
5 zh_trans.install()
6 print(_('hello world'))


而對於web服務中前端頁面的國際化支持也很是簡單,和python source文檔中同樣
在須要國際化的字符串前面添加_()便可。而後在render函數中,把當前translation對象
傳入模板便可。如Tornado render_string的實現:
01 def render_string(self, template_name, **kwargs):
02         # If no template_path is specified, use the path of the calling file
03         ... ...
04         args = dict(
05             handler=self,
06             request=self.request,
07             current_user=self.current_user,
08             locale=self.locale,
09             _=self.locale.translate,            
10             static_url=self.static_url,
11             xsrf_form_html=self.xsrf_form_html,
12             reverse_url=self.application.reverse_url
13         )
14         args.update(self.ui)
15         args.update(kwargs)
16         return t.generate(**args)


好了,上面搭建好i18n所須要的環境,下面就是準備對語言字符資源了。

python 工具: pygettext msgfmt

其餘工具: msgmerge
1. 建立po文檔

在當前目錄下建立locale文件夾,下面分別建en_US/LC_MESSAGES/ 和 zh_CN/LC_MESSAGES/目錄。
在locale下面建立名爲 demo.html的文件內容以下:
1 <html>
2     <head>
3         <title>${_('title')}</title>
4     </head>
5     <body>
6     <a href=''>${_('body')}</a>
7 </body>
8 </html>


而後打開命令行窗口,輸入 python pygettext.py -a -v -d messages -o messages.po \*.py \*.html
完成後,在當前目錄生成 messages.po 文件。
打開message.po 會看到其中的格式內容:
01 # SOME DESCRIPTIVE TITLE.
02 # Copyright (C) YEAR ORGANIZATION
03 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
04 #
05 msgid ""
06 msgstr ""
07 "Project-Id-Version: PACKAGE VERSION\\n"
08 "POT-Creation-Date: %(time)s\\n"
09 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n"
10 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\\n"
11 "Language-Team: LANGUAGE <LL@li.org>\\n"
12 "MIME-Version: 1.0\\n"
13 "Content-Type: text/plain; charset=CHARSET\\n"
14 "Content-Transfer-Encoding: ENCODING\\n"
15 "Generated-By: pygettext.py %(version)s\\n"
16  
17 #: demo.html:3
18 msgid "title"
19 msgstr ""
20  
21 #: demo.html:6
22 msgid "body"
23 msgstr ""

說明: #: demo.html:3
msgid "title"      #待轉換的字符串
msgstr ""          #轉換後的字符bytes,若是爲空,則返回原字符

關鍵信息:"Content-Type: text/plain; charset=CHARSET\n
這裏的CHARSET 指定了 msgstr的codeset。通常推薦charset設定爲utf-8.
關於msgstr保存的信息須要說明:實際上它是一個bytes,是翻譯後的字符串
調用encode結果。
而當調用_()函數時,實際上會調用translation設置的默認charset來decode(具體請參考gettext module)。
即咱們在message.po設置的charset。

2. 翻譯字符資源
將生成的messages.po的分別copy至 en_US/LC_MESSAGES/ 和 zh_CN/LC_MESSAGES/目錄下。
分別切換至en_US/LC_MESSAGES/ 和 zh_CN/LC_MESSAGES/ 目錄,
編輯messages.po,修改添加翻譯後的字符(注:source.encode(charset))

3. 生成mo文件
分別切換目錄至en_US/LC_MESSAGES/ 和 zh_CN/LC_MESSAGES/,
在命令行輸入: python msgfmt.py messages.po 生成mo文件。

最終生成的locale tree的目錄相似linux系統的/usr/share/locale,
 locale/{lang}/LC_MESSAGES/{domain}.mo

測試:
01 >>> import gettext
02 >>> en_trans = gettext.translation('messages', 'e:/python/locale', languages=['en_US'])
03 >>> zh_trans = gettext.translation('messages', 'e:/python/locale', languages=['zh_CN'])
04 >>> en_trans.gettext('title'), en_trans.gettext('body')
05 ('title', 'body')
06 >>> zh_trans.gettext('title'), zh_trans.gettext('body')
07 ('HTML Head 頭', 'HTML Body 測試')
08 >>> en_trans.install()
09 >>> _('title'), _('body'), _('hello')
10 ('title', 'body', 'hello')
11 >>> zh_trans.install()
12 >>> _('title'), _('body'), _('hello')
13 ('HTML Head 頭', 'HTML Body 測試', 'hello')

上例使用的python解析器是python3.2.2 2.*版本有些method參數稍有不一樣,請注意!

你們都知道SlideShowPro Director的語言文件是以mo和po爲結尾的,po的話能夠用EmEditor打開,可是mo的話,由於是Linux系統下的文件,因此 須要反編譯成po文件才能打開,下面就是來跟你們介紹一下相關的軟件和使用方法。

1、先來介紹一下相關的軟件:

1.編譯反編譯軟 件"gettext"

下載地址

2.po 文件的編輯軟件"poedit"

下載地址 下載地址

2、 接下來來講說他們的使用方法:

1.下載好的"gettext"是一個安裝文件,默認安裝路徑是C:\Program Files\GnuWin32\,當你須要把D盤根目錄下的default.mo反編譯成default.po時,你能夠在開始菜單的 「運行」中輸入"cmd",而後ms-dos界面下輸入引號中的內容"C:\Program Files\GnuWin32\bin\msgunfmt.exe d:\default.mo -o d:\default.po"便可完成反編譯。

2.編譯的 話有兩種辦法,第一種就是仍舊使用"gettext」軟件,輸入"C:\Program Files\GnuWin32\bin\msgfmt.exe -o d:\default.mod:\default.po"便可完成編譯工做。
注:用此方法反編譯後再編譯回來的文件和源文件是徹底相同的。

第 二種就是用"poedit"軟件打開一個反編譯後的po文件,翻譯後點選「保存消息目錄文檔」,它就會自動生成相同文件名的.mo文件。

注:用此方法生成mo文件時可能會報錯,生成的文件會和原來的有差別。

相關文章
相關標籤/搜索