Zope3宝典/国际化软件包

来自Ubuntu中文
跳到导航跳到搜索

Chapter 18: Internationalizing a Package(第 18 章:国际化软件包)


原文出处:The Zope 3 Developers Book - An Introduction for Python Programmers

原文作者:StephanRichter, zope.org

授权许可:创作共用协议

翻译人员:

校对人员:Leal, FireHare

适用版本:Zope 3

文章状态:校正阶段



Difficulty(难度)

Sprinter(进阶者)

Skills(技能)

  • You should be familiar with the previous chapters of the “Content Components” section.
    您应该熟悉前面的“内容组件”章节的内容;
  • Familiarity with Page Templates is desired.
    需要熟悉页面模板;
  • Basic knowledge of the gettext format and tools is also a plus. Optional.
    需要具备Gettext工具的基础知识(可选)。

Problem/Task(问题/任务)

Now that we have a working message board package, it is time to think about our friends overseas and the fact that not everyone can speak English. Therefore it is our task now to internationalize and localize the code to ...let’s say German.
现在我们有一个可以正常工作的软件包,如今我们需要替我们的海外朋友想想了,事实上不是每个人都能讲英语。因此我们现在的任务就把代码国际化和本地化...让我们试试德语。


Solution(解决方案)

Before we can start coding, it is important to cover some of the basics. You might already have wondered about the difference between the terms internationalization and localization.
在我们开始编码以前,对一些基础概念做一些了解是很重要的,您可能已经想知道国际化和本地化条款之间的所存在的差异。

  • Internationalization (I18n) is the process of making a package translatable, basically the programmer’s task of inserting the necessary code so that human-readable strings can be translated and dates/times be formatted, respecting the users “locale” settings.
    国际化(I18n)就是制作可翻译软件包的过程,程序员的基本任务就是插入必要的代码,把字符串翻译成可理解的格式并且日期/时间被格式化,这与用户的本地设置(“locale”)有关。
  • Localization (L10n) is the process of actually creating a translation for a particular language. Often translations are not done by programmers but by translators (or formally, localization vendors).
    本地化(L10n)实际上就是转换成一种特殊语言的过程。翻译常常不是有程序员来做,而是由翻译者来做(或者由正式的本地供货商来做)。

But what is a so-called “locale”? Locales are objects that contain information about a particular physical/abstract region in the world, such as language, dialect, monetary unit, date/time/number formats and so on. An example of a locale would be “de_DE_PREEURO” (language, country/region, variant), which describes Germany before the Euro was introduced. However, “de” is also a valid locale, referring to all German speaking regions. So you can imagine that there is a locale hierarchy. “de_DE_PREEURO” is more specific than “de_DE”, which is in turn more specific than “de”. So if the user’s locale setting is “de_DE_PREEURO” and we want to look for the date format template, the system will look up the path in “de_DE_PREEURO”, then “de_DE” and finally in “de”, where it will find it.
但是一个所谓的“locale(本地)”是什么? Locales是一个包含世界上一个特定物理区域/抽象区域的信息对象,例如语言、方言、货币单位、日期/时间/数字 格式等。例子中的locale将是“de_DE_PREEURO”(语言、国家/地区,差异),在Euro被介绍之前以德国来描述。然而,“de”也是一个有效的locale,涉及到所有讲德语的地区。因此您可以想象的到这儿有一个locale体系。“de_DE_PREEURO”是比“de_DE”更加特殊,当然更特殊于“de”。因而如果用户的locale设置是“de_DE_PREEURO”并且我们想寻找一个日期格式模板,系统将在“de_DE_PREEURO”这个路径里寻找该模板,然后依次是“de_DE”,最后才是“de”。

Note that this chapter has little to do with Python development, but is still useful to know, since all Zope 3 core components are required to be internationalized.
注意这章与Python开发完全无关,但知道一些仍然是有用的,因为所有Zope3核心组件都要求被国际化。

/湌?恪('!櫋?ㄝS唻?C9Y这黅=U>赶陗�iVs�8?€鏊拭E搴媍�渊?>昘7??摃Rjf锭殉佁~V?ZgI2�yM鎁?剪I!促?VCw缝▊� 斍V+礒楯滰W={?~\b蓇?飺C藢梪铁 h*)�栬梢殌Y?萛晧釛4y

18.2 Step II: Internationalizing Page Templates(18.2 步骤 II:国际化页面模板)

Internationalizing Page Templates is more interesting in many ways. We do not only have to worry about finding the correct tags to internationalize, but since we also can have heavy nesting, the complexity can become overwhelming. My suggestion: Keep the content of translatable tags as flat as possible, i.e. try to have translatable text that does not contain much HTML and TAL code.
采用多种方法对页面模板进行国际化是一件非常有趣的事情。由于有太多的嵌套,复杂得已经难以让我们承受。因此发现正确的标记进行国际化不仅仅是我们必须担心的内容。我的建议是:尽可能保持可转换标记简单化,尝试可转换文本不包含太多HTML和TAL代码。

To achieve internationalization support in Zope 3’s Page Templates, we designed a new i18n namespace. It is well documented at http://dev.zope.org/Zope3/ZPTInternationalizationSupport. The three most common attributes are i18n:domain, i18n:translate and i18n:attributes. Note that the i18n namespace has been back-ported to Zope 2 as well, so you might be familiar with it already.
为了在Zope 3的页面模板里实现支持国际化,我们设计了一个新的i18n命名空间。文档您可以在 http://dev.zope.org/Zope3/ZPTInternationalizationSupport 找到。这儿有三个通用属性,分别是:i18n:domain、i18n:translate和i18n:attributes。注意:i18n已经被很好的移植到了Zope 2,因此您可能对它已经很熟悉了。

The cleanest Page Template in the browser package is details.pt, so let’s internationalize it first:
在browser软件包里,details.pt是最简洁的页面模板,因此,让我们最先来对该页面进行国际化:

1  <html metal:use-macro="views/standard_macros/page">
2    <body>
3      <div metal:fill-slot="body" i18n:domain="messageboard">
4  
5        <h1 i18n:translate="">Message Details</h1>
6  
7          <div class="row">
8              <div class="label" i18n:translate="">Title</div>
9              <div class="field" tal:content="context/title" />
10          </div>
11  
12          <div class="row">
13              <div class="label" i18n:translate="">Author</div>
14              <div class="field" tal:content="view/author"/>
15          </div>
16  
17          <div class="row">
18              <div class="label" i18n:translate="">Date/Time</div>
19              <div class="field" tal:content="view/modified"/>
20          </div>
21  
22          <div class="row">
23              <div class="label" i18n:translate="">Parent</div>
24              <div class="field" tal:define="info view/parent_info">
25                <a href="../"
26                    tal:condition="info"
27                    tal:content="info/title" />
28              </div>
29          </div>
30  
31          <div class="row">
32              <div class="label" i18n:translate="">Body</div>
33              <div class="field" tal:content="structure context/body"/>
34          </div>
35  
36      </div>
37    </body>
38  </html>
  • Line 3: The best place for the domain specification is this div tag, since it is inside a specific slot and will not influence other template files’ domain settings.
    第3行:在div标记中指定域(domain)是最好的选择,因为它在一个特定的区域了并且不会影响到其它模板文件的域设置。
  • Line 8, 13, 18, 23 & 32: The i18n:translate="" just causes the content of the div tag to be translated.
    第8、13、18、23&32行:标有i18n:translate="" 的div标记里面的内容将被转换。

    Note that there was no need here to use i18n:attributes. However, when we deal with buttons, we use this instruction quite often. Here an example:
    注意在这儿我们没有必要使用i18n:attributes。然而,当我们处理按钮(button),我们还是经常这样做,实例如下:
1  <input type="submit" value="Add" i18n:attributes="value add-button" />

Similar to tal:attributes the value-attribute value will be replaced by the translation of add-button or remains as the default string ( Add), if no translation was found.
类似与tal:attributes,value-attribute的值将被add-button的转换替代,如果转换没有被发现,就保持缺省字符串(Add)。

This is really everything that is needed for Page Templates. As exercise 1 and 2 state, you should finish the other templates yourself. (Hint: If you do exercise 1 at this point, you can skip exercise 2.)
这是页面模板真正需要的。通过练习1、2,自行完成其它的模板。(提醒:如果您做练习1,您可以跳过练习2)。

18.3 Step III: Internationalizing ZCML(18.3 步骤 III:国际化 ZCML)

Internationalizing ZCML is a one time, one step process. All you need to do here is to add a i18n_domain="messageboard" attribute assignment in your configure tag of the main configure.zcml file. It is the responsibility of the directive author to specify which attribute values should be converted to message ids, so that you have to worry about nothing else. All of this might seem a bit magical, but it is explicit and an incredibly powerful feature of Zope 3’s translation system, since it minimizes the overhead of internationalizing ZCML code.
您需要在configure.zcml文件中的configure标记里添加i18n_domain="messageboard"属性。指令负责指定哪个属性值应该被转换成message id,因此您不需要有任何的担忧。所有的这些看起来都有些不可思议,Zope 3强大的翻译系统真的令人难以置信,因为它能让国际化ZCML代码开销减少到最少。

Setting this attribute will get rid of all the warnings you experienced until now when starting up Zope 3.
设置该属性时,您将忽略您所遇到的所有警告,直到Zope 3被启动。

18.4 Step IV: Creating Language Directories(18.4 步骤 IV:创建语言目录)

The directory structure of the translations has to follow a strict format, since we tried to keep it gettext compatible. By convention we keep all message catalogs and message catalog templates in a directory called locales (so create it now). This directory typically contains the message catalog template file (extension pot) and the various language directories, such as en. Since we want to create a translation for English and German, create the directories en and de, respectivily.
翻译的目录结构必须遵循一个严格的格式,因为我们尝试让它与gettext保持一致。现在创建一个名叫locales的目录,按照约定,我们把所有的message目录以及所有的message目录模板都放进locales里面。这个目录包含了message目录模板文件(扩展名为pot)和不同的语言目录,比如说en。既然我们想实现从英语转译成德语,那么现在我们应该创建en和de。

Now comes the part that might not make sense at first. The language directories do not contain the message catalog directly, but another directory called LC_MESSAGES. Create them in each language directory.
首先需要说明的是:接下来的部分可能没有任何意义。语言目录不直接包含message目录,但是需要在每个语言目录里面创建另一个名叫LC_MESSAGES的目录。

Since English is our default language, we always want it to use the default value. Therefore the message catalog can be totally empty (or just contain the meta-data). Create a file called messageboard.po in the locales/en/LC_MESSAGES directory and add the following comment and meta data.
既然英语是我们的缺省语言,以致于系统总是会使用缺省语言。因此message目录能够都为空(或者只包含元数据)。在locales/en/LC_MESSAGES目录里创建文件messageboard.po,并且在该文件里加上如下注释和元数据:

1  # This file contains no message ids because the messageboard's default
2  # language is English
3  msgid ""
4  msgstr ""
5  "Project-Id-Version: messageboard\n"
6  "MIME-Version: 1.0\n"
7  "Content-Type: text/plain; charset=UTF-8\n"
8  "Content-Transfer-Encoding: 8bit\n"

Now you are done with the preparations. Before we can localize the message board, we need to create the message catalogs as it will be described in the next section.
现在我们已经做完了准备工作。在我们本地化留言簿程序之前,我们需要创建一个message目录,在下一节我们将继续讨论。

18.5 Step V: Extracting Translatable Strings(18.5 步骤 V:提取翻译字符串)

Zope provides a very powerful extraction tool to grab all translatable text strings from Python, Page Template and ZCML files. With each translatable string, the file and line number is recorded and later added as comment in the message catalog template file.
Zope 提供了一个非常强大的提取工具来获取所有来自Python、页面模板、ZCML文件的可翻译文本字符串。在message目录模板文件里,就每个可翻译的字符串以注释记录了文件和行号。

After all strings were collected and duplicates merged into single entries, the tool saves the strings in a message catalog template file called <domain>.pot. This is the beginning of localization. From now on we are only concerned about using the template to create translations.
收集所有的字符串并且把副本并入各自的条目,工具在名叫<domain>.pot的message目录模板文件里保存了字符串。这才是本地化的开始,从现在开始我们唯一需要关心的就是用模板创建翻译。

The extraction tool, called i18nextract.py, can be found in ZOPE3/utilities. Before executing the tool, add your Zope 3 source directory to the PYTHONPATH, so that all necessary modules are found. In bash the PYTHONPATH can be set using
i18nextract.py就是系统中的提取工具,您可以在ZOPE3/utilities里发现它,在运行该工具之前,为了发现所有必须的模块,把您的Zope 3 源目录加入到PYTHONPATH。具体做法如下:

1  export PYTHONPATH=$PYTHONOATH:ZOPE3/src

To execute the tool, go to the messageboard directory and enter the following command. Make sure that you entered the absolute path for ZOPE3, since the tool does not work well with symlinks.
运行工具,在messageboard目录里输入如下命令。由于该工具不能很好的以symlinks工作,因此您需要确认您输入ZOPE3的绝对路径。

1   python ZOPE3/utilities/i18nextract.py -d messageboard -p ./ -o ./locales

This will extract all translatable strings from the message board package and store the template file as messageboard/locales/messageboard.pot.
这将从留言簿软件包中提取所有的可翻译字符串并且把messageboard/locales/messageboard.pot当作存储模板文件。

As you can see, the tool supports three options plus an help option:
正如您所看到的,可以通过帮助查看该工具的三个附加选项:

  • -h/--help - Print the help of the i18nextract.py tool on the screen and exit.
    -h/--help - 获取帮助
  • -d/--domain<domain> - This option specifies the domain, in our case messageboard, that is supposed to be extracted.
    -d/--domain<domain> -指定域
  • -p/--path<path> - The path specifies the package by path that is searched for translatable strings. In our case we just used ./, since we already were in the package.
    -p/--path<path> - 指定路径.
  • -odir - This option specifies a directory, relative to the package in which to put the output translation template, which is commonly ./locales in add-on packages.
    -odir - 指定目录

If you wish to update the Zope 3 core message catalog template file, you simply run the extraction tool without specifying any options.
如果您希望更新Zope 3核心的message目录模板文件,您需要在不指定任何附加参数的情况下运行该提取工具。

18.6 Step VI: Translating Message Strings(18.6 步骤 VI:翻译消息字符串)

Now that we have a Message Catalog Template file, we can finally create a translation. Since we do not have existing message catalogs, you can simply copy the POT template file to the language you want to localize. In Unix you can just do the following from the locales directory:
既然我们已经有了一个Message目录模板文件,那么我们现在就可以着手创建一个翻译。由于现在还没有message目录,您可以拷贝POT模板文件到相应的语言目录。在Unix您可以使用如下命令:

1  cp messageboard.pot de/LC_MESSAGES/messageboard.po

Open de/LC_MESSAGES/messageboard.po in you favorite translation tool or a text editor. However, it is strongly recommended to use a gettext-specific translation tool, since it will guarantee format integrity. Some of the choices include KBabel and the Vim/Emacs gettext modes.
用文本编辑器打开de/LC_MESSAGES/messageboard.po文件。在这里,为了保持文件格式的完整性,我们强烈建议您使用专有的gettext翻译工具。比如说Vim/Emacs、KBabel都是些不错的选择。

KBabel seems to be the most advanced tool and develops to become a standard application for localization. It has many functions that make it easy for translators to do their job efficiently. My wife and I have translated many files using KBabel and it is a fantastic tool. It allows you, for example, to walk only through all untranslated or fuzzy strings and helps managing the message strings by providing message numbers and statistics.
高级工具KBabel已经成为进行本地化开发的标准应用程序。它有很多功能可以让翻译工作变得更加容易和高效。我和我妻子使用KBabel翻译了许多的文件,KBabel真是一个让人感到奇妙的工具。举例来说, 它排列所有未翻译或模糊字符串,并且通过提供message编号和统计学来帮助管理message字符串。

After you are done with the translations, save the changes and you should be all set.
在做完翻译工作后,保存您所做过的设置。

Great, we have a translation, but what happens if you develop new code and you need to update the template and catalog files? For creating the template you have to do nothing different, since a template can be created over and over from scratch. But this is not so easy with the actual catalogs, since you do not want to loose existing translations. The gettext utilities, that come with every Linux system, have a nice command line tool called msgmerge (for Windows you can just use Cygwin’s version of the gettext packages). msgemerge merges all changes of the POT file into the message catalog, keeping all comments and existing translations intact and even marking changed translations as “fuzzy”.
我们已经有了翻译功能,但当您又开发了新代码,并且需要更新模板和目录文件,遇到这种情况我们需要采取什么样的措施呢?由于模板从一开始就被创建好了,因此创建的模板您不需要有任何改动。不过对于目录文件,为了不遗漏任何存在的翻译,就需要做一些其它的工作。每个Linux系统都提供了gettext实用工具,其中有个叫msgmerge的命令行工具(在Windows下,您能使用gettext软件包Cygwin版)。msgemerge能把所有改变了的POT文件并进了message目录,保留所有的注解和已经存在的未改变的翻译,并且标识被改变的翻译用做"fuzzy"。

Here is how you can use the tool from the locales directory:

1  msgmerge -U de/LC_MESSAGES/messageboard.po ./messageboard.pot

18.7 Step VII: Compiling and Registering Message Catalogs(18.7 步骤 VII:编译和注册Message目录)

Before we can use our new translations, we need to compile the message catalogs into a more efficient binary format and then register the locales directory as a message catalog container.
在使用我们的新翻译之前,我们需要把message目录编译成一个有效的二进制文件格式,然后以message catalog container注册locales目录。

To compile the catalogs, go to the directory and type:
编译目录,命令如下:

1  msgfmt messageboard.po -o messageboard.mo

The msgfmt program is part of the gettext tools, which you must have installed (like for the msgmerge tool) to successfully execute the above command.
msgfmt 程序是 gettext 工具的一部份, 您一定曾经安装 ( 如同msgmerge工具) 过并成功运行过上述命令。

If you have troubles keeping the extensions po and mo in mind, here is a crib: The “p” of the “.po” extension stands for “people comprehensible” and the “m” in “.mo” for “machine comprehensible”.
如果您觉得记住po和mo扩展名很难,现在就教您一招:".po" 中的"p" 就如同 "people comprehensible(人能理解)" ,".mo" 中的"m" 就如同 "machine comprehensible(机器能理解)"。

To register the locales directory as a translation container, open the main configure.zcml for the message board, and register the i18n namespace as follows in the configure tag:
注册locales目录作为翻译container,打开configure.zcml文件,按如下形式注册i18n命名空间:

1  xmlns:i18n="http://namespaces.zope.org/i18n"

Now you register the directory using
现在注册目录用:

1  <i18n:registerTranslations directory="locales" />

The i18n:registerTranslations directive is smart enough to detect the directory structure and extract all the message catalogs for all the available languages.
i18n:registerTranslations 指令能发现目录结构和并且为所有的可用语言提取所有的message的目录。

An important note: During the last few steps it was quietly asserted that the filename of the message catalog must be the domain name! The registerTranslations directive uses the filename to determine the domain, which is completely in line with the gettext standard.
重要提示:在最后一些步骤期间,message目录的文件名必须声明成域名称!registerTranslations指令将使用文件名来决定域,当然这完全与gettext标准一致。

18.8 Step VIII: Trying the Translations(18.8 步骤 III:尝试翻译)

To test the translations, restart Zope 3. Different languages are best tested with Mozilla, since it allows you to quickly change the accepted languages of the browser itself. You can change the language in the preferences under Navigator --> Languages. Put German[de] at the top of the list. The best view to test is the Preview, which you can reach with a URL similar to: http://localhost:8080/board/msg/@@details.html
为了测试翻译,请重新启动Zope 3,最好在Mozilla里测试不同的语言,原因在于该浏览器允许您在浏览器里快速更改您接受的语言。具体做法就是:在语言导航参数设置里面更改语言。把German[de]放在列表的最上面。您可以通过类似下面的URL来进行测试预览: http://localhost:8080/board/msg/@@details.html

You should now see all the attribute names (such as Title, which became Titel) in German. You should also notice that the date is formatted in the German standard way using “day.month.year” and a 24-hour time.
现在您可以看看各个属性名称在德语里如何显示(例如Title已经变成了Titel)。日期格式也变成德语标准格式"天.月.年"以及以24小时格式标注的时间。


Figure 18.1: The Message Details view in German

18.9 Step IX: Updating Translations on the Fly(在运行中更新翻译)

While translating a package, it might be very cumbersome to restart Zope 3 just to update translations. For this reason, a process control called “Translation Domain Control” ( http://localhost:8080/++etc++process/@@TranslationDomain.html) was created that allows you to update message catalogs at runtime without needing to restart the server. You should see the new messageboard domain for German ( de).
当翻译软件包时,更新翻译就重启Zope 3真的很令人厌烦。就是由于这个原因,系统提供了一个叫"Translation Domain Control" ( http://localhost:8080/++etc++process/@@TranslationDomain.html ) 的工具。该工具允许您在不重新启动服务器的前提下,在运行中可以更新message目录。您应该看看用于德语的新messageboard域de。


Figure 18.2: Translation Domain Control

Exercises(练习)

  • Complete the internationalization of all of the Page Templates.
    完成所有页面模板的国际化。
  • Extract the new message strings (due to exercise 1) and merge them with the existing translations and update the English message catalog.
    就练习1提取新的message字符串,并且把他们与已经存在的翻译合并以及更新英语message目录。