Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[gettext] How to change language at run-time

1,496 views
Skip to first unread message

pozz

unread,
Jun 15, 2017, 7:32:30 AM6/15/17
to
I know I can load multiple gettext.translation:

it = gettext.translation('test', localedir="locale", languages=["it"])
es = gettext.translation('test', localedir="locale", languages=["es"])

and install one translation at run-time when I want at a later time
(when the user selects a new language):

it.install()
or
es.install()


However the problem is that strings already translated are not
translated again when a new translation is installed. So they stay at
the language selected during start-up and don't change after a new
install().

One solution is to restart the application, but I think there's a better
and more elegant solution.

Peter Otten

unread,
Jun 15, 2017, 9:23:06 AM6/15/17
to
You need a way to defer the translation until the string is actually used.
The documentation has a few ideas

https://docs.python.org/dev/library/gettext.html#deferred-translations

and here's another one -- perform the translation in the __str__ method of
a custom class:

import gettext

class DeferredTranslation:
def __init__(self, message):
self.message = message
def __str__(self):
translate = _
if translate is DeferredTranslation:
return self.message
return translate(self.message)
@classmethod
def install(class_):
import builtins
builtins._ = class_

DeferredTranslation.install()

message = _("Hello, world!")
print(message)

it = gettext.translation("test", localedir="locale", languages=["it"])
es = gettext.translation("test", localedir="locale", languages=["es"])

for language in [it, es]:
language.install()
print(message)


pozz

unread,
Jun 15, 2017, 11:58:51 AM6/15/17
to
Il 15/06/2017 15:22, Peter Otten ha scritto:
> pozz wrote:
>
>> I know I can load multiple gettext.translation:
>>
>> it = gettext.translation('test', localedir="locale", languages=["it"])
>> es = gettext.translation('test', localedir="locale", languages=["es"])
>>
>> and install one translation at run-time when I want at a later time
>> (when the user selects a new language):
>>
>> it.install()
>> or
>> es.install()
>>
>>
>> However the problem is that strings already translated are not
>> translated again when a new translation is installed. So they stay at
>> the language selected during start-up and don't change after a new
>> install().
>>
>> One solution is to restart the application, but I think there's a better
>> and more elegant solution.
>
> You need a way to defer the translation until the string is actually used.
> The documentation has a few ideas
>
> https://docs.python.org/dev/library/gettext.html#deferred-translations
>
> and here's another one -- perform the translation in the __str__ method of
> a custom class:
> [...]


It's a nice trick. However you will have a string that isn't a string,
but a class. I think you can't use the class everywhere you can use a
string. For example, len() can't be called.

Peter Otten

unread,
Jun 15, 2017, 12:41:24 PM6/15/17
to
len() could be implemented as

class DeferredTranslation:
...
def __len__(self):
return len(str(self))

and usually I would expect that you only need a small subset of the str
methods for localized text. However, when you switch languages between the
len() and str() calls you will certainly make a mess...

dieter

unread,
Jun 16, 2017, 2:23:28 AM6/16/17
to
pozz <pozz...@gmail.com> writes:
> I know I can load multiple gettext.translation:
>
> it = gettext.translation('test', localedir="locale", languages=["it"])
> es = gettext.translation('test', localedir="locale", languages=["es"])
>
> and install one translation at run-time when I want at a later time
> (when the user selects a new language):
>
> it.install()
> or
> es.install()
>
>
> However the problem is that strings already translated are not
> translated again when a new translation is installed. So they stay at
> the language selected during start-up and don't change after a new
> install().

I know the internationalization/localisation of the web application framework
"Zope". There, it is completely natural, that the individual request
determines the target language.

This is handled as follows: things to be localized are represented
by so called "message_id"s. They behave somehow as unicode objects, but,
of course, they are more complex; especially, they may encapsulate parameters
to be incorparated in the translation.
When a "message_id" is localized, the target language is taken from
the context (i.e. the current request). It returns a unicode string
but does not change the "message_id".

0 new messages