wxPython 使用 python 自带的 gettext 构建国际化语言支持

国际化,英文为 internationalization,因英文单词太长不方便记忆,故采取 i18n 进行简写,其中18的意思为 internationalization 共20个字符,首尾字符分别为i和n,中间还有18个字符,故简称为 i18n。国际化即软件产品支持多个国家的语言、文化、使用习惯等环境,一般我们多指语言国际化,因为语言是使用者最大的障碍。

本地化,英文为 Localization,同样简称为 l10n。本地化即软件产品使用当地的环境,如语言、文化、使用习惯等.

python 自带的 gettext 模块就是为了支持国际化语言的,兼容 GUN gettext,GUN gettext 是最出名的国际化语言开源解决方案,这里对 GUN gettext  只做简介。GUN gettext 包含三种文件 .pot、.po、.mo:

    .pot 为 Portable Object Template 可移植对象模板,即语言模板文件,可以使用 GettextTools 或 Poedit 软件获得,推荐使用Poedit软件,有免费社区版,Poedit Pro 为收费版。

    .po 为 Portable Object 可移植对象,即可阅读语言翻译文件,此文件为 txt 格式,可以使用文本编辑器打开进行,文件结构这里不祥解,建议使用Poedit软件翻译

    .mo 为 Machine Object 机器对象,即机器语言文件,为二进制文件,不可使用文本编辑器编辑。

pot 文件可以被 Poedit 打开并转化为 po 文件,Poedit 翻译后保存自动生成 mo 文件,也可以通过 GettextTools 的 xgettext 获得 pot 文件(可以直接改扩展名为 po 文件)、msgfmt 编译 po 文件为 mo 文件,msgunfmt 反编译 mo 文件为 po 文件。 (注意:Poedit 也是利用 GettextTools 进行编译的 )

这里以 wxFormBuilder 创建 GUI 窗口框架,并开启国际化支持,即字符串 "xxxxxx" 使用 _("xxxxxx") 进行翻译,文件名 GUI_Frame.py 代码如下:

# -*- coding: utf-8 -*- 

###########################################################################
## Python code generated with wxFormBuilder (version Mar 23 2018)
## http://www.wxformbuilder.org/
##
## PLEASE DO *NOT* EDIT THIS FILE!
###########################################################################

import wx
import wx.xrc

## 下面两行为 wxFormBuilder 开启国际化支持自动使用 gettext 模块,对于文件中是否需要这两句,文章内有详细解释
import gettext
_ = gettext.gettext

###########################################################################
## Class MyFrame
###########################################################################

class MyFrame ( wx.Frame ):
    def __init__(self, parent):
        wx.Frame.__init__ (self, parent, id = wx.ID_ANY, title = _(u"i18n_example"),
            pos = wx.DefaultPosition, size = wx.Size( 800,460 ),
            style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL)
        self.SetSizeHints(wx.DefaultSize, wx.DefaultSize)
        self.SetBackgroundColour(wx.Colour( 239, 235, 235 ))
        self.m_menubar1 = wx.MenuBar(0)
        self.file = wx.Menu()
        self.m_menubar1.Append(self.file, _(u"File")) 
        self.about = wx.Menu()
        self.m_menubar1.Append(self.about, _(u"About")) 
        self.SetMenuBar(self.m_menubar1)
        self.Centre(wx.BOTH)
    def __del__( self ):
        pass

项目名称为 wx_i18n , 主文件为 wx_i18n.py 代码如下:

"""主文件,启用国际化支持."""

import wx
import os

## python gettext 来实现 i18n, gettext 提供两种方法:
# 实现国际化语言方法选择:1 类似 GUN gettext API,2 Python gettext 类
method = 1

"""
语言文件一般的路径一般为: localedir/language/LC_MESSAGES/domain.mo
其中:
    语言主目录: localedir - 通常设为 locale, 可自定义
    语言子目录: language 指具体语言的目录,可以有多种语言,
                语言和语言子目录有一个默认对应表,如 简体中文 为 zh_CN, 英文 为 en,见相关说明文档
    语言文件所在目录: LC_MESSAGES 无法修改,这是默认的
    语言文件: domain.mo,用户可自定义文件名,若定义了文件名,则所有的语言文件名均为此名称
"""

# ToDo: 1.类似 GUN gettext API 的一套方法
"""
此方法适用于下,程序会根据用户指定的语言或者是查询系统环境变量 LANGUAGE, LC_ALL,
LC_MESSAGES, LANG 指定的语言进行程序语言初始化.
注意:使用这种方法必须在项目的所有 .py 文件内添加 _ = gettext.gettext
"""
if method == 1:
    import gettext  # 导入模块 gettext
    lang_domain = "wx_i18n"  # 语言域, 即所有语言的语言文件均含有 wx_i18n.mo
    lang_localedir = os.path.abspath("locale")  # 指定语言主目录为 ".\\locale"
    # 将语言域 lang_domain 与 lang_localedir 语言主目录绑定
    # 这样 gettext 函数会在 lang_localedir 目录下搜索对应语言的二进制 wx_i18n.mo 文件
    gettext.bindtextdomain(lang_domain, lang_localedir)
    # 声明使用的语言域, 可以有多个语言域
    gettext.textdomain(lang_domain)
    # 使用 os.environ 设置环境变量 LANGUAGE, 也可以设置系统环境变量 LANGUAGE
    # 这里表示语言子目录, 只要语言子目录匹配到 "zh_CN" 即找到语言, 若存在多个以 zh_CN
    # 为开头的语言子目录, 则选择第一个匹配的语言。
    os.environ['LANGUAGE'] = "zh_CN"
    # 以上即指定了 语言文件为: locale/zh_CN/LC_MESSAGES/wx_i18n.mo
    # 把 _() 变成系统方法, 且关联为 gettext.gettext() 以支持多语言
    import builtins
    __builtins__.__dict__['_'] = gettext.gettext  # 翻译方法绑定, 即 _('xxxx') 的内容均会被翻译
    # 若不使用 builtins 模块把 _() 变为系统方法,则需要在每个项目文件内添加
    # import gettext
    # _ = gettext.gettext

# ToDo: 2.Python gettext 类的一套方法
"""
此方法适的每一种语言均要通过 gettext.translation() 进行设置,
使用 install() 进行安装,翻译方法 _() 函数会自动添加到 python 的内置命名空间中,
项目中其他 .py 文件不需要添加 _ = gettext.gettext,否则存在 _ = gettext.gettext 的文件
将不会被翻译为选定语言。并且最后一次安装的语言为当前生效语言。
"""
if method == 2:
    import gettext  # 导入模块 gettext

    lang_domain = "wx_i18n"  # 语言域, 即所有语言的语言文件均含有 wx_i18n.mo
    lang_localedir = os.path.abspath("locale")  # 指定语言主目录为 ".\\locale"
    # 设置 zh_CN 语言,指定语言主目录(lang_localedir)、指定使用哪种语言(zh_CN)、指定语言域(lang_domain)
    zh_CN = gettext.translation(domain=lang_domain, localedir=lang_localedir, languages=['zh_CN'])
    # 安装语言 install() 将 _() 函数添加到 python 的内置命名空间中
    zh_CN.install(True)

    # 安装 en_US 语言,指定语言主目录(lang_localedir)、指定使用哪种语言(en_US)、指定语言域(lang_domain)
    en_US = gettext.translation(lang_domain, lang_localedir, languages=['en_US'])
    en_US.install(True)
# ToDo: 无论使用哪种方法,语言的设置必须在主程序初始化之前

## GUI 窗口框架
import GUI_Frame

## 主函数
if __name__ == '__main__':
    if '_' in GUI_Frame.__dict__:
        GUI_Frame.__dict__.pop('_')  # 删除其他翻译函数, 以防冲突
    if 'app' in dir():
        del app  # 防止出现以下错误: PyNoAppError: The wx.App object must be created first!
    app = wx.App()  # 实例化 wx.App, 这是 wxPython 必要步骤
    frame = GUI_Frame.MyFrame(None)  # GUI 主框架实例
    frame.Show()  # 显示窗口
    app.MainLoop()  # wxPython 的启动函数

代码有了,就介绍一下语言文件所在位置:
语言文件一般的路径一般为: localedir/language/LC_MESSAGES/domain.mo
其中:

语言主目录: localedir - 通常设为 locale, 可自定义,与源码同目录

语言子目录: language 指具体语言的目录,可以有多种语言,语言和语言子目录有一个默认对应表,如 简体中文 为 zh_CN,英文 为 en,见相关说明文档

语言文件所在目录: LC_MESSAGES 无法修改,这是默认的

语言文件: domain.mo,用户可自定义文件名,若定义了文件名,则所有的语言文件名均为此名称
本例子下语言文件路径为:

locale
             +|  zh_CN
               .        +|  LC_MESSAGES
               .                 +|  wx_i18n.mo
               .                      wx_i18n.po
             +|  en_US
                .       +|  LC_MESSAGES
                .                +|  wx_i18n.mo
                .                     wx_i18n.po

这里分析一下 python gettext 的用法,gettext 提供两种方法:

第一种为类似 GUN gettext API 的一套方法

第二种为 python gettext 类成员的一套方法

    GUN gettext API 方法, 程序会根据用户指定的语言或者是系统环境变量 LANGUAGE, LC_ALL, LC_MESSAGES, LANG 指定的语言进行程序语言初始化.

     python gettext 提供了一套 API 和 GUN gettext 十分类似,主要常用的有如下:

              gettext .bindtextdomain(domain, localedir=None)  此函数的作用是绑定指定的语言文件主目录和语言域。参数 domain 为语言域,一种语言可以存在多个语言域,一般设置一个语言域就够用了,就如本例中 zh_CN 和 en_US 均只有一个语言域 wx_i18n。localedir 默认为 None,指的是语言文件的主目录,本例中为 .\locale 目录。

             gettext.textdomain(domain=None)  此函数的作用是选择使用哪个语言域(因为有可能存在多个语言域)。参数 domain 为语言域,本例只有一个语言域,因此只能指定 wx_i18n 这个语言域。本函数只指定了语言域但未指定具体使用那种语言

             os.environ['LANGUAGE'] = "zh_CN"  使用 os.environ 设置环境变量 LANGUAGE, 也可以设置系统环境变量 LANGUAGE,这里表示语言子目录, 只要语言子目录匹配到 "zh_CN" 即找到语言, 若存在多个以 zh_CN为开头的语言子目录, 则选择第一个匹配的语言。

              _ = gettext.gettext   翻译方法绑定, 即 _('xxxx') 的内容均会被翻译,gettext.gettext() 为默认翻译方法,但为每个字符串均加上这个方法太过于繁琐,因此简化为 _() 方法 。若要全局翻译,那么项目里所有的 .py 文件均要添加此翻译方法。

      Python gettext 类的一套方法,此方法的每一种语言均要通过 gettext.translation() 进行设置,使用 install() 进行安装,翻译方法 _() 函数会自动添加到 python 的内置命名空间中,项目中其他 .py 文件不需要添加 _ = gettext.gettext,否则选定语言在此文件内不生效。最后一次安装的语言为当前生效语言。

注意:无论使用哪种方法,语言的设置必须在主程序初始化之前!!!

实例源码:https://download.csdn.net/download/qq_26227591/12312538

      实例中,若删除 locale 文件夹,则为无语言情况,显示程序界面为:

实例中,选择多语言方式为 1(即:method = 1),语言设为中文(zh_CN),显示程序界面为:

实例中,选择多语言方式为 2(即:method = 2),语言设为美式英文(en_US),显示程序界面为:

扩展一下:

还有一种方法可以实现 wxPython 国际化多语言,即为 wxPython 自带的 wx.GetTranslation() 方法,其语言文件位置与 gettext 方式类似,以下为测试源码,需要上文实例的 语言文件和 GUI_Frame.py 文件。

# -*- coding: utf-8 -*-
import wx

# 把_()变成系统方法, 且关联为 wx.GetTranslation() 以支持多语言
import builtins
__builtins__.__dict__['_'] = wx.GetTranslation

## Implementing MyFrame
import GUI_Frame
class MyForm(GUI_Frame.MyFrame):
    def __init__(self, parent):
        GUI_Frame.MyFrame.__init__(self, parent)

## 主函数
if __name__ == '__main__':
    if '_' in GUI_Frame.__dict__:
        GUI_Frame.__dict__.pop('_')  # 删除其他翻译函数, 以防冲突
    if 'app' in dir():
        del app  # 防止出现以下错误: PyNoAppError: The wx.App object must be created first!
    app = wx.App()  # 实例化 wx.App, 这是 wxPython 必要步骤
    """" 语言文件通常为源码目录下的 localedir/language/LC_MESSAGES/domain.mo
    其中:
        语言主目录:localedir 语言所在主目录,一般设为 locale 可以自定义
        语言子目录:language 指具体语言的目录,可以有多种语言,比如 简体中文 为 zh_CN,见说明文档
        语言文件目录:LC_MESSAGES 无法修改,这是默认的
        语言文件:domain.mo,用户可自定义文件名,若定义了文件名,则所有的语言文件名均为此名称
        wx.GetTranslation() 方法必须在主程序初始化函数内切在控件初始化之前初始化语言
    """
    lang = None
    # 设置语言 wx.LANGUAGE_XXXX,同时也就指定了语言目录下选定语言的目录
    # 具体参照说明文档,此处为 简体中文 目录为 zh_CN
    lang = wx.Locale(wx.LANGUAGE_CHINESE_SIMPLIFIED)
    if lang.IsOk():
        # 设置语言主目录为源码目录下的 locale 目录,语言主目录名可以修改
        lang.AddCatalogLookupPathPrefix('locale')
        # 设置语言文件为 wx_i18n.mo,用户可自定义文件名, 返回值为 True 则语言加载成功
        ibRet = lang.AddCatalog('wx_i18n')
    frame = MyForm(None)  # GUI 主框架实例
    frame.Show()  # 显示窗口
    app.MainLoop()  # wxPython 的启动函数

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值