Search code examples
phpsymfonyenumssymfony-translator

Symfony Translatable Enum


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

Solution

  • 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', locale: $locale),
                self::WEBHOOK   => $translator->trans('supplier.notify.webhook', locale: $locale),
                self::PUNCH_OUT => $translator->trans('supplier.notify.punch_out', locale: $locale),
            };
        }
    }
    

    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

    Edit: Added $locale to trans() function calls, thx @jared-farrish