Off-shot from #1845546: Implement validation for the TypedData API. Let's use this issue to a) figure out how to integrate both and b) how we could pursue translation in a way potx is aware of them.
Related issue: #1852106: Add the symfony translator interface or translation component.
So, as of now - symfony validator does not handle message translations. It defines messages at the constraint classes using class variables that end with the "message" suffix. E.g. see the Range constraint
/**
* @Annotation
*
* @api
*/
class Range extends Constraint
{
public $minMessage = 'This value should be {{ limit }} or more.';
public $maxMessage = 'This value should be {{ limit }} or less.';
public $invalidMessage = 'This value should be a valid number.';
public $min;
public $max;
}
So, we need to figure out whether that is something that is reasonable to parse with potx, or we need to re-define every single translation message in a way it works for us. For that, the requirement would be that it is possible to get the untranslated message also, such that you could log the violation message to watchdog (consider a web service request failling due to validation, so you log the violations).
A possible strategy for potx to work with the symfony pattern could be using a regex that checks for the value of all variables having the Message suffix in a class extending "XXConstraint".
Comments
Comment #1
Gábor HojtsyAre we sure XXConstraint is coming from a validator component? Do we need to check the namespace of the Constraint class extended? Sounds to me like Constraint is a pretty generic name that could be used in other namespaces. Granted, it might be little for false positives, if we pick up the xzyMessage property of those as well.
Comment #2
fagoYeah, I think it shouldn't provide too many false positiives. However, if feasible we could additionally check that the namespaces ends with "Constraints" or "Constraint"?
Comment #3
Gábor HojtsyThat is theoretically possible yes. I did not check what kind of data is provided by the PHP tokenizer for this. You can try with http://hu2.php.net/token_get_all
Comment #4
fagoI think we won't be able to support context as is, e.g. all violations arr created via that method:
So there is no way to pass the context on here. Is that problematic? I'd assume sentences to not need to specify a context as usually they would not clash?
Different pluralizations could be handled already by the validating code by passing on the right message I think.
Comment #5
Gábor HojtsyRight, sentences usually should not need a context.
How would "the right message" be picked on a language dependent basis?
Comment #6
fagouhm, I was not aware of locale_get_plural() so assumed a check for $count > 1 is enough. Given it's not - I've no idea how to do that :(
Comment #7
fagoWell, we could move on with the concatenated string as message template, i.e. pass on implode(LOCALE_PLURAL_DELIMITER, array($singular, $plural)); if we have a plural count + provide a helper for that.
Then afterwards, when we have a plural count, we could explode the messages and move on...
Comment #8
Gábor HojtsyYes, languages have a rich difference in plural formulas so the plural selection logic is language dependent and there might be 4 (eg. Slovenian) or 6 (eg. Arabic) different plural versions depending on the number: http://translate.sourceforge.net/wiki/l10n/pluralforms It is definitely not just $count > 1 :)
Comment #9
fagoI posted a suggestion upstream to give us more flexibility here:
https://github.com/symfony/symfony/pull/6137#issuecomment-10840962
With that, we could do something like
Comment #10
fagoI noted it's not possible to use format_pural() with watchdog: http://api.drupal.org/api/drupal/core!includes!bootstrap.inc/function/wa...
Maybe, it would make sense to have a kind of TranslatedMessage object which does the translation upon method call + allows access to untranslated messages? Then make watchdog() and our violation accept that?
Comment #11
fagoI found a related issue: #1053690: watchdog call at system_cron() needs proper plural format - marked as won't fix :(
Comment #12
fagoSee http://drupal.org/node/1542144#comment-6790478 for a Translatable object prototype. I think a general solution like that would be preferable to a solutions specific to violations only.
Comment #13
fagodiscussed with bschussek again. We figured out a way we should be able to implement the symfony translation interface: Once validator adopts the regular symfony way of handling plural translation we'll get message that have both using the
|
delimiter:Thus, we should be able to split by the delimiter and pass it on to format_plural(). This should work for supporting plural translations. As it's a single string we should be able to handle it with potx as well.
One disadvantage is that it comes with a new DX for handling plural messages, but we'll have one anyway as currently there is now way to handle postponed format_plural() translations. (see related #1542144-12: Mark strings as localizable/translatable (new t()-alike string function that isn't t(), only for potx)) Then, the used delimiter is different to ours, but obviously we cannot use a constant in our strings.
Given that, I think the symfony translation interface is not 100% match, but it should be sufficient for handlinv violation constraint message translations as we do not need to support $context. Thoughts?
Comment #14
Gábor HojtsyWell, we don't have a way currently to handle postponed t()-s either, apart of the one-offs in watchdog() and hook_menu. Coming up with a new syntax for them is not a requirement to introduce this but I see you want to do it to conform to Symfony. I'll not say I'm happy about this, given that now translators will need to know if something is "@count comment" and "@count comments" or "{{ limit }} comment" and "{{ limit }} comments" it is essentially the same thing :/ :/
Comment #15
attiks CreditAttribution: attiks commentedI'm still hesitant about introducing another (SF) syntax for translatable strings, if this was something that was going to be used by not only Constraints I think it might be appropriate, but adding this only to be able to use some of SF Constraints directly is a bit over kill.
I would rather see us solve #1542144-12: Mark strings as localizable/translatable (new t()-alike string function that isn't t(), only for potx) and use our own coding standards for translations.
The other problem with 'blindly' using SF Constraints is that we need a way to handle string changes inside their Constraints, otherwise it will break existing sites.
Comment #16
fagoWe can fix the replacement patters as the API doesn't enforce the pattern (as no one stepped in for symfony replacements yet, I guess we'll have Drupal style), but I think we'd have to stick to the "single|plural" pattern.
Well, we need to come up with a way to do format_plural() such that translation is postponed and potx works, i.e. we could do something like violation_message_plural() and build in potx support for that. That would invent a new way to specify the translation also. So yes, we do not necesarily have to come up with a new syntax, but with a new way to specify the plural messages as format_plural() doesn't get it.
Comment #17
fagoI don't think symfony will have lots of string changes once its stable, but still git will expose all of them once we decide to update. Thus, if they'd really occur we can still easily prevent them by overridding messages.
Given we'll probably have Drupal replacements, we'll have to override most symfony messages anyway. So this is not really about re-using symfony messages, but finding a way we can specify translations such that a) it works with the symfony validator API b) supports all Drupal translation features we need, i.e. pluralization (see #4).
Comment #18
fagoSo with Drupal replacements we'd have:
I think that's a reasonable approach as it makes translation quite natural to Drupal, while giving use plural translation and possibly postponed translation?
Comment #19
attiks CreditAttribution: attiks commentedTo make sure I understand it correctly, the only 'new' thing is the pipe, if so that's something I can live with.
Comment #20
fagoad #19: exactly!
Comment #21
effulgentsia CreditAttribution: effulgentsia commentedGabor: any feedback on #18?
Comment #22
effulgentsia CreditAttribution: effulgentsia commentedResolving this (whether by #18, or something else, or deciding not to use Symfony Validation) is ultimately necessary for #1696648: [META] Untie content entity validation from form validation, which is necessary for web services. Therefore, raising to major and tagging.
Comment #23
Gábor Hojtsy@effulgentsia: as said above all is needed for the extraction of those strings is a reasonably identifiable code pattern and the ability to find these strings with static code analysis up front, so we can identify the strings and expose for community translation. #18 combined with prior proposals of placement of those messages within classes and following a special naming scheme looks to satisfy that.
Comment #24
effulgentsia CreditAttribution: effulgentsia commentedFrom the issue summary:
If this issue's scope is "figure out", and given #23, what's left to do on this issue?
Comment #25
webmozart CreditAttribution: webmozart commentedSome feedback from the Symfony camp. The validator now uses two different message styles by default:
message
for regular messages. Replaceable params follow the format{{ param }}
.singular|plural
for singular/plural messages. Params are supported like above.singular
is used for the exactly one case,plural
is used for zero and more than one.All core constraints use these two formats by default.
Now the but!
These two formats are not sufficient for languages other than English! So the Symfony Translator supports, in addition to the above formats, a third format that allows to specify intervals. The English messages in the above two formats are mapped to translated messages that potentially, but not necessarily use the more capable interval notation in translation files.
That means that
DefaultTranslator
shipped with the Validator that simply replaces params in the above two message formatsFor Drupal this means that you can map the English messages in the above two formats to translated messages in a more complex format that is understood by your translator.
Comment #26
fagoThanks for the update - that works out! I'll implement this and merge it into the main validation patch.
Comment #27
fagook, I've implemented this now. Please check the patch/interdiff over at #1845546-101: Implement validation for the TypedData API.
I'm going to call this issue fixed now, as the coding will be handled as part of #1845546-101: Implement validation for the TypedData API. If anything left is to be discussed regarding translations please just re-open it.
Comment #28.0
(not verified) CreditAttribution: commentedUpdated issue summary.