Fixed #6380 - Follow symlinks when examining source code and templates for translation strings.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@12443 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
71da5f62da
commit
fef575a7f9
|
@ -43,7 +43,31 @@ def _popen(cmd):
|
||||||
p = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE, close_fds=os.name != 'nt', universal_newlines=True)
|
p = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE, close_fds=os.name != 'nt', universal_newlines=True)
|
||||||
return p.communicate()
|
return p.communicate()
|
||||||
|
|
||||||
def make_messages(locale=None, domain='django', verbosity='1', all=False, extensions=None):
|
def walk(root, topdown=True, onerror=None, followlinks=False):
|
||||||
|
"""
|
||||||
|
A version of os.walk that can follow symlinks for Python < 2.6
|
||||||
|
"""
|
||||||
|
for dirpath, dirnames, filenames in os.walk(root, topdown, onerror):
|
||||||
|
yield (dirpath, dirnames, filenames)
|
||||||
|
if followlinks:
|
||||||
|
for d in dirnames:
|
||||||
|
p = os.path.join(dirpath, d)
|
||||||
|
if os.path.islink(p):
|
||||||
|
for link_dirpath, link_dirnames, link_filenames in walk(p):
|
||||||
|
yield (link_dirpath, link_dirnames, link_filenames)
|
||||||
|
|
||||||
|
def find_files(root, symlinks=False):
|
||||||
|
"""
|
||||||
|
Helper function to get all files in the given root.
|
||||||
|
"""
|
||||||
|
all_files = []
|
||||||
|
for (dirpath, dirnames, filenames) in walk(".", followlinks=symlinks):
|
||||||
|
all_files.extend([(dirpath, f) for f in filenames])
|
||||||
|
all_files.sort()
|
||||||
|
return all_files
|
||||||
|
|
||||||
|
def make_messages(locale=None, domain='django', verbosity='1', all=False,
|
||||||
|
extensions=None, symlinks=False):
|
||||||
"""
|
"""
|
||||||
Uses the locale directory from the Django SVN tree or an application/
|
Uses the locale directory from the Django SVN tree or an application/
|
||||||
project to process all
|
project to process all
|
||||||
|
@ -103,11 +127,7 @@ def make_messages(locale=None, domain='django', verbosity='1', all=False, extens
|
||||||
if os.path.exists(potfile):
|
if os.path.exists(potfile):
|
||||||
os.unlink(potfile)
|
os.unlink(potfile)
|
||||||
|
|
||||||
all_files = []
|
for dirpath, file in find_files(".", symlinks=symlinks):
|
||||||
for (dirpath, dirnames, filenames) in os.walk("."):
|
|
||||||
all_files.extend([(dirpath, f) for f in filenames])
|
|
||||||
all_files.sort()
|
|
||||||
for dirpath, file in all_files:
|
|
||||||
file_base, file_ext = os.path.splitext(file)
|
file_base, file_ext = os.path.splitext(file)
|
||||||
if domain == 'djangojs' and file_ext in extensions:
|
if domain == 'djangojs' and file_ext in extensions:
|
||||||
if verbosity > 1:
|
if verbosity > 1:
|
||||||
|
@ -184,6 +204,8 @@ class Command(BaseCommand):
|
||||||
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',
|
||||||
default=False, help='Reexamines all source code and templates for new translation strings and updates all message files for all available languages.'),
|
default=False, help='Reexamines all source code and templates for new translation strings and updates all message files for all available languages.'),
|
||||||
|
make_option('--symlinks', '-s', action='store_true', dest='symlinks',
|
||||||
|
default=False, help='Follows symlinks to directories when examining source code and templates for translation strings.'),
|
||||||
make_option('--extension', '-e', dest='extensions',
|
make_option('--extension', '-e', dest='extensions',
|
||||||
help='The file extension(s) to examine (default: ".html", separate multiple extensions with commas, or use -e multiple times)',
|
help='The file extension(s) to examine (default: ".html", separate multiple extensions with commas, or use -e multiple times)',
|
||||||
action='append'),
|
action='append'),
|
||||||
|
@ -202,6 +224,7 @@ class Command(BaseCommand):
|
||||||
verbosity = int(options.get('verbosity'))
|
verbosity = int(options.get('verbosity'))
|
||||||
process_all = options.get('all')
|
process_all = options.get('all')
|
||||||
extensions = options.get('extensions')
|
extensions = options.get('extensions')
|
||||||
|
symlinks = options.get('symlinks')
|
||||||
|
|
||||||
if domain == 'djangojs':
|
if domain == 'djangojs':
|
||||||
extensions = handle_extensions(extensions or ['js'])
|
extensions = handle_extensions(extensions or ['js'])
|
||||||
|
@ -211,4 +234,4 @@ class Command(BaseCommand):
|
||||||
if verbosity > 1:
|
if verbosity > 1:
|
||||||
sys.stdout.write('examining files with the extensions: %s\n' % get_text_list(list(extensions), 'and'))
|
sys.stdout.write('examining files with the extensions: %s\n' % get_text_list(list(extensions), 'and'))
|
||||||
|
|
||||||
make_messages(locale, domain, verbosity, process_all, extensions)
|
make_messages(locale, domain, verbosity, process_all, extensions, symlinks)
|
||||||
|
|
|
@ -46,7 +46,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" "]"
|
.BI "makemessages [" "\-\-locale=LOCALE" "] [" "\-\-domain=DOMAIN" "] [" "\-\-extension=EXTENSION" "] [" "\-\-all" "] [" "\-\-symlinks" "]"
|
||||||
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.
|
||||||
|
@ -155,6 +155,10 @@ The domain of the message files (default: "django") when using makemessages.
|
||||||
The file extension(s) to examine (default: ".html", separate multiple
|
The file extension(s) to examine (default: ".html", separate multiple
|
||||||
extensions with commas, or use -e multiple times).
|
extensions with commas, or use -e multiple times).
|
||||||
.TP
|
.TP
|
||||||
|
.I \-e, \-\-symlinks
|
||||||
|
Follows symlinks to directories when examining source code and templates for
|
||||||
|
translation strings.
|
||||||
|
.TP
|
||||||
.I \-a, \-\-all
|
.I \-a, \-\-all
|
||||||
Process all available locales when using makemessages..SH "ENVIRONMENT"
|
Process all available locales when using makemessages..SH "ENVIRONMENT"
|
||||||
.TP
|
.TP
|
||||||
|
|
|
@ -471,8 +471,17 @@ Example usage::
|
||||||
Use the ``--domain`` or ``-d`` option to change the domain of the messages files.
|
Use the ``--domain`` or ``-d`` option to change the domain of the messages files.
|
||||||
Currently supported:
|
Currently supported:
|
||||||
|
|
||||||
* ``django`` for all ``*.py`` and ``*.html`` files (default)
|
* ``django`` for all ``*.py`` and ``*.html`` files (default)
|
||||||
* ``djangojs`` for ``*.js`` files
|
* ``djangojs`` for ``*.js`` files
|
||||||
|
|
||||||
|
.. django-admin-option:: --symlinks
|
||||||
|
|
||||||
|
Use the ``--symlinks`` or ``-s`` option to follow symlinks to directories when
|
||||||
|
looking for new translation strings.
|
||||||
|
|
||||||
|
Example usage::
|
||||||
|
|
||||||
|
django-admin.py makemessages --locale=de --symlinks
|
||||||
|
|
||||||
reset <appname appname ...>
|
reset <appname appname ...>
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
|
@ -78,10 +78,10 @@ The script should be run from one of two places:
|
||||||
* The root directory of your Django project.
|
* The root directory of your Django project.
|
||||||
* The root directory of your Django app.
|
* The root directory of your Django app.
|
||||||
|
|
||||||
Th script runs over your project source tree or your application source tree and
|
The script runs over your project source tree or your application source tree
|
||||||
pulls out all strings marked for translation. It creates (or updates) a message
|
and pulls out all strings marked for translation. It creates (or updates) a
|
||||||
file in the directory ``locale/LANG/LC_MESSAGES``. In the ``de`` example, the
|
message file in the directory ``locale/LANG/LC_MESSAGES``. In the ``de``
|
||||||
file will be ``locale/de/LC_MESSAGES/django.po``.
|
example, the file will be ``locale/de/LC_MESSAGES/django.po``.
|
||||||
|
|
||||||
By default ``django-admin.py makemessages`` examines every file that has the
|
By default ``django-admin.py makemessages`` examines every file that has the
|
||||||
``.html`` file extension. In case you want to override that default, use the
|
``.html`` file extension. In case you want to override that default, use the
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
{% load i18n %}
|
||||||
|
{% trans "This literal should be included." %}
|
|
@ -40,3 +40,34 @@ class JavascriptExtractorTests(ExtractorTests):
|
||||||
po_contents = open(self.PO_FILE, 'r').read()
|
po_contents = open(self.PO_FILE, 'r').read()
|
||||||
self.assertMsgId('This literal should be included.', po_contents)
|
self.assertMsgId('This literal should be included.', po_contents)
|
||||||
self.assertMsgId('This one as well.', po_contents)
|
self.assertMsgId('This one as well.', po_contents)
|
||||||
|
|
||||||
|
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__))
|
||||||
|
self.symlinked_dir = os.path.join(self.test_dir, 'templates_symlinked')
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
super(SymlinkExtractorTests, self).tearDown()
|
||||||
|
os.chdir(self.test_dir)
|
||||||
|
try:
|
||||||
|
os.remove(self.symlinked_dir)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
os.chdir(self._cwd)
|
||||||
|
|
||||||
|
def test_symlink(self):
|
||||||
|
if hasattr(os, 'symlink'):
|
||||||
|
if os.path.exists(self.symlinked_dir):
|
||||||
|
self.assert_(os.path.islink(self.symlinked_dir))
|
||||||
|
else:
|
||||||
|
os.symlink(os.path.join(self.test_dir, 'templates'), self.symlinked_dir)
|
||||||
|
os.chdir(self.test_dir)
|
||||||
|
management.call_command('makemessages', locale=LOCALE, verbosity=0, symlinks=True)
|
||||||
|
self.assert_(os.path.exists(self.PO_FILE))
|
||||||
|
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)
|
||||||
|
|
Loading…
Reference in New Issue