ExpressJS - 国际化 (i18n)
Express.js - 现代国际化 (i18n)
Section titled “Express.js - 现代国际化 (i18n)”国际化,通常缩写为 i18n,是指在不进行工程更改的情况下,设计软件应用程序以使其能够适应各种语言和地区的过程。本教程将演示如何在现代 Express.js 应用程序中实现 i18n。
我们将使用一套强大且流行的库来处理翻译:
- i18next:核心 i18n 框架,提供主要的翻译功能。
- i18next-http-middleware:一个现代的中间件,用于检测用户语言并将 i18n 功能集成到 Express 的请求和响应中。
- i18next-fs-backend:i18next 的一个后端模块,用于从本地文件系统加载翻译资源。
首先,初始化一个新的 Node.js 项目,并安装 Express 和所需的 i18n 模块。
# 1. Create a new project directorymkdir express-i18n-example && cd express-i18n-example
# 2. Initialize a Node.js projectnpm init -y
# 3. Install dependenciesnpm install express i18next i18next-http-middleware i18next-fs-backend创建翻译文件
Section titled “创建翻译文件”以结构化的方式组织你的翻译文件。一种常见的做法是创建一个 locales 目录,并在其中为每种语言创建子目录。
项目文件夹结构
Section titled “项目文件夹结构”.├── locales/│ ├── en/│ │ └── translation.json│ └── fr/│ └── translation.json├── node_modules/├── index.js└── package.jsonlocales/en/translation.json
Section titled “locales/en/translation.json”{ "welcome": "Welcome to our modern Express application!", "greeting": "Hello, {{name}}! We are glad to have you here."}locales/fr/translation.json
Section titled “locales/fr/translation.json”{ "welcome": "Bienvenue dans notre application Express moderne !", "greeting": "Bonjour, {{name}} ! Nous sommes ravis de vous avoir ici."}初始化和使用 i18next
Section titled “初始化和使用 i18next”现在,让我们在主应用程序文件 index.js 中配置 i18next 并应用其中间件。
// index.jsimport express from 'express';import i18next from 'i18next';import Backend from 'i18next-fs-backend';import middleware from 'i18next-http-middleware';
// 初始化 i18nexti18next .use(Backend) // 从文件系统加载翻译 .use(middleware.LanguageDetector) // 从请求中检测用户语言 .init({ fallbackLng: 'en', backend: { loadPath: './locales/{{lng}}/translation.json', }, detection: { order: ['querystring', 'cookie', 'header'], caches: ['cookie'], lookupQuerystring: 'lang', // e.g., /?lang=fr lookupCookie: 'i18next', }, // 建议对值进行转义以防止 XSS 攻击 // 如果不使用已执行此操作的前端库。 interpolation: { escapeValue: true } });
const app = express();const PORT = process.env.PORT || 3000;
// 应用 i18next 中间件app.use(middleware.handle(i18next));
// --- 路由 ---app.get('/', (req, res) => { // t 函数由中间件添加到 req 对象中 res.status(200).send(req.t('welcome'));});
app.get('/greet/:name', (req, res) => { const { name } = req.params; res.status(200).send(req.t('greeting', { name }));});
// 基本错误处理app.use((err, req, res, next) => { console.error(err.stack); res.status(500).send('Something broke!');});
app.listen(PORT, () => { console.log(`Server is running on http://localhost:${PORT}`);});关键配置说明
Section titled “关键配置说明”import语法:我们使用现代 ES6 模块语法。要启用此功能,请在package.json文件中添加"type": "module"。.use(Backend):配置i18next-fs-backend以读取翻译 JSON 文件。.use(middleware.LanguageDetector):这个强大的检测器通过检查(按顺序)查询字符串参数 (?lang=fr)、cookie 和Accept-LanguageHTTP 头来自动查找用户首选语言。fallbackLng: 'en':如果在检测到的语言中找不到翻译键,它将回退到英语。app.use(middleware.handle(i18next)):这是将i18next集成到 Express 请求-响应生命周期的关键步骤,使req.t()函数在所有后续路由中可用。
测试应用程序
Section titled “测试应用程序”使用 node index.js 运行你的服务器。现在你可以测试不同的语言输出了。
- 默认(英语):打开你的浏览器或使用 curl:
curl http://localhost:3000/ - 通过查询字符串设置法语:
curl "http://localhost:3000/?lang=fr" - 英语问候语:
curl http://localhost:3000/greet/Alex - 法语问候语:
curl "http://localhost:3000/greet/Alex?lang=fr"
常见错误和调试
Section titled “常见错误和调试”- 翻译未加载:仔细检查
i18next.init()配置中的loadPath。确保它正确指向相对于你运行 Node 进程的locales目录。 req.t is not a function:此错误表示i18next-http-middleware配置不正确或放置在你的路由之后。确保app.use(middleware.handle(i18next));在定义任何路由之前调用。- ESM
import语法错误:如果你看到类似SyntaxError: Cannot use import statement outside a module的错误,请确保你已在package.json文件中添加了"type": "module"。