Skip to main content

Global validation

To use nestjs-i18n in your DTO validation you first need to follow the nestjs instructions. After that you need to use the I18nValidationPipe.

src/main.ts
import { i18nValidationErrorFactory } from 'nestjs-i18n';

app.useGlobalPipes(
new I18nValidationPipe(),
);

DTO definition

Inside your DTO class define all your properties and validators. The important thing here is to use the i18nValidationMessage helper function inside the message property.

src/dto/create-user.dto.ts
import {
IsBoolean,
IsDefined,
IsEmail,
IsNotEmpty,
Max,
Min,
ValidateNested,
} from 'class-validator';
import { Type } from 'class-transformer';
import { i18nValidationMessage } from 'nestjs-i18n';

export class ExtraUserDto {
@IsBoolean({ message: 'validation.INVALID_BOOLEAN' })
subscribeToEmail: string;

@Min(5, {
message: i18nValidationMessage('validation.MIN', { message: 'COOL' }),
})
min: number;

@Max(10, {
message: i18nValidationMessage('validation.MAX', { message: 'SUPER' }),
})
max: number;
}

export class CreateUserDto {
@IsNotEmpty({ message: i18nValidationMessage('validation.NOT_EMPTY') })
@IsEmail({}, { message: i18nValidationMessage('validation.INVALID_EMAIL') })
email: string;

@IsNotEmpty({ message: i18nValidationMessage('validation.NOT_EMPTY') })
password: string;

@ValidateNested()
@IsDefined()
@Type(() => ExtraUserDto)
extra: ExtraUserDto;
}
tip

By using the i18nValidationMessage helper function you can pass in extra arguments or make use of internal class-validator properties such as property, value, constraints.0.

Translations

Inside your translation you now can use class-validator properties such as property, value and constraints.0.

src/i18n/en/validation.json
{
"NOT_EMPTY": "{property} cannot be empty",
"INVALID_EMAIL": "email is invalid",
"INVALID_BOOLEAN": "{property} is not a boolean",
"MIN": "{property} with value: \"{value}\" needs to be at least {constraints.0}, ow and {message}",
"MAX": "{property} with value: \"{value}\" needs to be less than {constraints.0}, ow and {message}"
}

Filter

For nestjs-i18n to translate the class-validator errors add the I18nValidationExceptionFilter on your controller or globally.

src/app.controller.ts
import { I18nValidationExceptionFilter } from 'nestjs-i18n';

@Post()
@UseFilters(new I18nValidationExceptionFilter())
create(@Body() createUserDto: CreateUserDto): any {
return 'This action adds a new user';
}
src/main.ts
import { I18nValidationExceptionFilter } from 'nestjs-i18n';

app.useGlobalFilters(new I18nValidationExceptionFilter());

I18nValidationExceptionFilterOptions

I18nValidationExceptionFilter also takes an argument of type I18nValidationExceptionFilterOptions

NameTypeRequiredDefaultDescription
detailedErrorsbooleanfalsetrueSimplify error messages
errorFormatter(errors: ValidationError[]) => objectfalseReturn the validation errors in a format that you specify.
errorHttpStatusCodeHttpStatusfalse400Change the default http status code for the I18nValidationException.
info

Note that only one of the properties detailedErrors and errorFormatter can be used at the time.

Response

Now your validation errors are being translated 🎉!

response
{
"statusCode": 400,
"errors": [
{
"property": "email",
"children": [],
"constraints": {
"isEmail": "email is invalid",
"isNotEmpty": "email cannot be empty"
}
},
{
"property": "password",
"children": [],
"constraints": { "isNotEmpty": "password cannot be empty" }
},
{
"property": "extra",
"children": [
{
"property": "subscribeToEmail",
"children": [],
"constraints": {
"isBoolean": "subscribeToEmail is not a boolean"
}
},
{
"property": "min",
"children": [],
"constraints": {
"min": "min with value: \"1\" needs to be at least 5, ow and COOL"
}
},
{
"property": "max",
"children": [],
"constraints": {
"max": "max with value: \"100\" needs to be less than 10, ow and SUPER"
}
}
],
"constraints": {}
}
]
}
tip

If you want a different output, create your own interceptor! For an example look at the I18nValidationExceptionFilter.

Example

A working example is available here.