I have a user schema like the code below:
const Joi = require("joi");
const message = require("./types/string");
const username = Joi.string()
.regex(/^[A-Za-z0-9]+$/)
.required()
.min(5)
.max(20)
.messages(message);
const email = Joi.string()
.regex(/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/)
.required()
.min(5)
.max(255)
.email()
.messages(message);
const password = Joi.string()
.regex(/^[A-Za-z0-9]+$/)
.required()
.min(5)
.max(255)
.messages(message);
const userSchema = Joi.object({
username,
password,
email,
});
exports.userSchema = { route: "/users", object: userSchema };
and a schema validation like the code below that I have found at https://www.digitalocean.com/community/tutorials/how-to-use-joi-for-node-api-schema-validation:
const _ = require("lodash");
const { StatusCodes } = require("http-status-codes");
const { Schemas } = require("../joi-schema-validation");
exports.schemaValidator = function (useJoiError = false) {
const _useJoiError = _.isBoolean(useJoiError) && useJoiError;
const _supportedMethods = ["post", "put", "patch"];
const _validationOptions = {
abortEarly: false,
allowUnknown: true,
stripUnknown: true,
};
return (req, res, next) => {
const route = req.route.path;
const method = req.method.toLowerCase();
const schema = Schemas.find(
(schema) => schema.route === route.replace("/:id", "")
);
if (_.includes(_supportedMethods, method) && schema) {
const { object } = schema;
const { error, value } = object.validate(req.body, _validationOptions);
if (error) {
const JoiError = {
status: "failed",
validationErrors: {
details: _.map(error.details, ({ message, context }) => ({
[context.label]: req.t(message.replace(/['"]/g, "")),
})),
},
};
const CustomError = {
status: "failed",
error: "Invalid request data. Please review request and try again.",
};
return res
.status(StatusCodes.BAD_REQUEST)
.json(_useJoiError ? JoiError : CustomError);
} else {
req.body = value;
return next();
}
}
return next();
};
};
Let's say I have two locales joi messages, one in english and one in spanish. How can I switch to locale joi messages if "Accept-Language" header is "es-es" lcid?
After digging around and slept over it, I've manage to come up with an easy solution. In the beginning of the route handler middleware, i have a "messages" variable where I check the request header accept language. If the language LCID is "en" then I return the english error messages or return default error messages, in my case the dutch language error messages. Before validating, I pass the return error messages into the messages method of my schema and then chain the validate function to it.
The updated code looks now like code underneath:
const _ = require("lodash");
const { StatusCodes } = require("http-status-codes");
const { Schemas } = require("../joi-schema-validation");
exports.schemaValidator = function (useJoiError = false) {
const _useJoiError = _.isBoolean(useJoiError) && useJoiError;
const _supportedMethods = ["post", "put", "patch"];
const _validationOptions = {
abortEarly: false,
allowUnknown: true,
stripUnknown: true,
};
return (req, res, next) => {
const messages =
req.headers["accept-language"] === "en"
? require("../joi-schema-validation/types/string")
: require("../joi-schema-validation/types/string-nl");
const route = req.route.path;
const method = req.method.toLowerCase();
const schema = Schemas.find(
(schema) => schema.route === route.replace("/:id", "")
);
if (_.includes(_supportedMethods, method) && schema) {
const { object } = schema;
const { error, value } = object
.messages(messages)
.validate(req.body, _validationOptions);
if (error) {
const JoiError = {
status: "failed",
validationErrors: {
details: _.map(error.details, ({ message, context }) => ({
[context.label]: message.replace(/['"]/g, ""),
})),
},
};
const CustomError = {
status: "failed",
error: "Invalid request data. Please review request and try again.",
};
return res
.status(StatusCodes.BAD_REQUEST)
.json(_useJoiError ? JoiError : CustomError);
} else {
req.body = value;
return next();
}
}
return next();
};
};
If there are any comments or alternatives for this solution, I'm more than happy to read about them.
Happy coding