NestJS 根据浏览器语言传递静态文件
NestJS deliver static files based on language of browser
Nestjs 应该根据浏览器中定义的语言交付 Angular 应用程序。
Angular 应用程序位于 dist/public/en
或 dist/public/de
。
如果用户使用英文浏览器访问 /
,nestjs 应该从文件夹 dist/public/en
传送文件。在这种情况下,浏览器中的路径应指向 fqdn/en/
.
我已经用单一语言使用了这个 Angular 应用程序:
async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule);
app.useStaticAssets(join(__dirname, 'public'));
await app.listen(process.env.PORT || 3000);
}
bootstrap();
我还查看了 i18next,看起来很有希望。
但我不确定这是否是正确的方向。
热烈欢迎任何提示。
比静态提供 dist
文件夹更好的方法是将 all non-api 路由重定向到 index.html
以便您的 Angular SPA 可以处理路由。有关详细信息,请参阅 this answer。
您可以根据上面链接的答案调整中间件,方法是将您想要检测用户语言的因素考虑在内,例如ACCEPT-LANGUAGE
header 或某个 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'));
}
}
}
@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 传送文件,如果 运行 在开发模式而不是生产模式,则失败。
我会在那里搜索解决方案。
Nestjs 应该根据浏览器中定义的语言交付 Angular 应用程序。
Angular 应用程序位于 dist/public/en
或 dist/public/de
。
如果用户使用英文浏览器访问 /
,nestjs 应该从文件夹 dist/public/en
传送文件。在这种情况下,浏览器中的路径应指向 fqdn/en/
.
我已经用单一语言使用了这个 Angular 应用程序:
async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule);
app.useStaticAssets(join(__dirname, 'public'));
await app.listen(process.env.PORT || 3000);
}
bootstrap();
我还查看了 i18next,看起来很有希望。
但我不确定这是否是正确的方向。
热烈欢迎任何提示。
比静态提供 dist
文件夹更好的方法是将 all non-api 路由重定向到 index.html
以便您的 Angular SPA 可以处理路由。有关详细信息,请参阅 this answer。
您可以根据上面链接的答案调整中间件,方法是将您想要检测用户语言的因素考虑在内,例如ACCEPT-LANGUAGE
header 或某个 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'));
}
}
}
@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 传送文件,如果 运行 在开发模式而不是生产模式,则失败。
我会在那里搜索解决方案。