fix: translations not containing string formatting

In some translations we might be missing replacement placeholders (%).
This turns out to be problematic when calling the format function.

Wrap the jinja2 format function and just return the string unformatted
when % is missing.

Fixes: #341
Signed-off-by: moson <moson@archlinux.org>
This commit is contained in:
moson 2023-07-10 18:02:20 +02:00
parent c0bbe21d81
commit fa1212f2de
No known key found for this signature in database
GPG key ID: 4A4760AB4EE15296
2 changed files with 32 additions and 0 deletions

View file

@ -8,6 +8,7 @@ from zoneinfo import ZoneInfo
import fastapi import fastapi
import paginate import paginate
from jinja2 import pass_context from jinja2 import pass_context
from jinja2.filters import do_format
import aurweb.models import aurweb.models
from aurweb import config, l10n from aurweb import config, l10n
@ -164,3 +165,17 @@ def date_display(context: dict[str, Any], dt: Union[int, datetime]) -> str:
@pass_context @pass_context
def datetime_display(context: dict[str, Any], dt: Union[int, datetime]) -> str: def datetime_display(context: dict[str, Any], dt: Union[int, datetime]) -> str:
return date_strftime(context, dt, "%Y-%m-%d %H:%M (%Z)") return date_strftime(context, dt, "%Y-%m-%d %H:%M (%Z)")
@register_filter("format")
def safe_format(value: str, *args: Any, **kwargs: Any) -> str:
"""Wrapper for jinja2 format function to perform additional checks."""
# If we don't have anything to be formatted, just return the value.
# We have some translations that do not contain placeholders for replacement.
# In these cases the jinja2 function is throwing an error:
# "TypeError: not all arguments converted during string formatting"
if "%" not in value:
return value
return do_format(value, *args, **kwargs)

View file

@ -1,6 +1,8 @@
from datetime import datetime from datetime import datetime
from zoneinfo import ZoneInfo from zoneinfo import ZoneInfo
import pytest
from aurweb import filters, time from aurweb import filters, time
@ -34,3 +36,18 @@ def test_to_qs():
query = {"a": "b", "c": [1, 2, 3]} query = {"a": "b", "c": [1, 2, 3]}
qs = filters.to_qs(query) qs = filters.to_qs(query)
assert qs == "a=b&c=1&c=2&c=3" assert qs == "a=b&c=1&c=2&c=3"
@pytest.mark.parametrize(
"value, args, expected",
[
("", (), ""),
("a", (), "a"),
("a", (1,), "a"),
("%s", ("a",), "a"),
("%s", ("ab",), "ab"),
("%s%d", ("a", 1), "a1"),
],
)
def test_safe_format(value: str, args: tuple, expected: str):
assert filters.safe_format(value, *args) == expected