фильтры внутри django trans tag: сначала переводит, затем применяет фильтры; в отличие от других тегов - PullRequest
2 голосов
/ 19 марта 2020

Я столкнулся со странным поведением из тега django trans. Как вы знаете, всякий раз, когда мы используем фильтр внутри тега, фильтр сначала применяется, а затем выдает результат в качестве входных данных для тега. Но это в обратном порядке для тега trans.

Пример:

Предположим, у меня есть этот django .po файл:

msgid "msgid-world"
msgstr "world"

msgid "msgid-"
msgstr "message"

Теперь посмотрите результат этих теги:

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

Ожидаемый результат: "мир" (сначала конкат, затем переведите ключ)

ОБНОВЛЕНИЕ :

Моя проблема заключается в согласованности , Поведение с другими тегами (например, «если») является обратным!

Более того, если я напишу собственный тег для себя, как показано ниже:

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

, тогда он будет вести себя как другие теги. Результат этого примера (как и в приведенном выше примере):

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

будет "миром".

Это таинственный момент, который я хочу понять!

Ответы [ 2 ]

0 голосов
/ 20 марта 2020

Да, вы правы, я проанализировал django реализацию simple_tag и trans:

Важными частями анализа являются:

  1. Используя simple_tag и trans, оба в конечном итоге будут иметь одинаковые 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 - Возможно, строка do c может быть немного более явной.

С trans и blocktrans вы в основном можете go в обе стороны, предварительно заполненные или нет.

Вы все еще можете использовать tag вместо simple_tag и реализовать его по-другому .

Я не нашел ничего о руководящих указаниях, где следовать jinja2-filters logi c или нет. Это было ложное предположение с моей стороны.

0 голосов
/ 19 марта 2020

Согласно документации jinja2

Переменные могут быть изменены фильтрами. Фильтры отделяются от переменной символом канала (|) и могут иметь необязательные аргументы в скобках. Несколько фильтров могут быть связаны. Вывод одного фильтра применяется к следующему

Таким образом, он делает то, что описано:

  1. оценивает trans с аргументом "msgid -"
  2. передает результат следующему фильтру и добавляет «мир»

Я предлагаю вам использовать blocktrans для своего puropse

{% 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/ для тонны вариантов, как вы можете решить вашу проблему

...