#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.

Reply via email to