Fixed #10004 and #12320 -- Enabled the makemessages management command to collect comments for translators that start with the "Translators" keyword. Thanks for the report and patches, martinb and Claude Paroz.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@14595 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
d7ad02ff72
commit
17b329ae08
|
@ -196,7 +196,7 @@ def make_messages(locale=None, domain='django', verbosity='1', all=False,
|
||||||
'xgettext -d %s -L Perl %s --keyword=gettext_noop '
|
'xgettext -d %s -L Perl %s --keyword=gettext_noop '
|
||||||
'--keyword=gettext_lazy --keyword=ngettext_lazy:1,2 '
|
'--keyword=gettext_lazy --keyword=ngettext_lazy:1,2 '
|
||||||
'--keyword=pgettext:1c,2 --keyword=npgettext:1c,2,3 '
|
'--keyword=pgettext:1c,2 --keyword=npgettext:1c,2,3 '
|
||||||
'--from-code UTF-8 -o - "%s"' % (
|
'--from-code UTF-8 --add-comments=Translators -o - "%s"' % (
|
||||||
domain, wrap, os.path.join(dirpath, thefile)
|
domain, wrap, os.path.join(dirpath, thefile)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -240,8 +240,9 @@ def make_messages(locale=None, domain='django', verbosity='1', all=False,
|
||||||
'--keyword=ugettext_noop --keyword=ugettext_lazy '
|
'--keyword=ugettext_noop --keyword=ugettext_lazy '
|
||||||
'--keyword=ungettext_lazy:1,2 --keyword=pgettext:1c,2 '
|
'--keyword=ungettext_lazy:1,2 --keyword=pgettext:1c,2 '
|
||||||
'--keyword=npgettext:1c,2,3 --keyword=pgettext_lazy:1c,2 '
|
'--keyword=npgettext:1c,2,3 --keyword=pgettext_lazy:1c,2 '
|
||||||
'--keyword=npgettext_lazy:1c,2,3 --from-code UTF-8 -o - '
|
'--keyword=npgettext_lazy:1c,2,3 --from-code UTF-8 '
|
||||||
'"%s"' % (domain, wrap, os.path.join(dirpath, thefile))
|
'--add-comments=Translators -o - "%s"' % (
|
||||||
|
domain, wrap, os.path.join(dirpath, thefile))
|
||||||
)
|
)
|
||||||
msgs, errors = _popen(cmd)
|
msgs, errors = _popen(cmd)
|
||||||
if errors:
|
if errors:
|
||||||
|
@ -282,6 +283,8 @@ def make_messages(locale=None, domain='django', verbosity='1', all=False,
|
||||||
raise CommandError("errors happened while running msgmerge\n%s" % errors)
|
raise CommandError("errors happened while running msgmerge\n%s" % errors)
|
||||||
elif not invoked_for_django:
|
elif not invoked_for_django:
|
||||||
msgs = copy_plural_forms(msgs, locale, domain, verbosity)
|
msgs = copy_plural_forms(msgs, locale, domain, verbosity)
|
||||||
|
msgs = msgs.replace(
|
||||||
|
"#. #-#-#-#-# %s.pot (PACKAGE VERSION) #-#-#-#-#\n" % domain, "")
|
||||||
f = open(pofile, 'wb')
|
f = open(pofile, 'wb')
|
||||||
try:
|
try:
|
||||||
f.write(msgs)
|
f.write(msgs)
|
||||||
|
|
|
@ -82,6 +82,7 @@ VARIABLE_TAG_START = '{{'
|
||||||
VARIABLE_TAG_END = '}}'
|
VARIABLE_TAG_END = '}}'
|
||||||
COMMENT_TAG_START = '{#'
|
COMMENT_TAG_START = '{#'
|
||||||
COMMENT_TAG_END = '#}'
|
COMMENT_TAG_END = '#}'
|
||||||
|
TRANSLATOR_COMMENT_MARK = 'Translators'
|
||||||
SINGLE_BRACE_START = '{'
|
SINGLE_BRACE_START = '{'
|
||||||
SINGLE_BRACE_END = '}'
|
SINGLE_BRACE_END = '}'
|
||||||
|
|
||||||
|
@ -237,7 +238,10 @@ class Lexer(object):
|
||||||
elif token_string.startswith(BLOCK_TAG_START):
|
elif token_string.startswith(BLOCK_TAG_START):
|
||||||
token = Token(TOKEN_BLOCK, token_string[len(BLOCK_TAG_START):-len(BLOCK_TAG_END)].strip())
|
token = Token(TOKEN_BLOCK, token_string[len(BLOCK_TAG_START):-len(BLOCK_TAG_END)].strip())
|
||||||
elif token_string.startswith(COMMENT_TAG_START):
|
elif token_string.startswith(COMMENT_TAG_START):
|
||||||
token = Token(TOKEN_COMMENT, '')
|
content = ''
|
||||||
|
if token_string.find(TRANSLATOR_COMMENT_MARK):
|
||||||
|
content = token_string[len(COMMENT_TAG_START):-len(COMMENT_TAG_END)].strip()
|
||||||
|
token = Token(TOKEN_COMMENT, content)
|
||||||
else:
|
else:
|
||||||
token = Token(TOKEN_TEXT, token_string)
|
token = Token(TOKEN_TEXT, token_string)
|
||||||
return token
|
return token
|
||||||
|
|
|
@ -427,14 +427,23 @@ def templatize(src):
|
||||||
does so by translating the Django translation tags into standard gettext
|
does so by translating the Django translation tags into standard gettext
|
||||||
function invocations.
|
function invocations.
|
||||||
"""
|
"""
|
||||||
from django.template import Lexer, TOKEN_TEXT, TOKEN_VAR, TOKEN_BLOCK
|
from django.template import Lexer, TOKEN_TEXT, TOKEN_VAR, TOKEN_BLOCK, TOKEN_COMMENT
|
||||||
out = StringIO()
|
out = StringIO()
|
||||||
intrans = False
|
intrans = False
|
||||||
inplural = False
|
inplural = False
|
||||||
singular = []
|
singular = []
|
||||||
plural = []
|
plural = []
|
||||||
|
incomment = False
|
||||||
|
comment = []
|
||||||
for t in Lexer(src, None).tokenize():
|
for t in Lexer(src, None).tokenize():
|
||||||
if intrans:
|
if incomment:
|
||||||
|
if t.token_type == TOKEN_BLOCK and t.contents == 'endcomment':
|
||||||
|
out.write(' # %s' % ''.join(comment))
|
||||||
|
incomment = False
|
||||||
|
comment = []
|
||||||
|
else:
|
||||||
|
comment.append(t.contents)
|
||||||
|
elif intrans:
|
||||||
if t.token_type == TOKEN_BLOCK:
|
if t.token_type == TOKEN_BLOCK:
|
||||||
endbmatch = endblock_re.match(t.contents)
|
endbmatch = endblock_re.match(t.contents)
|
||||||
pluralmatch = plural_re.match(t.contents)
|
pluralmatch = plural_re.match(t.contents)
|
||||||
|
@ -488,6 +497,8 @@ def templatize(src):
|
||||||
elif cmatches:
|
elif cmatches:
|
||||||
for cmatch in cmatches:
|
for cmatch in cmatches:
|
||||||
out.write(' _(%s) ' % cmatch)
|
out.write(' _(%s) ' % cmatch)
|
||||||
|
elif t.contents == 'comment':
|
||||||
|
incomment = True
|
||||||
else:
|
else:
|
||||||
out.write(blankout(t.contents, 'B'))
|
out.write(blankout(t.contents, 'B'))
|
||||||
elif t.token_type == TOKEN_VAR:
|
elif t.token_type == TOKEN_VAR:
|
||||||
|
@ -500,6 +511,8 @@ def templatize(src):
|
||||||
out.write(' %s ' % p.split(':',1)[1])
|
out.write(' %s ' % p.split(':',1)[1])
|
||||||
else:
|
else:
|
||||||
out.write(blankout(p, 'F'))
|
out.write(blankout(p, 'F'))
|
||||||
|
elif t.token_type == TOKEN_COMMENT:
|
||||||
|
out.write(' # %s' % t.contents)
|
||||||
else:
|
else:
|
||||||
out.write(blankout(t.contents, 'X'))
|
out.write(blankout(t.contents, 'X'))
|
||||||
return out.getvalue()
|
return out.getvalue()
|
||||||
|
|
|
@ -39,6 +39,22 @@ See the :doc:`reference documentation of the app </ref/contrib/staticfiles>`
|
||||||
for more details or learn how to :doc:`manage static files
|
for more details or learn how to :doc:`manage static files
|
||||||
</howto/static-files>`.
|
</howto/static-files>`.
|
||||||
|
|
||||||
|
Translation comments
|
||||||
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
If you would like to give translators hints about a translatable string, you
|
||||||
|
can add a comment prefixed with the ``Translators`` keyword on the line
|
||||||
|
preceding the string, e.g.::
|
||||||
|
|
||||||
|
def my_view(request):
|
||||||
|
# Translators: This message appears on the home page only
|
||||||
|
output = ugettext("Welcome to my site.")
|
||||||
|
|
||||||
|
The comment will appear in the resulting .po file and should also be
|
||||||
|
displayed by most translation tools.
|
||||||
|
|
||||||
|
For more information, see :ref:`translator-comments`.
|
||||||
|
|
||||||
Backwards-incompatible changes in 1.3 alpha 2
|
Backwards-incompatible changes in 1.3 alpha 2
|
||||||
=============================================
|
=============================================
|
||||||
|
|
||||||
|
|
|
@ -121,13 +121,17 @@ value, protect, or do nothing.
|
||||||
For more information, see the :attr:`~django.db.models.ForeignKey.on_delete`
|
For more information, see the :attr:`~django.db.models.ForeignKey.on_delete`
|
||||||
documentation.
|
documentation.
|
||||||
|
|
||||||
Contextual markers in translatable strings
|
Contextual markers and comments for translatable strings
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
For translation strings with ambiguous meaning, you can now
|
For translation strings with ambiguous meaning, you can now
|
||||||
use the ``pgettext`` function to specify the context of the string.
|
use the ``pgettext`` function to specify the context of the string.
|
||||||
|
|
||||||
For more information, see :ref:`contextual-markers`
|
And if you just want to add some information for translators, you
|
||||||
|
can also add special translator comments in the source.
|
||||||
|
|
||||||
|
For more information, see :ref:`contextual-markers` and
|
||||||
|
:ref:`translator-comments`.
|
||||||
|
|
||||||
Everything else
|
Everything else
|
||||||
~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~
|
||||||
|
|
|
@ -100,6 +100,30 @@ instead of positional interpolation (e.g., ``%s`` or ``%d``) whenever you
|
||||||
have more than a single parameter. If you used positional interpolation,
|
have more than a single parameter. If you used positional interpolation,
|
||||||
translations wouldn't be able to reorder placeholder text.
|
translations wouldn't be able to reorder placeholder text.
|
||||||
|
|
||||||
|
.. _translator-comments:
|
||||||
|
|
||||||
|
Comments for translators
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
.. versionadded:: 1.3
|
||||||
|
|
||||||
|
If you would like to give translators hints about a translatable string, you
|
||||||
|
can add a comment prefixed with the ``Translators`` keyword on the line
|
||||||
|
preceding the string, e.g.::
|
||||||
|
|
||||||
|
def my_view(request):
|
||||||
|
# Translators: This message appears on the home page only
|
||||||
|
output = ugettext("Welcome to my site.")
|
||||||
|
|
||||||
|
This also works in templates with the :ttag:`comment` tag:
|
||||||
|
|
||||||
|
.. code-block:: django+html
|
||||||
|
|
||||||
|
{% comment %}Translators: This is a text of the base template {% endcomment %}
|
||||||
|
|
||||||
|
The comment will then appear in the resulting .po file and should also be
|
||||||
|
displayed by most translation tools.
|
||||||
|
|
||||||
Marking strings as no-op
|
Marking strings as no-op
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
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.")
|
||||||
|
|
|
@ -38,7 +38,18 @@ class ExtractorTests(TestCase):
|
||||||
return self.assert_(not re.search('^msgid %s' % msgid, s, re.MULTILINE))
|
return self.assert_(not re.search('^msgid %s' % msgid, s, re.MULTILINE))
|
||||||
|
|
||||||
|
|
||||||
class TemplateExtractorTests(ExtractorTests):
|
class BasicExtractorTests(ExtractorTests):
|
||||||
|
|
||||||
|
def test_comments_extractor(self):
|
||||||
|
os.chdir(self.test_dir)
|
||||||
|
management.call_command('makemessages', locale=LOCALE, verbosity=0)
|
||||||
|
self.assert_(os.path.exists(self.PO_FILE))
|
||||||
|
po_contents = open(self.PO_FILE, 'r').read()
|
||||||
|
self.assert_('#. Translators: This comment should be extracted' in po_contents)
|
||||||
|
self.assert_('This comment should not be extracted' not in po_contents)
|
||||||
|
# Comments in templates
|
||||||
|
self.assert_('#. Translators: Django template comment for translators' in po_contents)
|
||||||
|
self.assert_('#. Translators: Django comment block for translators' in po_contents)
|
||||||
|
|
||||||
def test_templatize(self):
|
def test_templatize(self):
|
||||||
os.chdir(self.test_dir)
|
os.chdir(self.test_dir)
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
{% comment %}Translators: Django comment block for translators {% endcomment %}
|
||||||
{% trans "This literal should be included." %}
|
{% trans "This literal should be included." %}
|
||||||
{% trans "This literal should also be included wrapped or not wrapped depending on the use of the --no-wrap option." %}
|
{% trans "This literal should also be included wrapped or not wrapped depending on the use of the --no-wrap option." %}
|
||||||
{% blocktrans %}I think that 100% is more that 50% of anything.{% endblocktrans %}
|
|
||||||
|
{# Translators: Django template comment for translators #}
|
||||||
|
<p>{% blocktrans %}I think that 100% is more that 50% of anything.{% endblocktrans %}</p>
|
||||||
{% blocktrans with 'txt' as obj %}I think that 100% is more that 50% of {{ obj }}.{% endblocktrans %}
|
{% blocktrans with 'txt' as obj %}I think that 100% is more that 50% of {{ obj }}.{% endblocktrans %}
|
Loading…
Reference in New Issue