Skip to content

[Validator] Integrated the Translator in the Validator component #6137

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Jan 9, 2013

Conversation

webmozart
Copy link
Contributor

Bug fix: no
Feature addition: no
Backwards compatibility break: yes
Symfony2 tests pass: yes
Fixes the following tickets: #5844, #6117
Todo: -
License of the code: MIT
Documentation PR: -

This PR allows to replace the default message substitution strategy in the validator (strtr()) by passing an implementation of Symfony\Component\Translation\TranslatorInterface. The motivation for this are both #5844 and the need to replace the translation strategy in Drupal's integration of the Validator.

In the stand-alone usage of the validator, both the translator and the default translation domain can now be passed to ValidatorBuilderInterface:

$validator = Validation::createValidatorBuilder()
    ->setTranslator(new MyTranslator())
    ->setTranslationDomain('validators')
    ->getValidator();

References:

$id,
array $parameters = array(),
$domain = null,
$locale = null
Copy link
Member

Choose a reason for hiding this comment

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

we are not using multiline signatures in the codebase

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

@Tobion
Copy link
Contributor

Tobion commented Nov 28, 2012

no BC break? Looking at ValidatorBuilderInterface there is definitely one.

@webmozart
Copy link
Contributor Author

ValidatorBuilderInterface is not part of the stable API. You are not supposed to implement this interface.

@Tobion
Copy link
Contributor

Tobion commented Nov 28, 2012

We're not only documenting bc breaks for stable API, otherwise we could remove 90% of the upgrade file since few methods are tagged with API.
An interface that nobody should implement?

@webmozart
Copy link
Contributor Author

The question is what to consider a BC break. Something will always break for someone. Should we consequently mark everything as BC break? I don't think so.

For example, since 2.1, you are supposed to use Validation::createValidator*() for creating a validator. Because of that, I won't consider changing the constructor signature of Validator a BC break anymore from 2.1 on.

The same for the unstable interfaces. These are currently meant to be used only, that is, type hint against them and call their methods. But we don't guarantee that we won't add methods to them.

@Tobion
Copy link
Contributor

Tobion commented Nov 28, 2012

I agree that almost any change could be considered a BC break. So we probably need to better define what a BC break is and what not. Otherwise Symfony will stop evolving after 2.3 because from then on Fabien wanted to prevent BC breaks which is almost impossible in a strict definition of bc break.

@fabpot
Copy link
Member

fabpot commented Nov 28, 2012

BC breaks should always be documented, and we guarantee BC only for things tagged with @api. I'm going to update the docs to make things clearer.

@webmozart
Copy link
Contributor Author

@fabpot I documented these changes now in the CHANGELOG: af99ebb1206ac92889b7193ba1ecc12bf2617e85

Are we sure we want to document all BC breaks from now on, even in non-@api code? This could rather scare people looking at our changelogs (lots of BC BREAKS there).

@fago
Copy link
Contributor

fago commented Nov 28, 2012

Unfortunately, it turns out the symfony translator interface does not mach the Drupal translation system as well as we initally thought, see http://drupal.org/node/1852106. Given that, this would integrating the validator component into Drupal even harder, because it introduces the dependency on the (unwanted) translation component. :(

@stof
Copy link
Member

stof commented Nov 28, 2012

If this does not help Drupal anyway, maybe #5844 is a better way to manage translations for people using the validator outside forms ?
and the Drupal guys would simply follow a similar approach, but based on their own translator instead of the symfony one.

@fago
Copy link
Contributor

fago commented Nov 28, 2012

Yeah. The only problem I see with the approach of #5844 is that after validation only the translated messages are available. We'd need to have access to the untranslated messages also.

@fago
Copy link
Contributor

fago commented Nov 29, 2012

As our translation system handles translating pluralized messages differently, the current ExecutionContextInterface::addViolation() method poses a problem also. We need to pass on - both the single and plural - message, as the message gets chosen during translation, see http://api.drupal.org/api/drupal/core!includes!common.inc/function/format_plural/8
So maybe, we could allow adding an already created ConstraintViolation object also? Then, we could implement a "PluralConstraintViolation" class that takes both message templates.

@webmozart
Copy link
Contributor Author

I updated this PR to support pluralized messages by default in the validator. This should solve the problem of the Drupal guys, because their implementation of TranslatorInterface::transChoice($id, $number, ...) can now simply split the $id by pipes (|) and pass the parts to their own format_plural($count, $singular, $plural, ...) function.

For us, it breaks BC because translation catalog sources had to be adapted.

@fabpot
Copy link
Member

fabpot commented Dec 3, 2012

Most of the XLF files are broken (the end is missing now).

IIUC, we now have a hard dependency on the Translation component, which is something we wanted to avoid.

@fabpot
Copy link
Member

fabpot commented Dec 3, 2012

Oops, clicked on the "comment" button too fast.

So, the dependency is hard (you need to install the dep) but light as we only rely on the translation interface from the component (when using the default translator). It looks acceptable to me, especially because we now use Composer to manage dependencies.

@webmozart
Copy link
Contributor Author

@fabpot Thanks for the hint. Going to fix this.

@webmozart
Copy link
Contributor Author

@fabpot Fixed.

/**
* {@inheritdoc}
*/
public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = 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 implementation is totally wrong. The string format for a plural message can be more complex than just foo|bar, you can have ranges, several plurals, ...

That's also why we have what we have right now. If you want to use translation, you need the translation component.
.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's also why we have what we have right now. If you want to use translation, you need the translation component.

This doesn't change. The Default translator does not support message catalogs or any of this. It supports a simple subset of the Translation component that lets the Validator work without that component, unless you need actual translations or more complicated plural messages (which we don't have in the Validator core).

Copy link
Member

Choose a reason for hiding this comment

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

So, if I get you correctly, we are reinventing a way to "fake" plural messages? The source message has a convention where we have 2 messages separated by a pipe? If that's the case, then it should be documented.

Copy link
Member

Choose a reason for hiding this comment

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

And for the record, you cannot say that we don't have complicated plural messages in the core validators, as any message needing plural is complicated in some languages (a message is never complex by itself, but the translation for some languages are complex).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

you cannot say that we don't have complicated plural messages in the core validators, as any message needing plural is complicated in some languages

DefaultTranslator does not support translation :) Just interpolation, i.e. parsing of parameters into messages. It does not have to care about what translations look like.

So, if I get you correctly, we are reinventing a way to "fake" plural messages?

To make a long answer short, yes. People can use intervals in their constraint classes, but then these constraints are bound to the Translation component and not compatible for example with Drupal's translation mechanism.

@webmozart
Copy link
Contributor Author

Is there anything missing for this PR to be merged?

*/
public function __construct($queryBuilder, $manager = null, $class = null)
public function __construct(QueryBuilder $queryBuilder)
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like an unrelated change??

fabpot added a commit that referenced this pull request Jan 9, 2013
This PR was merged into the master branch.

Commits
-------

586a16e [Validator] Changed DefaultTranslator::getLocale() to always return 'en'
58bfd60 [Validator] Improved the inline documentation of DefaultTranslator
cd662cc [Validator] Added ExceptionInterface, BadMethodCallException and InvalidArgumentException
e00e5ec [Validator] Fixed failing test
cc0df0a [Validator] Changed validator to support pluralized messages by default
56d61eb [Form][Validator] Added BC breaks in unstable code to the CHANGELOG
1e34e91 [Form] Added upgrade instructions to the UPGRADE file
b94a256 [DoctrineBridge] Adapted DoctrineBridge to translator integration in the validator
c96a051 [FrameworkBundle] Adapted FrameworkBundle to translator integration in the validator
92a3b27 [TwigBridge] Adapted TwigBridge to translator integration in the validator
e7eb5b0 [Form] Adapted Form component to translator integration in the validator
46f751c [Validator] Extracted message interpolation logic of ConstraintViolation and used the Translation component for that

Discussion
----------

[Validator] Integrated the Translator in the Validator component

Bug fix: no
Feature addition: no
Backwards compatibility break: yes
Symfony2 tests pass: yes
Fixes the following tickets: #5844, #6117
Todo: -
License of the code: MIT
Documentation PR: -

This PR allows to replace the default message substitution strategy in the validator (`strtr()`) by passing an implementation of `Symfony\Component\Translation\TranslatorInterface`. The motivation for this are both #5844 and the need to replace the translation strategy in Drupal's integration of the Validator.

In the stand-alone usage of the validator, both the translator and the default translation domain can now be passed to `ValidatorBuilderInterface`:

```php
$validator = Validation::createValidatorBuilder()
    ->setTranslator(new MyTranslator())
    ->setTranslationDomain('validators')
    ->getValidator();
```

References:

* #5844
* #6117
* #6129
* [Add a validation framework to Drupal 8](http://drupal.org/node/1845546)
* [Add the symfony validator component to core despite Symfony potentially releasing BC-breaking updates after 2.3.](http://drupal.org/node/1849564)

---------------------------------------------------------------------------

by Tobion at 2012-11-28T08:53:25Z

no BC break? Looking at ValidatorBuilderInterface there is definitely one.

---------------------------------------------------------------------------

by bschussek at 2012-11-28T08:55:01Z

ValidatorBuilderInterface is not part of the stable API. You are not supposed to implement this interface.

---------------------------------------------------------------------------

by Tobion at 2012-11-28T09:01:07Z

We're not only documenting bc breaks for stable API, otherwise we could remove 90% of the upgrade file since few methods are tagged with API.
An interface that nobody should implement?

---------------------------------------------------------------------------

by bschussek at 2012-11-28T09:30:02Z

The question is what to consider a BC break. Something will always break for someone. Should we consequently mark everything as BC break? I don't think so.

For example, since 2.1, you are supposed to use `Validation::createValidator*()` for creating a validator. Because of that, I won't consider changing the constructor signature of `Validator` a BC break anymore from 2.1 on.

The same for the unstable interfaces. These are currently meant to be used only, that is, type hint against them and call their methods. But we don't guarantee that we won't add methods to them.

---------------------------------------------------------------------------

by Tobion at 2012-11-28T09:38:19Z

I agree that almost any change could be considered a BC break. So we probably need to better define what a BC break is and what not. Otherwise Symfony will stop evolving after 2.3 because from then on Fabien wanted to prevent BC breaks which is almost impossible in a strict definition of bc break.

---------------------------------------------------------------------------

by fabpot at 2012-11-28T11:37:22Z

BC breaks should always be documented, and we guarantee BC only for things tagged with @api. I'm going to update the docs to make things clearer.

---------------------------------------------------------------------------

by bschussek at 2012-11-28T13:09:57Z

@fabpot I documented these changes now in the CHANGELOG: af99ebb1206ac92889b7193ba1ecc12bf2617e85

Are we sure we want to document *all* BC breaks from now on, even in non-@api code? This could rather scare people looking at our changelogs (lots of BC BREAKS there).

---------------------------------------------------------------------------

by fago at 2012-11-28T17:29:58Z

Unfortunately, it turns out the symfony translator interface does not mach the Drupal translation system as well as we initally thought, see http://drupal.org/node/1852106. Given that, this would integrating the validator component into Drupal even harder, because it introduces the dependency on the (unwanted) translation component. :(

---------------------------------------------------------------------------

by stof at 2012-11-28T18:19:36Z

If this does not help Drupal anyway, maybe #5844 is a better way to manage translations for people using the validator outside forms ?
and the Drupal guys would simply follow a similar approach, but based on their own translator instead of the symfony one.

---------------------------------------------------------------------------

by fago at 2012-11-28T18:50:12Z

Yeah. The only problem I see with the approach of #5844 is that *after* validation only the translated messages are available. We'd need to have access to the untranslated messages also.

---------------------------------------------------------------------------

by fago at 2012-11-29T09:49:47Z

As our translation system handles translating pluralized messages differently, the current ExecutionContextInterface::addViolation() method poses a problem also. We need to pass on - both the single and plural - message, as the message gets chosen during translation, see http://api.drupal.org/api/drupal/core!includes!common.inc/function/format_plural/8
So maybe, we could allow adding an already created ConstraintViolation object also? Then, we could implement a "PluralConstraintViolation" class that takes both message templates.

---------------------------------------------------------------------------

by bschussek at 2012-12-03T15:52:36Z

I updated this PR to support pluralized messages by default in the validator. This should solve the problem of the Drupal guys, because their implementation of `TranslatorInterface::transChoice($id, $number, ...)` can now simply split the $id by pipes (`|`) and pass the parts to their own `format_plural($count, $singular, $plural, ...)` function.

For us, it breaks BC because translation catalog sources had to be adapted.

---------------------------------------------------------------------------

by fabpot at 2012-12-03T16:25:52Z

Most of the XLF files are broken (the end is missing now).

IIUC, we now have a hard dependency on the Translation component, which is something we wanted to avoid.

---------------------------------------------------------------------------

by fabpot at 2012-12-03T16:27:56Z

Oops, clicked on the "comment" button too fast.

So, the dependency is hard (you need to install the dep) but light as we only rely on the translation interface from the component (when using the default translator). It looks acceptable to me, especially because we now use Composer to manage dependencies.

---------------------------------------------------------------------------

by bschussek at 2012-12-03T16:54:10Z

@fabpot Thanks for the hint. Going to fix this.

---------------------------------------------------------------------------

by bschussek at 2012-12-04T11:34:43Z

@fabpot Fixed.

---------------------------------------------------------------------------

by bschussek at 2012-12-07T12:40:24Z

Is there anything missing for this PR to be merged?
@fabpot fabpot merged commit 586a16e into symfony:master Jan 9, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants