What is nestjs-i18n?
nestjs-i18n is a powerful internationalization (i18n) module for NestJS applications. It provides a comprehensive set of tools to manage translations, handle localization, and support multiple languages in a NestJS application.
What are nestjs-i18n's main functionalities?
Basic Setup
This code sets up the basic configuration for nestjs-i18n. It initializes the I18nModule with a fallback language and specifies the parser and the path to the translation files.
```typescript
import { Module } from '@nestjs/common';
import { I18nModule, I18nJsonParser } from 'nestjs-i18n';
import * as path from 'path';
@Module({
imports: [
I18nModule.forRoot({
fallbackLanguage: 'en',
parser: I18nJsonParser,
parserOptions: {
path: path.join(__dirname, '/i18n/'),
},
}),
],
})
export class AppModule {}
```
Translation Service
This code demonstrates how to use the I18nService to translate a message. The `translate` method is used to fetch the translation for the given key ('HELLO_MESSAGE').
```typescript
import { Injectable } from '@nestjs/common';
import { I18nService } from 'nestjs-i18n';
@Injectable()
export class AppService {
constructor(private readonly i18n: I18nService) {}
async getHello(): Promise<string> {
return this.i18n.translate('HELLO_MESSAGE');
}
}
```
Request Scoped Translations
This code shows how to use request-scoped translations. By injecting the I18nContext into the controller method, you can translate messages based on the current request's language.
```typescript
import { Controller, Get } from '@nestjs/common';
import { I18n, I18nContext } from 'nestjs-i18n';
@Controller()
export class AppController {
@Get()
async getHello(@I18n() i18n: I18nContext): Promise<string> {
return i18n.translate('HELLO_MESSAGE');
}
}
```
Other packages similar to nestjs-i18n
i18next
i18next is a popular internationalization framework for JavaScript applications. It provides a wide range of features for managing translations and supports various backends for loading translation files. Compared to nestjs-i18n, i18next is more general-purpose and can be used with any JavaScript framework, not just NestJS.
nestjs-i18n
nestjs-i18n is another internationalization module for NestJS. It offers similar functionalities to nestjs-i18n, such as managing translations and supporting multiple languages. However, it may have different configuration options and features.
react-i18next
react-i18next is a powerful internationalization library specifically designed for React applications. It builds on top of i18next and provides React-specific bindings. While it offers similar translation management features, it is tailored for use with React rather than NestJS.
![Greenkeeper badge](https://badges.greenkeeper.io/ToonvanStrijp/nestjs-i18n.svg)
Description
The i18n module for Nest.
Installation
$ npm i --save nestjs-i18n
Quick Start
Structure
create a directory and in it define your language keys as directories.
i18n
├── en
│ ├── category.json
│ └── auth.json
└── nl
├── category.json
└── auth.json
Translation File
The format for the translation file could look like this:
{
"HELLO_MESSAGE": "Hello {username}",
"GOODBYE_MESSAGE": "Goodbye {username}",
"USER_ADDED_PRODUCT": "{0.username} added {1.productName} to cart",
"SETUP": {
"WELCOME": "Welcome {0.username}",
"GOODBYE": "Goodbye {0.username}"
},
"ARRAY": [
"ONE",
"TWO",
"THREE"
]
}
String formatting is done by: string-format
Translation Module
To use the translation service we first add the module. The I18nModule
has an @Global()
attribute so you should only import it once.
import { Module } from '@nestjs/common';
import * as path from 'path';
import { I18nModule } from 'nestjs-i18n';
@Module({
imports: [
I18nModule.forRoot({
path: path.join(__dirname, '/i18n'),
filePattern: '*.json',
fallbackLanguage: 'en',
}),
],
controllers: []
})
export class AppModule {}
Using forRootAsync()
import { Module } from '@nestjs/common';
import * as path from 'path';
import { I18nModule } from 'nestjs-i18n';
@Module({
imports: [
I18nModule.forRootAsync({
useFactory: (config: ConfigurationService) => ({
path: configService.i18nPath,
fallbackLanguage: configService.fallbackLanguage,
filePattern: configService.i18nFilePattern,
}),
inject: [ConfigurationService]
}),
],
controllers: []
})
export class AppModule {}
Language Resolvers
To make it easier to manage in what language to respond you can make use of resolvers
@Module({
imports: [
I18nModule.forRoot({
path: path.join(__dirname, '/i18n/'),
fallbackLanguage: 'en',
resolvers: [
new QueryResolver(['lang', 'locale', 'l']),
new HeaderResolver(),
],
}),
],
controllers: [HelloController],
})
export class AppModule {}
Currently, there are two build-in resolvers
Resolver | Default value |
---|
QueryResolver | none |
HeaderResolver | accept-language |
To implement your own resolver (or custom logic) use the I18nResolver
interface.
Using Translation Service and Language Resolver
@Controller()
export class SampleController {
constructor(
private readonly i18n: I18nService,
) {}
@Get()
sample(
@I18nLang() lang: string
) {
this.i18n.translate('HELLO_MESSAGE', {lang: lang, args: {id: 1, username: 'Toon'}});
this.i18n.translate('SETUP.WELCOME', {lang: 'en', args: {id: 1, username: 'Toon'}});
this.i18n.translate('ARRAY.0', {lang: 'en'});
}
}
Missing Translations
If you require a translation that is missing, I18n
will log an error. However, you can also write these missing translations to a new file in order to help translating your application later on.
This behaviour can be controlled via the saveMissing: boolean
attribute when adding the I18nModule
to your application. Thereby, true
describes the following behaviour:
Say, you request the translation mail.registration.subject
in a de
language, and this specific key is missing. This will create a de/mail.missing
file in your i18n
folder and add the following content:
{
"registration": {
"subject": ""
}
}
CLI
To easily check if your i18n folder is correctly structured you can use the following command:
nest-i18n check <i18n-path>
example: nest-i18n check src/i18n
This is very useful inside a CI environment to prevent releases with missing translations.
Breaking changes:
-
from V4.0.0 on we changed the signature of the translate
method, the language is now optional, if no language is given it'll fallback to the fallbackLanguage
-
from V3.0.0 on we load translations based on their directory name instead of file name. Change your translations files to the structure above: info