diff --git a/django/core/management/commands/makemessages.py b/django/core/management/commands/makemessages.py index 060def5d5a..695cad419b 100644 --- a/django/core/management/commands/makemessages.py +++ b/django/core/management/commands/makemessages.py @@ -402,11 +402,11 @@ class Command(NoArgsCommand): if self.verbosity > 1: self.stdout.write("copying plural forms: %s\n" % m.group('value')) lines = [] - seen = False + found = False for line in msgs.split('\n'): - if not line and not seen: + if not found and (not line or plural_forms_re.search(line)): line = '%s\n' % m.group('value') - seen = True + found = True lines.append(line) msgs = '\n'.join(lines) break diff --git a/tests/i18n/commands/__init__.py b/tests/i18n/commands/__init__.py index ffd439140e..76249ca34d 100644 --- a/tests/i18n/commands/__init__.py +++ b/tests/i18n/commands/__init__.py @@ -1,4 +1,4 @@ -from django.utils.translation import ugettext as _ +from django.utils.translation import ugettext as _, ungettext # Translators: This comment should be extracted dummy1 = _("This is a translatable string.") @@ -6,3 +6,7 @@ dummy1 = _("This is a translatable string.") # This comment should not be extracted dummy2 = _("This is another translatable string.") +# This file has a literal with plural forms. When processed first, makemessages +# shouldn't create a .po file with duplicate `Plural-Forms` headers +number = 3 +dummuy3 = ungettext("%(number)s Foo", "%(number)s Foos", number) % {'number': number} diff --git a/tests/i18n/commands/extraction.py b/tests/i18n/commands/extraction.py index 8696ae453b..dd1dce2ed0 100644 --- a/tests/i18n/commands/extraction.py +++ b/tests/i18n/commands/extraction.py @@ -329,6 +329,15 @@ class SymlinkExtractorTests(ExtractorTests): class CopyPluralFormsExtractorTests(ExtractorTests): + PO_FILE_ES = 'locale/es/LC_MESSAGES/django.po' + + def tearDown(self): + os.chdir(self.test_dir) + try: + self._rmrf('locale/es') + except OSError: + pass + os.chdir(self._cwd) def test_copy_plural_forms(self): os.chdir(self.test_dir) @@ -338,6 +347,16 @@ class CopyPluralFormsExtractorTests(ExtractorTests): po_contents = force_text(fp.read()) self.assertTrue('Plural-Forms: nplurals=2; plural=(n != 1)' in po_contents) + def test_override_plural_forms(self): + """Ticket #20311.""" + os.chdir(self.test_dir) + management.call_command('makemessages', locale='es', extensions=['djtpl'], verbosity=0) + self.assertTrue(os.path.exists(self.PO_FILE_ES)) + with open(self.PO_FILE_ES, 'r') as fp: + po_contents = force_text(fp.read()) + found = re.findall(r'^(?P"Plural-Forms.+?\\n")\s*$', po_contents, re.MULTILINE | re.DOTALL) + self.assertEqual(1, len(found)) + class NoWrapExtractorTests(ExtractorTests): diff --git a/tests/i18n/commands/templates/plural.djtpl b/tests/i18n/commands/templates/plural.djtpl new file mode 100644 index 0000000000..b2f2a18750 --- /dev/null +++ b/tests/i18n/commands/templates/plural.djtpl @@ -0,0 +1,6 @@ +{% load i18n %} +{% comment %} +This file has a literal with plural forms. When processed first, makemessages +shouldn't create a .po file with duplicate `Plural-Forms` headers +{% endcomment %} +{% blocktrans count number=3 %}{{ number }} Bar{% plural %}{{ number }} Bars{% endblocktrans %}