Support t-strings in Python 3.14
PEP 750 has been accepted and it would be great to have support for this ready once Python 3.14 gets released!
Writing translatable strings like this would be much more natural than the current way of using .format() or % on them, and also much less error-prone (people accidentally calling .format() inside _() instead of outside):
_(t'Hello {user}: {message}')
ngettext(t'{n} user', t'{n} users', n)
Unfortunately certain case are trickier, since you'd need to generate placeholder names from somewhat arbitrary python expressions:
_(t'Hello {user.name}: {get_message(user)}')
However, I think anything besides simple attribute accesses are probably somewhat of an edge case, and generating something like user_name and get_message_user, or failing in more complex cases (or when two different expressions would be turned into the same placeholder string) would not be too bad. In fact, Jinja's i18n tag already does that (you can use simple variables directly, but have to bind anything else to a simple variable name).
FYI I opened python/cpython#137354 in the hopes to get this into stdlib's gettext.
I also have t-string extraction working fine in my local copy of babel, so I'll send a PR to make the necessary change sooner or later (after I got enough feedback on the stdlib PR, or after it's merged depending on how it goes).
PS: Feel free to assign this issue to me.
@ThiefMaster Thanks for pushing forward on the stdlib side of the fence! I was hesitant to really do anything about this other than 👍 because the API would need to be at least somewhat set in stone before we can extract things :)
Since upstream interest seems to be relatively low for now, I'd like to get this into Babel for now and if people start using it, push for getting it into stdlib again maybe in a year or two).
My preferred way to do this would be by vendoring stdlib's gettext.py with the necessary changes and using that instead of the stdlib one, instead of trying to somehow hack this on top of the existing ones, which would likely be pretty messy due to the NullTranslations inheritance combined with the fallback translations (my first prototype did that, but completely ignored fallbacks).
Let me know if you have any opinion on this :)
@akx ping