toonvanstrijp / nestjs-i18n

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

Resolvers not working when using I18nService in class constructor #554

Closed pedrocosta012 closed 10 months ago

pedrocosta012 commented 10 months ago

Describe the bug

When using someClassMethod(@I18n() methodName: I18nContext) the resolvers work perfectly as they should, however when using constructor(private readonly i18n: I18nService) the resolvers have no effect

Reproduction

// app.module.ts

import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import {
    AcceptLanguageResolver,
    HeaderResolver,
    I18nModule,
    QueryResolver,
} from 'nestjs-i18n';
import * as path from 'path';
import { env } from 'src/config/env';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TokenMiddleware } from './app.middleware';

@Module({
    imports: [
        I18nModule.forRoot({
            fallbackLanguage: 'pt_br',
            loaderOptions: {
                path: path.join(__dirname, '../../i18n/'),
                watch: true,
            },
            resolvers: [
                new HeaderResolver(['x-lang']),
                new QueryResolver(['lang']),
                AcceptLanguageResolver,
            ],
        }),
        JwtModule.register({
            global: true,
            secret: env.jwtSecret,
            signOptions: { expiresIn: env.jwtExpiresIn },
        }),
    ],
    controllers: [AppController],
    providers: [AppService],
})
export class AppModule implements NestModule {
    configure(consumer: MiddlewareConsumer) {
        consumer.apply(TokenMiddleware).forRoutes('*');
    }
}

// app.middleware.ts

import { Injectable, NestMiddleware } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { isJWT } from 'class-validator';
import { NextFunction, Request, Response } from 'express';
import { I18nService } from 'nestjs-i18n';
import { env } from 'src/config/env';

@Injectable()
export class TokenMiddleware implements NestMiddleware {
    constructor(
        private readonly jwtService: JwtService,
        private readonly i18n: I18nService, // it doesn't work with resolvers
    ) {}

    use(req: Request, res: Response, next: NextFunction) {
        if (!req.headers?.authorization) {
            return res.status(400).json({
                statusCode: 400,
                error: 'bad request',
                message: this.i18n.t('error.missingToken'),
            });
        }
        if (!isJWT(req.headers.authorization)) {
            return res.status(401).json({
                statusCode: 401,
                error: 'Unauthorized',
                message: this.i18n.t('error.invalidToken'),
            });
        }
        req.body.userTokenData = this.jwtService.verify(
            req.headers.authorization,
            { secret: env.jwtSecret },
        );
        next();
    }
}

// app.controller.ts

import { Body, Controller, Get, UnauthorizedException } from '@nestjs/common';
import { I18n, I18nContext } from 'nestjs-i18n';

import { AppService } from './app.service';
import { UserDataBody } from '../user/dtos/user.dtos';

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

    @Get()
    getHello(
        @Body() body: UserDataBody, 
        @I18n() i18n: I18nContext, // it works with 
    ): string {
        console.log(body);
        throw new UnauthorizedException(i18n.t('error.invalidEmail'));
    }
}

System Info

System:
    OS: Linux 6.4 Pop!_OS 22.04 LTS
    CPU: (4) x64 Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz
    Memory: 1021.43 MB / 7.54 GB
    Container: Yes
    Shell: 5.8.1 - /usr/bin/zsh
  Binaries:
    Node: 18.17.0 - ~/.nvm/versions/node/v18.17.0/bin/node
    Yarn: 1.22.19 - ~/.nvm/versions/node/v18.17.0/bin/yarn
    npm: 9.8.1 - ~/.nvm/versions/node/v18.17.0/bin/npm
  Browsers:
    Chrome: 116.0.5845.140

Used Package Manager

yarn

Validations

pedrocosta012 commented 10 months ago

Is this indeed a bug or did i do something wrong?

pedrocosta012 commented 10 months ago

I reopened the issue just because of the doubt in case changing the "lang" using resolvers has no effect on I18nService

pedrocosta012 commented 10 months ago

I just saw that to use the dynamic language you just need to get it directly from the context as you can see at https://nestjs-i18n.com/quick-start I apologize for the inconvenience and hope this issue can serve as a reference for future library beginners.