【问题标题】:filters inside django trans tag : first translates then applies filters; unlike other tagsdjango trans 标签内的过滤器:首先翻译然后应用过滤器;不像其他标签
【发布时间】:2020-06-30 22:22:59
【问题描述】:

我遇到了来自 django trans 标签的奇怪行为。如您所知,每当我们在标签内使用过滤器时,过滤器首先应用,然后将结果作为输入提供给标签。但这与 trans 标签的顺序相反。

例子:

假设我有这个 django.po 文件:

msgid "msgid-world"
msgstr "world"

msgid "msgid-"
msgstr "message"

现在看看这些标签的结果:

{% trans "msgid-"|add:"world" %}
result: messageworld  (first translate then concat)

预期结果:“world”(先concat然后翻译key)

更新

我的问题是关于一致性。与其他标签(如“if”)的行为相反!

此外,如果我为自己编写一个自定义标签,如下所示:

@register.simple_tag
def customtrans(a):
    return _(str(a))

那么它将表现得像其他标签一样。本例的结果(如上例):

{% customtrans "msgid-"|add:"world" %}

将是“世界”。

这就是我想了解的奥秘!

【问题讨论】:

    标签: django django-templates django-template-filters django-i18n


    【解决方案1】:

    根据jinja2 documentation

    变量可以通过过滤器进行修改。过滤器通过管道符号 (|) 与变量分隔,并且可以在括号中包含可选参数。可以链接多个过滤器。一个过滤器的输出应用于下一个过滤器

    所以它做了描述的事情:

    1. 使用参数“msgid-”评估trans
    2. 将结果传递给下一个过滤器并添加“世界”

    我建议您使用blocktrans 来实现您的目的

    {% load i18n %}
    {% blocktrans %}
        msgid-world
    {% endblocktrans %}
    

    或者你可以使用 with 语句:

    {% with variable="msgid-"|add:"world"}
        {% trans variable %}
    {% endwith%}
    

    还可以查看https://docs.djangoproject.com/en/3.0/topics/i18n/translation/,了解如何解决问题的大量选项

    【讨论】:

      【解决方案2】:

      是的你是对的,我分析了simple_tagtrans的django实现:

      分析的重要部分是:

      1. 使用simple_tagtrans,两者最终将具有相同的FilterExpression https://github.com/django/django/blob/e3d546a1d986f83d8698c32e13afd048b65d06eb/django/template/library.py#L123

        (Pdb) l
        119                     args, kwargs = parse_bits(
        120                         parser, bits, params, varargs, varkw, defaults,
        121                         kwonly, kwonly_defaults, takes_context, function_name,
        122                     )
        123  ->                 return SimpleNode(func, takes_context, args, kwargs, target_var)
        (Pdb) print(args)
        [<django.template.base.FilterExpression object at 0x1061e5cf8>]
        (Pdb) print(args[0].__dict__)
        {'token': '"msgid-"|add:"world"', 'filters': [(<function add at 0x10c2369d8>, [(False, 'world')])], 'var': 'msgid-'}
        
        (Pdb) l
        368         message_context = None
        369         seen = set()
        370         invalid_context = {'as', 'noop'}
        371
        372  ->     while remaining:
        373             option = remaining.pop(0)
        374             if option in seen:
        376                 raise TemplateSyntaxError(
        377                     "The '%s' option was specified more than once." % 
        (Pdb) message_string.__dict__
        {'token': '"msgid-"|add:"world"', 'filters': [(<function add at 0x1112a79d8>, [(False, 'world')])], 'var': 'msgid-'}
        
      2. 但现在实现不同了

        simple_tag 使用 SimpleNode,它在传递给你的函数之前首先解析参数 (https://github.com/django/django/blob/e3d546a1d986f83d8698c32e13afd048b65d06eb/django/template/library.py#L191),trans 使用它自己的 TranslationNode (https://github.com/django/django/blob/e3d546a1d986f83d8698c32e13afd048b65d06eb/django/templatetags/i18n.py#L68) 实现,其行为不同.

      一致性 首先,这很有趣,因为我不知道不同的行为。

      最后是一个实现细节,这是基于作者的品味。 simple_tag 是这样实现的,它也在代码 https://github.com/django/django/commit/655f52491505932ef04264de2bce21a03f3a7cd0#diff-258b66ed22ebadbcfec255f802c95bdfR173-R176 中描述 - 也许文档字符串可能更明确一点。

      使用transblocktrans,您基本上可以双向使用,无论是否预先填充。

      您仍然可以使用tag 代替simple_tag 并以不同的方式实现它。

      我还没有找到任何关于遵循 jinja2-filters 逻辑的指南。这是我的错误假设。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-03-18
        • 2020-02-16
        • 2017-11-11
        • 2011-04-05
        • 2013-03-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多