一、什么是python的国际化(I18N)
有关I18N,百度上解释一大堆,个人比较喜欢这个说法。
i18n是 Internationalization 这个英文的简写,因为Internationalization这个单词去掉头尾的i和n刚好还剩下18个字符,意思是国际化。
再通俗讲就是程序的多语言:程序提供多语言功能,用户选择中文,则切换到中文界面,选择英文,则切换到英文界面,甚至是俄文、西班牙文、繁体等等。
具体到本文的python下的wxpython国际化,是指在python开发环境下,实现windows程序(基于wxpython开发)多语言功能。
很简单也很普世的需求吧,但在实现的过程中间其实遇到了很多困难,主要原因还是两个:1、百度资料太少,2、英文水平又一般。
经过几天的研究,各种google,结合wxpython下的Editra示例程序(在C:\Python27\Lib\site-packages\wx-3.0-msw\wx\tools\Editra目录下),最后总结出来一个如下的简化用法。
特别说明:本方案适合小白用户,只需要实现,不需要了解国际化的具体实现方法。
二、版本说明
三、wxpython程序代码说明
程序如下:上面是英文界面,下面是中文界面。
1、主程序 eUpdateMainFrame.py
程序很简单,全部是使用wx的配套界面工具wxFormBuilder自动生成,红色字体部分就是用来实现多语言功能的代码。
a.修改__builtin__.__dict__,引入_()函数到系统内建模块中,使_()等同于wx.GetTranslation()。
b.调用wx.locale(wx.LANGUAGE_ENGLISH),声明使用英语界面,若是要改成简体中文,则是wx.LANGUAGE_CHINESE_SIMPLIFIED
c.调用wx.locale().AddCatalogLookupPathPrefix(\'local\'),声明语言包放在程序目录下local子目录下。
d.调用wx.locale().AddCatalog(\'autoupdate\') 声明语言文件名字autoupdate,注意这个函数一定得是返回True才是调用成功。
"""Subclass of MainFrame, which is generated by wxFormBuilder.""" import wx import eupdate #把_()变成系统方法 import __builtin__ __builtin__.__dict__[\'_\'] = wx.GetTranslation # Implementing MainFrame class eUpdateMainFrame( eupdate.MainFrame ): def __init__( self, parent ): locale = None locale = wx.Locale(wx.LANGUAGE_ENGLISH) if locale.IsOk(): locale.AddCatalogLookupPathPrefix(\'locale\') ibRet = locale.AddCatalog(\'autoupdate\') eupdate.MainFrame.__init__( self, parent ) # init the programe #实例化APP,因为wxformbuilder只提供界面布局,所以需要我们自己对代码进行构架 app = wx.App() #frame的实例 frame = eUpdateMainFrame(None) frame.Show(); #wxpython的启动函数 app.MainLoop()
2、窗口布局代码 eupdate.py(用wxFormBuilder画的。)
a.注意所有需要自动翻译的文本都需要用前文定义的_()函数扩起来。
譬如:title=_(u"自动升级"), 本来写法是:title=u"自动升级"。
# -*- coding: utf-8 -*- ########################################################################### ## Python code generated with wxFormBuilder (version Jun 17 2015) ## http://www.wxformbuilder.org/ ## ## PLEASE DO "NOT" EDIT THIS FILE! ########################################################################### import wx import wx.xrc import wx.richtext ########################################################################### ## Class MainFrame ########################################################################### class MainFrame ( wx.Frame ): def __init__( self, parent ): wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = _(u"自动升级"), pos = wx.DefaultPosition, size = wx.Size( 500,300 ), style = wx.CAPTION|wx.CLOSE_BOX|wx.STAY_ON_TOP|wx.TAB_TRAVERSAL ) self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize ) self.SetForegroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNTEXT ) ) self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ) ) self.SetToolTipString( _(u"自动升级程序") ) sizer = wx.BoxSizer( wx.VERTICAL ) self.m_tip = wx.StaticText( self, wx.ID_ANY, _(u"MyLabel"), wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_LEFT ) self.m_tip.Wrap( -1 ) self.m_tip.SetForegroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_CAPTIONTEXT ) ) self.m_tip.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ) ) sizer.Add( self.m_tip, 1, wx.ALIGN_TOP|wx.ALL|wx.EXPAND, 5 ) self.m_desc = wx.richtext.RichTextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, wx.TE_AUTO_URL|wx.TE_READONLY|wx.VSCROLL|wx.HSCROLL|wx.NO_BORDER|wx.WANTS_CHARS ) sizer.Add( self.m_desc, 2, wx.ALIGN_TOP|wx.ALL|wx.EXPAND, 5 ) self.m_gauage_process = wx.Gauge( self, wx.ID_ANY, 100, wx.DefaultPosition, wx.DefaultSize, wx.GA_HORIZONTAL|wx.GA_SMOOTH ) self.m_gauage_process.SetValue( 0 ) self.m_gauage_process.SetMinSize( wx.Size( -1,25 ) ) sizer.Add( self.m_gauage_process, 0, wx.ALL|wx.EXPAND, 5 ) sizebtn = wx.BoxSizer( wx.HORIZONTAL ) sizebtn.AddSpacer( ( 0, 0), 1, wx.EXPAND, 5 ) self.m_btnok = wx.Button( self, wx.ID_ANY, _(u"升级&O"), wx.DefaultPosition, wx.DefaultSize, wx.BU_BOTTOM ) self.m_btnok.SetDefault() self.m_btnok.SetMinSize( wx.Size( -1,25 ) ) sizebtn.Add( self.m_btnok, 0, wx.ALIGN_BOTTOM|wx.ALIGN_RIGHT|wx.ALL|wx.EXPAND, 2 ) self.m_btncacel = wx.Button( self, wx.ID_ANY, _(u"取消升级&C"), wx.DefaultPosition, wx.DefaultSize, wx.BU_BOTTOM ) self.m_btncacel.SetMinSize( wx.Size( -1,25 ) ) sizebtn.Add( self.m_btncacel, 0, wx.ALIGN_BOTTOM|wx.ALIGN_RIGHT|wx.ALL|wx.EXPAND, 2 ) sizer.Add( sizebtn, 0, wx.ALL|wx.EXPAND|wx.ALIGN_RIGHT, 5 ) self.SetSizer( sizer ) self.Layout() self.Centre( wx.BOTH ) # Connect Events self.m_btncacel.Bind( wx.EVT_BUTTON, self.close ) def __del__( self ): pass # Virtual event handlers, overide them in your derived class def close( self, event ): pass
四、I18N多语言原理
1、多语言原理
前面的多语言功能代码,提到_()函数等同于wx.translation方法,其核心原理:
读取指定的语言文件,依据原始文本查找对应的翻译文本。譬如_(\'自动升级\')翻译成英文就是\'auto update\'。
2、多语言文件
语言文件主要是指三个文件:.mo文件,.po文件,.pot文件,百度上资料也很多,具体可以查看这个网址:http://shandian.biz/278.html
这里简单说明如下:
1、pot文件,原始的语言文件,提取自源代码,读取所有的_()括弧内的文本,按一定规则生成这个文件。
2、po文件,是从原始pot文件对应的翻译文件,生成这个文件需要用到一个poedit软件。
3、mo文件,是编译后的po文件,程序可以直接读取,个人理解这么设置的目的是提高加载效率。
这里说明一点,这个pot、po、mo文件是一个通用规则,不是python首创的,很多著名的开发语言都支持上述i18n解决方案。
五、python下语言文件生成方法
如前文所述,语言文件主要有三步:
1.提取文本,生成pot文件,代码如下:
python C:\Python27\Tools\i18n\pygettext.py -a -d eupdate -o eupdate.pot -p d:\python\eupdate\locale d:\python\eupdate
a、调用C:\Python27\Tools\i18n\下的pygettext.py脚本;
b、提取源码目录d:\python\eupdate中,所有的py中的_()中文本,生成pot文件。
2.使用poEdit生成po文件。
a、这里提到的外部工具poEDIT有中文版本,请自行到https://poedit.net去下载.
b、读取pot文件,翻译生成po文件,这个需要手动逐条完成 。
3.生产mo文件
python C:\Python27\Tools\i18n\msgfmt.py d:\python\eupdate\locale\en\LC_MESSAGES\eupdate.po
a、调用C:\Python27\Tools\i18n\下的msgfmt.py脚本;
b、读取步骤2生成的d:\python\eupdate\locale\en\LC_MESSAGES\eupdate.po文件,生成mo文件。
但是,但是,经过研究发现poEDIT最新版本,集成了上述三个功能,而且实测该功能支持python代码。
具体步骤请各位自行琢磨,中文菜单相对还是比较简单的。
六、语言文件目录及命名规则
前面介绍了语言文件原理,其实语言文件还有一个特定的命名、存放目录规则,下面实例说明:
#1、locale目录默认在源码目录下,名字可以自定义。
D:\python\eupdate\locale>dir /S 驱动器 D 中的卷没有标签。 卷的序列号是 36D9-CDC7
#2、en目录默认在locale下,名字有规则,与源码中配置对应。 D:\python\eupdate\locale 的目录 2016-10-03 21:00 <DIR> . 2016-10-03 21:00 <DIR> .. 2016-10-03 21:01 <DIR> en 2016-10-03 20:58 995 eupdate.pot 1 个文件 995 字节
#3、en目录下的LC_MESSAGES,名字不能改 D:\python\eupdate\locale\en 的目录 2016-10-03 21:01 <DIR> . 2016-10-03 21:01 <DIR> .. 2016-10-03 21:03 <DIR> LC_MESSAGES 0 个文件 0 字节
#4、mo、po文件必须放在LC_MESSAGES目录下,名字可以改,也需与代码配合 D:\python\eupdate\locale\en\LC_MESSAGES 的目录 2016-10-03 21:03 <DIR> . 2016-10-03 21:03 <DIR> .. 2016-10-03 21:03 832 autoupdate.mo 2016-10-03 21:03 1,136 autoupdate.po 2 个文件 1,968 字节 所列文件总数: 3 个文件 2,963 字节 8 个目录 116,639,555,584 可用字节
1、在源码目录下有locale子目录,对应代码wx.locale().AddCatalogLookupPathPrefix(\'locale\'),目录名名可以修改。
2、locale下子目录en,对应代码wx.Locale(wx.LANGUAGE_ENGLISH),目录名与语言有一个对照关系规则(附一个对照关系表)。
(\'LANGUAGE_ABKHAZIAN\', 2, u\'ab\') (\'LANGUAGE_AFAR\', 3, u\'aa\') (\'LANGUAGE_AFRIKAANS\', 4, u\'af_ZA\') (\'LANGUAGE_ALBANIAN\', 5, u\'sq_AL\') (\'LANGUAGE_AMHARIC\', 6, u\'am\') (\'LANGUAGE_ARABIC\', 7, u\'ar\') (\'LANGUAGE_ARABIC_ALGERIA\', 8, u\'ar_DZ\') (\'LANGUAGE_ARABIC_BAHRAIN\', 9, u\'ar_BH\') (\'LANGUAGE_ARABIC_EGYPT\', 10, u\'ar_EG\') (\'LANGUAGE_ARABIC_IRAQ\', 11, u\'ar_IQ\') (\'LANGUAGE_ARABIC_JORDAN\', 12, u\'ar_JO\') (\'LANGUAGE_ARABIC_KUWAIT\', 13, u\'ar_KW\') (\'LANGUAGE_ARABIC_LEBANON\', 14, u\'ar_LB\') (\'LANGUAGE_ARABIC_LIBYA\', 15, u\'ar_LY\') (\'LANGUAGE_ARABIC_MOROCCO\', 16, u\'ar_MA\') (\'LANGUAGE_ARABIC_OMAN\', 17, u\'ar_OM\') (\'LANGUAGE_ARABIC_QATAR\', 18, u\'ar_QA\') (\'LANGUAGE_ARABIC_SAUDI_ARABIA\', 19, u\'ar_SA\') (\'LANGUAGE_ARABIC_SUDAN\', 20, u\'ar_SD\') (\'LANGUAGE_ARABIC_SYRIA\', 21, u\'ar_SY\') (\'LANGUAGE_ARABIC_TUNISIA\', 22, u\'ar_TN\') (\'LANGUAGE_ARABIC_UAE\', 23, u\'ar_AE\') (\'LANGUAGE_ARABIC_YEMEN\', 24, u\'ar_YE\') (\'LANGUAGE_ARMENIAN\', 25, u\'hy\') (\'LANGUAGE_ASSAMESE\', 26, u\'as\') (\'LANGUAGE_ASTURIAN\', 27, u\'ast\') (\'LANGUAGE_AYMARA\', 28, u\'ay\') (\'LANGUAGE_AZERI\', 29, u\'az\') (\'LANGUAGE_AZERI_CYRILLIC\', 30, u\'az\') (\'LANGUAGE_AZERI_LATIN\', 31, u\'az\') (\'LANGUAGE_BASHKIR\', 32, u\'ba\') (\'LANGUAGE_BASQUE\', 33, u\'eu_ES\') (\'LANGUAGE_BELARUSIAN\', 34, u\'be_BY\') (\'LANGUAGE_BENGALI\', 35, u\'bn\') (\'LANGUAGE_BHUTANI\', 36, u\'dz\') (\'LANGUAGE_BIHARI\', 37, u\'bh\') (\'LANGUAGE_BISLAMA\', 38, u\'bi\') (\'LANGUAGE_BRETON\', 40, u\'br\') (\'LANGUAGE_BULGARIAN\', 41, u\'bg_BG\') (\'LANGUAGE_BURMESE\', 42, u\'my\') (\'LANGUAGE_CAMBODIAN\', 43, u\'km\') (\'LANGUAGE_CATALAN\', 44, u\'ca_ES\') (\'LANGUAGE_CHINESE\', 45, u\'zh_TW\') (\'LANGUAGE_CHINESE_HONGKONG\', 48, u\'zh_HK\') (\'LANGUAGE_CHINESE_MACAU\', 49, u\'zh_MO\') (\'LANGUAGE_CHINESE_SIMPLIFIED\', 46, u\'zh_CN\') (\'LANGUAGE_CHINESE_SINGAPORE\', 50, u\'zh_SG\') (\'LANGUAGE_CHINESE_TAIWAN\', 51, u\'zh_TW\') (\'LANGUAGE_CHINESE_TRADITIONAL\', 47, u\'zh_TW\') (\'LANGUAGE_CORSICAN\', 52, u\'co\') (\'LANGUAGE_CROATIAN\', 53, u\'hr_HR\') (\'LANGUAGE_CZECH\', 54, u\'cs_CZ\') (\'LANGUAGE_DANISH\', 55, u\'da_DK\') (\'LANGUAGE_DEFAULT\', 0, u\'zh_CN\') (\'LANGUAGE_DUTCH\', 56, u\'nl_NL\') (\'LANGUAGE_DUTCH_BELGIAN\', 57, u\'nl_BE\') (\'LANGUAGE_ENGLISH\', 58, u\'en_GB\') (\'LANGUAGE_ENGLISH_AUSTRALIA\', 61, u\'en_AU\') (\'LANGUAGE_ENGLISH_BELIZE\', 62, u\'en_BZ\') (\'LANGUAGE_ENGLISH_BOTSWANA\', 63, u\'en_BW\') (\'LANGUAGE_ENGLISH_CANADA\', 64, u\'en_CA\') (\'LANGUAGE_ENGLISH_CARIBBEAN\', 65, u\'en_CB\') (\'LANGUAGE_ENGLISH_DENMARK\', 66, u\'en_DK\') (\'LANGUAGE_ENGLISH_EIRE\', 67, u\'en_IE\') (\'LANGUAGE_ENGLISH_JAMAICA\', 68, u\'en_JM\') (\'LANGUAGE_ENGLISH_NEW_ZEALAND\', 69, u\'en_NZ\') (\'LANGUAGE_ENGLISH_PHILIPPINES\', 70, u\'en_PH\') (\'LANGUAGE_ENGLISH_SOUTH_AFRICA\', 71, u\'en_ZA\') (\'LANGUAGE_ENGLISH_TRINIDAD\', 72, u\'en_TT\') (\'LANGUAGE_ENGLISH_UK\', 59, u\'en_GB\') (\'LANGUAGE_ENGLISH_US\', 60, u\'en_US\') (\'LANGUAGE_ENGLISH_ZIMBABWE\', 73, u\'en_ZW\') (\'LANGUAGE_ESPERANTO\', 74, u\'eo\') (\'LANGUAGE_ESTONIAN\', 75, u\'et_EE\') (\'LANGUAGE_FAEROESE\', 76, u\'fo_FO\') (\'LANGUAGE_FARSI\', 77, u\'fa_IR\') (\'LANGUAGE_FIJI\', 78, u\'fj\') (\'LANGUAGE_FINNISH\', 79, u\'fi_FI\') (\'LANGUAGE_FRENCH\', 80, u\'fr_FR\') (\'LANGUAGE_FRENCH_BELGIAN\', 81, u\'fr_BE\') (\'LANGUAGE_FRENCH_CANADIAN\', 82, u\'fr_CA\') (\'LANGUAGE_FRENCH_LUXEMBOURG\', 83, u\'fr_LU\') (\'LANGUAGE_FRENCH_MONACO\', 84, u\'fr_MC\') (\'LANGUAGE_FRENCH_SWISS\', 85, u\'fr_CH\') (\'LANGUAGE_FRISIAN\', 86, u\'fy\') (\'LANGUAGE_GALICIAN\', 87, u\'gl_ES\') (\'LANGUAGE_GEORGIAN\', 88, u\'ka_GE\') (\'LANGUAGE_GERMAN\', 89, u\'de_DE\') (\'LANGUAGE_GERMAN_AUSTRIAN\', 90, u\'de_AT\') (\'LANGUAGE_GERMAN_BELGIUM\', 91, u\'de_BE\') (\'LANGUAGE_GERMAN_LIECHTENSTEIN\', 92, u\'de_LI\') (\'LANGUAGE_GERMAN_LUXEMBOURG\', 93, u\'de_LU\') (\'LANGUAGE_GERMAN_SWISS\', 94, u\'de_CH\') (\'LANGUAGE_GREEK\', 95, u\'el_GR\') (\'LANGUAGE_GREENLANDIC\', 96, u\'kl_GL\') (\'LANGUAGE_GUARANI\', 97, u\'gn\') (\'LANGUAGE_GUJARATI\', 98, u\'gu\') (\'LANGUAGE_HAUSA\', 99, u\'ha\') (\'LANGUAGE_HEBREW\', 100, u\'he_IL\') (\'LANGUAGE_HINDI\', 101, u\'hi_IN\') (\'LANGUAGE_HUNGARIAN\', 102, u\'hu_HU\') (\'LANGUAGE_ICELANDIC\', 103, u\'is_IS\') (\'LANGUAGE_INDONESIAN\', 104, u\'id_ID\') (\'LANGUAGE_INTERLINGUA\', 105, u\'ia\') (\'LANGUAGE_INTERLINGUE\', 106, u\'ie\') (\'LANGUAGE_INUKTITUT\', 107, u\'iu\') (\'LANGUAGE_INUPIAK\', 108, u\'ik\') (\'LANGUAGE_IRISH\', 109, u\'ga_IE\') (\'LANGUAGE_ITALIAN\', 110, u\'it_IT\') (\'LANGUAGE_ITALIAN_SWISS\', 111, u\'it_CH\') (\'LANGUAGE_JAPANESE\', 112, u\'ja_JP\') (\'LANGUAGE_JAVANESE\', 113, u\'jv\') (\'LANGUAGE_KANNADA\', 114, u\'kn\') (\'LANGUAGE_KASHMIRI\', 115, u\'ks\') (\'LANGUAGE_KASHMIRI_INDIA\', 116, u\'ks_IN\') (\'LANGUAGE_KAZAKH\', 117, u\'kk\') (\'LANGUAGE_KERNEWEK\', 118, u\'kw_GB\') (\'LANGUAGE_KINYARWANDA\', 119, u\'rw\') (\'LANGUAGE_KIRGHIZ\', 120, u\'ky\') (\'LANGUAGE_KIRUNDI\', 121, u\'rn\') (\'LANGUAGE_KONKANI\', 122, u\'\') (\'LANGUAGE_KOREAN\', 123, u\'ko_KR\') (\'LANGUAGE_KURDISH\', 124, u\'ku_TR\') (\'LANGUAGE_LAOTHIAN\', 125, u\'lo\') (\'LANGUAGE_LATIN\', 126, u\'la\') (\'LANGUAGE_LATVIAN\', 127, u\'lv_LV\') (\'LANGUAGE_LINGALA\', 128, u\'ln\') (\'LANGUAGE_LITHUANIAN\', 129, u\'lt_LT\') (\'LANGUAGE_MACEDONIAN\', 130, u\'mk_MK\') (\'LANGUAGE_MALAGASY\', 131, u\'mg\') (\'LANGUAGE_MALAY\', 132, u\'ms_MY\') (\'LANGUAGE_MALAYALAM\', 133, u\'ml\') (\'LANGUAGE_MALAY_BRUNEI_DARUSSALAM\', 134, u\'ms_BN\') (\'LANGUAGE_MALAY_MALAYSIA\', 135, u\'ms_MY\') (\'LANGUAGE_MALTESE\', 136, u\'mt_MT\') (\'LANGUAGE_MANIPURI\', 137, u\'\') (\'LANGUAGE_MAORI\', 138, u\'mi\') (\'LANGUAGE_MARATHI\', 139, u\'mr_IN\') (\'LANGUAGE_MOLDAVIAN\', 140, u\'mo\') (\'LANGUAGE_MONGOLIAN\', 141, u\'mn\') (\'LANGUAGE_NAURU\', 142, u\'na\') (\'LANGUAGE_NEPALI\', 143, u\'ne_NP\') (\'LANGUAGE_NEPALI_INDIA\', 144, u\'ne_IN\') (\'LANGUAGE_NORWEGIAN_BOKMAL\', 145, u\'nb_NO\') (\'LANGUAGE_NORWEGIAN_NYNORSK\', 146, u\'nn_NO\') (\'LANGUAGE_OCCITAN\', 147, u\'oc\') (\'LANGUAGE_ORIYA\', 148, u\'or\') (\'LANGUAGE_OROMO\', 149, u\'om\') (\'LANGUAGE_PASHTO\', 150, u\'ps\') (\'LANGUAGE_POLISH\', 151, u\'pl_PL\') (\'LANGUAGE_PORTUGUESE\', 152, u\'pt_PT\') (\'LANGUAGE_PORTUGUESE_BRAZILIAN\', 153, u\'pt_BR\') (\'LANGUAGE_PUNJABI\', 154, u\'pa\') (\'LANGUAGE_QUECHUA\', 155, u\'qu\') (\'LANGUAGE_RHAETO_ROMANCE\', 156, u\'rm\') (\'LANGUAGE_ROMANIAN\', 157, u\'ro_RO\') (\'LANGUAGE_RUSSIAN\', 158, u\'ru_RU\') (\'LANGUAGE_RUSSIAN_UKRAINE\', 159, u\'ru_UA\') (\'LANGUAGE_SAMI\', 160, u\'se_NO\') (\'LANGUAGE_SAMOAN\', 161, u\'sm\') (\'LANGUAGE_SANGHO\', 162, u\'sg\') (\'LANGUAGE_SANSKRIT\', 163, u\'sa\') (\'LANGUAGE_SCOTS_GAELIC\', 164, u\'gd\') (\'LANGUAGE_SERBIAN\', 165, u\'sr_RS\') (\'LANGUAGE_SERBIAN_CYRILLIC\', 166, u\'sr_RS\') (\'LANGUAGE_SERBIAN_LATIN\', 167, u\'sr_RS@latin\') (\'LANGUAGE_SERBO_CROATIAN\', 168, u\'sh\') (\'LANGUAGE_SESOTHO\', 169, u\'st\') (\'LANGUAGE_SETSWANA\', 170, u\'tn\') (\'LANGUAGE_SHONA\', 171, u\'sn\') (\'LANGUAGE_SINDHI\', 172, u\'sd\') (\'LANGUAGE_SINHALESE\', 173, u\'si\') (\'LANGUAGE_SISWATI\', 174, u\'ss\') (\'LANGUAGE_SLOVAK\', 175, u\'sk_SK\') (\'LANGUAGE_SLOVENIAN\', 176, u\'sl_SI\') (\'LANGUAGE_SOMALI\', 177, u\'so\') (\'LANGUAGE_SPANISH\', 178, u\'es_ES\') (\'LANGUAGE_SPANISH_ARGENTINA\', 179, u\'es_AR\') (\'LANGUAGE_SPANISH_BOLIVIA\', 180, u\'es_BO\') (\'LANGUAGE_SPANISH_CHILE\', 181, u\'es_CL\') (\'LANGUAGE_SPANISH_COLOMBIA\', 182, u\'es_CO\') (\'LANGUAGE_SPANISH_COSTA_RICA\', 183, u\'es_CR\') (\'LANGUAGE_SPANISH_DOMINICAN_REPUBLIC\', 184, u\'es_DO\') (\'LANGUAGE_SPANISH_ECUADOR\', 185, u\'es_EC\') (\'LANGUAGE_SPANISH_EL_SALVADOR\', 186, u\'es_SV\') (\'LANGUAGE_SPANISH_GUATEMALA\', 187, u\'es_GT\') (\'LANGUAGE_SPANISH_HONDURAS\', 188, u\'es_HN\') (\'LANGUAGE_SPANISH_MEXICAN\', 189, u\'es_MX\') (\'LANGUAGE_SPANISH_MODERN\', 190, u\'es_ES\') (\'LANGUAGE_SPANISH_NICARAGUA\', 191, u\'es_NI\') (\'LANGUAGE_SPANISH_PANAMA\', 192, u\'es_PA\') (\'LANGUAGE_SPANISH_PARAGUAY\', 193, u\'es_PY\') (\'LANGUAGE_SPANISH_PERU\', 194, u\'es_PE\') (\'LANGUAGE_SPANISH_PUERTO_RICO\', 195, u\'es_PR\') (\'LANGUAGE_SPANISH_URUGUAY\', 196, u\'es_UY\') (\'LANGUAGE_SPANISH_US\', 197, u\'es_US\') (\'LANGUAGE_SPANISH_VENEZUELA\', 198, u\'es_VE\') (\'LANGUAGE_SUNDANESE\', 199, u\'su\') (\'LANGUAGE_SWAHILI\', 200, u\'sw_KE\') (\'LANGUAGE_SWEDISH\', 201, u\'sv_SE\') (\'LANGUAGE_SWEDISH_FINLAND\', 202, u\'sv_FI\') (\'LANGUAGE_TAGALOG\', 203, u\'tl_PH\') (\'LANGUAGE_TAJIK\', 204, u\'tg\') (\'LANGUAGE_TAMIL\', 205, u\'ta\') (\'LANGUAGE_TATAR\', 206, u\'tt\') (\'LANGUAGE_TELUGU\', 207, u\'te\') (\'LANGUAGE_THAI\', 208, u\'th_TH\') (\'LANGUAGE_TIBETAN\', 209, u\'bo\') (\'LANGUAGE_TIGRINYA\', 210, u\'ti\') (\'LANGUAGE_TONGA\', 211, u\'to\') (\'LANGUAGE_TSONGA\', 212, u\'ts\') (\'LANGUAGE_TURKISH\', 213, u\'tr_TR\') (\'LANGUAGE_TURKMEN\', 214, u\'tk\') (\'LANGUAGE_TWI\', 215, u\'tw\') (\'LANGUAGE_UIGHUR\', 216, u\'ug\') (\'LANGUAGE_UKRAINIAN\', 217, u\'uk_UA\') (\'LANGUAGE_URDU\', 218, u\'ur\') (\'LANGUAGE_URDU_INDIA\', 219, u\'ur_IN\') (\'LANGUAGE_URDU_PAKISTAN\', 220, u\'ur_PK\') (\'LANGUAGE_UZBEK\', 221, u\'uz\') (\'LANGUAGE_UZBEK_CYRILLIC\', 222, u\'uz\') (\'LANGUAGE_UZBEK_LATIN\', 223, u\'uz\') (\'LANGUAGE_VALENCIAN\', 224, u\'ca_ES@valencia\') (\'LANGUAGE_VIETNAMESE\', 225, u\'vi_VN\') (\'LANGUAGE_VOLAPUK\', 226, u\'vo\') (\'LANGUAGE_WELSH\', 227, u\'cy\') (\'LANGUAGE_WOLOF\', 228, u\'wo\') (\'LANGUAGE_XHOSA\', 229, u\'xh\') (\'LANGUAGE_YIDDISH\', 230, u\'yi\') (\'LANGUAGE_YORUBA\', 231, u\'yo\') (\'LANGUAGE_ZHUANG\', 232, u\'za\') (\'LANGUAGE_ZULU\', 233, u\'zu\')
3、en子目录下需要有个LC_MESSAGES子目录,这个不能改。
4、LC_MESSAGES目录下存放autoupdate.mo语言文件,对照代码wx.locale().AddCatalog(\'autoupdate\'),文件名字可以修改。
其他
1、以上内容都是自己读代码琢磨以及google出来的,已经使用正常,唯一的问题:
语言文件的目录规则(譬如en与wx.LANGUAGE_ENGLISHT想对应)的具体机制,没看到实现源码(貌似被封装wx的dll里了),若有高手知情,请不吝赐教。
2、另外,i18n的机制不是python的首创,还多语言都有类似的实现,不过mo文件能否通用没试过。
3、脑洞大开,python的开发工具wing,wxpython包等等,是否也支持国际化,有待研究,不过确确实实在安装目录里看到了语言文件目录。
4、与cxfreeze的结合,可能还是会存在文件目录的问题,估计要判断frozen了。
经验证cxfreeze支持wx.locale,没问题,赞 ^_^
5、wxpython3.0.2下有个很强大的例子程序Editra,有关这个Edittra:
首先它本身是一个功能很强大的开源产品,功能有实用性(网上有编译好的版本供下载)。
其次它的源码结构性很好,用了很多wx里不太被人知道,但很强大的机制,譬如pubsub,很值得研究:
a、editra一开始会编译出错,需要修改ed_xml.py文件的import部分。
#import extern.dexml as dexml
#from extern.dexml.fields
import * import dexml as dexml
from dexml.fields import *
把extern.dexml换成dexml,至于dexml哪里来的?当然是用pip install dexml安装了。
b、editra目录下有个ed_i18n.py,这个小程序实现了两个很好的功能:
1)、GetAvailLocales()获取当前目录下已经安装的mo文件。
2)、GetLocaleDict()获取当前已安装的mo文件,对应的wx.LANGUAGE_XXX的值,这个值就是wx.locale()的参数。
c、editra实现了不基于esky的update,个人觉得可以学习。
以上内容,都是个人理解,错误之处请指正。