Opened 13 years ago
Closed 5 years ago
#18995 closed Cleanup/optimization (fixed)
String formatting error when passing floats as values in {% blocktrans %} tags
| Reported by: | Bruno Renié | Owned by: | Jacob Walls |
|---|---|---|---|
| Component: | Internationalization | Version: | dev |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Ready for checkin | |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
With the following template code:
{% blocktrans count counter=person.distance_in_miles|floatformat:0 %}{{ counter }} mile away{% plural %}{{ counter }} miles away{% endblocktrans %}
And a russian translation:
#, python-format msgid "%(counter)s mile away" msgid_plural "%(counter)s miles away" msgstr[0] "На расстоянии %(counter)s мили" msgstr[1] "На расстоянии %(counter)s миль" msgstr[2] "На расстоянии %(counter)s миль"
Rendering the template fails with a String formatting error: "TypeError: not all arguments converted during string formatting".
This happens because gettext string formatting fails when a float is passed. Removing the floatformat and casting the value as int works fine.
This could be improved by either:
- Swallow
TypeErrorand throw a friendlier message saying the type might not be compatible with gettext's string formatting (not a fan of swallowingTypeErrorthough, we need to make sure nothing else in do_translate throws such an exception) - Actively checking the type's compatibility with the string format
Change History (7)
comment:1 by , 13 years ago
| Triage Stage: | Unreviewed → Accepted |
|---|---|
| Type: | Uncategorized → Cleanup/optimization |
comment:2 by , 12 years ago
comment:4 by , 5 years ago
| Patch needs improvement: | set |
|---|---|
| Version: | 1.4 → master |
comment:5 by , 5 years ago
| Patch needs improvement: | unset |
|---|
Adjusted patch per review to allow floats and decimal.Decimal in addition to integers.
comment:6 by , 5 years ago
| Triage Stage: | Accepted → Ready for checkin |
|---|
Note:
See TracTickets
for help on using tickets.
I've done some digging and found that the issue isn't to do with floats. In fact,
ungettextwill happily work with floats without raising any exceptions.The root of the problem is that
floatformatreturns a string, which conflicts with the Russian plural rules. Indeed, those rules use the modulo sign%:If you pass a string as a value for
n, then the%sign will operate as string formatting instead of a modulo, therefore causing theTypeError. The same effect can be easily reproduced as follows:I suggest making
blocktransraise an exception upstream if the value provided for the counter is not a number.