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 將在執行時回退到英文。
翻譯字串
-
查看翻譯儀表板,了解哪些內容需要翻譯。檢查未合併的 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" -
測試你的翻譯(見下文)。
-
提交 PR 到
main分支。標題格式: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 工具無法感知版面約束或介面上下文。
- 在 PR 描述中說明是否使用了 AI。
- 明顯未經審核的機器翻譯 PR 將被關閉。
部分翻譯
歡迎提交部分翻譯。你不需要在一個 PR 中翻譯所有字串——任何進展都有幫助。未翻譯的字串將在執行時回退到英文。