Thursday, November 28, 2013

mako二三事 -- 与Babel的结合

为了支持国际化,在python程序中,经常需要使用Babel将语言相关的字符串抽取出来,形成pot文件。而在mako模板文件中,有大量的文本性内容需要国际化处理,因此,mako必须要支持Babel的抽取功能。

一、mako字符串的简单抽取

在mako中,使用了一个名为mako.ext.babelplugin的Babel抽取插件,正确安装Babel、mako后,就可以使用pybabel命令进行字符串抽取。

首先,我们创建一个a.html文件,内容为:


  Name:
  ${_('Francois Pinard')}



再创建一个babel.cfg文件,作为Babel 的配置文件:

[mako: **.html]
input_encoding = utf-8 

然后运行命令

pybabel extract -F babel.cfg .

即可在console输出:

extracting messages from a.html (input_encoding="utf-8")
# Translations template for PROJECT.
# Copyright (C) 2013 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
# FIRST AUTHOR , 2013.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2013-11-26 16:01+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 0.9.6\n"

#: a.html:3
msgid "Francois Pinard"
msgstr ""  

这个就是我们通常使用的pot文件,有了pot文件,我们就可以很方便的按照国际化命令生成po文件,mo文件。

在a.html中,我们可以看到的一个明显的变化是:Francois Pinard这段文本被改写成了${_('Francois Pinard’)},mako的Babel插件能够识别这种格式并抽取到pot文件中,而普通的文本name:则不会。

Babel进行抽取的时候,需要指定一个配置文件,这里我们做了一个简单的配置文件babel.cfg。在该文件中,**.html表示本目录以及子目录所有html文件,前面的mako表示这些文件均有mako的Babel插件来解析。input_encoding为模板的编码格式,这个跟模板载入时用的encoding是一致的。

二、对抽取字符串做注释

有时候,为了能够清楚分辨抽取字符串,可以对这些字符串做一个注释。

首先,我们修改a.html为:


  Name:
  ## TRANSLATORS: This is a proper name. See the gettext
  ## manual, section Names.
  ${_('Francois Pinard')}


这里要注意的是,这个注释必须直接放在抽取字符串之前,中间不能有其他多余字符串。

然后,运行

pybabel extract -F babel.cfg -c "TRANSLATORS:” . 

可以得到: 

#. TRANSLATORS: This is a proper name. See the gettext
#. manual, section Names.
#: a.html:5
msgid "Francois Pinard"
msgstr "" 

从上面结果可以看到,在pot文件中,将html文件里面对这个字符串的注释也抽取到了该文件中。


三、pyramid项目的支持

通常的,我们不会简单的对一个文件进行国际化,而是对一个使用了特定framework的项目进行国际化。比如使用了pyramid框架,通过pcreate生成的项目中,会有setup.py和setup.cfg两个文件,为了支持Babel抽取,需要在setup.py中加入mako配置(setup中加两个参数):

      package_data={'mypyramid': ['locale/*/LC_MESSAGES/*.mo']},
      message_extractors = { 'mypyramid': [
          ('**.py',   'lingua_python', None ),
          ('templates/**.pt',   'lingua_xml', None ),
          ('templates/**.html', 'mako', None),
          ('static/**', 'ignore', None),
          ]}, 

然后在mypyramid目录下建立locale文件夹即可。这里的'templates/**.html', 'mako', None含义跟上面的配置文件含义一致。

另外,在setup.cfg中,有国际化字符串抽取、编译、更新的系列配置,如果有需要,可以调整这些参数。
[compile_catalog]
directory = mypyramid/locale
domain = MyPyramid
statistics = true

[extract_messages]
add_comments = TRANSLATORS:
output_file = mypyramid/locale/MyPyramid.pot
width = 80

[init_catalog]
domain = MyPyramid
input_file = mypyramid/locale/MyPyramid.pot
output_dir = mypyramid/locale

[update_catalog]
domain = MyPyramid
input_file = mypyramid/locale/MyPyramid.pot
output_dir = mypyramid/locale
previous = true 

在pyramid项目中,为了支持国际化,还需要从python程序中将_这个函数压入到context中,如下:

tsf = TranslationStringFactory('MyPyramid’)
 
@subscriber(BeforeRender)
def add_renderer_globals(event):
    def auto_translate(string, domain=None, mapping=None):
        return localizer.translate(tsf(string), domain=domain, mapping=mapping) 
    request = event.get('request')
    if request:
        event['_'] = auto_translate

No comments:

Post a Comment