#24257: The trans template tag fails to get a message when there is a %
character
in the string
-------------------------------------+-------------------------------------
Reporter: aboudreault | Owner: nobody
Type: Bug | Status: new
Component: | Version: 1.7
Internationalization |
Severity: Normal | Resolution:
Keywords: trans templatetag | Triage Stage: Accepted
i18n |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by beck):
This was the ticket I decided to tackle at the pycon sprints (claudep wish
you were there so I could thank you in person for your patience on my
previous pull... and this one too).
This issue turned out to be quite difficult. I've tried multiple
approaches.
== Long story short ==
The simplest solution is to ensure that all translation messages that have
a percent signs get python formatting.
== Long story long ==
In an ideal world we would be able to use the template string (with it's
curly brace variables) as our msgid. Since that is not possible, template
copy is coerced into a python formatted / sprintf string.
This is a source of much pain and confusion, especially with percent
signs. Why?
'''xgettext is awkward.'''
xgettext will identify all python-format strings, example:
{{{
echo 'gettext("%s");' | xgettext --language=python --output=- -
#, python-format
msgid "%s"
msgstr ""
}}}
This is all good. It gets awkward when you pass it an invalid python fmt
string, say:
{{{
echo 'gettext("%s costs 10%");' | xgettext --language=python --output=- -
msgid "%s costs 10%"
msgstr ""
}}}
This is awkward because the single `%` is seen as invalid python format
and so the message id is not marked as we would expect.
'''sprintf is awkward.'''
Since humans are bad parsers, when I look at the format, `% %s` I see a
percent followed by a string specifier. What this actually means a percent
sign specifier, with a whitespace conversion flag, followed by an `s`
character.
Example:
{{{
>>> "% %s" % ()
'%s'
>>> "% 10%s" % ()
' %s'
>>>
}}}
These two bits awkwardness in gettext and sprinf has caused some confusion
as past developers have tried to shoehorn the template language into these
technologies.
Example:
{{{
{% blocktrans with a=1 %}Blocktrans extraction shouldn't double escape
this: %%, a={{ a }}{% endblocktrans %}
}}}
The correct msgid is:
{{{
Blocktrans extraction shouldn't double escape this: %%%%, a=%(a)s
}}}
Not:
{{{
Blocktrans extraction shouldn't double escape this: %%, a={{ a }}
}}}
== The solution ==
First get some robust tests that capture all corner cases of awkwardness.
I've added a sample app to the i18n tests to make it easier to write tests
that evaluate extraction and translation using the same gettext catalogs.
I then refactored tests addressing extraction and translation when a `%`
is involved.
Second, knock out any special handling of percents and ensure valid
python-formatting on strings.
Technically not all template strings with a percent should be python-
formatted. If the template was only `{% trans "10%" %}` this could go
into the gettext catalog with msgid `10%` but such things is not possible
with how `blocktrans` is rendered.
When using `trans` and `blocktrans` with the same copy, the two should
always extract the same msgid and render identically.
The pull: https://github.com/django/django/pull/4549
--
Ticket URL: <https://code.djangoproject.com/ticket/24257#comment:4>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/069.61e3a7b0d598f0fdecef7f67b4328aea%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.