Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine
This tutorial has a new version, check it out!

Changing Validation Messages

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $12.00

Check out the web debug toolbar: it's highlighted with the number of validation errors, which is pretty cool. It's even cooler because we can see where those are coming from.

The default message for the NotBlank constraint is obviously

This value should not be blank

We can easily change this by passing a message option to the annotation. But wait a second: we're going to use NotBlank a lot. Is there a way to customize the default message across the whole system?

Yea! All of these strings are passed through Symfony's translator. And we can take advantage of that to customize this message, even in English.

Enabling the Translator

First, in case you don't already have it enabled, open up app/config/config.yml. Activate the translator service by uncommenting out the translator key under framework:

... lines 1 - 11
framework:
... line 13
translator: { fallbacks: ["%locale%"] }
... lines 15 - 74

Refresh this page and watch the web debug toolbar. Suddenly, there's an extra icon that's coming from the translator. It's reporting that there are ten missing messages. In other words, we are apparently already sending ten messages through the translator that are missing translation strings.

This is because every form field and all validation errors are automatically sent through the translator. Nothing looks weird, because those strings are already English, so it's not really a problem that they aren't translated.

Changing Validation Messages

But, if you want to customize this message, copy it. And, notice, the domain is validators: that's basically a translation "category", and it's important for what we do next.

We don't have any translation files yet, so create a new directory called translations in app/Resources. Inside, add a new file: validators.en.yml. This is validators because the message is being translated in that domain.

Inside, paste the string and set it to "Hi! Please enter something for this field.":

"This value should not be blank.": Hi! Please enter *something* for this field :)

And that's it! Go back and refresh! Oh no, it didn't work! Well, I kind of expected that. Find your terminal, open a new tab, and run:

./bin/console cache:clear

You almost never need to worry about clearing your cache while developing but very occasionally, you'll find a quirk in Symfony that needs this. Sometimes, when you add a new translation file, this happens.

Let's refresh again. There it is!

So yay validation! There's one more constraint I want you to see: Callback. This is your Swiss army knife: it allows you to write whatever custom validation logic you want inside a method. There, you can create different validation errors and map them to any field.

Leave a comment!

7
Login or Register to join the conversation
Mike P. Avatar
Mike P. Avatar Mike P. | posted 5 years ago | edited

Is there a best practice for translated validation messages?

Because in this video you show us to use the string directly:
"This value should not be blank.": Hi! Please enter something for this field :)

`In another video someone recommends using:
user:
email:

  unique: "It looks like your already have an account!"

`
(and set the validation message as user.email.unique)

Does this differ in terms of performance / best practice?

Reply

Hey Mike P.

I'm not sure if using keys impacts performance, but it is recommended to use them, they are short, descriptive, and hard to change.
You can dive deeper about internationalization best practices here: http://symfony.com/doc/curr...
Also symfony has a dedicated section for best practices: http://symfony.com/doc/curr...

I hope it helps you :)

1 Reply
Mike P. Avatar
Mike P. Avatar Mike P. | posted 5 years ago

Is it possible to combine the message field with the translation file?
Example:

I want the following error message: "Email cannot be longer than than {{ limit }} characters"
Of course this constraint message is the same for a lot of different fields, just the name "Email" changes.
I want:

Entity:
* @Assert\Length(max=100, maxMessage="Email length.max")

Validators:
length.max: cannot be longer than than {{ limit }} characters

Wanted Result:
Email cannot be longer than than {{ limit }} characters

But this doesn't seem to work.
A TWIG Variable like {{ label }} doesn't seem to exist. (Idea was to add length.max: {{ label }} cannot be longer than than {{ limit }} characters)
Do I really have to generate a translation row inside the validation file for every single label field?

Reply

Hey Mike,

That's a good question about customization but a a little overhead. Actually, you don't need field labels in translation messages because errors tied to its fields. Therefore, considering this fact, you already have a context about what exactly field is invalid. So, if you have an HTML layout with a good CSS styles - it should look fine.

Anyway, you *can* override that error message, and you *can* use custom variables in it, so your overwritten message should look like:
{{ label }} cannot be longer than than {{ limit }} characters.

But you need to inject that {{ label }} variable manually in place where this message is translated, for that you need to override a Symfony form template for this field with your own, i.e. create your custom Twig form theme. Here's a bit more information how to create and use your custom Twig form: https://knpuniversity.com/s...

Cheers!

Reply
Mike P. Avatar

Very profound answer, thank you very much Victor!

Reply
Shaun T. Avatar
Shaun T. Avatar Shaun T. | posted 5 years ago

Hey guys, I have a weird error, the Symfony profiler toolbar is showing on list page, but not on the new genus page, any idea how I can track this down?!

Reply

Hey Shaun T.

Could you show me your controller's code ?
I believe you are missing the head/body tags on your page, does your controller extends from Symfony's base controller ?

Cheers!

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": ">=5.5.9",
        "symfony/symfony": "3.1.*", // v3.1.4
        "doctrine/orm": "^2.5", // v2.7.2
        "doctrine/doctrine-bundle": "^1.6", // 1.6.4
        "doctrine/doctrine-cache-bundle": "^1.2", // 1.3.0
        "symfony/swiftmailer-bundle": "^2.3", // v2.3.11
        "symfony/monolog-bundle": "^2.8", // 2.11.1
        "symfony/polyfill-apcu": "^1.0", // v1.2.0
        "sensio/distribution-bundle": "^5.0", // v5.0.22
        "sensio/framework-extra-bundle": "^3.0.2", // v3.0.16
        "incenteev/composer-parameter-handler": "^2.0", // v2.1.2
        "composer/package-versions-deprecated": "^1.11", // 1.11.99
        "knplabs/knp-markdown-bundle": "^1.4", // 1.4.2
        "doctrine/doctrine-migrations-bundle": "^1.1" // 1.1.1
    },
    "require-dev": {
        "sensio/generator-bundle": "^3.0", // v3.0.7
        "symfony/phpunit-bridge": "^3.0", // v3.1.3
        "nelmio/alice": "^2.1", // 2.1.4
        "doctrine/doctrine-fixtures-bundle": "^2.3" // 2.3.0
    }
}
userVoice