bugGNU gettext - Bugs: bug #61596, Support for Python f-strings


You are not allowed to post comments on this tracker with your current authentication level.

bug #61596: Support for Python f-strings

Submitter:  Ben <qtclyinh>
Submitted:  Wed 01 Dec 2021 04:02:14 PM UTC
Category:  Python Severity:  3 - Normal
Item Group:  None Status:  Fixed
Privacy:  Public Assigned to:  haible
Open/Closed:  Closed

Jump to the original submission

Tue 05 Dec 2023 01:41:56 PM UTC, comment #8: 
Bruno Haible <haible>
Group administrator
Mon 06 Nov 2023 10:17:41 PM UTC, comment #7: 

comment #6:

> IOW, this will never work, for the reasons @habile outlined:

Apologies, that should've said @haible.

Frank Dana <ferdnyc>
Mon 06 Nov 2023 10:12:51 PM UTC, comment #6: 

comment #5:

> I suppose we shouldn't use f-strings in our code in the meanwhile, as long as we want to internationalize the strings

Well, you shouldn't attempt to translate f-strings, or (currently) to translate inside f-strings. Using f-strings themselves is fine.

IOW, this will never work, for the reasons @habile outlined:

intro = "Translatable string"
outro = "about something"
message = _(f"{intro} {outro}")

This doesn't currently work, because the `msgfmt` tool doesn't capture the two strings when collecting translatable inputs. Fixing that behavior is what this bug is about:

message = f'{_("Translatable string")} {_("about something")}'

But, this equivalent form will work just fine:

intro = _("Translatable string")
outro = _("about something")
message = f'{intro} {outro}'

(Obviously, you should never break a single translatable sentence into multiple pieces like this. It's merely an example.)

Frank Dana <ferdnyc>
Mon 04 Sep 2023 03:04:31 PM UTC, comment #5: 

I'm facing the same problem with i18n inside f-strings. Is there any news about this?
I don't understand code issues well, but it seems possible.

I suppose we shouldn't use f-strings in our code in the meanwhile, as long as we want to internationalize the strings

Porrumentzio <porru>
Tue 07 Dec 2021 10:12:27 PM UTC, comment #4: 

> xgettext should not accept f-strings as arguments ... but should recognise gettext(), or whatever is defined, inside f-strings.

Oh I see. You expressed yourself well; I misunderstood it.

That makes perfect sense.

Bruno Haible <haible>
Group administrator
Tue 07 Dec 2021 06:10:58 PM UTC, comment #3: 

I am afraid I did not express myself well: xgettext should not accept f-strings as arguments of () or gettext(), but should recognise () or gettext(), or whatever is defined, inside f-strings.

So, in the last example:


xgettext should recognise "Title", because of _() inside the f-string.

So, what xgettext should do is evaluate anything inside braces {} within f-strings as normal Python (which it is!) to see whether there are any gettext() calls.

An f-string is any Python string (with ', ", ''' or """) prepended by an 'f' or an 'F'.

Ben <qtclyinh>
Tue 07 Dec 2021 04:41:07 PM UTC, comment #2: 

Supporting this kind of strings in xgettext in the naïve way, i.e. where the string itself would appear as an msgid in the PO file, is not appropriate for the following reasons:

1) PEP 498 says "It should be noted that an f-string is really an expression evaluated at run time". But the translator is not a programmer. An expression from a programming language is just gibberish to a translator; we should not expose translators to that.

2) The translator would have the ability to change the expressions that occur inside an f-string. (Even if 'msgfmt -c' checks against that; some tool don't invoke msgfmt with the '-c' option.) To make this safe, the verification that the expressions have not been modified during translation would have to occur at runtime.

3) When the programmer changes the subexpressions, this would lead to a modified POT file, and work for the translators ensues.

It would be possible to write into the POT file a derived string, e.g. in your example '<label>{0}:</label>'. But then we need a runtime function that substitutes expression values into a format string that comes from a translator. Still, the added complexity feels awkward. It is better to let the programmer change their program, to separate internationalization and formatting, so that it uses one of the two supported format string syntaxes:
'...%(ident)d...' % { 'ident': value }

Bruno Haible <haible>
Group administrator
Wed 01 Dec 2021 04:04:48 PM UTC, comment #1: 

Sorry, the last example should read:




Ben <qtclyinh>
Wed 01 Dec 2021 04:02:14 PM UTC, original submission:  

Python 3.5 introduced f-strings, as specified in PEP 498 Literal String Interpolation:


Basically it means that if a string is prefixed with the letter f (uppercase or lowercase), inside the string there can be any Python expression within braces, such as:

f'My name is {name}!' # Inserts the value of variable name.

f"My name is {sanitise(name)}!"



Currently, xgettext does not recognise gettext() calls inside f-strings.

Ben <qtclyinh>


(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

No files currently attached


Depends on the following items: None found

Items that depend on this one: None found


Carbon-Copy List
  • -email is unavailable- added by ferdnyc (Posted a comment)
  • -email is unavailable- added by porru (Posted a comment)
  • -email is unavailable- added by haible (Posted a comment)
  • -email is unavailable- added by qtclyinh (Submitted the item)

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.


    Follow 7 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2023-12-05 haible StatusNone Fixed
        Open/ClosedOpen Closed
    2021-12-07 haible StatusNot a Bug None
        Open/ClosedClosed Open
    2021-12-07 haible StatusNone Not a Bug
        Assigned toNone haible
        Open/ClosedOpen Closed

    Back to the top

    Powered by Savane 3.13-4448.
    Corresponding source code