From 41ebf3e2ed0147e060f784cbe5b54161e9261054 Mon Sep 17 00:00:00 2001 From: jomae Date: Sun, 5 May 2024 02:41:40 +0000 Subject: [PATCH] 1.6.1dev: fix `KeyError` raised when `IRequestHandler.process_request` returns domain parameter in the metadata and add `tagn_`, `dtgettext` and `dtngettext` to `translation.functions` (closes #13745) git-svn-id: http://trac.edgewall.org/intertrac/log:/branches/1.6-stable@17794 af82e41b-90c4-0310-8c96-b1721e28e2e2 --- trac/util/translation.py | 5 +++++ trac/web/chrome.py | 5 ++++- trac/web/tests/chrome.py | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/trac/util/translation.py b/trac/util/translation.py index 9e53e1bf99..d7b959c5e4 100644 --- a/trac/util/translation.py +++ b/trac/util/translation.py @@ -292,6 +292,8 @@ def domain_functions(domain, *symbols): def wrapdomain(symbol): if symbol == 'N_': return _noop + if symbol not in _functions: + raise KeyError(symbol) return lambda *args, **kw: _functions[symbol](domain, *args, **kw) return [wrapdomain(s) for s in symbols] @@ -455,4 +457,7 @@ def s_gettext(msgid, **kwargs): 'gettext': s_gettext, 'ngettext': ngettext, 'tag_': tag_, + 'tagn_': tagn_, + 'dtgettext': dtgettext, + 'dtngettext': dtngettext, } diff --git a/trac/web/chrome.py b/trac/web/chrome.py index 4ce423e7fd..6652879f85 100644 --- a/trac/web/chrome.py +++ b/trac/web/chrome.py @@ -1477,13 +1477,16 @@ def prepare_template(self, req, filename, data, text=False, domain=None): (see `populate_data`) :param text: in text mode (``True``) XML/HTML auto-escape of variable expansion is disabled. + :param domain: domain to be adapted to the translation helper functions :rtype: a pair of Jinja2 `Template` and a `dict`. """ template = self.load_template(filename, text) if domain: - symbols = list(translation.functions) + symbols = [s for s in translation.functions + if s not in ('dgettext', 'dngettext', 'dtgettext', + 'dtngettext')] domain_functions = translation.domain_functions(domain, symbols) data.update(dict(zip(symbols, domain_functions))) data = self.populate_data(req, data) diff --git a/trac/web/tests/chrome.py b/trac/web/tests/chrome.py index 2296e44758..4c43092b9c 100644 --- a/trac/web/tests/chrome.py +++ b/trac/web/tests/chrome.py @@ -1230,6 +1230,45 @@ def fn(): b'common/css/blahblah.css", "text/css");', content) self.assertIn(b' var blahblah=42;', content) + def test_render_template_i18n_domain(self): + """Regression test for #13745""" + + template = textwrap.dedent("""\ + ${_("anonymous")} + ${gettext("Admin")} + ${ngettext("%(num)d byte", "%(num)d bytes", num=num)} + ${tag_("You may use %(wikiformatting)s here.", + wikiformatting=tag.b('WikiFormatting'))} + ${tagn_("%(value)s added", "%(value)s added", len(values), + value=values|join(' '))} + ${dgettext("messages", "Timeline")} + ${dngettext("messages", "%(num)d day", "%(num)d days", num)} + ${dtgettext("messages", "Quickjump to %(name)s", + name=tag.b('WikiStart'))} + ${dtngettext("messages", "%(value)s removed", "%(value)s removed", + len(values), value=values|join(' '))} + """) + filename = 'ticket13745.html' + filepath = os.path.join(self.env.templates_dir, filename) + create_file(filepath, template) + + def test(domain=None): + req = MockRequest(self.env) + data = {'num': 42, 'values': ['foo', 'bar']} + metadata = {'iterable': False} + if domain: + metadata['domain'] = domain + content = str(self.chrome.render_template(req, filename, data, + metadata), 'utf-8') + self.assertEqual([ + 'anonymous', 'Admin', '42 bytes', + 'You may use WikiFormatting here.', 'foo bar added', + 'Timeline', '42 days', 'Quickjump to WikiStart', + 'foo bar removed'], content.splitlines()) + + test(domain=None) + test(domain='messages') + def test_suite(): suite = unittest.TestSuite()