I have some troubles when i use gettext for module- and class-level variables.
First of all, at import time i use my default locale and install it.
After it I get specific locale when I start my project by parsing settings and use gettext.translation.install
for set right locale. All work well, but in my code all module- and class-level variables stay translated with default locale, not right.
For example I have project like this:
├── foo.py
├── i18t
│ └── __init__.py
├── __init__.py
└── run.py
i18t/__init__.py
contains:
import gettext
from os import path
SUPPORTED_LANGUAGES = ('en', 'fr')
DEFAULT_LANGUAGE = SUPPORTED_LANGUAGES[0]
locale_path = path.abspath(path.join(path.dirname(__file__), 'locale'))
TRANSLATIONS = {
lang: gettext.translation(
'domain',
locale_path,
languages=[lang]
) for lang in SUPPORTED_LANGUAGES
}
def install_language(language):
lang = TRANSLATIONS.get(language)
if lang is None:
lang = TRANSLATIONS[DEFAULT_LANGUAGE]
lang.install()
__init__.py
:
from i18n import DEFAULT_LANGUAGE, install_language
install_language(DEFAULT_LANGUAGE)
foo.py
:
foo = _('Bar')
run.py
:
from i18t import install_language
import foo
def main():
...
read config and get right locale
...
install_language(right_locale)
bar = _('Bazz')
print(foo.foo)
print(bar)
I execute run.py
and I get translated foo.foo
with default locale and bar
with right locale.
I know that foo.foo
run _
(gettext) only once when I import module but I need to get right translated string.
Which better way to do it?
Problem of this case is desire to use run-time function gettext
for strings which evaluated only once in import-time. I think it's better not to do this.
But I resolved this problem with using string-like object like in speaklater package or inherit object UserSting and make your own gettext
function:
from collections import UserString
class RuntimeTranslatedString(UserString):
def __init__(self, message):
self._data = message
@property
def data(self):
return _(self._data)
def N_(message):
return RuntimeTranslatedString(message)
In your code you can use it like _
(gettext):
from .i18n import N_
foo = N_('Bar')
Don't forget add it to your extract_message
command. In my setup.cfg
it looks like:
[extract_messages]
output_file = my-package/i18n/locale/translation.pot
keywords = _ N_
I'm not sure that this is the good solution but it works.