Ross Wan's World!

Python, Ajax, PHP and Linux.

wxPython:国际化

Posted by Ross Wan 于 2008/04/28

Unicode

       wxPython 同时支持 unicode 和 ansi,如果要在程序里使用非英语系的语言,我们最好使用 unicode 进行编码。

       Unicode 已经成为一个行业的标准,它使得计算机可以在不同的文字系统里一致地显示和处理文本。unicode 字符编码使用16位来储存字符,而传统的 ASCII 编码则仅使用8位。

       在 Python 里,我们可以这样取得 Unicode 编码,以 Лев Николaевич Толстoй Анна Каренина 这个字符串为例子:

>>> unicode(u’Лев Николaевич Толстoй Анна Каренина’)
u’\u041b\u0435\u0432 \u041d\u0438\u043aa\u0430\u0301
\u0435\u0432\u0438\u0447\u0422\u043e\u043b\u0441o
\u0439 \u0410\u043d\u043d\u0430\u041a\u0430\u0440
\u0435\u043d\u0438\u043d\u0430′

       在 Python 命令行下,使用 unicode() 函数取得字符串的 unicode 编码。

#!/usr/bin/python

import wx

text = u’\u041b\u0435\u0432 \u041d\u0438\u043a\u043e\u043b\u0430\
\u0435\u0432\u0438\u0447 \u0422\u043e\u043b\u0441\u0442\u043e\u0439 \n\
\u0410\u043d\u043d\u0430 \u041a\u0430\u0440\u0435\u043d\u0438\u043d\u0430′

class Unicode(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(250, 150))

        self.Bind(wx.EVT_PAINT, self.OnPaint)

        self.Centre()
        self.Show(True)

    def OnPaint(self, event):
        dc = wx.PaintDC(self)
        dc.DrawText(text, 50, 50)

app = wx.App()
Unicode(None, -1, ‘Unicode’)
app.MainLoop()

Locale 模块

       一个 locale 对象定义了用户使用的语言、国家、数字格式、字母格式、货币格式等等。一个 locale 有下面的格式:

[language[_territory][.codeset][@modifier]]

       例如,de_AT.utf8 是一个在奥地利使用的德语 UTF8 字符集。

#!/usr/bin/python
# locale.py

import wx
import time
import locale

class Locale(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(250, 420))

        panel = wx.Panel(self, -1)

        tm = time.localtime()

        font = wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD)
        us = wx.StaticText(self, -1, ‘United States’, (25, 20))
        us.SetFont(font)

        wx.StaticLine(self, -1, (25, 50), (200 ,1))

        locale.setlocale(locale.LC_ALL, ”)
        date = time.strftime(‘%x’, tm)
        time_ = time.strftime(‘%X’, tm)
        curr =  locale.currency(100000)

        wx.StaticText(self, -1, ‘date: ‘, (25, 70))
        wx.StaticText(self, -1, ‘time: ‘, (25, 90))
        wx.StaticText(self, -1, ‘currency: ‘, (25, 110))

        wx.StaticText(self, -1, str(date), (125, 70))
        wx.StaticText(self, -1, str(time_), (125, 90))
        wx.StaticText(self, -1, str(curr), (125, 110))

        de = wx.StaticText(self, -1, ‘Germany’, (25, 150))
        de.SetFont(font)

        wx.StaticLine(self, -1, (25, 180), (200,1))

        locale.setlocale(locale.LC_ALL, (‘de_DE’, ‘UTF8’))
        date = time.strftime(‘%x’, tm)
        time_ = time.strftime(‘%X’, tm)
        curr =  locale.currency(100000)

        wx.StaticText(self, -1, ‘date: ‘, (25, 200))
        wx.StaticText(self, -1, ‘time: ‘, (25, 220))
        wx.StaticText(self, -1, ‘currency: ‘, (25, 240))
        wx.StaticText(self, -1, date, (125, 200))
        wx.StaticText(self, -1, time_, (125, 220))
        wx.StaticText(self, -1, curr, (125, 240))

        de = wx.StaticText(self, -1, ‘Slovakia’, (25, 280))
        de.SetFont(font)

        wx.StaticLine(self, -1, (25, 310), (200,1))

        locale.setlocale(locale.LC_ALL, (‘sk_SK’, ‘UTF8’))
        date = time.strftime(‘%x’, tm)
        time_ = time.strftime(‘%X’, tm)
        curr =  locale.currency(100000)

        wx.StaticText(self, -1, ‘date: ‘, (25, 330))
        wx.StaticText(self, -1, ‘time: ‘, (25, 350))
        wx.StaticText(self, -1, ‘currency: ‘, (25, 370))

        wx.StaticText(self, -1, str(date), (125, 330))
        wx.StaticText(self, -1, str(time_), (125, 350))
        wx.StaticText(self, -1, str(curr), (125, 370))

        self.Centre()
        self.Show(True)

app = wx.App()
Locale(None, -1, ‘Locale’)
app.MainLoop()

       我们使用 Python 内建的 local 模块来进行本地化的处理。在上面的例子中,我们分别显示美国、德国和斯洛伐克的多种数据格式。

locale.setlocale(locale.LC_ALL, (‘de_DE’, ‘UTF8’))

       我们设置了一个德国的 locale 对象,LC_ALL 是一个组合值,它包括了 LC_TIME,LC_MONETARY,LC_NUMERIC 等等。

 date = time.strftime(‘%x’, tm)
 time_ = time.strftime(‘%X’, tm)
 curr =  locale.currency(100000)

       函数使用对应的 locale 对象。

世界时(World Time)

       因为存在时区,所以世界上的时间是不尽相同的。wxPython 通过 wx.DateTime 对象来处理这个问题,它表示了一个绝对时刻。

#!/usr/bin/python

import wx
import time

class WorldTime(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(270, 280))

        self.panel = wx.Panel(self, -1)
        self.panel.SetBackgroundColour(‘#000000’)
        font = wx.Font(12, wx.FONTFAMILY_DEFAULT,
        wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, False, ‘Georgia’)

        self.dt = wx.DateTime()

        self.tokyo = wx.StaticText(self.panel, -1,
        self.dt.FormatTime() , (20, 20))
        self.tokyo.SetForegroundColour(‘#23f002’)
        self.tokyo.SetFont(font)

        self.moscow = wx.StaticText(self.panel, -1,  
        self.dt.FormatTime() , (20, 70))
        self.moscow.SetForegroundColour(‘#23f002’)
        self.moscow.SetFont(font)

        self.budapest = wx.StaticText(self.panel, -1,  
        self.dt.FormatTime() , (20, 120))
        self.budapest.SetForegroundColour(‘#23f002’)
        self.budapest.SetFont(font)

        self.london = wx.StaticText(self.panel, -1,  
        self.dt.FormatTime() , (20, 170))
        self.london.SetForegroundColour(‘#23f002’)
        self.london.SetFont(font)

        self.newyork = wx.StaticText(self.panel, -1,  
        self.dt.FormatTime() , (20, 220))
        self.newyork.SetForegroundColour(‘#23f002’)
        self.newyork.SetFont(font)

        self.OnTimer(None)

        self.timer = wx.Timer(self)
        self.timer.Start(1000)
        self.Bind(wx.EVT_TIMER, self.OnTimer)

        self.Centre()
        self.Show(True)

    def OnTimer(self, evt):
        now = self.dt.Now()
        self.tokyo.SetLabel(‘Tokyo: ‘ + str(now.Format((‘%a %T’),
        wx.DateTime.GMT_9)))
        self.moscow.SetLabel(‘Moscow: ‘ + str(now.Format((‘%a %T’),
        wx.DateTime.MSD)))
        self.budapest.SetLabel(‘Budapest: ‘ +  str(now.Format((‘%a %T’),
        wx.DateTime.CEST)))
        self.london.SetLabel(‘London: ‘ + str(now.Format((‘%a %T’),
        wx.DateTime.WEST)))
        self.newyork.SetLabel(‘New York: ‘ + str(now.Format((‘%a %T’),
        wx.DateTime.EDT)))

app = wx.App()
WorldTime(None, -1, ‘World Time’)
app.MainLoop()

       在上面的例子中,我们显示了东京、莫斯科、布达佩斯、伦敦和纽约的当前时间。

 self.dt = wx.DateTime()

       创建一个 wx.DateTime 对象。

 now = self.dt.Now()

       取得当前的绝对时间。

 self.tokyo.SetLabel(‘Tokyo: ‘ + str(now.Format((‘%a %T’), wx.DateTime.GMT_9)))

       格式化时间字符串。%a 表示使用星期的缩写格式;%T 表示使用 %H:%M:%S 格式显示时间;wx.DateTime.GMT_9 表示时区,GMT_9 是日本的时区。

排序(Sorting)

       注意,本地化的设置会影响到字符串的排序。

#!/usr/bin/python
# collate.py

import wx
import locale

ID_SORT = 1

words = [u’Sund’, u’S\xe4bel’, u’S\xfcnde’, u’Schl\xe4fe’, u’Sabotage’]

class Collate(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(300, 220))

        panel = wx.Panel(self, -1)
        hbox = wx.BoxSizer(wx.HORIZONTAL)

        self.listbox = wx.ListBox(panel, -1)
        for i in words:
            self.listbox.Append(i)
        hbox.Add(self.listbox, 1, wx.EXPAND | wx.ALL, 20)

        btnPanel = wx.Panel(panel, -1)
        vbox = wx.BoxSizer(wx.VERTICAL)
        new = wx.Button(btnPanel, ID_SORT, ‘Sort’, size=(90, 30))

        self.Bind(wx.EVT_BUTTON, self.OnSort, id=ID_SORT)

        vbox.Add((-1, 20))
        vbox.Add(new)

        btnPanel.SetSizer(vbox)
        hbox.Add(btnPanel, 0.6, wx.EXPAND | wx.RIGHT, 20)
        panel.SetSizer(hbox)

        locale.setlocale(locale.LC_COLLATE, (‘de_DE’, ‘UTF8’))

        self.Centre()
        self.Show(True)

    def OnSort(self, event):
        self.listbox.Clear()
        words.sort( lambda a,b: locale.strcoll(a, b) )
        for i in words:
            self.listbox.Append(i)

app = wx.App()
Collate(None, -1, ‘Collate’)
app.MainLoop()

       在上面的例子中,我们对5个德文单词进行排序。默认的 sort() 方法排序后得到的结果为:Sabotage, Schläfe, Sund, Säbel, Sünde。但这个结果是错误的,因为是德语里,ä 字符是排第一的。要得到正确的排序,我们必须使用 locale。

 locale.setlocale(locale.LC_COLLATE, (‘de_DE’, ‘UTF8’))

       这里,我们设置为德语。LC_COLLATE 处也可以使用 LC_COLLATE。

 words.sort( lambda a,b: locale.strcoll(a, b) )

       我们向 sort() 方法提供一个指定的比较方法,这里是一个匿名的方法。strcoll() 方法跟 sort() 方法想像,也是比较两个字符串,然后返回-1,0,1,但会根据具体的 locale 进行比较。

简单翻译(Simple translation)

       在下面的例子中,我们将会演示一个简单的翻译过程。

       我们有翻译的方式,使用 GNU gettext 或者 wxPython 的 catalogs。而两者是相互兼容。

       wxPython 有一个 wx.Locale 类,它可以简单的使用 message catalogs。如果我们想翻译一个字符串为德语,首先需要确认系统已经提供对德语的支持。下面的命令(*NIX 系统 命令)可以查看当前系统支持的语言:

$ locale -a
C
de_AT.utf8
de_BE.utf8
de_CH.utf8
de_DE.utf8
de_LU.utf8
en_AU.utf8
en_BW.utf8
en_CA.utf8
en_DK.utf8
en_GB.utf8
en_HK.utf8
en_IE.utf8
en_IN
en_NZ.utf8
en_PH.utf8
en_SG.utf8
en_US.utf8
en_ZA.utf8
en_ZW.utf8
POSIX
sk_SK.utf8

       如上所示,在我的系统里,提供了对英语、德语、斯洛伐克语的支持。utf8 表示系统使用 utf8 对字符串进行编码。

#!/usr/bin/python

import wx

class Translation(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(220, 100))

        panel = wx.Panel(self, -1)

        mylocale = wx.Locale()
        mylocale.AddCatalogLookupPathPrefix(‘.’)
        mylocale.AddCatalog(‘simple_de’)

        _ = wx.GetTranslation

        wx.StaticText(panel, -1, _(“hello”), (10, 10))
    #wx.StaticText(panel, -1, wx.GetTranslation(‘hello’), (10, 10))

        self.Centre()
        self.Show(True)

app = wx.App()
Translation(None, -1, ‘Translation’)
app.MainLoop()

       下面我们创建一个 PO 文件,这是用于翻译的文本文件。

 pygettext -o simple_de.po simple.py

       这里我们使用 pygettext 命令来创建 PO 文件。pygettext 的具体使用请查看 GNU gettext 手册

 “Content-Type: text/plain; charset=utf-8\n”

       编辑 simple_de.po 文件,指定其字符集为 utf-8。

#: simple.py:17
msgid “hello”
msgstr “Grüß Gott”

       这里,我们提供一个对 Hello 的翻译。

       最后,我们必须创建一个二进制的 message catalog。

 msgfmt –output-file simple_de.mo simple_de.po

       使用 msgfmt 命令来生成一个 mo 文件。

Advertisements

一条回应 to “wxPython:国际化”

  1. Ross Wan said

    翻译自:The wxPython tutorial

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s

 
%d 博主赞过: