Type safety
@softkit/i18n
can generate types! This way your translations will be completely type safe! 🎉
Types Generator
To facilitate internationalization in your project, @softkit/i18n
provides a powerful CLI generator. It allows you to create types dynamically which ensures type safety for your translation keys.
Below is how you can configure @softkit/i18n
for your project:
import { I18nJsonLoader, I18nOptions } from '@softkit/i18n';
import * as path from 'path';
export const i18nOptions: I18nOptions = {
fallbackLanguage: 'en',
loaders: [
new I18nJsonLoader({
path: path.join(__dirname, '/i18n/'),
}),
],
};
Utilize the i18nOptions
in your module like this:
import { Module } from '@nestjs/common';
import { I18nModule } from '@softkit/i18n';
import { i18nOptions } from './i18n-options';
@Module({
imports: [I18nModule.forRoot(i18nOptions)],
controllers: [],
providers: [],
})
export class AppModule {}
Also, update your package.json
to include the i18n
configuration and scripts to generate types:
{
"scripts": {
"generate-types": "ts-node --project ./tsconfig.app.json ../../node_modules/@softkit/i18n/src/lib/cli.js generate-types -w",
"generate": "i18n generate-types -w -t json -p ./src/app/i18n/"
},
"i18n": {
"typesOutputPath": "./src/generated/i18n.generated.ts",
"optionsFile": "./src/app/i18n-options.ts"
}
}
Usage
To use the types within your code import the I18nTranslations
type from the generated file. Pass this type into the generic type properties of the I18nContext
or I18nService
.
import { Controller, Get } from '@nestjs/common';
import { I18n, I18nContext } from '@softkit/i18n';
import { I18nTranslations } from './generated/i18n.generated.ts';
@Controller()
export class AppController {
@Get()
async getHello(@I18n() i18n: I18nContext<I18nTranslations>) {
return await i18n.t('test.HELLO');
}
}
You can import the I18nPath
type so you require a valid i18n path in your code. This is useful when handling exceptions with translations.
import { I18nPath } from './generated/i18n.generated.ts';
export class ApiException extends Error {
get translation(): I18nPath {
return this.message as I18nPath;
}
get args(): any {
return this._args;
}
constructor(
key: I18nPath,
private readonly _args?: any,
) {
super(key);
}
}
For now type safety is optional and need to be enabled. We're planning to make a breaking change where type safety is enabled by default.
Type safety with DTOS
You can also use the generated types in your DTOs. This way you can reduce the chance of having a typo in your validation messages.
import { I18nTranslations } from './generated/i18n.generated.ts';
import { IsEmail, IsNotEmpty } from 'class-validator';
import { i18nValidationMessage } from '@softkit/i18n';
export class CreateUserDto {
@IsNotEmpty({
message: i18nValidationMessage<I18nTranslations>('validation.isNotEmpty'),
})
@IsEmail(
{},
{ message: i18nValidationMessage<I18nTranslations>('validation.isEmail') },
)
email: string;
@IsNotEmpty({
message: i18nValidationMessage<I18nTranslations>('validation.isNotEmpty'),
})
password: string;
}