Fixed #22328 -- Added --exclude option to compilemessages and makemessages.
This commit is contained in:
parent
d1f93e9c1e
commit
0707b824fe
1
AUTHORS
1
AUTHORS
|
@ -367,6 +367,7 @@ answer newbie questions, and generally made Django that much better:
|
||||||
Martin Kosír <martin@martinkosir.net>
|
Martin Kosír <martin@martinkosir.net>
|
||||||
Arthur Koziel <http://arthurkoziel.com>
|
Arthur Koziel <http://arthurkoziel.com>
|
||||||
Meir Kriheli <http://mksoft.co.il/>
|
Meir Kriheli <http://mksoft.co.il/>
|
||||||
|
Ana Krivokapic <https://github.com/infraredgirl>
|
||||||
Bruce Kroeze <http://coderseye.com/>
|
Bruce Kroeze <http://coderseye.com/>
|
||||||
krzysiek.pawlik@silvermedia.pl
|
krzysiek.pawlik@silvermedia.pl
|
||||||
konrad@gwu.edu
|
konrad@gwu.edu
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import codecs
|
import codecs
|
||||||
|
import glob
|
||||||
import os
|
import os
|
||||||
from optparse import make_option
|
from optparse import make_option
|
||||||
|
|
||||||
|
@ -30,8 +31,11 @@ def is_writable(path):
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
option_list = BaseCommand.option_list + (
|
option_list = BaseCommand.option_list + (
|
||||||
make_option('--locale', '-l', dest='locale', action='append',
|
make_option('--locale', '-l', dest='locale', action='append', default=[],
|
||||||
help='locale(s) to process (e.g. de_AT). Default is to process all. Can be used multiple times.'),
|
help='Locale(s) to process (e.g. de_AT). Default is to process all. Can be '
|
||||||
|
'used multiple times.'),
|
||||||
|
make_option('--exclude', '-e', dest='exclude', action='append', default=[],
|
||||||
|
help='Locales to exclude. Default is none. Can be used multiple times.'),
|
||||||
)
|
)
|
||||||
help = 'Compiles .po files to .mo files for use with builtin gettext support.'
|
help = 'Compiles .po files to .mo files for use with builtin gettext support.'
|
||||||
|
|
||||||
|
@ -43,6 +47,7 @@ class Command(BaseCommand):
|
||||||
|
|
||||||
def handle(self, **options):
|
def handle(self, **options):
|
||||||
locale = options.get('locale')
|
locale = options.get('locale')
|
||||||
|
exclude = options.get('exclude')
|
||||||
self.verbosity = int(options.get('verbosity'))
|
self.verbosity = int(options.get('verbosity'))
|
||||||
|
|
||||||
if find_command(self.program) is None:
|
if find_command(self.program) is None:
|
||||||
|
@ -62,9 +67,19 @@ class Command(BaseCommand):
|
||||||
"checkout or your project or app tree, or with "
|
"checkout or your project or app tree, or with "
|
||||||
"the settings module specified.")
|
"the settings module specified.")
|
||||||
|
|
||||||
|
# Build locale list
|
||||||
|
all_locales = []
|
||||||
for basedir in basedirs:
|
for basedir in basedirs:
|
||||||
if locale:
|
locale_dirs = filter(os.path.isdir, glob.glob('%s/*' % basedir))
|
||||||
dirs = [os.path.join(basedir, l, 'LC_MESSAGES') for l in locale]
|
all_locales.extend(map(os.path.basename, locale_dirs))
|
||||||
|
|
||||||
|
# Account for excluded locales
|
||||||
|
locales = locale or all_locales
|
||||||
|
locales = set(locales) - set(exclude)
|
||||||
|
|
||||||
|
for basedir in basedirs:
|
||||||
|
if locales:
|
||||||
|
dirs = [os.path.join(basedir, l, 'LC_MESSAGES') for l in locales]
|
||||||
else:
|
else:
|
||||||
dirs = [basedir]
|
dirs = [basedir]
|
||||||
locations = []
|
locations = []
|
||||||
|
@ -90,8 +105,8 @@ class Command(BaseCommand):
|
||||||
|
|
||||||
# Check writability on first location
|
# Check writability on first location
|
||||||
if i == 0 and not is_writable(npath(base_path + '.mo')):
|
if i == 0 and not is_writable(npath(base_path + '.mo')):
|
||||||
self.stderr.write("The po files under %s are in a seemingly not "
|
self.stderr.write("The po files under %s are in a seemingly not writable location. "
|
||||||
"writable location. mo files will not be updated/created." % dirpath)
|
"mo files will not be updated/created." % dirpath)
|
||||||
return
|
return
|
||||||
|
|
||||||
args = [self.program] + self.program_options + ['-o',
|
args = [self.program] + self.program_options + ['-o',
|
||||||
|
|
|
@ -160,9 +160,11 @@ def write_pot_file(potfile, msgs):
|
||||||
|
|
||||||
class Command(NoArgsCommand):
|
class Command(NoArgsCommand):
|
||||||
option_list = NoArgsCommand.option_list + (
|
option_list = NoArgsCommand.option_list + (
|
||||||
make_option('--locale', '-l', default=None, dest='locale', action='append',
|
make_option('--locale', '-l', default=[], dest='locale', action='append',
|
||||||
help='Creates or updates the message files for the given locale(s) (e.g. pt_BR). '
|
help='Creates or updates the message files for the given locale(s) (e.g. pt_BR). '
|
||||||
'Can be used multiple times.'),
|
'Can be used multiple times.'),
|
||||||
|
make_option('--exclude', '-e', default=[], dest='exclude', action='append',
|
||||||
|
help='Locales to exclude. Default is none. Can be used multiple times.'),
|
||||||
make_option('--domain', '-d', default='django', dest='domain',
|
make_option('--domain', '-d', default='django', dest='domain',
|
||||||
help='The domain of the message files (default: "django").'),
|
help='The domain of the message files (default: "django").'),
|
||||||
make_option('--all', '-a', action='store_true', dest='all',
|
make_option('--all', '-a', action='store_true', dest='all',
|
||||||
|
@ -189,7 +191,7 @@ class Command(NoArgsCommand):
|
||||||
"pulls out all strings marked for translation. It creates (or updates) a message "
|
"pulls out all strings marked for translation. It creates (or updates) a message "
|
||||||
"file in the conf/locale (in the django tree) or locale (for projects and "
|
"file in the conf/locale (in the django tree) or locale (for projects and "
|
||||||
"applications) directory.\n\nYou must run this command with one of either the "
|
"applications) directory.\n\nYou must run this command with one of either the "
|
||||||
"--locale or --all options.")
|
"--locale, --exclude or --all options.")
|
||||||
|
|
||||||
requires_system_checks = False
|
requires_system_checks = False
|
||||||
leave_locale_alone = True
|
leave_locale_alone = True
|
||||||
|
@ -201,6 +203,7 @@ class Command(NoArgsCommand):
|
||||||
|
|
||||||
def handle_noargs(self, *args, **options):
|
def handle_noargs(self, *args, **options):
|
||||||
locale = options.get('locale')
|
locale = options.get('locale')
|
||||||
|
exclude = options.get('exclude')
|
||||||
self.domain = options.get('domain')
|
self.domain = options.get('domain')
|
||||||
self.verbosity = int(options.get('verbosity'))
|
self.verbosity = int(options.get('verbosity'))
|
||||||
process_all = options.get('all')
|
process_all = options.get('all')
|
||||||
|
@ -235,7 +238,7 @@ class Command(NoArgsCommand):
|
||||||
exts = extensions if extensions else ['html', 'txt']
|
exts = extensions if extensions else ['html', 'txt']
|
||||||
self.extensions = handle_extensions(exts)
|
self.extensions = handle_extensions(exts)
|
||||||
|
|
||||||
if (locale is None and not process_all) or self.domain is None:
|
if (locale is None and not exclude and not process_all) or self.domain is None:
|
||||||
raise CommandError("Type '%s help %s' for usage information." % (
|
raise CommandError("Type '%s help %s' for usage information." % (
|
||||||
os.path.basename(sys.argv[0]), sys.argv[1]))
|
os.path.basename(sys.argv[0]), sys.argv[1]))
|
||||||
|
|
||||||
|
@ -270,12 +273,16 @@ class Command(NoArgsCommand):
|
||||||
os.makedirs(self.default_locale_path)
|
os.makedirs(self.default_locale_path)
|
||||||
|
|
||||||
# Build locale list
|
# Build locale list
|
||||||
locales = []
|
|
||||||
if locale is not None:
|
|
||||||
locales = locale
|
|
||||||
elif process_all:
|
|
||||||
locale_dirs = filter(os.path.isdir, glob.glob('%s/*' % self.default_locale_path))
|
locale_dirs = filter(os.path.isdir, glob.glob('%s/*' % self.default_locale_path))
|
||||||
locales = [os.path.basename(l) for l in locale_dirs]
|
all_locales = map(os.path.basename, locale_dirs)
|
||||||
|
|
||||||
|
# Account for excluded locales
|
||||||
|
if process_all:
|
||||||
|
locales = all_locales
|
||||||
|
else:
|
||||||
|
locales = locale or all_locales
|
||||||
|
locales = set(locales) - set(exclude)
|
||||||
|
|
||||||
if locales:
|
if locales:
|
||||||
check_programs('msguniq', 'msgmerge', 'msgattrib')
|
check_programs('msguniq', 'msgmerge', 'msgattrib')
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ script found at the top level of each Django project directory.
|
||||||
.BI cleanup
|
.BI cleanup
|
||||||
Cleans out old data from the database (only expired sessions at the moment).
|
Cleans out old data from the database (only expired sessions at the moment).
|
||||||
.TP
|
.TP
|
||||||
.BI "compilemessages [" "\-\-locale=LOCALE" "]"
|
.BI "compilemessages [" "\-\-locale=LOCALE" "] [" "\-\-exclude=LOCALE" "]"
|
||||||
Compiles .po files to .mo files for use with builtin gettext support.
|
Compiles .po files to .mo files for use with builtin gettext support.
|
||||||
.TP
|
.TP
|
||||||
.BI "createcachetable [" "tablename" "]"
|
.BI "createcachetable [" "tablename" "]"
|
||||||
|
@ -59,7 +59,7 @@ Executes
|
||||||
.B sqlall
|
.B sqlall
|
||||||
for the given app(s) in the current database.
|
for the given app(s) in the current database.
|
||||||
.TP
|
.TP
|
||||||
.BI "makemessages [" "\-\-locale=LOCALE" "] [" "\-\-domain=DOMAIN" "] [" "\-\-extension=EXTENSION" "] [" "\-\-all" "] [" "\-\-symlinks" "] [" "\-\-ignore=PATTERN" "] [" "\-\-no\-default\-ignore" "] [" "\-\-no\-wrap" "] [" "\-\-no\-location" "]"
|
.BI "makemessages [" "\-\-locale=LOCALE" "] [" "\-\-exclude=LOCALE" "] [" "\-\-domain=DOMAIN" "] [" "\-\-extension=EXTENSION" "] [" "\-\-all" "] [" "\-\-symlinks" "] [" "\-\-ignore=PATTERN" "] [" "\-\-no\-default\-ignore" "] [" "\-\-no\-wrap" "] [" "\-\-no\-location" "]"
|
||||||
Runs over the entire source tree of the current directory and pulls out all
|
Runs over the entire source tree of the current directory and pulls out all
|
||||||
strings marked for translation. It creates (or updates) a message file in the
|
strings marked for translation. It creates (or updates) a message file in the
|
||||||
conf/locale (in the django tree) or locale (for project and application) directory.
|
conf/locale (in the django tree) or locale (for project and application) directory.
|
||||||
|
@ -176,6 +176,9 @@ output a full stack trace whenever an exception is raised.
|
||||||
.I \-l, \-\-locale=LOCALE
|
.I \-l, \-\-locale=LOCALE
|
||||||
The locale to process when using makemessages or compilemessages.
|
The locale to process when using makemessages or compilemessages.
|
||||||
.TP
|
.TP
|
||||||
|
.I \-e, \-\-exclude=LOCALE
|
||||||
|
The locale to exclude from processing when using makemessages or compilemessages.
|
||||||
|
.TP
|
||||||
.I \-d, \-\-domain=DOMAIN
|
.I \-d, \-\-domain=DOMAIN
|
||||||
The domain of the message files (default: "django") when using makemessages.
|
The domain of the message files (default: "django") when using makemessages.
|
||||||
.TP
|
.TP
|
||||||
|
|
|
@ -141,12 +141,22 @@ the builtin gettext support. See :doc:`/topics/i18n/index`.
|
||||||
Use the :djadminopt:`--locale` option (or its shorter version ``-l``) to
|
Use the :djadminopt:`--locale` option (or its shorter version ``-l``) to
|
||||||
specify the locale(s) to process. If not provided, all locales are processed.
|
specify the locale(s) to process. If not provided, all locales are processed.
|
||||||
|
|
||||||
|
.. versionadded:: 1.8
|
||||||
|
|
||||||
|
Use the :djadminopt:`--exclude` option (or its shorter version ``-e``) to
|
||||||
|
specify the locale(s) to exclude from processing. If not provided, no locales
|
||||||
|
are excluded.
|
||||||
|
|
||||||
Example usage::
|
Example usage::
|
||||||
|
|
||||||
django-admin.py compilemessages --locale=pt_BR
|
django-admin.py compilemessages --locale=pt_BR
|
||||||
django-admin.py compilemessages --locale=pt_BR --locale=fr
|
django-admin.py compilemessages --locale=pt_BR --locale=fr
|
||||||
django-admin.py compilemessages -l pt_BR
|
django-admin.py compilemessages -l pt_BR
|
||||||
django-admin.py compilemessages -l pt_BR -l fr
|
django-admin.py compilemessages -l pt_BR -l fr
|
||||||
|
django-admin.py compilemessages --exclude=pt_BR
|
||||||
|
django-admin.py compilemessages --exclude=pt_BR --exclude=fr
|
||||||
|
django-admin.py compilemessages -e pt_BR
|
||||||
|
django-admin.py compilemessages -e pt_BR -e fr
|
||||||
|
|
||||||
createcachetable
|
createcachetable
|
||||||
----------------
|
----------------
|
||||||
|
@ -551,12 +561,23 @@ Separate multiple extensions with commas or use -e or --extension multiple times
|
||||||
Use the :djadminopt:`--locale` option (or its shorter version ``-l``) to
|
Use the :djadminopt:`--locale` option (or its shorter version ``-l``) to
|
||||||
specify the locale(s) to process.
|
specify the locale(s) to process.
|
||||||
|
|
||||||
|
.. versionadded:: 1.8
|
||||||
|
|
||||||
|
Use the :djadminopt:`--exclude` option (or its shorter version ``-e``) to
|
||||||
|
specify the locale(s) to exclude from processing. If not provided, no locales
|
||||||
|
are excluded.
|
||||||
|
|
||||||
Example usage::
|
Example usage::
|
||||||
|
|
||||||
django-admin.py makemessages --locale=pt_BR
|
django-admin.py makemessages --locale=pt_BR
|
||||||
django-admin.py makemessages --locale=pt_BR --locale=fr
|
django-admin.py makemessages --locale=pt_BR --locale=fr
|
||||||
django-admin.py makemessages -l pt_BR
|
django-admin.py makemessages -l pt_BR
|
||||||
django-admin.py makemessages -l pt_BR -l fr
|
django-admin.py makemessages -l pt_BR -l fr
|
||||||
|
django-admin.py makemessages --exclude=pt_BR
|
||||||
|
django-admin.py makemessages --exclude=pt_BR --exclude=fr
|
||||||
|
django-admin.py makemessages -e pt_BR
|
||||||
|
django-admin.py makemessages -e pt_BR -e fr
|
||||||
|
|
||||||
|
|
||||||
.. versionchanged:: 1.7
|
.. versionchanged:: 1.7
|
||||||
|
|
||||||
|
|
|
@ -128,6 +128,10 @@ Management Commands
|
||||||
* :djadmin:`dumpdata` now has the option :djadminopt:`--output` which allows
|
* :djadmin:`dumpdata` now has the option :djadminopt:`--output` which allows
|
||||||
specifying the file to which the serialized data is written.
|
specifying the file to which the serialized data is written.
|
||||||
|
|
||||||
|
* :djadmin:`makemessages` and :djadmin:`compilemessages` now have the option
|
||||||
|
:djadminopt:`--exclude` which allows exclusion of specific locales from
|
||||||
|
processing.
|
||||||
|
|
||||||
Models
|
Models
|
||||||
^^^^^^
|
^^^^^^
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
# This package is used to test the --exclude option of
|
||||||
|
# the makemessages and compilemessages management commands.
|
||||||
|
# The locale directory for this app is generated automatically
|
||||||
|
# by the test cases.
|
||||||
|
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
|
# Translators: This comment should be extracted
|
||||||
|
dummy1 = _("This is a translatable string.")
|
||||||
|
|
||||||
|
# This comment should not be extracted
|
||||||
|
dummy2 = _("This is another translatable string.")
|
|
@ -0,0 +1,27 @@
|
||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2014-04-25 15:39-0500\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"Language: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#. Translators: This comment should be extracted
|
||||||
|
#: __init__.py:8
|
||||||
|
msgid "This is a translatable string."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: __init__.py:11
|
||||||
|
msgid "This is another translatable string."
|
||||||
|
msgstr ""
|
|
@ -0,0 +1,28 @@
|
||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2014-04-25 15:39-0500\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"Language: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||||
|
|
||||||
|
#. Translators: This comment should be extracted
|
||||||
|
#: __init__.py:8
|
||||||
|
msgid "This is a translatable string."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: __init__.py:11
|
||||||
|
msgid "This is another translatable string."
|
||||||
|
msgstr ""
|
|
@ -0,0 +1,28 @@
|
||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2014-04-25 15:39-0500\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"Language: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
|
#. Translators: This comment should be extracted
|
||||||
|
#: __init__.py:8
|
||||||
|
msgid "This is a translatable string."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: __init__.py:11
|
||||||
|
msgid "This is another translatable string."
|
||||||
|
msgstr ""
|
|
@ -1,4 +1,5 @@
|
||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
import stat
|
import stat
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
@ -10,17 +11,23 @@ from django.utils import translation
|
||||||
from django.utils._os import upath
|
from django.utils._os import upath
|
||||||
from django.utils.six import StringIO
|
from django.utils.six import StringIO
|
||||||
|
|
||||||
test_dir = os.path.abspath(os.path.join(os.path.dirname(upath(__file__)), 'commands'))
|
|
||||||
has_msgfmt = find_command('msgfmt')
|
has_msgfmt = find_command('msgfmt')
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipUnless(has_msgfmt, 'msgfmt is mandatory for compilation tests')
|
@unittest.skipUnless(has_msgfmt, 'msgfmt is mandatory for compilation tests')
|
||||||
class MessageCompilationTests(SimpleTestCase):
|
class MessageCompilationTests(SimpleTestCase):
|
||||||
|
|
||||||
|
test_dir = os.path.abspath(os.path.join(os.path.dirname(upath(__file__)), 'commands'))
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self._cwd = os.getcwd()
|
self._cwd = os.getcwd()
|
||||||
self.addCleanup(os.chdir, self._cwd)
|
self.addCleanup(os.chdir, self._cwd)
|
||||||
os.chdir(test_dir)
|
os.chdir(self.test_dir)
|
||||||
|
|
||||||
|
def _rmrf(self, dname):
|
||||||
|
if os.path.commonprefix([self.test_dir, os.path.abspath(dname)]) != self.test_dir:
|
||||||
|
return
|
||||||
|
shutil.rmtree(dname)
|
||||||
|
|
||||||
def rmfile(self, filepath):
|
def rmfile(self, filepath):
|
||||||
if os.path.exists(filepath):
|
if os.path.exists(filepath):
|
||||||
|
@ -60,7 +67,7 @@ class PoFileContentsTests(MessageCompilationTests):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(PoFileContentsTests, self).setUp()
|
super(PoFileContentsTests, self).setUp()
|
||||||
self.addCleanup(os.unlink, os.path.join(test_dir, self.MO_FILE))
|
self.addCleanup(os.unlink, os.path.join(self.test_dir, self.MO_FILE))
|
||||||
|
|
||||||
def test_percent_symbol_in_po_file(self):
|
def test_percent_symbol_in_po_file(self):
|
||||||
call_command('compilemessages', locale=[self.LOCALE], stdout=StringIO())
|
call_command('compilemessages', locale=[self.LOCALE], stdout=StringIO())
|
||||||
|
@ -76,10 +83,10 @@ class PercentRenderingTests(MessageCompilationTests):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(PercentRenderingTests, self).setUp()
|
super(PercentRenderingTests, self).setUp()
|
||||||
self.addCleanup(os.unlink, os.path.join(test_dir, self.MO_FILE))
|
self.addCleanup(os.unlink, os.path.join(self.test_dir, self.MO_FILE))
|
||||||
|
|
||||||
@override_settings(LOCALE_PATHS=(os.path.join(test_dir, 'locale'),))
|
|
||||||
def test_percent_symbol_escaping(self):
|
def test_percent_symbol_escaping(self):
|
||||||
|
with override_settings(LOCALE_PATHS=(os.path.join(self.test_dir, 'locale'),)):
|
||||||
from django.template import Template, Context
|
from django.template import Template, Context
|
||||||
call_command('compilemessages', locale=[self.LOCALE], stdout=StringIO())
|
call_command('compilemessages', locale=[self.LOCALE], stdout=StringIO())
|
||||||
with translation.override(self.LOCALE):
|
with translation.override(self.LOCALE):
|
||||||
|
@ -92,31 +99,71 @@ class PercentRenderingTests(MessageCompilationTests):
|
||||||
self.assertEqual(rendered, 'IT translation of Completed 50%% of all the tasks')
|
self.assertEqual(rendered, 'IT translation of Completed 50%% of all the tasks')
|
||||||
|
|
||||||
|
|
||||||
@override_settings(LOCALE_PATHS=(os.path.join(test_dir, 'locale'),))
|
|
||||||
class MultipleLocaleCompilationTests(MessageCompilationTests):
|
class MultipleLocaleCompilationTests(MessageCompilationTests):
|
||||||
|
|
||||||
MO_FILE_HR = None
|
MO_FILE_HR = None
|
||||||
MO_FILE_FR = None
|
MO_FILE_FR = None
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(MultipleLocaleCompilationTests, self).setUp()
|
super(MultipleLocaleCompilationTests, self).setUp()
|
||||||
localedir = os.path.join(test_dir, 'locale')
|
localedir = os.path.join(self.test_dir, 'locale')
|
||||||
self.MO_FILE_HR = os.path.join(localedir, 'hr/LC_MESSAGES/django.mo')
|
self.MO_FILE_HR = os.path.join(localedir, 'hr/LC_MESSAGES/django.mo')
|
||||||
self.MO_FILE_FR = os.path.join(localedir, 'fr/LC_MESSAGES/django.mo')
|
self.MO_FILE_FR = os.path.join(localedir, 'fr/LC_MESSAGES/django.mo')
|
||||||
self.addCleanup(self.rmfile, os.path.join(localedir, self.MO_FILE_HR))
|
self.addCleanup(self.rmfile, os.path.join(localedir, self.MO_FILE_HR))
|
||||||
self.addCleanup(self.rmfile, os.path.join(localedir, self.MO_FILE_FR))
|
self.addCleanup(self.rmfile, os.path.join(localedir, self.MO_FILE_FR))
|
||||||
|
|
||||||
def test_one_locale(self):
|
def test_one_locale(self):
|
||||||
|
with override_settings(LOCALE_PATHS=(os.path.join(self.test_dir, 'locale'),)):
|
||||||
call_command('compilemessages', locale=['hr'], stdout=StringIO())
|
call_command('compilemessages', locale=['hr'], stdout=StringIO())
|
||||||
|
|
||||||
self.assertTrue(os.path.exists(self.MO_FILE_HR))
|
self.assertTrue(os.path.exists(self.MO_FILE_HR))
|
||||||
|
|
||||||
def test_multiple_locales(self):
|
def test_multiple_locales(self):
|
||||||
|
with override_settings(LOCALE_PATHS=(os.path.join(self.test_dir, 'locale'),)):
|
||||||
call_command('compilemessages', locale=['hr', 'fr'], stdout=StringIO())
|
call_command('compilemessages', locale=['hr', 'fr'], stdout=StringIO())
|
||||||
|
|
||||||
self.assertTrue(os.path.exists(self.MO_FILE_HR))
|
self.assertTrue(os.path.exists(self.MO_FILE_HR))
|
||||||
self.assertTrue(os.path.exists(self.MO_FILE_FR))
|
self.assertTrue(os.path.exists(self.MO_FILE_FR))
|
||||||
|
|
||||||
|
|
||||||
|
class ExcludedLocaleCompilationTests(MessageCompilationTests):
|
||||||
|
|
||||||
|
test_dir = os.path.abspath(os.path.join(os.path.dirname(upath(__file__)), 'exclude'))
|
||||||
|
|
||||||
|
MO_FILE = 'locale/%s/LC_MESSAGES/django.mo'
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(ExcludedLocaleCompilationTests, self).setUp()
|
||||||
|
|
||||||
|
shutil.copytree('canned_locale', 'locale')
|
||||||
|
self.addCleanup(self._rmrf, os.path.join(self.test_dir, 'locale'))
|
||||||
|
|
||||||
|
def test_one_locale_excluded(self):
|
||||||
|
call_command('compilemessages', exclude=['it'], stdout=StringIO())
|
||||||
|
self.assertTrue(os.path.exists(self.MO_FILE % 'en'))
|
||||||
|
self.assertTrue(os.path.exists(self.MO_FILE % 'fr'))
|
||||||
|
self.assertFalse(os.path.exists(self.MO_FILE % 'it'))
|
||||||
|
|
||||||
|
def test_multiple_locales_excluded(self):
|
||||||
|
call_command('compilemessages', exclude=['it', 'fr'], stdout=StringIO())
|
||||||
|
self.assertTrue(os.path.exists(self.MO_FILE % 'en'))
|
||||||
|
self.assertFalse(os.path.exists(self.MO_FILE % 'fr'))
|
||||||
|
self.assertFalse(os.path.exists(self.MO_FILE % 'it'))
|
||||||
|
|
||||||
|
def test_one_locale_excluded_with_locale(self):
|
||||||
|
call_command('compilemessages', locale=['en', 'fr'], exclude=['fr'], stdout=StringIO())
|
||||||
|
self.assertTrue(os.path.exists(self.MO_FILE % 'en'))
|
||||||
|
self.assertFalse(os.path.exists(self.MO_FILE % 'fr'))
|
||||||
|
self.assertFalse(os.path.exists(self.MO_FILE % 'it'))
|
||||||
|
|
||||||
|
def test_multiple_locales_excluded_with_locale(self):
|
||||||
|
call_command('compilemessages', locale=['en', 'fr', 'it'], exclude=['fr', 'it'],
|
||||||
|
stdout=StringIO())
|
||||||
|
self.assertTrue(os.path.exists(self.MO_FILE % 'en'))
|
||||||
|
self.assertFalse(os.path.exists(self.MO_FILE % 'fr'))
|
||||||
|
self.assertFalse(os.path.exists(self.MO_FILE % 'it'))
|
||||||
|
|
||||||
|
|
||||||
class CompilationErrorHandling(MessageCompilationTests):
|
class CompilationErrorHandling(MessageCompilationTests):
|
||||||
|
|
||||||
LOCALE = 'ja'
|
LOCALE = 'ja'
|
||||||
|
@ -124,7 +171,7 @@ class CompilationErrorHandling(MessageCompilationTests):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(CompilationErrorHandling, self).setUp()
|
super(CompilationErrorHandling, self).setUp()
|
||||||
self.addCleanup(self.rmfile, os.path.join(test_dir, self.MO_FILE))
|
self.addCleanup(self.rmfile, os.path.join(self.test_dir, self.MO_FILE))
|
||||||
|
|
||||||
def test_error_reported_by_msgfmt(self):
|
def test_error_reported_by_msgfmt(self):
|
||||||
with self.assertRaises(CommandError):
|
with self.assertRaises(CommandError):
|
||||||
|
|
|
@ -5,6 +5,7 @@ import io
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
|
import time
|
||||||
from unittest import SkipTest, skipUnless
|
from unittest import SkipTest, skipUnless
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
|
@ -27,12 +28,12 @@ has_xgettext = find_command('xgettext')
|
||||||
@skipUnless(has_xgettext, 'xgettext is mandatory for extraction tests')
|
@skipUnless(has_xgettext, 'xgettext is mandatory for extraction tests')
|
||||||
class ExtractorTests(SimpleTestCase):
|
class ExtractorTests(SimpleTestCase):
|
||||||
|
|
||||||
|
test_dir = os.path.abspath(os.path.join(os.path.dirname(upath(__file__)), 'commands'))
|
||||||
|
|
||||||
PO_FILE = 'locale/%s/LC_MESSAGES/django.po' % LOCALE
|
PO_FILE = 'locale/%s/LC_MESSAGES/django.po' % LOCALE
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self._cwd = os.getcwd()
|
self._cwd = os.getcwd()
|
||||||
self.test_dir = os.path.abspath(
|
|
||||||
os.path.join(os.path.dirname(upath(__file__)), 'commands'))
|
|
||||||
|
|
||||||
def _rmrf(self, dname):
|
def _rmrf(self, dname):
|
||||||
if os.path.commonprefix([self.test_dir, os.path.abspath(dname)]) != self.test_dir:
|
if os.path.commonprefix([self.test_dir, os.path.abspath(dname)]) != self.test_dir:
|
||||||
|
@ -103,6 +104,20 @@ class ExtractorTests(SimpleTestCase):
|
||||||
"""Check the opposite of assertLocationComment()"""
|
"""Check the opposite of assertLocationComment()"""
|
||||||
return self._assertPoLocComment(False, po_filename, line_number, *comment_parts)
|
return self._assertPoLocComment(False, po_filename, line_number, *comment_parts)
|
||||||
|
|
||||||
|
def assertRecentlyModified(self, path):
|
||||||
|
"""
|
||||||
|
Assert that file was recently modified (modification time was less than 10 seconds ago).
|
||||||
|
"""
|
||||||
|
delta = time.time() - os.stat(path).st_mtime
|
||||||
|
self.assertLess(delta, 10, "%s was recently modified" % path)
|
||||||
|
|
||||||
|
def assertNotRecentlyModified(self, path):
|
||||||
|
"""
|
||||||
|
Assert that file was not recently modified (modification time was more than 10 seconds ago).
|
||||||
|
"""
|
||||||
|
delta = time.time() - os.stat(path).st_mtime
|
||||||
|
self.assertGreater(delta, 10, "%s wasn't recently modified" % path)
|
||||||
|
|
||||||
|
|
||||||
class BasicExtractorTests(ExtractorTests):
|
class BasicExtractorTests(ExtractorTests):
|
||||||
|
|
||||||
|
@ -402,6 +417,7 @@ class SymlinkExtractorTests(ExtractorTests):
|
||||||
|
|
||||||
|
|
||||||
class CopyPluralFormsExtractorTests(ExtractorTests):
|
class CopyPluralFormsExtractorTests(ExtractorTests):
|
||||||
|
|
||||||
PO_FILE_ES = 'locale/es/LC_MESSAGES/django.po'
|
PO_FILE_ES = 'locale/es/LC_MESSAGES/django.po'
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
|
@ -527,7 +543,56 @@ class MultipleLocaleExtractionTests(ExtractorTests):
|
||||||
self.assertTrue(os.path.exists(self.PO_FILE_DE))
|
self.assertTrue(os.path.exists(self.PO_FILE_DE))
|
||||||
|
|
||||||
|
|
||||||
|
class ExcludedLocaleExtractionTests(ExtractorTests):
|
||||||
|
|
||||||
|
LOCALES = ['en', 'fr', 'it']
|
||||||
|
PO_FILE = 'locale/%s/LC_MESSAGES/django.po'
|
||||||
|
|
||||||
|
test_dir = os.path.abspath(os.path.join(os.path.dirname(upath(__file__)), 'exclude'))
|
||||||
|
|
||||||
|
def _set_times_for_all_po_files(self):
|
||||||
|
"""
|
||||||
|
Set access and modification times to the Unix epoch time for all the .po files.
|
||||||
|
"""
|
||||||
|
for locale in self.LOCALES:
|
||||||
|
os.utime(self.PO_FILE % locale, (0, 0))
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(ExcludedLocaleExtractionTests, self).setUp()
|
||||||
|
|
||||||
|
os.chdir(self.test_dir) # ExtractorTests.tearDown() takes care of restoring.
|
||||||
|
shutil.copytree('canned_locale', 'locale')
|
||||||
|
self._set_times_for_all_po_files()
|
||||||
|
self.addCleanup(self._rmrf, os.path.join(self.test_dir, 'locale'))
|
||||||
|
|
||||||
|
def test_one_locale_excluded(self):
|
||||||
|
management.call_command('makemessages', exclude=['it'], stdout=StringIO())
|
||||||
|
self.assertRecentlyModified(self.PO_FILE % 'en')
|
||||||
|
self.assertRecentlyModified(self.PO_FILE % 'fr')
|
||||||
|
self.assertNotRecentlyModified(self.PO_FILE % 'it')
|
||||||
|
|
||||||
|
def test_multiple_locales_excluded(self):
|
||||||
|
management.call_command('makemessages', exclude=['it', 'fr'], stdout=StringIO())
|
||||||
|
self.assertRecentlyModified(self.PO_FILE % 'en')
|
||||||
|
self.assertNotRecentlyModified(self.PO_FILE % 'fr')
|
||||||
|
self.assertNotRecentlyModified(self.PO_FILE % 'it')
|
||||||
|
|
||||||
|
def test_one_locale_excluded_with_locale(self):
|
||||||
|
management.call_command('makemessages', locale=['en', 'fr'], exclude=['fr'], stdout=StringIO())
|
||||||
|
self.assertRecentlyModified(self.PO_FILE % 'en')
|
||||||
|
self.assertNotRecentlyModified(self.PO_FILE % 'fr')
|
||||||
|
self.assertNotRecentlyModified(self.PO_FILE % 'it')
|
||||||
|
|
||||||
|
def test_multiple_locales_excluded_with_locale(self):
|
||||||
|
management.call_command('makemessages', locale=['en', 'fr', 'it'], exclude=['fr', 'it'],
|
||||||
|
stdout=StringIO())
|
||||||
|
self.assertRecentlyModified(self.PO_FILE % 'en')
|
||||||
|
self.assertNotRecentlyModified(self.PO_FILE % 'fr')
|
||||||
|
self.assertNotRecentlyModified(self.PO_FILE % 'it')
|
||||||
|
|
||||||
|
|
||||||
class CustomLayoutExtractionTests(ExtractorTests):
|
class CustomLayoutExtractionTests(ExtractorTests):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self._cwd = os.getcwd()
|
self._cwd = os.getcwd()
|
||||||
self.test_dir = os.path.join(os.path.dirname(upath(__file__)), 'project_dir')
|
self.test_dir = os.path.join(os.path.dirname(upath(__file__)), 'project_dir')
|
||||||
|
|
Loading…
Reference in New Issue