Fixed #25297 -- Allowed makemessages to work with {% trans %} tags that use template filters.

This commit is contained in:
Alexandre Pocquet 2015-08-28 17:09:20 +02:00 committed by Tim Graham
parent cc968b9c90
commit e7b7f94678
3 changed files with 48 additions and 7 deletions

View File

@ -529,7 +529,14 @@ def blankout(src, char):
context_re = re.compile(r"""^\s+.*context\s+((?:"[^"]*?")|(?:'[^']*?'))\s*""") context_re = re.compile(r"""^\s+.*context\s+((?:"[^"]*?")|(?:'[^']*?'))\s*""")
inline_re = re.compile(r"""^\s*trans\s+((?:"[^"]*?")|(?:'[^']*?'))(\s+.*context\s+((?:"[^"]*?")|(?:'[^']*?')))?\s*""") inline_re = re.compile(
# Match the trans 'some text' part
r"""^\s*trans\s+((?:"[^"]*?")|(?:'[^']*?'))"""
# Match and ignore optional filters
r"""(?:\s*\|\s*[^\s:]+(?::(?:[^\s'":]+|(?:"[^"]*?")|(?:'[^']*?')))?)*"""
# Match the optional context part
r"""(\s+.*context\s+((?:"[^"]*?")|(?:'[^']*?')))?\s*"""
)
block_re = re.compile(r"""^\s*blocktrans(\s+.*context\s+((?:"[^"]*?")|(?:'[^']*?')))?(?:\s+|$)""") block_re = re.compile(r"""^\s*blocktrans(\s+.*context\s+((?:"[^"]*?")|(?:'[^']*?')))?(?:\s+|$)""")
endblock_re = re.compile(r"""^\s*endblocktrans$""") endblock_re = re.compile(r"""^\s*endblocktrans$""")
plural_re = re.compile(r"""^\s*plural$""") plural_re = re.compile(r"""^\s*plural$""")

View File

@ -58,6 +58,18 @@ continued here.{% endcomment %}
{% trans "Translatable literal #7b" as var context "Special trans context #2" %} {% trans "Translatable literal #7b" as var context "Special trans context #2" %}
{% trans "Translatable literal #7c" context "Special trans context #3" as var %} {% trans "Translatable literal #7c" context "Special trans context #3" as var %}
{% trans "Translatable literal #7.1a" | upper context "context #7.1a" %}
{% trans "Translatable literal #7.1b" |upper as var context "context #7.1b" %}
{% trans "Translatable literal #7.1c"| upper context "context #7.1c" as var %}
{% trans "Translatable literal #7.1d"|add:" foo" context "context #7.1d" %}
{% trans "Translatable literal #7.1e"|add:' ûè本' as var context "context #7.1e" %}
{% with foo=" foo" %}
{% trans "Translatable literal #7.1f"|add:foo context "context #7.1f" as var %}
{% endwith %}
{% trans "Translatable literal #7.1g"|add:2 context "context #7.1g" as var %}
{% trans "Translatable literal #7.1h" | add:"foo" | add:2 context "context #7.1h" as var %}
{% blocktrans context "Special blocktrans context #1" %}Translatable literal #8a{% endblocktrans %} {% blocktrans context "Special blocktrans context #1" %}Translatable literal #8a{% endblocktrans %}
{% blocktrans count 2 context "Special blocktrans context #2" %}Translatable literal #8b-singular{% plural %}Translatable literal #8b-plural{% endblocktrans %} {% blocktrans count 2 context "Special blocktrans context #2" %}Translatable literal #8b-singular{% plural %}Translatable literal #8b-plural{% endblocktrans %}
{% blocktrans context "Special blocktrans context #3" count 2 %}Translatable literal #8c-singular{% plural %}Translatable literal #8c-plural{% endblocktrans %} {% blocktrans context "Special blocktrans context #3" count 2 %}Translatable literal #8c-singular{% plural %}Translatable literal #8c-plural{% endblocktrans %}
@ -79,7 +91,7 @@ continued here.{% endcomment %}
line breaks, this time line breaks, this time
should be trimmed. should be trimmed.
{% endblocktrans %} {% endblocktrans %}
{% trans "I'm on line 82" %} {% trans "Get my line number" %}
{% blocktrans trimmed count counter=mylist|length %} {% blocktrans trimmed count counter=mylist|length %}
First `trans`, then `blocktrans` with a plural First `trans`, then `blocktrans` with a plural

View File

@ -102,15 +102,28 @@ class ExtractorTests(SimpleTestCase):
# #: path/to/file.html:123 # #: path/to/file.html:123
cwd_prefix = '' cwd_prefix = ''
parts = ['#: '] parts = ['#: ']
parts.append(os.path.join(cwd_prefix, *comment_parts))
path = os.path.join(cwd_prefix, *comment_parts)
parts.append(path)
if isinstance(line_number, six.string_types):
line_number = self._get_token_line_number(path, line_number)
if line_number is not None: if line_number is not None:
parts.append(':%d' % line_number) parts.append(':%d' % line_number)
needle = ''.join(parts) needle = ''.join(parts)
if assert_presence: if assert_presence:
return self.assertIn(needle, po_contents, '"%s" not found in final .po file.' % needle) return self.assertIn(needle, po_contents, '"%s" not found in final .po file.' % needle)
else: else:
return self.assertNotIn(needle, po_contents, '"%s" shouldn\'t be in final .po file.' % needle) return self.assertNotIn(needle, po_contents, '"%s" shouldn\'t be in final .po file.' % needle)
def _get_token_line_number(self, path, token):
with open(path) as f:
for line, content in enumerate(f, 1):
if token in force_text(content):
return line
self.fail("The token '%s' could not be found in %s, please check the test config" % (token, path))
def assertLocationCommentPresent(self, po_filename, line_number, *comment_parts): def assertLocationCommentPresent(self, po_filename, line_number, *comment_parts):
""" """
self.assertLocationCommentPresent('django.po', 42, 'dirA', 'dirB', 'foo.py') self.assertLocationCommentPresent('django.po', 42, 'dirA', 'dirB', 'foo.py')
@ -121,7 +134,11 @@ class ExtractorTests(SimpleTestCase):
(or `#: .\dirA\dirB\foo.py:42` on Windows) (or `#: .\dirA\dirB\foo.py:42` on Windows)
None can be passed for the line_number argument to skip checking of the :42 suffix part. None can be passed for the line_number argument to skip checking of
the :42 suffix part.
A string token can also be pased as line_number, in which case it
will be searched in the template, and its line number will be used.
A msgid is a suitable candidate.
""" """
return self._assertPoLocComment(True, po_filename, line_number, *comment_parts) return self._assertPoLocComment(True, po_filename, line_number, *comment_parts)
@ -179,8 +196,8 @@ class BasicExtractorTests(ExtractorTests):
# should be trimmed # should be trimmed
self.assertMsgId("Again some text with a few line breaks, this time should be trimmed.", po_contents) self.assertMsgId("Again some text with a few line breaks, this time should be trimmed.", po_contents)
# #21406 -- Should adjust for eaten line numbers # #21406 -- Should adjust for eaten line numbers
self.assertMsgId("I'm on line 82", po_contents) self.assertMsgId("Get my line number", po_contents)
self.assertLocationCommentPresent(self.PO_FILE, 82, 'templates', 'test.html') self.assertLocationCommentPresent(self.PO_FILE, 'Get my line number', 'templates', 'test.html')
def test_force_en_us_locale(self): def test_force_en_us_locale(self):
"""Value of locale-munging option used by the command is the right one""" """Value of locale-munging option used by the command is the right one"""
@ -235,6 +252,11 @@ class BasicExtractorTests(ExtractorTests):
self.assertIn('msgctxt "Special trans context #3"', po_contents) self.assertIn('msgctxt "Special trans context #3"', po_contents)
self.assertMsgId("Translatable literal #7c", po_contents) self.assertMsgId("Translatable literal #7c", po_contents)
# {% trans %} with a filter
for minor_part in 'abcdefgh': # Iterate from #7.1a to #7.1h template markers
self.assertIn('msgctxt "context #7.1{}"'.format(minor_part), po_contents)
self.assertMsgId('Translatable literal #7.1{}'.format(minor_part), po_contents)
# {% blocktrans %} # {% blocktrans %}
self.assertIn('msgctxt "Special blocktrans context #1"', po_contents) self.assertIn('msgctxt "Special blocktrans context #1"', po_contents)
self.assertMsgId("Translatable literal #8a", po_contents) self.assertMsgId("Translatable literal #8a", po_contents)
@ -578,7 +600,7 @@ class LocationCommentsTests(ExtractorTests):
management.call_command('makemessages', locale=[LOCALE], verbosity=0, no_location=False) management.call_command('makemessages', locale=[LOCALE], verbosity=0, no_location=False)
self.assertTrue(os.path.exists(self.PO_FILE)) self.assertTrue(os.path.exists(self.PO_FILE))
# #16903 -- Standard comment with source file relative path should be present # #16903 -- Standard comment with source file relative path should be present
self.assertLocationCommentPresent(self.PO_FILE, 55, 'templates', 'test.html') self.assertLocationCommentPresent(self.PO_FILE, 'Translatable literal #6b', 'templates', 'test.html')
# #21208 -- Leaky paths in comments on Windows e.g. #: path\to\file.html.py:123 # #21208 -- Leaky paths in comments on Windows e.g. #: path\to\file.html.py:123
self.assertLocationCommentNotPresent(self.PO_FILE, None, 'templates', 'test.html.py') self.assertLocationCommentNotPresent(self.PO_FILE, None, 'templates', 'test.html.py')