Skip to content

Commit 4e193e8

Browse files
committed
Feat: improved example for translatable objects
1 parent 50f1f4d commit 4e193e8

File tree

1 file changed

+75
-20
lines changed

1 file changed

+75
-20
lines changed

translation.rst

Lines changed: 75 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -307,40 +307,93 @@ using PHP's :phpclass:`MessageFormatter` class. Read more about this in
307307
Translatable Objects
308308
--------------------
309309

310-
Sometimes translating contents in templates is cumbersome because you need the
311-
original message, the translation parameters and the translation domain for
312-
each content. Making the translation in the controller or services simplifies
313-
your templates, but requires injecting the translator service in different
314-
parts of your application and mocking it in your tests.
310+
When it comes to translating a whole application, texts not only come from Twig
311+
templates or controllers but also from constants, services, entities, ...
315312

316-
Instead of translating a string at the time of creation, you can use a
317-
"translatable object", which is an instance of the
318-
:class:`Symfony\\Component\\Translation\\TranslatableMessage` class. This object stores
319-
all the information needed to fully translate its contents when needed::
313+
For example, how you could manage to display a title and a description for each enumeration
314+
cases in your templates::
320315

321-
use Symfony\Component\Translation\TranslatableMessage;
316+
.. code-block:: php
322317
323-
// the first argument is required and it's the original message
324-
$message = new TranslatableMessage('Symfony is great!');
325-
// the optional second argument defines the translation parameters and
326-
// the optional third argument is the translation domain
327-
$status = new TranslatableMessage('order.status', ['%status%' => $order->getStatus()], 'store');
318+
enum UserRoleEnum
319+
{
320+
case USER;
321+
case ADMIN;
322+
323+
public function getTitle(): string
324+
{
325+
return match ($this) {
326+
self::USER => 'User',
327+
self::ADMIN => 'Admin',
328+
};
329+
}
330+
331+
public function getDescription(): string
332+
{
333+
return match ($this) {
334+
self::USER => 'A regular user',
335+
self::ADMIN => 'A super-powered user',
336+
};
337+
}
338+
}
339+
340+
Then from Twig templates you merely call the methods ``roleAdmin.title``
341+
and ``roleAdmin.description`` and that's it. But, when dealing with translations,
342+
you could think of multiple approaches. One of them consists of returning the
343+
translation identifier. But this approach has significant drawbacks:
344+
345+
#. It's hard to pass along translation parameters and translation domain if needed.
346+
Like contextualizing a translation with plural, feminine or anything else.
347+
348+
#. The :ref:`extractor command <extracting-translation-contents>`
349+
will not be able to update translation files for you. And loose
350+
the ability to use the ``--clean`` parameter to remove unused
351+
translation identifiers.
328352

329-
Templates are now much simpler because you can pass translatable objects to the
330-
``trans`` filter:
353+
That's why you should use "translatable objects", which implements the
354+
:class:`Symfony\\Contracts\\Translation\\TranslatableInterface`.
355+
This object has the responsibility to store all the information needed to fully
356+
translate its contents.
357+
358+
Our updated ``UserRoleEnum::getTitle()`` and ``UserRoleEnum::getDescription()`` functions
359+
return a :class:`Symfony\\Component\\Translation\\TranslatableMessage` that will hold
360+
the translation identifier::
361+
362+
.. code-block:: php
363+
364+
public function getTitle(): TranslatableMessage
365+
{
366+
return match ($this) {
367+
self::USER => new TranslatableMessage('enums.user_role.user.title'),
368+
self::ADMIN => new TranslatableMessage('enums.user_role.admin.title'),
369+
};
370+
}
371+
372+
public function getDescription(): TranslatableMessage
373+
{
374+
return match ($this) {
375+
self::USER => new TranslatableMessage('enums.user_role.user.description'),
376+
self::ADMIN => new TranslatableMessage('enums.user_role.admin.description'),
377+
};
378+
}
379+
380+
The :ref:`extractor command <extracting-translation-contents>` is now able to keep track
381+
of translation identifiers passed as parameter to the constructor of
382+
:class:`Symfony\\Component\\Translation\\TranslatableMessage` objects.
383+
And in Twig templates a little change happen by adding the ``trans`` filter:
331384

332385
.. code-block:: html+twig
333386

334-
<h1>{{ message|trans }}</h1>
335-
<p>{{ status|trans }}</p>
387+
<h1>{{ roleAdmin.title|trans }}</h1>
388+
<p>{{ roleAdmin.description|trans }}</p>
336389

337390
.. tip::
338391

339392
The translation parameters can also be a :class:`Symfony\\Component\\Translation\\TranslatableMessage`.
340393

341394
.. tip::
342395

343-
There's also a :ref:`function called t() <reference-twig-function-t>`,
396+
There is a :ref:`function called t() <reference-twig-function-t>`,
344397
available both in Twig and PHP, as a shortcut to create translatable objects.
345398

346399
.. _translation-in-templates:
@@ -509,6 +562,8 @@ use for translation::
509562

510563
$translator->trans('Symfony is great', locale: 'fr_FR');
511564

565+
.. _extracting-translation-contents:
566+
512567
Extracting Translation Contents and Updating Catalogs Automatically
513568
-------------------------------------------------------------------
514569

0 commit comments

Comments
 (0)