can we use new string formatting using .format() method?

Issue #99 open
Thomas Waldmann
repo owner created an issue

moin stil uses "%s %d" % (foo, bar) style string formatting.

some work has already been done on replacing this with .format() new style formatting, but it is not completed yet.

especially, a lot of translatable strings still use old %-style.

maybe this is related to the _() method there, this should be checked (and whether we can / should use .format() there.

this needs to be done before doing translations, because change of original english strings would make the translated string invalid.

if we decide on using some other formatting method than now, the respective refactoring should be done globally in the source.

Comments (7)

  1. Julian Brost

    If you look at the gettext implementation of flask-babel, you can see that it just formats the translated string using the % syntax, nothing fancy there.

    Without patching flask-babel, it would be possible to do something like

    _('Good morning, {}!').format('Joe')
    

    but of course it would be much nicer if one could do the same thing like this:

    _('Good morning, {}!', 'Joe')
    

    I don't know if there's a specific reason for this or if it is just out of habit.

    [1] https://github.com/mitsuhiko/flask-babel/blob/master/flaskext/babel.py#L447

  2. Arne Klein

    It seems that a decision has to be made on how to proceed with the gettext translations. I am aware of the following four possibilities:

    1. Use the current recommended flask-babel syntax, which uses formatting with %

      Example:

      _(u'Hello %(name)s!', name='World')

    2. Ask the flask-babel project again (possibly with more explanation, https://github.com/mitsuhiko/flask-babel/issues/16) to provide alternative gettext functions which use .format syntax. This only concerns the functions gettext, ngettext, pgettext and npgettext and in total 8 lines of code.

      Example:

      _(u'Hello {name}!', name='World')

      _(u'Hello {name!s}!', name='World') # calls str() on the argument before replacement

    3. Use the same syntax as in 2., but implement/overwrite the four gettext functions in our code.

    4. Use the current flask-babel gettext functions, applying .format manually.

      Example:

      _(u'Hello {name!s}!').format(name='World')

  3. RogerHaase

    Given the choice between the status quo and a working .format alternative:

    {% set title = _("Modifying '%(item_name)s'", item_name=fqname.value) %}
    {% set title = _("Modifying '{item_name}'").format(item_name=fqname.value) %}
    

    ... and a non-working alternative:

    {% set title = _("Modifying '{item_name}'", item_name=fqname.value) %}
    

    ... then of course, we prefer the non-working alternative because there are fewer characters to type and the syntax is most similar to the status quo. So our choice of the above options is 2, ask the flask-babel project again.

    As to the urgency of this issue, way back in 2009 Guido said %-formatting would not go away before Python 4: https://mail.python.org/pipermail/python-dev/2009-September/092399.html

    Regarding the need to decide and complete this before the mass translations begins, there are already 3 languages and within each messages.po file there are ~200 effected strings. Rather then manually rekeying all of these, there is already probably a time savings to be had by writing a script to change lines similar to:

    msgid "Modifying '%(item_name)s'"
    msgstr "'%(item_name)s' bearbeiten"
    

    to:

    msgid "Modifying '{item_name}'"
    msgstr "'{item_name}' bearbeiten"
    

    Adding the creation of such a script to this task means the decision and completion can be delayed until after translations are complete (or even while translations are in progress given some extra coordination). For testing that the conversion of xxx.html templates inludes all effected lines, the same script could be run against a copy of MoinMoin.pot and compared a newly generated version.

  4. Log in to comment