Symfony: translate Assert custom messages from entities

Thomas Dutrion
2 min readOct 2, 2022

If you follow Symfony’s documentation, you will at some point set constraints on your entities. And quite often, you will have to create custom messages to explain the issue a little further to your end-user… Lucky for you, the documentation also explains it: How to Translate Validation Constraint Messages.

So what is the story here? You’ve written the assert annotation on your entity, you then run bin/console translation:extract en --dump-messages, but surprisingly you can’t see your custom message, so let’s get down to the bottom of it.

From Extracting Translation Contents and Updating Catalogs Automatically, we can read the following:

The translation:extract command looks for missing translations in:

Templates stored in the templates/ directory (or any other directory defined in the twig.default_path and twig.paths config options);

Any PHP file/class that injects or autowires the translator service and makes calls to the trans() method.

Any PHP file/class stored in the src/ directory that creates Translations using the constructor or the t() method or calls the trans() method.

So then, nothing from this page can find your custom message… What a shame. Can we make this work?

Sure we can! We now know that t() can triggers the translation, and that we can use PHP code in annotations, so let’s try it!

#[Assert\NotBlank(
message: t('my.translation.key', [], 'validators')
)]

And that’s it, done! Running bin/console translation:extract en --dump-messages, you will now be able to find your key under Messages extracted for domain "validators" (xxx messages).

Right, it works, so now the question is: SHOULD WE USE THIS TRICK?

My honest answer would probably be no, but then I would not recommend using annotations or attributes to define constraints either, as it will couple your entity which is domain code to your framework.

If you’re fine with coupling with symfony/validation, that’s one thing, but please consider that t() is part of Twig, so you’re extending the coupling way further… which might not be a problem for you depending on your project.

Whatever you choose, you’re right, you just need to know what you’re doing, and hopefully I have helped you get a better understanding on this specific topic. Please feel free to discuss this solution in the comments, and tell me how you’re dealing with it personally and with your team(s) if you have any!

--

--

Freelance PHP Developer / Web architect, @scotlandphp organiser | Zend Certified Architect