【发布时间】:2016-01-22 05:18:26
【问题描述】:
我想扩展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 确实不允许在这里进行任何不同的处理(如果我错了,请纠正我)。理想情况下,我会定义另一个节点(用于变量),这个节点将处理它在编译期间的处理方式,但我不明白这是怎么可能的。我可能过于关注这个作为解决方案,所以也许有人可以提供替代方案。
【问题讨论】:
-
你有没有想过一个函数来生成所需的 HTML,用法如下:
My name is {{ slug("username") }}? -
不,我没有。那将是另一种解决方案。如果我找不到更接近我的想法的东西,我会解决这个问题。
-
试过了,但似乎不起作用。作为宏
slug在{% trans %}环境中无法识别(但在外部有效)。 -
将函数传递到渲染环境是可行的(也可以在 trans 标头中使用宏并将其分配给变量)。
-
优秀 - 如果您找到了可行的解决方案,请随时将其转化为答案
标签: python compilation jinja2 python-babel