Добавление ссылки внутри переведенного контента в шаблоне Twig

Внутри шаблона Twig мне понадобится переведенный текст, содержащий ссылку (путь должен быть сгенерирован маршрутизатором, а не статически встроен). Twig не позволяет отображать переменную внутри блока trans - я также знаю следующее:

{% trans with {'%name%': 'Fabien'} from "app" %}
Hello %name%
{% endtrans %}

но я не вижу, как использовать это, чтобы вставить в перевод такой кусок

<a href="{{ path('privacy') }}">privacy policy</a>

(конечно, якорный текст тоже нужно перевести)


person Roberto    schedule 18.07.2012    source источник


Ответы (4)


Я использовал следующий подход:

В файле перевода:

page.privacy.policy: Please read our %link_start%privacy policy%link_end%

В файле ветки:

<p>{{ 'page.privacy.policy' | trans({'%link_start%' : '<a href="'~path('privacy-policy')~'">', '%link_end%' : '</a>'}, 'account') | raw }}</p>

Я не уверен, можно ли это сделать, используя синтаксис блока, о котором вы упомянули выше, поскольку я обнаружил, что он не работает, если я не передал результат перевода через «необработанный» фильтр. Также я использую домены сообщений для разделения переводов, отсюда и параметр account.

Я думаю, что наиболее близким к вашему примеру будет:

<p>{{ 'Please read our %link_start%privacy policy%link_end%' | trans({'%link_start%' : '<a href="'~path('privacy-policy')~'">', '%link_end%' : '</a>'}) | raw }}</p>

РЕДАКТИРОВАТЬ:

Единственная проблема с этим подходом, с которой я столкнулся, заключается в том, что мне нужно программно следовать переведенной ссылке в модульном тесте, поскольку нет единого перевода, представляющего текст ссылки. Хотя это и беспорядочно, я думаю, что можно было бы обойти это, предоставив отдельный перевод для текста ссылки и подставив переведенное значение в полный текст в качестве дополнительной переменной.

person redbirdo    schedule 18.07.2012
comment
Также убедитесь, что замены %link_start% и %link_end% не содержат вводимых пользователем данных, поскольку последняя строка не закодирована (|raw). Это сделает приложение уязвимым для атаки межсайтового скриптинга (XSS). - person thomaskonrad; 01.08.2014
comment
Короче (нет необходимости использовать% xxx%): в файле перевода: page.privacy.policy: прочтите нашу [политику конфиденциальности]; в файле twig: {{'page.privacy.policy' | trans ({'[': '‹a href='~path('privacy-policy')~'›', ']': '‹/a›'}, 'account') | сырой }} - person Ka.; 20.04.2015
comment
@ka, хотя он короче и красивее, во многих организациях такие значения перевода могут произвольно изменяться не разработчиками, то есть они используются как нетехнический способ обновления текста страницы. Если вы используете в качестве разделителя один символ, например '[', гораздо больше шансов, что он в какой-то момент столкнется с подлинным использованием этого символа. Соглашение% xxx% - это то, что документы symfony используют в своих примерах для заполнителей сообщений. - person redbirdo; 24.04.2015

Решение rebdirdo на самом деле небезопасно, поскольку оно не экранирует все сообщение. Он работает некорректно для таких сообщений, как "don't use <b> tag, use <strong> tag instead. %link_start%Here%link_end% you can find why.", потому что теги не будут экранированы и не будут видны.

рабочий подход:

файл перевода:

advises.strong: don't use <b> tag, use <strong> tag instead. %link_start%Here%link_end% you can find why.

файл twig:

{{ 'advises.strong'|trans|nl2br|replace({'%link_start%': '<a href="'~path('privacy-policy')~'">', '%link_end%': '</a>'})|raw }}

Обратите внимание на фильтр nl2br. Здесь необходимо поставить какой-то фильтр, чтобы сырой фильтр работал только для тегов ссылок.

person J4rmu1    schedule 09.08.2013
comment
Да, на это стоит указать. Если вы хотите буквально отображать HTML-теги, используйте этот ответ. Если вы хотите, чтобы ваши HTML-теги интерпретировались как HTML, используйте основной ответ. - person ecc; 14.04.2015
comment
Я бы рекомендовал использовать escape-фильтр вместо nl2br. Тот же результат, никаких возможных нежелательных побочных эффектов, и он гораздо более логичен и не требует пояснений. - person patrickj; 01.09.2016

Это лучший способ:

{{ 'Please read our %privacy_policy%'|trans({
    '%privacy_policy%': '<a href="' ~ path('privacypolicy') ~ '"> ' ~ 'Privacy Policy'|trans ~ '</a>'
})|raw }}
person the_nuts    schedule 08.06.2016

Ветка:

{{'body.term'|trans('%link_terms%' :app.request.getSchemeAndHttpHost()~path('terms')},'AcmeTerm')|raw }}

AcmeTerm.yml

body
    term: >
      <ul>          
          <li>Read<a href="%link_terms%">Terms</a>.</li>
      </ul>

где path ('terms') - это такой маршрут, как:

it__RG__terms                             ANY      ANY    ANY  /it/termini-e-condizioni
en__RG__terms                             ANY      ANY    ANY  /en/terms-and-conditions
person Barno    schedule 05.10.2013
comment
Вы также можете просто использовать функцию url('terms') вместо app.request.getSchemeAndHttpHost()~path('terms'). - person Soullivaneuh; 26.01.2017