Change record status: 
Project: 
Introduced in branch: 
8.x
Description: 

In template files, we currently do something like this:

<p class="submitted">{{ submitted }}</p>

Front-end developers despise this. What they want instead:

<p class="submitted">Submitted by {{ author }} on {{ date }}</p>

Unfortunately, this isn't translatable. We'd have to give them something like:

<p class="submitted">{{ "Submitted by !author on @date"|t({ '!author': author, '@date': date }) }}</p>

This syntax is extremely complex to scan. This also requires the front-end developer to know about the @ ! % "Drupalism" prefix of placeholders and what each of them do.

Introducing the Twig {% trans %} tag

Twig has a better way to solve this problem, the {% trans %} tag. It will translate the text using tokens with t() or format_plural() if the {% plural ... %} switch has been declared in the tag:

<p class="submitted">
{% trans %}
  Submitted by {{ author.name }} on {{ node.date }}
{% endtrans %}
</p>

Note: When using complex tokens (ie: arrays/objects) the placeholder name used for translation msgids is the key name in the token (after the . dot). In the above example, the msgid would read: Submitted by @name on @date, not Submitted by @author.name on @node.date.

Note: Filtering tokens inside the {% trans %} tag generally work. However, some of these filters may not work properly or at all. If you are not seeing the desired result or you are receiving fatal errors/WSOD you may need scale down what you are trying to do inside the {% trans %} tag. Create a new token outside of the tag with this filter applied:

{% set date = node.created|format_date('medium') %}
{% trans %}
  Node was created on {{ date }}.
{% endtrans %}

We can also extend the {% trans %} tag with a {% plural ... %} switch as well:

{% set count = comments|length %}
{% trans %}
  {{ count }} comment was deleted successfully.
{% plural count %}
  {{ count }} comments were deleted successfully.
{% endtrans %}

By default, all tokens are sent to t() or format_plural() with a @ prefix, to be escaped. If the value of that token needs to be passed through (!) or used as a placeholder (%), modify the token with these filters:

{% set string = '&"<>' %}
<div>
  {% trans %}
    Escaped: {{ string }}
  {% endtrans %}
</div>
<div>
  {% trans %}
    Pass-through: {{ string|passthrough }}
  {% endtrans %}
</div>
<div>
  {% trans %}
    Placeholder: {{ string|placeholder }}
  {% endtrans %}
</div>

View the expected translation msgid when templates use {% trans %} and twig_debug is enabled:

<!-- TRANSLATION: "Hello star.", PLURAL: "Hello @count stars." -->

Language Options

The t() and format_plural() functions have an $options parameter that can provide additional context or allow a specific language to be chosen for translation. To pass these options in the {% trans %} tag, use the with { ... } syntax in the opening tag:

{% trans with {'context': 'Long month name', 'langcode': 'fr'} %}
  January
{% endtrans %}

Example debug output using with { ... }:
<!-- TRANSLATION: "January", CONTEXT: "Long month name", LANGCODE: "fr" -->

Impacts: 
Site builders, administrators, editors
Module developers
Themers
Updates Done (doc team, etc.)
Online documentation: 
Not done
Theming guide: 
Not done
Module developer documentation: 
Not done
Examples project: 
Not done
Coder Review: 
Not done
Coder Upgrade: 
Not done
Other: 
Not done