i18n for Kivy
Project description
i18n
Kivyアプリの多言語化は面倒くさいです。 というのも只表示する文字列を切り替えればいいわけではないからです。 Kivyは文字列の描画に必要なフォントを自動で選んでくれはしないので、アプリ側がKivyに教えてあげなければいけません。 それを怠れば画面には文字に代わって豆腐が表示されてしまいます。
また多くのKivyアプリはフォントをアプリに詰め込むという方法を採っていますが、これも多言語化の際には問題となります。 フォントを幾つも詰め込んでアプリのサイズが数十MB膨れ上がればアプリの利用者は喜ばないでしょう。
そこでこのmoduleの出番です。 このmoduleは文字列を切り替える機能に加えて、OSにinstall済のフォントの中から各言語用の物を自動で選んでくれます。 なのでアプリにフォントを詰め込む必要はもうありません。
使い方
フォントの検索
表示する文字列の切り替えとフォントの切り替えは別々の機能であり、どちらか片方だけ使うこともできます。 また多言語化には興味無いもののOSにinstall済のフォントを利用して少しでもアプリの容量を減らしたいという人も居るでしょう。 そういった人には以下のような使い方がおすすめです。
# OSにinstall済の日本語フォントの内 最初に見つけた物を利用する例
from kivy_garden.i18n.fontfinder import enum_fonts_from_lang
font = next(enum_fonts_from_lang('ja'), None)
if font is None:
print("日本語フォントが見つかりませんでした")
else:
print("日本語フォントが見つかりました:", font.name)
label.font_name = font.name
textinput.font_name = font.name
フォントの切り替え
そして多言語化させたい場合は以下のようにします。
from kivy_garden.i18n.localizer import KXLocalizer
loc = KXLocalizer()
loc.lang = 'ja'
print(loc.font_name) # => 何かの日本語フォント名が出力される
loc.lang = 'zh'
print(loc.font_name) # => 何かの中文フォント名が出力される
重要なのがKXLocalizer
がEventDispatcher
な事で
class KXLocalizer(EventDispatcher):
lang = StringProperty(...)
font_name = StringProperty(...)
_ = ObjectProperty(...)
bindingを利かせればlang
を切り替えた時にLabel
のfont_name
も自動で切り替えられます。
from kivy.app import App
from kivy.lang import Builder
from kivy_garden.i18n.localizer import KXLocalizer
KV_CODE = '''
Label:
font_name: app.loc.font_name
'''
class SampleApp(App):
def build(self):
self.loc = KXLocalizer()
return Builder.load_string(KV_CODE)
def on_start(self):
self.loc.lang = 'ja' # bindingによりLabelには自動で日本語フォントが適用される
self.loc.lang = 'ko' # bindingによりLabelには自動で韓国語フォントが適用される
またKXLocalizer.install()
を用いる事で#:import
無しでKXLocalizer
をKv言語内で直接参照できます。
ただしglobal変数を書き換える行為なので使用は自己責任で。
# 上のcodeど同等のcode
from kivy.app import App
from kivy.lang import Builder
from kivy_garden.i18n.localizer import KXLocalizer
KV_CODE = '''
Label:
font_name: l.font_name # import無しで参照 !!
'''
class SampleApp(App):
def build(self):
self.loc = KXLocalizer()
self.loc.install(name='l') # install
return Builder.load_string(KV_CODE)
def on_start(self):
self.loc.lang = 'ja'
翻訳(文字列の切り替え)
そして肝心の翻訳ですが、これはKXLocalizer
に翻訳者(Translator)を与える事で実現できます。
現在ある翻訳者は
gettext
を利用するGettextTranslator
と- 辞書を用いた単純な仕組みの
DictBasedTranslator
の二種で、ここではDictBasedTranslator
を用いた方法を解説します。
GettextTranslator
に関してはgettext_exampleを参照して下さい。
まず必要となるのは以下のような辞書型の翻訳表です。
翻訳表 = {
'tiger': {
'zh': '老虎',
'ja': '虎',
'en': 'tiger',
},
'apple': {
'zh': '蘋果',
'ja': 'りんご',
'en': 'apple',
},
}
pythonの辞書literalは書きづらいので実際にはYAML形式で翻訳表を作り、それをpythonの辞書に変換した方が良いかもしれません。
tiger:
zh: 老虎
ja: 虎
en: tiger
apple:
zh: 蘋果
ja: りんご
en: apple
# pip install pyyaml
import yaml
翻訳表 = yaml.safe_load(YAML文字列)
翻訳表ができたら後は以下のようにしてKXLocalizer
に与えるだけです。
from kivy_garden.i18n.localizer import KXLocalizer, DictBasedTranslator
loc = KXLocalizer(translator=DictBasedTranslator(翻訳表))
これで既にloc.lang
(現在の言語)に基づいて適切な翻訳結果が得られるようになっています。
loc.lang = 'ja'
print(loc._("tiger")) # => 虎
print(loc._("apple")) # => りんご
print(loc.font_name) # => 何かの日本語フォント名
loc.lang = 'zh'
print(loc._("tiger")) # => 老虎
print(loc._("apple")) # => 蘋果
print(loc.font_name) # => 何かの中文フォント名
そして当然bindingを利かせてあげればloc.lang
(現在の言語)に連動してLabel
のtext
とfont_name
が自動で更新されます。
from kivy.app import App
from kivy.lang import Builder
from kivy_garden.i18n.localizer import KXLocalizer, DictBasedTranslator
KV_CODE = '''
Label:
font_name: l.font_name
text: l._("apple")
'''
class SampleApp(App):
def build(self):
self.loc = KXLocalizer(translator=DictBasedTranslator(翻訳表))
self.loc.install(name='l')
return Builder.load_string(KV_CODE)
def on_start(self):
# Labelのfont_nameに日本語フォントが、textには りんご が入る
self.loc.lang = 'ja'
# Labelのfont_nameに英文フォントが、textには apple が入る
self.loc.lang = 'en'
このようにEventDispacther
のbindingの仕組みを利用するとアプリの実行中に表示言語を自由に切り替えられるのがこのmoduleの強みとなります。
もちろん言語切替時にアプリの再起動を求めるつもりなのであれば無理にbindingを利かせる必要はありません。
以上がこのmoduleの基本的な使い方となります。
小道具
xgettext
は翻訳の必要性のある文字列をpythonソース中から抜き出してくれる素晴らしい道具ですが、
文字列literalの中までは見てくれないという欠点があります。
すなわち以下のcodeにおいて
KV_CODE = '''
BoxLayout:
Label:
text: _("ABC")
Label:
text: _("DEF")
'''
_("123")
123
は抜き出してくれてもABC
とDEF
は抜き出してくれません。
というわけでそういったことをしてくれる物を作りました。
python -m kivy_gardem.i18n.extract_msgids_from_string_literals 上記のpythonファイル > ./output.py
# output.pyの中身
_("ABC")
_("DEF")
このように文字列literal内の翻訳対象文字列をその外に抜き出してくれるので、
それをxgettext
に喰わせてあげれば取りこぼさずに済みます。
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for kivy_garden_i18n-0.1.0-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | ec6f175f4754dae054c92ea6523528c68d4b9886a870abf834eeda6b7cf873dc |
|
MD5 | 8b3a870a8ae37ca47482b937a03f597c |
|
BLAKE2b-256 | a74ade6b13db057f994899213a5eb6b405548e73b7a5d51b4dfed23f04a4a3d2 |