Localizer

This module plays a key role in multilingual localization, and helps you dynamically switch fonts and texts according to its “current language”.

Usage

There are two types of text sources you can use by default. One is .mo files generated by the gettext toolset. The other one is a collections.abc.Mapping object like this:

table = {
    'greeting': {
        'ja': 'おはよう',
        'en': 'morning',
    },
    'app title': {
        'ja': '初めてのKivyプログラム',
        'en': 'My First Kivy App,
    },
}

The first step is to create a TranslatorFactory instance from your source.

from kivy_garden.i18n.localizer import GettextBasedTranslatorFactory, MappingBasedTranslatorFactory

# gettext
factory = GettextBasedTranslatorFactory(domain, localedir)

# mapping
factory = MappingBasedTranslatorFactory(table)

(domain and localedir are passed to gettext.translation()).

Next, create a Localizer instance.

from kivy_garden.i18n.localizer import Localizer

loc = Localizer(translator_factory=factory)

And you’re done. You can now ask it “What’s the translation of this word?” or “Which font is suitable for your current language?”

loc.lang = 'en'  # set the "current language" to 'en'
print(loc.font_name)  # => Roboto
print(loc._("greeting"))  # => morning
print(loc._("app title"))  # => My First Kivy App

loc.lang = 'ja'
print(loc.font_name)  # => some Japanese font
print(loc._("greeting"))  # => おはよう
print(loc._("app title"))  # => 初めてのKivyプログラム

Not only that, since the loc is an kivy.event.EventDispatcher, and both loc.font_name and loc._ are Kivy properties, you can take an advantage of its binding feature.

# Assuming you assigned the 'loc' to 'app.loc'
Label:
    font_name: app.loc.font_name
    text: app.loc._("greeting")

When loc.lang changes, loc._ and loc.font_name will also change, which causes the app.loc.font_name and app.loc._("greeting") above to be re-evaluated. Great! You have successfully created a label that dynamically changes its text and font_name as the loc.lang changes.

By the way, app is a global variable. If you don’t hesitate to use that kind, there is a better way.

Localizer.install(*, name)

Makes the localizer accessble from kv without any import-statements.

loc = Localizer(...)
loc.install(name='l')
Label:
    font_name: l.font_name
    text: l._("msgid")
Raises:

I18nError – if the name has already been used.

Advanced Usage

If you want to use other types of text sources, you’ll need to create your own TranslatorFactory. And if you want to customize the way the Localizer picks fonts, you’ll need to create your own FontPicker.

Localizer.__init__(*, lang: Lang = 'en', translator_factory: TranslatorFactory = None, font_picker: FontPicker = None)
  • TranslatorFactory must be a callable that takes a string representing a language, and returns a Translator.

  • Translator must be a callable that takes a msgid, and returns a msgstr. If you’ve ever used gettext, you may already know what msgid and msgstr are.

  • FontPicker must be a callable that takes a string representing a language, and returns a Font.

  • Font must be either a path to a font file or a name registered using kivy.core.text.LabelBase.register() e.g. Roboto.

They are defined as follows:

Msgid: TypeAlias = str
Msgstr: TypeAlias = str
Lang: TypeAlias = str
Translator: TypeAlias = Callable[[Msgid], Msgstr]
TranslatorFactory : TypeAlias = Callable[[Lang], Translator]
Font: TypeAlias = str
FontPicker: TypeAlias = Callable[[Lang], Font]

You can use any object as long as it satisfies the above constraints.