﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
28304	pgettext should return SafeData if both `message` and `context` are instances of SafeData	Artem Polunin	nobody	"`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."	Bug	closed	Internationalization	dev	Normal	fixed			Ready for checkin	1	0	0	0	1	0
