Symfony News

New in Symfony 5.2: Translatable objects

Nate Wiebe

Contributed by
Nate Wiebe
in #37670.

Translating contents usually require more information than the original message, such as the translation parameters and the translation domain. In order to make templates simpler, you could translate the entire messages in the backend and pass the translations to the templates.

However, this is sometimes cumbersome and also requires injecting the translator service in several layers of your application. Another alternative is to pass all the translation data (message, parameters, domain) to the template:

1
2
3
4
5
6
7
return $this->render('...', [
    'order_status' => [
        'message' => 'order.status_message',
        'params' => ['status' => $status, 'order' => $order],
        'domain' => 'admin',
    ],
]);

This no longer requires injecting the translator, but makes templates more complex:

1
{{ order_status.message|trans(order_status.params, order_status.domain) }}

In Symfony 5.2 we’re introducing a new Translatable class that solves this problem in an easier way. First, create a Translatable object and pass all the translation data to it:

1
2
3
4
5
6
7
8
9
use Symfony\Component\Translation\Translatable;

return $this->render('...', [
    'order_status' => new Translatable(
        'order.status_message',
        ['status' => $status, 'order' => $order],
        'admin'
    ),
]);

Now you can translate this object in your template with the same trans filter as before, but in a much simpler way:

1
{{ order_status|trans }}

The translatable object holds all the translation data, so the trans filter can extract it automatically. This solution allows to simplify both the templates and the backend code, because you don’t need to inject the translator or mock it when writing unit tests.

This feature also introduces a new t() function, usable both in PHP and Twig templates, to quickly create this kind of objects. The following example uses that function to create a fallback translation which uses different parameters than the default translation:

1
2
3
4
5
{# Before #}
{{ message is defined ? message|trans : fallback|trans({'%param%': value}) }}

{# After #}
{{ message|default(t(fallback, {'%param%': value}))|trans }}

Kudos to the amazing folks at Symfony Slack chat who helped me better understand this feature so I could prepare this blog post.


Sponsor the Symfony project.


About us

What a Symfony developer should know about the framework: News, Jobs, Tweets, Events, Videos,...

Resources

Find us on Twitter

Find us on Facebook