【问题标题】:NestJS deliver static files based on language of browserNestJS 根据浏览器的语言传递静态文件
【发布时间】:2019-09-25 07:57:42
【问题描述】:

Nestjs 应该基于浏览器中定义的语言交付一个 Angular 应用程序。

Angular 应用程序位于dist/public/endist/public/de

如果用户使用英文浏览器访问/,nestjs 应该从文件夹dist/public/en 传送文件。在这种情况下,浏览器中的路径应指向fqdn/en/

我已经在单语言 Angular App 中使用了它:

async function bootstrap() {
  const app = await NestFactory.create<NestExpressApplication>(AppModule);

  app.useStaticAssets(join(__dirname, 'public'));
  await app.listen(process.env.PORT || 3000);
}
bootstrap();

我还查看了i18next,看起来很有希望。

但我不确定这是否是正确的方向。

热烈欢迎任何提示。

【问题讨论】:

    标签: javascript node.js angular nestjs i18next


    【解决方案1】:

    比静态提供 dist 文件夹更好的方法是将 所有 非 API 路由重定向到 index.html,以便您的 Angular SPA 可以处理路由.详情请见this answer


    您可以通过考虑要检测用户语言的因素来调整上面链接答案中的中间件,例如ACCEPT-LANGUAGE 标头或某个 cookie:

    @Middleware()
    export class FrontendMiddleware implements NestMiddleware {
      use(req: Request, res: Response, next: Function) {
        // Some way of detecting the user's language
        const languages = req.header('ACCEPT-LANGUAGE') || 'en-US';
    
        if (languages.contains('de-DE')) {
          res.sendFile(join(__dirname, 'public', 'de' ,'index.html'));
        } else {
          res.sendFile(join(__dirname, 'public', 'en', 'index.html'));
        }
      }
    }
    

    【讨论】:

      【解决方案2】:

      @kim-kern 非常感谢您的回答。它把我推向了正确的方向。

      我现在通过以下方式解决了这个问题: maint.ts 将基于全局中间件进行语言检测,并定义文件的静态传递:

      import { NestFactory } from '@nestjs/core';
      import { AppModule } from './app.module';
      import * as compression from 'compression';
      import { NestExpressApplication } from '@nestjs/platform-express';
      import { join } from 'path';
      const i18next = require('i18next');
      const middleware = require('i18next-http-middleware');
      
      async function bootstrap() {
        const app = await NestFactory.create<NestExpressApplication>(AppModule);
      
        i18next.use(middleware.LanguageDetector).init({
          detection: {
            order: ['path', 'session', 'querystring', 'cookie', 'header'],
          },
        });
      
        app.use(
          middleware.handle(i18next, {
            ignoreRoutes: ['/api'],
            removeLngFromUrl: false,
          }),
        );
      
        app.useStaticAssets(join(__dirname, 'public'));
        app.use(compression());
        await app.listen(process.env.PORT || 3000);
      }
      bootstrap();
      

      我定义了一个自定义中间件,用于检查找到的语言并根据 baseUrl 提供正确的 index.html 文件:

      import { NestMiddleware, Injectable } from '@nestjs/common';
      import { Request, Response } from 'express';
      import { join } from 'path';
      
      @Injectable()
      export class FrontendMiddleware implements NestMiddleware {
        use(req: any, res: Response, next: Function) {
          if (req.lng && !req.baseUrl && req.lng.startsWith('de')) {
            res.sendFile(join(__dirname, 'public', 'de', 'index.html'));
          } else if (!req.baseUrl) {
            res.sendFile(join(__dirname, 'public', 'en', 'index.html'));
          } else {
            next();
          }
        }
      }
      

      然后将自定义中间件包含在 app.module.ts 中:

      ...
      export class AppModule implements NestModule {
        configure(consumer: MiddlewareConsumer): void {
          consumer.apply(FrontendMiddleware).forRoutes({
            path: '/**',
            method: RequestMethod.ALL,
          });
        }
      }
      

      现在唯一存在的问题是它总是尝试从固定目录 public 传递文件,如果在开发模式而不是生产模式下运行,则会失败。

      我会在那里寻找解决方案。

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-08
      • 1970-01-01
      • 2018-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-21
      • 2015-02-19
      相关资源
      最近更新 更多