您的位置:首页 > 编程语言 > Python开发

Python实例浅谈之十国际化支持

2015-10-08 23:55 603 查看


一、简介

        Python通过gettext模块支持国际化(i18n),可以实现程序的多语言界面的支持。


二、详解

1、Linux下Python的国际化编程

       在Linux的操作和C语言的国际化过程是一样的,在需要国际化的字符串前面添加_()即可。

(1)代码:internation.py

第一种:程序中进行实时切换语言,同时输出中文和英文(此处使用第一种方法)

# -*- coding: utf-8 -*-
#!/usr/bin/env python

import gettext
locale_path = './locale/'
#gettext.install('internation', locale_path) # 这条语句会将_()函数自动放到python的内置命名空间中
zh_trans = gettext.translation('internation', locale_path, languages=['zh_CN'])
en_trans = gettext.translation('internation', locale_path, languages=['en_US'])

print "----中文版本----"
zh_trans.install()
print _("Hello world!")
print _("Python is a good Language.")

print "----英文版本----"
en_trans.install()
print _("Hello world!")
print _("Python is a good Language.")
第二种:根据用户系统的语言配置(系统的环境变量LANGUAGE, LC_ALL, LC_MESSAGES,
LANG),自动选择语言。

       使用#echo $LANG或#locale查看当前系统语言环境,使用#export LANG="en_US"或#export LANG="zh_CN"设置本shell的语言环境。
# -*- coding: utf-8 -*-
import gettext
locale_path = './locale/'
# 将域APP_NAME与LOCALE_PATH目录绑定,
# 这样gettext函数会在LOCALE_PATH目录下搜索对应语言的二进制APP_NAME.mo文件
gettext.bindtextdomain('internation', locale_path)
# 声明使用现在的域,可以使用多个域,便可以为同一种语言提供多套翻译,
# 本程序只使用了一个域
gettext.textdomain('internation')
_ = gettext.gettext

print _("Hello world!")
print _("Python is a good Language.")
(2)生成po文件
xgettext -k_ -o internation.po_en internation.py
xgettext -k_ -o internation.po_zh internation.py
(3)翻译(charset设定为utf-8)

英文:
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-10-08 22:06+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\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"

#: internation.py:11 internation.py:16
msgid "Hello world!"
msgstr "translate:Hello world"

#: internation.py:12 internation.py:17
msgid "Python is a good Language."
msgstr "translate:python is a good Language."
中文:
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-10-08 22:06+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\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"

#: internation.py:11 internation.py:16
msgid "Hello world!"
msgstr "您好!"

#: internation.py:12 internation.py:17
msgid "Python is a good Language."
msgstr "Python是一种好语言。"
 (4)建立翻译文件路径
在主文件目录下建立英文翻译路径./locale/en_US/LC_MESSAGES/和中文翻译路径./locale/zh_CN/LC_MESSAGES/ (对文件层次比较严格)。
(5)生成mo最终文件
msgfmt -o ./locale/en_US/LC_MESSAGES/internation.mo internation.po_en
msgfmt -o ./locale/zh_CN/LC_MESSAGES/internation.mo internation.po_zh
(6)运行



2、Window下Python的国际化编程(未测试)

(1)在python安装目录下的./Tools/i18n/(windows下例 D:\Program Files\Python25\Tools\i18n)目录中找到pygettext.py运行,生
成翻译文件模版messages.pot,部分内容修改为charset=gb2312 Content-Transfer-Encoding: utf8,文件改名为lang.po,如下:

# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2007-01-18 09:55+China Standard Time\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=gb2312\n"
"Content-Transfer-Encoding: utf8\n"
"Generated-By: pygettext.py 1.5\n"
(2)建立翻译文件路径,在主文件目录下建立中文翻译路径.D:\python-prj\src\locale\cn\LC_MESSAGES(其中src目录是源文件主目录),英文翻译路径D:\python-prj\src\locale\en\LC_MESSAGES(其中src目录是源文件主目录)。
(3)在主文件中引入gettext模块

# -*- coding: utf-8 -*-
#!/usr/bin/env python
import gettext
gettext.install('lang', './locale', unicode=False)
gettext.translation('lang', './locale', languages=['cn']).install(True)
第四行中lang是翻译文件主名, ./locale是存放翻译文件的路径,第三个参数是是否使用unicode,第五行languages参数指定要使用的语言存放的子目录,这里cn表示使用./locale/cn/LC_MESSAGES/路径下的翻译文件。

注意: # -*- coding: utf-8 -*- 一定要写在前两行,写第三行都不会生效

(4)处理要翻译的字符串:
print _("Hello world!")
print _("Python is a good Language.")
(5)编写并生成翻译文件,打开上述编辑过的lang.po文件添加翻译文字,形成如下内容:

(也可以直接使用命令:python pygettext.py -a -v -d lang -o lang.po *.py ,然后翻译)

b5.         编写并生成翻译文件,打开步骤1中编辑过的lang.po文件添加翻译文字,形成如下内容:
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2007-01-18 09:55+China Standard Time\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=gb2312\n"
"Content-Transfer-Encoding: utf8\n"
"Generated-By: pygettext.py 1.5\n"

msgid " Hello world!"
msgstr "世界你好!"

msgid " Python is a good Language."
msgstr "Python 是门好语言."
     将lang.po文件拷贝到./Tools/i18n/目录下,运行命令行窗口,到改目录下键入:msgfmt.py
lang.po,生成ang.mo,将该文件拷贝至./locale/cn/LC_MESSAGES/目录下,将步骤1生成的lang.po文件直接生成lang.mo文件拷贝到./locale/en/LC_MESSAGES/目录下,运行程序,看看两个print命令是不是输出了世界你好!
Python 是门好语言.,如果将主文件第五行languages参数置为en,则输出是Hello
world! Python is a good Language.,因为en目录下lang.mo文件未做任何的翻译,默认字符串不被替换.
      上述实现的方法用在界面编程上可以实现中英文界面的切换,需要作个配置文件选择中/英文;或者在主文件开始时先获取操作系统本地语言然后根据获取结果再设置中/英文,这样就可以实现软件语言自适应;如果想实现软件语言在线切换,对于python来说就比较困难了,需要在软件中加入界面刷新机制(不推荐),可以在切换中/英文设置后软件下一次启动生效(软件如Ulipad)。

3、Window下的其他参考

      python中对于国际化的字符串,只需要外加_()即可。如: print(_('hello world')),然后根据user选择的语言,创建translation对象,然后调用install方法install_()函数到Python’s builtins namespace。如:

import gettext
en_trans = gettext.install('messages', locale='i18n_path', languages=['default_language'])
zh_trans = gettext.install('messages', locale'i18n_path', languages=['zh_CH'])
print(_('hello world'))
zh_trans.install()
print(_('hello world'))

       而对于web服务中前端页面的国际化支持也非常简单,和python source文档中一样,在需要国际化的字符串前面添加_()即可。然后在render函数中,把当前translation对象传入模板即可。如Tornado render_string的实现:
def render_string(self, template_name, **kwargs):
# If no template_path is specified, use the path of the calling file
... ...
args = dict(
handler=self,
request=self.request,
current_user=self.current_user,
locale=self.locale,
_=self.locale.translate,
static_url=self.static_url,
xsrf_form_html=self.xsrf_form_html,
reverse_url=self.application.reverse_url
)
args.update(self.ui)
args.update(kwargs)
return t.generate(**args)


好了,上面搭建好i18n所需要的环境,下面就是准备对语言字符资源了。
python 工具: pygettext msgfmt,其他工具: msgmerge

1. 创建po文档
在当前目录下创建locale文件夹,下面分别建en_US/LC_MESSAGES/ 和 zh_CN/LC_MESSAGES/目录。
在locale下面创建名为 demo.html的文件内容如下:
<html>
<head>
<title>${_('title')}</title>
</head>
<body>
<a href=''>${_('body')}</a>
</body>
</html>
        然后打开命令行窗口,输入 python pygettext.py -a -v -d messages -o messages.po \*.py \*.html,完成后,在当前目录生成 messages.po 文件,其中的格式内容:

# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\\n"
"POT-Creation-Date: %(time)s\\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\\n"
"Language-Team: LANGUAGE <LL@li.org>\\n"
"MIME-Version: 1.0\\n"
"Content-Type: text/plain; charset=CHARSET\\n"
"Content-Transfer-Encoding: ENCODING\\n"
"Generated-By: pygettext.py %(version)s\\n"

#: demo.html:3
msgid "title"
msgstr ""

#: demo.html:6
msgid "body"
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。
>>> import gettext
>>> en_trans = gettext.translation('messages', 'e:/python/locale', languages=['en_US'])
>>> zh_trans = gettext.translation('messages', 'e:/python/locale', languages=['zh_CN'])
>>> en_trans.gettext('title'), en_trans.gettext('body')
('title', 'body')
>>> zh_trans.gettext('title'), zh_trans.gettext('body')
('HTML Head 头', 'HTML Body 测试')
>>> en_trans.install()
>>> _('title'), _('body'), _('hello')
('title', 'body', 'hello')
>>> zh_trans.install()
>>> _('title'), _('body'), _('hello')
('HTML Head 头', 'HTML Body 测试', 'hello')
上例使用的python解析器是python3.2.2 2.*版本有些method参数稍有不同,请注意!


三、总结

(1)国际化的过程还需要细节的完善,widows下还需要调整使用。

(2)可参考:https://docs.python.org/2/library/gettext.htmlhttp://underthehood.blog.51cto.com/2531780/1663604

(3)若有不足,请留言,在此先感谢!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  python 国际化