Security News
Input Validation Vulnerabilities Dominate MITRE's 2024 CWE Top 25 List
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
nestjs-i18n
Advanced tools
[![Build Status](https://travis-ci.org/ToonvanStrijp/nestjs-i18n.svg?branch=master)](https://travis-ci.org/ToonvanStrijp/nestjs-i18n) [![Greenkeeper badge](https://badges.greenkeeper.io/ToonvanStrijp/nestjs-i18n.svg)](https://greenkeeper.io/) [![Coverage
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.
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');
}
}
```
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 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 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.
The i18n module for Nest.
$ npm i --save nestjs-i18n
create a directory and in it define your language keys as directories.
i18n
├── en
│ ├── category.json
│ └── auth.json
└── nl
├── category.json
└── auth.json
The format of a 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
To use the translation service we first add the module. The I18nModule
has a @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 {}
import { Module } from '@nestjs/common';
import * as path from 'path';
import { I18nModule } from 'nestjs-i18n';
@Module({
imports: [
I18nModule.forRootAsync({
useFactory: (configService: ConfigurationService) => ({
path: configService.i18nPath,
fallbackLanguage: configService.fallbackLanguage, // e.g., 'en'
filePattern: configService.i18nFilePattern, // e.g., '*.i18n.json'
}),
inject: [ConfigurationService],
}),
],
controllers: [],
})
export class AppModule {}
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: [
{ use: QueryResolver, options: ['lang', 'locale', 'l'] },
HeaderResolver,
new CookieResolver(['lang', 'locale', 'l']),
],
}),
],
controllers: [HelloController],
})
export class AppModule {}
Currently, there are two built-in resolvers
Resolver | Default value |
---|---|
QueryResolver | none |
HeaderResolver | accept-language |
CookieResolver | lang |
To implement your own resolver (or custom logic) use the I18nResolver
interface. The resolvers are provided via the nestjs dependency injection, this way you can inject your own services if needed.
@Injectable()
export class QueryResolver implements I18nResolver {
constructor(@I18nResolverOptions() private keys: string[]) {}
resolve(req: any) {
let lang: string;
for (const key of this.keys) {
if (req.query != undefined && req.query[key] !== undefined) {
lang = req.query[key];
break;
}
}
return lang;
}
}
To provide initial options to your custom resolver use the @I18nResolverOptions()
decorator, also provide the resolver as followed:
I18nModule.forRoot({
path: path.join(__dirname, '/i18n/'),
fallbackLanguage: 'en',
saveMissing: false,
resolvers: [{ use: QueryResolver, options: ['lang', 'locale', 'l'] }],
});
I18nModule.forRootAsync({
useFactory: () => {
return {
path: path.join(__dirname, '/i18n'),
fallbackLanguage: 'en',
saveMissing: false,
};
},
resolvers: [{ use: QueryResolver, options: ['lang', 'locale', 'l'] }],
});
I18nLang
decorator and I18nService
@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' });
}
}
I18n
decorator@Controller()
export class SampleController {
@Get()
sample(@I18n() i18n: I18nContext) {
i18n.translate('HELLO_MESSAGE', { args: { id: 1, username: 'Toon' } });
i18n.translate('SETUP.WELCOME', { args: { id: 1, username: 'Toon' } });
i18n.translate('ARRAY.0');
}
}
No need to handle lang
manually.
I18nRequestScopeService
within a custom service using request scoped translation service@Injectable()
export class SampleService {
constructor(private readonly i18n: I18nRequestScopeService) {}
doFancyStuff() {
this.i18n.translate('HELLO_MESSAGE', { args: { id: 1, username: 'Toon' } });
this.i18n.translate('SETUP.WELCOME', { args: { id: 1, username: 'Toon' } });
this.i18n.translate('ARRAY.0');
}
}
To be used within other services like sending E-mails.
The advantage is that you don't have to worry about transporting lang
from the Request
to your service.
Use with caution! The I18nRequestScopeService
uses the REQUEST
scope and is no singleton.
This will be inherited to all consumers of I18nRequestScopeService
!
Read Nest Docs for more information.
Dont use I18nRequestScopeService
within controllers. The I18n
decorator is a much better solution.
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": ""
}
}
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.
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
FAQs
The i18n module for Nest.
The npm package nestjs-i18n receives a total of 94,030 weekly downloads. As such, nestjs-i18n popularity was classified as popular.
We found that nestjs-i18n demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.
Research
Security News
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.