Skip to content

Commit

Permalink
Support Symfony's TranslatableInterface in enum fields (#8212)
Browse files Browse the repository at this point in the history
  • Loading branch information
zyberspace authored Nov 13, 2024
1 parent f82eb21 commit bed2aaf
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 5 deletions.
58 changes: 53 additions & 5 deletions docs/reference/field_types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Fieldtype Description
``FieldDescriptionInterface::TYPE_DATETIME`` display a formatted date and time. Accepts the options ``format`` and ``timezone``
``FieldDescriptionInterface::TYPE_STRING`` display a text
``FieldDescriptionInterface::TYPE_EMAIL`` display a mailto link. Accepts the options ``as_string``, ``subject`` and ``body``
``FieldDescriptionInterface::TYPE_ENUM`` display the name of a backed enum
``FieldDescriptionInterface::TYPE_ENUM`` display an enum
``FieldDescriptionInterface::TYPE_TEXTAREA`` display a textarea
``FieldDescriptionInterface::TYPE_TRANS`` translate the value with a provided ``value_translation_domain`` and ``format`` (sprintf format) option
``FieldDescriptionInterface::TYPE_FLOAT`` display a number
Expand Down Expand Up @@ -199,13 +199,61 @@ The ``FieldDescriptionInterface::TYPE_CHOICE`` field type also supports multiple

You can use the following options:

====================================== ==============================================================
====================================== ========================================================================
Option Description
====================================== ==============================================================
====================================== ========================================================================
**use_value** Determines if the field must show the value or the case' name.
``false`` by default.
**enum_translation_domain** Translation domain.
====================================== ==============================================================

*Ignored if the enum implements Symfony's* ``TranslatableInterface`` *.*
**enum_translation_domain** | Translation domain. If set, the enum value or case' name will be send
to the translator.
| ``{{ value|trans({}, translation_domain) }}``

*Ignored if the enum implements Symfony's* ``TranslatableInterface`` *.*
====================================== ========================================================================

.. note::

If the enum implements Symfony's ``TranslatableInterface`` the options above will be ignored and the enum's
``trans()`` method will be used instead to display the enum.

This provides full compatibility with symfony's
`EnumType <https://symfony.com/doc/current/reference/forms/types/enum.html>`_ form type:

::

protected function configureListFields(ListMapper $list): void
{
$list
// Sonata Admin will select the `FieldDescriptionInterface::TYPE_ENUM`
// field type automatically. If the enum implements `TranslatableInterface`,
// the `trans()` method will be used to render its value.
->add('saluation')
;
}

protected function configureFormFields(FormMapper $form): void
{
$form
// Symfony's EnumType form field will automatically detect the usage of
// the `TranslatableInterface` and use the enum's `trans()` method to
// render the choice labels.
->add('salutation', EnumType::class, [
'class' => Salutation::class,
])
;
}

protected function configureShowFields(ShowMapper $show): void
{
$show
// Again, Sonata Admin will select the `FieldDescriptionInterface::TYPE_ENUM`
// field type automatically. If the enum implements `TranslatableInterface`,
// the `trans()` method will be used to render its value.
->add('salutation')
;
}

``FieldDescriptionInterface::TYPE_URL``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
3 changes: 3 additions & 0 deletions src/Resources/views/CRUD/display_enum.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ file that was distributed with this source code.
{%- apply spaceless %}
{% if value is null %}
&nbsp;
{% elseif value.trans is defined %}
{# Enum implements TranslatableInterface and therefore has direct control over how it should be displayed. #}
{{ value|trans }}
{% else %}
{% set value = use_value|default(false) ? value.value : value.name %}

Expand Down
35 changes: 35 additions & 0 deletions tests/Fixtures/Enum/TranslatableSuit.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Sonata\AdminBundle\Tests\Fixtures\Enum;

use Symfony\Contracts\Translation\TranslatableInterface;
use Symfony\Contracts\Translation\TranslatorInterface;

enum TranslatableSuit: string implements TranslatableInterface
{
case Hearts = 'hearts';
case Diamonds = 'diamonds';
case Clubs = 'clubs';
case Spades = 'spades';

#[\Override]
public function trans(TranslatorInterface $translator, ?string $locale = null): string
{
return $translator->trans(
id: 'enum.suit.'.$this->value,
domain: 'render-element-extension-test',
locale: $locale,
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
D: '[trans]D[/trans]'
Diamonds: '[trans]Diamonds[/trans]'
enum:
suit:
hearts: '[trans]enum.suit.hearts[/trans]'
diamonds: '[trans]enum.suit.diamonds[/trans]'
clubs: '[trans]enum.suit.clubs[/trans]'
spades: '[trans]enum.suit.spades[/trans]'
47 changes: 47 additions & 0 deletions tests/Twig/Extension/RenderElementExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use Sonata\AdminBundle\Templating\TemplateRegistryInterface;
use Sonata\AdminBundle\Tests\Fixtures\Entity\FooToString;
use Sonata\AdminBundle\Tests\Fixtures\Enum\Suit;
use Sonata\AdminBundle\Tests\Fixtures\Enum\TranslatableSuit;
use Sonata\AdminBundle\Tests\Fixtures\StubFilesystemLoader;
use Sonata\AdminBundle\Twig\Extension\RenderElementExtension;
use Sonata\AdminBundle\Twig\Extension\XEditableExtension;
Expand All @@ -36,6 +37,7 @@
use Symfony\Component\Routing\Loader\XmlFileLoader;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Translation\Loader\XliffFileLoader;
use Symfony\Component\Translation\Loader\YamlFileLoader;
use Symfony\Component\Translation\Translator;
use Symfony\Contracts\Translation\TranslatorInterface;
use Twig\Environment;
Expand Down Expand Up @@ -79,12 +81,19 @@ protected function setUp(): void
// translation extension
$translator = new Translator('en');
$translator->addLoader('xlf', new XliffFileLoader());
$translator->addLoader('yaml', new YamlFileLoader());
$translator->addResource(
'xlf',
\sprintf('%s/../../../src/Resources/translations/SonataAdminBundle.en.xliff', __DIR__),
'en',
'SonataAdminBundle'
);
$translator->addResource(
'yaml',
\sprintf('%s/../../Fixtures/Resources/translations/render-element-extension-test.en.yaml', __DIR__),
'en',
'render-element-extension-test',
);

$this->translator = $translator;

Expand Down Expand Up @@ -1551,6 +1560,44 @@ class="x-editable"
],
];

$elements[] = [
'<td class="sonata-ba-list-field sonata-ba-list-field-enum" objectId="12345"> [trans]Diamonds[/trans] </td>',
FieldDescriptionInterface::TYPE_ENUM,
Suit::Diamonds,
[
'use_value' => false,
'enum_translation_domain' => 'render-element-extension-test',
],
];

$elements[] = [
'<td class="sonata-ba-list-field sonata-ba-list-field-enum" objectId="12345"> [trans]D[/trans] </td>',
FieldDescriptionInterface::TYPE_ENUM,
Suit::Diamonds,
[
'use_value' => true,
'enum_translation_domain' => 'render-element-extension-test',
],
];

$elements[] = [
'<td class="sonata-ba-list-field sonata-ba-list-field-enum" objectId="12345"> [trans]enum.suit.hearts[/trans] </td>',
FieldDescriptionInterface::TYPE_ENUM,
TranslatableSuit::Hearts,
[],
];

$elements[] = [
'<td class="sonata-ba-list-field sonata-ba-list-field-enum" objectId="12345"> [trans]enum.suit.spades[/trans] </td>',
FieldDescriptionInterface::TYPE_ENUM,
TranslatableSuit::Spades,
[
// These values are ignored if the enum implements the TranslatableInterface
'use_value' => false,
'enum_translation_domain' => 'doesnt-exist',
],
];

return $elements;
}

Expand Down

0 comments on commit bed2aaf

Please sign in to comment.