-
-
Notifications
You must be signed in to change notification settings - Fork 564
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
Validation messages translation #711
Comments
Can you elaborate a bit more on what is your use-case? Why do you want to translate validation messages? These messages are not supposed to be shown to end-users. They are mostly for developers (those who write API clients). |
Our API used as backend for a few frontend applications and for admin panel wich is used by non developers. And API by itself used by some specialists who know how it works, but they are not developers. Some of our frontend applications use custom made graphQl query builders and all this non developer users not always understand returned errors. For example if they entered wrong type, or something wrong in their query if they work with API directly or this is just frontend app query builder problem for developers. And also we have another validators running on this API which returns translated errors and users see some translated errors and some not. In short words we have API, and it used by some other people, we not always know how they handle all our errors on their side, and where they show them, and they ask us for full translation. So we need to translate all our errors. |
I don't want to complicate things in this library by introducing the translation layer (as this is not intended usage of those errors) but we can allow overriding message templates. Something along the lines: class ValuesOfCorrectType extends ValidationRule
{
static protected $messages = [
'unknownFieldMessage' => 'Field "%s" is not defined by type %s',
];
// This should be probably common in ValidationRule class
public static function setMessage($id, $textTemplate)
{
static::$messages[$id] = $textTemplate;
}
public static function unknownFieldMessage($typeName, $fieldName, $message = null)
{
return sprintf(static::$messages['unknownFieldMessage'], $fieldName, $typeName) .
($message ? sprintf('; %s', $message) : '.');
}
} Will it work for you? |
Additionally, we can add |
@vladar how about we just use public properties and prefix them all with class ValuesOfCorrectType extends ValidationRule
{
static public $messageUnknownField = 'Field "%s" is not defined by type %s';
public static function unknownFieldMessage($typeName, $fieldName, $message = null)
{
return sprintf(static::$messageUnknownField, $fieldName, $typeName) .
($message ? sprintf('; %s', $message) : '.');
}
} That way, autocompletion and static validation work to ensure the correct property is changed. |
Yes, that will help alot, but maybe somethig like
or add some |
Sure, a PR is welcome! We can continue this discussion there. |
@spawnia Works for me and looks simpler 👍 |
Okay, thank you! Then I'll make a PR with something like
No seters, no getters, just Variant with |
I can not exactly follow why the indirection of using an array is necessary. What's wrong with just setting the properties for each class: ValuesOfCorrectType::$messageUnknownField = '...';
AnotherValidationRule::$messageSomeCondition = '...'; Another idea to allow for dynamic messages: ValuesOfCorrectType::$messageUnknownField = static function($typeName, $fieldName, $message) {
return TranslationService::message(...)
};
class ValuesOfCorrectType extends ValidationRule
{
static public $unknownFieldMessage = 'Field "%s" is not defined by type %s';
public static function unknownFieldMessage($typeName, $fieldName, $message = null)
{
if (is_callable(self::$unknownFieldMessage)) {
return self::$unkownFieldMessage($typeName, $fieldName, $message);
}
...
}
} |
My intention was to allow fetching all messages and their keys. But prefix will probably allow this too if actually required |
Because for this variant we need to store some of your lib data (like names of every class message variables or something) in our code, or we need to extend all your validation classes, make translations inside and then replace them using But with public static array we can do in our code something like
and that will be all. No extending, no callbacks, no other interactions or changes. At least that is how i see it. Sorry if i got somethig wrong. |
Forgive my stubbornness, but I still do not see how that is useful.
This Setting a property on a specific class is as simple as it gets. If you require multiple language, you could do something like: if ($languageA) {
SomeClass::$messageFoo = 'translatation for a';
...
} elseif ($languageB) {
SomeClass::$messageFoo = 'translation for b';
} My thinking is you have to know which classes and which kinds of messages exist in order to translate them properly. No amount of indirection is going to solve that. |
This
and then translator function requires something like That is why the simplest way to do this translation is to get list of some templates, translate and set this messages back to some "storage". That is why i propose variant with Option like
requires to store a list of classes and list of all properties with Yes both options is suitable as i see it, first is a bit more convenient for us. I will make PR for any of these options, I just want to understand which one will be acceptable for you and also convenient for our needs. |
From a maintenance perspective, we should be able to guarantee stable property names (or array keys), rather than stable message contents. If the goal is to make sure that all messages are translated, depending on the keys seems like a more reliable long term option. I personally prefer to write code in a way that prevents silly errors, such as misspelling an array key, or maybe missing a dot or other punctuation in the contents of a message. However, that also comes from a tendency of mine to ruthlessly refactor things. |
Okay, I'll fork and do a PR with something like |
Is is possible to extend the default validation rules. All of them conveniently have the actual error message generation extracted to separate methods, which you can override: graphql-php/tests/Validator/CustomRuleTest.php Lines 19 to 55 in a5d64c7
|
Hi, I want to add translations to your validation rules messages, but I can't find a right way to do it more or less "acceptable". Can you help me a bit with this problem?
As far as i can see almost all your validation rules has static methods with messages which return dynamic text. And almost all this static methods used by their own class objects in non static methods using self:: .
For example:
I can extend any
ValidationRule
class give it proper$name
and rewrite it inDocumentValidator::$defaultRules
array before validation usingDocumentValidator::addRule()
method. But i can't only redefine ValidationRules static methods with error mesages and do something likebecause this methods called via
self::
and not viastatic::
(but even ifstatic::
was used, this is also not the best way to add translations to messages) and static methods is not comfortable to translate if you don't have a static translator (i use symfony/translation 5.0).All i can do in this situation for now, as i can see it, is to make a full copy of every validation class that i want to translate to my project, make all necessary changes and rewrite it via
DocumentValidator::addRule()
. But that is not a proper way to do it, because of updates and etc.Maybe there is another way to solve this problem? Or maybe you working on some changes for validation messages (like some messages storage class where i can redefine any validation messages)?
Thank you in advance!
The text was updated successfully, but these errors were encountered: