ZF-2730: Zend_Validate_Abstract::setMessgage() does not overwrite the message from the translator.
Description
When I have set a translation object in Zend_Registry() to be used as default translator, sometime I will need to set a Custom Validator Error Message for a specific field.
But when we call Zend_Validate_Abstract::setMessgage() it does not overwrite the message from the translator.
To have it working I had to add a property in Zend_Validate_Abstract to keep track of the messages template which have been changed by Zend_Validate_Abstract::setMessgage();
And use it to see if the translator message should overwrite it, in Zend_Validate_Abstract:: _createMessage():
if (null !== ($translator = $this->getTranslator()) && !in_array($messageKey, $this->_messagesOverWriten)) {
if ($translator->isTranslated($messageKey)) {
$message = $translator->translate($messageKey);
}
}
Comments
Posted by Wil Sinclair (wil) on 2008-04-18T16:55:02.000+0000
Please evaluate and categorize/assign as necessary.
Posted by Thomas Weidner (thomas) on 2009-03-08T12:47:03.000+0000
That's correct behaviour. It could be described as:
First output Original message ->> but when set then the own message ->> and then when set the translation
Expect you have set own messages and also translation: A english user would get you own message and a french user would get the translation of the original message.
So, having both you would have to change the translation, otherwise your message is inconsistent.
Posted by Laurent Melmoux (laurent melmoux) on 2009-03-09T01:20:01.000+0000
What I want to say is that sometime you don't want to display the generic translation but a custom one. A use case will make it clearer :
For exemple with the NotEmpty Validator the original message is : * Value is empty, but a non-empty value is required Then my translation is : * le champs est requis But now let say I want so display something more specific, for exemple "the terme of use checkbox" and display * vous devez accepter les conditions d'utilisations du site
The in this specific use case custom message is usefull
Posted by Thomas Weidner (thomas) on 2009-06-26T11:45:42.000+0000
To have a "custom" translation you would have to extend the default translation instance and add your wished "custom" translations.
Then you have to give this "extended" translation instance to the validator you want to customize. It's not possible to do "chained" translations.
Posted by Thomas Weidner (thomas) on 2009-06-26T11:47:15.000+0000
Closing as won't fix due to the previous mentioned reasons.
Posted by Laurent Melmoux (laurent melmoux) on 2009-06-29T01:02:41.000+0000
I'm using Zend_Form and if I use your solution all the field will used the custom translation when I just need an one specific field to used it.
Also the behavior between native language and others language (with i18n translation object) is not the same : With Zen_Form and without i18n support you can use custom message (@see ZF manual > Zend_Form > 23.3.3.1. Custom Error Messages) but as long as you use i18n support by setting the default translator in Zend_Registry() this feature does not work anymore. IMHO it should be the same behaviors. Activating i18n shouldn't change as your application behave.
Posted by Thomas Weidner (thomas) on 2009-06-29T03:37:27.000+0000
As described before do custom translations by using setTranslator() which is a instance method of the abstract class.
Why should the custom translation be used for all elements? This is only the case when you use the same element multiple times.
The solution is to use different instances... one with translation-A and one with translation-B. When you want to use a "specific" field then also initiate it as specific field (seperate instance). Simple OOP behaviour.
And why should translation no longer work when setting a custom error message ? All errors are translated as long as you provide their key and their translation. When you don't want the custom error to be translated use a different key or a different translation.
This works for the default errors the same as for custom errors. There is no change in behaviour.
Posted by Laurent Melmoux (laurent melmoux) on 2009-06-29T06:22:18.000+0000
Thomas,
I probably don't express me very well so let's take an example to illustrate my issue :
Let's say I have a form with severals fields where I need to validate the string length. Most of the time the generic message for Zend_Validate_StringLength string too short is good enough, but I want a more explicit/friendly message for my username field.
Here how it works with no i18n setup :
So here, all is fine. But when I start to use the i18n feature it doesn't work the same :
It is not possible anymore to set an custom message .
Posted by Thomas Weidner (thomas) on 2009-06-29T06:38:04.000+0000
Reopened due to new reproducable example.
Posted by Thomas Weidner (thomas) on 2009-08-29T12:30:16.000+0000
After digging a little bit the reason is logical and also the solution is clear.
There are 2 possibilities to select from: 1.) A message will ALWAYS be translated. Default behaviour because otherwise you would have to call setMessage based on the users locale. Which means that you do the translation yourself.
2.) A message will ONLY be translated when setMessage is not set. This is problematic as you need to give different messages based on the users locale. In this case you do the translation yourself.
To select between this 2 different behaviours you have to handle your translation file differently...
Using the messageKey as source will force the first way. Using the messageContent as source will force the second way.
So for you this means to change your translation file as follows when you want to override translations and not the content of the templates:
Posted by Thomas Weidner (thomas) on 2009-08-29T12:34:43.000+0000
Closing as not an issue due the previous described reasons.
Posted by Laurent Melmoux (laurent melmoux) on 2009-09-14T09:19:58.000+0000
Thomas,
I'm still thinking that the correct behavior should be 2) A message will ONLY be translated when setMessage is not set. :-)
Right now if you use the validators in a i18n context (with an application wide locale within your registry) Zend_Validate::setMessage() is not working at all which means you have a behavior's change bettween the "default" and the localised context. And this is the same with Zend_Form_Element::addErrorMessage() and co.
To set custom message depending on the user local it is easy to do something $validator->setMessage($customMessages[$locale]['stringLengthTooShort']);
Also about your exemple, what should I do with $messageTemplates ?
Thanks.
Posted by Thomas Weidner (thomas) on 2009-09-14T10:57:49.000+0000
I still don't get the point about your problem of things which already work. $messageTemplates in my example is just a variable... name it $something or $dontknow... it's just a variable.
As described before translation does already work for case 2 when things are handled like described.
Posted by Laurent Melmoux (laurent melmoux) on 2009-09-15T02:38:41.000+0000
Pardon me if I'm not really clear.
I'm mostly using Zend_Validate with Zend_Form in an Automated CRUD and I'm creating them with a config object, then if I want a custom message I can simply do :
I really like this feature because I have no additional code to write and I don't really want to rewrite everything by hand only to add a custom message. :-(
To illustrate this here is 2 simples working examples :
With no translator, here the custom message is as expected :
But when I'm using a translator within the form my custom message is not display :
Posted by Thomas Weidner (thomas) on 2009-09-15T10:54:57.000+0000
There is no solution to this usecase:
You changed the messageTemplate of the validator and you added translation to the form. Now the form translates returned messages. How should the validator know what should be translated and what not? The validator has no connection to the form.
I see no way how this should be integrated.
Eighter change your translation as mentioned before or handle it different in this case. (You can disable translation on a element).