Skip to content

Translation - Cannot extract some constraint attribute messages #49397

@nfragnet

Description

@nfragnet

Symfony version(s) affected

6.2.6

Description

Hi,

When running bin/console translation:extract --domain=validators en on my local env most of the messages stored in constraints attributes are not extracted.

Some exceptions remains for Assert/Email or Assert/Expression for example.
Those ones are extracted. On the other hand a simple GreaterThan or Length with message, or minMessage/maxMessage option are not.

How to reproduce

#[Assert\Length(
    min: 1,
    max: 25,
    minMessage: 'transkey_min', // Those two are not extracted
    maxMessage: 'transkey_max', //
)]
#[Assert\Expression(
    expression: '1 === 1', 
    message: 'transkey_expression', // This one is extracted
)]
private string $foo;

Then run bin/console translation:extract --domain=validators en .

  • transkey_expression is extracted
  • transkey_min & transkey_max are not

Possible Solution

No response

Additional Context

Expected behaviour => https://symfony.com/doc/current/translation.html#extracting-translation-contents-and-updating-catalogs-automatically

The translation:extract command looks for missing translations in:

  • ...
  • Any PHP file/class stored in the src/ directory that uses Constraints Attributes with *message named argument(s).

I checked the class Symfony\Component\Translation\DependencyInjection\TranslatorPass and noticed the way constraint class names are injected into ConstraintVisitor service.

$constraintVisitorDefinition = $container->getDefinition('translation.extractor.visitor.constraint');
$constraintClassNames = [];

foreach ($container->findTaggedServiceIds('validator.constraint_validator', true) as $id => $attributes) {
    $serviceDefinition = $container->getDefinition($id);
    // Resolve constraint validator FQCN even if defined as %foo.validator.class% parameter
    $className = $container->getParameterBag()->resolveValue($serviceDefinition->getClass());
    // Extraction of the constraint class name from the Constraint Validator FQCN
    $constraintClassNames[] = str_replace('Validator', '', substr(strrchr($className, '\\'), 1));
}

$constraintVisitorDefinition->setArgument(0, $constraintClassNames);

By reading this I expect all symfony validator constraints to be in the $constraintClassNames but it's not the case. Only those EXPLICITLY tagged (and not the autoconfigured one) are present.

By adding manually and additional entry in $constraintClassNames array, I've been able to extract messages from this constraint.

The issue is IMO that $container->findTaggedServiceIds('validator.constraint_validator', true) does not return all the validators.

The result have been confirmed by executing bin/console debug:container --tag=validator.constraint_validator. It listed all my custom validators and the one having an explicit service definition from Symfony.

I have not been able to go further and now need help.
I'd be glad to help and provide a PR :)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions