summaryrefslogtreecommitdiff
path: root/ext/inlinegettext.py
blob: cf4ed5e4418cd6059f69164fbfc6899366dfecd7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# -*- coding: utf-8 -*-
"""
    Inline Gettext
    ~~~~~~~~~~~~~~

    An example extension for Jinja2 that supports inline gettext calls.
    Requires the i18n extension to be loaded.

    :copyright: (c) 2009 by the Jinja Team.
    :license: BSD.
"""
import re
from jinja2.ext import Extension
from jinja2.lexer import Token, count_newlines
from jinja2.exceptions import TemplateSyntaxError


_outside_re = re.compile(r'\\?(gettext|_)\(')
_inside_re = re.compile(r'\\?[()]')


class InlineGettext(Extension):
    """This extension implements support for inline gettext blocks::

        <h1>_(Welcome)</h1>
        <p>_(This is a paragraph)</p>

    Requires the i18n extension to be loaded and configured.
    """

    def filter_stream(self, stream):
        paren_stack = 0

        for token in stream:
            if token.type is not 'data':
                yield token
                continue

            pos = 0
            lineno = token.lineno

            while 1:
                if not paren_stack:
                    match = _outside_re.search(token.value, pos)
                else:
                    match = _inside_re.search(token.value, pos)
                if match is None:
                    break
                new_pos = match.start()
                if new_pos > pos:
                    preval = token.value[pos:new_pos]
                    yield Token(lineno, 'data', preval)
                    lineno += count_newlines(preval)
                gtok = match.group()
                if gtok[0] == '\\':
                    yield Token(lineno, 'data', gtok[1:])
                elif not paren_stack:
                    yield Token(lineno, 'block_begin', None)
                    yield Token(lineno, 'name', 'trans')
                    yield Token(lineno, 'block_end', None)
                    paren_stack = 1
                else:
                    if gtok == '(' or paren_stack > 1:
                        yield Token(lineno, 'data', gtok)
                    paren_stack += gtok == ')' and -1 or 1
                    if not paren_stack:
                        yield Token(lineno, 'block_begin', None)
                        yield Token(lineno, 'name', 'endtrans')
                        yield Token(lineno, 'block_end', None)
                pos = match.end()

            if pos < len(token.value):
                yield Token(lineno, 'data', token.value[pos:])

        if paren_stack:
            raise TemplateSyntaxError('unclosed gettext expression',
                                      token.lineno, stream.name,
                                      stream.filename)