使用Pyramid和Python 3进行国际化
现在Pyramid在使用Python 3时的国际化支持情况怎么样呢?
目前看起来,Pyramid用来处理国际化的两个包,lingua和babel,似乎都不支持Python 3。
有一个链接是 https://bitbucket.org/felixschwarz/babel-py3k,但是没有官方发布的版本。
至于lingua,我只找到了一些叫做lingua3k的影子信息,但到处的链接都坏了,也没有官方发布的版本。
我该如何在Python 3中使用Pyramid的国际化功能呢?
3 个回答
要按照自己的方式翻译一个Python应用程序,通常有两个主要步骤:
- 提取消息目录
- 翻译字符串
第一个步骤是由Babel和lingua来处理,第二个步骤则是用gettext(或者它的其他封装工具,比如translationstring)。
简短回答:下载Poedit来处理目录工作,使用常规的Pyramid库进行翻译。
详细回答
如果Babel和lingua对你不适用,你可以自己创建消息目录。然后,使用现有的.pot
文件,你可以为每种语言创建.po
文件。如果你使用Poedit,它可以自动将你的.po
文件编译成.mo
文件。这些文件可以仅用Python的标准库gettext来处理,而不需要其他依赖。
具体步骤是:使用Poedit创建一个消息目录(文件->新建目录
)。仔细设置所有选项。Poedit甚至可以提取字符串,可能你在这里不需要手动操作,只需查看源路径和源关键字在目录属性中。
然后你翻译所有提取的(或手动添加的)字符串。Pyramid会期待以下的目录结构:
myproject/
locale/
en/
LC_MESSAGES/
myproject.po
myproject.mo
myproject.pot
这个pot
文件就是你的目录。en
文件夹是用来翻译成英语的。对于其他语言,你可以在这里放入相应的语言代码:de
代表德语,es
代表西班牙语,等等。你可以先创建一个空的.po
文件,然后让Poedit从.pot
文件中更新。
翻译完成后,使用Pyramid的文档来了解如何处理这些文件。如果你能用其他方式提取消息,就不需要Babel。
顺便提一下:你在翻译过程中使用的所有工具都是围绕Python的gettext库构建的,所以如果遇到任何问题,你甚至可以直接使用这个库。只要你有一个有效的目录,这种方法在任何情况下都能工作。
Py3 状态更新 2013年6月28日
这是对2013年3月发布的两个答案的更新,适合任何偶然看到这个内容的人。
关于 Python 3 的 Babel 项目,目前还没有官方发布的版本。维护者在这里有一个未解决的问题:http://babel.edgewall.org/ticket/209
不过,有一群人接过了这个项目,开始在 BitBucket 上建立一个非官方的 Babel3 代码库:https://bitbucket.org/babel3_developers/babel3
Pyramid 也使用了 lingua。目前,如果你尝试使用 easy_install 或 pip 安装 lingua,会失败。原因是 xlwt 还没有被官方移植。
如果你想安装 lingua,就需要手动修补 xlwt。
安装非官方的 Babel3
现在,Python 3 的 Babel 还没有官方发布的版本。pypi 上也没有相关内容(也就是说,使用 easy_install babel/babel3 或 pip install babel/babel3 是无法正常工作的)。不过,你可以使用非官方的版本。
- 要获取非官方版本,首先你需要安装 mercurial(一个源代码管理工具)。你需要这个工具来从 BitBucket 下载源代码。Windows 用户可以在这里获取:https://www.mercurial-scm.org/。Linux/Unix 用户可以使用你们的发行版工具获取二进制文件或从源代码编译。
- 在命令提示符下,导航到你想临时存储 Babel3 源代码安装文件的目录,然后运行:hg clone https://bitbucket.org/babel3_developers/babel3(Windows 用户可能需要输入 hg.exe 的完整路径,或者确保将 hg.exe 所在的目录添加到系统路径中)
- 这会在你的本地计算机上创建一个包含 setup.py 文件的目录。进入这个新目录并执行文件:python setup.py install
安装 Lingua
Pyramid 的国际化(i18n)依赖于另一个名为 lingua 的 Python 模块。它与另一个依赖模块 xlwt 有问题。这个问题也在这里得到了非官方的修补:https://github.com/tonyroberts/xlwt
- 在这里获取修补版本的 xlwt 源代码:https://github.com/tonyroberts/xlwt(点击右下角的“下载 zip”)
- 将内容解压到临时位置
- 在结果目录内打开命令提示符
- 运行:python setup.py install
- 现在通过:pip install lingua -or- easy_install lingua 安装 lingua
我找不到关于在Python 3中使用Pyramid框架的i18n(国际化)辅助包(比如babel和lingua)当前或未来状态的任何信息。
为了应对这个问题,我做了四件事:
- 创建了一个使用Python 2.7的第二个虚拟环境。
- 添加了一个特定的国际化设置文件,叫做setup_i18n.py。
- 写了一个简单的脚本,叫做translate.py,这个脚本会被setup.py调用来进行翻译。
- 在setup.py中添加了一个入口点,指向translate脚本。
具体细节:
我在我的项目中创建了一个非常简单的Python 2.7虚拟环境,叫做env_python_2.7,并把它放在项目的根目录下。
然后在setup.py所在的目录里,我创建了另一个设置文件setup_i18n.py。这个文件只包含国际化支持所需的内容。我的setup_i18n.py文件内容如下:
from setuptools import setup, find_packages
requires = [
'Babel',
'lingua',
]
setup(name='my_project',
packages=find_packages(),
install_requires=requires,
message_extractors={'.': [
('**.py', 'lingua_python', None),
('**.pt', 'lingua_xml', None),
]},
)
接着,我创建了一个叫做translate.py的脚本,并把它放在与初始化数据库的脚本initializedb.py同一个目录下,这个目录是在你从模板创建项目时生成的。这个脚本比较通用,可以根据需要进行更具体的调整,但目前看起来是这样的:
import argparse
import subprocess
import sys
from pyramid.paster import (
get_appsettings,
setup_logging,
)
description = """\
A script to facilitate the translation of strings in the app.
"""
parser = argparse.ArgumentParser(description=description)
parser.add_argument('ini_file', help='Ini file to setup environment for this script')
parser.add_argument('-a', '--add', metavar='locale',
help='Add locale name of new language for translation (eg: en, de)')
def main(argv=sys.argv):
args = parser.parse_args()
setup_logging(args.ini_file)
settings = get_appsettings(args.ini_file)
# Python 2.7 is needed for translation strings at this time, because the
# available translation string tools are not compatible with Python 3
# at this time
python27 = settings['my_project.python27_dir'] + '/bin/python'
setup_file = settings['my_project.i18n_setup_file']
if args.add:
subprocess.call([python27, setup_file, 'init_catalog', '-l', args.add])
subprocess.call([python27, setup_file, 'extract_messages'])
subprocess.call([python27, setup_file, 'update_catalog'])
subprocess.call([python27, setup_file, 'compile_catalog'])
if __name__ == '__main__':
main()
最后,我修改了setup.py中的入口点,让它指向translate脚本。我的入口点看起来是这样的:
entry_points="""\
[paste.app_factory]
main = my_project:main
[console_scripts]
my_project_db = my_project.script.initializedb:main
my_project_translate = my_project.script.translate:main
""",
现在我可以通过运行 'python3 setup.py my_project_translate' 来进行应用的国际化处理。