工作原理

@lingo.dev/compiler 通过智能代码分析和 AI 驱动的翻译,在构建时将您的 React 应用转化为多语言应用。

构建时转换

传统的运行时 i18n 库(如 i18next、react-intl)在应用运行时加载翻译、插值变量并格式化消息。这会增加包体积、运行时开销和实现复杂度。

@lingo.dev/compiler 的工作方式不同:它在构建过程中转换您的代码。您的 React 组件保持简洁,翻译内容会被预编译为优化后的包。

结果: 零运行时开销、更小的包体积,无需手动管理翻译键。

流程说明

1. AST 分析

编译器使用 Babel 将您的 React 代码解析为抽象语法树(AST)。它遍历 JSX,识别可翻译内容:

  • 文本节点(<p>Hello</p>
  • 字符串属性(<img alt="Logo" />
  • 模板表达式中的文本(<p>Hello {name}</p>

编译器理解 React 组件边界,并维护上下文信息以确保翻译准确。技术标识符、代码片段和不可翻译元素会被自动过滤。

2. 内容提取

对于每个可翻译字符串,编译器会:

  • 生成稳定的哈希标识符
  • 保留组件上下文(文件、位置、周边元素)
  • 提取富文本结构(可处理嵌套元素,如 <strong><em>
  • 保持插值占位符

这些元数据会存储在 .lingo/metadata.json —— 一个用于追踪应用中所有可翻译内容的版本化文件中。

3. 翻译生成

在开发过程中,翻译服务器会按需处理翻译:

  • 伪翻译模式(默认):即时生成假翻译,便于查看哪些内容会被翻译且无需 API 成本
  • 真实翻译模式:调用您配置的 LLM 提供商(Lingo.dev Engine 或直接 LLM)

该翻译服务是无状态的,并能优雅地处理部分失败——即使部分翻译失败,仍会使用已缓存的翻译。

4. 代码注入

编译器会将翻译查找自动注入到你的 JSX 中:

// Your source code
<p>Hello {name}</p>

// Transformed code (simplified)
<p>{t('abc123', { name })}</p>

t() 函数经过优化并会自动注入。它会在预加载的翻译字典中基于哈希进行查找。

5. 包优化

构建时:

  • 会为每个语言环境生成独立的包
  • 只包含实际用到的翻译
  • 未使用的翻译会被消除(dead code elimination)
  • 字典会按组件进行 tree-shaking

开发工作流

开发模式

{
  dev: {
    usePseudotranslator: true,
  }
}

当你运行 npm run dev 时:

  1. 编译器会启动一个翻译服务器(自动查找 60000-60099 端口)
  2. 你的应用会向服务器请求翻译
  3. 伪翻译器会即时生成假翻译
  4. 翻译会缓存在 .lingo/metadata.json
  5. HMR 正常工作——状态会被保留

开发小部件(如启用)允许你在浏览器中编辑翻译并实时查看更改。

生产模式

{
  buildMode: "cache-only",
}

当你运行 npm run build 时:

  1. 不会启动翻译服务器
  2. 只会使用 .lingo/metadata.json 中的缓存翻译
  3. 如果有翻译缺失,构建会失败并给出明确错误
  4. 不会发起 API 调用——无需 API key

为什么只用缓存? 在生产环境下,你需要确定性的构建。翻译应在 CI 阶段(有 API key)生成,而不是在生产构建时生成。

推荐工作流

本地开发:

  • 使用伪翻译器
  • 快速反馈
  • 无 API 成本

CI/CD:

{
  buildMode: "translate",
  dev: {
    usePseudotranslator: false,
  }
}
  • 生成真实翻译
  • 每次部署时运行一次
  • 提交 .lingo/ 变更

生产构建:

{
  buildMode: "cache-only",
}
  • 使用预生成的翻译
  • 无需 API 密钥
  • 构建速度快且结果可预测

架构

编译器围绕关注点分离进行组织:

元数据管理器

  • 针对 .lingo/metadata.json 进行 CRUD 操作
  • 文件锁保证线程安全
  • 基于哈希的翻译标识符

翻译服务

  • 协调翻译工作流
  • 处理缓存策略
  • 管理部分失败情况
  • 返回成功和失败的翻译结果

翻译器(无状态)

  • 伪翻译器:即时生成假翻译
  • LCP Translator:集成 Lingo.dev 引擎
  • LLM Translator:直接集成第三方服务商
  • 不自带缓存——由服务层统一处理

翻译服务器

  • 用于开发的 HTTP 服务器
  • 支持 WebSocket 实时小部件更新
  • 自动端口管理
  • 批量请求处理

实现细节请参见 源代码架构文档

框架集成

Next.js

编译器通过 withLingo() 封装集成:

  • 支持 Webpack 和 Turbopack
  • 兼容 React Server Components
  • 异步配置,支持插件懒加载
  • 自动基于 locale 的路由(如已配置)

Vite

编译器通过 lingoCompilerPlugin 集成:

  • 基于 unplugin(兼容 Vite、Webpack、Rollup)
  • 完全支持 HMR
  • 高效的开发服务器集成
  • 自动生成虚拟模块

常见问题

支持 Server Components 吗? 支持。在 Next.js 中,编译器会转换 Server 和 Client Components。翻译查找可同构运行。

如何处理代码分割? 翻译会随组件自动分割。每个 chunk 只包含所需的翻译内容。

翻译如何缓存? 所有翻译都存储在 .lingo/metadata.json 文件中。该文件受版本控制,作为翻译缓存。编译器采用内容哈希,只有新增或变更的文本才会触发重新翻译。

如果翻译失败怎么办? 服务会返回部分结果。成功的翻译会被缓存并直接使用,错误会带有上下文记录到日志以便调试。您的应用不会崩溃——它会回退到已缓存的翻译或源文本。

我可以查看转换后的代码吗? 可以。在构建输出中,查找已转换的文件。转换非常轻量——仅包含 t() 函数调用和基于哈希的查找。

后续步骤