mirror of
https://github.com/django/django.git
synced 2025-11-07 07:15:35 +00:00
Fixed #11240 -- Made makemessages i18n command escape % symbols in literals passed to the trans tag.
This avoids problems with unintended automatic detection, marking and validation of Python string formatting specifiers performed by xgettext(1)/msgfmt(1) that stem from the fact that under the hood makemessages converts templates to Python code before passing them to xgettext. This also makes it consistent with its behavior on literals passed to the blocktrans tag. Thanks Jannis and claude for reviewing and feedback. git-svn-id: http://code.djangoproject.com/svn/django/trunk@17190 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
@@ -31,10 +31,13 @@ class ExtractorTests(TestCase):
|
||||
os.chdir(self._cwd)
|
||||
|
||||
def assertMsgId(self, msgid, s, use_quotes=True):
|
||||
q = '"'
|
||||
if use_quotes:
|
||||
msgid = '"%s"' % msgid
|
||||
q = "'"
|
||||
needle = 'msgid %s' % msgid
|
||||
msgid = re.escape(msgid)
|
||||
return self.assertTrue(re.search('^msgid %s' % msgid, s, re.MULTILINE))
|
||||
return self.assertTrue(re.search('^msgid %s' % msgid, s, re.MULTILINE), 'Could not find %(q)s%(n)s%(q)s in generated PO file' % {'n':needle, 'q':q})
|
||||
|
||||
def assertNotMsgId(self, msgid, s, use_quotes=True):
|
||||
if use_quotes:
|
||||
@@ -49,35 +52,57 @@ class BasicExtractorTests(ExtractorTests):
|
||||
os.chdir(self.test_dir)
|
||||
management.call_command('makemessages', locale=LOCALE, verbosity=0)
|
||||
self.assertTrue(os.path.exists(self.PO_FILE))
|
||||
po_contents = open(self.PO_FILE, 'r').read()
|
||||
self.assertTrue('#. Translators: This comment should be extracted' in po_contents)
|
||||
self.assertTrue('This comment should not be extracted' not in po_contents)
|
||||
# Comments in templates
|
||||
self.assertTrue('#. Translators: Django template comment for translators' in po_contents)
|
||||
self.assertTrue("#. Translators: Django comment block for translators\n#. string's meaning unveiled" in po_contents)
|
||||
#po_contents = open(self.PO_FILE, 'r').read()
|
||||
with open(self.PO_FILE, 'r') as fp:
|
||||
po_contents = fp.read()
|
||||
self.assertTrue('#. Translators: This comment should be extracted' in po_contents)
|
||||
self.assertTrue('This comment should not be extracted' not in po_contents)
|
||||
# Comments in templates
|
||||
self.assertTrue('#. Translators: Django template comment for translators' in po_contents)
|
||||
self.assertTrue("#. Translators: Django comment block for translators\n#. string's meaning unveiled" in po_contents)
|
||||
|
||||
self.assertTrue('#. Translators: One-line translator comment #1' in po_contents)
|
||||
self.assertTrue('#. Translators: Two-line translator comment #1\n#. continued here.' in po_contents)
|
||||
self.assertTrue('#. Translators: One-line translator comment #1' in po_contents)
|
||||
self.assertTrue('#. Translators: Two-line translator comment #1\n#. continued here.' in po_contents)
|
||||
|
||||
self.assertTrue('#. Translators: One-line translator comment #2' in po_contents)
|
||||
self.assertTrue('#. Translators: Two-line translator comment #2\n#. continued here.' in po_contents)
|
||||
self.assertTrue('#. Translators: One-line translator comment #2' in po_contents)
|
||||
self.assertTrue('#. Translators: Two-line translator comment #2\n#. continued here.' in po_contents)
|
||||
|
||||
self.assertTrue('#. Translators: One-line translator comment #3' in po_contents)
|
||||
self.assertTrue('#. Translators: Two-line translator comment #3\n#. continued here.' in po_contents)
|
||||
self.assertTrue('#. Translators: One-line translator comment #3' in po_contents)
|
||||
self.assertTrue('#. Translators: Two-line translator comment #3\n#. continued here.' in po_contents)
|
||||
|
||||
self.assertTrue('#. Translators: One-line translator comment #4' in po_contents)
|
||||
self.assertTrue('#. Translators: Two-line translator comment #4\n#. continued here.' in po_contents)
|
||||
self.assertTrue('#. Translators: One-line translator comment #4' in po_contents)
|
||||
self.assertTrue('#. Translators: Two-line translator comment #4\n#. continued here.' in po_contents)
|
||||
|
||||
self.assertTrue('#. Translators: One-line translator comment #5 -- with non ASCII characters: áéíóúö' in po_contents)
|
||||
self.assertTrue('#. Translators: Two-line translator comment #5 -- with non ASCII characters: áéíóúö\n#. continued here.' in po_contents)
|
||||
self.assertTrue('#. Translators: One-line translator comment #5 -- with non ASCII characters: áéíóúö' in po_contents)
|
||||
self.assertTrue('#. Translators: Two-line translator comment #5 -- with non ASCII characters: áéíóúö\n#. continued here.' in po_contents)
|
||||
|
||||
def test_templatize(self):
|
||||
def test_templatize_trans_tag(self):
|
||||
# ticket #11240
|
||||
os.chdir(self.test_dir)
|
||||
management.call_command('makemessages', locale=LOCALE, verbosity=0)
|
||||
self.assertTrue(os.path.exists(self.PO_FILE))
|
||||
po_contents = open(self.PO_FILE, 'r').read()
|
||||
self.assertMsgId('I think that 100%% is more that 50%% of anything.', po_contents)
|
||||
self.assertMsgId('I think that 100%% is more that 50%% of %(obj)s.', po_contents)
|
||||
#po_contents = open(self.PO_FILE, 'r').read()
|
||||
with open(self.PO_FILE, 'r') as fp:
|
||||
po_contents = fp.read()
|
||||
self.assertMsgId('Literal with a percent symbol at the end %%', po_contents)
|
||||
self.assertMsgId('Literal with a percent %% symbol in the middle', po_contents)
|
||||
self.assertMsgId('Completed 50%% of all the tasks', po_contents)
|
||||
self.assertMsgId('Completed 99%% of all the tasks', po_contents)
|
||||
self.assertMsgId("Shouldn't double escape this sequence: %% (two percent signs)", po_contents)
|
||||
self.assertMsgId("Shouldn't double escape this sequence %% either", po_contents)
|
||||
self.assertMsgId("Looks like a str fmt spec %%s but shouldn't be interpreted as such", po_contents)
|
||||
self.assertMsgId("Looks like a str fmt spec %% o but shouldn't be interpreted as such", po_contents)
|
||||
|
||||
def test_templatize_blocktrans_tag(self):
|
||||
# ticket #11966
|
||||
os.chdir(self.test_dir)
|
||||
management.call_command('makemessages', locale=LOCALE, verbosity=0)
|
||||
self.assertTrue(os.path.exists(self.PO_FILE))
|
||||
#po_contents = open(self.PO_FILE, 'r').read()
|
||||
with open(self.PO_FILE, 'r') as fp:
|
||||
po_contents = fp.read()
|
||||
self.assertMsgId('I think that 100%% is more that 50%% of anything.', po_contents)
|
||||
self.assertMsgId('I think that 100%% is more that 50%% of %(obj)s.', po_contents)
|
||||
|
||||
def test_extraction_error(self):
|
||||
os.chdir(self.test_dir)
|
||||
@@ -103,26 +128,28 @@ class BasicExtractorTests(ExtractorTests):
|
||||
os.chdir(self.test_dir)
|
||||
management.call_command('makemessages', locale=LOCALE, verbosity=0)
|
||||
self.assertTrue(os.path.exists(self.PO_FILE))
|
||||
po_contents = open(self.PO_FILE, 'r').read()
|
||||
# {% trans %}
|
||||
self.assertTrue('msgctxt "Special trans context #1"' in po_contents)
|
||||
self.assertTrue("Translatable literal #7a" in po_contents)
|
||||
self.assertTrue('msgctxt "Special trans context #2"' in po_contents)
|
||||
self.assertTrue("Translatable literal #7b" in po_contents)
|
||||
self.assertTrue('msgctxt "Special trans context #3"' in po_contents)
|
||||
self.assertTrue("Translatable literal #7c" in po_contents)
|
||||
#po_contents = open(self.PO_FILE, 'r').read()
|
||||
with open(self.PO_FILE, 'r') as fp:
|
||||
po_contents = fp.read()
|
||||
# {% trans %}
|
||||
self.assertTrue('msgctxt "Special trans context #1"' in po_contents)
|
||||
self.assertTrue("Translatable literal #7a" in po_contents)
|
||||
self.assertTrue('msgctxt "Special trans context #2"' in po_contents)
|
||||
self.assertTrue("Translatable literal #7b" in po_contents)
|
||||
self.assertTrue('msgctxt "Special trans context #3"' in po_contents)
|
||||
self.assertTrue("Translatable literal #7c" in po_contents)
|
||||
|
||||
# {% blocktrans %}
|
||||
self.assertTrue('msgctxt "Special blocktrans context #1"' in po_contents)
|
||||
self.assertTrue("Translatable literal #8a" in po_contents)
|
||||
self.assertTrue('msgctxt "Special blocktrans context #2"' in po_contents)
|
||||
self.assertTrue("Translatable literal #8b-singular" in po_contents)
|
||||
self.assertTrue("Translatable literal #8b-plural" in po_contents)
|
||||
self.assertTrue('msgctxt "Special blocktrans context #3"' in po_contents)
|
||||
self.assertTrue("Translatable literal #8c-singular" in po_contents)
|
||||
self.assertTrue("Translatable literal #8c-plural" in po_contents)
|
||||
self.assertTrue('msgctxt "Special blocktrans context #4"' in po_contents)
|
||||
self.assertTrue("Translatable literal #8d" in po_contents)
|
||||
# {% blocktrans %}
|
||||
self.assertTrue('msgctxt "Special blocktrans context #1"' in po_contents)
|
||||
self.assertTrue("Translatable literal #8a" in po_contents)
|
||||
self.assertTrue('msgctxt "Special blocktrans context #2"' in po_contents)
|
||||
self.assertTrue("Translatable literal #8b-singular" in po_contents)
|
||||
self.assertTrue("Translatable literal #8b-plural" in po_contents)
|
||||
self.assertTrue('msgctxt "Special blocktrans context #3"' in po_contents)
|
||||
self.assertTrue("Translatable literal #8c-singular" in po_contents)
|
||||
self.assertTrue("Translatable literal #8c-plural" in po_contents)
|
||||
self.assertTrue('msgctxt "Special blocktrans context #4"' in po_contents)
|
||||
self.assertTrue("Translatable literal #8d" in po_contents)
|
||||
|
||||
class JavascriptExtractorTests(ExtractorTests):
|
||||
|
||||
@@ -132,20 +159,22 @@ class JavascriptExtractorTests(ExtractorTests):
|
||||
os.chdir(self.test_dir)
|
||||
management.call_command('makemessages', domain='djangojs', locale=LOCALE, verbosity=0)
|
||||
self.assertTrue(os.path.exists(self.PO_FILE))
|
||||
po_contents = open(self.PO_FILE, 'r').read()
|
||||
self.assertMsgId('This literal should be included.', po_contents)
|
||||
self.assertMsgId('This one as well.', po_contents)
|
||||
self.assertMsgId(r'He said, \"hello\".', po_contents)
|
||||
self.assertMsgId("okkkk", po_contents)
|
||||
self.assertMsgId("TEXT", po_contents)
|
||||
self.assertMsgId("It's at http://example.com", po_contents)
|
||||
self.assertMsgId("String", po_contents)
|
||||
self.assertMsgId("/* but this one will be too */ 'cause there is no way of telling...", po_contents)
|
||||
self.assertMsgId("foo", po_contents)
|
||||
self.assertMsgId("bar", po_contents)
|
||||
self.assertMsgId("baz", po_contents)
|
||||
self.assertMsgId("quz", po_contents)
|
||||
self.assertMsgId("foobar", po_contents)
|
||||
#po_contents = open(self.PO_FILE, 'r').read()
|
||||
with open(self.PO_FILE, 'r') as fp:
|
||||
po_contents = fp.read()
|
||||
self.assertMsgId('This literal should be included.', po_contents)
|
||||
self.assertMsgId('This one as well.', po_contents)
|
||||
self.assertMsgId(r'He said, \"hello\".', po_contents)
|
||||
self.assertMsgId("okkkk", po_contents)
|
||||
self.assertMsgId("TEXT", po_contents)
|
||||
self.assertMsgId("It's at http://example.com", po_contents)
|
||||
self.assertMsgId("String", po_contents)
|
||||
self.assertMsgId("/* but this one will be too */ 'cause there is no way of telling...", po_contents)
|
||||
self.assertMsgId("foo", po_contents)
|
||||
self.assertMsgId("bar", po_contents)
|
||||
self.assertMsgId("baz", po_contents)
|
||||
self.assertMsgId("quz", po_contents)
|
||||
self.assertMsgId("foobar", po_contents)
|
||||
|
||||
class IgnoredExtractorTests(ExtractorTests):
|
||||
|
||||
@@ -154,9 +183,11 @@ class IgnoredExtractorTests(ExtractorTests):
|
||||
pattern1 = os.path.join('ignore_dir', '*')
|
||||
management.call_command('makemessages', locale=LOCALE, verbosity=0, ignore_patterns=[pattern1])
|
||||
self.assertTrue(os.path.exists(self.PO_FILE))
|
||||
po_contents = open(self.PO_FILE, 'r').read()
|
||||
self.assertMsgId('This literal should be included.', po_contents)
|
||||
self.assertNotMsgId('This should be ignored.', po_contents)
|
||||
#po_contents = open(self.PO_FILE, 'r').read()
|
||||
with open(self.PO_FILE, 'r') as fp:
|
||||
po_contents = fp.read()
|
||||
self.assertMsgId('This literal should be included.', po_contents)
|
||||
self.assertNotMsgId('This should be ignored.', po_contents)
|
||||
|
||||
|
||||
class SymlinkExtractorTests(ExtractorTests):
|
||||
@@ -184,9 +215,11 @@ class SymlinkExtractorTests(ExtractorTests):
|
||||
os.chdir(self.test_dir)
|
||||
management.call_command('makemessages', locale=LOCALE, verbosity=0, symlinks=True)
|
||||
self.assertTrue(os.path.exists(self.PO_FILE))
|
||||
po_contents = open(self.PO_FILE, 'r').read()
|
||||
self.assertMsgId('This literal should be included.', po_contents)
|
||||
self.assertTrue('templates_symlinked/test.html' in po_contents)
|
||||
#po_contents = open(self.PO_FILE, 'r').read()
|
||||
with open(self.PO_FILE, 'r') as fp:
|
||||
po_contents = fp.read()
|
||||
self.assertMsgId('This literal should be included.', po_contents)
|
||||
self.assertTrue('templates_symlinked/test.html' in po_contents)
|
||||
|
||||
|
||||
class CopyPluralFormsExtractorTests(ExtractorTests):
|
||||
@@ -195,8 +228,10 @@ class CopyPluralFormsExtractorTests(ExtractorTests):
|
||||
os.chdir(self.test_dir)
|
||||
management.call_command('makemessages', locale=LOCALE, verbosity=0)
|
||||
self.assertTrue(os.path.exists(self.PO_FILE))
|
||||
po_contents = open(self.PO_FILE, 'r').read()
|
||||
self.assertTrue('Plural-Forms: nplurals=2; plural=(n != 1)' in po_contents)
|
||||
#po_contents = open(self.PO_FILE, 'r').read()
|
||||
with open(self.PO_FILE, 'r') as fp:
|
||||
po_contents = fp.read()
|
||||
self.assertTrue('Plural-Forms: nplurals=2; plural=(n != 1)' in po_contents)
|
||||
|
||||
|
||||
class NoWrapExtractorTests(ExtractorTests):
|
||||
@@ -205,15 +240,19 @@ class NoWrapExtractorTests(ExtractorTests):
|
||||
os.chdir(self.test_dir)
|
||||
management.call_command('makemessages', locale=LOCALE, verbosity=0, no_wrap=True)
|
||||
self.assertTrue(os.path.exists(self.PO_FILE))
|
||||
po_contents = open(self.PO_FILE, 'r').read()
|
||||
self.assertMsgId('This literal should also be included wrapped or not wrapped depending on the use of the --no-wrap option.', po_contents)
|
||||
#po_contents = open(self.PO_FILE, 'r').read()
|
||||
with open(self.PO_FILE, 'r') as fp:
|
||||
po_contents = fp.read()
|
||||
self.assertMsgId('This literal should also be included wrapped or not wrapped depending on the use of the --no-wrap option.', po_contents)
|
||||
|
||||
def test_no_wrap_disabled(self):
|
||||
os.chdir(self.test_dir)
|
||||
management.call_command('makemessages', locale=LOCALE, verbosity=0, no_wrap=False)
|
||||
self.assertTrue(os.path.exists(self.PO_FILE))
|
||||
po_contents = open(self.PO_FILE, 'r').read()
|
||||
self.assertMsgId('""\n"This literal should also be included wrapped or not wrapped depending on the "\n"use of the --no-wrap option."', po_contents, use_quotes=False)
|
||||
#po_contents = open(self.PO_FILE, 'r').read()
|
||||
with open(self.PO_FILE, 'r') as fp:
|
||||
po_contents = fp.read()
|
||||
self.assertMsgId('""\n"This literal should also be included wrapped or not wrapped depending on the "\n"use of the --no-wrap option."', po_contents, use_quotes=False)
|
||||
|
||||
|
||||
class NoLocationExtractorTests(ExtractorTests):
|
||||
@@ -222,12 +261,16 @@ class NoLocationExtractorTests(ExtractorTests):
|
||||
os.chdir(self.test_dir)
|
||||
management.call_command('makemessages', locale=LOCALE, verbosity=0, no_location=True)
|
||||
self.assertTrue(os.path.exists(self.PO_FILE))
|
||||
po_contents = open(self.PO_FILE, 'r').read()
|
||||
self.assertFalse('#: templates/test.html:55' in po_contents)
|
||||
#po_contents = open(self.PO_FILE, 'r').read()
|
||||
with open(self.PO_FILE, 'r') as fp:
|
||||
po_contents = fp.read()
|
||||
self.assertFalse('#: templates/test.html:55' in po_contents)
|
||||
|
||||
def test_no_location_disabled(self):
|
||||
os.chdir(self.test_dir)
|
||||
management.call_command('makemessages', locale=LOCALE, verbosity=0, no_location=False)
|
||||
self.assertTrue(os.path.exists(self.PO_FILE))
|
||||
po_contents = open(self.PO_FILE, 'r').read()
|
||||
self.assertTrue('#: templates/test.html:55' in po_contents)
|
||||
#po_contents = open(self.PO_FILE, 'r').read()
|
||||
with open(self.PO_FILE, 'r') as fp:
|
||||
po_contents = fp.read()
|
||||
self.assertTrue('#: templates/test.html:55' in po_contents)
|
||||
|
||||
Reference in New Issue
Block a user