Author a.badger
Recipients Allie Fitter, a.badger, eric.smith
Date 2019-05-09.15:31:36
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1557415897.39.0.98978181742.issue36310@roundup.psfhosted.org>
In-reply-to
Content
Eric, I'm CC'ing you on this issue because I'm not sure if you've considered f-strings and gettext and figured out a way to make them work together.  If you have, I can look into adding support for extracting the strings to pygettext but at the moment, I'm not sure if it's a style that we want to propogate or not.

The heart of the problem is that the gettext function has to run before string interpolation occurs.  With .format() and the other formatting methods in Python, this is achievable rather naturally.  For instance:

    from gettext import gettext as _

    first = "foo"
    last = "baz"
    foo = _("{first}, bar, and {last}").format(**globals())

will lead to the string first being gettext substituted like:

    "{first}, bar, y {last}"

and then interpolated:

    "foo, bar, y baz"

However, trying to do the same with f-strings translates more like this:

    foo = _(f"{first}, bar, and {last}") 
    foo = _("{first}, bar, and {last}".format(**globals()))  # This is the equivalent of the f-string

So the interpolation happens first:

    "foo, bar, and baz"

Then, when gettext substitution is tried, it won't be able to find the string it knows to look for ("{first}, bar, and {last}")  so no translation will occur.

Allie Fitter's code corrects this ordering problem but introduces other issues.  Taking the sample string:

    foo = f'{_("{first}, bar, and {last}")}

f-string interpolation runs first, but it sees that it has to invoke the _() function so the f-string machinery itself runs gettext:

    f'{"{first}, bar, y {last}"}'

The machinery then simply returns that string so we end up with:

   '{first}, bar, y {last}'

which is not quite right but can be fixed by nesting f-strings:

    foo = f'{_(f"{first}, bar, and {last}")}

which results in:

    f'{f"{first}, bar, y {last}"}

which results in:

    f'{"foo, bar, y baz"}'

And finally:

    "foo, bar, y baz"

So, that recipe works but is that what we want to tell people to do?  It seems quite messy that we have to run the gettext function within the command and use nested f-strings so is there/should there be a different way to make this work?
History
Date User Action Args
2019-05-09 15:31:37a.badgersetrecipients: + a.badger, eric.smith, Allie Fitter
2019-05-09 15:31:37a.badgersetmessageid: <1557415897.39.0.98978181742.issue36310@roundup.psfhosted.org>
2019-05-09 15:31:37a.badgerlinkissue36310 messages
2019-05-09 15:31:36a.badgercreate