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

OpenL Team Jul 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 檔案。 請使用包含 msgid 和 msgstr 條目的語言檔案。如果你只有 .pot 樣板,請先從它建立目標語言的 .po 檔案,再上傳 .po 檔。

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

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

  6. 優先檢查高風險字串。 在翻譯後的檔案中搜尋 %、{、}、<、>、msgid_plural、msgctxt 和 #, 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. 複數型態需分開翻譯。 複數條目會包含 msgid、msgid_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 項目需要翻譯嗎?安全範例為什麼這很重要
msgid否msgid "Save changes"應用程式在許多 gettext 工作流程中會用這個原文字串作為查找鍵。
msgstr是msgstr "Guardar cambios"這是使用者實際看到的目標語言文字。
msgctxt否msgctxt "button"上下文可釐清相同原文的不同用途。
%s, %d, %1$s否Hello, %s -> Hola, %s執行時程式會用即時值取代這些佔位符。
{name}, %(count)s, :name否Welcome, {name}命名變數必須與應用程式程式碼一致。
HTML 標籤通常不翻譯<strong>Warning</strong>只翻譯標籤內的文字,不要改動標籤語法。
msgid_plural否msgid_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 檔以 msgid 和 msgstr 為核心;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。

Sources