#28304: pgettext should return SafeData if both `message` and `context` are
instances of SafeData
------------------------------------------------+------------------------
               Reporter:  Artem Polunin         |          Owner:  nobody
                   Type:  Bug                   |         Status:  new
              Component:  Internationalization  |        Version:  master
               Severity:  Normal                |       Keywords:
           Triage Stage:  Unreviewed            |      Has patch:  0
    Needs documentation:  0                     |    Needs tests:  0
Patch needs improvement:  0                     |  Easy pickings:  0
                  UI/UX:  0                     |
------------------------------------------------+------------------------
 `pgettext` always returns `str` even if both `message` and `context` are
 instances of `SafeData` (assuming translations exist).

 If we have following translations into Ukrainian
 {{{
 msgid ""
 msgstr ""
 "Project-Id-Version: django\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2017-06-09 14:23+0000\n"
 "PO-Revision-Date: 2017-06-09 10:22-0400\n"
 "Last-Translator: None\n"
 "Language-Team: Ukrainian\n"
 "Language: uk_UA\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 &&
 n"
 "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"

 msgid "&#39;"
 msgstr "&#39; відсотків"

 msgctxt "percent"
 msgid "&#39;"
 msgstr "&#39; відсотків"
 }}}
 then
 {{{
 >>> from django.utils.translation import activate, ugettext, pgettext
 >>> from django.utils.safestring import SafeText
 >>>
 >>> activate('ua')
 >>>
 >>> type(pgettext(SafeText('percent'), SafeText('&#39;')))    # Should
 return `SafeText` instance
 <class 'str'>
 >>>
 >>> type(ugettext(SafeText('&#39;')))    # This works correctly
 <class 'django.utils.safestring.SafeText'>
 }}}

 This causes additional escape when using `trans` with `context` in
 templates:
 {{{
 >>> from django.utils.translation import activate
 >>> from django.template import Context, Template
 >>>
 >>> activate('ua')
 >>>
 >>> Template("{% load i18n %}{% trans '&#39;' context 'percent'
 %}").render(Context())    # `&` unnecessary escaped into `&amp;`
 '&amp;#39; відсотків'
 >>>
 >>> Template("{% load i18n %}{% trans '&#39;' %}").render(Context())    #
 This works correctly
 '&#39; відсотків'
 }}}
 -----
 The fix can be as follows:
 This line
 
https://github.com/django/django/blob/master/django/utils/translation/trans_real.py#L325
 in `pgettext` can be changed into:
 {{{
     msg_with_ctxt = "%s%s%s" % (context, CONTEXT_SEPARATOR, message)
     if isinstance(context, SafeData) and isinstance(message, SafeData):
         msg_with_ctxt = mark_safe(msg_with_ctxt)
 }}}
 -----
 All versions from 1.8 to master are affected.

--
Ticket URL: <https://code.djangoproject.com/ticket/28304>
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/049.37f31499000cca49f6a6406ec7817990%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to