Document message templating
- Dominant language
- JavaScript
- Stars
- 21.2k
- Forks
- 1.5k
- Avg merge
- 4h 57m
- Merged PRs (30d)
- 14
Description
#### Context
* *node version*: N/A
* *module version*: N/A
#### What are you trying to achieve or the steps to reproduce ?
```js
const Joi = require("joi");
const schema = Joi.object({
nested: Joi.object({
name: Joi.string().required().messages({
"any.required": "how do I do templating here?",
"string.base"() {
// via a function?
return arguments.join(" ");
},
"string.empty": "like this? ${key} and what are the values I can use?",
}),
}),
});
const result = schema.validate({
nested: {
},
});
console.log(result.error.details);
```
Message formatting isn't at all documented, including:
- the templating syntax (I had to dig through source to find things like `{{#label}}` and `{:[.]}`, but I've never seen that syntax, what do those characters mean or do?).
- which values are available to be interpolated into the message for each (digging through the source I found `key`, `label`, and `value`, but had to use `console.log()` to learn that `label` is a quoted, dot-joined key path)
Copied from a StackOverflow answer I posted:
https://stackoverflow.com/a/68092831/101869
---
### Using templates
I had to dig through the [source][] to find an example of how to do context-dependent templating / formatting of messages since it doesn't seem to be documented:
[source]: https://github.com/sideway/joi/blob/master/lib/types/string.js#L688
```js
messages: {
'string.alphanum': '{{#label}} must only contain alpha-numeric characters',
'string.base': '{{#label}} must be a string',
'string.base64': '{{#label}} must be a valid base64 string',
'string.creditCard': '{{#label}} must be a credit card',
'string.dataUri': '{{#label}} must be a valid dataUri string',
'string.domain': '{{#label}} must contain a valid domain name',
'string.email': '{{#label}} must be a valid email',
'string.empty': '{{#label}} is not allowed to be empty',
'string.guid': '{{#label}} must be a valid GUID',
'string.hex': '{{#label}} must only contain hexadecimal characters',
'string.hexAlign': '{{#label}} hex decoded representation must be byte aligned',
'string.hostname': '{{#label}} must be a valid hostname',
'string.ip': '{{#label}} must be a valid ip address with a {{#cidr}} CIDR',
'string.ipVersion': '{{#label}} must be a valid ip address of one of the following versions {{#version}} with a {{#cidr}} CIDR',
'string.isoDate': '{{#label}} must be in iso format',
'string.isoDuration': '{{#label}} must be a valid ISO 8601 duration',
'string.length': '{{#label}} length must be {{#limit}} characters long',
'string.lowercase': '{{#label}} must only contain lowercase characters',
'string.max': '{{#label}} length must be less than or equal to {{#limit}} characters long',
'string.min': '{{#label}} length must be at least {{#limit}} characters long',
'string.normalize': '{{#label}} must be unicode normalized in the {{#form}} form',
'string.token': '{{#label}} must only contain alpha-numeric and underscore characters',
'string.pattern.base': '{{#label}} with value {:[.]} fails to match the required pattern: {{#regex}}',
'string.pattern.name': '{{#label}} with value {:[.]} fails to match the {{#name}} pattern',
'string.pattern.invert.base': '{{#label}} with value {:[.]} matches the inverted pattern: {{#regex}}',
'string.pattern.invert.name': '{{#label}} with value {:[.]} matches the inverted {{#name}} pattern',
'string.trim': '{{#label}} must not have leading or trailing whitespace',
'string.uri': '{{#label}} must be a valid uri',
'string.uriCustomScheme': '{{#label}} must be a valid uri with a scheme matching the {{#scheme}} pattern',
'string.uriRelativeOnly': '{{#label}} must be a valid relative uri',
'string.uppercase': '{{#label}} must only contain uppercase characters'
}
```
An example of using a templated message:
``` js
const Joi = require("joi");
const schema = Joi.object({
nested: Joi.object({
name: Joi.string().required().messages({
"any.required": "{{#label}} is required!!",
"string.empty": "{{#label}} can't be empty!!",
}),
}),
});
const result = schema.validate({
nested: {
// comment/uncomment to see the other message
// name: "",
},
});
console.log(result.error.details);
```
When using the template syntax, the context values that seem to be passed are something like the following, though specific rules / validators may pass more context:
``` js
{
key: "name", // this key, without ancestry
label: `"nested.name"`, // full path with dots as separators, in quotes
value: "", // the value that was validated
}
```
Contributor guide
Assessment
This issue has not been assessed yet.