Commit 7a7c789d authored by Bouke Haarsma's avatar Bouke Haarsma Committed by Anssi Kääriäinen
Browse files

Fixed #5849 -- Strip whitespace from blocktrans

Add the trimmed option to the blocktrans tag to trim any newlines and
whitespace from its content.

This allows the developer to indent the blocktrans tag without adding
new lines and whitespace to the msgid in the PO file.

Thanks to mpessas for the initial patch and Dmitri Fedortchenko for the
report.
parent 30203a0d
Loading
Loading
Loading
Loading
+12 −3
Original line number Diff line number Diff line
@@ -97,14 +97,16 @@ class TranslateNode(Node):


class BlockTranslateNode(Node):

    def __init__(self, extra_context, singular, plural=None, countervar=None,
            counter=None, message_context=None):
            counter=None, message_context=None, trimmed=False):
        self.extra_context = extra_context
        self.singular = singular
        self.plural = plural
        self.countervar = countervar
        self.counter = counter
        self.message_context = message_context
        self.trimmed = trimmed

    def render_token_list(self, tokens):
        result = []
@@ -115,7 +117,10 @@ class BlockTranslateNode(Node):
            elif token.token_type == TOKEN_VAR:
                result.append('%%(%s)s' % token.contents)
                vars.append(token.contents)
        return ''.join(result), vars
        msg = ''.join(result)
        if self.trimmed:
            msg = translation.trim_whitespace(msg)
        return msg, vars

    def render(self, context, nested=False):
        if self.message_context:
@@ -438,6 +443,8 @@ def do_block_translate(parser, token):
                    '"context" in %r tag expected '
                    'exactly one argument.') % bits[0]
                six.reraise(TemplateSyntaxError, TemplateSyntaxError(msg), sys.exc_info()[2])
        elif option == "trimmed":
            value = True
        else:
            raise TemplateSyntaxError('Unknown argument for %r tag: %r.' %
                                      (bits[0], option))
@@ -453,6 +460,8 @@ def do_block_translate(parser, token):
        message_context = None
    extra_context = options.get('with', {})

    trimmed = options.get("trimmed", False)

    singular = []
    plural = []
    while parser.tokens:
@@ -474,7 +483,7 @@ def do_block_translate(parser, token):
        raise TemplateSyntaxError("'blocktrans' doesn't allow other block tags (seen %r) inside it" % token.contents)

    return BlockTranslateNode(extra_context, singular, plural, countervar,
            counter, message_context)
                              counter, message_context, trimmed=trimmed)


@register.tag
+7 −1
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@
Internationalization support.
"""
from __future__ import unicode_literals

import re
from django.utils.encoding import force_text
from django.utils.functional import lazy
from django.utils import six
@@ -218,3 +218,9 @@ def get_language_info(lang_code):
            return LANG_INFO[generic_lang_code]
        except KeyError:
            raise KeyError("Unknown language code %s and %s." % (lang_code, generic_lang_code))

trim_whitespace_re = re.compile('\s*\n\s*')


def trim_whitespace(s):
    return trim_whitespace_re.sub(' ', s.strip())
+17 −5
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@ from django.utils._os import upath
from django.utils.safestring import mark_safe, SafeData
from django.utils import six
from django.utils.six import StringIO
from django.utils.translation import TranslatorCommentWarning
from django.utils.translation import TranslatorCommentWarning, trim_whitespace


# Translations are cached in a dictionary for every language+app tuple.
@@ -530,6 +530,7 @@ def blankout(src, char):
    """
    return dot_re.sub(char, src)


context_re = re.compile(r"""^\s+.*context\s+((?:"[^"]*?")|(?:'[^']*?'))\s*""")
inline_re = re.compile(r"""^\s*trans\s+((?:"[^"]*?")|(?:'[^']*?'))(\s+.*context\s+((?:"[^"]*?")|(?:'[^']*?')))?\s*""")
block_re = re.compile(r"""^\s*blocktrans(\s+.*context\s+((?:"[^"]*?")|(?:'[^']*?')))?(?:\s+|$)""")
@@ -553,6 +554,7 @@ def templatize(src, origin=None):
    message_context = None
    intrans = False
    inplural = False
    trimmed = False
    singular = []
    plural = []
    incomment = False
@@ -582,20 +584,29 @@ def templatize(src, origin=None):
                endbmatch = endblock_re.match(t.contents)
                pluralmatch = plural_re.match(t.contents)
                if endbmatch:
                    if trimmed:
                        singular = trim_whitespace(''.join(singular))
                    else:
                        singular = ''.join(singular)

                    if inplural:
                        if trimmed:
                            plural = trim_whitespace(''.join(plural))
                        else:
                            plural = ''.join(plural)
                        if message_context:
                            out.write(' npgettext(%r, %r, %r,count) ' % (message_context, ''.join(singular), ''.join(plural)))
                            out.write(' npgettext(%r, %r, %r,count) ' % (message_context, singular, plural))
                        else:
                            out.write(' ngettext(%r, %r, count) ' % (''.join(singular), ''.join(plural)))
                            out.write(' ngettext(%r, %r, count) ' % (singular, plural))
                        for part in singular:
                            out.write(blankout(part, 'S'))
                        for part in plural:
                            out.write(blankout(part, 'P'))
                    else:
                        if message_context:
                            out.write(' pgettext(%r, %r) ' % (message_context, ''.join(singular)))
                            out.write(' pgettext(%r, %r) ' % (message_context, singular))
                        else:
                            out.write(' gettext(%r) ' % ''.join(singular))
                            out.write(' gettext(%r) ' % singular)
                        for part in singular:
                            out.write(blankout(part, 'S'))
                    message_context = None
@@ -678,6 +689,7 @@ def templatize(src, origin=None):
                            message_context = message_context.strip("'")
                    intrans = True
                    inplural = False
                    trimmed = 'trimmed' in t.split_contents()
                    singular = []
                    plural = []
                elif cmatches:
+9 −0
Original line number Diff line number Diff line
@@ -342,6 +342,15 @@ Internationalization
  still read from in 1.7. Sessions will be migrated to the new ``_language``
  key as they are written.

* The :ttag:`blocktrans` now supports a ``trimmed`` option. This
  option will remove newline characters from the beginning and the end of the
  content of the ``{% blocktrans %}`` tag, replace any whitespace at the
  beginning and end of a line and merge all lines into one using a space
  character to separate them. This is quite useful for indenting the content of
  a ``{% blocktrans %}`` tag without having the indentation characters end up
  in the corresponding entry in the PO file, which makes the translation
  process easier.

Management Commands
^^^^^^^^^^^^^^^^^^^

+24 −0
Original line number Diff line number Diff line
@@ -674,6 +674,30 @@ markers<contextual-markers>` using the ``context`` keyword:

    {% blocktrans with name=user.username context "greeting" %}Hi {{ name }}{% endblocktrans %}

Another feature ``{% blocktrans %}`` supports is the ``trimmed`` option. This
option will remove newline characters from the beginning and the end of the
content of the ``{% blocktrans %}`` tag, replace any whitespace at the beginning
and end of a line and merge all lines into one using a space character to
separate them. This is quite useful for indenting the content of a ``{%
blocktrans %}`` tag without having the indentation characters end up in the
corresponding entry in the PO file, which makes the translation process easier.

For instance, the following ``{% blocktrans %}`` tag::

    {% blocktrans trimmed %}
      First sentence.
      Second paragraph.
    {% endblocktrans %}

will result in the entry ``"First sentence. Second paragraph."`` in the PO file,
compared to ``"\n  First sentence.\n  Second sentence.\n"``, if the ``trimmed``
option had not been specified.

.. versionchanged:: 1.7

    The ``trimmed`` option was added.


String literals passed to tags and filters
------------------------------------------

Loading