基于xrced的i18n的实现

Posted by abloz on February 17, 2010

#

周海汉 /文 2010.2.17 我以前一篇文章《wxpython 使用 XRCed创建界面 》,提到如何用xrced创建界面以及它支持gettext的i18n,但并没有具体的i18n的实现。本文举例基于xrced的i18n的实现。 参考文档中有金庆的关于xrc的i18n的实现。不过,他在2007年末是完全自己实现装载xrc,那么事件,控件的绑定都需要自己实现。而 xrced自动生成的代码可以自动实现装载和绑定,我的实现是基于自动的代码之上的i18n。应该比金庆的更简单快捷。尤其是界面复杂而又经常变动时。 所以本文可以算是他的文章的一个有益补充与更新。

一、使用xrced建立一个简单框架

保存为xrci18n.xrc,如下:
200,200 hello,world EVT_TEXT_ENTER 200,200 hello

二、使用xrced生成py代码

在“generate python”对话框里,一定选上”generate gettext strings”.生成xrci18n_xrc.py。

# This file was automatically generated by pywxrc.
# -*- coding: UTF-8 -*-
import wx
import wx.xrc as xrc
__res = None
def get_resources():
    """ This function provides access to the XML resources in this module."""
    global __res
    if __res == None:
        __init_resources()
    return __res
class xrcxrcframe(wx.Frame):
#!XRCED:begin-block:xrcxrcframe.PreCreate
    def PreCreate(self, pre):
        """ This function is called during the class's initialization.

        Override it for custom setup before the window is created usually to
        set additional window styles using SetWindowStyle() and SetExtraStyle().
        """
        pass
    def i18n_install(self, localdir, languages):
        self.lang = wx.Locale()
        self.lang.Init(wx.LANGUAGE_CHINESE_SIMPLIFIED)
        self.lang.AddCatalogLookupPathPrefix(localdir)
        self.lang.AddCatalog('messages')
        gettext.install('messages', localedir=localdir, unicode=True)

#!XRCED:end-block:xrcxrcframe.PreCreate
    def __init__(self, parent):
        # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation)
        pre = wx.PreFrame()
        self.PreCreate(pre)
        get_resources().LoadOnFrame(pre, parent, "xrcframe")
        self.PostCreate(pre)
        # Define variables for the controls, bind event handlers
        self.Bind(wx.EVT_TEXT_ENTER, self.OnText_enter_xrctext, id=xrc.XRCID('xrctext'))
#!XRCED:begin-block:xrcxrcframe.OnText_enter_xrctext
    def OnText_enter_xrctext(self, evt):
        # Replace with event handler code
        print "OnText_enter_xrctext()"
#!XRCED:end-block:xrcxrcframe.OnText_enter_xrctext
# ------------------------ Resource data ----------------------
def __init_resources():
    global __res
    __res = xrc.EmptyXmlResource()
    __res.Load('xrci18n.xrc')
# ----------------------- Gettext strings ---------------------
def __gettext_strings():
    # This is a dummy function that lists all the strings that are used in
    # the XRC file in the _("a string") format to be recognized by GNU
    # gettext utilities (specificaly the xgettext utility) and the
    # mki18n.py script.  For more information see:
    # http://wiki.wxpython.org/index.cgi/Internationalization

    def _(str): pass

    _("hello,world")
    _("hello")

三、增加对i18n的支持代码

新建一个文件xrci18nfrm.py,继承自动生成的xrcxrcframe框架类,用于重载方法,事件的实现。而xrci18n_xrc.py每次修改xrc界面都会自动生成,导致你的实现可能丢失,所以要在新文件中继承并实现。

#!/bin/env python
# -*- coding: utf8 -*-
#   Author:        ablozhou
#   E-mail:        ablozhou@gmail.com
#
#   Copyright 2010 ablozhou
#   File: xrci18nfrm.py
import wx
import wx.xrc as xrc
import xrci18n_xrc
import gettext
class xrcframe(xrci18n_xrc.xrcxrcframe):
    def PreCreate(self, pre):
        pass
    def i18n_install(self, localdir, languages):
        self.lang = wx.Locale()
        self.lang.Init(wx.LANGUAGE_CHINESE_SIMPLIFIED)
        self.lang.AddCatalogLookupPathPrefix(localdir)
        self.lang.AddCatalog('messages')
        gettext.install('messages', localedir=localdir, unicode=True)

    def __init__(self, parent):
        self.i18n_install('locale',['zh_CN'])
        xrci18n_xrc.xrcxrcframe.__init__(self,parent)
    def OnText_enter_xrctext(self, evt):
        print "xrcframe OnText_enter_xrctext()"

这里增加了对i18n的支持。实现了一个函数i18n_install. 并在__init__方法中调用。 wx的i18n不是单纯的gettext就可以的。必须使用wx.Locale(). 代码中将其语言初始化为wx.LANGUAGE_CHINESE_SIMPLIFIED,即中文简体。 设置翻译语言路径,增加类别。最后使用gettext安装该语言。 此处可以再实现为配置文件,以及根据系统环境自动选择语言。

四、处理xrc资源

gettext不能直接处理xrc,只能处理自动生成的xrci18n_xrc.py。 4.1 安装gettext 其实python自带gettext处理模块,但我还是选择安装gettext和msgfmt,方便使用。 sudo agp-get install gettext ** ** 4.2 生成pot文件和mo文件

zhouhh@zhouhh-home:~$ cd xrci18n/
zhouhh@zhouhh-home:~/xrci18n$ xgettext xrci18n
xrci18n.py      xrci18n.xrc     xrci18n_xrc.py
zhouhh@zhouhh-home:~/xrci18n$ xgettext xrci18n_xrc.py
zhouhh@zhouhh-home:~/xrci18n$ ls
messages.po  xrci18n.py  xrci18n.xrc  xrci18n_xrc.py
zhouhh@zhouhh-home:~/xrci18n$ gedit messages.po
zhouhh@zhouhh-home:~/xrci18n$ msgfmt.py messages.po
msgfmt.py: command not found
zhouhh@zhouhh-home:~/xrci18n$ msgfmt messages.po
zhouhh@zhouhh-home:~/xrci18n$ ls
locale  messages.mo  messages.po  xrci18n.py  xrci18n.xrc  xrci18n_xrc.py

其中messages.po是xgettext提取出来的。如下:

# 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 , YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSIONn"
"Report-Msgid-Bugs-To: n"
"POT-Creation-Date: 2010-02-17 09:44+0800n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONEn"
"Last-Translator: FULL NAME n"
"Language-Team: LANGUAGE n"
"MIME-Version: 1.0n"
"Content-Type: text/plain; charset=CHARSETn"
"Content-Transfer-Encoding: 8bitn"
#: xrci18n_xrc.py:77
msgid "hello,world"
msgstr ""
#: xrci18n_xrc.py:78
msgid "hello"
msgstr ""

可以看到hello和hello,world两个资源。 修改后如下:

# XRC I18N file
# Copyright (C) 2010 ablo zhou
# This file is distributed under the same license as the PACKAGE package.
# ablo zhou ,2010.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSIONn"
"Report-Msgid-Bugs-To: n"
"POT-Creation-Date: 2010-02-17 08:36+0800n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONEn"
"Last-Translator: ablo zhou n"
"Language-Team: zh_CN  n"
"MIME-Version: 1.0n"
"Content-Type: text/plain; charset=UTF-8n"
"Content-Transfer-Encoding: UTF-8n"
#: xrci18n_xrc.py:78
msgid "hello,world"
msgstr "你好,世界"
#: xrci18n_xrc.py:79
msgid "hello"
msgstr "你好程序"

调用msgfmt生成mo文件: zhouhh@zhouhh-home:~/xrci18n$ msgfmt messages.po 4.3 遵循gettext格式,新建locale目录 下面有各种语言如en_US,zh_CN,每种语言下面新建LC_MESSAGES目录,下面放真正的翻译mo文件。 zhouhh@zhouhh-home:~/xrci18n$ ls locale en_US  zh_CN zhouhh@zhouhh-home:~/xrci18n$ ls locale/zh_CN LC_MESSAGES zhouhh@zhouhh-home:~/xrci18n$ ls locale/zh_CN/LC_MESSAGES/ messages.mo 再将生成的messages.mo拷贝到locale/zh_CN/LC_MESSAGES/目录下。

五、新建测试文件xrci18n.py

#!/bin/env python
# -*- coding: utf8 -*-
#   Author:        ablozhou
#   E-mail:        ablozhou@gmail.com
#
#   Copyright 2010 ablozhou
#   File:xrci18n.py
import wx
import xrci18nfrm
class XrcApp(wx.App):
    def OnInit(self):
        '''Init Xrc App.'''
        self.mainfrm = xrci18nfrm.xrcframe(parent = None)
        self.SetTopWindow(self.mainfrm)
        self.mainfrm.Show()
        return True

    def Exit(self):
        pass

def main():
    app = XrcApp()
    app.MainLoop()
if __name__ == '__main__':
    main()

继承wx.App是为了程序以后有更多的扩展。实现其OnInit和OnExit方法。

六、执行

python xrci18n.py 看到程序已经变成中文界面。由于csdn关闭传图,故不能展示效果。

七、参考:

社区讨论:http://bbs.pythonid.com/viewthread.php?tid=179 wxpython官网:http://wiki.wxpython.org/XRCAndI18N 相关ppt:http://yergler.net/talks/desktopapps_uk/ wxpython官网:http://wiki.wxpython.org/UsingXmlResources 金庆的相关文章:http://blog.csdn.net/jq0123/archive/2007/12/17/1943440.aspx