Code

Ticket #16721: 16721.diff

File 16721.diff, 3.6 KB (added by claudep, 3 years ago)

Fix percent escaping in blocktrans rendering

Line 
1diff --git a/django/templatetags/i18n.py b/django/templatetags/i18n.py
2index c7202e2..866db44 100644
3--- a/django/templatetags/i18n.py
4+++ b/django/templatetags/i18n.py
5@@ -110,16 +110,17 @@ class BlockTranslateNode(Node):
6         # the end of function
7         context.update(tmp_context)
8         singular, vars = self.render_token_list(self.singular)
9+        # Escape all isolated '%'
10+        singular = re.sub(u'%(?!\()', u'%%', singular)
11         if self.plural and self.countervar and self.counter:
12             count = self.counter.resolve(context)
13             context[self.countervar] = count
14             plural, plural_vars = self.render_token_list(self.plural)
15+            plural = re.sub(u'%(?!\()', u'%%', plural)
16             result = translation.ungettext(singular, plural, count)
17             vars.extend(plural_vars)
18         else:
19             result = translation.ugettext(singular)
20-        # Escape all isolated '%' before substituting in the context.
21-        result = re.sub(u'%(?!\()', u'%%', result)
22         data = dict([(v, _render_value_in_context(context.get(v, ''), context)) for v in vars])
23         context.pop()
24         return result % data
25diff --git a/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.mo b/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.mo
26index 241de05..72af5d9 100644
27Binary files a/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.mo and b/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.mo differ
28diff --git a/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.po b/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.po
29index 2d9b89e..1204d80 100644
30--- a/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.po
31+++ b/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.po
32@@ -40,3 +40,15 @@ msgid "%d result"
33 msgid_plural "%d results"
34 msgstr[0] "%d Resultat"
35 msgstr[1] "%d Resultate"
36+
37+#: models.py:13
38+#, python-format
39+msgid "The result was %(percent)s%%"
40+msgstr "Das Ergebnis war %(percent)s%%"
41+
42+#: models.py:13
43+#, python-format
44+msgid "%(percent)s%% represents %(num)s object"
45+msgid_plural "%(percent)s%% represents %(num)s objects"
46+msgstr[0] "%(percent)s%% darstellt %(num)s Objekt"
47+msgstr[1] "%(percent)s%% darstellt %(num)s Objekte"
48diff --git a/tests/regressiontests/i18n/tests.py b/tests/regressiontests/i18n/tests.py
49index 0b955ad..20302d1 100644
50--- a/tests/regressiontests/i18n/tests.py
51+++ b/tests/regressiontests/i18n/tests.py
52@@ -600,6 +600,19 @@ class MiscTests(TestCase):
53         r.META = {'HTTP_ACCEPT_LANGUAGE': 'de'}
54         self.assertEqual(g(r), 'zh-cn')
55 
56+    def test_percent_in_translatable_block(self):
57+        extended_locale_paths = settings.LOCALE_PATHS + (
58+            os.path.join(os.path.dirname(os.path.abspath(__file__)), 'other', 'locale'),
59+        )
60+        with self.settings(LOCALE_PATHS=extended_locale_paths):
61+            t_sing = Template("{% load i18n %}{% blocktrans %}The result was {{ percent }}%{% endblocktrans %}")
62+            t_plur = Template("{% load i18n %}{% blocktrans count num as number %}{{ percent }}% represents {{ num }} object{% plural %}{{ percent }}% represents {{ num }} objects{% endblocktrans %}")
63+            with translation.override('de'):
64+                self.assertEqual(t_sing.render(Context({'percent': 42})), u'Das Ergebnis war 42%')
65+                self.assertEqual(t_plur.render(Context({'percent': 42, 'num': 1})), u'42% darstellt 1 Objekt')
66+                self.assertEqual(t_plur.render(Context({'percent': 42, 'num': 4})), u'42% darstellt 4 Objekte')
67+
68+
69 class ResolutionOrderI18NTests(TestCase):
70 
71     def setUp(self):