My supplier entity has enum property notifyType. Any idea how translate the enum this way?
{{ supplier.notifyType|trans }}
Unfortunately, use __toString method in Enum is not possible.
// error - Enum may not include __toString
public function __toString(): string
{
return 'supplier.notify.'.$this->name;
}
Then I just tried this:
use Symfony\Contracts\Translation\TranslatableInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
enum NotifyType: int implements TranslatableInterface
{
case EMAIL = 1;
case WEBHOOK = 2;
case PUNCH_OUT = 4;
public function trans(TranslatorInterface $translator, string $locale = null): string
{
return $translator->trans('supplier.notify.'.$this->name, locale: $locale);
}
}
But it's not possible pass translatable object to trans method. String only accepted.
$this->translator->trans(NotifyType::EMAIL); // error: must be of type string
CodePudding user response:
TL;DR : NotifyType::EMAIL->trans($this->translator)
Your Enum is correct and should works like that thanks to TranslatableInterface
implementation.
The only problem that I can find with that is the "auto discover" by translation:extract
symfony's command will not correctly works, since your translations are dynamics.
You should avoid using concatenated trans id
and use match
expression instead
(assuming you are in PHP >= 8.1
because of the enum problem) :
enum NotifyType: int implements TranslatableInterface
{
case EMAIL = 1;
case WEBHOOK = 2;
case PUNCH_OUT = 4;
public function trans(TranslatorInterface $translator, string $locale = null): string
{
return match ($this) {
self::EMAIL => $translator->trans('supplier.notify.email'),
self::WEBHOOK => $translator->trans('supplier.notify.webhook'),
self::PUNCH_OUT => $translator->trans('supplier.notify.punch_out'),
};
}
}
PHP usage
NotifyType::EMAIL->trans($this->translator)
Twig usage
{{ supplier.notifyType | trans }}
But definitely not like that :
{{ supplier.notifyType.value | trans }}
=> wrong{{ supplier.notifyType.name | trans }}
=> wrong
CodePudding user response:
The |trans
simply calls TranslatorExtension
's trans
function with the value it filters as a parameter. It only accepts the following types: string|\Stringable|TranslatableInterface|null
So then you have 2 (Edit: 3) solutions:
- Make your own
|trans
filter that overrides the one fromTranslatorExtension
(not ideal IMO) - Create your own filters specifically for Enums.
EDIT
There is a third and simpler solution: add a public function (for example getTransString
) in your Enum that returns 'supplier.notify.'. $this->name
and do this in twig: {{ supplier.notifyType.getTransString|trans }}
Here's a very simple example of the second solution that I tried and worked as expected:
class EnumTranslationService
{
public function __construct(private readonly TranslatorInterface $translator)
{
}
public function translateNotifyType(NotifyType $notifyType): string
{
return $this->translator->trans('supplier.notify.' . $notifyType->name);
}
}
AppExtension:
class AppExtension extends AbstractExtension
{
public function getFilters(): array
{
return [
new TwigFilter('transNotifyType', [EnumTranslationService::class, 'translateNotifyType'])
];
}
}
Twig:
{{ supplier.notifyType|transNotifyType }}