Commit 839edceb authored by Matthew Somerville's avatar Matthew Somerville Committed by Tim Graham
Browse files

Fixed #21695 -- Added asvar option to blocktrans.

Thanks Bojan Mihelac for the initial patch.
parent b35b43df
Loading
Loading
Loading
Loading
+24 −3
Original line number Diff line number Diff line
@@ -96,7 +96,7 @@ class TranslateNode(Node):
class BlockTranslateNode(Node):

    def __init__(self, extra_context, singular, plural=None, countervar=None,
            counter=None, message_context=None, trimmed=False):
            counter=None, message_context=None, trimmed=False, asvar=None):
        self.extra_context = extra_context
        self.singular = singular
        self.plural = plural
@@ -104,6 +104,7 @@ class BlockTranslateNode(Node):
        self.counter = counter
        self.message_context = message_context
        self.trimmed = trimmed
        self.asvar = asvar

    def render_token_list(self, tokens):
        result = []
@@ -166,6 +167,10 @@ class BlockTranslateNode(Node):
                    "string returned by gettext: %r using %r" % (result, data))
            with translation.override(None):
                result = self.render(context, nested=True)
        if self.asvar:
            context[self.asvar] = result
            return ''
        else:
            return result


@@ -429,6 +434,13 @@ def do_block_translate(parser, token):
        {% blocktrans with foo|filter as bar and baz|filter as boo %}
        {% blocktrans count var|length as count %}

    The translated string can be stored in a variable using `asvar`::

        {% blocktrans with bar=foo|filter boo=baz|filter asvar var %}
        This is {{ bar }} and {{ boo }}.
        {% endblocktrans %}
        {{ var }}

    Contextual translations are supported::

        {% blocktrans with bar=foo|filter context "greeting" %}
@@ -442,6 +454,7 @@ def do_block_translate(parser, token):

    options = {}
    remaining_bits = bits[1:]
    asvar = None
    while remaining_bits:
        option = remaining_bits.pop(0)
        if option in options:
@@ -468,6 +481,13 @@ def do_block_translate(parser, token):
                six.reraise(TemplateSyntaxError, TemplateSyntaxError(msg), sys.exc_info()[2])
        elif option == "trimmed":
            value = True
        elif option == "asvar":
            try:
                value = remaining_bits.pop(0)
            except IndexError:
                msg = "No argument provided to the '%s' tag for the asvar option." % bits[0]
                six.reraise(TemplateSyntaxError, TemplateSyntaxError(msg), sys.exc_info()[2])
            asvar = value
        else:
            raise TemplateSyntaxError('Unknown argument for %r tag: %r.' %
                                      (bits[0], option))
@@ -506,7 +526,8 @@ 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, trimmed=trimmed)
                              counter, message_context, trimmed=trimmed,
                              asvar=asvar)


@register.tag
+3 −0
Original line number Diff line number Diff line
@@ -332,6 +332,9 @@ Internationalization
  project and it will find all the app message files that were created by
  :djadmin:`makemessages`.

* :ttag:`blocktrans` supports assigning its output to a variable using
  ``asvar``.

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

+18 −2
Original line number Diff line number Diff line
@@ -580,8 +580,9 @@ use the following syntax::
    <title>{{ the_title }}</title>
    <meta name="description" content="{{ the_title }}">

In practice you'll use this to get strings that are used in multiple places
or should be used as arguments for other template tags or filters::
In practice you'll use this to get a string you can use in multiple places in a
template or so you can use the output as an argument for other template tags or
filters::

    {% trans "starting point" as start %}
    {% trans "end point" as end %}
@@ -682,6 +683,21 @@ be retrieved (and stored) beforehand::
    This is a URL: {{ the_url }}
    {% endblocktrans %}

If you'd like to retrieve a translated string without displaying it, you can
use the following syntax::

    {% blocktrans asvar the_title %}The title is {{ title }}.{% endblocktrans %}
    <title>{{ the_title }}</title>
    <meta name="description" content="{{ the_title }}">

In practice you'll use this to get a string you can use in multiple places in a
template or so you can use the output as an argument for other template tags or
filters.

.. versionchanged:: 1.9

    The ``asvar`` syntax was added.

``{% blocktrans %}`` also supports :ref:`contextual
markers<contextual-markers>` using the ``context`` keyword:

+35 −0
Original line number Diff line number Diff line
@@ -435,6 +435,35 @@ class I18nTagTests(SimpleTestCase):
            'fr: French/français/francouzsky bidi=False; '
        )

    # blocktrans tag with asvar
    @setup({'i18n39': '{% load i18n %}'
                      '{% blocktrans asvar page_not_found %}Page not found{% endblocktrans %}'
                      '>{{ page_not_found }}<'})
    def test_i18n39(self):
        with translation.override('de'):
            output = self.engine.render_to_string('i18n39')
        self.assertEqual(output, '>Seite nicht gefunden<')

    @setup({'i18n40': '{% load i18n %}'
                      '{% trans "Page not found" as pg_404 %}'
                      '{% blocktrans with page_not_found=pg_404 asvar output %}'
                      'Error: {{ page_not_found }}'
                      '{% endblocktrans %}'})
    def test_i18n40(self):
        output = self.engine.render_to_string('i18n40')
        self.assertEqual(output, '')

    @setup({'i18n41': '{% load i18n %}'
                      '{% trans "Page not found" as pg_404 %}'
                      '{% blocktrans with page_not_found=pg_404 asvar output %}'
                      'Error: {{ page_not_found }}'
                      '{% endblocktrans %}'
                      '>{{ output }}<'})
    def test_i18n41(self):
        with translation.override('de'):
            output = self.engine.render_to_string('i18n41')
        self.assertEqual(output, '>Error: Seite nicht gefunden<')

    @setup({'template': '{% load i18n %}{% trans %}A}'})
    def test_syntax_error_no_arguments(self):
        msg = "'trans' takes at least one argument"
@@ -453,6 +482,12 @@ class I18nTagTests(SimpleTestCase):
        with self.assertRaisesMessage(TemplateSyntaxError, msg):
            self.engine.render_to_string('template')

    @setup({'template': '{% load i18n %}{% blocktrans asvar %}Yes{% endblocktrans %}'})
    def test_blocktrans_syntax_error_missing_assignment(self):
        msg = "No argument provided to the 'blocktrans' tag for the asvar option."
        with self.assertRaisesMessage(TemplateSyntaxError, msg):
            self.engine.render_to_string('template')

    @setup({'template': '{% load i18n %}{% trans "Yes" as var context %}'})
    def test_syntax_error_missing_context(self):
        msg = "No argument provided to the 'trans' tag for the context option."