Skip to content

Commit

Permalink
docs: update i18n guidelines for string interpolation in Python
Browse files Browse the repository at this point in the history
  • Loading branch information
Samk13 committed Feb 5, 2025
1 parent 751e709 commit 05a395d
Showing 1 changed file with 30 additions and 5 deletions.
35 changes: 30 additions & 5 deletions docs/develop/howtos/i18n.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,39 @@ 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.

Instead, use `format`:
```diff
- _(f"Hi {username}")
+ _("Hi {username}".format(username=username))
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.
translated = _("Hello, {username}", username=username)
```

and also do not perform interpolation inside the `_()` call:

```python
# ❌ Incorrect – interpolation happens before marking the string for translation.
translated = _("Hello, {username}".format(username=username))
```

Instead, if you prefer new‑style formatting, mark your string with placeholders and apply `.format()` after the `_()` call:

```python
# ✅ Correct – the extracted message remains "Hello, {username}".
# ⚠️ However, the translation result will be immediately evaluated and thus not a lazy string!
translated = _("Hello, {username}").format(username=username)
```

!!!note
Using `.format()` on a lazy string (as returned by `lazy_gettext()`) converts it into a regular (non‑lazy) string. If lazy evaluation is important, it is recommended to use the old‑style `%` formatting which supports passing parameters directly:

```python
# ✅ Recommended for lazy evaluation.
translated = _("Hello, %(username)s", username=username)
```

Marking strings in python is done via the `Flask-BabelEx` package. First, make sure to import the package and the `*gettext` function. We usually import it as `_` to be consistent throughout different packages.

```python
Expand Down

0 comments on commit 05a395d

Please sign in to comment.