class-validator-translator-middleware
v1.0.5
Published
A middleware to convert class-validator messages to locale languages using similar i18n pattern
Downloads
42
Maintainers
Readme
class-validator-translator-middleware
How to use this package
first install it
npm i class-validator-translator-middleware
Now create a directory wherever you want and name it what ever you like but I use class-validator-errors:
mkdir src/class-validator-errors
Then you should create
error-codes.json
in that directory:touch src/class-validator-errors/error-codes.json
Now in it you have to define your error codes like this.
{ "title_should_be_sample": "title_should_be_sample" }
Now you must define your error locale messages in separated files on that directory. E.X. you should
touch src/class-validator-errors/en.json
and in that file you have:{ "title_should_be_sample": "sample is good" }
And Also
touch src/class-validator-errors/fa.json
:{ "title_should_be_sample": "تست خوبه" }
Important note: You cannot define an error code in
error-codes.json
but it had no defined error message in your error locale messages. If you do this intentionally or accidentally you will get an error while creating a new instance ofClassValidatorTranslatorMiddleware
, The thrown error is instance of this error custom error class:IncompatibleErrorCodeAndErrorMessage
.Since I am reading the error messages using require, they will be cached in the memory and this will prevent unnecessary reads from file system. for more info please read
ClassValidatorTranslatorMiddleware
codes :star_struck:Note if you are using tsc: because we will never ever use fa.json and other json files you have to include this unused json files in your
tsconfig.json
/tsconfig.build.json
file like this (If you do not include your fa.json, en.json, ... files will not be in the compiled version. unless you import them implicitly):{ "include": ["src", "src/**/*.json"] // ... }
I client side sends an locale that you do not defined its error-message file in the
class-validator-errors
directory you will get An error in the next error handler middleware. In this case you will get an error that it is instance ofSpecifiedErrorMessageFileNotFound
.Your frontend have to specify the
accept-language
header in their requests and it should be within theLocale
enum.Final examples:
Here is one example in ExpressJS:
// app.ts import { join } from 'path'; import { Equals, IsOptional } from 'class-validator'; import { ClassValidatorTranslatorMiddleware, IncompatibleErrorCodeAndErrorMessage } from 'class-validator-translator-middleware'; process.on('uncaughtException', (error) => { if (error instanceof IncompatibleErrorCodeAndErrorMessage) { // do what ever you like, like sending email/notification to your devops guy process.exit(1); } }) const messagesPath = join(__dirname, 'class-validator-errors'); const classValidatorTranslatorMiddleware = new ClassValidatorTranslatorMiddleware(messagesPath); const classValidatorTranslatorMiddleware = new ClassValidatorTranslatorMiddleware(messagesPath); app.use(classValidatorTranslatorMiddleware.middleware); // this can be your class validator class TestClassValidator { @IsOptional() @Equals('sample', { message: 'title_should_be_sample' }) title: string = 'bad_value'; } app.use((error, req, res, next) => { for (const error of errors) { console.log(error.constraints); // تست خوبه } }); ```
Here is one example in routing controller
// messages.ts import { ClassValidatorTranslatorMiddleware } from 'class-validator-translator-middleware'; // city-filter.ts import { IsBoolean, IsAlpha, IsOptional, } from 'class-validator'; export class CityFilterQuery { @IsOptional() @IsAlpha('en', { message: 'serviced_should_be_boolean_not_empty', }) @IsBoolean({ message: 'serviced_should_be_boolean' }) serviced?: boolean; } // class-validator-error-translator.middleware.ts import { join } from 'path'; import { ValidationError } from 'class-validator'; import { Middleware, ExpressErrorMiddlewareInterface, HttpError, } from 'routing-controllers'; import { NextFunction, Request, Response } from 'express'; import { ClassValidatorTranslatorMiddleware } from 'class-validator-translator-middleware'; const messagesPath = join( __dirname, 'class-validator-errors', ); const classValidatorTranslatorMiddleware = new ClassValidatorTranslatorMiddleware(messagesPath); class CustomValidationError { errors: ValidationError[]; status?: number; statusCode?: number; } @Middleware({ type: 'after' }) export class ClassValidatorErrorTranslator implements ExpressErrorMiddlewareInterface { error( error: HttpError | CustomValidationError, request: Request, response: Response, next: NextFunction, ): void { classValidatorTranslatorMiddleware.middleware( error, request, response, next, ); } } // another middleware import { ValidationError } from 'class-validator'; import { Middleware, ExpressErrorMiddlewareInterface, HttpError, } from 'routing-controllers'; import { NextFunction, Request, Response } from 'express'; import { SpecifiedErrorMessageFileNotFound } from 'class-validator-translator-middleware'; @Middleware({ type: 'after' }) export class ClassValidatorErrorTranslator implements ExpressErrorMiddlewareInterface { error( error: HttpError | CustomValidationError, request: Request, response: Response, next: NextFunction, ): void { if ( error instanceof SpecifiedErrorMessageFileNotFound ) { // do whatever you want. response.status(400).json({ message: 'un-supported-language', }); } next(error); } } // app.ts import { ClassValidatorErrorTranslator } from './middlewares/class-validator-error-translator.middleware'; import express from 'express'; const app = express(); const routingControllersOptions: RoutingControllersOptions = { controllers: [ /* controllers */ ], middlewares: [ClassValidatorErrorTranslator], /* other configs */ validation: { whitelist: true, }, }; useExpressServer(app, routingControllersOptions);
Supported languages in Locale
enum
Notes
- I had no time to add all the languages in the Locale
- Please use it with Typescript to prevent any unexpected behaviours
- Feel free to create issue or pull request
Contribution
- Clone repository
npm i; npm i prepeare
- Create a new branch from
develop
branch (git checkout -b develop-your-name
) - Write you code
- Write its tests in tests directory
- run
npm test
and make sure it works perfectly