diff --git a/django/core/management/commands/makemessages.py b/django/core/management/commands/makemessages.py index 2c514884ba..000ed0a8fa 100644 --- a/django/core/management/commands/makemessages.py +++ b/django/core/management/commands/makemessages.py @@ -11,6 +11,7 @@ from django.core.management.base import CommandError, BaseCommand from django.utils.text import get_text_list pythonize_re = re.compile(r'(?:^|\n)\s*//') +plural_forms_re = re.compile(r'^(?P"Plural-Forms.+?\\n")\s*$', re.MULTILINE | re.DOTALL) def handle_extensions(extensions=('html',)): """ @@ -82,6 +83,37 @@ def find_files(root, ignore_patterns, verbosity, symlinks=False): all_files.sort() return all_files +def copy_plural_forms(msgs, locale, domain, verbosity): + """ + Copies plural forms header contents from a Django catalog of locale to + the msgs string, inserting it at the right place. msgs should be the + contents of a newly created .po file. + """ + import django + django_dir = os.path.normpath(os.path.join(os.path.dirname(django.__file__))) + if domain == 'djangojs': + domains = ('djangojs', 'django') + else: + domains = ('django',) + for domain in domains: + django_po = os.path.join(django_dir, 'conf', 'locale', locale, 'LC_MESSAGES', '%s.po' % domain) + if os.path.exists(django_po): + m = plural_forms_re.search(open(django_po, 'rU').read()) + if m: + if verbosity > 1: + sys.stderr.write("copying plural forms: %s\n" % m.group('value')) + lines = [] + seen = False + for line in msgs.split('\n'): + if not line and not seen: + line = '%s\n' % m.group('value') + seen = True + lines.append(line) + msgs = '\n'.join(lines) + break + return msgs + + def make_messages(locale=None, domain='django', verbosity='1', all=False, extensions=None, symlinks=False, ignore_patterns=[]): """ @@ -97,8 +129,10 @@ def make_messages(locale=None, domain='django', verbosity='1', all=False, from django.utils.translation import templatize + invoked_for_django = False if os.path.isdir(os.path.join('conf', 'locale')): localedir = os.path.abspath(os.path.join('conf', 'locale')) + invoked_for_django = True elif os.path.isdir('locale'): localedir = os.path.abspath('locale') else: @@ -208,6 +242,8 @@ def make_messages(locale=None, domain='django', verbosity='1', all=False, msgs, errors = _popen('msgmerge -q "%s" "%s"' % (pofile, potfile)) if errors: raise CommandError("errors happened while running msgmerge\n%s" % errors) + elif not invoked_for_django: + msgs = copy_plural_forms(msgs, locale, domain, verbosity) open(pofile, 'wb').write(msgs) os.unlink(potfile) diff --git a/tests/regressiontests/makemessages/tests.py b/tests/regressiontests/makemessages/tests.py index 4be31a717b..4b4fa1b07e 100644 --- a/tests/regressiontests/makemessages/tests.py +++ b/tests/regressiontests/makemessages/tests.py @@ -8,6 +8,8 @@ LOCALE='de' class ExtractorTests(TestCase): + PO_FILE='locale/%s/LC_MESSAGES/django.po' % LOCALE + def setUp(self): self._cwd = os.getcwd() self.test_dir = os.path.abspath(os.path.dirname(__file__)) @@ -47,8 +49,6 @@ class JavascriptExtractorTests(ExtractorTests): class IgnoredExtractorTests(ExtractorTests): - PO_FILE='locale/%s/LC_MESSAGES/django.po' % LOCALE - def test_ignore_option(self): os.chdir(self.test_dir) management.call_command('makemessages', locale=LOCALE, verbosity=0, ignore_patterns=['ignore_dir/*']) @@ -60,8 +60,6 @@ class IgnoredExtractorTests(ExtractorTests): class SymlinkExtractorTests(ExtractorTests): - PO_FILE='locale/%s/LC_MESSAGES/django.po' % LOCALE - def setUp(self): self._cwd = os.getcwd() self.test_dir = os.path.abspath(os.path.dirname(__file__)) @@ -88,3 +86,13 @@ class SymlinkExtractorTests(ExtractorTests): po_contents = open(self.PO_FILE, 'r').read() self.assertMsgId('This literal should be included.', po_contents) self.assert_('templates_symlinked/test.html' in po_contents) + + +class CopyPluralFormsExtractorTests(ExtractorTests): + + def test_copy_plural_forms(self): + os.chdir(self.test_dir) + management.call_command('makemessages', locale=LOCALE, verbosity=0) + self.assert_(os.path.exists(self.PO_FILE)) + po_contents = open(self.PO_FILE, 'r').read() + self.assert_('Plural-Forms: nplurals=2; plural=(n != 1)' in po_contents)