我想trans
通过呈现变量而不是作为上下文中的值,而是作为 html(不使用上下文)来扩展 的行为。我的目标是能够通过 JavaScript 在客户端上填充这些变量。
Jinja 似乎不允许进行大量此类自定义,或者我只是找不到合适的钩子。
这是我想要实现的目标:
{% etrans name=username %}
My name is {{ name }}
{% endetrans %}
这应该呈现为:
My name is <span id='#username'></span>
当然,我可以只使用普通{% trans %}
指令并将我的 html 代码传递给template.render(html_code_params)
,但这需要在模板中定义它们以及我想避免的呈现代码。
这是我到目前为止得到的(不多),它允许一个新的etrans
标签和使用任何好东西的能力InternationalizationExtension
。
from jinja2.ext import InternationalizationExtension
from jinja2.runtime import concat
class JavaScriptVariableExtension(InternationalizationExtension):
tagname = 'etrans'
tags = set([tagname])
def _parse_block(self, parser, allow_pluralize):
"""Parse until the next block tag with a given name.
Copy from InternationalizationExtension, as this uses hardcoded
`name:endtrans` instead of relying on tag name
"""
referenced = []
buf = []
while 1:
if parser.stream.current.type == 'data':
buf.append(parser.stream.current.value.replace('%', '%%'))
next(parser.stream)
elif parser.stream.current.type == 'variable_begin':
next(parser.stream)
name = parser.stream.expect('name').value
referenced.append(name)
buf.append('%%(%s)s' % name)
parser.stream.expect('variable_end')
elif parser.stream.current.type == 'block_begin':
next(parser.stream)
# can't use hardcoded "endtrans"
# if parser.stream.current.test('name:endtrans'):
if parser.stream.current.test('name:end%s' % self.tagname):
break
elif parser.stream.current.test('name:pluralize'):
if allow_pluralize:
break
parser.fail('a translatable section can have only one '
'pluralize section')
parser.fail('control structures in translatable sections are '
'not allowed')
elif parser.stream.eos:
parser.fail('unclosed translation block')
else:
assert False, 'internal parser error'
return referenced, concat(buf)
i18n_extended = JavaScriptVariableExtension
我不介意重载更多方法(尽管上述方法的原因可能应该在上游修复)。
单步执行代码是一次非常有趣的冒险。但是,我遇到了一个障碍,如果有人可以提供一些建议,我很感兴趣。
我看到的问题是,在编译过程中,函数 context.resolve() 被烘焙到编译后的代码中。jinja2.jinja2.compiler.CodeGenerator
在这里实际上不允许任何不同的处理(如果我错了,请纠正我)。理想情况下,我会定义另一个节点(用于变量),并且该节点将处理它在编译期间的处理方式,但我不明白这是怎么可能的。我可能过于关注这个作为解决方案,所以也许有人可以提供替代方案。