Skip to content

Commit

Permalink
Percent signs escaping in templatetags
Browse files Browse the repository at this point in the history
Closes python-babel#43

In Django >= 1.9, `%` signs are escaped to `%%` during extraction
then replaced by `%` during the rendering. [1]
Before Django 1.9, only single percent signs were escaped.

The extraction now behaves in the same way.

[1] django/django@b750889
  • Loading branch information
Mickaël Guérin committed May 28, 2018
1 parent f2ddaba commit a0ce42a
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 2 deletions.
18 changes: 16 additions & 2 deletions django_babel/extract.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
from django.utils.translation.template import (
inline_re, block_re, endblock_re, plural_re, constant_re)

try:
from django.utils.translation.trans_real import one_percent_re
except ImportError:
# Django 1.9+
one_percent_re = None


def join_tokens(tokens, trim=False):
message = ''.join(tokens)
Expand Down Expand Up @@ -112,10 +118,14 @@ def extract_django(fileobj, keywords, comment_tags, options):
else:
singular.append('%%(%s)s' % t.contents)
elif t.token_type == TOKEN_TEXT:
if one_percent_re:
contents = one_percent_re.sub('%%', t.contents)
else:
contents = t.contents.replace('%', '%%')
if inplural:
plural.append(t.contents)
plural.append(contents)
else:
singular.append(t.contents)
singular.append(contents)
else:
if t.token_type == TOKEN_BLOCK:
imatch = inline_re.match(t.contents)
Expand All @@ -124,6 +134,10 @@ def extract_django(fileobj, keywords, comment_tags, options):
if imatch:
g = imatch.group(1)
g = strip_quotes(g)
if one_percent_re:
g = one_percent_re.sub('%%', g)
else:
g = g.replace('%', '%%')
message_context = imatch.group(3)
if message_context:
# strip quotes
Expand Down
30 changes: 30 additions & 0 deletions tests/test_extract.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,3 +218,33 @@ def test_blocktrans_with_whitespace_trimmed(self):
buf = BytesIO(test_tmpl)
messages = list(extract_django(buf, default_keys, [], {}))
self.assertEqual([(4, None, u'foo bar', [])], messages)

@pytest.mark.skipif(django.VERSION >= (1, 9),
reason='%-sign escaping changed in django 1.9')
def test_extract_trans_percents_old_way(self):
"""Before Django 1.9, only a signle %-sign was escaped to %%"""
buf = BytesIO(b'{% trans "1 %, 2 %%, 3 %%%" %}')
messages = list(extract_django(buf, default_keys, [], {}))
self.assertEqual([(1, None, u'1 %%, 2 %%, 3 %%%', [])], messages)

@pytest.mark.skipif(django.VERSION >= (1, 9),
reason='%-sign escaping changed in django 1.9')
def test_extract_blocktrans_percents_old_way(self):
"""Before Django 1.9, only a signle %-sign was escaped to %%"""
buf = BytesIO(b'{% blocktrans %}1 %, 2 %%, 3 %%%{% endblocktrans %}')
messages = list(extract_django(buf, default_keys, [], {}))
self.assertEqual([(1, None, u'1 %%, 2 %%, 3 %%%', [])], messages)

@pytest.mark.skipif(django.VERSION < (1, 9),
reason='%-sign escaping changed in django 1.9')
def test_extract_trans_percents(self):
buf = BytesIO(b'{% trans "1 %, 2 %%, 3 %%%" %}')
messages = list(extract_django(buf, default_keys, [], {}))
self.assertEqual([(1, None, u'1 %%, 2 %%%%, 3 %%%%%%', [])], messages)

@pytest.mark.skipif(django.VERSION < (1, 9),
reason='%-sign escaping changed in django 1.9')
def test_extract_blocktrans_percents(self):
buf = BytesIO(b'{% blocktrans %}1 %, 2 %%, 3 %%%{% endblocktrans %}')
messages = list(extract_django(buf, default_keys, [], {}))
self.assertEqual([(1, None, u'1 %%, 2 %%%%, 3 %%%%%%', [])], messages)

0 comments on commit a0ce42a

Please sign in to comment.