def include_block(parser, token):
    """
    Render the passed item of StreamField content, passing the current template context
    if there's an identifiable way of doing so (i.e. if it has a `render_as_block` method).
    """
    tokens = token.split_contents()

    try:
        tag_name = tokens.pop(0)
        block_var_token = tokens.pop(0)
    except IndexError:
        raise template.TemplateSyntaxError("%r tag requires at least one argument" % tag_name)

    block_var = parser.compile_filter(block_var_token)

    if tokens and tokens[0] == 'with':
        tokens.pop(0)
        extra_context = token_kwargs(tokens, parser)
    else:
        extra_context = None

    use_parent_context = True
    if tokens and tokens[0] == 'only':
        tokens.pop(0)
        use_parent_context = False

    if tokens:
        raise template.TemplateSyntaxError("Unexpected argument to %r tag: %r" % (tag_name, tokens[0]))

    return IncludeBlockNode(block_var, extra_context, use_parent_context)
Example #2
0
def include_block(parser, token):
    """
    Render the passed item of StreamField content, passing the current template context
    if there's an identifiable way of doing so (i.e. if it has a `render_as_block` method).
    """
    tokens = token.split_contents()

    try:
        tag_name = tokens.pop(0)
        block_var_token = tokens.pop(0)
    except IndexError:
        raise template.TemplateSyntaxError(
            "%r tag requires at least one argument" % tag_name)

    block_var = parser.compile_filter(block_var_token)

    if tokens and tokens[0] == 'with':
        tokens.pop(0)
        extra_context = token_kwargs(tokens, parser)
    else:
        extra_context = None

    use_parent_context = True
    if tokens and tokens[0] == 'only':
        tokens.pop(0)
        use_parent_context = False

    if tokens:
        raise template.TemplateSyntaxError(
            "Unexpected argument to %r tag: %r" % (tag_name, tokens[0]))

    return IncludeBlockNode(block_var, extra_context, use_parent_context)
def do_render_model(parser, token):
    bits = token.split_contents()
    if len(bits) < 3:
        raise TemplateSyntaxError("%r tag takes at least two arguments: the object and the name of the template to render it with." % bits[0])
    options = {}
    remaining_bits = bits[3:]
    while remaining_bits:
        option = remaining_bits.pop(0)
        if option in options:
            raise TemplateSyntaxError('The %r option was specified more '
                                      'than once.' % option)
        if option == 'with':
            value = token_kwargs(remaining_bits, parser, support_legacy=False)
            if not value:
                raise TemplateSyntaxError('"with" in %r tag needs at least '
                                          'one keyword argument.' % bits[0])
        elif option == 'only':
            value = True
        else:
            raise TemplateSyntaxError('Unknown argument for %r tag: %r.' %
                                      (bits[0], option))
        options[option] = value
    isolated_context = options.get('only', False)
    namemap = options.get('with', {})
    return RenderObjectNode(
        parser.compile_filter(bits[1]),
        parser.compile_filter(bits[2]),
        extra_context=namemap,
        isolated_context=isolated_context)
Example #4
0
def __render_helper(parser, token):

    tokens = token.split_contents()

    try:
        tag_name = tokens.pop(0)
        block_var_token = tokens.pop(0)
    except IndexError:
        raise template.TemplateSyntaxError(
            "%r tag requires at least one argument" % tag_name)

    block_var = parser.compile_filter(block_var_token)

    if tokens and tokens[0] == 'with':
        tokens.pop(0)
        extra_context = token_kwargs(tokens, parser)
    else:
        extra_context = None

    use_parent_context = True
    if tokens and tokens[0] == 'only':
        tokens.pop(0)
        use_parent_context = False

    if tokens:
        raise template.TemplateSyntaxError(
            "Unexpected argument to %r tag: %r" % (tag_name, tokens[0]))

    return HyperNode(block_var, extra_context, use_parent_context)
Example #5
0
def signed_amount(parser, token):
    """Take a number and currency and display it according to the language

    Examples:
    {% signed_amount 100 'USD' %}
    Shows 100$ in russian and $100 in other languages
    {% signed_amount -100 'EUR' %}
    Shows -100€ in russian language and -€100 in other languages

    It also accepts precision argument, and rounds the value to that precision
    with decimal computations
    {% signed_amount balance account.currency precision=2 %}

    """
    bits = token.split_contents()
    if not 3 <= len(bits) <= 4:
        raise template.TemplateSyntaxError, "%r tag requires 2 arguments" % token.contents.split(
        )[0]

    tag, amount, currency = bits[:3]

    extra_context = token_kwargs(bits[3:], parser)

    amount = template.Variable(amount)
    currency = template.Variable(currency)

    return SignedAmountNode(amount, currency, extra_context=extra_context)
def provider_login_url(parser, token):
    """

    """
    bits = token.split_contents()
    provider_id = bits[1]
    params = token_kwargs(bits[2:], parser, support_legacy=False)
    return ProviderLoginURLNode(provider_id, params)
Example #7
0
def get_settings(parser, token):
    bits = token.split_contents()[1:]
    target_var = "settings"
    if len(bits) >= 2 and bits[-2] == "as":
        target_var = bits[-1]
        bits = bits[:-2]
    kwargs = token_kwargs(bits, parser) if bits else {}
    return GetSettingsNode(kwargs, target_var)
Example #8
0
def provider_login_url(parser, token):
    """
    {% provider_login_url "facebook" next=bla %}
    {% provider_login_url "openid" openid="http://me.yahoo.com" next=bla %}
    """
    bits = token.split_contents()
    provider_id = bits[1]
    params = token_kwargs(bits[2:], parser, support_legacy=False)
    return ProviderLoginURLNode(provider_id, params)
Example #9
0
def get_url(parser, token):
	bits = token.split_contents()
	remaining_bits = bits[1:]
	extra_context = token_kwargs(remaining_bits, parser, support_legacy=True)
	if not extra_context:
		raise TemplateSyntaxError("%r expected at least one variable assignment" % bits[0])
	if remaining_bits:
		raise TemplateSyntaxError("%r received an invalid token: %r" % (bits[0], remaining_bits[0]))
	return get_url_node(extra_context)
Example #10
0
def provider_login_url(parser, token):
    """
    {% provider_login_url "facebook" next=bla %}
    {% provider_login_url "openid" openid="http://me.yahoo.com" next=bla %}
    """
    bits = token.split_contents()
    provider_id = bits[1]
    params = token_kwargs(bits[2:], parser, support_legacy=False)
    return ProviderLoginURLNode(provider_id, params)
def do_section_menu(parser, token):
    try:
        # split_contents() knows not to split quoted strings.
        args = token.split_contents()[1:]
        kwargs = token_kwargs(args, parser)
        if len(args) > 0:
            raise ValueError
    except ValueError:
        raise djtemplate.TemplateSyntaxError(
                "%r tag accepts only keyword arguments" \
                % token.contents.split()[0])
    return SectionMenuNode(**kwargs)
def do_category_menu(parser, token):
    try:
        # split_contents() knows not to split quoted strings.
        args = token.split_contents()[1:]
        kwargs = token_kwargs(args, parser)
        if len(args) > 0:
            raise ValueError
    except ValueError:
        raise djtemplate.TemplateSyntaxError(
                "%r tag accepts only keyword arguments" \
                % token.contents.split()[0])
    return CategoryMenuNode(**kwargs)
Example #13
0
def canjs(parser, token):
    bits = token.split_contents()
    if len(bits) > 1:
        kwargs = token_kwargs(bits[1:], parser, support_legacy=False)
        for k,v in kwargs.iteritems():
            if isinstance(v, FilterExpression):
                v = str(v.var)
                if k == "extras":
                    v = v.split(",")
                kwargs[k] = v
        urls = canjs_urls(**kwargs)
    else:
        urls = canjs_urls()
    return CanJSNode(urls=urls)
Example #14
0
def do_include(parser, token):
    """
    Loads a template and renders it with the current context. You can pass
    additional context using keyword arguments.

    Example::

        {% include "foo/some_include" %}
        {% include "foo/some_include" with bar="BAZZ!" baz="BING!" %}

    Use the ``only`` argument to exclude the current context when rendering
    the included template::

        {% include "foo/some_include" only %}
        {% include "foo/some_include" with bar="1" only %}
    """
    bits = token.split_contents()
    if len(bits) < 2:
        raise TemplateSyntaxError(
            "%r tag takes at least one argument: the name of the template to be included."
            % bits[0])
    options = {}
    remaining_bits = bits[2:]
    while remaining_bits:
        option = remaining_bits.pop(0)
        if option in options:
            raise TemplateSyntaxError('The %r option was specified more '
                                      'than once.' % option)
        if option == 'with':
            value = token_kwargs(remaining_bits, parser, support_legacy=False)
            if not value:
                raise TemplateSyntaxError('"with" in %r tag needs at least '
                                          'one keyword argument.' % bits[0])
        elif option == 'only':
            value = True
        else:
            raise TemplateSyntaxError('Unknown argument for %r tag: %r.' %
                                      (bits[0], option))
        options[option] = value
    isolated_context = options.get('only', False)
    namemap = options.get('with', {})
    path = bits[1]
    if path[0] in ('"', "'") and path[-1] == path[0]:
        return ConstantIncludeNode(path[1:-1],
                                   extra_context=namemap,
                                   isolated_context=isolated_context)
    return IncludeNode(parser.compile_filter(bits[1]),
                       extra_context=namemap,
                       isolated_context=isolated_context)
Example #15
0
    def _parse_blocks(cls, parser, token):
        """
        Return an :class:`OrderedDict` of tag blocks as found in the template.
        
        Each block will be defined as:
        
        keyword: (processor, arguments, kwargs, body)
        
        """
        blocks = OrderedDict()

        # Process first block
        block_arguments = token.split_contents()
        block_keyword = block_arguments.pop(0)

        processors = cls._get_declared_blocks()
        closing_keyword = 'end_' + block_keyword
        while (True):
            try:
                block_processor = processors[block_keyword]
            except KeyError:
                raise TemplateSyntaxError(
                    'Block %r not found, candidates are %r' %
                    (block_keyword, block_processor._next_blocks))

            # Parse token keyword arguments if necessary
            if cls.resolve_block_parameters:
                # The parsed keyword arguments are removed from the original
                # list
                block_kwargs = token_kwargs(block_arguments, parser)
            else:
                block_kwargs = {}

            # Parse the body of the block
            next_blocks = _MultiBlockTagPrefixes(block_processor._next_blocks)
            block_body = parser.parse(next_blocks)

            blocks[block_keyword] = ((block_processor, block_arguments,
                                      block_kwargs, block_body))

            # Parse next block
            token = parser.next_token()
            block_arguments = token.split_contents()
            block_keyword = block_arguments.pop(0)

            if block_keyword == closing_keyword:
                break

        return blocks
Example #16
0
    def _parse_blocks(cls, parser, token):
        """
        Return an :class:`OrderedDict` of tag blocks as found in the template.
        
        Each block will be defined as:
        
        keyword: (processor, arguments, kwargs, body)
        
        """
        blocks = OrderedDict()

        # Process first block
        block_arguments = token.split_contents()
        block_keyword = block_arguments.pop(0)

        processors = cls._get_declared_blocks()
        closing_keyword = "end_" + block_keyword
        while True:
            try:
                block_processor = processors[block_keyword]
            except KeyError:
                raise TemplateSyntaxError(
                    "Block %r not found, candidates are %r" % (block_keyword, block_processor._next_blocks)
                )

            # Parse token keyword arguments if necessary
            if cls.resolve_block_parameters:
                # The parsed keyword arguments are removed from the original
                # list
                block_kwargs = token_kwargs(block_arguments, parser)
            else:
                block_kwargs = {}

            # Parse the body of the block
            next_blocks = _MultiBlockTagPrefixes(block_processor._next_blocks)
            block_body = parser.parse(next_blocks)

            blocks[block_keyword] = (block_processor, block_arguments, block_kwargs, block_body)

            # Parse next block
            token = parser.next_token()
            block_arguments = token.split_contents()
            block_keyword = block_arguments.pop(0)

            if block_keyword == closing_keyword:
                break

        return blocks
Example #17
0
def do_include(parser, token):
    """
    Loads a template and renders it with the current context. You can pass
    additional context using keyword arguments.

    Example::

        {% include "foo/some_include" %}
        {% include "foo/some_include" with bar="BAZZ!" baz="BING!" %}

    Use the ``only`` argument to exclude the current context when rendering
    the included template::

        {% include "foo/some_include" only %}
        {% include "foo/some_include" with bar="1" only %}
    """
    bits = token.split_contents()
    if len(bits) < 2:
        raise TemplateSyntaxError("%r tag takes at least one argument: the name of the template to be included." % bits[0])
    options = {}
    remaining_bits = bits[2:]
    while remaining_bits:
        option = remaining_bits.pop(0)
        if option in options:
            raise TemplateSyntaxError('The %r option was specified more '
                                      'than once.' % option)
        if option == 'with':
            value = token_kwargs(remaining_bits, parser, support_legacy=False)
            if not value:
                raise TemplateSyntaxError('"with" in %r tag needs at least '
                                          'one keyword argument.' % bits[0])
        elif option == 'only':
            value = True
        else:
            raise TemplateSyntaxError('Unknown argument for %r tag: %r.' %
                                      (bits[0], option))
        options[option] = value
    isolated_context = options.get('only', False)
    namemap = options.get('with', {})
    path = bits[1]
    if path[0] in ('"', "'") and path[-1] == path[0]:
        return ConstantIncludeNode(path[1:-1], extra_context=namemap,
                                   isolated_context=isolated_context)
    return IncludeNode(parser.compile_filter(bits[1]), extra_context=namemap,
                       isolated_context=isolated_context)
Example #18
0
def payment_details(parser, token):
    """ 
        Outputs HTML code needed to render details of a payment.
    """
    token_parts = token.split_contents()
    if len(token_parts) < 2:
        raise TemplateSyntaxError("A payment detail dictionary is a mandatory parameter for %r" % token_parts[0])
    payment_info_reference = token_parts[1]

    remaining_token_parts = token_parts[2:]
    options = token_kwargs(remaining_token_parts, parser, support_legacy = False)
    if remaining_token_parts:
        raise TemplateSyntaxError("%r received an invalid token: %r" % \
                                  (token_parts[0], remaining_token_parts[0]))

    for (key, value) in options.items():
        options[key] = unicode(value)

    return PaymentDetailsNode(payment_info_reference, options)
def payment_details(parser, token):
    """ 
        Outputs HTML code needed to render details of a payment.
    """
    token_parts = token.split_contents()
    if len(token_parts) < 2:
        raise TemplateSyntaxError(
            "A payment detail dictionary is a mandatory parameter for %r" %
            token_parts[0])
    payment_info_reference = token_parts[1]

    remaining_token_parts = token_parts[2:]
    options = token_kwargs(remaining_token_parts, parser, support_legacy=False)
    if remaining_token_parts:
        raise TemplateSyntaxError("%r received an invalid token: %r" % \
                                  (token_parts[0], remaining_token_parts[0]))

    for (key, value) in options.items():
        options[key] = unicode(value)

    return PaymentDetailsNode(payment_info_reference, options)
def partial_include(parser, token):
    bits = token.split_contents()
    if len(bits) < 2:
        raise TemplateSyntaxError("%r tag takes at least one argument: the name of the template to be included." % bits[0])

    options = {}
    remaining_bits = bits[2:]
    while remaining_bits:
        option = remaining_bits.pop(0)
        if option == "with":
            value = token_kwargs(remaining_bits, parser, support_legacy=False)
            if not value:
                raise TemplateSyntaxError('"with" in %r tag needs at least one keyword argument.' % bits[0])
        elif option == "only":
            value = True
        elif option == "quiet":
            value = True
        else:
            raise TemplateSyntaxError("Unknown argument for %r tag: %r." % (bits[0], option))
        options[str(option)] = value

    options.setdefault("only", False)
    options.setdefault("quiet", False)
    options.setdefault("with", {})

    block = options["with"].pop("block", None)
    if block:
        block = block.token
        if is_quoted(block):
            block = block[1:-1]

    template_name = bits[1]
    if is_quoted(template_name):
        resolve = False
        template_name = template_name[1:-1]
    else:
        resolve = True
        template_name = parser.compile_filter(template_name)

    return IncludeNode(template_name, resolve=resolve, block=block, **options)
Example #21
0
def def_model_details(parser, token):
    params = token.split_contents()
    tag_name = params[0]
    if len(params) < 2:
        raise template.TemplateSyntaxError("{0} tag should have at least one argument")

    model = params[1]
    bits = params[2:]
    kwargs = token_kwargs(bits, parser)
    include_fields = kwargs.get('fields', None)
    exclude_fields = kwargs.get('exclude_fields', None)
    nodelist = parser.parse(("end" + tag_name, 'extra'))
    token = parser.next_token()
    if token.contents == 'extra':
        nodelist_extra = parser.parse(('end' + tag_name,))
        parser.delete_first_token()
    else:
        nodelist_extra = None

    return ModelDetailsNode(
        model, nodelist,
        include_fields=include_fields, exclude_fields=exclude_fields, extra=nodelist_extra
    )
Example #22
0
def make_tag(parser, token):
    nodelist = parser.parse(('endtag',))
    parser.delete_first_token()
    tokens = token.split_contents()

    try:
        tag_name = tokens[1]
    except IndexError:
        raise TemplateSyntaxError(
            "'{}' tag requires at least 1 argument.".format(tokens[0]))

    if tag_name[0] != tag_name[-1] or tag_name[0] not in ['"', "'"]:
        raise TemplateSyntaxError(
            "'{}' tag's first argument should be in quotes.".format(tokens[0]))
    tag_name = tag_name[1:-1]

    options = {}
    remaining_bits = tokens[2:]
    while remaining_bits:
        option = remaining_bits.pop(0)
        if option in options:
            raise TemplateSyntaxError(
                "The '{}' option was specified more than once.".format(option))
        if option == 'with':
            value = token_kwargs(remaining_bits, parser)
            if not value:
                raise TemplateSyntaxError(
                    "'with' in '{}' tag needs at least one "
                    "keyword argument.".format(tokens[0]))
        else:
            raise TemplateSyntaxError(
                "Unknown argument for '{}' tag: {}".format(tokens[0], option))
        options[option] = value

    extra_context = options.get('with', {})

    return TagNode(nodelist, tag_name, extra_context)
Example #23
0
    def _parse_block(self, token, parser, original_string):
        """Parse any {% ... %} token and return a migration object.

        :param django.template.base.Token token: the token object
        :param django.template.base.parser: the parser object
        :param unicode original_string: the string found in the template
        """
        # Split the given token into its parts (includes the template tag
        # name), e.g. "{% trans "This is the title" context "Some context" %}"
        # returns: ['trans', '"This is the title"', 'context', '"Some
        # context"']
        bits = token.split_contents()

        tag_name = bits[0]

        # Right after {% load i18n %} append a {% load transifex %} tag
        if (tag_name == templates.LOAD_TAG
                and bits[1] == templates.DJANGO_i18n_TAG_NAME):
            # Make sure there is not already a tag that loads "transifex"
            # by checking all remaining nodes
            for t in parser.tokens:
                if (templates.LOAD_TAG in t.contents
                        and templates.TRANSIFEX_TAG_NAME in t.contents):
                    return (StringMigration(original_string,
                                            original_string), None)

            string_migration = StringMigration(
                original_string,
                'original\n{% load transifex %}'.replace(
                    'original', original_string),
            )
            return string_migration, None

        # A {% with %} tag was found
        elif tag_name == templates.WITH_TAG:
            with_kwargs = token_kwargs(bits[1:], parser, support_legacy=True)
            self._with_kwargs.append(
                {k: v.var
                 for k, v in with_kwargs.items()})
        # An {% endwith %} tag was found
        elif tag_name == templates.ENDWITH_TAG:
            self._with_kwargs.pop()

        # A {% comment %} tag was found; If this is a translation comment,
        # expect the actual comment text to follow shortly
        elif tag_name == templates.COMMENT_TAG:
            next_token = parser.tokens[0] if parser.tokens else None
            if next_token.token_type == TOKEN_TEXT:
                comment = _retrieve_comment(next_token.contents)
                if comment:
                    self._comment = COMMENT_FOUND
                    # Create a string migration and start keeping track
                    # of all the strings that will be migrated
                    # within the following set of tokens that apply
                    self._current_string_migration = StringMigration(
                        original_string, '')
                    return None, None

        # An {% endcomment %} tag was found
        elif tag_name == templates.ENDCOMMENT_TAG:
            # No need to do anything special, just make sure to record
            # that the tag is removed from the migrated result
            # If a translation comment wasn't open, ignore it
            if self._comment is not None:
                if self._current_string_migration:
                    self._current_string_migration.update(original_string, '')
                return None, None

        # A {% trans %} tag was found
        elif tag_name in templates.TRANSLATE_TAGS:
            return self._parse_trans(token, parser, original_string)

        # A {% blocktrans %} tag was found
        elif tag_name in templates.BLOCK_TRANSLATE_TAGS:
            return self._parse_blocktrans(token, parser, original_string)

        # This is the default case; any other block tag that wasn't
        # explicitly covered above, which means that it doesn't need migration
        return StringMigration(original_string, original_string), None
Example #24
0
def twitter_login_url(parser, token):
    bits = token.split_contents()
    params = token_kwargs(bits[1:], parser, support_legacy=False)
    return TwitterLoginURLNode(params)
def facebook_login_url(parser, token):
    bits = token.split_contents()
    params = token_kwargs(bits[1:], parser, support_legacy=False)
    return FacebookLoginURLNode(params)
Example #26
0
def do_t(parser, token):
    """ Parse a transifex translation tag.

        Inline syntax:
          {% t/ut <source>[|filter...] [key=param[|filter...]...] [as <var>] %}

          <source> can either be a literal string or a variable containing a
          string. In each case, the string will be considered an ICU template
          whose parameters will be rendered against the parameters of the tag
          and the context of the template.

        Block syntax:
          {% t/ut [|filter...] [key=param[|filter...]...] [as <var>] %}
            <source>
          {% endt/ut %}

          <source> can be anything. Django template tokens will not be parsed,
          but captured verbatim (which will most likely mess up with ICU
          formatting).

        Arguments:

        :param parser: A django Parser object. Has information about how the
                       templating engine is setup, what filters and tags are
                       available and the tokens that haven't yet been processed

        :param token:  A django Token instance. Has information about the
                       contents of the token we are currently processing
    """

    # We will gradually "consume" bits left-to-right. At any given moment, the
    # leftmost bit is the one we need to be processing
    bits = list(token.split_contents())

    # {% t ... %}
    #    ^
    tag_name = bits.pop(0)

    # not {% t %}
    has_args = bool(bits)
    # {% t |escapejs ... %} ... {% endt %}
    first_arg_is_filter = has_args and bits[0].startswith('|')
    # {% t "hello world" ... %}
    first_arg_is_string_literal = (has_args and bits[0][0] in ('"', "'")
                                   and bits[0][0] == bits[0][-1])
    # {% t var=var ... %}
    first_arg_is_param = (has_args and not first_arg_is_string_literal
                          and '=' in bits[0])
    # {% t as text %}
    first_arg_is_as = has_args and bits[0] == "as"

    is_block = (not has_args or first_arg_is_filter or first_arg_is_param
                or first_arg_is_as)

    if not is_block:
        # Treat the source string as a full filter expression. Proper
        # exceptions will be raised if it is not formatted properly
        source_string = parser.compile_filter(bits.pop(0))
    else:
        block = []
        while True:
            try:
                # `next_token` removes the first token from the parser's list
                token = parser.next_token()
            except IndexError:
                # We ran out of tokens
                raise TemplateSyntaxError(
                    "'{tag_name}' tag not closed with "
                    "'end{tag_name}'".format(tag_name=tag_name))
            if (token.token_type == TOKEN_BLOCK
                    and token.contents == "end{}".format(tag_name)):
                break

            # Here we capture the contents of the block verbatim.
            # Unfortunately, there is some loss of information here: When
            # django captures a token, it saves the content as
            # `text[2:-2].strip()`, which means that the size of the
            # surrounding spaces is lost. This means that we end up capturing
            # `{%     tag%}` as `{% tag %}`
            if token.token_type == TOKEN_VAR:
                block.append(''.join((VARIABLE_TAG_START, ' ', token.contents,
                                      ' ', VARIABLE_TAG_END)))
            elif token.token_type == TOKEN_BLOCK:
                block.append(''.join((BLOCK_TAG_START, ' ', token.contents,
                                      ' ', BLOCK_TAG_END)))
            elif token.token_type == TOKEN_COMMENT and token.contents:
                block.append(''.join((COMMENT_TAG_START, ' ', token.contents,
                                      ' ', COMMENT_TAG_END)))
            elif token.token_type == TOKEN_TEXT:
                block.append(token.contents)
            else:  # pragma: no cover
                # Unreachable code
                raise TemplateSyntaxError("Could not parse body of '{}' tag "
                                          "block".format(tag_name))
        block = ''.join(block)

        # Create a dummy filter expression with the provided filters and then
        # replace its 'var' attribute with the captured text. This effectively
        # makes
        # `{% t %}text{% endt %}` equivalent to `{% t "text" %}` and
        # `{% t |filter %}text{% endt %}` equivalent to `{% t "text"|filter %}`
        # while allowing the text to contain characters that would be invalid
        # with the inline syntax, like newlines and `"`
        if first_arg_is_filter:
            source_string = parser.compile_filter('""' + bits.pop(0))
        else:
            source_string = parser.compile_filter('""')
        source_string.var = block

    # {% t "string" var=value var2=value2 ... %}
    #               ^^^^^^^^^
    params_list = []
    while bits and '=' in bits[0]:
        params_list.append(bits.pop(0))
    # Proper exceptions will be raised if the params are not formatted properly
    params = token_kwargs(params_list, parser, support_legacy=False)

    # {% t "string" as var %}
    #               ^^^^^^
    asvar = None
    if bits:
        if len(bits) != 2 or bits[0] != "as":
            raise TemplateSyntaxError("Unrecognized tail: {}".format(
                ' '.join(bits)))
        else:
            asvar = bits[1]
            del bits[:2]

    if bits:
        raise TemplateSyntaxError("Unrecognized tail: {}".format(
            ' '.join(bits)))

    return TNode(tag_name, source_string, params, asvar)
Example #27
0
def do_block_translate(parser, token):
    """
    This will translate a block of text with parameters.

    Usage::

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

    Additionally, this supports pluralization::

        {% blocktrans count count=var|length %}
        There is {{ count }} object.
        {% plural %}
        There are {{ count }} objects.
        {% endblocktrans %}

    This is much like ngettext, only in template syntax.

    The "var as value" legacy format is still supported::

        {% blocktrans with foo|filter as bar and baz|filter as boo %}
        {% blocktrans count var|length as count %}
    """
    bits = token.split_contents()

    options = {}
    remaining_bits = bits[1:]
    while remaining_bits:
        option = remaining_bits.pop(0)
        if option in options:
            raise TemplateSyntaxError('The %r option was specified more '
                                      'than once.' % option)
        if option == 'with':
            value = token_kwargs(remaining_bits, parser, support_legacy=True)
            if not value:
                raise TemplateSyntaxError('"with" in %r tag needs at least '
                                          'one keyword argument.' % bits[0])
        elif option == 'count':
            value = token_kwargs(remaining_bits, parser, support_legacy=True)
            if len(value) != 1:
                raise TemplateSyntaxError('"count" in %r tag expected exactly '
                                          'one keyword argument.' % bits[0])
        else:
            raise TemplateSyntaxError('Unknown argument for %r tag: %r.' %
                                      (bits[0], option))
        options[option] = value

    if 'count' in options:
        countervar, counter = options['count'].items()[0]
    else:
        countervar, counter = None, None
    extra_context = options.get('with', {})

    singular = []
    plural = []
    while parser.tokens:
        token = parser.next_token()
        if token.token_type in (TOKEN_VAR, TOKEN_TEXT):
            singular.append(token)
        else:
            break
    if countervar and counter:
        if token.contents.strip() != 'plural':
            raise TemplateSyntaxError(
                "'blocktrans' doesn't allow other block tags inside it")
        while parser.tokens:
            token = parser.next_token()
            if token.token_type in (TOKEN_VAR, TOKEN_TEXT):
                plural.append(token)
            else:
                break
    if token.contents.strip() != 'endblocktrans':
        raise TemplateSyntaxError(
            "'blocktrans' doesn't allow other block tags (seen %r) inside it" %
            token.contents)

    return BlockTranslateNode(extra_context, singular, plural, countervar,
                              counter)
Example #28
0
def get_flatpages(parser, token):
    """
    Returns a list of flatpages based on the given criteria.
    
    Basic usage::
    
        {% get_flatpages %}
        
    ... which returns all flatpages (not recommended on sites with many flatpages).
    
    Example usage::
    
        {% get_flatpages as flatpages %}
        {% get_flatpages sort='views' as flatpages %}
        {% get_flatpages sort='random' limit=10 as random_flatpages %}
        {% get_flatpages owners=1 limit=5 as user_flatpages %}
        {% get_flatpages tags='foo,bar,baz' as flatpages %}
        {% get_flatpages starts_with='/about/' as about_pages %}
        {% get_flatpages sort='random' remove=flatpage.id limit=5 as random_flatpages %}
    
    All fields are optional. If nothing is passed to the templatetag, it will 
    return all flatpages, sorted by most recently created
    
    Here are the available options::
    
        sort=                       What to sort the flatpages by. Optional. Default is by url.
            'created'               Returns least recently created flatpages first.
            '-created'              Returns most recently created flatpages first.
            'modified'              Returns least recently modified flatpages first.
            '-modified'             Returns most recently modified flatpages first.
            'views'                 Returns the most viewed flatpages first.
            '-views'                Returns the least viewed flatpages first.
            'random'                Returns random flatpages.
        
        tags='foo,bar,baz'          Returns all flatpages tagged with _either_      
                                    'foo', 'bar', or 'baz'. Optional.
        
        not_tags='foo,bar'          Removes any flatpages tagged with 'foo' or
                                    'bar' from the QuerySet.
    
        starts_with='/about/'       Return all flatpages that have a URL that 
                                    starts with '/about/'.
    
        owners=1                    Returns all flatpages by the User with ID 1. 
                                    Optional. Can be a string of IDs 
                                    (e.g. '1,5,6,8,234') or an integer 
                                    (e.g. 1). Optional.
                                
        limit=10                    Limits the number of flatpages that are 
                                    returned to 10 results. Optional.
                                
        remove=1                    Removes a given flatpage ID or list of IDs from
                                    the results list. Can be a string of IDs 
                                    (e.g. '1,5,6,8,234') or an integer 
                                    (e.g. 1). Optional.
    
    """
    bits = token.split_contents()
    remaining_bits = bits[1:]
    var_name = 'flatpages'
    if remaining_bits:
        if remaining_bits[-2] == 'as':
            var_name = remaining_bits[-1]
            # Remove the var_name and "as" bits from the list or it will throw an error.
            del remaining_bits[-2:-1]
    extra_context = token_kwargs(remaining_bits, parser)
    return FlatpagesNode(extra_context, var_name)
Example #29
0
def facebook_login_url(parser, token):
    bits = token.split_contents()
    params = token_kwargs(bits[1:], parser, support_legacy=False)
    return FacebookLoginURLNode(params)
Example #30
0
def do_block_translate(parser, token):
    bits = token.split_contents()

    options = {}
    remaining_bits = bits[1:]
    while remaining_bits:
        option = remaining_bits.pop(0)
        if option in options:
            raise TemplateSyntaxError(
                'The %r option was specified more than once.' % option)
        if option == 'with':
            value = token_kwargs(remaining_bits, parser, support_legacy=True)
            if not value:
                raise TemplateSyntaxError(
                    '"with" in %r tag needs at least one keyword argument.' %
                    bits[0])
        elif option == 'count':
            value = token_kwargs(remaining_bits, parser, support_legacy=True)
            if len(value) != 1:
                raise TemplateSyntaxError(
                    '"count" in %r tag expected exactly one keyword argument.'
                    % bits[0])
        elif option == "context":
            try:
                value = remaining_bits.pop(0)
                value = parser.compile_filter(value)
            except Exception:
                msg = ('"context" in %r tag expected exactly one argument.'
                       ) % bits[0]
                six.reraise(TemplateSyntaxError, TemplateSyntaxError(msg),
                            sys.exc_info()[2])
        else:
            raise TemplateSyntaxError('Unknown argument for %r tag: %r.' %
                                      (bits[0], option))
        options[option] = value

    if 'count' in options:
        countervar, counter = list(six.iteritems(options['count']))[0]
    else:
        countervar, counter = None, None
    if 'context' in options:
        message_context = options['context']
    else:
        message_context = None

    extra_context = options.get('with', {})

    singular = []
    plural = []
    while parser.tokens:
        token = parser.next_token()
        if token.token_type in (TOKEN_VAR, TOKEN_TEXT):
            singular.append(token)
        else:
            break
    if countervar and counter:
        if token.contents.strip() != 'plural':
            raise TemplateSyntaxError(
                "'blocktrans' doesn't allow other block tags inside it")
        while parser.tokens:
            token = parser.next_token()
            if token.token_type in (TOKEN_VAR, TOKEN_TEXT):
                plural.append(token)
            else:
                break
    if token.contents.strip() != 'endblocktrans':
        raise TemplateSyntaxError(
            "'blocktrans' doesn't allow other block tags (seen %r) inside it" %
            token.contents)

    if phrase_settings.PHRASE_ENABLED:
        node = PhraseBlockTranslateNode(extra_context, singular, plural,
                                        countervar, counter, message_context)
    else:
        node = BlockTranslateNode(extra_context, singular, plural, countervar,
                                  counter, message_context)

    return node
Example #31
0
from __future__ import unicode_literals
Example #32
0
def do_block_translate(parser, token):
    """
    This will translate a block of text with parameters.

    Usage::

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

    Additionally, this supports pluralization::

        {% blocktrans count count=var|length %}
        There is {{ count }} object.
        {% plural %}
        There are {{ count }} objects.
        {% endblocktrans %}

    This is much like ngettext, only in template syntax.

    The "var as value" legacy format is still supported::

        {% blocktrans with foo|filter as bar and baz|filter as boo %}
        {% blocktrans count var|length as count %}

    Contextual translations are supported::

        {% blocktrans with bar=foo|filter context "greeting" %}
            This is {{ bar }}.
        {% endblocktrans %}

    This is equivalent to calling pgettext/npgettext instead of
    (u)gettext/(u)ngettext.
    """
    bits = token.split_contents()

    options = {}
    remaining_bits = bits[1:]
    while remaining_bits:
        option = remaining_bits.pop(0)
        if option in options:
            raise TemplateSyntaxError('The %r option was specified more '
                                      'than once.' % option)
        if option == 'with':
            value = token_kwargs(remaining_bits, parser, support_legacy=True)
            if not value:
                raise TemplateSyntaxError('"with" in %r tag needs at least '
                                          'one keyword argument.' % bits[0])
        elif option == 'count':
            value = token_kwargs(remaining_bits, parser, support_legacy=True)
            if len(value) != 1:
                raise TemplateSyntaxError('"count" in %r tag expected exactly '
                                          'one keyword argument.' % bits[0])
        elif option == "context":
            try:
                value = remaining_bits.pop(0)
                value = parser.compile_filter(value)
            except Exception:
                msg = (
                    '"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))
        options[option] = value

    if 'count' in options:
        countervar, counter = list(six.iteritems(options['count']))[0]
    else:
        countervar, counter = None, None
    if 'context' in options:
        message_context = options['context']
    else:
        message_context = None
    extra_context = options.get('with', {})

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

    singular = []
    plural = []
    while parser.tokens:
        token = parser.next_token()
        if token.token_type in (TOKEN_VAR, TOKEN_TEXT):
            singular.append(token)
        else:
            break
    if countervar and counter:
        if token.contents.strip() != 'plural':
            raise TemplateSyntaxError("'blocktrans' doesn't allow other block tags inside it")
        while parser.tokens:
            token = parser.next_token()
            if token.token_type in (TOKEN_VAR, TOKEN_TEXT):
                plural.append(token)
            else:
                break
    if token.contents.strip() != 'endblocktrans':
        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)
def get_flatpages(parser, token):
    """
    Returns a list of flatpages based on the given criteria.
    
    Basic usage::
    
        {% get_flatpages %}
        
    ... which returns all flatpages (not recommended on sites with many flatpages).
    
    Example usage::
    
        {% get_flatpages as flatpages %}
        {% get_flatpages sort='views' as flatpages %}
        {% get_flatpages sort='random' limit=10 as random_flatpages %}
        {% get_flatpages owners=1 limit=5 as user_flatpages %}
        {% get_flatpages tags='foo,bar,baz' as flatpages %}
        {% get_flatpages starts_with='/about/' as about_pages %}
        {% get_flatpages sort='random' remove=flatpage.id limit=5 as random_flatpages %}
    
    All fields are optional. If nothing is passed to the templatetag, it will 
    return all flatpages, sorted by most recently created
    
    Here are the available options::
    
        sort=                       What to sort the flatpages by. Optional. Default is by url.
            'created'               Returns least recently created flatpages first.
            '-created'              Returns most recently created flatpages first.
            'modified'              Returns least recently modified flatpages first.
            '-modified'             Returns most recently modified flatpages first.
            'views'                 Returns the most viewed flatpages first.
            '-views'                Returns the least viewed flatpages first.
            'random'                Returns random flatpages.
        
        tags='foo,bar,baz'          Returns all flatpages tagged with _either_      
                                    'foo', 'bar', or 'baz'. Optional.
        
        not_tags='foo,bar'          Removes any flatpages tagged with 'foo' or
                                    'bar' from the QuerySet.
    
        starts_with='/about/'       Return all flatpages that have a URL that 
                                    starts with '/about/'.
    
        owners=1                    Returns all flatpages by the User with ID 1. 
                                    Optional. Can be a string of IDs 
                                    (e.g. '1,5,6,8,234') or an integer 
                                    (e.g. 1). Optional.
                                
        limit=10                    Limits the number of flatpages that are 
                                    returned to 10 results. Optional.
                                
        remove=1                    Removes a given flatpage ID or list of IDs from
                                    the results list. Can be a string of IDs 
                                    (e.g. '1,5,6,8,234') or an integer 
                                    (e.g. 1). Optional.
    
    """
    bits = token.split_contents()
    remaining_bits = bits[1:]
    var_name = "flatpages"
    if remaining_bits:
        if remaining_bits[-2] == "as":
            var_name = remaining_bits[-1]
            # Remove the var_name and "as" bits from the list or it will throw an error.
            del remaining_bits[-2:-1]
    extra_context = token_kwargs(remaining_bits, parser)
    return FlatpagesNode(extra_context, var_name)
Example #34
0
def do_block_translate(parser, token):
    """
    Translate a block of text with parameters.

    Usage::

        {% blocktranslate with bar=foo|filter boo=baz|filter %}
        This is {{ bar }} and {{ boo }}.
        {% endblocktranslate %}

    Additionally, this supports pluralization::

        {% blocktranslate count count=var|length %}
        There is {{ count }} object.
        {% plural %}
        There are {{ count }} objects.
        {% endblocktranslate %}

    This is much like ngettext, only in template syntax.

    The "var as value" legacy format is still supported::

        {% blocktranslate with foo|filter as bar and baz|filter as boo %}
        {% blocktranslate count var|length as count %}

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

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

    Contextual translations are supported::

        {% blocktranslate with bar=foo|filter context "greeting" %}
            This is {{ bar }}.
        {% endblocktranslate %}

    This is equivalent to calling pgettext/npgettext instead of
    (u)gettext/(u)ngettext.
    """
    bits = token.split_contents()

    options = {}
    remaining_bits = bits[1:]
    asvar = None
    while remaining_bits:
        option = remaining_bits.pop(0)
        if option in options:
            raise TemplateSyntaxError('The %r option was specified more '
                                      'than once.' % option)
        if option == 'with':
            value = token_kwargs(remaining_bits, parser, support_legacy=True)
            if not value:
                raise TemplateSyntaxError('"with" in %r tag needs at least '
                                          'one keyword argument.' % bits[0])
        elif option == 'count':
            value = token_kwargs(remaining_bits, parser, support_legacy=True)
            if len(value) != 1:
                raise TemplateSyntaxError('"count" in %r tag expected exactly '
                                          'one keyword argument.' % bits[0])
        elif option == "context":
            try:
                value = remaining_bits.pop(0)
                value = parser.compile_filter(value)
            except Exception:
                raise TemplateSyntaxError(
                    '"context" in %r tag expected exactly one argument.' %
                    bits[0])
        elif option == "trimmed":
            value = True
        elif option == "asvar":
            try:
                value = remaining_bits.pop(0)
            except IndexError:
                raise TemplateSyntaxError(
                    "No argument provided to the '%s' tag for the asvar option."
                    % bits[0])
            asvar = value
        else:
            raise TemplateSyntaxError('Unknown argument for %r tag: %r.' %
                                      (bits[0], option))
        options[option] = value

    if 'count' in options:
        countervar, counter = next(iter(options['count'].items()))
    else:
        countervar, counter = None, None
    if 'context' in options:
        message_context = options['context']
    else:
        message_context = None
    extra_context = options.get('with', {})

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

    singular = []
    plural = []
    while parser.tokens:
        token = parser.next_token()
        if token.token_type in (TokenType.VAR, TokenType.TEXT):
            singular.append(token)
        else:
            break
    if countervar and counter:
        if token.contents.strip() != 'plural':
            raise TemplateSyntaxError(
                "%r doesn't allow other block tags inside it" % bits[0])
        while parser.tokens:
            token = parser.next_token()
            if token.token_type in (TokenType.VAR, TokenType.TEXT):
                plural.append(token)
            else:
                break
    end_tag_name = 'end%s' % bits[0]
    if token.contents.strip() != end_tag_name:
        raise TemplateSyntaxError(
            "%r doesn't allow other block tags (seen %r) inside it" %
            (bits[0], token.contents))

    return BlockTranslateNode(extra_context,
                              singular,
                              plural,
                              countervar,
                              counter,
                              message_context,
                              trimmed=trimmed,
                              asvar=asvar,
                              tag_name=bits[0])
Example #35
0
def do_block_translate(parser, token):
    bits = token.split_contents()

    options = {}
    remaining_bits = bits[1:]
    while remaining_bits:
        option = remaining_bits.pop(0)
        if option in options:
            raise TemplateSyntaxError("The %r option was specified more than once." % option)
        if option == "with":
            value = token_kwargs(remaining_bits, parser, support_legacy=True)
            if not value:
                raise TemplateSyntaxError('"with" in %r tag needs at least one keyword argument.' % bits[0])
        elif option == "count":
            value = token_kwargs(remaining_bits, parser, support_legacy=True)
            if len(value) != 1:
                raise TemplateSyntaxError('"count" in %r tag expected exactly one keyword argument.' % bits[0])
        elif option == "context":
            try:
                value = remaining_bits.pop(0)
                value = parser.compile_filter(value)
            except Exception:
                msg = ('"context" in %r tag expected exactly one argument.') % bits[0]
                six.reraise(TemplateSyntaxError, TemplateSyntaxError(msg), sys.exc_info()[2])
        else:
            raise TemplateSyntaxError("Unknown argument for %r tag: %r." % (bits[0], option))
        options[option] = value

    if "count" in options:
        countervar, counter = list(six.iteritems(options["count"]))[0]
    else:
        countervar, counter = None, None
    if "context" in options:
        message_context = options["context"]
    else:
        message_context = None

    extra_context = options.get("with", {})

    singular = []
    plural = []
    while parser.tokens:
        token = parser.next_token()
        if token.token_type in (TOKEN_VAR, TOKEN_TEXT):
            singular.append(token)
        else:
            break
    if countervar and counter:
        if token.contents.strip() != "plural":
            raise TemplateSyntaxError("'blocktrans' doesn't allow other block tags inside it")
        while parser.tokens:
            token = parser.next_token()
            if token.token_type in (TOKEN_VAR, TOKEN_TEXT):
                plural.append(token)
            else:
                break
    if token.contents.strip() != "endblocktrans":
        raise TemplateSyntaxError("'blocktrans' doesn't allow other block tags (seen %r) inside it" % token.contents)

    if phrase_settings.PHRASE_ENABLED:
        node = PhraseBlockTranslateNode(extra_context, singular, plural, countervar, counter, message_context)
    else:
        node = BlockTranslateNode(extra_context, singular, plural, countervar, counter, message_context)

    return node
Example #36
0
def openid_login_url(parser, token):
    bits = token.split_contents()
    params = token_kwargs(bits[1:], parser, support_legacy=False)
    return OpenIDLoginURLNode(params)
Example #37
0
def do_block_translate(parser, token):
    """
    This will translate a block of text with parameters.

    Usage::

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

    Additionally, this supports pluralization::

        {% blocktrans count count=var|length %}
        There is {{ count }} object.
        {% plural %}
        There are {{ count }} objects.
        {% endblocktrans %}

    This is much like ngettext, only in template syntax.

    The "var as value" legacy format is still supported::

        {% blocktrans with foo|filter as bar and baz|filter as boo %}
        {% blocktrans count var|length as count %}
    """
    bits = token.split_contents()

    options = {}
    remaining_bits = bits[1:]
    while remaining_bits:
        option = remaining_bits.pop(0)
        if option in options:
            raise TemplateSyntaxError('The %r option was specified more '
                                      'than once.' % option)
        if option == 'with':
            value = token_kwargs(remaining_bits, parser, support_legacy=True)
            if not value:
                raise TemplateSyntaxError('"with" in %r tag needs at least '
                                          'one keyword argument.' % bits[0])
        elif option == 'count':
            value = token_kwargs(remaining_bits, parser, support_legacy=True)
            if len(value) != 1:
                raise TemplateSyntaxError('"count" in %r tag expected exactly '
                                          'one keyword argument.' % bits[0])
        else:
            raise TemplateSyntaxError('Unknown argument for %r tag: %r.' %
                                      (bits[0], option))
        options[option] = value

    if 'count' in options:
        countervar, counter = options['count'].items()[0]
    else:
        countervar, counter = None, None
    extra_context = options.get('with', {}) 

    singular = []
    plural = []
    while parser.tokens:
        token = parser.next_token()
        if token.token_type in (TOKEN_VAR, TOKEN_TEXT):
            singular.append(token)
        else:
            break
    if countervar and counter:
        if token.contents.strip() != 'plural':
            raise TemplateSyntaxError("'blocktrans' doesn't allow other block tags inside it")
        while parser.tokens:
            token = parser.next_token()
            if token.token_type in (TOKEN_VAR, TOKEN_TEXT):
                plural.append(token)
            else:
                break
    if token.contents.strip() != 'endblocktrans':
        raise TemplateSyntaxError("'blocktrans' doesn't allow other block tags (seen %r) inside it" % token.contents)

    return BlockTranslateNode(extra_context, singular, plural, countervar,
            counter)
Example #38
0
def twitter_login_url(parser, token):
    bits = token.split_contents()
    params = token_kwargs(bits[1:], parser, support_legacy=False)
    return TwitterLoginURLNode(params)
Example #39
0
def do_block_translate(parser, token):
    """
    This will translate a block of text with parameters.

    Usage::

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

    Additionally, this supports pluralization::

        {% blocktrans count count=var|length %}
        There is {{ count }} object.
        {% plural %}
        There are {{ count }} objects.
        {% endblocktrans %}

    This is much like ngettext, only in template syntax.

    The "var as value" legacy format is still supported::

        {% blocktrans with foo|filter as bar and baz|filter as boo %}
        {% blocktrans count var|length as count %}

    Contextual translations are supported::

        {% blocktrans with bar=foo|filter context "greeting" %}
            This is {{ bar }}.
        {% endblocktrans %}

    This is equivalent to calling pgettext/npgettext instead of
    (u)gettext/(u)ngettext.
    """
    bits = token.split_contents()

    options = {}
    remaining_bits = bits[1:]
    while remaining_bits:
        option = remaining_bits.pop(0)
        if option in options:
            raise TemplateSyntaxError('The %r option was specified more '
                                      'than once.' % option)
        if option == 'with':
            value = token_kwargs(remaining_bits, parser, support_legacy=True)
            if not value:
                raise TemplateSyntaxError('"with" in %r tag needs at least '
                                          'one keyword argument.' % bits[0])
        elif option == 'count':
            value = token_kwargs(remaining_bits, parser, support_legacy=True)
            if len(value) != 1:
                raise TemplateSyntaxError('"count" in %r tag expected exactly '
                                          'one keyword argument.' % bits[0])
        elif option == "context":
            try:
                value = remaining_bits.pop(0)
                value = parser.compile_filter(value)
            except Exception:
                msg = ('"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))
        options[option] = value

    if 'count' in options:
        countervar, counter = list(six.iteritems(options['count']))[0]
    else:
        countervar, counter = None, None
    if 'context' in options:
        message_context = options['context']
    else:
        message_context = None
    extra_context = options.get('with', {})

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

    singular = []
    plural = []
    while parser.tokens:
        token = parser.next_token()
        if token.token_type in (TOKEN_VAR, TOKEN_TEXT):
            singular.append(token)
        else:
            break
    if countervar and counter:
        if token.contents.strip() != 'plural':
            raise TemplateSyntaxError(
                "'blocktrans' doesn't allow other block tags inside it")
        while parser.tokens:
            token = parser.next_token()
            if token.token_type in (TOKEN_VAR, TOKEN_TEXT):
                plural.append(token)
            else:
                break
    if token.contents.strip() != 'endblocktrans':
        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)