Validator plugin manager requires a `MvcTranslator` for translation - in any context
Bug Report
| Q | A |
|---|---|
| Version(s) | 2.33.0 |
Summary
The validator plugin manager tries to inject a translator with name MvcTranslator but outside of a laminas-mvc based application there is no MvcTranslator. This means it will fail in a Mezzio based application or any other context.
Current behavior
The validator plugin manager searches for a service with name MvcTranslator:
https://github.com/laminas/laminas-validator/blob/1d82b5c0ede9316263e14d11e9284dfb3130f158/src/ValidatorPluginManager.php#L590-L594
A registered service with name Laminas\I18n\Translator\TranslatorInterface::class will not be used and an alias can not be used because the AbstractValidator expected an implementation of Laminas\Validator\Translator\TranslatorInterface:
https://github.com/laminas/laminas-validator/blob/1d82b5c0ede9316263e14d11e9284dfb3130f158/src/Translator/TranslatorInterface.php#L5-L14
https://github.com/laminas/laminas-validator/blob/1d82b5c0ede9316263e14d11e9284dfb3130f158/src/AbstractValidator.php#L441
How to reproduce
// Service manager
$serviceManager = new Laminas\ServiceManager\ServiceManager();
$serviceManager->setService('config', []); // for translator factory
$serviceManager->configure(
(new Laminas\I18n\ConfigProvider())->getDependencyConfig()
);
// Translator
/** @var Laminas\I18n\Translator\TranslatorInterface $translator */
$translator = $serviceManager->get(
Laminas\I18n\Translator\TranslatorInterface::class
);
$translator->addTranslationFilePattern(
Laminas\I18n\Translator\Loader\PhpArray::class,
Laminas\I18n\Translator\Resources::getBasePath(),
Laminas\I18n\Translator\Resources::getPatternForValidator()
);
Locale::setDefault('de');
// Test
$validatorManager = new Laminas\Validator\ValidatorPluginManager(
$serviceManager
);
$validator = $validatorManager->get(Laminas\Validator\NotEmpty::class);
$validator->isValid('');
// Is not translated!
echo $validator->getMessages()['isEmpty']; // Value is required and can't be empty
A service must be added manually:
$serviceManager->setService(
'MvcTranslator',
new class ($translator)
implements Laminas\Validator\Translator\TranslatorInterface {
public function __construct(
private readonly Laminas\I18n\Translator\TranslatorInterface $translator
) {
}
public function translate(
$message,
$textDomain = 'default',
$locale = null
) {
return $this->translator->translate($message, $textDomain, $locale);
}
}
);
Or laminas-mvc-i18n must be used:
$serviceManager->configure(
(new Laminas\Mvc\I18n\ConfigProvider())->getDependencyConfig()
);
echo $validator->getMessages()['isEmpty']; // Es wird eine Eingabe benötigt
Expected behavior
Seamless integration should also be available outside of laminas-mvc based application without the user having to write anything manually or have to use an MVC package in a Mezzio application.
Yah, laminas-mvc actually does the whole wiring stuff. mainly due to the modulemanager as it provides those provider interfaces.
Not sure if @Xerkus wanted to drop modulemanager in some way, but these provider interfaces are actually the source of the problem. But I do not see issues with having additional provider features in MVC but as you say, the config key should be handled by each component on its own imho.
Related pull requests:
- https://github.com/zendframework/zendframework/pull/4391
- https://github.com/zendframework/zendframework/pull/4410