from collections import deque
from jinja2 import nodes
from jinja2.defaults import *
-from jinja2.environment import get_spontaneous_environment
+from jinja2.environment import Environment
from jinja2.runtime import Undefined, concat
from jinja2.exceptions import TemplateAssertionError, TemplateSyntaxError
from jinja2.utils import contextfunction, import_string, Markup, next
def attr(self, name, lineno=None):
"""Return an attribute node for the current extension. This is useful
- to pass constants on extensions to generated template code::
+ to pass constants on extensions to generated template code.
+
+ ::
self.attr('_my_attribute', lineno=lineno)
"""
def _make_new_ngettext(func):
@contextfunction
- def ngettext(__context, __singular, __plural, num, **variables):
- variables.setdefault('num', num)
- rv = __context.call(func, __singular, __plural, num)
+ def ngettext(__context, __singular, __plural, __num, **variables):
+ variables.setdefault('num', __num)
+ rv = __context.call(func, __singular, __plural, __num)
if __context.eval_ctx.autoescape:
rv = Markup(rv)
return rv % variables
def parse(self, parser):
"""Parse a translatable tag."""
lineno = next(parser.stream).lineno
+ num_called_num = False
# find all the variables referenced. Additionally a variable can be
# defined in the body of the trans block too, but this is checked at
variables[name.value] = var = parser.parse_expression()
else:
variables[name.value] = var = nodes.Name(name.value, 'load')
+
if plural_expr is None:
plural_expr = var
+ num_called_num = name.value == 'num'
parser.stream.expect('block_end')
referenced.update(singular_names)
if plural_expr is None:
plural_expr = nodes.Name(singular_names[0], 'load')
+ num_called_num = singular_names[0] == 'num'
# if we have a pluralize block, we parse that too
if parser.stream.current.test('name:pluralize'):
name.value, name.lineno,
exc=TemplateAssertionError)
plural_expr = variables[name.value]
+ num_called_num = name.value == 'num'
parser.stream.expect('block_end')
plural_names, plural = self._parse_block(parser, False)
next(parser.stream)
parser.fail('pluralize without variables', lineno)
node = self._make_node(singular, plural, variables, plural_expr,
- bool(referenced))
+ bool(referenced),
+ num_called_num and have_plural)
node.set_lineno(lineno)
return node
return referenced, concat(buf)
def _make_node(self, singular, plural, variables, plural_expr,
- vars_referenced):
+ vars_referenced, num_called_num):
"""Generates a useful node from the data provided."""
# no variables referenced? no need to escape for old style
- # gettext invocations
+ # gettext invocations only if there are vars.
if not vars_referenced and not self.environment.newstyle_gettext:
singular = singular.replace('%%', '%')
if plural:
# enough to handle the variable expansion and autoescape
# handling itself
if self.environment.newstyle_gettext:
- print 'HERE'
for key, value in variables.iteritems():
+ # the function adds that later anyways in case num was
+ # called num, so just skip it.
+ if num_called_num and key == 'num':
+ continue
node.kwargs.append(nodes.Keyword(key, value))
# otherwise do that here
gettext call in one line of code and the matching comment in the
same line or the line before.
+ .. versionchanged:: 2.5.1
+ The `newstyle_gettext` flag can be set to `True` to enable newstyle
+ gettext calls.
+
+ .. versionchanged:: 2.7
+ A `silent` option can now be provided. If set to `False` template
+ syntax errors are propagated instead of being ignored.
+
:param fileobj: the file-like object the messages should be extracted from
:param keywords: a list of keywords (i.e. function names) that should be
recognized as translation functions
if InternationalizationExtension not in extensions:
extensions.add(InternationalizationExtension)
- environment = get_spontaneous_environment(
+ def getbool(options, key, default=False):
+ return options.get(key, str(default)).lower() in \
+ ('1', 'on', 'yes', 'true')
+
+ silent = getbool(options, 'silent', True)
+ environment = Environment(
options.get('block_start_string', BLOCK_START_STRING),
options.get('block_end_string', BLOCK_END_STRING),
options.get('variable_start_string', VARIABLE_START_STRING),
options.get('comment_end_string', COMMENT_END_STRING),
options.get('line_statement_prefix') or LINE_STATEMENT_PREFIX,
options.get('line_comment_prefix') or LINE_COMMENT_PREFIX,
- str(options.get('trim_blocks', TRIM_BLOCKS)).lower() in \
- ('1', 'on', 'yes', 'true'),
+ getbool(options, 'trim_blocks', TRIM_BLOCKS),
NEWLINE_SEQUENCE, frozenset(extensions),
- # fill with defaults so that environments are shared
- # with other spontaneus environments. The rest of the
- # arguments are optimizer, undefined, finalize, autoescape,
- # loader, cache size, auto reloading setting and the
- # bytecode cache
- True, Undefined, None, False, None, 0, False, None
+ cache_size=0,
+ auto_reload=False
)
+ if getbool(options, 'newstyle_gettext'):
+ environment.newstyle_gettext = True
+
source = fileobj.read().decode(options.get('encoding', 'utf-8'))
try:
node = environment.parse(source)
tokens = list(environment.lex(environment.preprocess(source)))
except TemplateSyntaxError, e:
+ if not silent:
+ raise
# skip templates with syntax errors
return