Fixed #5522 -- Moved make-messages, compile-messages and daily-cleanup into django-admin.py.

They are now called  "makemessages", "compilemessages" and "cleanup". This is
backwards incompatible for make-messages.py and compile-messages.py, although
the old executables still exist for now and print an error pointing the caller
to the right command to call.

This reduces the number of binaries and man pages Django needs to install.

Patch from Janis Leidel.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@7844 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2008-07-06 06:39:44 +00:00
parent bff075973a
commit 3cfa3cbd07
16 changed files with 418 additions and 381 deletions

View File

@ -1,64 +1,11 @@
#!/usr/bin/env python
import optparse
import os
if __name__ == "__main__":
import sys
try:
set
except NameError:
from sets import Set as set # For Python 2.3
def compile_messages(locale=None):
basedirs = (os.path.join('conf', 'locale'), 'locale')
if os.environ.get('DJANGO_SETTINGS_MODULE'):
from django.conf import settings
basedirs += settings.LOCALE_PATHS
# Gather existing directories.
basedirs = set(map(os.path.abspath, filter(os.path.isdir, basedirs)))
if not basedirs:
print "This script should be run from the Django SVN tree or your project or app tree, or with the settings module specified."
name = sys.argv[0]
args = ' '.join(sys.argv[1:])
print >> sys.stderr, "%s has been moved into django-admin.py" % name
print >> sys.stderr, 'Please run "django-admin.py compilemessages %s" instead.'% args
print >> sys.stderr
sys.exit(1)
for basedir in basedirs:
if locale:
basedir = os.path.join(basedir, locale, 'LC_MESSAGES')
compile_messages_in_dir(basedir)
def compile_messages_in_dir(basedir):
for dirpath, dirnames, filenames in os.walk(basedir):
for f in filenames:
if f.endswith('.po'):
sys.stderr.write('processing file %s in %s\n' % (f, dirpath))
pf = os.path.splitext(os.path.join(dirpath, f))[0]
# Store the names of the .mo and .po files in an environment
# variable, rather than doing a string replacement into the
# command, so that we can take advantage of shell quoting, to
# quote any malicious characters/escaping.
# See http://cyberelk.net/tim/articles/cmdline/ar01s02.html
os.environ['djangocompilemo'] = pf + '.mo'
os.environ['djangocompilepo'] = pf + '.po'
if sys.platform == 'win32': # Different shell-variable syntax
cmd = 'msgfmt --check-format -o "%djangocompilemo%" "%djangocompilepo%"'
else:
cmd = 'msgfmt --check-format -o "$djangocompilemo" "$djangocompilepo"'
os.system(cmd)
def main():
parser = optparse.OptionParser()
parser.add_option('-l', '--locale', dest='locale',
help="The locale to process. Default is to process all.")
parser.add_option('--settings',
help='Python path to settings module, e.g. "myproject.settings". If provided, all LOCALE_PATHS will be processed. If this isn\'t provided, the DJANGO_SETTINGS_MODULE environment variable will be checked as well.')
options, args = parser.parse_args()
if len(args):
parser.error("This program takes no arguments")
if options.settings:
os.environ['DJANGO_SETTINGS_MODULE'] = options.settings
compile_messages(options.locale)
if __name__ == "__main__":
main()

View File

@ -7,14 +7,7 @@ Can be run as a cronjob to clean out old data from the database (only expired
sessions at the moment).
"""
import datetime
from django.db import transaction
from django.contrib.sessions.models import Session
def clean_up():
"""Clean up expired sessions."""
Session.objects.filter(expire_date__lt=datetime.datetime.now()).delete()
transaction.commit_unless_managed()
from django.core import management
if __name__ == "__main__":
clean_up()
management.call_command('cleanup')

View File

@ -1,159 +1,11 @@
#!/usr/bin/env python
# Need to ensure that the i18n framework is enabled
from django.conf import settings
settings.configure(USE_I18N = True)
from django.utils.translation import templatize
import re
import os
import sys
import getopt
from itertools import dropwhile
pythonize_re = re.compile(r'\n\s*//')
def make_messages():
localedir = None
if os.path.isdir(os.path.join('conf', 'locale')):
localedir = os.path.abspath(os.path.join('conf', 'locale'))
elif os.path.isdir('locale'):
localedir = os.path.abspath('locale')
else:
print "This script should be run from the django svn tree or your project or app tree."
print "If you did indeed run it from the svn checkout or your project or application,"
print "maybe you are just missing the conf/locale (in the django tree) or locale (for project"
print "and application) directory?"
print "make-messages.py doesn't create it automatically, you have to create it by hand if"
print "you want to enable i18n for your project or application."
sys.exit(1)
(opts, args) = getopt.getopt(sys.argv[1:], 'l:d:va')
lang = None
domain = 'django'
verbose = False
all = False
for o, v in opts:
if o == '-l':
lang = v
elif o == '-d':
domain = v
elif o == '-v':
verbose = True
elif o == '-a':
all = True
if domain not in ('django', 'djangojs'):
print "currently make-messages.py only supports domains 'django' and 'djangojs'"
sys.exit(1)
if (lang is None and not all) or domain is None:
print "usage: make-messages.py -l <language>"
print " or: make-messages.py -a"
sys.exit(1)
languages = []
if lang is not None:
languages.append(lang)
elif all:
languages = [el for el in os.listdir(localedir) if not el.startswith('.')]
for lang in languages:
print "processing language", lang
basedir = os.path.join(localedir, lang, 'LC_MESSAGES')
if not os.path.isdir(basedir):
os.makedirs(basedir)
pofile = os.path.join(basedir, '%s.po' % domain)
potfile = os.path.join(basedir, '%s.pot' % domain)
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:
if domain == 'djangojs' and file.endswith('.js'):
if verbose: sys.stdout.write('processing file %s in %s\n' % (file, dirpath))
src = open(os.path.join(dirpath, file), "rb").read()
src = pythonize_re.sub('\n#', src)
open(os.path.join(dirpath, '%s.py' % file), "wb").write(src)
thefile = '%s.py' % file
cmd = 'xgettext -d %s -L Perl --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy:1,2 --from-code UTF-8 -o - "%s"' % (domain, os.path.join(dirpath, thefile))
(stdin, stdout, stderr) = os.popen3(cmd, 't')
msgs = stdout.read()
errors = stderr.read()
if errors:
print "errors happened while running xgettext on %s" % file
print errors
sys.exit(8)
old = '#: '+os.path.join(dirpath, thefile)[2:]
new = '#: '+os.path.join(dirpath, file)[2:]
msgs = msgs.replace(old, new)
if os.path.exists(potfile):
# Strip the header
msgs = '\n'.join(dropwhile(len, msgs.split('\n')))
else:
msgs = msgs.replace('charset=CHARSET', 'charset=UTF-8')
if msgs:
open(potfile, 'ab').write(msgs)
os.unlink(os.path.join(dirpath, thefile))
elif domain == 'django' and (file.endswith('.py') or file.endswith('.html')):
thefile = file
if file.endswith('.html'):
src = open(os.path.join(dirpath, file), "rb").read()
thefile = '%s.py' % file
open(os.path.join(dirpath, thefile), "wb").write(templatize(src))
if verbose:
sys.stdout.write('processing file %s in %s\n' % (file, dirpath))
cmd = 'xgettext -d %s -L Python --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy:1,2 --keyword=ugettext_noop --keyword=ugettext_lazy --keyword=ungettext_lazy:1,2 --from-code UTF-8 -o - "%s"' % (
domain, os.path.join(dirpath, thefile))
(stdin, stdout, stderr) = os.popen3(cmd, 't')
msgs = stdout.read()
errors = stderr.read()
if errors:
print "errors happened while running xgettext on %s" % file
print errors
sys.exit(8)
if thefile != file:
old = '#: '+os.path.join(dirpath, thefile)[2:]
new = '#: '+os.path.join(dirpath, file)[2:]
msgs = msgs.replace(old, new)
if os.path.exists(potfile):
# Strip the header
msgs = '\n'.join(dropwhile(len, msgs.split('\n')))
else:
msgs = msgs.replace('charset=CHARSET', 'charset=UTF-8')
if msgs:
open(potfile, 'ab').write(msgs)
if thefile != file:
os.unlink(os.path.join(dirpath, thefile))
if os.path.exists(potfile):
(stdin, stdout, stderr) = os.popen3('msguniq --to-code=utf-8 "%s"' % potfile, 'b')
msgs = stdout.read()
errors = stderr.read()
if errors:
print "errors happened while running msguniq"
print errors
sys.exit(8)
open(potfile, 'w').write(msgs)
if os.path.exists(pofile):
(stdin, stdout, stderr) = os.popen3('msgmerge -q "%s" "%s"' % (pofile, potfile), 'b')
msgs = stdout.read()
errors = stderr.read()
if errors:
print "errors happened while running msgmerge"
print errors
sys.exit(8)
open(pofile, 'wb').write(msgs)
os.unlink(potfile)
if __name__ == "__main__":
make_messages()
import sys
name = sys.argv[0]
args = ' '.join(sys.argv[1:])
print >> sys.stderr, "%s has been moved into django-admin.py" % name
print >> sys.stderr, 'Please run "django-admin.py makemessages %s" instead.'% args
print >> sys.stderr
sys.exit(1)

View File

@ -6,6 +6,11 @@ import django
from django.core.exceptions import ImproperlyConfigured
from django.core.management.color import color_style
try:
set
except NameError:
from sets import Set as set # For Python 2.3
class CommandError(Exception):
pass

View File

@ -0,0 +1,11 @@
import datetime
from django.core.management.base import NoArgsCommand
class Command(NoArgsCommand):
help = "Can be run as a cronjob or directly to clean out old data from the database (only expired sessions at the moment)."
def handle_noargs(self, **options):
from django.db import transaction
from django.contrib.sessions.models import Session
Session.objects.filter(expire_date__lt=datetime.datetime.now()).delete()
transaction.commit_unless_managed()

View File

@ -0,0 +1,58 @@
import os
import sys
from optparse import make_option
from django.core.management.base import BaseCommand
from django.core.management.color import no_style
try:
set
except NameError:
from sets import Set as set # For Python 2.3
def compile_messages(locale=None):
basedirs = (os.path.join('conf', 'locale'), 'locale')
if os.environ.get('DJANGO_SETTINGS_MODULE'):
from django.conf import settings
basedirs += settings.LOCALE_PATHS
# Gather existing directories.
basedirs = set(map(os.path.abspath, filter(os.path.isdir, basedirs)))
if not basedirs:
raise CommandError("This script should be run from the Django SVN tree or your project or app tree, or with the settings module specified.")
for basedir in basedirs:
if locale:
basedir = os.path.join(basedir, locale, 'LC_MESSAGES')
for dirpath, dirnames, filenames in os.walk(basedir):
for f in filenames:
if f.endswith('.po'):
sys.stderr.write('processing file %s in %s\n' % (f, dirpath))
pf = os.path.splitext(os.path.join(dirpath, f))[0]
# Store the names of the .mo and .po files in an environment
# variable, rather than doing a string replacement into the
# command, so that we can take advantage of shell quoting, to
# quote any malicious characters/escaping.
# See http://cyberelk.net/tim/articles/cmdline/ar01s02.html
os.environ['djangocompilemo'] = pf + '.mo'
os.environ['djangocompilepo'] = pf + '.po'
if sys.platform == 'win32': # Different shell-variable syntax
cmd = 'msgfmt --check-format -o "%djangocompilemo%" "%djangocompilepo%"'
else:
cmd = 'msgfmt --check-format -o "$djangocompilemo" "$djangocompilepo"'
os.system(cmd)
class Command(BaseCommand):
option_list = BaseCommand.option_list + (
make_option('--locale', '-l', dest='locale',
help='The locale to process. Default is to process all.'),
)
help = 'Compiles .po files to .mo files for use with builtin gettext support.'
requires_model_validation = False
can_import_settings = False
def handle(self, **options):
locale = options.get('locale')
compile_messages(locale)

View File

@ -0,0 +1,159 @@
import re
import os
import sys
from itertools import dropwhile
from optparse import make_option
from django.core.management.base import CommandError, BaseCommand
pythonize_re = re.compile(r'\n\s*//')
def make_messages(locale=None, domain='django', verbosity='1', all=False):
"""
Uses the locale directory from the Django SVN tree or an application/
project to process all
"""
# Need to ensure that the i18n framework is enabled
from django.conf import settings
settings.configure(USE_I18N = True)
from django.utils.translation import templatize
if os.path.isdir(os.path.join('conf', 'locale')):
localedir = os.path.abspath(os.path.join('conf', 'locale'))
elif os.path.isdir('locale'):
localedir = os.path.abspath('locale')
else:
raise CommandError("This script should be run from the Django SVN tree or your project or app tree. If you did indeed run it from the SVN checkout or your project or application, maybe you are just missing the conf/locale (in the django tree) or locale (for project and application) directory? It is not created automatically, you have to create it by hand 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'")
if (locale is None and not all) or domain is None:
# backwards compatible error message
if not sys.argv[0].endswith("make-messages.py"):
message = "Type '%s help %s' for usage.\n" % (os.path.basename(sys.argv[0]), sys.argv[1])
else:
message = "usage: make-messages.py -l <language>\n or: make-messages.py -a\n"
raise CommandError(message)
languages = []
if locale is not None:
languages.append(locale)
elif all:
languages = [el for el in os.listdir(localedir) if not el.startswith('.')]
for locale in languages:
if verbosity > 0:
print "processing language", locale
basedir = os.path.join(localedir, locale, 'LC_MESSAGES')
if not os.path.isdir(basedir):
os.makedirs(basedir)
pofile = os.path.join(basedir, '%s.po' % domain)
potfile = os.path.join(basedir, '%s.pot' % domain)
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:
if domain == 'djangojs' and file.endswith('.js'):
if verbosity > 1:
sys.stdout.write('processing file %s in %s\n' % (file, dirpath))
src = open(os.path.join(dirpath, file), "rb").read()
src = pythonize_re.sub('\n#', src)
open(os.path.join(dirpath, '%s.py' % file), "wb").write(src)
thefile = '%s.py' % file
cmd = 'xgettext -d %s -L Perl --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy:1,2 --from-code UTF-8 -o - "%s"' % (domain, os.path.join(dirpath, thefile))
(stdin, stdout, stderr) = os.popen3(cmd, 't')
msgs = stdout.read()
errors = stderr.read()
if errors:
raise CommandError("errors happened while running xgettext on %s\n%s" % (file, errors))
old = '#: '+os.path.join(dirpath, thefile)[2:]
new = '#: '+os.path.join(dirpath, file)[2:]
msgs = msgs.replace(old, new)
if os.path.exists(potfile):
# Strip the header
msgs = '\n'.join(dropwhile(len, msgs.split('\n')))
else:
msgs = msgs.replace('charset=CHARSET', 'charset=UTF-8')
if msgs:
open(potfile, 'ab').write(msgs)
os.unlink(os.path.join(dirpath, thefile))
elif domain == 'django' and (file.endswith('.py') or file.endswith('.html')):
thefile = file
if file.endswith('.html'):
src = open(os.path.join(dirpath, file), "rb").read()
thefile = '%s.py' % file
open(os.path.join(dirpath, thefile), "wb").write(templatize(src))
if verbosity > 1:
sys.stdout.write('processing file %s in %s\n' % (file, dirpath))
cmd = 'xgettext -d %s -L Python --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy:1,2 --keyword=ugettext_noop --keyword=ugettext_lazy --keyword=ungettext_lazy:1,2 --from-code UTF-8 -o - "%s"' % (
domain, os.path.join(dirpath, thefile))
(stdin, stdout, stderr) = os.popen3(cmd, 't')
msgs = stdout.read()
errors = stderr.read()
if errors:
raise CommandError("errors happened while running xgettext on %s\n%s" % (file, errors))
if thefile != file:
old = '#: '+os.path.join(dirpath, thefile)[2:]
new = '#: '+os.path.join(dirpath, file)[2:]
msgs = msgs.replace(old, new)
if os.path.exists(potfile):
# Strip the header
msgs = '\n'.join(dropwhile(len, msgs.split('\n')))
else:
msgs = msgs.replace('charset=CHARSET', 'charset=UTF-8')
if msgs:
open(potfile, 'ab').write(msgs)
if thefile != file:
os.unlink(os.path.join(dirpath, thefile))
if os.path.exists(potfile):
(stdin, stdout, stderr) = os.popen3('msguniq --to-code=utf-8 "%s"' % potfile, 'b')
msgs = stdout.read()
errors = stderr.read()
if errors:
raise CommandError("errors happened while running msguniq\n%s" % errors)
open(potfile, 'w').write(msgs)
if os.path.exists(pofile):
(stdin, stdout, stderr) = os.popen3('msgmerge -q "%s" "%s"' % (pofile, potfile), 'b')
msgs = stdout.read()
errors = stderr.read()
if errors:
raise CommandError("errors happened while running msgmerge\n%s" % errors)
open(pofile, 'wb').write(msgs)
os.unlink(potfile)
class Command(BaseCommand):
option_list = BaseCommand.option_list + (
make_option('--locale', '-l', default=None, dest='locale',
help='Creates or updates the message files only for the given locale (e.g. pt_BR).'),
make_option('--domain', '-d', default='django', dest='domain',
help='The domain of the message files (default: "django").'),
make_option('--verbosity', '-v', action='store', dest='verbosity',
default='1', type='choice', choices=['0', '1', '2'],
help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'),
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.'),
)
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 file in the conf/locale (in the django tree) or locale (for project and application) directory."
requires_model_validation = False
can_import_settings = False
def handle(self, *args, **options):
if len(args) != 0:
raise CommandError("Command doesn't accept any arguments")
locale = options.get('locale')
domain = options.get('domain')
verbosity = int(options.get('verbosity'))
process_all = options.get('all')
make_messages(locale, domain, verbosity, process_all)

View File

@ -392,7 +392,7 @@ translated, here's what to do:
* Create translations using the methods described in the
`i18n documentation`_.
* Create a diff of the ``.po`` file against the current Subversion trunk.
* Make sure that `` bin/compile-messages.py -l <lang>`` runs without
* Make sure that `` django-admin.py compilemessages -l <lang>`` runs without
producing any warnings.
* Attach the patch to a ticket in Django's ticket system.

View File

@ -85,6 +85,32 @@ your admin's index page. See `Tutorial 2`_ for more information.
.. _Tutorial 2: ../tutorial02/
cleanup
-------
**New in Django development version**
Can be run as a cronjob or directly to clean out old data from the database
(only expired sessions at the moment).
compilemessages
---------------
**New in Django development version**
Compiles .po files created with ``makemessages`` to .mo files for use with
the builtin gettext support. See the `i18n documentation`_ for details.
--locale
~~~~~~~~
Use the ``--locale`` or ``-l`` option to specify the locale to process.
If not provided all locales are processed.
Example usage::
django-admin.py compilemessages --locale=br_PT
createcachetable <tablename>
----------------------------
@ -362,6 +388,62 @@ Example usage::
django-admin.py loaddata --verbosity=2
makemessages
------------
**New in Django development version**
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. After making changes to the messages files you need to compile them
with ``compilemessages`` for use with the builtin gettext support. See the
`i18n documentation`_ for details.
.. _i18n documentation: ../i18n/#how-to-create-language-files
--all
~~~~~
Use the ``--all`` or ``-a`` option to update the message files for all
available languages.
Example usage::
django-admin.py makemessages --all
--locale
~~~~~~~~
Use the ``--locale`` or ``-l`` option to specify the locale to process.
Example usage::
django-admin.py makemessages --locale=br_PT
--domain
~~~~~~~~
Use the ``--domain`` or ``-d`` option to change the domain of the messages files.
Currently supported:
* ``django`` for all ``*.py`` and ``*.html`` files (default)
* ``djangojs`` for ``*.js`` files
--verbosity
~~~~~~~~~~~
Use ``--verbosity`` or ``-v`` to specify the amount of notification and debug
information that ``django-admin.py`` should print to the console.
* ``0`` means no output.
* ``1`` means normal output (default).
* ``2`` means verbose output.
Example usage::
django-admin.py makemessages --verbosity=2
reset <appname appname ...>
---------------------------

View File

@ -122,8 +122,8 @@ Translation works on variables. Again, here's an identical example::
(The caveat with using variables or computed values, as in the previous two
examples, is that Django's translation-string-detecting utility,
``make-messages.py``, won't be able to find these strings. More on
``make-messages`` later.)
``django-admin.py makemessages``, won't be able to find these strings. More on
``makemessages`` later.)
The strings you pass to ``_()`` or ``ugettext()`` can take placeholders,
specified with Python's standard named-string interpolation syntax. Example::
@ -393,12 +393,17 @@ file is a plain-text file, representing a single language, that contains all
available translation strings and how they should be represented in the given
language. Message files have a ``.po`` file extension.
Django comes with a tool, ``bin/make-messages.py``, that automates the creation
and upkeep of these files.
Django comes with a tool, ``django-admin.py makemessages``, that automates the
creation and upkeep of these files.
.. admonition:: A note to Django veterans
The old tool ``bin/make-messages.py`` has been moved to the command
``django-admin.py makemessages`` to provide consistency throughout Django.
To create or update a message file, run this command::
bin/make-messages.py -l de
django-admin.py makemessages -l de
...where ``de`` is the language code for the message file you want to create.
The language code, in this case, is in locale format. For example, it's
@ -423,11 +428,11 @@ do the same, but the location of the locale directory is ``locale/LANG/LC_MESSAG
.. admonition:: No gettext?
If you don't have the ``gettext`` utilities installed, ``make-messages.py``
will create empty files. If that's the case, either install the ``gettext``
utilities or just copy the English message file
(``conf/locale/en/LC_MESSAGES/django.po``) and use it as a starting point;
it's just an empty translation file.
If you don't have the ``gettext`` utilities installed,
``django-admin.py makemessages`` will create empty files. If that's the
case, either install the ``gettext`` utilities or just copy the English
message file (``conf/locale/en/LC_MESSAGES/django.po``) and use it as a
starting point; it's just an empty translation file.
The format of ``.po`` files is straightforward. Each ``.po`` file contains a
small bit of metadata, such as the translation maintainer's contact
@ -440,8 +445,8 @@ For example, if your Django app contained a translation string for the text
_("Welcome to my site.")
...then ``make-messages.py`` will have created a ``.po`` file containing the
following snippet -- a message::
...then ``django-admin.py makemessages`` will have created a ``.po`` file
containing the following snippet -- a message::
#: path/to/python/module.py:23
msgid "Welcome to my site."
@ -476,24 +481,30 @@ otherwise, they'll be tacked together without whitespace!
To reexamine all source code and templates for new translation strings and
update all message files for **all** languages, run this::
make-messages.py -a
django-admin.py makemessages -a
Compiling message files
-----------------------
After you create your message file -- and each time you make changes to it --
you'll need to compile it into a more efficient form, for use by ``gettext``.
Do this with the ``bin/compile-messages.py`` utility.
Do this with the ``django-admin.py compilemessages`` utility.
This tool runs over all available ``.po`` files and creates ``.mo`` files,
which are binary files optimized for use by ``gettext``. In the same directory
from which you ran ``make-messages.py``, run ``compile-messages.py`` like
this::
from which you ran ``django-admin.py makemessages``, run
``django-admin.py compilemessages`` like this::
bin/compile-messages.py
django-admin.py compilemessages
That's it. Your translations are ready for use.
.. admonition:: A note to Django veterans
The old tool ``bin/compile-messages.py`` has been moved to the command
``django-admin.py compilemessages`` to provide consistency throughout
Django.
.. admonition:: A note to translators
If you've created a translation in a language Django doesn't yet support,
@ -598,9 +609,9 @@ Notes:
('en', ugettext('English')),
)
With this arrangement, ``make-messages.py`` will still find and mark
these strings for translation, but the translation won't happen at
runtime -- so you'll have to remember to wrap the languages in the *real*
With this arrangement, ``django-admin.py makemessages`` will still find
and mark these strings for translation, but the translation won't happen
at runtime -- so you'll have to remember to wrap the languages in the *real*
``ugettext()`` in any code that uses ``LANGUAGES`` at runtime.
* The ``LocaleMiddleware`` can only select languages for which there is a
@ -677,15 +688,16 @@ All message file repositories are structured the same way. They are:
searched in that order for ``<language>/LC_MESSAGES/django.(po|mo)``
* ``$PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|mo)``
To create message files, you use the same ``make-messages.py`` tool as with the
Django message files. You only need to be in the right place -- in the directory
where either the ``conf/locale`` (in case of the source tree) or the ``locale/``
(in case of app messages or project messages) directory are located. And you
use the same ``compile-messages.py`` to produce the binary ``django.mo`` files
that are used by ``gettext``.
To create message files, you use the same ``django-admin.py makemessages``
tool as with the Django message files. You only need to be in the right place
-- in the directory where either the ``conf/locale`` (in case of the source
tree) or the ``locale/`` (in case of app messages or project messages)
directory are located. And you use the same ``django-admin.py compilemessages``
to produce the binary ``django.mo`` files that are used by ``gettext``.
You can also run ``compile-message.py --settings=path.to.settings`` to make
the compiler process all the directories in your ``LOCALE_PATHS`` setting.
You can also run ``django-admin.py compilemessages --settings=path.to.settings``
to make the compiler process all the directories in your ``LOCALE_PATHS``
setting.
Application message files are a bit complicated to discover -- they need the
``LocaleMiddleware``. If you don't use the middleware, only the Django message
@ -695,15 +707,15 @@ Finally, you should give some thought to the structure of your translation
files. If your applications need to be delivered to other users and will
be used in other projects, you might want to use app-specific translations.
But using app-specific translations and project translations could produce
weird problems with ``make-messages``: ``make-messages`` will traverse all
weird problems with ``makemessages``: ``makemessages`` will traverse all
directories below the current path and so might put message IDs into the
project message file that are already in application message files.
The easiest way out is to store applications that are not part of the project
(and so carry their own translations) outside the project tree. That way,
``make-messages`` on the project level will only translate strings that are
connected to your explicit project and not strings that are distributed
independently.
``django-admin.py makemessages`` on the project level will only translate
strings that are connected to your explicit project and not strings that are
distributed independently.
The ``set_language`` redirect view
==================================
@ -858,14 +870,14 @@ Creating JavaScript translation catalogs
----------------------------------------
You create and update the translation catalogs the same way as the other
Django translation catalogs -- with the make-messages.py tool. The only
difference is you need to provide a ``-d djangojs`` parameter, like this::
Django translation catalogs -- with the django-admin.py makemessages tool. The
only difference is you need to provide a ``-d djangojs`` parameter, like this::
make-messages.py -d djangojs -l de
django-admin.py makemessages -d djangojs -l de
This would create or update the translation catalog for JavaScript for German.
After updating translation catalogs, just run ``compile-messages.py`` the same
way as you do with normal Django translation catalogs.
After updating translation catalogs, just run ``django-admin.py compilemessages``
the same way as you do with normal Django translation catalogs.
Specialties of Django translation
==================================

View File

@ -1,40 +0,0 @@
.TH "compile-messages.py" "1" "August 2007" "Django Project" ""
.SH "NAME"
compile-messages.py \- Internationalization utility for the Django
web framework
.SH "SYNOPSIS"
.B compile-messages.py \fR[-l <locale>]
.SH "DESCRIPTION"
A Django-customised wrapper around gettext's \fBmsgfmt\fR command. Generates
binary message catalogs (.mo files) from textual translation descriptions (.po
files).
.sp
The script should be invoked after running
.BI make-messages.py,
in the same directory from which
.BI make-messages.py
was invoked.
.SH "OPTIONS"
.TP
.I \-l <locale>
Compile the message catalogs for a specific locale. If this option is omitted,
all message catalogs are (re-)compiled.
.SH "SEE ALSO"
The man page for
.BI msgfmt
from the GNU gettext utilities, and the internationalization documentation
for Django:
.sp
.I http://www.djangoproject.com/documentation/i18n/
.SH "AUTHORS/CREDITS"
Originally developed at World Online in Lawrence, Kansas, USA. Refer to the
AUTHORS file in the Django distribution for contributors.
.SH "LICENSE"
New BSD license. For the full license text refer to the LICENSE file in the
Django distribution.

View File

@ -1,4 +1,4 @@
.TH "django-admin.py" "1" "June 2007" "Django Project" ""
.TH "django-admin.py" "1" "March 2008" "Django Project" ""
.SH "NAME"
django\-admin.py \- Utility script for the Django web framework
.SH "SYNOPSIS"
@ -21,6 +21,12 @@ script found at the top level of each Django project directory.
.BI "adminindex [" "appname ..." "]"
Prints the admin\-index template snippet for the given app name(s).
.TP
.BI cleanup
Cleans out old data from the database (only expired sessions at the moment).
.TP
.BI "compilemessages [" "\-\-locale=LOCALE" "]"
Compiles .po files to .mo files for use with builtin gettext support.
.TP
.BI "createcachetable [" "tablename" "]"
Creates the table needed to use the SQL cache backend
.TP
@ -43,6 +49,11 @@ Executes
.B sqlall
for the given app(s) in the current database.
.TP
.BI "makemessages [" "\-\-locale=LOCALE" "] [" "\-\-domain=DOMAIN" "] [" "\-\-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
conf/locale (in the django tree) or locale (for project and application) directory.
.TP
.BI "reset [" "appname ..." "]"
Executes
.B sqlreset
@ -136,7 +147,15 @@ Verbosity level: 0=minimal output, 1=normal output, 2=all output.
.TP
.I \-\-adminmedia=ADMIN_MEDIA_PATH
Specifies the directory from which to serve admin media when using the development server.
.TP
.I \-l, \-\-locale=LOCALE
The locale to process when using makemessages or compilemessages.
.TP
.I \-d, \-\-domain=DOMAIN
The domain of the message files (default: "django") when using makemessages.
.TP
.I \-a, \-\-all
Process all available locales when using makemessages.
.SH "ENVIRONMENT"
.TP
.I DJANGO_SETTINGS_MODULE

View File

@ -1,62 +0,0 @@
.TH "make-messages.py" "1" "August 2007" "Django Project" ""
.SH "NAME"
make-messages.py \- Internationalization utility for the Django
web framework
.SH "SYNOPSIS"
.B make-messages.py\fR [\-a] [\-v] [\-l <locale>] [\-d <domain>]
.SH "DESCRIPTION"
This script creates or updates one or more message files for a Django app,
a Django project or the Django framework itself. It should be run from one
of three places: the root directory of a Django app; the root directory
of a Django project; or the root django directory (the one in your PYTHONPATH,
not the root of a Subversion checkout).
.sp
The script will run over the source tree of an application, project or Django
itself (depending on where it is invoked), pulling out all strings marked for
translation and creating or updating a standard PO-format message file for the
specified language. Refer to Django's internationalization documentation for
details of where this file is created.
.sp
The \fI\-a\fR and \fI\-l\fR options are used to control whether message
catalogs are created for all locales, or just a single one.
.SH "OPTIONS"
.TP
.I \-a
Run make-messages for all locales specified in the Django settings file. Cannot
be used in conjuntion with \fI\-l\fR.
.TP
.I \-d <domain>
Specifies the translation domain to use. Valid domains are \fIdjango\fR or
\fIdjangojs\fR, depending on whether you wish to generate translation strings
for the Python or JavaScript components of your app, your project or the
framework itself. The default domain is \fIdjango\fR.
.TP
.I \-l <locale>
Extract messages for a particular locale.
.TP
.I \-v
Run verbosely.
.SH "ENVIRONMENT"
.TP
.I DJANGO_SETTINGS_MODULE
This environment variable defines the settings module to be read.
It should be in Python-import form, e.g. "myproject.settings".
.SH "SEE ALSO"
The Django internationalization documentation:
.sp
.I http://www.djangoproject.com/documentation/i18n/
.sp
The PO file format is documented in the GNU gettext documentation.
.SH "AUTHORS/CREDITS"
Originally developed at World Online in Lawrence, Kansas, USA. Refer to the
AUTHORS file in the Django distribution for contributors.
.SH "LICENSE"
New BSD license. For the full license text refer to the LICENSE file in the
Django distribution.

View File

@ -349,7 +349,7 @@ table. Django updates this row each time the session data changes. If the user
logs out manually, Django deletes the row. But if the user does *not* log out,
the row never gets deleted.
Django provides a sample clean-up script in ``django/bin/daily_cleanup.py``.
Django provides a sample clean-up script in ``django-admin.py cleanup``.
That script deletes any session in the session table whose ``expire_date`` is
in the past -- but your application may have different requirements.

View File

@ -682,10 +682,10 @@ settings file::
('en', gettext('English')),
)
With this arrangement, ``make-messages.py`` will still find and mark these
strings for translation, but the translation won't happen at runtime -- so
you'll have to remember to wrap the languages in the *real* ``gettext()`` in
any code that uses ``LANGUAGES`` at runtime.
With this arrangement, ``django-admin.py makemessages`` will still find and
mark these strings for translation, but the translation won't happen at
runtime -- so you'll have to remember to wrap the languages in the *real*
``gettext()`` in any code that uses ``LANGUAGES`` at runtime.
LOCALE_PATHS
------------

View File

@ -42,13 +42,13 @@ _django_completion()
prev="${COMP_WORDS[COMP_CWORD-1]}"
# Standalone options
opts="--help --settings --pythonpath --noinput --noreload --format --indent --verbosity --adminmedia --version"
opts="--help --settings --pythonpath --noinput --noreload --format --indent --verbosity --adminmedia --version --locale --domain"
# Actions
actions="adminindex createcachetable createsuperuser dbshell diffsettings \
dumpdata flush inspectdb loaddata reset runfcgi runserver \
shell sql sqlall sqlclear sqlcustom sqlflush sqlindexes \
sqlreset sqlsequencereset startapp startproject \
syncdb test validate"
actions="adminindex createcachetable createsuperuser compilemessages \
dbshell diffsettings dumpdata flush inspectdb loaddata \
makemessages reset runfcgi runserver shell sql sqlall sqlclear \
sqlcustom sqlflush sqlindexes sqlreset sqlsequencereset startapp \
startproject syncdb test validate"
# Action's options
action_shell_opts="--plain"
action_runfcgi_opts="host port socket method maxspare minspare maxchildren daemonize pidfile workdir"
@ -118,8 +118,9 @@ _django_completion()
return 0
;;
createcachetable|dbshell|diffsettings| \
inspectdb|runserver|startapp|startproject|syncdb| \
createcachetable|cleanup|compilemessages|dbshell| \
diffsettings|inspectdb|makemessages| \
runserver|startapp|startproject|syncdb| \
validate)
COMPREPLY=()
return 0