Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed a few problems with variable resolving inside of blocktrans tag…

…s. A couple of these were exposed by the auto-escaping changes, but I suspect the other one has been hiding in plain sight for a while.

Fixed #5952, #5953


git-svn-id: http://code.djangoproject.com/svn/django/trunk@6682 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit adcec0885d847896e2f51dc739a34755d3a7ddb6 1 parent 64c0bf8
@malcolmt malcolmt authored
View
32 django/templatetags/i18n.py
@@ -1,9 +1,10 @@
import re
-from django.template import Node, Variable
+from django.template import Node, Variable, VariableNode
from django.template import TemplateSyntaxError, TokenParser, Library
from django.template import TOKEN_TEXT, TOKEN_VAR
from django.utils import translation
+from django.utils.encoding import force_unicode
register = Library()
@@ -45,7 +46,8 @@ def render(self, context):
return translation.ugettext(value)
class BlockTranslateNode(Node):
- def __init__(self, extra_context, singular, plural=None, countervar=None, counter=None):
+ def __init__(self, extra_context, singular, plural=None, countervar=None,
+ counter=None):
self.extra_context = extra_context
self.singular = singular
self.plural = plural
@@ -54,29 +56,32 @@ def __init__(self, extra_context, singular, plural=None, countervar=None, counte
def render_token_list(self, tokens):
result = []
+ vars = []
for token in tokens:
if token.token_type == TOKEN_TEXT:
result.append(token.contents)
elif token.token_type == TOKEN_VAR:
- result.append('%%(%s)s' % token.contents)
- return ''.join(result)
+ result.append(u'%%(%s)s' % token.contents)
+ vars.append(token.contents)
+ return ''.join(result), vars
def render(self, context):
context.push()
- for var,val in self.extra_context.items():
- context[var] = val.resolve(context)
- singular = self.render_token_list(self.singular)
+ for var, val in self.extra_context.items():
+ context[var] = val.render(context)
+ singular, vars = self.render_token_list(self.singular)
if self.plural and self.countervar and self.counter:
count = self.counter.resolve(context)
context[self.countervar] = count
- plural = self.render_token_list(self.plural)
+ plural = self.render_token_list(self.plural)[0]
result = translation.ungettext(singular, plural, count)
else:
result = translation.ugettext(singular)
# Escape all isolated '%' before substituting in the context.
- result = re.sub('%(?!\()', '%%', result) % context
+ result = re.sub(u'%(?!\()', u'%%', result)
+ data = dict([(v, force_unicode(context[v])) for v in vars])
context.pop()
- return result
+ return result % data
def do_get_available_languages(parser, token):
"""
@@ -198,7 +203,6 @@ def do_block_translate(parser, token):
This is much like ngettext, only in template syntax.
"""
class BlockTranslateParser(TokenParser):
-
def top(self):
countervar = None
counter = None
@@ -209,7 +213,8 @@ def top(self):
value = self.value()
if self.tag() != 'as':
raise TemplateSyntaxError, "variable bindings in 'blocktrans' must be 'with value as variable'"
- extra_context[self.tag()] = parser.compile_filter(value)
+ extra_context[self.tag()] = VariableNode(
+ parser.compile_filter(value))
elif tag == 'count':
counter = parser.compile_filter(self.value())
if self.tag() != 'as':
@@ -241,7 +246,8 @@ def top(self):
if token.contents.strip() != 'endblocktrans':
raise TemplateSyntaxError, "'blocktrans' doesn't allow other block tags (seen %r) inside it" % token.contents
- return BlockTranslateNode(extra_context, singular, plural, countervar, counter)
+ return BlockTranslateNode(extra_context, singular, plural, countervar,
+ counter)
register.tag('get_available_languages', do_get_available_languages)
register.tag('get_current_language', do_get_current_language)
View
9 tests/regressiontests/templates/tests.py
@@ -705,10 +705,10 @@ def get_template_tests(self):
'i18n02': ('{% load i18n %}{% trans "xxxyyyxxx" %}', {}, "xxxyyyxxx"),
# simple translation of a variable
- 'i18n03': ('{% load i18n %}{% blocktrans %}{{ anton }}{% endblocktrans %}', {'anton': 'xxxyyyxxx'}, "xxxyyyxxx"),
+ 'i18n03': ('{% load i18n %}{% blocktrans %}{{ anton }}{% endblocktrans %}', {'anton': '\xc3\x85'}, u"Å"),
# simple translation of a variable and filter
- 'i18n04': ('{% load i18n %}{% blocktrans with anton|lower as berta %}{{ berta }}{% endblocktrans %}', {'anton': 'XXXYYYXXX'}, "xxxyyyxxx"),
+ 'i18n04': ('{% load i18n %}{% blocktrans with anton|lower as berta %}{{ berta }}{% endblocktrans %}', {'anton': '\xc3\x85'}, u'å'),
# simple translation of a string with interpolation
'i18n05': ('{% load i18n %}{% blocktrans %}xxx{{ anton }}xxx{% endblocktrans %}', {'anton': 'yyy'}, "xxxyyyxxx"),
@@ -740,6 +740,11 @@ 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
+ # template.
+ 'i18n17': ('{% load i18n %}{% blocktrans with anton|escape as berta %}{{ berta }}{% endblocktrans %}', {'anton': 'α & β'}, u'α &amp; β'),
+ 'i18n18': ('{% load i18n %}{% blocktrans with anton|force_escape as berta %}{{ berta }}{% endblocktrans %}', {'anton': 'α & β'}, u'α &amp; β'),
+
### HANDLING OF TEMPLATE_STRING_IF_INVALID ###################################
'invalidstr01': ('{{ var|default:"Foo" }}', {}, ('Foo','INVALID')),
Please sign in to comment.
Something went wrong with that request. Please try again.