Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: update i18n guidelines for string interpolation in Python #740

Merged

Conversation

Samk13
Copy link
Member

@Samk13 Samk13 commented Feb 5, 2025

❤️ Thank you for your contribution!

Description

Read the comment on Discord: https://discord.com/channels/692989811736182844/852219787005919242/1336648054488567868

Checklist

Ticks in all boxes and 🟢 on all GitHub actions status checks are required to merge:

  • I'm aware of the code of conduct.
  • I've created logical separate commits and followed the commit message format.
  • I've targeted the master branch.
  • If this documentation change impacts the current release of InvenioRDM, I will backport it to the production branch following approval or indicate to a maintainer that it should be backported.

Reminder

By using GitHub, you have already agreed to the GitHub’s Terms of Service including that:

  1. You license your contribution under the same terms as the current repository’s license.
  2. You agree that you have the right to license your contribution under the current repository’s license.

@Samk13 Samk13 requested a review from max-moser February 5, 2025 12:51
Copy link
Contributor

@max-moser max-moser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm not very deep in this translation business, so i can't judge the importance of e.g. lazy strings, but here's my two cents anyway (please correct me if i'm wrong!):

from my understanding, there's usually[1] no real downside of using lazy_gettext() over gettext(), and i think it enables postponing the translation until the very last moment, at which some more context (e.g. user preferences for locale) may become available... in the worst case it's effectively the same.

either way, i would suggest keeping the format aligned either way, to reduce mental overhead – also, maybe some changes will make lazy evaluation more relevant for individual messages at a later point than when they were initially added?

as such, i would suggest moving the old-style formatting up to the top as the suggested variant, and making the alternatives less prominent (perhaps even as a folded accordion per default?)

💭 an alternative would of course be to simply submit a PR to flask_babel that enables new-style formatting in addition to old-style formatting, to allow something like _("hello, {name}", name=name) 😄
that might actually save us quite a bit of effort of updating all the translations all over the place (though the _() calls will still likely need fixups).

[1] except for when there are...
i remember not being able to use lazy strings in the context of requests & events (i.e. comments) easily because lazy strings don't support being serialized (e.g. into the JSON in the DB) all that well.
back then, i just went for normal strings via gettext() instead.
not sure if that's still the case though, maybe somebody put in some more work!

@@ -9,12 +9,35 @@ In order to translate strings, they have to be marked. This ensures that they wi
### Python

!!! warning
Do not use `f-strings` for translatable text. Interpolation is not supported for these types of strings (see [Issue](https://github.com/python-babel/babel/issues/594)).
Do not use f‑strings for translatable text.
F‑strings perform interpolation immediately, so the extracted message will contain the interpolated text (e.g. "Hello, max") rather than the intended placeholder (e.g. "Hello, {username}"). This means that your translators will see the wrong string and translations will not work as expected.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think that even with f-strings, the extracted message will still have the shape "Hello, {username}" because the extraction runs on static code by parsing the syntax tree, and doesn't need to run the code (which would be required to know the content of variables (unless they're hard-coded values)

Similarly, do not pass keyword arguments to `_()` when using new‑style (curly‑brace) placeholders. For example, avoid this pattern:

```python
# ❌ Incorrect – the placeholder is not interpolated at runtime.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indeed, the placeholder isn't replaced at runtime – because flask_babel.gettext() uses s % variables (old-style formatting), but for new-style formatting we would require s.format(variables)

@Samk13 Samk13 force-pushed the i18n-update-python-best-practices branch from 410910a to 05a395d Compare February 5, 2025 14:42
@Samk13
Copy link
Member Author

Samk13 commented Feb 5, 2025

Thanks for sharing your thoughts @max-moser I agree that lazy_gettext() generally has advantages in terms of postponing translation until the last moment, which can be useful in many cases, though, as you pointed out, serialization issues can make it tricky in some contexts.

For this PR, I mainly kicked things off based on the discussions and your testing shared on Discord. Feel free to update or even close it if you think a different approach makes more sense, I'm keeping it open for further discussion by others as well.
You have free hands on this one! :)

@max-moser max-moser force-pushed the i18n-update-python-best-practices branch from 05a395d to f163633 Compare February 21, 2025 15:18
Copy link
Contributor

@max-moser max-moser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the late action, I've just slightly updated the text and force-pushed.
Here's a screenshot of the current state:
image

@Samk13 Samk13 merged commit 7e44d96 into inveniosoftware:master Feb 21, 2025
1 check passed
fenekku pushed a commit to fenekku/docs-invenio-rdm that referenced this pull request Feb 25, 2025
@fenekku fenekku mentioned this pull request Feb 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants