【发布时间】:2021-05-04 12:20:49
【问题描述】:
我有一个 nestjs-graphql 项目。我使用class-validator 和nestjs-i18n 模块。
当按预期注入服务时,我可以使用i18nService。然而,我正在努力做的是在我的ExceptionFilter 中使用 i18n 从由class-validator 处理的ValidationPipe 返回翻译的消息
我目前拥有的
//app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ItemsModule } from './items/items.module';
import { GraphQLModule } from '@nestjs/graphql';
import { MongooseModule } from '@nestjs/mongoose';
import { ConfigModule } from '@nestjs/config';
import { I18nModule, I18nJsonParser } from 'nestjs-i18n';
import configuration from './config/configuration';
import * as path from 'path';
@Module({
imports: [
ConfigModule.forRoot({ isGlobal: true, load: [configuration] }),
MongooseModule.forRoot(process.env.MONGO_URI),
I18nModule.forRoot({
fallbackLanguage: 'en',
parser: I18nJsonParser,
parserOptions: { path: path.join(__dirname, '/i18n/') },
}),
GraphQLModule.forRoot({
autoSchemaFile: 'schema.gql',
playground: true,
introspection: true,
context: ({ req, connection }) =>
connection ? { req: connection.context } : { req },
}),
ItemsModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
//main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common';
import { AllExceptionsFilter } from './utils/exceptions.filters';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe({ transform: true }));
app.useGlobalFilters(new AllExceptionsFilter(new Logger('Exceptions')));
app.enableCors();
const port = process.env.PORT || 3000;
await app.listen(port);
}
bootstrap();
//AllExceptionFilters.ts
import {
ExceptionFilter,
Catch,
HttpException,
HttpStatus,
Logger,
} from '@nestjs/common';
import { ApolloError } from 'apollo-server-errors';
import { MongoError } from 'mongodb';
@Catch(HttpException)
export class AllExceptionsFilter implements ExceptionFilter {
constructor(private logger: Logger) {}
async catch(exception: HttpException) {
const status =
exception instanceof HttpException
? exception.getStatus()
: HttpStatus.INTERNAL_SERVER_ERROR;
const exceptionMessage = (exception) =>
exception instanceof MongoError
? exception?.message
: exception?.response?.message;
this.logger.error(exceptionMessage(exception), exception.stack);
throw new ApolloError(exceptionMessage(exception), status.toString());
}
}
我的想法是将 i18n 密钥传递给类以进行验证:
import { Field, InputType, } from '@nestjs/graphql';
import { Length } from 'class-validator';
@InputType()
export class ItemToValidate {
@Length(5, 30, { message: 'global.length' }) //i18n Key
@Field()
readonly title: string;
}
...在AllExceptionsFilter 中使用它,就像在服务中一样:
@Catch(HttpException)
export class AllExceptionsFilter implements ExceptionFilter {
constructor(private logger: Logger, private i18n: I18nService) {}
async catch(exception: HttpException) {
const status =
exception instanceof HttpException
? exception.getStatus()
: HttpStatus.INTERNAL_SERVER_ERROR;
const exceptionMessage = (exception) =>
exception instanceof MongoError
? exception?.message
: exception?.response?.message;
const translatedMessage = await this.i18n.translate(
exceptionMessage(exception),
);
...
}
}
但是,我在 boostrap 函数中实例化 Filter 类时出现逻辑错误,因为我不知道如何访问 I18nService 并从那里注入它:
async function bootstrap() {
const logger = new Logger('bootstrap');
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe({ transform: true }));
app.useGlobalFilters(new AllExceptionsFilter(new Logger('Exceptions'), /*I18nService ?*/ ));
}
bootstrap();
实现这一目标的最佳方法是什么?
【问题讨论】:
标签: internationalization nestjs class-validator nestjs-i18n