Angular 19 SSR集成i18n报错,寻求标准集成方案
Angular 19 SSR 与 i18n 集成问题
此前按照《Angular 17: SSR with i18n alongside》的步骤实现了 SSR 与 i18n 集成,升级至 Angular 19 后该方案失效。修改 proxy-server.mjs(代码如下)后,出现错误:TypeError: Cannot read properties of undefined (reading 'method')。请问 Angular 19 是否有标准的 i18n 集成方式?
import serverEn from './server/en/server.mjs'; import serverFr from './server/fr/server.mjs'; const express = require('express'); function getPreferredLanguage(req) { const acceptedLanguages = req.acceptsLanguages(['fr', 'en']); return acceptedLanguages || 'fr'; // Default to 'fr' if no match is found } function run() { const port = process.env.PORT || 4000; const server = express(); // Redirect root requests to the preferred language server.get('/', (req, res) => { const lang = getPreferredLanguage(req); res.redirect(`/${lang}`); }); // Serve the language-specific servers server.use('/fr', serverFr()); server.use('/en', serverEn()); // Handle unmatched routes server.use((req, res) => { res.status(404).send('Page not found'); }); server.listen(port, () => { console.log(`Node Express server listening on http://localhost:${port}`); }); } run();
先解决当前错误问题
你遇到的 TypeError 是因为 Angular 19 调整了 SSR 服务器的导出格式:语言包的 server.mjs 不再导出可直接调用的函数,而是导出一个 app 对象,需直接传给 server.use,不能加括号调用。同时建议统一使用 ES 模块语法,避免混合 CommonJS 和 ES 模块导致的冲突。
修改后的 proxy-server.mjs 代码:
import { app as serverEn } from './server/en/server.mjs'; import { app as serverFr } from './server/fr/server.mjs'; import express from 'express'; function getPreferredLanguage(req) { const acceptedLanguages = req.acceptsLanguages(['fr', 'en']); return acceptedLanguages || 'fr'; } function run() { const port = process.env.PORT || 4000; const server = express(); server.get('/', (req, res) => { const lang = getPreferredLanguage(req); res.redirect(`/${lang}`); }); // 直接使用导出的 app 对象,无需调用函数 server.use('/fr', serverFr); server.use('/en', serverEn); server.use((req, res) => { res.status(404).send('Page not found'); }); server.listen(port, () => { console.log(`Node Express server listening on http://localhost:${port}`); }); } run();
Angular 19 标准的 i18n + SSR 集成方式
Angular 19 内置了更简化的多语言 SSR 支持,无需手动编写代理服务器,步骤如下:
1. 配置 angular.json
在项目配置中定义多语言构建目标,确保每个语言的客户端和 SSR 构建都启用本地化:
"projects": { "your-app": { "i18n": { "sourceLocale": "fr", "locales": { "en": "src/locale/messages.en.xlf" } }, "architect": { "build": { "configurations": { "en": { "localize": ["en"], "outputPath": "dist/your-app/en" }, "fr": { "localize": ["fr"], "outputPath": "dist/your-app/fr" } } }, "server": { "configurations": { "en": { "localize": ["en"], "outputPath": "dist/your-app/server/en" }, "fr": { "localize": ["fr"], "outputPath": "dist/your-app/server/fr" } } } } } }
2. 构建多语言包
运行命令构建所有语言的客户端和 SSR 代码:
ng build --configuration=en,fr ng run your-app:server --configuration=en,fr
3. 统一启动多语言 SSR
使用 @angular/ssr 提供的工具创建统一服务器入口,自动处理语言路由:
import { ngExpressEngine } from '@angular/ssr'; import express from 'express'; import { join } from 'path'; import { AppServerModule } from './src/main.server'; import { APP_BASE_HREF, LOCALE_ID } from '@angular/common'; const app = express(); const port = process.env.PORT || 4000; const locales = ['fr', 'en']; // 为每个语言配置静态文件和 SSR 渲染 locales.forEach(locale => { const browserDist = join(process.cwd(), `dist/your-app/${locale}/browser`); const serverDist = join(process.cwd(), `dist/your-app/server/${locale}`); // 托管静态资源 app.use(`/${locale}`, express.static(browserDist, { maxAge: '1y' })); // 配置 SSR 引擎 app.engine('html', ngExpressEngine({ bootstrap: AppServerModule, providers: [ { provide: APP_BASE_HREF, useValue: `/${locale}` }, { provide: LOCALE_ID, useValue: locale } ] })); app.set('view engine', 'html'); app.set('views', serverDist); // 处理语言路由下的所有请求 app.get(`/${locale}/*`, (req, res) => { res.render('index', { req, res, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] }); }); }); // 根路径重定向到首选语言 app.get('/', (req, res) => { const preferredLang = req.acceptsLanguages(locales) || 'fr'; res.redirect(`/${preferredLang}`); }); app.listen(port, () => { console.log(`Server listening on http://localhost:${port}`); });
4. 启动服务器
运行上述入口文件即可,无需手动维护多个语言的服务器实例,完全遵循 Angular 官方规范,后续版本升级兼容性更强。
内容的提问来源于stack exchange,提问作者mbagiella
相关产品推荐
相关产品推荐

