Skip to Content
Message Documentation

Message Documentation

This documentation explains the features and usage of Message Module: Located at src/common/message

Overview

Message Service provides internationalization (i18n) support using nestjs-i18n  to manage multi-language messages. All message files are stored in src/languages/{language} directory in JSON format. Currently, only English (en) is available.

The MessageModule is imported globally via CommonModule in src/common/common.module.ts, making MessageService available throughout the application without additional imports.

Table of Contents

Configuration

Default language is configured via environment variable:

APP_LANGUAGE=en

Configuration structure:

// src/config/message.config.ts export default registerAs( 'message', (): IConfigMessage => ({ availableLanguage: Object.values(EnumMessageLanguage), language: process.env.APP_LANGUAGE ?? EnumMessageLanguage.EN, }) );

Language options are defined in the enum:

export enum EnumMessageLanguage { EN = 'en', }

Message Files

Message files use JSON format with nested structure. Key paths follow the pattern: filename.field.nested.

Example structure:

// src/languages/en/auth.json { "login": { "success": "Login successful", "error": { "notFound": "Email not found", "passwordNotMatch": "Password does not match" } } }

Access pattern:

// Key path: auth.login.success // Output: "Login successful" // Key path: auth.login.error.notFound // Output: "Email not found"

Usage

Basic Translation

Inject MessageService and use setMessage method:

@Injectable() export class UserService { constructor(private readonly messageService: MessageService) { } getWelcomeMessage(): string { return this.messageService.setMessage('user.welcome'); } }

Translation with Variables

Pass variables through the properties option:

// src/languages/en/user.json { "greeting": "Hello, {name}!", "itemCount": "You have {count} items" }
const greeting = this.messageService.setMessage('user.greeting', { properties: { name: 'John' } }); // Output: "Hello, John!" const itemCount = this.messageService.setMessage('user.itemCount', { properties: { count: 5 } }); // Output: "You have 5 items"

Custom Language

Override default language using the customLanguage option:

const message = this.messageService.setMessage('user.welcome', { customLanguage: 'id' // Indonesian });

Request-specific language can be set via the x-custom-lang header:

await axios.get('http://localhost:3000/api/users', { headers: { 'x-custom-lang': 'id' } });

Integration

Exception Filters

Exception filters automatically translate message paths.

throw new BadRequestException({ statusCode: EnumUserStatus_CODE_ERROR.emailExist, message: 'user.error.emailExists', // Will be translated });

With variables:

throw new NotFoundException({ statusCode: EnumUserStatus_CODE_ERROR.notFound, message: 'user.error.notFoundWithId', _metadata: { customProperty: { messageProperties: { id: userId } } } });

Response Decorator

The @Response decorator translates success message paths. See Response Documentation for details.

@Response('user.create') @Post('/') async create(@Body() dto: CreateUserDto ): Promise < IResponse > { const user = await this.userService.create(dto); return { data: user }; }

With variables:

@Response('user.update') @Patch('/:id') async update( @Param('id') id: string, @Body() dto: UpdateUserDto ): Promise < IResponse > { const user = await this.userService.update(id, dto); return { data: user, _metadata: { customProperty: { messageProperties: { name: user.name } } } }; }

Validation Pipe

Validation errors are automatically translated by MessageService. The service handles both flat and nested validation errors by traversing the error tree and extracting constraints at each level. See Request Validation Documentation for details.

Message Resolution Strategy:

  1. Primary: Tries to resolve message from request.error.{constraint} path
  2. Fallback: If translation not found, uses the raw message from class-validator

Example message file:

// src/languages/en/request.json { "error": { "isNotEmpty": "{property} should not be empty", "isEmail": "{property} must be a valid email", "minLength": "{property} must be at least {min} characters" } }

Nested Validation:

For nested objects, the service return the full property path by traversing child errors:

// Input DTO with nested validation class AddressDto { @IsNotEmpty() street: string; } class UserDto { @ValidateNested() address: AddressDto; } // Validation error output: { "key": "isNotEmpty", "property": "address.street", "message": "street should not be empty" }

Standard validation response:

// Automatic transformation { "statusCode" : 400, "message" : "Validation error", "errors" : [ { "key": "isNotEmpty", "property": "email", "message": "email should not be empty" }, { "key": "isEmail", "property": "email", "message": "email must be a valid email" } ] }

Adding New Language

  1. Create a new language directory:
mkdir -p src/languages/id
  1. Copy and translate JSON files:
cp src/languages/en/*.json src/languages/id/
  1. Update the enum:
export enum EnumMessageLanguage { EN = 'en', ID = 'id', // Add new language }
  1. Restart the application to load new language files.
Last updated on