EJS
使用 Lingo.dev CLI 对 EJS 模板进行 AI 翻译
什么是 EJS?
EJS(Embedded JavaScript,嵌入式 JavaScript)是一种简单的模板语言,可以让你用纯 JavaScript 生成 HTML 标记。它通常用于 Node.js 应用的服务端渲染。
什么是 Lingo.dev CLI?
Lingo.dev CLI 是一个免费的开源命令行工具,用于通过 AI 翻译应用和内容。它旨在替代传统的翻译管理软件,并可集成到现有的开发流水线中。
了解更多信息,请参见 概述。
关于本指南
本指南将介绍如何使用 Lingo.dev CLI 翻译 EJS 模板。
你将学习如何:
- 从零创建项目
- 配置翻译流水线
- 使用 AI 生成翻译
前置条件
要使用 Lingo.dev CLI,请确保已安装 Node.js v18 及以上版本:
❯ node -v
v22.17.0
步骤 1. 创建项目
在你的项目目录下,创建一个 i18n.json 文件:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.10",
"locale": {
"source": "en",
"targets": ["es"]
},
"buckets": {}
}
该文件定义了翻译流水线的行为,包括需要翻译的语言以及本地化内容在文件系统中的位置。
要了解更多可用属性,请参见 i18n.json。
步骤 2. 配置源语言区域
源语言区域 是指你的内容最初编写时所用的语言和地区。要配置源语言区域,请在 i18n.json 文件中设置 locale.source 属性:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.10",
"locale": {
"source": "en",
"targets": ["es"]
},
"buckets": {}
}
源语言区域必须以 BCP 47 语言标签 的形式提供。
如需查看 Lingo.dev CLI 支持的所有语言区域代码,请参见 支持的语言区域代码。
步骤 3. 配置目标语言区域
目标语言区域 指的是您希望将内容翻译成的语言和地区。要配置目标语言区域,请在 locale.targets 属性中设置,并写入 i18n.json 文件:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.10",
"locale": {
"source": "en",
"targets": ["es"]
},
"buckets": {}
}
步骤 4. 创建源内容
如果尚未创建,请新建一个或多个包含待翻译内容的 EJS 模板文件。这些文件的路径中必须包含源语言区域(例如,作为目录名 en/,或作为文件名的一部分 messages.en.ejs)。
对于 EJS 模板,可翻译内容包括:
- HTML 元素内的文本内容
- 属性值(alt 文本、标题、标签、占位符、按钮值)
- JavaScript alert() 或其他字符串字面量中的文本
EJS 模板标签(<%= %>、<%- %>、<% %>)和变量名在翻译过程中会被保留。
例如:
<!DOCTYPE html>
<html lang="en">
<head>
<title><%= pageTitle %></title>
</head>
<body>
<h1>Welcome back!</h1>
<p>Hello, <%= user.name %>! You have <%= messageCount %> new messages.</p>
<form action="/login" method="post">
<label for="username">Username:</label>
<input type="text" id="username" placeholder="Enter username">
</form>
</body>
</html>
步骤 5. 创建 bucket
-
在
i18n.json文件中,向buckets对象添加一个"ejs"对象:{ "$schema": "https://lingo.dev/schema/i18n.json", "version": "1.10", "locale": { "source": "en", "targets": ["es"] }, "buckets": { "ejs": {} } } -
在
"ejs"对象中,定义一个或多个include模式的数组:{ "$schema": "https://lingo.dev/schema/i18n.json", "version": "1.10", "locale": { "source": "en", "targets": ["es"] }, "buckets": { "ejs": { "include": ["./[locale]/example.ejs"] } } }这些模式用于定义需要翻译的文件。
模式本身:
- 必须包含
[locale]作为已配置语言区域的占位符 - 可以指向文件路径(如
"[locale]/config.ejs") - 可以使用星号作为通配符(如
"[locale]/*.ejs")
不支持递归 glob 模式(如
**/*.ejs)。 - 必须包含
步骤 6. 配置 LLM
Lingo.dev CLI 使用大型语言模型(LLM)通过 AI 翻译内容。要使用这些模型,您需要从支持的服务商获取 API 密钥。
为尽快开始使用,我们推荐选择 Lingo.dev Engine —— 我们自有的托管平台,每月可免费使用 10,000 个 token:
-
运行以下命令:
npx lingo.dev@latest login这将打开您的默认浏览器,并要求您进行身份验证。
-
按提示操作。
步骤 7. 生成翻译内容
在包含 i18n.json 文件的目录下,运行以下命令:
npx lingo.dev@latest run
该命令将:
- 读取
i18n.json文件。 - 查找需要翻译的文件。
- 提取文件中的可翻译内容。
- 使用已配置的 LLM 翻译提取的内容。
- 将翻译后的内容写回文件系统。
首次生成翻译时,会创建一个 i18n.lock 文件。该文件用于记录已翻译的内容,防止后续运行时重复翻译。
示例
en/example.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<title><%= pageTitle %></title>
</head>
<body>
<% if (user) { %>
<h1>Welcome back!</h1>
<p>Hello, <%= user.name %>! You have <%= messageCount %> new messages.</p>
<% } else { %>
<h1>Please log in</h1>
<form action="/login" method="post">
<label for="username">Username:</label>
<input type="text" id="username" placeholder="Enter username">
<button type="submit">Sign In</button>
</form>
<% } %>
</body>
</html>
es/example.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<title><%= pageTitle %></title>
</head>
<body>
<% if (user) { %>
<h1>¡Bienvenido de nuevo!</h1>
<p>Hola, <%= user.name %>! Tienes <%= messageCount %> nuevos mensajes.</p>
<% } else { %>
<h1>Por favor, inicia sesión</h1>
<form action="/login" method="post">
<label for="username">Nombre de usuario:</label>
<input type="text" id="username" placeholder="Enter username">
<button type="submit">Iniciar sesión</button>
</form>
<% } %>
</body>
</html>
i18n.json
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.10",
"locale": {
"source": "en",
"targets": ["es"]
},
"buckets": {
"ejs": {
"include": ["./[locale]/example.ejs"]
}
}
}
i18n.lock
version: 1
checksums:
21b99a2aea148b309f95ec2c966d326c:
text_0: e4d2da607604b3fda41eef5e0dd35faa
text_1: 69eb28c44f7168b1df0455ad2a62588c
text_2: bff335b01588a8db802bd193c725ec11
text_3: 0744639a7ac440afe0d792ea79c54512
text_4: b4cc462fb3a00d2f60deefe548c10a33
text_5: d0fd310aef9cf3c5827f1db4b0c098a1
text_6: 85bb1f6fb66b5ab65a9c61469183236e
text_7: bdbc827b3d224e03394dfd56304500f2
text_8: 5e8497af456decf6cf716c0a23f1dbc2
text_9: d572e25ed81420669e65c03925da1001
text_10: 2cf6537fb69cdd2eb030e55bf4223b93
text_11: ec7b8f314fe9bc6591006707484ede61
text_12: c2460fb2a7887fdf2d68db2b553a4338
text_13: 3abe623951250bd24a9d7799415761ab
text_14: 988be328b82702586f2cd541858710fe
text_15: b2328773b0ef0699fd5791055c5cf9e2
text_16: 92acabd12cd9b63c825294c54fcbc806