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:
Jannis Leidel 2010-02-16 12:14:27 +00:00
parent 71da5f62da
commit fef575a7f9
6 changed files with 83 additions and 14 deletions

View File

@ -43,7 +43,31 @@ def _popen(cmd):
p = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE, close_fds=os.name != 'nt', universal_newlines=True)
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/
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):
os.unlink(potfile)
all_files = []
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:
for dirpath, file in find_files(".", symlinks=symlinks):
file_base, file_ext = os.path.splitext(file)
if domain == 'djangojs' and file_ext in extensions:
if verbosity > 1:
@ -184,6 +204,8 @@ class Command(BaseCommand):
help='The domain of the message files (default: "django").'),
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.'),
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',
help='The file extension(s) to examine (default: ".html", separate multiple extensions with commas, or use -e multiple times)',
action='append'),
@ -202,6 +224,7 @@ class Command(BaseCommand):
verbosity = int(options.get('verbosity'))
process_all = options.get('all')
extensions = options.get('extensions')
symlinks = options.get('symlinks')
if domain == 'djangojs':
extensions = handle_extensions(extensions or ['js'])
@ -211,4 +234,4 @@ class Command(BaseCommand):
if verbosity > 1:
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)

View File

@ -46,7 +46,7 @@ Executes
.B sqlall
for the given app(s) in the current database.
.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
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.
@ -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
extensions with commas, or use -e multiple times).
.TP
.I \-e, \-\-symlinks
Follows symlinks to directories when examining source code and templates for
translation strings.
.TP
.I \-a, \-\-all
Process all available locales when using makemessages..SH "ENVIRONMENT"
.TP

View File

@ -474,6 +474,15 @@ Currently supported:
* ``django`` for all ``*.py`` and ``*.html`` files (default)
* ``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 ...>
---------------------------

View File

@ -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 app.
Th script runs over your project source tree or your application source tree and
pulls out all strings marked for translation. It creates (or updates) a message
file in the directory ``locale/LANG/LC_MESSAGES``. In the ``de`` example, the
file will be ``locale/de/LC_MESSAGES/django.po``.
The script runs over your project source tree or your application source tree
and pulls out all strings marked for translation. It creates (or updates) a
message file in the directory ``locale/LANG/LC_MESSAGES``. In the ``de``
example, the file will be ``locale/de/LC_MESSAGES/django.po``.
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

View File

@ -0,0 +1,2 @@
{% load i18n %}
{% trans "This literal should be included." %}

View File

@ -40,3 +40,34 @@ class JavascriptExtractorTests(ExtractorTests):
po_contents = open(self.PO_FILE, 'r').read()
self.assertMsgId('This literal should be included.', 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)