Linuxでの空き地形式の単純なpygtkプログラムのローカライズ

すぐに2番目のバージョンのpythonとgtkを予約します。



私はロシア語だけでなく、他の言語(私だけでなく必要な場合もある)で開発しているプログラムのメインフォームに碑文を作成するという予期せぬ欲求により、実装方法の検索を開始せざるを得ませんでした。 空き地フォームのローカライズに関する実用的なドキュメントを簡単に見つけることができなかったため、他の人がより幸運になるように、将来この記事を書くことにしました。



この記事にはないもの:

-プロセスでフォームを翻訳する方法。 これは見つかりませんでしたが、知りたいのですが...

-プロセスで.pyコードのテキストを翻訳する方法。

-もちろん、ビール、ブラックジャック、その他もここにはありません。



翻訳は、起動時にロケール(またはデフォルトのロケール)を指定することにより行われます。





最初に必要なのは、既製の空き地フォームです。 なぜなら 具体的には簡単なテストを行ってそれを把握しましたが、フォームは単純で、ラベル、ボタン、チェックボックスがあります。



xmlフォームコード
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd"> <!--Generated with glade3 3.4.5 on Tue Nov 13 12:44:47 2012 --> <glade-interface> <widget class="GtkWindow" id="window1"> <child> <widget class="GtkVBox" id="vbox1"> <property name="visible">True</property> <child> <widget class="GtkLabel" id="label1"> <property name="visible">True</property> <property name="label" translatable="yes">label text</property> </widget> </child> <child> <widget class="GtkButton" id="button1"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> <property name="label" translatable="yes">button text</property> <property name="response_id">0</property> </widget> <packing> <property name="position">1</property> </packing> </child> <child> <widget class="GtkCheckButton" id="checkbutton1"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="label" translatable="yes">checkbutton text</property> <property name="response_id">0</property> <property name="draw_indicator">True</property> </widget> <packing> <property name="position">2</property> </packing> </child> </widget> </child> </widget> </glade-interface>
      
      







また、このフォームを表示するpythonプログラムも必要になります(これについて書いているので)。



 #!/usr/bin/env python # -*- coding: utf-8 -*- import pygtk, gtk, gtk.glade print "hello to me" wTree = gtk.glade.XML("localize.glade", "window1") window = wTree.get_widget("window1") window.connect("delete_event", gtk.main_quit) window.show_all() gtk.main()
      
      





同時に、コンソールで言語が変更されていることを示す文字列をコンソールに出力します。



さまざまな方法でローカライズできます。 たとえば、各行/ウィジェットの処理コードを自分で記述し、何らかの制御コマンドに応じて行を更新します。 これには小さなプラスがあります-すべてのアクションはプログラムのいつでも実行できますが、残りはマイナスです。 そして、それはひどく見えて動作します。



問題は自然に発生します-正方形の車輪で車輪を再発明しないのはどうですか? すべてがすでにそこにあることがわかったので、それを使用する必要があるだけです(ほとんどの場合)。



最初に、ロケール設定をユーザーのデフォルトにリセットする必要があります(通常はLANG環境変数で定義されます)。 これは、マルチスレッドプログラムで起こりうる問題を取り除くのに役立ちます。 このようなアクションの場合、 ロケールモジュールを接続する必要があります。



  locale.setlocale(locale.LC_ALL, '')
      
      





次に、 gettextモジュールの機能を使用します(したがって、接続する必要もあります)。 彼のドキュメントを見ると、「バイナリ.moファイル」が必要なことがわかります。



.moファイルは、すべての翻訳可能なプログラム行のリストを持つファイルです。



それらを取得する方法:



最初に、グレードフォーム(ウィジェットの碑文)からすべての行を削除する必要がありますが、もちろんこれを手動で行うことは価値がありません。 これを行うには、intltoolコマンドのセットを使用します。



  intltool-extract --type=gettext/glade localize.glade
      
      





必要に応じて、追加のパラメータを人で見つけることができます。 最後の入力パラメーターは、テキストをリッピングするフォームの空き地ファイルです。 このコマンドは、localize.glade.hファイルを作成します。



  char *s = N_("label text"); char *s = N_("button text"); char *s = N_("checkbutton text");
      
      





ご覧のとおり、フォームのウィジェットのすべてのテキスト行がリストされています。



Pythonファイルには、翻訳したい行もあります。 ローカライズする必要はなく、ローカライズチームが翻訳が必要であることを理解できるようにマークするだけです。 そのため、ドキュメントでは次のように行を記述することを推奨しています。



  print _("hello to me")
      
      





つまり _()を取り込む



上記でわかるように、localize.glade.hでは、行はN_()でラップされています。 また、一種のマーカーです。



そのため、必要なすべてのテキストにマークが付けられ、1つの場所に収集する必要があります。 チームはこれを支援します:



  xgettext --language=Python --keyword=_ --keyword=N_ --output=show_form.pot show_form.py localize.glade.h
      
      





--keywordオプションは、収集時に検索するラベルをプログラムに示します。これは、2つの「_」と「N_」があるためです。 --outputは出力ファイルの名前を設定し、ラベルを検索する必要があるすべてのファイルのリストがあります(ラベルは異なる可能性があると結論付けることができますが、これは特に重要ではないので気にしませんでした)。



結果は、次の内容のファイルです。
#説明的なタイトル。

#著作権年のパッケージの著作権者

#このファイルは、PACKAGEパッケージと同じライセンスの下で配布されます。

#第一著者<EMAIL @ ADDRESS>、年。



#、ファジー





「プロジェクトIDバージョン:パッケージバージョン\ n」

「Report-Msgid-Bugs-To:\ n」

「POT-作成日:2012-11-14 13:54 + 0300 \ n」

「PO改訂日:YEAR-MO-DA HO:MI + ZONE \ n」

「最後の翻訳者:氏名<EMAIL @ ADDRESS> \ n」

「言語チーム:LANGUAGE <LL@li.org> \ n」

「言語:\ n」

「MIMEバージョン:1.0 \ n」

「Content-Type:text / plain; 文字セット= CHARSET \ n»

「コンテンツ転送エンコード:8ビット\ n」



#:show_form.py:14

msgstr「こんにちは」





#:localize.glade.h:1

msgstr "ラベルテキスト"





#:localize.glade.h:2

msgstr "ボタンテキスト"





#:localize.glade.h:3

msgstr "チェックボタンのテキスト"





これは、将来のすべての翻訳ファイルのテンプレートです。 編集する必要はありません。 今こそ言語を決める時です。 私は英語(en_US)、ロシア語(ru)、ドイツ語(de_DE)を使用しました(実際、ドイツ語では "Hitler Kaput"と "Handehokh"しかわからず、それは書かれていませんが、ヒープに置いてください)。 言語ごとに、テンプレートからローカライズされたファイルを作成する必要があります。 これはコマンドによって行われます:



  msginit --locale=ru --input=show_form.pot msginit --locale=en_US --input=show_form.pot msginit --locale=de_DE --input=show_form.pot
      
      





その結果、3つのru.po、de.po、およびen_US.poファイルが表示されます。 内部では、テンプレートとほぼ同じくらい空になっていますが、ヘッダーは満たされていますが、希望するデータではなく(キーに何かを指定しなかったかもしれません)、行を他の言語に(自然に)翻訳していません。 手で翻訳をmsgstrフィールドに変換する必要があります。 また、文字セットをutf-8に修正しました。文字サイズは16ビットおよび電子メールです。



結果は次のとおりです。

ru.po
#パッケージパッケージのロシア語翻訳。

#Copyright 2012 THE PACKAGE'S COPYRIGHT HOLDER

#このファイルは、PACKAGEパッケージと同じライセンスの下で配布されます。

#<aaa @ bbb>、2012年。







「プロジェクトIDバージョン:パッケージバージョン\ n」

「Report-Msgid-Bugs-To:\ n」

「POT-作成日:2012-11-14 13:54 + 0300 \ n」

「PO改訂日:2012-11-14 13:58 + 0300 \ n」

「最後の翻訳者:<aaa @ bbb> \ n」

「言語チーム:ロシア語\ n」

「言語:ru \ n」

「MIMEバージョン:1.0 \ n」

「Content-Type:text / plain; 文字セット= utf-8 \ n "

「コンテンツ転送エンコード:16ビット\ n」

「複数形:nplurals = 3; 複数=(n%10 == 1 && n%100!= 11?0:n%10> = 2 && n "

"%10 <= 4 &&(n%100 <10 || n%100> = 20)?1:2); \ n"



#:show_form.py:14

msgstr「こんにちは」

「こんにちは」



#:localize.glade.h:1

msgstr "ラベルテキスト"

msgstr "ラベル"



#:localize.glade.h:2

msgstr "ボタンテキスト"

msgstr "ボタン"



#:localize.glade.h:3

msgstr "チェックボタンのテキスト"

msgstrチェックマーク



de.po
(はい、ドイツ語ではありませんが、それはまったく重要ではありません):

#パッケージパッケージのドイツ語翻訳。

#Copyright 2012 THE PACKAGE'S COPYRIGHT HOLDER

#このファイルは、PACKAGEパッケージと同じライセンスの下で配布されます。

#<aaa @ bbb>、2012年。







「プロジェクトIDバージョン:パッケージバージョン\ n」

「Report-Msgid-Bugs-To:\ n」

「POT-作成日:2012-11-14 13:54 + 0300 \ n」

「PO改訂日:2012-11-14 14:14 + 0300 \ n」

「最後の翻訳者:<aaa @ bbb> \ n」

「言語チーム:ドイツ語\ n」

「言語:de \ n」

「MIMEバージョン:1.0 \ n」

「Content-Type:text / plain; 文字セット= utf-8 \ n "

「コンテンツ転送エンコード:16ビット\ n」

「複数形:nplurals = 2; 複数=(n!= 1); \ n "



#:show_form.py:14

msgstr「こんにちは」

msgstr "f"



#:localize.glade.h:1

msgstr "ラベルテキスト"

msgstr "d"



#:localize.glade.h:2

msgstr "ボタンテキスト"

msgstr "g"



#:localize.glade.h:3

msgstr "チェックボタンのテキスト"

msgstr "e"



en_US.po
#パッケージパッケージの英語翻訳。

#Copyright 2012 THE PACKAGE'S COPYRIGHT HOLDER

#このファイルは、PACKAGEパッケージと同じライセンスの下で配布されます。

#<aaa @ bbb>、2012年。







「プロジェクトIDバージョン:パッケージバージョン\ n」

「Report-Msgid-Bugs-To:\ n」

「POT-作成日:2012-11-14 13:54 + 0300 \ n」

「PO改訂日:2012-11-14 13:58 + 0300 \ n」

「最後の翻訳者:<aaa @ bbb> \ n」

「言語チーム:英語\ n」

「言語:en_US \ n」

「MIMEバージョン:1.0 \ n」

「Content-Type:text / plain; 文字セット= utf-8 \ n "

「コンテンツ転送エンコード:16ビット\ n」

「複数形:nplurals = 2; 複数=(n!= 1); \ n "



#:show_form.py:14

msgstr「こんにちは」

msgstr「こんにちは」



#:localize.glade.h:1

msgstr "ラベルテキスト"

msgstr "ラベルテキスト"



#:localize.glade.h:2

msgstr "ボタンテキスト"

msgstr "ボタンテキスト"



#:localize.glade.h:3

msgstr "チェックボタンのテキスト"

msgstr "チェックボタンのテキスト"



どうやらネイティブバージョンを作成するようです(デフォルトでen_USがあります)。 しかし、結局のところ、他の人、たとえばde_DEを持っている可能性があり、英語への翻訳を見たいと思うでしょう。 はい。gettext開発者は作成することをお勧めします。



一部のプログラマーは、intltool-mergeコマンドを使用してフォームに変更を加えることも推奨していますが、 同時に、まったく同じフォームを変更せずに作成しましたが、その必要性はわかりません。



したがって、.moファイルを作成するためのすべてがあります。 これはコマンドによって行われます:



  msgfmt ru.po -o locale/ru/LC_MESSAGES/show_form.mo msgfmt en_US.po -o locale/en_US/LC_MESSAGES/show_form.mo msgfmt de.po -o locale/de/LC_MESSAGES/show_form.mo
      
      





-oオプション(非常に明白)は、完成したファイルが配置されるディレクトリを示します。最上位ディレクトリ(ここでは「ロケール」)はすべての.moファイルで同じである必要があり、そのロケール名のディレクトリが移動することに注意してください(ru、de、en_US、de_DE、ru_RU-最後の2つには方言がないため、プログラムはそれらを最初の文字に減らしますが、フルネームを使用できます)。 Pythonプログラムで指定されたドメインと同じ方法で、「。mo」のみで呼び出す必要があります。 また、LC_MESSAGESは、内部ディレクトリの名前のいくつかの可能なバリエーションの1つです(また、同じ名前を使用することをお勧めします)。

これについては公式文書が述べています:



...

localedir / language / LC_MESSAGES / domain.mo。言語はそれぞれ環境変数LANGUAGE、LC_ALL、LC_MESSAGES、LANGで検索されます。



その結果、プログラムで既に使用できる改行付きのファイルが得られました(このような操作は、Python / gladeだけでなく実行されます)。



pythonプログラムに戻りましょう。



まず、gettextを構成します。 ロケール設定をリセットした後、翻訳ファイルを取得する場所とファイルを彼に伝える必要があります。 このために、2つの変数を導入しました。



  APP="show_form" DIR="locale"
      
      





APPがプログラムの名前と一致するという事実は、ドキュメントには残っていませんが、任意の名前が存在する可能性があると思います。 関連付けられているプログラムの名前で.moファイルを見ると、何が何であるかを理解するのがはるかに簡単になります。



APPは.moファイルの名前、DIRは言語を含む共通ディレクトリです。 この事実gettextの説明は、次の行によって生成されます。



  gettext.bindtextdomain(APP, DIR) gettext.textdomain(APP)
      
      





次に、_()の形式の行をどうするかをPythonに説明する必要があります。 これを行うには、「_」に指定されたファイルから翻訳を取得する機能が割り当てられます。 これは2つの方法で記述できます。



  lang = gettext.translation(APP, DIR) _ = lang.gettext
      
      





または



  _ = gettext.gettext
      
      





それは、モジュールコードを見ると同じことです。 したがって、より短いレコードを選択することは理にかなっています。



これで、.pyファイル内のテキストを目的の言語で表示できます。 そしてgladeフォームをローカライズするために、gtk、翻訳の入手先、そしてどれを説明する必要があります:



  gtk.glade.bindtextdomain(APP, DIR) wTree = gtk.glade.XML("localize.glade", "window1", APP)
      
      





最終コード:



 #!/usr/bin/env python # -*- coding: utf-8 -*- import pygtk, gtk, gtk.glade import locale, gettext APP="show_form" DIR="locale" locale.setlocale(locale.LC_ALL, '') gettext.bindtextdomain(APP, DIR) gettext.textdomain(APP) _ = gettext.gettext print _("hello to me") gtk.glade.bindtextdomain(APP, DIR) wTree = gtk.glade.XML("localize.glade", "window1", APP) window = wTree.get_widget("window1") window.connect("delete_event", gtk.main_quit) window.show_all() gtk.main()
      
      





打ち上げ:



 LANG=en_US.utf-8 ./show_form.py
      
      





画像



 LANG=ru_RU.utf-8 ./show_form.py
      
      





画像



 LANG=de_DE.utf-8 ./show_form.py
      
      





そして、ここでエラーが正直に飛び出します、tk。 ドイツのロケールは私に接続されていません。 したがって、ロケールを使用するには、グラフィカルシェルの設定に追加する必要があります。



それだけです



更新



ビルダーについて。 libgladeのフォームが既にある場合は、libglade-convertを使用して変換しようとするか(エラーが発生しました)、ビルダー用に新しいフォームを描画します。



コードは次のようになります。



 #!/usr/bin/env python # -*- coding: utf-8 -*- import gtk, gtk.glade import locale, gettext APP="show_form" DIR="locale" locale.setlocale(locale.LC_ALL, '') gettext.bindtextdomain(APP, DIR) gettext.textdomain(APP) _ = gettext.gettext print _("hello to me") builder = gtk.Builder() gtk.glade.bindtextdomain(APP, DIR) builder.set_translation_domain(APP) builder.add_from_file("localize.xml") window = builder.get_object("window1") window.connect("delete_event", gtk.main_quit) window.show_all() gtk.main()
      
      







また、Moonriseが正しく指摘しているように、Content-Transfer-Encodingは8ビットに設定すること(つまり、変更しないこと)が公式に推奨されています。



All Articles