EmDash 的管理界面可使用 Lingui 进行消息提取,并使用 Lunaria 跟踪翻译进度。所有翻译都存储在 PO (gettext) 文件中 — 每个语言一个。
翻译状态
查看翻译仪表板了解所有语言的当前进度。
谁可以翻译
每个翻译都必须由母语者或流利的使用者监督。接受 AI 生成的翻译,但仅限于流利的使用者在提交之前审查每个字符串并在运行的管理面板中预览的情况。不接受无监督的机器输出。请参阅下面的 AI 辅助翻译 和测试您的翻译。
让字符串保持未翻译状态比错误翻译更好。错误的翻译会误导用户;英文回退只会给他们带来不便。
文件结构
翻译目录位于 packages/admin/src/locales/:
packages/admin/src/locales/
├── en/
│ └── messages.po # English (source)
├── de/
│ └── messages.po # German
└── ...
每个 .po 文件包含 msgid/msgstr 对。msgid 是英文源文本;msgstr 是您的翻译。空的 msgstr 表示”尚未翻译” — Lingui 在运行时将回退到英文。
翻译字符串
-
查看翻译仪表板 以了解需要处理的内容。检查打开的 PR 以避免重复工作。
-
Fork 仓库并创建分支:
git checkout -b i18n/de -
打开您语言的 PO 文件(例如,
packages/admin/src/locales/de/messages.po)。 -
填写翻译。 每个条目如下所示:
#: packages/admin/src/components/LoginPage.tsx:304 msgid "Sign in with Passkey" msgstr ""填写
msgstr:#: packages/admin/src/components/LoginPage.tsx:304 msgid "Sign in with Passkey" msgstr "Mit Passkey anmelden" -
测试您的翻译(见下文)。
-
打开针对
main的 PR。标题格式:i18n(de): add/update German translations。
需要翻译的内容
- 每个条目的
msgstr值。
不应翻译的内容
msgid值 — 这些是查找键。- 插值占位符,如
{error}、{email}、{label}— 保持完全不变。 - XML 风格的标签,如
<0>、</0>— 这些包装交互元素(链接、按钮)。保留标签并翻译它们之间的文本。 - 以
#:开头的注释 — 这些是 Lingui 添加的源引用。
插值和标签
某些字符串包含占位符和标签:
msgid "Authentication error: {error}"
msgstr "Authentifizierungsfehler: {error}"
msgid "Don't have an account? <0>Sign up</0>"
msgstr "Noch kein Konto? <0>Registrieren</0>"
msgid "If an account exists for <0>{email}</0>, we've sent a sign-in link."
msgstr "Falls ein Konto für <0>{email}</0> existiert, haben wir einen Anmeldelink gesendet."
占位符({error}、{email})在运行时被动态值替换。标签(<0>...</0>)包装 React 组件。两者都必须在您的翻译中以与源中完全相同的方式出现 — 相同的名称、相同的嵌套。
测试您的翻译
-
编译并运行演示:
pnpm run locale:compile pnpm build pnpm --filter emdash-demo dev -
在管理设置页面中切换语言,并验证您的翻译在上下文中看起来正确。
伪语言
EmDash 提供一个伪语言,它将所有包装的字符串转换为带重音符号的相似字符 — "Dashboard" 变成 "Ðàšĥƀöàřð",依此类推。在伪语言激活时以正常英文显示的任何字符串要么缺少 t\…“ 包装器,要么来自目录外部。
要启用它,请在演示目录中的 .env 文件中添加以下内容:
EMDASH_PSEUDO_LOCALE=1
然后重新启动开发服务器。伪语言在登录页面和设置的语言选择器中显示为 Pseudo。切换到它以一目了然地发现未包装的字符串。
添加新语言
如果您的语言还没有 PO 文件:
-
将语言添加到
packages/admin/src/locales/locales.ts:export const LOCALES: LocaleDefinition[] = [ { code: "en", label: "English", enabled: true }, { code: "de", label: "Deutsch", enabled: true }, // ... { code: "ja", label: "日本語", enabled: false }, // add yours ];这是唯一的真理来源 —
lingui.config.ts、lunaria.config.ts和管理运行时都从此文件派生其语言列表。除非您的翻译达到 100% 覆盖率,否则设置enabled: false— 一旦翻译达到足够的覆盖率,维护者将启用它。 -
运行提取以生成空的 PO 文件:
pnpm run locale:extract这将创建
packages/admin/src/locales/{your-locale}/messages.po,其中包含所有准备翻译的字符串。 -
按照上述步骤翻译和测试。
翻译标准
准确性
翻译应忠实地以母语者水平表示英文源文本。不要添加、删除或重新解释意义。如果源字符串含糊不清,请检查 #: 注释以获取源文件位置 — 阅读组件代码以理解上下文。
一致性
在您的语言中使用一致的术语。如果您在一个地方将 “collection” 翻译为 “Sammlung”,请不要在其他地方切换到 “Kollektion”。如果您的语言已经有翻译,请在开始之前阅读现有的 PO 文件以匹配已建立的术语。
语气
管理界面使用直接、专业的语气。在您的语言中匹配它 — 避免过于正式或过于随意的措辞。
AI 辅助翻译
您可以使用 AI 工具生成翻译,包括完整的第一遍,但流利的使用者必须监督结果:
- 流利的使用者必须审查每个字符串。AI 工具会犯下只有流利使用者才能发现的细微错误 — 错误的语域、不自然的措辞、不正确的技术术语。
- 流利的使用者必须在运行的管理界面中预览翻译。AI 工具不了解布局约束或 UI 上下文。
- 在您的 PR 描述中披露 AI 使用情况。
- 包含无监督机器翻译的 PR 将被关闭。
部分翻译
欢迎部分翻译。您不需要在一个 PR 中翻译每个字符串 — 任何进展都有帮助。未翻译的字符串将在运行时回退到英文。