【问题标题】:Nest js : Use I18n service in Exception FilterNest js:在异常过滤器中使用 I18n 服务
【发布时间】:2021-05-04 12:20:49
【问题描述】:

我有一个 nestjs-graphql 项目。我使用class-validatornestjs-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


    【解决方案1】:

    docs 所示,如果您使用useGlobalFilters() 注册过滤器,则无法进行依赖注入。

    相反,您必须这样做:

    import { Module } from '@nestjs/common';
    import { APP_FILTER } from '@nestjs/core';
    
    @Module({
      providers: [
        {
          provide: APP_FILTER,
          useClass: AllExceptionsFilter,
        },
      ],
    })
    export class AppModule {}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-08
      • 2021-11-05
      • 1970-01-01
      • 2017-06-29
      • 1970-01-01
      • 1970-01-01
      • 2021-10-27
      相关资源
      最近更新 更多