From eee865257aaa9005947a7b4994c475c2ad59d698 Mon Sep 17 00:00:00 2001 From: Ramiro Morales Date: Wed, 16 Jan 2013 15:36:22 -0300 Subject: [PATCH] Fixed #17008 -- Added makemessages option to not remove .pot files. Thanks airstrike for the report and initial patch, Julien for an enhanced patch and Jannis for reviewing. --- .../core/management/commands/makemessages.py | 33 ++++++++++++------- docs/ref/django-admin.txt | 8 +++++ .../i18n/commands/extraction.py | 33 +++++++++++++++++++ tests/regressiontests/i18n/tests.py | 2 +- 4 files changed, 63 insertions(+), 13 deletions(-) diff --git a/django/core/management/commands/makemessages.py b/django/core/management/commands/makemessages.py index 606cbe0b85..449d3d7c5a 100644 --- a/django/core/management/commands/makemessages.py +++ b/django/core/management/commands/makemessages.py @@ -126,7 +126,7 @@ def write_pot_file(potfile, msgs, file, work_file, is_templatized): fp.write(msgs) def process_file(file, dirpath, potfile, domain, verbosity, - extensions, wrap, location, stdout=sys.stdout): + extensions, wrap, location, keep_pot, stdout=sys.stdout): """ Extract translatable literals from :param file: for :param domain: creating or updating the :param potfile: POT file. @@ -183,7 +183,7 @@ def process_file(file, dirpath, potfile, domain, verbosity, if status != STATUS_OK: if is_templatized: os.unlink(work_file) - if os.path.exists(potfile): + if not keep_pot and os.path.exists(potfile): os.unlink(potfile) raise CommandError( "errors happened while running xgettext on %s\n%s" % @@ -197,7 +197,7 @@ def process_file(file, dirpath, potfile, domain, verbosity, os.unlink(work_file) def write_po_file(pofile, potfile, domain, locale, verbosity, stdout, - copy_pforms, wrap, location, no_obsolete): + copy_pforms, wrap, location, no_obsolete, keep_pot): """ Creates of updates the :param pofile: PO file for :param domain: and :param locale:. Uses contents of the existing :param potfile:. @@ -208,7 +208,8 @@ def write_po_file(pofile, potfile, domain, locale, verbosity, stdout, (wrap, location, potfile)) if errors: if status != STATUS_OK: - os.unlink(potfile) + if not keep_pot: + os.unlink(potfile) raise CommandError( "errors happened while running msguniq\n%s" % errors) elif verbosity > 0: @@ -221,7 +222,8 @@ def write_po_file(pofile, potfile, domain, locale, verbosity, stdout, (wrap, location, pofile, potfile)) if errors: if status != STATUS_OK: - os.unlink(potfile) + if not keep_pot: + os.unlink(potfile) raise CommandError( "errors happened while running msgmerge\n%s" % errors) elif verbosity > 0: @@ -232,7 +234,8 @@ def write_po_file(pofile, potfile, domain, locale, verbosity, stdout, "#. #-#-#-#-# %s.pot (PACKAGE VERSION) #-#-#-#-#\n" % domain, "") with open(pofile, 'w') as fp: fp.write(msgs) - os.unlink(potfile) + if not keep_pot: + os.unlink(potfile) if no_obsolete: msgs, errors, status = _popen( 'msgattrib %s %s -o "%s" --no-obsolete "%s"' % @@ -246,7 +249,7 @@ def write_po_file(pofile, potfile, domain, locale, verbosity, stdout, def make_messages(locale=None, domain='django', verbosity=1, all=False, extensions=None, symlinks=False, ignore_patterns=None, no_wrap=False, - no_location=False, no_obsolete=False, stdout=sys.stdout): + no_location=False, no_obsolete=False, stdout=sys.stdout, keep_pot=False): """ Uses the ``locale/`` directory from the Django Git tree or an application/project to process all files with translatable literals for @@ -280,10 +283,12 @@ def make_messages(locale=None, domain='django', verbosity=1, all=False, "if you want to enable i18n for your project or application.") if domain not in ('django', 'djangojs'): - raise CommandError("currently makemessages only supports domains 'django' and 'djangojs'") + raise CommandError("currently makemessages only supports domains " + "'django' and 'djangojs'") if (locale is None and not all) or domain is None: - message = "Type '%s help %s' for usage information." % (os.path.basename(sys.argv[0]), sys.argv[1]) + message = "Type '%s help %s' for usage information." % ( + os.path.basename(sys.argv[0]), sys.argv[1]) raise CommandError(message) # We require gettext version 0.15 or newer. @@ -325,11 +330,11 @@ def make_messages(locale=None, domain='django', verbosity=1, all=False, for dirpath, file in find_files(".", ignore_patterns, verbosity, stdout, symlinks=symlinks): process_file(file, dirpath, potfile, domain, verbosity, extensions, - wrap, location, stdout) + wrap, location, keep_pot, stdout) if os.path.exists(potfile): write_po_file(pofile, potfile, domain, locale, verbosity, stdout, - not invoked_for_django, wrap, location, no_obsolete) + not invoked_for_django, wrap, location, no_obsolete, keep_pot) class Command(NoArgsCommand): @@ -355,6 +360,8 @@ class Command(NoArgsCommand): default=False, help="Don't write '#: filename:line' lines"), make_option('--no-obsolete', action='store_true', dest='no_obsolete', default=False, help="Remove obsolete message strings"), + make_option('--keep-pot', action='store_true', dest='keep_pot', + default=False, help="Keep .pot file after making messages. Useful when debugging."), ) help = ("Runs over the entire source tree of the current directory and " "pulls out all strings marked for translation. It creates (or updates) a message " @@ -379,6 +386,7 @@ class Command(NoArgsCommand): no_wrap = options.get('no_wrap') no_location = options.get('no_location') no_obsolete = options.get('no_obsolete') + keep_pot = options.get('keep_pot') if domain == 'djangojs': exts = extensions if extensions else ['js'] else: @@ -390,4 +398,5 @@ class Command(NoArgsCommand): % get_text_list(list(extensions), 'and')) make_messages(locale, domain, verbosity, process_all, extensions, - symlinks, ignore_patterns, no_wrap, no_location, no_obsolete, self.stdout) + symlinks, ignore_patterns, no_wrap, no_location, + no_obsolete, self.stdout, keep_pot) diff --git a/docs/ref/django-admin.txt b/docs/ref/django-admin.txt index 8d612ae6a6..3c73e268e2 100644 --- a/docs/ref/django-admin.txt +++ b/docs/ref/django-admin.txt @@ -472,6 +472,14 @@ Use the ``--no-location`` option to not write '``#: filename:line``' comment lines in language files. Note that using this option makes it harder for technically skilled translators to understand each message's context. +.. django-admin-option:: --keep-pot + +.. versionadded:: 1.6 + +Use the ``--keep-pot`` option to prevent django from deleting the temporary +.pot file it generates before creating the .po file. This is useful for +debugging errors which may prevent the final language files from being created. + runfcgi [options] ----------------- diff --git a/tests/regressiontests/i18n/commands/extraction.py b/tests/regressiontests/i18n/commands/extraction.py index aa5efe1967..bd2b84a952 100644 --- a/tests/regressiontests/i18n/commands/extraction.py +++ b/tests/regressiontests/i18n/commands/extraction.py @@ -293,3 +293,36 @@ class NoLocationExtractorTests(ExtractorTests): with open(self.PO_FILE, 'r') as fp: po_contents = force_text(fp.read()) self.assertTrue('#: templates/test.html:55' in po_contents) + + +class KeepPotFileExtractorTests(ExtractorTests): + + def setUp(self): + self.POT_FILE = self.PO_FILE + 't' + super(KeepPotFileExtractorTests, self).setUp() + + def tearDown(self): + super(KeepPotFileExtractorTests, self).tearDown() + os.chdir(self.test_dir) + try: + os.unlink(self.POT_FILE) + except OSError: + pass + os.chdir(self._cwd) + + def test_keep_pot_disabled_by_default(self): + os.chdir(self.test_dir) + management.call_command('makemessages', locale=LOCALE, verbosity=0) + self.assertFalse(os.path.exists(self.POT_FILE)) + + def test_keep_pot_explicitly_disabled(self): + os.chdir(self.test_dir) + management.call_command('makemessages', locale=LOCALE, verbosity=0, + keep_pot=False) + self.assertFalse(os.path.exists(self.POT_FILE)) + + def test_keep_pot_enabled(self): + os.chdir(self.test_dir) + management.call_command('makemessages', locale=LOCALE, verbosity=0, + keep_pot=True) + self.assertTrue(os.path.exists(self.POT_FILE)) diff --git a/tests/regressiontests/i18n/tests.py b/tests/regressiontests/i18n/tests.py index 44d84f9143..5d789b4acb 100644 --- a/tests/regressiontests/i18n/tests.py +++ b/tests/regressiontests/i18n/tests.py @@ -32,7 +32,7 @@ if can_run_extraction_tests: from .commands.extraction import (ExtractorTests, BasicExtractorTests, JavascriptExtractorTests, IgnoredExtractorTests, SymlinkExtractorTests, CopyPluralFormsExtractorTests, NoWrapExtractorTests, - NoLocationExtractorTests) + NoLocationExtractorTests, KeepPotFileExtractorTests) if can_run_compilation_tests: from .commands.compilation import (PoFileTests, PoFileContentsTests, PercentRenderingTests)