tamanegiの日記: 備忘録: wxPythonでの国際化
wxFormBuilderがpythonやxrcの国際化に対応していないような気がしていたが、気のせいだったらしい。別に問題なかった。というわけで備忘録。
まずはgettext一般のところ。クラスとか関数とかの外側で。テキストドメインはhoge、翻訳ファイル置き場はなんでもいいけど、普通にlocaleとする。この辺そんなにきちんとわかっていないけど、あまり気にしないことにする。
DIR_FILE = os.path.dirname( os.path.abspath( __file__ ) )
LOCALEDIR = os.path.join( DIR_FILE, 'locale' )
_ = gettext.translation( domain='hoge',
localedir=LOCALEDIR,
fallback=True ).ugettext
通常のpythonのコードについてはあとは普通にテキストを _("hoge") みたいにくくってやれば別に問題無い。この辺はいろんなとこに書いてあるので省略。wx, xrc関連のものについては、追加で以下のような処理が必要になる。
class MyApp( wx.App ):
def OnInit( self ):
self.i18n = self.init_i18n() # do not discard this variable
...
def init_i18n( self ):
wx.Locale.AddCatalogLookupPathPrefix( LOCALEDIR )
i18n = wx.Locale( wx.LANGUAGE_DEFAULT, flags=0 ) # use system locale
i18n.AddCatalog( "hoge" )
return i18n
self.i18nというメンバ変数をわざわざ用意するのはこいつが破棄されないようにするため。wx.Localeを作るところで、wx.LANGUAGE_DEFAULTを使うと現在のシステム設定を自動的に使ってくれる。flags=0をつけたのはwxPythonが独自に持っている(?)謎のカタログを使わないようにしてみたかっただけ。通常は必要無いと思う。他の行は大体見たまんまな気がしたので特に調べてないけど、まぁ大丈夫だろ。
んで、xrc(とpythonコード)からカタログ作る方法。まずは、pywxrc.pyでラベルとかを抜き出す。出力ファイルにはgettext的に翻訳対象になるような形で文字列入っているだけで、これ自体はカタログにはならない。ちなpywxrcのパスは自分の環境でのもの。
% python /usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/tools/pywxrc.py -g a.xrc > a.txt
んで、この抽出した何かとpythonコードから翻訳カタログのテンプレートとなるpotファイルを作る。
% pygettext -o hoge.pot source1.py source2.py a.txt
できたpotファイルからpoファイルを作り(コピーするだけ; 初めからpoだけ作ってもいいけど)、それをpoeditとかで編集する。翻訳する文字列についてはまぁ特にコメントないけど、ヘッダ部分のCHARSETとかENCODINGとかのとこはutf-8とか8bitとか意味のある文字列をいれておく。こうしておかないとこける。
ついでだけど、pythonの文字列はこんな感じに翻訳時に便利な形にしておいたほうがいいかも。
_("Unable to open file %(file) for writing") % { "file": filename }
一つだけだとあまり意味ないけど、複数の%なんとかが入る時には翻訳時に順番変更したりできて自由度あがるので、積極的にこーゆー形を使うべき。
それはさておき、編集したら、poをmoに変換する。自分はmsgfmtコマンドでやるけど、poeditの中とかで何とかできるのかも。moのファイル名は(テキストドメイン名).moにする。ここではhoge.moになる。このファイルを翻訳ファイル置き場(記事先頭を参照)におけば良い。今回の場合ではlocale/ja/LC_MESSAGES/hoge.moに設置すれば良い。
% msgfmt hoge.po -o hoge.mo
% mv hoge.mo locale/ja/LC_MESSAGES/
あとは普通に起動して翻訳がきちんと反映されているか確認すればいいとおも。微妙な注意点として、翻訳すると、MenuBar.FindMenuみたいにラベル名でオブジェクト検索するやつはちょっと特殊な扱いをしてあげないといけない。
例えば、
edit = menubar.GetMenu( menubar.FindMenu( "&Edit" ) )
みたいのは、
search_string = self.i18n.GetString( "&Edit" )
edit = menubar.GetMenu( menubar.FindMenu( search_string ) )
みたいにする必要がある。
参考:
http://wiki.wxpython.org/XRCAndI18N
http://d.hatena.ne.jp/fgshun/20100319/1269004530
備忘録: wxPythonでの国際化 More ログイン