Armin Ronacher | d02fc7d | 2008-06-14 14:19:47 +0200 | [diff] [blame^] | 1 | # -*- 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 | """ |
| 12 | import re |
| 13 | from jinja2.ext import Extension |
| 14 | from jinja2.lexer import Token, count_newlines |
| 15 | from jinja2.exceptions import TemplateSyntaxError |
| 16 | |
| 17 | |
| 18 | _outside_re = re.compile(r'\\?(gettext|_)\(') |
| 19 | _inside_re = re.compile(r'\\?[()]') |
| 20 | |
| 21 | |
| 22 | class 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) |