#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 [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/049.37f31499000cca49f6a6406ec7817990%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to