如何翻譯 PO 檔案而不影響你的應用程式

OpenL Team 7/3/2026
如何翻譯 PO 檔案而不影響你的應用程式

TABLE OF CONTENTS

PO 檔案看起來就像一般的文字檔,直到一個被翻譯的 %s、缺少的複數形式,或被修改的 msgid 讓你的應用程式出錯。請依照這個工作流程翻譯面向使用者的字串,同時保持 gettext 結構不變。

不要把整個檔案貼到一般的文字翻譯器裡。PO 檔案接近原始碼:文字可以翻譯,但檔案結構、佔位符、註解和複數索引必須完全保留。

方法一:使用 PO 檔案翻譯工具

如果你想要最快速且安全的初稿,又不想手動編輯 msgid / msgstr 配對,請選擇這個方法。

  1. 備份原始 .po 檔案。 在將檔案交給翻譯人員前,請先在你的版本庫中保留一份乾淨的副本。如果翻譯後的檔案出錯,你需要一個已知沒問題的版本來比對。

  2. 打開支援 PO 的翻譯工具。 使用專為 gettext 檔案設計的工具,例如 OpenL PO Translator,這是一個按次付費的文件翻譯工具。支援 PO 的工具會翻譯目標字串,同時保留原始字串、註解、佔位符和檔案結構。如果你還在選擇工具,可以參考我們的最佳 PO 翻譯工具指南進行比較。

  3. 上傳 .po 檔案。 請使用包含 msgidmsgstr 條目的語言檔案。如果你只有 .pot 樣板,請先從它建立目標語言的 .po 檔案,再上傳 .po 檔。

  4. 選擇來源語言和目標語言。 來源語言要對應 msgid 內的文字,而不是你的管理介面語言。例如,如果檔案內的 msgid 是英文、你需要西班牙文輸出,請選擇英文到西班牙文。

  5. 下載翻譯後的檔案。 儲存時請依照你的框架所需的語系命名規則。WordPress 外掛通常使用文字網域加語系的格式,而 Django 則多半將檔案放在 locale/<language>/LC_MESSAGES/ 目錄下。

  6. 優先檢查高風險字串。 在翻譯後的檔案中搜尋 %{}<>msgid_pluralmsgctxt#, fuzzy。這些條目最有可能影響執行時的行為。

  7. 在應用程式中測試翻譯檔案。 將語言檔案載入本地,並點擊所有使用到翻譯字串的畫面。PO 檔案並非翻譯完成就算結束,只有當應用程式依然能正確顯示時,才算真正完成。

方法二:在 Poedit 中翻譯 PO 檔案

當你需要人工審核、WordPress 相容性,或是逐條細緻翻譯流程時,請選擇此方法。

  1. 在 Poedit 中開啟檔案。 Poedit 是專為 PO 及其他在地化格式設計的翻譯編輯器;基本編輯器免費,進階工作流程則有付費 Pro 版本。對於 WordPress,官方 Polyglots 手冊說明 Poedit 可從 POT 檔建立 .po.mo 檔,並支援複數型態與 UTF-8。

  2. 若原始內容有變更,請從 POT 樣板更新。 如果開發者修改了應用程式文字,請在翻譯前,先用最新的 .pot 檔更新 .po 檔。這樣可以讓新增、移除或模糊的字串明確顯示,避免過時的介面文字被悄悄釋出。

  3. 只翻譯 msgstr 欄位。 msgid 是應用程式用來查找翻譯的原文字串。在一般 gettext 工作流程中,譯者應只編輯 msgstr,不要動 msgid

  4. 佔位符必須完全保留。 請勿翻譯或更動像 %s%d%1$s{name}%(count)s:name 或 HTML 標籤等變數。如果語序需要調整,請整個佔位符一起移動。

  5. 複數型態需分開翻譯。 複數條目會包含 msgidmsgid_plural 及多個 msgstr[n] 欄位。請根據目標語言的需求,完整填寫每個複數欄位,而不是每一欄都複製同一句話。

  6. 儲存並編譯 .mo 檔案(如應用程式需要)。 有些技術棧在開發期間會直接讀取 .po 檔案,但 WordPress 及多數 gettext 架構在執行時會使用編譯後的 .mo 檔案。Poedit 可以在儲存時自動編譯 .mo;Django 則可用 django-admin compilemessages 來編譯訊息。

  7. 上傳前先解決所有警告。 在 Poedit 中,警告圖示通常代表佔位符錯誤、變數遺漏或複數型態不符。請在將翻譯匯入 WordPress、Django、Drupal 或發行分支前,先修正這些問題。

方法三:使用在地化平台

當有多位譯者、審核者或發行管理員需要協作同一份 PO 檔時,建議選用此法。

  1. 將 PO 檔匯入支援 gettext 的平台。 Weblate 及類似的在地化平台都支援 PO 工作流程。團隊型在地化平台多為付費產品,但 Weblate 也有開源自架版。各平台對註解、標頭、模糊字串及佔位符的處理方式不同,上傳正式檔案前請先檢查格式設定。

  2. 啟用佔位符與標籤檢查。 開啟 QA 規則,檢查 printf 風格佔位符、命名變數、HTML/XML 標籤及複數型態。這些檢查能發現一般拼字檢查無法察覺的錯誤。

  3. 讓開發者註解保持可見。 PO 註解可包含來源參考、開發者備註、標記及前一版原文等資訊。當像「Open」這樣的短介面標籤可能是動詞、形容詞或選單指令時,譯者需要這些註解來釐清語境。

  4. 搭配審核使用翻譯記憶庫。 翻譯記憶庫對於重複的介面字串很有幫助,但有時會將舊譯文套用到新語境。當 msgctxt、來源參考或周邊介面有變化時,請務必審核重用的字串。

  5. 匯出 PO 檔並進行本地檢查。 匯出後請勿直接信任結果。將翻譯檔重新放回應用程式,必要時編譯,並實際測試畫面後再合併。

PO 檔案絕不可違反的規則

PO 項目需要翻譯嗎?安全範例為什麼這很重要
msgidmsgid "Save changes"應用程式在許多 gettext 工作流程中會用這個原文字串作為查找鍵。
msgstrmsgstr "Guardar cambios"這是使用者實際看到的目標語言文字。
msgctxtmsgctxt "button"上下文可釐清相同原文的不同用途。
%s, %d, %1$sHello, %s -> Hola, %s執行時程式會用即時值取代這些佔位符。
{name}, %(count)s, :nameWelcome, {name}命名變數必須與應用程式程式碼一致。
HTML 標籤通常不翻譯<strong>Warning</strong>只翻譯標籤內的文字,不要改動標籤語法。
msgid_pluralmsgid_plural "%d files"原文複數形式屬於原始程式碼流程。
msgstr[0], msgstr[1]是,但要小心msgstr[0] "%d file"每種目標語言有自己的複數規則。
#, fuzzy先檢查#, fuzzyfuzzy 代表翻譯可能過時或尚未確認。
#. 開發者註解通常不翻譯#. Button label這些註解協助譯者理解上下文。

快速範例:安全 vs. 出錯的 PO 翻譯

以下是一個正常的 gettext 條目:

#. %s is the user's display name.
#, c-format
msgid "Welcome back, %s"
msgstr ""

一個安全的西班牙語翻譯會保留 %s 不變:

#. %s is the user's display name.
#, c-format
msgid "Welcome back, %s"
msgstr "Bienvenido de nuevo, %s"

一個出錯的翻譯則改動了佔位符:

msgid "Welcome back, %s"
msgstr "Bienvenido de nuevo, % s"

那個小小的空格就可能造成問題。GNU msgfmt --check-format 就是用來檢查像是錯誤 % 佔位符這類格式字串不符的情況,Poedit 也會針對常見的佔位符問題發出警告。若要查閱更多應保持不變的字串,請參考我們的不可翻譯內容指南

如何檢查已翻譯的 PO 檔案

  1. 如果你已安裝 gettext,請執行 gettext 驗證。
msgfmt --check --check-format -o /tmp/messages.mo path/to/messages.po

這個指令會檢查語法、標頭和格式字串,若檔案有效,則會寫入一個暫時編譯的 catalog。

  1. 依照你的框架需求編譯檔案。
django-admin compilemessages

對於 Django 專案來說,compilemessages 會將由 makemessages 產生的 .po 檔案編譯成 .mo 檔案,以支援 gettext。

  1. 搜尋空白翻譯。
grep -n 'msgstr ""' path/to/messages.po

空的 msgstr 欄位可能是尚未翻譯的條目,這通常是有意為之,但在發佈時不應讓你感到意外。

  1. 搜尋模糊翻譯字串。
grep -n '#, fuzzy' path/to/messages.po

模糊(fuzzy)字串應在發佈前由人工審查。預設情況下,msgfmt 不會使用模糊翻譯,除非你用 --use-fuzzy 編譯,因此模糊條目在最終 catalog 中會像未翻譯字串一樣處理。

  1. 實際測試 UI。 請開啟包含表單、複數計數、錯誤訊息、帳號選單及付款流程的畫面。PO 檔驗證能抓出檔案問題,只有 UI 測試才能發現用詞不自然、文字溢出或語境缺失等問題。

你該用哪一種方法?

情境最佳方法原因
你需要為單一 PO 檔案快速產出初稿PO 檔案翻譯器最快且能保留結構
你維護 WordPress 外掛或佈景主題Poedit熟悉的 WordPress 工作流程,並可編譯 .mo
你維護 Django 應用程式PO 翻譯器或 Poedit,然後執行 compilemessages翻譯可快速完成,但仍需框架編譯
你有多種語言及多位審核者在地化平台更佳的指派、歷史紀錄、品質控管與審核管理
你在翻譯開發者相關字串機器翻譯後進行人工審核程式碼術語、佔位符與語境更為重要
你也要在地化 JSON 或前端 i18n 檔案使用對應格式的工作流程PO 的規則不一定適用於 JSON、YAML 或 ICU 訊息

如果你的專案同時包含 gettext PO 檔與 JSON 語系檔,請分別使用能理解其結構的工具來翻譯。PO 檔以 msgidmsgstr 為核心;JSON 在地化則以鍵值對為主。這類工作流程,請參考我們的2026 年最佳 JSON 翻譯工具指南

常見問題

我可以用 Google 翻譯來翻譯 PO 檔嗎?

你可以將單一 msgstr 值複製到一般翻譯器中,但將整個 PO 檔上傳或貼到純文字翻譯器中風險很高。一般翻譯器可能會改動 msgid、註解、引號跳脫、複數索引或佔位符。建議改用支援 PO 格式的翻譯器、Poedit 或在地化平台。

.po.pot.mo 有什麼不同?

.pot 是從原始碼擷取出來的範本,通常只包含原文字串,沒有翻譯內容。.po 是針對單一目標語言可編輯的翻譯檔案。.mo 則是編譯後的二進位目錄,許多基於 gettext 的應用程式在執行時會載入它。

我應該翻譯 msgid 嗎?

不,正常工作流程中不是这样操作的。请翻译 msgstr。GNU gettext 手册将 msgid 描述为原始未翻译字符串,而 msgstr 则是翻译内容;msgid 字符串由 gettext 工具生成和管理。

如何檢查 PO 檔案是否有效?

如果有安裝 gettext,可以執行 msgfmt --check --check-format,也可以用 Poedit 開啟檔案,或利用你的在地化平台的 QA 檢查功能。然後將檔案編譯並在應用程式內測試。驗證是必要步驟,但不能取代 UI 測試。

如果我破壞了一個佔位符會怎樣?

最好的情況是,應用程式顯示奇怪的字串。更糟的情況是,執行時格式化器會拋出錯誤,因為翻譯後的字串已經和程式碼傳入的變數不符。佔位符只能作為完整的標記移動,絕不能翻譯或部分編輯。

OpenL 可以翻譯 PO 檔案嗎?

可以。OpenL PO Translator 專為 gettext .po 檔案設計,並聲稱在翻譯超過 100 種語言時,會保持佔位符和變數不變。它採用按次計費的文件翻譯流程,因此當你需要快速產出初稿、又必須保留 PO 結構時,可以考慮使用。如果你只有 .pot 範本,請先建立目標語言的 .po 檔案再用 OpenL。

來源