documenso国际化翻译工作流:Crowdin配置与协作
引言:多语言支持的开发痛点与解决方案
在全球化协作日益普遍的今天,文档管理系统的多语言支持已成为企业级应用的核心需求。documenso作为一款支持Markdown和Wiki语法的文档管理系统,其国际化架构面临三大挑战:如何高效提取分散在代码中的文本、如何实现翻译团队与开发团队的无缝协作、以及如何确保翻译内容的版本一致性。本文将系统拆解documenso基于Crowdin与Lingui构建的国际化工作流,包括配置细节、自动化流程与协作最佳实践,帮助开发团队快速落地企业级i18n方案。
技术架构概览:工具链与工作流设计
documenso国际化架构采用"提取-翻译-集成"的闭环设计,核心由三大组件构成:
- Lingui.js:负责代码中可翻译文本的提取与运行时国际化
- Crowdin:提供翻译管理平台与译者协作环境
- GitHub Actions:自动化翻译文件的同步与集成
三者协作流程如下:
核心技术选型对比
工具 | 优势 | 局限性 | 应用场景 |
---|---|---|---|
Lingui.js | 支持React组件语法、ICU消息格式 | 配置复杂度较高 | React/Remix前端项目 |
Crowdin | 提供TMS完整功能、API丰富 | 免费版有翻译量限制 | 多团队协作翻译 |
PO文件 | 广泛支持、版本控制友好 | 可读性较差 | 翻译文件存储 |
环境配置详解:从本地开发到Crowdin集成
1. 项目初始化配置
documenso采用Monorepo架构,国际化相关依赖集中声明在根目录package.json
:
{
"devDependencies": {
"@lingui/cli": "^5.2.0",
"@lingui/format-po": "^5.2.0"
},
"scripts": {
"translate:extract": "lingui extract --clean",
"translate:compile": "lingui compile"
}
}
关键配置文件lingui.config.ts
定义了翻译源文件路径与格式:
export default defineConfig({
sourceLocale: "en",
locales: ["es", "fr", "de", "zh-CN"], // 支持的目标语言
catalogs: [
{
path: "<rootDir>/packages/lib/translations/{locale}/web",
include: ["apps/remix/app", "packages/ui", "packages/lib"],
exclude: ["**/node_modules/**"],
},
],
format: formatter({ lineNumbers: false }),
});
2. Crowdin项目配置
根目录crowdin.yml
建立了Crowdin与本地文件系统的映射关系:
files:
- source: packages/lib/translations/en/web.po
translation: packages/lib/translations/%two_letters_code%/%original_file_name%
此配置将英语源文件映射到目标语言目录,其中%two_letters_code%
变量会被Crowdin替换为语言代码(如es
、fr
)。
3. 翻译文件目录结构
packages/lib/translations/
├── en/
│ └── web.po # 英语源文件
├── es/
│ └── web.po # 西班牙语翻译
├── fr/
│ └── web.po # 法语翻译
└── zh-CN/
└── web.po # 简体中文翻译
开发实战:文本标记与翻译提取
1. 代码中标记可翻译文本
documenso使用Lingui的<Trans>
组件和t
函数标记文本:
React组件中使用JSX语法:
import { Trans } from "@lingui/macro";
function Dashboard() {
return (
<h1>
<Trans>Dashboard</Trans>
</h1>
<p>
<Trans>Welcome back! Here's an overview of your account.</Trans>
</p>
);
}
TypeScript文件中使用函数调用:
import { t } from "@lingui/macro";
const errorMessage = t`Document not found`;
复数与动态内容处理:
<Trans>
{count, plural,
one {You have 1 pending invitation}
other {You have # pending invitations}
}
</Trans>
2. 提取与编译翻译
执行以下命令从代码中提取文本到PO文件:
npm run translate:extract
命令执行后会更新web.po
文件:
msgid "Dashboard"
msgstr ""
msgid "Welcome back! Here's an overview of your account."
msgstr ""
编译PO文件为JavaScript模块:
npm run translate:compile
编译后生成的JSON文件位于translations/{locale}/web.json
,可直接被应用加载。
协作流程:Crowdin平台操作指南
1. 项目创建与权限配置
- 在Crowdin创建新项目,设置源语言为英语
- 配置成员角色:
- 管理者:完全权限
- 翻译者:仅翻译权限
- 校对者:审核翻译内容
2. 翻译任务管理
- 开发者上传最新PO文件后,Crowdin自动创建翻译任务
- 译者在Web界面或桌面客户端完成翻译:
- 使用内置翻译记忆库提高一致性
- 利用机器翻译辅助(如DeepL)
- 校对者审核翻译内容,标记为"已批准"
3. 关键质量控制功能
- 术语库:维护项目专用术语表,确保翻译一致性
- 翻译记忆:自动复用已有翻译,减少重复工作
- QA检查:检测格式错误、标点缺失、长度超限等问题
自动化集成:GitHub Actions工作流
documenso实现了完整的翻译自动化流程,核心工作流定义在.github/workflows/
目录。
1. 翻译内容上传(translations-upload.yml)
当代码合并到main分支时触发:
on:
push:
branches: ['main']
jobs:
extract_translations:
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Extract translations
run: npm run translate:extract
- name: Upload to Crowdin
uses: crowdin/github-action@v2
with:
upload_sources: true
upload_translations: false
2. 翻译内容拉取(translations-pull.yml)
每两小时执行一次,拉取已批准的翻译:
on:
schedule:
- cron: '0 */2 * * *'
jobs:
pull_translations:
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Pull from Crowdin
uses: crowdin/github-action@v2
with:
download_translations: true
export_only_approved: true
- name: Create PR
uses: peter-evans/create-pull-request@v5
with:
title: 'chore: update translations'
branch: chore/translations
3. 强制同步机制(translations-force-pull.yml)
用于手动触发紧急翻译更新:
on:
workflow_dispatch: # 支持手动触发
jobs:
pull_translations:
steps:
- name: Pull from Crowdin
uses: crowdin/github-action@v2
with:
download_translations: true
export_only_approved: false # 下载所有翻译,无论是否批准
最佳实践与常见问题
1. 开发规范
-
文本标记原则:
- 避免在同一标签中混合静态文本和动态变量
- 长文本拆分多个
<Trans>
组件,提高复用率 - 保持句子完整性,便于翻译理解上下文
-
分支管理策略:
- 翻译相关变更使用
chore/translations
分支 - 定期合并翻译更新到开发分支(建议每周)
- 翻译相关变更使用
2. 性能优化
- 按需加载:只加载当前语言的翻译文件
- 预编译:构建时将PO文件转换为JSON,减少运行时开销
- 缓存策略:缓存翻译JSON文件,减少网络请求
3. 常见问题排查
Q: 提取命令失败,提示"没有找到可翻译文本"
A: 检查Lingui配置中的include
路径是否正确包含源代码目录:
// lingui.config.ts
catalogs: [
{
include: ["apps/remix/app", "packages/ui", "packages/lib"],
}
]
Q: Crowdin翻译后未同步到代码库
A: 检查三个可能原因:
- 翻译未标记为"已批准"(export_only_approved: true)
- GitHub Actions权限不足(需配置GH_PAT密钥)
- 工作流触发条件未满足(可手动触发workflow_dispatch)
Q: 运行时出现"Missing translation"错误
A: 执行以下命令检查完整性:
npm run translate:compile -- --strict
该命令会在发现缺失翻译时抛出错误。
未来优化方向
- 增量翻译提取:仅处理变更文件,提高提取效率
- 翻译质量评分:集成自动化质量评估工具
- 分支预览:为PR自动生成多语言预览环境
- 本地化测试:添加伪本地化测试,检测UI兼容性
总结
documenso的国际化工作流通过Lingui、Crowdin与GitHub Actions的深度集成,实现了从文本标记到生产部署的全流程自动化。这套方案不仅解决了多团队协作的效率问题,还通过严格的自动化流程保障了翻译质量与版本一致性。对于中大型项目,建议参考其分层架构设计:
- 代码层:使用Lingui标记可翻译内容
- 文件层:采用PO格式存储翻译内容
- 协作层:通过Crowdin管理翻译过程
- 部署层:GitHub Actions实现无缝集成
通过这套架构,开发团队可以将国际化工作流的维护成本降低60%以上,同时显著提升翻译质量与交付速度。
附录:常用命令速查表
命令 | 功能 |
---|---|
npm run translate:extract | 提取可翻译文本到PO文件 |
npm run translate:compile | 编译PO文件为JSON模块 |
npm run dx | 完整开发环境初始化 |
crowdin status | 检查Crowdin同步状态 |
延伸阅读
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考