toonvanstrijp / nestjs-i18n

The i18n module for nestjs.
https://nestjs-i18n.com
Other
642 stars 106 forks source link

Translation not working using i18nService #497

Closed n1rjal closed 1 year ago

n1rjal commented 1 year ago

Hi, I am using i18n service in Nestjs and the translating part is not working when I use i18nService.t() implementation Here is my code. The version I am using are

...
"nestjs-i18n": "^10.2.6",
"@nestjs/common": "^8.4.7",
"@nestjs/core": "^8.4.7",
...

i18n.module.ts


@Global()
@Module({
  imports: [
    I18nModule.forRoot({
      fallbackLanguage: "en",
      fallbacks: {
        "np-*": "np",
        "en-*": "en",
      },
      loaderOptions: {
        watch: true,
        path: join(__dirname, "../../../src/resources/i18n/"),
        includeSubfolders: true,
      },
      typesOutputPath: join(__dirname, "../../../../src/i18n.generated.ts"),
      logging: true,
      resolvers: [
        { use: QueryResolver, options: ["lang"] },
        new QueryResolver(["lang"]),
        AcceptLanguageResolver,
      ],
    }),
  ],
  exports: [I18nModule],
})
export class NestI18nModule {}

app.controller.ts

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(@I18n() i18nContext: I18nContext) {
    return this.appService.getHello(i18nContext);
  }
}

app.service.ts

@Injectable()
export class AppService {
  constructor(private readonly i18n: I18nService<I18nTranslations>) {}

  getHello(i18n: I18nContext): string {
    console.log(i18n.t("generic.youWantFreeFood"));                   // Vous voulez des aliments gratuits? <- Works
    console.log(this.i18n.t("generic.youWantFreeFood"));           // You want free food? <- Doesnot work
    return this.i18n.t("generic.youWantFreeFood");
  }
}

main.ts

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.use(I18nMiddleware);
  app.enableCors({
    origin: "*",
  });

  app.useGlobalPipes(
    new ValidationPipe({
      transform: true,
      stopAtFirstError: true,
      exceptionFactory,
      transformOptions: {
        enableImplicitConversion: false,
      },
    }),
  );

  await app.listen(3000);

}
bootstrap();
tuphamdev96 commented 1 year ago

+1 the same problem

vigor-13 commented 1 year ago

+1 the same problem

rubiin commented 1 year ago

Before 10, you can use I18nRequestScopeService. But as of version 10 and above, I18nRequestScopeService is removed . This because we now have async_hooks support. This allows you to get the current I18nContext by doing I18nContext.current(). That being said, you can follow here for translation for services https://github.com/toonvanstrijp/nestjs-i18n/blob/main/samples/simple/src/app.service.ts. Feel free to open if the issue persists

jskrajna commented 5 months ago

@rubiin that resolution clearly works, but I wonder if there's away to setting by default language from context. Is it a way to set it globally and not having to set it individually for every translation declaration ?

fr6nco commented 4 months ago

Hi I assume this issue is related to the nestjs mailer not translating the emails as the i18nService is passed down in the module init.

MailerModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService, I18nService],
      useFactory: (configService: ConfigService, i18n: I18nService) => ({
        transport: {
          host: configService.get('MAILER_HOST'),
          port: +configService.get('MAILER_PORT'),
          secure: false,
          auth: {
            user: configService.get('MAILER_USER') ?? undefined,
            pass: configService.get('MAILER_PASS') ?? undefined,
          },
        },
        defaults: {
          from: configService.get('MAILER_FROM'),
        },
        preview: configService.get('MAILER_PREV') === 'true',
        template: {
          dir:
            configService.get('MAILER_TEMPLATES_DIR') ??
            process.cwd() + '/src/templates',
          adapter: new HandlebarsAdapter({ t: i18n.hbsHelper }),
          options: {
            strict: true,
          },
        },
        options: {
          partials: {
            dir:
              configService.get('MAILER_PARTIALS_DIR') ??
              process.cwd() + '/src/templates/partials',
          },
        },
      }),
    }),

This is the definition of the mailer module.

in my controller

  @Post('create')
  create(
    @Body() orderCreatedContext: OrderCreatedMailContext,
    @I18n() i18nContext: I18nContext,
  ) {
    this.logger.debug(orderCreatedContext);
    console.log(i18nContext.t('order.MAIL_SUBJECT'));
    console.log(i18nContext.lang);
    this.mailerService.sendMail({
      to: orderCreatedContext.body.billing_address.email,
      from: this.configService.get('MAILER_FROM'),
      subject: i18nContext.translate('order.MAIL_SUBJECT'),
      template: './order-create',
      context: orderCreatedContext,
    });
  }

when I send a request with x-lang set, the i18nContext.t and .lang resolves fine, but the email is sent out in the fallback locale.

I beleive this is a bug.