From b8892e7b036118015b158b173f73845878166d03 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Sat, 29 May 2010 17:58:06 +0200 Subject: [PATCH] Finished support for newstyle gettext translations --HG-- branch : trunk --- jinja2/environment.py | 7 +++++ jinja2/ext.py | 22 ++++++-------- jinja2/testsuite/ext.py | 63 +++++++++++++++++++++++++++++++++++------ 3 files changed, 71 insertions(+), 21 deletions(-) diff --git a/jinja2/environment.py b/jinja2/environment.py index 529c14c..03aef1a 100644 --- a/jinja2/environment.py +++ b/jinja2/environment.py @@ -279,6 +279,13 @@ class Environment(object): _environment_sanity_check(self) + def add_extension(self, extension): + """Adds an extension after the environment was created. + + .. versionadded:: 2.5 + """ + load_extensions(self, [extension]) + def extend(self, **attributes): """Add the items to the instance of the environment if they do not exist yet. This is used by :ref:`extensions ` to register diff --git a/jinja2/ext.py b/jinja2/ext.py index e6bef2f..4220657 100644 --- a/jinja2/ext.py +++ b/jinja2/ext.py @@ -124,13 +124,13 @@ class Extension(object): @contextfunction def _gettext_alias(__context, *args, **kwargs): - return __context.resolve('gettext')(*args, **kwargs) + return __context.call(__context.resolve('gettext'), *args, **kwargs) def _make_new_gettext(func): @contextfunction def gettext(__context, __string, **variables): - rv = func(__string) + rv = __context.call(func, __string) if __context.eval_ctx.autoescape: rv = Markup(rv) return rv % variables @@ -141,7 +141,7 @@ def _make_new_ngettext(func): @contextfunction def ngettext(__context, __singular, __plural, num, **variables): variables.setdefault('num', num) - rv = func(__singular, __plural, num) + rv = __context.call(func, __singular, __plural, num) if __context.eval_ctx.autoescape: rv = Markup(rv) return rv % variables @@ -286,12 +286,6 @@ class InternationalizationExtension(Extension): elif plural_expr is None: parser.fail('pluralize without variables', lineno) - if variables: - variables = nodes.Dict([nodes.Pair(nodes.Const(x, lineno=lineno), y) - for x, y in variables.items()]) - else: - variables = None - node = self._make_node(singular, plural, variables, plural_expr) node.set_lineno(lineno) return node @@ -349,9 +343,8 @@ class InternationalizationExtension(Extension): # enough to handle the variable expansion and autoescape # handling itself if self.environment.newstyle_gettext: - if variables is None: - variables = nodes.Dict([]) - node.kwargs = variables + for key, value in variables.iteritems(): + node.kwargs.append(nodes.Keyword(key, value)) # otherwise do that here else: @@ -359,7 +352,10 @@ class InternationalizationExtension(Extension): # environment with autoescaping turned on node = nodes.MarkSafeIfAutoescape(node) if variables: - node = nodes.Mod(node, variables) + node = nodes.Mod(node, nodes.Dict([ + nodes.Pair(nodes.Const(key), value) + for key, value in variables.items() + ])) return nodes.Output([node]) diff --git a/jinja2/testsuite/ext.py b/jinja2/testsuite/ext.py index c00c589..1306973 100644 --- a/jinja2/testsuite/ext.py +++ b/jinja2/testsuite/ext.py @@ -31,24 +31,37 @@ importable_object = 23 _gettext_re = re.compile(r'_\((.*?)\)(?s)') -templates = { +i18n_templates = { 'master.html': '{{ page_title|default(_("missing")) }}' '{% block body %}{% endblock %}', 'child.html': '{% extends "master.html" %}{% block body %}' '{% trans %}watch out{% endtrans %}{% endblock %}', 'plural.html': '{% trans user_count %}One user online{% pluralize %}' '{{ user_count }} users online{% endtrans %}', - 'stringformat.html': '{{ _("User: %d")|format(user_count) }}' + 'stringformat.html': '{{ _("User: %(num)d")|format(num=user_count) }}' +} + +newstyle_i18n_templates = { + 'master.html': '{{ page_title|default(_("missing")) }}' + '{% block body %}{% endblock %}', + 'child.html': '{% extends "master.html" %}{% block body %}' + '{% trans %}watch out{% endtrans %}{% endblock %}', + 'plural.html': '{% trans user_count %}One user online{% pluralize %}' + '{{ user_count }} users online{% endtrans %}', + 'stringformat.html': '{{ _("User: %(num)d", num=user_count) }}', + 'ngettext.html': '{{ ngettext("%(num)d apple", "%(num)d apples", apples) }}' } languages = { 'de': { - 'missing': 'fehlend', - 'watch out': 'pass auf', - 'One user online': 'Ein Benutzer online', - '%(user_count)s users online': '%(user_count)s Benutzer online', - 'User: %d': 'Benutzer: %d' + 'missing': u'fehlend', + 'watch out': u'pass auf', + 'One user online': u'Ein Benutzer online', + '%(user_count)s users online': u'%(user_count)s Benutzer online', + 'User: %(num)d': u'Benutzer: %(num)d', + '%(num)d apple': u'%(num)d Apfel', + '%(num)d apples': u'%(num)d Äpfel' } } @@ -68,7 +81,7 @@ def ngettext(context, s, p, n): i18n_env = Environment( - loader=DictLoader(templates), + loader=DictLoader(i18n_templates), extensions=['jinja2.ext.i18n'] ) i18n_env.globals.update({ @@ -77,6 +90,11 @@ i18n_env.globals.update({ 'ngettext': ngettext }) +newstyle_i18n_env = Environment( + loader=DictLoader(newstyle_i18n_templates), + extensions=['jinja2.ext.i18n'] +) +newstyle_i18n_env.install_gettext_callables(gettext, ngettext, newstyle=True) class TestExtension(Extension): tags = set(['test']) @@ -266,6 +284,34 @@ class InternationalizationTestCase(JinjaTestCase): ] +class NewstyleInternationalizationTestCase(JinjaTestCase): + + def test_trans(self): + tmpl = newstyle_i18n_env.get_template('child.html') + assert tmpl.render(LANGUAGE='de') == 'fehlendpass auf' + + def test_trans_plural(self): + tmpl = newstyle_i18n_env.get_template('plural.html') + assert tmpl.render(LANGUAGE='de', user_count=1) == 'Ein Benutzer online' + assert tmpl.render(LANGUAGE='de', user_count=2) == '2 Benutzer online' + + def test_complex_plural(self): + tmpl = newstyle_i18n_env.from_string('{% trans foo=42, count=2 %}{{ count }} item{% ' + 'pluralize count %}{{ count }} items{% endtrans %}') + assert tmpl.render() == '2 items' + self.assert_raises(TemplateAssertionError, i18n_env.from_string, + '{% trans foo %}...{% pluralize bar %}...{% endtrans %}') + + def test_trans_stringformatting(self): + tmpl = newstyle_i18n_env.get_template('stringformat.html') + assert tmpl.render(LANGUAGE='de', user_count=5) == 'Benutzer: 5' + + def test_newstyle_plural(self): + tmpl = newstyle_i18n_env.get_template('ngettext.html') + assert tmpl.render(LANGUAGE='de', apples=1) == '1 Apfel' + assert tmpl.render(LANGUAGE='de', apples=5) == u'5 Äpfel' + + class AutoEscapeTestCase(JinjaTestCase): def test_scoped_setting(self): @@ -347,5 +393,6 @@ def suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(ExtensionsTestCase)) suite.addTest(unittest.makeSuite(InternationalizationTestCase)) + suite.addTest(unittest.makeSuite(NewstyleInternationalizationTestCase)) suite.addTest(unittest.makeSuite(AutoEscapeTestCase)) return suite -- 2.26.2