sonata-project / SonataAdminBundle

The missing Symfony Admin Generator
https://docs.sonata-project.org/projects/SonataAdminBundle
MIT License
2.11k stars 1.26k forks source link

Support Symfony's `TranslatableInterface` in enum fields #8212

Closed zyberspace closed 1 week ago

zyberspace commented 1 month ago

Support Symfony's TranslatableInterface in enum fields

Fixes the translation of enums implementing Symfony's TranslatableInterface.

Right now there is a discrepancy between how the Symfony EnumType form type translates enums and how Sonata Admin translates them. The EnumType uses the enum case's name by default for the choice labels. If you need anything else, your enum has to implement the TranslatableInterface and a trans() method like in the third example on the docs page: https://symfony.com/doc/current/reference/forms/types/enum.html#example-usage

However the FieldDescriptionInterface::TYPE_ENUM field type completely ignores this and instead implements the options use_value and enum_translation_domain, which severely limits how the enum can be translated. I for example often use the format enum.[ENUM_SHORT_NAME].[ENUM_VALUE] which is not possible with the current implementation.

With this PR, the FieldDescriptionInterface::TYPE_ENUM field type will use the enum's trans() method if available to translate the enum and therefore use the same logic, Symfony's EnumType uses.

With this PR, using enums is as easy as:

enum Salutation implements TranslatableInterface
{
    /* case ... = ...; */

    public function trans(TranslatorInterface $translator, ?string $locale = null): string
    {
        // Implement your custom enum translation logic here
        return $translator->trans('enum.saluation.'.$this->value, locale: $locale);
    }
}
protected function configureListFields(ListMapper $list): void
{
    $list
        ->add('saluation')
    ;
}

protected function configureFormFields(FormMapper $form): void
{
    $form
        ->add('salutation', EnumType::class, [
            'class' => Salutation::class,
        ])
    ;
}

protected function configureShowFields(ShowMapper $show): void
{
    $show
        ->add('salutation')
    ;
}

I also added tests for the previous translation method, as there were none.

I am targeting the 4.x branch, because people using enums with the TranslatableInterface currently can not use the enum field type anyway, as it would use the wrong translation, so there should be no backwards compatible issues here.

Changelog

### Changed
- Enums implementing Symfony's `TranslatableInterface` are now correctly translated by the `FieldDescriptionInterface::TYPE_ENUM` field type
virtualize commented 1 week ago

@VincentLanglet could you please have a look at this PR?

zyberspace commented 1 week ago

Will rebase as soon as #8215 is merged. Should fix the checks.

VincentLanglet commented 1 week ago

Hi, it can be rebased

zyberspace commented 1 week ago

@VincentLanglet Done. And thanks for fixing the build!

Can you approve the workflow a second time? Thanks!

VincentLanglet commented 1 week ago

Thanks @zyberspace