Skip to main content

Quickstart

In this quick start you'll learn how to do a basic i18n setup.

Installation

npm install --save nestjs-i18n

Setup translation files

By default nestjs-i18n uses the I18nJsonLoader loader class. This loader reads translations from json files. Create a folder named i18n in the src folder of your project.

package.json
package-lock.json
...
src
└── i18n
├── en
│   ├── events.json
│   └── test.json
└── nl
   ├── events.json
   └── test.json
src/i18n/en/test.json
{
"HELLO": "Hello",
"PRODUCT": {
"NEW": "New Product: {name}"
},
"ENGLISH": "English",
"ARRAY": ["ONE", "TWO", "THREE"],
"cat": "Cat",
"cat_name": "Cat: {name}",
"set-up-password": {
"heading": "Hello, {username}",
"title": "Forgot password",
"followLink": "Please follow the link to set up your password"
},
"day_interval": {
"one": "Every day",
"other": "Every {count} days",
"zero": "Never"
},
"nested": "We go shopping: $t(test.day_interval, {{\"count\": {count} }})"
}
caution

The i18n folder isn't automatically copied to your dist folder during the build process. To enable nestjs to do this modify the compilerOptions inside nest-cli.json.

nest-cli.json
{
"collection": "@nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"assets": [
{ "include": "i18n/**/*", "watchAssets": true }
]
}
}
caution

When using a monorepo structure don't forget to set the outDir

nest-cli.json
{
"collection": "@nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"assets": [
{
"include": "i18n/**/*",
"watchAssets": true,
+ "outDir": "dist/apps/api"
}
]
}
}

Module setup

src/app.module.ts
import { Module } from '@nestjs/common';
import * as path from 'path';
import { I18nModule } from 'nestjs-i18n';

@Module({
imports: [
I18nModule.forRoot({
fallbackLanguage: 'en',
loaderOptions: {
path: path.join(__dirname, '/i18n/'),
watch: true,
},
}),
],
controllers: [],
})
export class AppModule {}
caution

The I18nModule is a global module. This means you'll only need to register the module once (in the root module). After that it's accessible throughout the whole application.

Live reloading 🎉

Setting the watch option to true in the loaderOptions enables live reloading 🎉.

Add resolvers

Resolvers are used for getting the current language of our request. In basic web applications this is done via the Accept-Language header. But in many cases you want to override this language by your logged in user settings, or some header you define yourself.

nestjs-i18n comes with a set of built-in resolvers.

NameDefault value
QueryResolver['lang']
HeaderResolver[]
AcceptLanguageResolver{matchType: 'strict-loose'
CookieResolverlang
GraphQLWebsocketResolverN/A
GrpcMetadataResolver['lang']

To add resolvers add them to the resolvers array in your I18nModule options. The way nestjs-i18n works it's going to resolve the language in order. So in this case it tries the QueryResolver first, if it can't resolve a language it'll jump to the next one.

src/app.module.ts
import { Module } from '@nestjs/common';
import * as path from 'path';
import {
AcceptLanguageResolver,
I18nJsonLoader,
I18nModule,
QueryResolver,
} from 'nestjs-i18n';

@Module({
imports: [
I18nModule.forRoot({
fallbackLanguage: 'en',
loaderOptions: {
path: path.join(__dirname, '/i18n/'),
watch: true,
},
resolvers: [
{ use: QueryResolver, options: ['lang'] },
AcceptLanguageResolver,
],
}),
],
controllers: [],
})
export class AppModule {}
tip

It's possible to create your own resolvers! For example if you want to resolve the language from your logged-in user's settings. Please see the resolvers page for instructions.

Translate stuff 🎉

Now that we've setup everything we can start to do translations! The easiest way to do this is in your controller.

src/app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { I18n, I18nContext } from 'nestjs-i18n';

@Controller()
export class AppController {
@Get()
async getHello(@I18n() i18n: I18nContext) {
return await i18n.t('test.HELLO');
}
}