国际化复数形式的支持与pygettext的补丁

↘锁芯ラ 提交于 2020-04-06 21:11:29

国际化复数形式的支持与pygettext的补丁

今天把plugs中的论坛进行了一些优化,其中想使用uliweb中早就内置的timesince.py模块。这块需要i18n的支持。于是使用:

uliweb i18n -l zh_CN --uliweb

来运行。结果报错。其主要原因是timesince中使用了复数形式的i18n函数ungettext。而uliweb使用的pygettext.py不支持。

pygettext.py 是python在tools目录下自带的一个模块,可以用它来从python源码中抽取翻译字符串,它支持命令行,代码也不算很复杂。所以在uliweb 中提供了纯python的命令行工具。不过uliweb为了让其可以支持模板和ini文件,修改了pygettext源码,所以和python自带的还不 完全一样。许多其它的python项目是使用xgettext工具来处理。因为pygettext.py不支持复数的翻译串,我查了一下,主要区别就是对 于复数,在po文件中是这样的:

msgid "month"

msgid_plural "months"

msgstr[0] "月"

msgstr[1] ""而不带复数的形式是这样的:

msgid "month"

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.编译反编译软 件"gettext"

下载地址

2.po 文件的编辑软件"poedit"

下载地址 下载地址

二、 接下来来说说他们的使用方法:

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文件时可能会报错,生成的文件会和原来的有差异。


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!