[Python-ideas] Combine f-strings with i18n

Stephen J. Turnbull turnbull.stephen.fw at u.tsukuba.ac.jp
Sun Sep 16 04:35:09 EDT 2018

Hans Polak writes:

 > The second problem is that I need to translate strings on the fly.

I don't understand what that means.  gettext() does exactly that.  Do
you mean you need to switch languages on the fly?

 > I propose to add a f''.language() method to the f-string format.
 > Rationale:
 > More pythonic.

I don't think so, since as Chris points out, an f-string is an
expression whose value is a str, with the values of the locals already
interpolated in the string.  You'd need a lot of magic in the compiler
to make this work.

 > At this moment, _('').format() is the way to go, so I 
 > would need to wrap another call around that: T(_(''), args, 'es_ES') 
 > <===This is an ugly hack.
 > # Set the _() function to return the same string
 > _ = lambda s: s
 > es = gettext.translation('myapplication', languages=['es_ES'])

If, as I guessed, you want to change languages on the fly, I would
advise to make a hash table of languages used so far, and add
translation tables to it on the fly as new languages are requested.
Or, if space is at a premium, a LRU cache of tables.

 > def T(translatable_string, args_dictionary = None, language = None)
 >      if 'es_ES' == language:
 >          # Return translated, formatted string
 >          return es.gettext(translatable_string).format(args)
 >      # Default, return formatted string
 >      return translatable_string.format(args)

Then you can replace this with

    # Use duck-typing of gettext.translation objects
    class NullTranslation:
        def __init__(self):
            self.gettext = lambda s: s

    def get_gettext(language, translation={'C': NullTranslation()}):
        if language not in translation:
            translation[language] = \
                gettext.translation('myapplication', languages=[language])
        return translation[language].gettext


    # This could be one line, but I guess in many cases you're likely
    # to use use the gettext function repeatedly.  Also, use of the
    # _() idiom marks translatable string for translators.
    _ = get_gettext(language)

instead of T(translatable_string, args, language) which isn't great
style (the names "T" and "args" are not very evocative).  It's a
little more code, but it doesn't require changing the semantics of
existing Python code, and is prettier than your T() function IMO.


More information about the Python-ideas mailing list