翻译 EmDash

本页内容

EmDash 的管理界面使用 Lingui 进行消息提取,使用 Lunaria 跟踪翻译进度,支持国际化翻译。所有翻译存放在 PO(gettext)文件中——每个语言对应一个文件。

翻译状态

查看翻译仪表板了解所有语言的当前进度。

谁可以翻译

翻译必须由母语使用者或流利使用者提交。我们不接受机器生成的翻译。如果你使用 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 将在运行时回退到英文。

翻译字符串

  1. 查看翻译仪表板,了解哪些内容需要翻译。检查未合并的 PR,避免重复劳动。

  2. Fork 仓库并创建分支:

    git checkout -b i18n/de
  3. 打开你所在语言的 PO 文件(例如 packages/admin/src/locales/de/messages.po)。

  4. 填写翻译。 每个条目的格式如下:

    #: 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"
  5. 测试你的翻译(见下文)。

  6. 提交 PRmain 分支。标题格式: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 组件。两者在翻译中必须与源文本完全一致——相同的名称、相同的嵌套结构。

测试你的翻译

  1. 编译并运行示例项目:

    pnpm run locale:compile
    pnpm build
    pnpm --filter emdash-demo dev
  2. 切换语言,在管理界面的设置页面中验证你的翻译在上下文中是否正确。

伪语言

EmDash 内置了一个伪语言,它会将所有被包裹的字符串转换为带重音的相似字符——"Dashboard" 变成 "Ðàšĥƀöàřð",以此类推。在伪语言激活时,如果某个字符串仍然显示为正常英文,说明它缺少 t..“ 包裹,或者来自目录之外。

要启用伪语言,在示例项目目录的 .env 文件中添加以下内容:

EMDASH_PSEUDO_LOCALE=1

然后重启开发服务器。伪语言会在登录页面和设置页面的语言选择器中显示为 Pseudo。切换到该语言即可一目了然地发现未包裹的字符串。

添加新语言

如果你的语言还没有 PO 文件:

  1. 将语言添加到 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.tslunaria.config.ts 和管理界面运行时都从此文件获取语言列表。除非你的翻译覆盖率达到 100%,否则请将 enabled 设为 false——翻译达到足够覆盖率后我们会启用它。

  2. 运行提取以生成空的 PO 文件:

    pnpm run locale:extract

    这会创建 packages/admin/src/locales/{your-locale}/messages.po,其中包含所有待翻译的字符串。

  3. 翻译并测试,按照上述步骤操作。

翻译标准

准确性

翻译应忠实地反映英文源文本,达到母语使用者的水平。不要添加、删除或重新解读含义。如果源字符串含义不明确,请查看 #: 注释中的源文件位置——阅读组件代码以理解上下文。

一致性

在你的语言中使用一致的术语。如果你在一处将”collection”翻译为”Sammlung”,不要在另一处切换为”Kollektion”。如果你的语言已有翻译,请在开始之前通读已有的 PO 文件,以匹配已建立的术语体系。

语气

管理界面使用直接、专业的语气。在你的语言中也保持这种风格——避免过于正式或过于随意的表达。

AI 辅助翻译

你可以使用 AI 工具起草翻译,但:

  • 必须亲自审核每一个字符串。AI 工具会产生只有流利使用者才能察觉的细微错误——语域不当、表达不自然、技术术语不正确。
  • 必须在运行中的管理界面中测试结果。AI 工具无法感知布局约束或界面上下文。
  • 在 PR 描述中说明是否使用了 AI。
  • 明显未经审核的机器翻译 PR 将被关闭。

部分翻译

欢迎提交部分翻译。你不需要在一个 PR 中翻译所有字符串——任何进展都有帮助。未翻译的字符串将在运行时回退到英文。