Closed tujoworker closed 1 week ago
Thank you very much! I need to see the code (or an example) to give a proper answer. Can you share it with me? In general, Valibot's error messages follow a hierarchy. The most specific messages available is applied and all others are ignored.
For now, I can customise the translations this way:
function getValidationMessage(issue: BaseIssue<unknown>, locale: Locale) {
const tr = translations[locale]
switch (issue.received) {
case 'undefined':
return tr.Field.errorRequired
}
switch (issue.type) {
case 'non_empty':
case 'non_optional':
return tr.Field.errorRequired
}
return issue.message
}
But not all issues have the needed info to make this work nicely.
e.g. I want to mimic the Ajv exclusiveMinimum
, which I do like so:
v.custom((value: number) => value > props.exclusiveMinimum)
But I would need to return more info to the issue
I receive later (like type or at least the requirement
). Is that possible?
Now I get Invalid type: Expected unknown but received 1
but can't change it to mye custom "translation", because I don't know that the exclusiveMinimum
has initialised it.
If you upgrade to our latest version you can use rawCheck
to fully control the issue information:
import * as v from 'valibot';
const Schema = v.pipe(
v.number(),
v.rawCheck(({ dataset, addIssue }) => {
if (dataset.typed && dataset.value <= props.exclusiveMinimum) {
addIssue({ message: 'Error!!!', expected: `>${props.exclusiveMinimum}` });
}
})
);
For more info about custom error messages and i18n have a look at this guide and this comment.
Nice!
I want to both add type
and requirement
via addIssue
but get this type error: type' does not exist in type 'IssueInfo$1<number>'
. Any thoughts?
Different issue: I wonder, is it possible to get the path in the issue, likeissue.path
, when setting a translation with setGlobalMessage
?
Different issue: I wonder, is it possible to get the path in the issue, like
issue.path
, when setting a translation withsetGlobalMessage
?
Yes, this should be possible.
I want to both add
type
andrequirement
viaaddIssue
but get this type error:type' does not exist in type 'IssueInfo$1<number>'
. Any thoughts?
Can you share your code with me? You can use our playground to do so. All issue info properties are optional and will be set automatically for you if you do not set them. The type
should not be a custom string and the requirement should be null
or the input requirement, e.g. props.exclusiveMinimum
.
I am happy to work with you on this issue to find a proper solution in the long run.
I want to both add type and requirement via addIssue but get this type error: type' does not exist in type 'IssueInfo$1
'. Any thoughts?
Here in this playground you see that requirement
is undefined. My custom type
I also need to know, in order to set the translation via setGlobalMessage
. I want to set all the translations in "one" place, and not here and there.
With this custom "custom" schema, I get what I need. But it would be nicer to have less code to make that happen.
That said – I was a bit unclear regarding the other issue; when using setGlobalMessage
, the issue.path
is undefined. But it would help me a lot in order to show it in a certain translation message.
Here is a playground that shows this.
Here in this playground you see that
requirement
is undefined. My customtype
I also need to know, in order to set the translation viasetGlobalMessage
.
My bad. At the moment it is not supported to set type
and requirement
via addIssue
and I am not sure if we should add it since it is not intended that way. Also, rawCheck
should only be used in special cases and not for simple validations.
I want to set all the translations in "one" place, and not here and there.
To create a custom t
function is probably what you are looking for. The downside is that it is not tree-shakable.
import * as v from 'valibot';
type TranslationCode =
| 'email:invalid'
| 'email:format'
| 'password:invalid'
| 'password:length';
const translations: Record<string, Record<TranslationCode, string>> = {
en: {
'email:invalid': 'The email has the wrong data type',
'email:format': 'The email is badly formatted',
'password:invalid': 'The password has the wrong data type',
'password:length': 'The password is too short',
},
de: {
'email:invalid': 'Die E-Mail hat den falschen Datentyp',
'email:format': 'Die E-Mail ist falsch formatiert',
'password:invalid': 'Das Passwort hat den falschen Datentyp',
'password:length': 'Das Passwort ist zu kurz',
},
};
function t(code: TranslationCode): v.ErrorMessage<v.BaseIssue<unknown>> {
return (issue) => translations[issue.lang || 'en']?.[code] ?? issue.message;
}
const Schema = v.object({
email: v.pipe(v.string(t('email:invalid')), v.email(t('email:format'))),
password: v.pipe(
v.string(t('password:invalid')),
v.minLength(8, t('password:length')),
),
});
That said – I was a bit unclear regarding the other issue; when using
setGlobalMessage
, theissue.path
is undefined. But it would help me a lot in order to show it in a certain translation message.
Thanks for the tip. This is because each schema is independent and the path is added by the parent schema, but the error message is added before that.
The possibility to add translation directly in the schema is what I want to avoid. Because in my case, every "component" has its own little schema. But at that stage I don't want to deal with translations too. Because it makes the code unnecessary complex to read and maintain.
By dealing with translations later, I can handle it with one block of logic.
But so far, I can do that with my own "custom" schema function, like you have sees in one of the example codes.
So I think this issue can be closed.
Thanks for your feedback. I will close this issue for now, but if anyone has good ideas on how we can improve this part of the library in the long run, I will be happy to reopen it.
Hi,
thank you for making this great library 🥇
When I use Valibot in a library that provides its custom strings. Like a error message for all kinds of
required
cases. I can check if the issuetype
is non_empty, non_optional etc. and return my message.But what if the user of that library provides a message manually? How can I know that the given message was a custom one?
v.getSpecificMessage(v.nonEmpty)
so I can compare it, but get undefined back.Invalid length: ...
) – but still, I can't know if its a custom message that is provided. But I could use this approach as of now, even it is not a nice way to fine the "same" message to multiple field schemas, which has different pipes with various validations.Do you have a workaround or could consider to add a property to the issue object?