Skip to content
This repository was archived by the owner on Jan 30, 2020. It is now read-only.

Fix #28 - NotEmpty validation message cannot be localized #67

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions src/Input.php
Original file line number Diff line number Diff line change
Expand Up @@ -491,10 +491,17 @@ protected function injectNotEmptyValidator()
*/
protected function prepareRequiredValidationFailureMessage()
{
$notEmpty = new NotEmpty();
$templates = $notEmpty->getOption('messageTemplates');
$notEmpty = $this->getValidatorChain()->plugin(NotEmpty::class);
$templates = $notEmpty->getOption('messageTemplates');
$message = $templates[NotEmpty::IS_EMPTY];
$translator = $notEmpty->getTranslator();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Translator will always be empty here because you're directly instantiating it. Try pulling it from the validator chain instead, add that will likely use the plugin manager, and thus have access to the translator.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I beg to differ. This actually works in a real application.

The test reproduces the issue with the configuration suggested in http://framework.zend.com/manual/current/en/modules/zend.validator.messages.html#using-pre-translated-validation-messages

I also have a functional test in a real world application that reproduces it exactly in the same way.

The translator will not be empty even in new instances, as long as Zend\Validator\AbstractValidator::setDefaultTranslator() is used;
I tried avoding the static method usage, but in my experience the ValidatorPluginManager does not work consistently and I ended up with the translator not being correctly injected.

I can change the new statement with a plugin() invocation from the validator chain, but the static method call will still be necessary.


if ($translator) {
$message = $translator->translate($message, $notEmpty->getTranslatorTextDomain());
}

return [
NotEmpty::IS_EMPTY => $templates[NotEmpty::IS_EMPTY],
NotEmpty::IS_EMPTY => $message,
];
}
}
27 changes: 27 additions & 0 deletions test/InputTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
use Zend\Filter\FilterChain;
use Zend\InputFilter\Input;
use Zend\InputFilter\InputInterface;
use Zend\Validator\AbstractValidator;
use Zend\Validator\NotEmpty as NotEmptyValidator;
use Zend\Validator\Translator\TranslatorInterface;
use Zend\Validator\ValidatorChain;
use Zend\Validator\ValidatorInterface;

Expand All @@ -34,6 +36,11 @@ public function setUp()
$this->input = new Input('foo');
}

protected function tearDown()
{
AbstractValidator::setDefaultTranslator(null);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works in tests. But in an app, translators are directly injected via the plugin manager.

}

public function assertRequiredValidationErrorMessage(Input $input, $message = '')
{
$message = $message ?: 'Expected failure message for required input';
Expand Down Expand Up @@ -569,6 +576,26 @@ public function testInputMergeWithTargetValue()
$this->assertTrue($target->hasValue(), 'hasValue() value not match');
}

public function testNotEmptyMessageIsTranslated()
{
/** @var TranslatorInterface|MockObject $translator */
$translator = $this->getMock(TranslatorInterface::class);
AbstractValidator::setDefaultTranslator($translator);
$notEmpty = new NotEmptyValidator();

$translatedMessage = 'some translation';
$translator->expects($this->atLeastOnce())
->method('translate')
->with($notEmpty->getMessageTemplates()[NotEmptyValidator::IS_EMPTY])
->willReturn($translatedMessage)
;

$this->assertFalse($this->input->isValid());
$messages = $this->input->getMessages();
$this->assertArrayHasKey('isEmpty', $messages);
$this->assertSame($translatedMessage, $messages['isEmpty']);
}

public function fallbackValueVsIsValidProvider()
{
$required = true;
Expand Down