blob: 049ab3b2d6f00cbdaba7a5580c80e696cd2c2a70 [file] [log] [blame]
Armin Ronacherd02fc7d2008-06-14 14:19:47 +02001# -*- coding: utf-8 -*-
2"""
3 Inline Gettext
4 ~~~~~~~~~~~~~~
5
6 An example extension for Jinja2 that supports inline gettext calls.
7 Requires the i18n extension to be loaded.
8
9 :copyright: Copyright 2008 by Armin Ronacher.
10 :license: BSD.
11"""
12import re
13from jinja2.ext import Extension
14from jinja2.lexer import Token, count_newlines
15from jinja2.exceptions import TemplateSyntaxError
16
17
18_outside_re = re.compile(r'\\?(gettext|_)\(')
19_inside_re = re.compile(r'\\?[()]')
20
21
22class InlineGettext(Extension):
23 """This extension implements support for inline gettext blocks::
24
25 <h1>_(Welcome)</h1>
26 <p>_(This is a paragraph)</p>
27
28 Requires the i18n extension to be loaded and configured.
29 """
30
31 def filter_stream(self, stream):
32 paren_stack = 0
33
34 for token in stream:
35 if token.type is not 'data':
36 yield token
37 continue
38
39 pos = 0
40 lineno = token.lineno
41
42 while 1:
43 if not paren_stack:
44 match = _outside_re.search(token.value, pos)
45 else:
46 match = _inside_re.search(token.value, pos)
47 if match is None:
48 break
49 new_pos = match.start()
50 if new_pos > pos:
51 preval = token.value[pos:new_pos]
52 yield Token(lineno, 'data', preval)
53 lineno += count_newlines(preval)
54 gtok = match.group()
55 if gtok[0] == '\\':
56 yield Token(lineno, 'data', gtok[1:])
57 elif not paren_stack:
58 yield Token(lineno, 'block_begin', None)
59 yield Token(lineno, 'name', 'trans')
60 yield Token(lineno, 'block_end', None)
61 paren_stack = 1
62 else:
63 if gtok == '(' or paren_stack > 1:
64 yield Token(lineno, 'data', gtok)
65 paren_stack += gtok == ')' and -1 or 1
66 if not paren_stack:
67 yield Token(lineno, 'block_begin', None)
68 yield Token(lineno, 'name', 'endtrans')
69 yield Token(lineno, 'block_end', None)
70 pos = match.end()
71
72 if pos < len(token.value):
73 yield Token(lineno, 'data', token.value[pos:])
74
75 if paren_stack:
76 raise TemplateSyntaxError('unclosed gettext expression',
77 token.lineno, stream.name,
78 stream.filename)