diff --git a/docs/case-sensitiveness.md b/docs/case-sensitiveness.md index 3ad39fbe9..f13227fdb 100644 --- a/docs/case-sensitiveness.md +++ b/docs/case-sensitiveness.md @@ -7,7 +7,7 @@ SPDX-FileContributor: Henrique Moody # Case Insensitive Validation -For most simple cases, you can use `v::call` wrappers to perform +For most simple cases, you can use `v::after` wrappers to perform case normalization before comparison. For strings: diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 000000000..aaa3d818c --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,19 @@ + + +# Configuration + +## Container configuration + +The `ContainerRegistry::createContainer()` method returns a [PHP-DI](https://php-di.org/) container. The definitions array follows the [PHP-DI definitions format](https://php-di.org/doc/php-definitions.html). + +If you prefer to use a different container, `ContainerRegistry::setContainer()` accepts any [PSR-11](https://www.php-fig.org/psr/psr-11/) compatible container: + +```php +use Respect\Validation\ContainerRegistry; + +ContainerRegistry::setContainer($yourPsr11Container); +``` diff --git a/docs/messages/placeholder-conversion.md b/docs/messages/placeholder-conversion.md index 68d2017e2..bb11fee4f 100644 --- a/docs/messages/placeholder-conversion.md +++ b/docs/messages/placeholder-conversion.md @@ -35,19 +35,7 @@ ContainerRegistry::setContainer( ); ``` -See [PlaceholderFormatter][] documentation for more information on creating custom modifiers. - -## Container configuration - -The `ContainerRegistry::createContainer()` method returns a [PHP-DI](https://php-di.org/) container. The definitions array follows the [PHP-DI definitions format](https://php-di.org/doc/php-definitions.html). - -If you prefer to use a different container, `ContainerRegistry::setContainer()` accepts any [PSR-11](https://www.php-fig.org/psr/psr-11/) compatible container: - -```php -use Respect\Validation\ContainerRegistry; - -ContainerRegistry::setContainer($yourPsr11Container); -``` +See [PlaceholderFormatter][] documentation for more information on creating custom modifiers and the [configuration](../configuration.md) section for more details on container setup. [PlaceholderFormatter]: https://github.com/Respect/StringFormatter/blob/main/docs/PlaceholderFormatter.md [Respect\StringFormatter]: https://github.com/Respect/StringFormatter diff --git a/docs/messages/translation.md b/docs/messages/translation.md index b75d56649..cea9bf819 100644 --- a/docs/messages/translation.md +++ b/docs/messages/translation.md @@ -1,39 +1,63 @@ # Message translation -Validation uses [symfony/translation](https://symfony.com/doc/current/translation.html) for message translation, providing interoperability with the Symfony ecosystem and other PHP projects. +Validation provides full translation capabilities, but they are not enabled by default nor +do we provide official translations for our messages other than English. -By default, validation messages are not translated. To enable translation, provide a `Symfony\Contracts\Translation\TranslatorInterface` implementation to `ContainerRegistry::createContainer()`: +Therefore, if you want to use it with translation, you must provide the translations yourself +using a compatible [translation contract](https://github.com/symfony/translation-contracts). + +Here's a quick setup using [symfony/translation](https://symfony.com/doc/current/translation.html): ```php use Respect\Validation\ContainerRegistry; +use Respect\Validation\Message\TemplateRegistry; +use Respect\Validation\Validators as vs; +use Symfony\Component\Translation\Loader\ArrayLoader; use Symfony\Component\Translation\Translator; use Symfony\Contracts\Translation\TranslatorInterface; -// Create your Symfony Translator instance -// See: https://symfony.com/doc/current/translation.html +$templates = new TemplateRegistry(); $translator = new Translator('pt_BR'); -// ... configure loaders and resources +$translator->addLoader('array', new ArrayLoader()); // Choose the loader of your preference +$translator->addResource('array', [ + // Reference standard template by class (StringVal, Intval, ...) and mode (default or inverted) + $templates->get(vs\IntVal::class)->default => '{{subject}} DEVE ser um inteiro.', + $templates->get(vs\IntVal::class)->inverted => '{{subject}} NÃO DEVE ser um inteiro.', + + // Reference alternative templates by their id (second argument) + $templates->get(vs\AllOf::class, vs\AllOf::TEMPLATE_ALL)->default => 'Todas as regras requeridas DEVEM passar para {{subject}}', + + // You can also just translate messages directly + '{{subject}} must be a URL' => '{{subject}} DEVE ser uma URL' +]); $container = ContainerRegistry::createContainer([ TranslatorInterface::class => $translator, + TemplateRegistry::class => $templates ]); - ContainerRegistry::setContainer($container); ``` -After setting up the container, all messages produced by Validation will your translator. +You only need to do this once before you perform any validation, and messages will start +being produced with your translation setup. If you're using a framework, you can configure +this in the service provider of your choice. + +Check out the documentation for each validator for its available modes and existing messages +and the [configuration](../configuration.md) section. ## Translating dynamic values Validation messages contain placeholders like `{{subject}}` and `{{minValue}}` that are replaced with actual values. Some of these values may also need translation. -Use the `|trans` modifier to translate parameter values: +You will encounter several messages with `|trans` in different validators. Those enable the +translation of such dynamic values automatically. ```php // Message template @@ -44,6 +68,8 @@ Use the `|trans` modifier to translate parameter values: 'Palestine' => 'Palestina', ``` +The `|trans` modifier will also work with custom templates defined by [Templated](../validators/Templated.md) or provided by [`assert`](../handling-exceptions.md). + ## Translating lists When using validators that display lists of values, use the `|list:or` or `|list:and` modifiers. These modifiers also require translating the conjunctions: @@ -63,15 +89,3 @@ When using validators that display lists of values, use the `|list:or` or `|list '{{haystack|list:and}} are the only possible names' => '{{haystack|list:and}} são os únicos nomes possíveis', 'and' => 'e', ``` - -## Container configuration - -The `ContainerRegistry::createContainer()` method returns a [PHP-DI](https://php-di.org/) container. The definitions array follows the [PHP-DI definitions format](https://php-di.org/doc/php-definitions.html). - -If you prefer to use a different container, `ContainerRegistry::setContainer()` accepts any [PSR-11](https://www.php-fig.org/psr/psr-11/) compatible container: - -```php -use Respect\Validation\ContainerRegistry; - -ContainerRegistry::setContainer($yourPsr11Container); -``` diff --git a/docs/migrating-from-v2-to-v3.md b/docs/migrating-from-v2-to-v3.md index ec71b90cb..82cf2e368 100644 --- a/docs/migrating-from-v2-to-v3.md +++ b/docs/migrating-from-v2-to-v3.md @@ -932,6 +932,13 @@ v::email()->assert( ); ``` +### Translation + +The project now uses Symfony [translation contracts](https://github.com/symfony/translation-contracts) +instead of a custom callback. + +See [messages/translation.md](messages/translation.md) for more info. + ### Placeholder pipes Customize how values are rendered in templates using pipes: diff --git a/src/ContainerRegistry.php b/src/ContainerRegistry.php index 4e34ac73d..c2dd2bb8b 100644 --- a/src/ContainerRegistry.php +++ b/src/ContainerRegistry.php @@ -38,6 +38,7 @@ use Respect\Validation\Message\Parameters\PathHandler; use Respect\Validation\Message\Parameters\ResultHandler; use Respect\Validation\Message\Renderer; +use Respect\Validation\Message\TemplateRegistry; use Respect\Validation\Transformers\Prefix; use Respect\Validation\Transformers\Transformer; use Symfony\Contracts\Translation\TranslatorInterface; @@ -56,7 +57,8 @@ public static function createContainer(array $definitions = []): Container return new Container($definitions + [ PhoneNumberUtil::class => factory(static fn() => PhoneNumberUtil::getInstance()), Transformer::class => create(Prefix::class), - TemplateResolver::class => create(TemplateResolver::class), + TemplateRegistry::class => create(TemplateRegistry::class), + TemplateResolver::class => autowire(TemplateResolver::class), TranslatorInterface::class => autowire(BypassTranslator::class), Renderer::class => autowire(InterpolationRenderer::class), ResultFilter::class => create(OnlyFailedChildrenResultFilter::class), diff --git a/src/Message/Formatter/TemplateResolver.php b/src/Message/Formatter/TemplateResolver.php index ebedc9270..373f33e8e 100644 --- a/src/Message/Formatter/TemplateResolver.php +++ b/src/Message/Formatter/TemplateResolver.php @@ -11,11 +11,9 @@ namespace Respect\Validation\Message\Formatter; -use ReflectionClass; -use Respect\Validation\Message\Template; +use Respect\Validation\Message\TemplateRegistry; use Respect\Validation\Path; use Respect\Validation\Result; -use Respect\Validation\Validator; use function array_reduce; use function array_reverse; @@ -24,8 +22,10 @@ final class TemplateResolver { - /** @var array> */ - private array $templates = []; + public function __construct( + private TemplateRegistry $templateRegistry, + ) { + } /** @param array $templates */ public function getGivenTemplate(Result $result, array $templates): string|null @@ -53,7 +53,7 @@ public function getGivenTemplate(Result $result, array $templates): string|null public function getValidatorTemplate(Result $result): string { - foreach ($this->extractTemplates($result->validator) as $template) { + foreach ($this->templateRegistry->getTemplates($result->validator::class) as $template) { if ($template->id !== $result->template) { continue; } @@ -68,19 +68,6 @@ public function getValidatorTemplate(Result $result): string return $result->template; } - /** @return array