Ticket #14806: 14806.template-tags-pgettext.3.diff

File 14806.template-tags-pgettext.3.diff, 28.7 KB (added by julien, 4 years ago)
  • django/template/base.py

    diff --git a/django/template/base.py b/django/template/base.py
    index 8001e93..3a2b740 100644
    a b from django.utils.itercompat import is_iterable 
    1010from django.utils.text import (smart_split, unescape_string_literal,
    1111    get_text_list)
    1212from django.utils.encoding import smart_unicode, force_unicode, smart_str
    13 from django.utils.translation import ugettext_lazy
     13from django.utils.translation import ugettext_lazy, pgettext_lazy
    1414from django.utils.safestring import (SafeData, EscapeData, mark_safe,
    1515    mark_for_escaping)
    1616from django.utils.formats import localize
    class Variable(object): 
    673673        self.literal = None
    674674        self.lookups = None
    675675        self.translate = False
     676        self.message_context = None
    676677
    677678        try:
    678679            # First try to treat this variable as a number.
    class Variable(object): 
    720721            # We're dealing with a literal, so it's already been "resolved"
    721722            value = self.literal
    722723        if self.translate:
    723             return ugettext_lazy(value)
     724            if self.message_context:
     725                return pgettext_lazy(self.message_context, value)
     726            else:
     727                return ugettext_lazy(value)
    724728        return value
    725729
    726730    def __repr__(self):
  • django/templatetags/i18n.py

    diff --git a/django/templatetags/i18n.py b/django/templatetags/i18n.py
    index 669cdc9..dc3d93e 100644
    a b class GetCurrentLanguageBidiNode(Node): 
    7070
    7171
    7272class TranslateNode(Node):
    73     def __init__(self, filter_expression, noop, asvar=None):
     73    def __init__(self, filter_expression, noop, asvar=None,
     74                 message_context=None):
    7475        self.noop = noop
    7576        self.asvar = asvar
     77        self.message_context = message_context
    7678        self.filter_expression = filter_expression
    7779        if isinstance(self.filter_expression.var, basestring):
    78             self.filter_expression.var = Variable(u"'%s'" % self.filter_expression.var)
     80            self.filter_expression.var = Variable(u"'%s'" %
     81                                                  self.filter_expression.var)
    7982
    8083    def render(self, context):
    8184        self.filter_expression.var.translate = not self.noop
     85        if self.message_context:
     86            self.filter_expression.var.message_context = (
     87                self.message_context.resolve(context))
    8288        output = self.filter_expression.resolve(context)
    8389        value = _render_value_in_context(output, context)
    8490        if self.asvar:
    class TranslateNode(Node): 
    9096
    9197class BlockTranslateNode(Node):
    9298    def __init__(self, extra_context, singular, plural=None, countervar=None,
    93             counter=None):
     99            counter=None, message_context=None):
    94100        self.extra_context = extra_context
    95101        self.singular = singular
    96102        self.plural = plural
    97103        self.countervar = countervar
    98104        self.counter = counter
     105        self.message_context = message_context
    99106
    100107    def render_token_list(self, tokens):
    101108        result = []
    class BlockTranslateNode(Node): 
    109116        return ''.join(result), vars
    110117
    111118    def render(self, context):
     119        if self.message_context:
     120            message_context = self.message_context.resolve(context)
     121        else:
     122            message_context = None
    112123        tmp_context = {}
    113124        for var, val in self.extra_context.items():
    114125            tmp_context[var] = val.resolve(context)
    class BlockTranslateNode(Node): 
    123134            context[self.countervar] = count
    124135            plural, plural_vars = self.render_token_list(self.plural)
    125136            plural = re.sub(u'%(?!\()', u'%%', plural)
    126             result = translation.ungettext(singular, plural, count)
     137            if message_context:
     138                result = translation.npgettext(message_context, singular,
     139                                               plural, count)
     140            else:
     141                result = translation.ungettext(singular, plural, count)
    127142            vars.extend(plural_vars)
    128143        else:
    129             result = translation.ugettext(singular)
     144            if message_context:
     145                result = translation.pgettext(message_context, singular)
     146            else:
     147                result = translation.ugettext(singular)
    130148        data = dict([(v, _render_value_in_context(context.get(v, ''), context)) for v in vars])
    131149        context.pop()
    132150        try:
    def do_translate(parser, token): 
    290308    This will just try to translate the contents of
    291309    the variable ``variable``. Make sure that the string
    292310    in there is something that is in the .po file.
     311
     312    It is possible to store the translated string into a variable::
     313
     314        {% trans "this is a test" as var %}
     315        {{ var }}
     316
     317    Contextual translations are also supported::
     318
     319        {% trans "this is a test" context "greeting" %}
     320
     321    This is equivalent to calling pgettext instead of (u)gettext.
    293322    """
    294323    class TranslateParser(TokenParser):
    295324        def top(self):
    def do_translate(parser, token): 
    301330            # backwards compatibility with existing uses of ``trans``
    302331            # where single quote use is supported.
    303332            if value[0] == "'":
    304                 pos = None
    305333                m = re.match("^'([^']+)'(\|.*$)", value)
    306334                if m:
    307335                    value = '"%s"%s' % (m.group(1).replace('"','\\"'), m.group(2))
    def do_translate(parser, token): 
    310338
    311339            noop = False
    312340            asvar = None
     341            message_context = None
    313342
    314343            while self.more():
    315344                tag = self.tag()
    316345                if tag == 'noop':
    317346                    noop = True
     347                elif tag == 'context':
     348                    message_context = parser.compile_filter(self.value())
    318349                elif tag == 'as':
    319350                    asvar = self.tag()
    320351                else:
    321352                    raise TemplateSyntaxError(
    322                         "only options for 'trans' are 'noop' and 'as VAR.")
    323             return (value, noop, asvar)
    324     value, noop, asvar = TranslateParser(token.contents).top()
    325     return TranslateNode(parser.compile_filter(value), noop, asvar)
     353                        "Only options for 'trans' are 'noop', " \
     354                        "'context \"xxx\"', and 'as VAR'.")
     355            return value, noop, asvar, message_context
     356    value, noop, asvar, message_context = TranslateParser(token.contents).top()
     357    return TranslateNode(parser.compile_filter(value), noop, asvar,
     358                         message_context)
    326359
    327360@register.tag("blocktrans")
    328361def do_block_translate(parser, token):
    def do_block_translate(parser, token): 
    349382
    350383        {% blocktrans with foo|filter as bar and baz|filter as boo %}
    351384        {% blocktrans count var|length as count %}
     385
     386    Contextual translations are supported::
     387
     388        {% blocktrans with bar=foo|filter context "greeting" %}
     389            This is {{ bar }}.
     390        {% endblocktrans %}
     391
     392    This is equivalent to calling pgettext/npgettext instead of
     393    (u)gettext/(u)ngettext.
    352394    """
    353395    bits = token.split_contents()
    354396
    def do_block_translate(parser, token): 
    369411            if len(value) != 1:
    370412                raise TemplateSyntaxError('"count" in %r tag expected exactly '
    371413                                          'one keyword argument.' % bits[0])
     414        elif option == "context":
     415            try:
     416                value = remaining_bits.pop(0)
     417                value = parser.compile_filter(value)
     418            except Exception:
     419                raise TemplateSyntaxError('"context" in %r tag expected '
     420                                          'exactly one argument.' % bits[0])
    372421        else:
    373422            raise TemplateSyntaxError('Unknown argument for %r tag: %r.' %
    374423                                      (bits[0], option))
    def do_block_translate(parser, token): 
    378427        countervar, counter = options['count'].items()[0]
    379428    else:
    380429        countervar, counter = None, None
    381     extra_context = options.get('with', {})
     430    if 'context' in options:
     431        message_context = options['context']
     432    else:
     433        message_context = None
     434    extra_context = options.get('with', {})
    382435
    383436    singular = []
    384437    plural = []
    def do_block_translate(parser, token): 
    401454        raise TemplateSyntaxError("'blocktrans' doesn't allow other block tags (seen %r) inside it" % token.contents)
    402455
    403456    return BlockTranslateNode(extra_context, singular, plural, countervar,
    404             counter)
     457            counter, message_context)
    405458
    406459@register.tag
    407460def language(parser, token):
  • django/utils/translation/trans_real.py

    diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py
    index 71765e7..f43cfd9 100644
    a b def blankout(src, char): 
    433433    """
    434434    return dot_re.sub(char, src)
    435435
    436 inline_re = re.compile(r"""^\s*trans\s+((?:".*?")|(?:'.*?'))\s*""")
    437 block_re = re.compile(r"""^\s*blocktrans(?:\s+|$)""")
     436context_re = re.compile(r"""^\s+.*context\s+((?:"[^"]*?")|(?:'[^']*?'))\s*""")
     437inline_re = re.compile(r"""^\s*trans\s+((?:"[^"]*?")|(?:'[^']*?'))(\s+.*context\s+(?:"[^"]*?")|(?:'[^']*?'))?\s*""")
     438block_re = re.compile(r"""^\s*blocktrans(\s+.*context\s+(?:"[^"]*?")|(?:'[^']*?'))?(?:\s+|$)""")
    438439endblock_re = re.compile(r"""^\s*endblocktrans$""")
    439440plural_re = re.compile(r"""^\s*plural$""")
    440441constant_re = re.compile(r"""_\(((?:".*?")|(?:'.*?'))\)""")
    441442
     443
    442444def templatize(src, origin=None):
    443445    """
    444446    Turns a Django template into something that is understood by xgettext. It
    def templatize(src, origin=None): 
    448450    from django.template import (Lexer, TOKEN_TEXT, TOKEN_VAR, TOKEN_BLOCK,
    449451            TOKEN_COMMENT, TRANSLATOR_COMMENT_MARK)
    450452    out = StringIO()
     453    message_context = None
    451454    intrans = False
    452455    inplural = False
    453456    singular = []
    def templatize(src, origin=None): 
    477480                pluralmatch = plural_re.match(t.contents)
    478481                if endbmatch:
    479482                    if inplural:
    480                         out.write(' ngettext(%r,%r,count) ' % (''.join(singular), ''.join(plural)))
     483                        if message_context:
     484                            out.write(' npgettext(%r, %r, %r,count) ' % (message_context, ''.join(singular), ''.join(plural)))
     485                        else:
     486                            out.write(' ngettext(%r, %r, count) ' % (''.join(singular), ''.join(plural)))
    481487                        for part in singular:
    482488                            out.write(blankout(part, 'S'))
    483489                        for part in plural:
    484490                            out.write(blankout(part, 'P'))
    485491                    else:
    486                         out.write(' gettext(%r) ' % ''.join(singular))
     492                        if message_context:
     493                            out.write(' pgettext(%r, %r) ' % (message_context, ''.join(singular)))
     494                        else:
     495                            out.write(' gettext(%r) ' % ''.join(singular))
    487496                        for part in singular:
    488497                            out.write(blankout(part, 'S'))
     498                    message_context = None
    489499                    intrans = False
    490500                    inplural = False
    491501                    singular = []
    def templatize(src, origin=None): 
    515525                cmatches = constant_re.findall(t.contents)
    516526                if imatch:
    517527                    g = imatch.group(1)
    518                     if g[0] == '"': g = g.strip('"')
    519                     elif g[0] == "'": g = g.strip("'")
    520                     out.write(' gettext(%r) ' % g)
     528                    if g[0] == '"':
     529                        g = g.strip('"')
     530                    elif g[0] == "'":
     531                        g = g.strip("'")
     532                    if imatch.group(2):
     533                        # A context is provided
     534                        context_match = context_re.match(imatch.group(2))
     535                        message_context = context_match.group(1)
     536                        if message_context[0] == '"':
     537                            message_context = message_context.strip('"')
     538                        elif message_context[0] == "'":
     539                            message_context = message_context.strip("'")
     540                        out.write(' pgettext(%r, %r) ' % (message_context, g))
     541                        message_context = None
     542                    else:
     543                        out.write(' gettext(%r) ' % g)
    521544                elif bmatch:
    522545                    for fmatch in constant_re.findall(t.contents):
    523546                        out.write(' _(%s) ' % fmatch)
     547                    if bmatch.group(1):
     548                        # A context is provided
     549                        context_match = context_re.match(bmatch.group(1))
     550                        message_context = context_match.group(1)
     551                        if message_context[0] == '"':
     552                            message_context = message_context.strip('"')
     553                        elif message_context[0] == "'":
     554                            message_context = message_context.strip("'")
    524555                    intrans = True
    525556                    inplural = False
    526557                    singular = []
  • docs/releases/1.4.txt

    diff --git a/docs/releases/1.4.txt b/docs/releases/1.4.txt
    index 3e364fb..00acc65 100644
    a b Additionally, it's now possible to define translatable URL patterns using 
    191191:ref:`url-internationalization` for more information about the language prefix
    192192and how to internationalize URL patterns.
    193193
     194Contextual translation support for ``{% trans %}`` and ``{% blocktrans %}``
     195~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     196
     197Django 1.3 introduced :ref:`contextual translation<contextual-markers>` support
     198in Python files via the ``pgettext`` function. This is now also supported by
     199the :ttag:`trans` and :ttag:`blocktrans` template tags using the new
     200``context`` keyword.
     201
    194202Customizable ``SingleObjectMixin`` URLConf kwargs
    195203~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    196204
  • docs/topics/i18n/internationalization.txt

    diff --git a/docs/topics/i18n/internationalization.txt b/docs/topics/i18n/internationalization.txt
    index b06c9bd..7dc3db0 100644
    a b will appear in the .po file as: 
    266266    msgid "May"
    267267    msgstr ""
    268268
     269.. versionadded:: 1.4
     270
     271Contextual markers are also supported by the :ttag:`trans` and
     272:ttag:`blocktrans` template tags.
     273
    269274.. _lazy-translations:
    270275
    271276Lazy translation
    It's not possible to mix a template variable inside a string within ``{% trans 
    453458%}``. If your translations require strings with variables (placeholders), use
    454459``{% blocktrans %}`` instead.
    455460
    456 .. versionchanged:: 1.4
     461.. versionadded:: 1.4
    457462
    458463If you'd like to retrieve a translated string without displaying it, you can
    459464use the following syntax::
    or should be used as arguments for other template tags or filters:: 
    479484    {% endfor %}
    480485    </p>
    481486
     487.. versionadded:: 1.4
     488
     489``{% trans %}`` also supports :ref:`contextual markers<contextual-markers>`
     490using the ``context`` keyword:
     491
     492.. code-block:: html+django
     493
     494    {% trans "May" context "month name" %}
     495
    482496.. templatetag:: blocktrans
    483497
    484498``blocktrans`` template tag
    be retrieved (and stored) beforehand:: 
    560574    This is a URL: {{ the_url }}
    561575    {% endblocktrans %}
    562576
     577.. versionadded:: 1.4
     578
     579``{% blocktrans %}`` also supports :ref:`contextual
     580markers<contextual-markers>` using the ``context`` keyword:
     581
     582.. code-block:: html+django
     583
     584    {% blocktrans with name=user.username context="greeting" %}Hi {{ name }}{% endblocktrans %}
     585
    563586.. _template-translation-vars:
    564587
    565588Other tags
  • tests/regressiontests/i18n/commands/extraction.py

    diff --git a/tests/regressiontests/i18n/commands/extraction.py b/tests/regressiontests/i18n/commands/extraction.py
    index 7d7cdf7..c495772 100644
    a b class BasicExtractorTests(ExtractorTests): 
    9494            os.remove('./templates/template_with_error.html')
    9595            os.remove('./templates/template_with_error.html.py') # Waiting for #8536 to be fixed
    9696
     97    def test_template_message_context_extractor(self):
     98        """
     99        Ensure that message contexts are correctly extracted for the
     100        {% trans %} and {% blocktrans %} template tags.
     101        Refs #14806.
     102        """
     103        os.chdir(self.test_dir)
     104        management.call_command('makemessages', locale=LOCALE, verbosity=0)
     105        self.assertTrue(os.path.exists(self.PO_FILE))
     106        po_contents = open(self.PO_FILE, 'r').read()
     107        # {% trans %}
     108        self.assertTrue('msgctxt "Special trans context #1"' in po_contents)
     109        self.assertTrue("Translatable literal #7a" in po_contents)
     110        self.assertTrue('msgctxt "Special trans context #2"' in po_contents)
     111        self.assertTrue("Translatable literal #7b" in po_contents)
     112        self.assertTrue('msgctxt "Special trans context #3"' in po_contents)
     113        self.assertTrue("Translatable literal #7c" in po_contents)
     114
     115        # {% blocktrans %}
     116        self.assertTrue('msgctxt "Special blocktrans context #1"' in po_contents)
     117        self.assertTrue("Translatable literal #8a" in po_contents)
     118        self.assertTrue('msgctxt "Special blocktrans context #2"' in po_contents)
     119        self.assertTrue("Translatable literal #8b-singular" in po_contents)
     120        self.assertTrue("Translatable literal #8b-plural" in po_contents)
     121        self.assertTrue('msgctxt "Special blocktrans context #3"' in po_contents)
     122        self.assertTrue("Translatable literal #8c-singular" in po_contents)
     123        self.assertTrue("Translatable literal #8c-plural" in po_contents)
     124        self.assertTrue('msgctxt "Special blocktrans context #4"' in po_contents)
     125        self.assertTrue("Translatable literal #8d" in po_contents)
    97126
    98127class JavascriptExtractorTests(ExtractorTests):
    99128
  • tests/regressiontests/i18n/commands/templates/test.html

    diff --git a/tests/regressiontests/i18n/commands/templates/test.html b/tests/regressiontests/i18n/commands/templates/test.html
    index b5d705c..24fc708 100644
    a b continued here.{% endcomment %} 
    5757{% comment %}  Translators: Two-line translator comment #5 -- with non ASCII characters: áéíóúö
    5858continued here.{% endcomment %}
    5959{% trans "Translatable literal #6b" %}
     60
     61{% trans "Translatable literal #7a" context "Special trans context #1" %}
     62{% trans "Translatable literal #7b" as var context "Special trans context #2" %}
     63{% trans "Translatable literal #7c" context "Special trans context #3" as var %}
     64
     65{% blocktrans context "Special blocktrans context #1" %}Translatable literal #8a{% endblocktrans %}
     66{% blocktrans count 2 context "Special blocktrans context #2" %}Translatable literal #8b-singular{% plural %}Translatable literal #8b-plural{% endblocktrans %}
     67{% blocktrans context "Special blocktrans context #3" count 2 %}Translatable literal #8c-singular{% plural %}Translatable literal #8c-plural{% endblocktrans %}
     68{% blocktrans with a=1 context "Special blocktrans context #4" %}Translatable literal #8d {{ a }}{% endblocktrans %}
     69 No newline at end of file
  • tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.po

    diff --git a/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.mo b/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.mo
    index a1a93c8..f825e39 100644
    Binary files a/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.mo and b/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.mo differ
    diff --git a/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.po b/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.po
    index 7226ad1..a471d38 100644
    a b msgid "%(percent)s%% represents %(num)s object" 
    5252msgid_plural "%(percent)s%% represents %(num)s objects"
    5353msgstr[0] "%(percent)s%% stellt %(num)s Objekt dar"
    5454msgstr[1] "%(percent)s%% stellt %(num)s Objekte dar"
     55
     56#: models.py:17
     57msgctxt "super search"
     58msgid "%(number)s super result"
     59msgid_plural "%(number)s super results"
     60msgstr[0] "%(number)s Super-Ergebnis"
     61msgstr[1] "%(number)s Super-Ergebnisse"
     62
     63#: models.py:19
     64msgctxt "other super search"
     65msgid "%(number)s super result"
     66msgid_plural "%(number)s super results"
     67msgstr[0] "%(number)s anderen Super-Ergebnis"
     68msgstr[1] "%(number)s andere Super-Ergebnisse"
     69
     70#: models.py:21
     71msgctxt "comment count"
     72msgid "There are %(num_comments)s comments"
     73msgstr "Es gibt %(num_comments)s Kommentare"
     74
     75#: models.py:23
     76msgctxt "other comment count"
     77msgid "There are %(num_comments)s comments"
     78msgstr "Andere: Es gibt %(num_comments)s Kommentare"
     79 No newline at end of file
  • tests/regressiontests/i18n/tests.py

    diff --git a/tests/regressiontests/i18n/tests.py b/tests/regressiontests/i18n/tests.py
    index fc69d9c..10e9935 100644
    a b from threading import local 
    99
    1010from django.conf import settings
    1111from django.template import Template, Context
     12from django.template.base import TemplateSyntaxError
    1213from django.test import TestCase, RequestFactory
    1314from django.test.utils import override_settings
    1415from django.utils import translation
    class TranslationTests(TestCase): 
    8788                self.assertEqual(pgettext("verb", "May"), u"Kann")
    8889                self.assertEqual(npgettext("search", "%d result", "%d results", 4) % 4, u"4 Resultate")
    8990
     91    def test_template_tags_pgettext(self):
     92        """
     93        Ensure that message contexts are taken into account the {% trans %} and
     94        {% blocktrans %} template tags.
     95        Refs #14806.
     96        """
     97        # Reset translation catalog to include other/locale/de
     98        extended_locale_paths = settings.LOCALE_PATHS + (
     99            os.path.join(here, 'other', 'locale'),
     100        )
     101        with self.settings(LOCALE_PATHS=extended_locale_paths):
     102            from django.utils.translation import trans_real
     103            trans_real._active = local()
     104            trans_real._translations = {}
     105            with translation.override('de'):
     106
     107                # {% trans %} -----------------------------------
     108
     109                # Inexisting context...
     110                t = Template('{% load i18n %}{% trans "May" context "unexisting" %}')
     111                rendered = t.render(Context())
     112                self.assertEqual(rendered, 'May')
     113
     114                # Existing context...
     115                # Using a literal
     116                t = Template('{% load i18n %}{% trans "May" context "month name" %}')
     117                rendered = t.render(Context())
     118                self.assertEqual(rendered, 'Mai')
     119                t = Template('{% load i18n %}{% trans "May" context "verb" %}')
     120                rendered = t.render(Context())
     121                self.assertEqual(rendered, 'Kann')
     122
     123                # Using a variable
     124                t = Template('{% load i18n %}{% trans "May" context message_context %}')
     125                rendered = t.render(Context({'message_context': 'month name'}))
     126                self.assertEqual(rendered, 'Mai')
     127                t = Template('{% load i18n %}{% trans "May" context message_context %}')
     128                rendered = t.render(Context({'message_context': 'verb'}))
     129                self.assertEqual(rendered, 'Kann')
     130
     131                # Using a filter
     132                t = Template('{% load i18n %}{% trans "May" context message_context|lower %}')
     133                rendered = t.render(Context({'message_context': 'MONTH NAME'}))
     134                self.assertEqual(rendered, 'Mai')
     135                t = Template('{% load i18n %}{% trans "May" context message_context|lower %}')
     136                rendered = t.render(Context({'message_context': 'VERB'}))
     137                self.assertEqual(rendered, 'Kann')
     138
     139                # Using 'as'
     140                t = Template('{% load i18n %}{% trans "May" context "month name" as var %}Value: {{ var }}')
     141                rendered = t.render(Context())
     142                self.assertEqual(rendered, 'Value: Mai')
     143                t = Template('{% load i18n %}{% trans "May" as var context "verb" %}Value: {{ var }}')
     144                rendered = t.render(Context())
     145                self.assertEqual(rendered, 'Value: Kann')
     146
     147                # Mis-uses
     148                self.assertRaises(TemplateSyntaxError, Template, '{% load i18n %}{% trans "May" context as var %}{{ var }}')
     149                self.assertRaises(TemplateSyntaxError, Template, '{% load i18n %}{% trans "May" as var context %}{{ var }}')
     150
     151                # {% blocktrans %} ------------------------------
     152
     153                # Inexisting context...
     154                t = Template('{% load i18n %}{% blocktrans context "unexisting" %}May{% endblocktrans %}')
     155                rendered = t.render(Context())
     156                self.assertEqual(rendered, 'May')
     157
     158                # Existing context...
     159                # Using a literal
     160                t = Template('{% load i18n %}{% blocktrans context "month name" %}May{% endblocktrans %}')
     161                rendered = t.render(Context())
     162                self.assertEqual(rendered, 'Mai')
     163                t = Template('{% load i18n %}{% blocktrans context "verb" %}May{% endblocktrans %}')
     164                rendered = t.render(Context())
     165                self.assertEqual(rendered, 'Kann')
     166
     167                # Using a variable
     168                t = Template('{% load i18n %}{% blocktrans context message_context %}May{% endblocktrans %}')
     169                rendered = t.render(Context({'message_context': 'month name'}))
     170                self.assertEqual(rendered, 'Mai')
     171                t = Template('{% load i18n %}{% blocktrans context message_context %}May{% endblocktrans %}')
     172                rendered = t.render(Context({'message_context': 'verb'}))
     173                self.assertEqual(rendered, 'Kann')
     174
     175                # Using a filter
     176                t = Template('{% load i18n %}{% blocktrans context message_context|lower %}May{% endblocktrans %}')
     177                rendered = t.render(Context({'message_context': 'MONTH NAME'}))
     178                self.assertEqual(rendered, 'Mai')
     179                t = Template('{% load i18n %}{% blocktrans context message_context|lower %}May{% endblocktrans %}')
     180                rendered = t.render(Context({'message_context': 'VERB'}))
     181                self.assertEqual(rendered, 'Kann')
     182
     183                # Using 'count'
     184                t = Template('{% load i18n %}{% blocktrans count number=1 context "super search" %}{{ number }} super result{% plural %}{{ number }} super results{% endblocktrans %}')
     185                rendered = t.render(Context())
     186                self.assertEqual(rendered, '1 Super-Ergebnis')
     187                t = Template('{% load i18n %}{% blocktrans count number=2 context "super search" %}{{ number }} super result{% plural %}{{ number }} super results{% endblocktrans %}')
     188                rendered = t.render(Context())
     189                self.assertEqual(rendered, '2 Super-Ergebnisse')
     190                t = Template('{% load i18n %}{% blocktrans context "other super search" count number=1 %}{{ number }} super result{% plural %}{{ number }} super results{% endblocktrans %}')
     191                rendered = t.render(Context())
     192                self.assertEqual(rendered, '1 anderen Super-Ergebnis')
     193                t = Template('{% load i18n %}{% blocktrans context "other super search" count number=2 %}{{ number }} super result{% plural %}{{ number }} super results{% endblocktrans %}')
     194                rendered = t.render(Context())
     195                self.assertEqual(rendered, '2 andere Super-Ergebnisse')
     196
     197                # Using 'with'
     198                t = Template('{% load i18n %}{% blocktrans with num_comments=5 context "comment count" %}There are {{ num_comments }} comments{% endblocktrans %}')
     199                rendered = t.render(Context())
     200                self.assertEqual(rendered, 'Es gibt 5 Kommentare')
     201                t = Template('{% load i18n %}{% blocktrans with num_comments=5 context "other comment count" %}There are {{ num_comments }} comments{% endblocktrans %}')
     202                rendered = t.render(Context())
     203                self.assertEqual(rendered, 'Andere: Es gibt 5 Kommentare')
     204
     205                # Mis-uses
     206                self.assertRaises(TemplateSyntaxError, Template, '{% load i18n %}{% blocktrans context with month="May" %}{{ month }}{% endblocktrans %}')
     207                self.assertRaises(TemplateSyntaxError, Template, '{% load i18n %}{% blocktrans context %}{% endblocktrans %}')
     208                self.assertRaises(TemplateSyntaxError, Template, '{% load i18n %}{% blocktrans count number=2 context %}{{ number }} super result{% plural %}{{ number }} super results{% endblocktrans %}')
     209
     210
    90211    def test_string_concat(self):
    91212        """
    92213        unicode(string_concat(...)) should not raise a TypeError - #4796
Back to Top