#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 django-updates+unsubscr...@googlegroups.com.
To post to this group, send email to django-updates@googlegroups.com.
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