From b1a5db37e6631ab4a964d7f8d52dfe593f9e6c4b Mon Sep 17 00:00:00 2001 From: Malcolm Tredinnick Date: Sat, 11 Apr 2009 12:03:52 +0000 Subject: [PATCH] Fixed #10369 -- Fixed auto-escaping inside "tran" and "blocktrans" tags. Patch from Andrew Badr. git-svn-id: http://code.djangoproject.com/svn/django/trunk@10519 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/template/__init__.py | 19 ++++++++++++++----- django/templatetags/i18n.py | 6 +++--- tests/regressiontests/templates/tests.py | 6 +++++- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/django/template/__init__.py b/django/template/__init__.py index 95aa36af2120a..5493e5bbb7748 100644 --- a/django/template/__init__.py +++ b/django/template/__init__.py @@ -801,6 +801,18 @@ def __repr__(self): def render(self, context): return self.s + +def _render_value_in_context(value, context): + """ + Converts any value to a string to become part of a rendered template. This + means escaping, if required, and conversion to a unicode object. If value + is a string, it is expected to have already been translated. + """ + value = force_unicode(value) + if (context.autoescape and not isinstance(value, SafeData)) or isinstance(value, EscapeData): + return escape(value) + else: + return value class VariableNode(Node): def __init__(self, filter_expression): @@ -811,15 +823,12 @@ def __repr__(self): def render(self, context): try: - output = force_unicode(self.filter_expression.resolve(context)) + output = self.filter_expression.resolve(context) except UnicodeDecodeError: # Unicode conversion can fail sometimes for reasons out of our # control (e.g. exception rendering). In that case, we fail quietly. return '' - if (context.autoescape and not isinstance(output, SafeData)) or isinstance(output, EscapeData): - return force_unicode(escape(output)) - else: - return force_unicode(output) + return _render_value_in_context(output, context) def generic_tag_compiler(params, defaults, name, node_class, parser, token): "Returns a template.Node subclass." diff --git a/django/templatetags/i18n.py b/django/templatetags/i18n.py index 190cb7012875e..046743323c26f 100644 --- a/django/templatetags/i18n.py +++ b/django/templatetags/i18n.py @@ -1,6 +1,6 @@ import re -from django.template import Node, Variable, VariableNode +from django.template import Node, Variable, VariableNode, _render_value_in_context from django.template import TemplateSyntaxError, TokenParser, Library from django.template import TOKEN_TEXT, TOKEN_VAR from django.utils import translation @@ -43,7 +43,7 @@ def render(self, context): if self.noop: return value else: - return translation.ugettext(value) + return _render_value_in_context(translation.ugettext(value), context) class BlockTranslateNode(Node): def __init__(self, extra_context, singular, plural=None, countervar=None, @@ -82,7 +82,7 @@ def render(self, context): result = translation.ugettext(singular) # Escape all isolated '%' before substituting in the context. result = re.sub(u'%(?!\()', u'%%', result) - data = dict([(v, force_unicode(context[v])) for v in vars]) + data = dict([(v, _render_value_in_context(context[v], context)) for v in vars]) context.pop() return result % data diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py index 5176b116e9e5e..953e8faa1accf 100644 --- a/tests/regressiontests/templates/tests.py +++ b/tests/regressiontests/templates/tests.py @@ -851,10 +851,14 @@ def get_template_tests(self): 'i18n15': ('{{ absent|default:_("Password") }}', {'LANGUAGE_CODE': 'de', 'absent': ""}, 'Passwort'), 'i18n16': ('{{ _("<") }}', {'LANGUAGE_CODE': 'de'}, '<'), - # Escaping inside blocktrans works as if it was directly in the + # Escaping inside blocktrans and trans works as if it was directly in the # template. 'i18n17': ('{% load i18n %}{% blocktrans with anton|escape as berta %}{{ berta }}{% endblocktrans %}', {'anton': 'α & β'}, u'α & β'), 'i18n18': ('{% load i18n %}{% blocktrans with anton|force_escape as berta %}{{ berta }}{% endblocktrans %}', {'anton': 'α & β'}, u'α & β'), + 'i18n19': ('{% load i18n %}{% blocktrans %}{{ andrew }}{% endblocktrans %}', {'andrew': 'a & b'}, u'a & b'), + 'i18n20': ('{% load i18n %}{% trans andrew %}', {'andrew': 'a & b'}, u'a & b'), + 'i18n21': ('{% load i18n %}{% blocktrans %}{{ andrew }}{% endblocktrans %}', {'andrew': mark_safe('a & b')}, u'a & b'), + 'i18n22': ('{% load i18n %}{% trans andrew %}', {'andrew': mark_safe('a & b')}, u'a & b'), ### HANDLING OF TEMPLATE_STRING_IF_INVALID ###################################