Skip to main content

本頁要達成的目標

以多語言發布套件的訊息,讓使用端應用程式只需變更必要的文字。並整理如何將翻譯鍵與預留位置視為公開 API,以及在套件更新時保留自訂內容的方法。 在地化說明應用程式中的基本操作,Laravel 套件開發說明註冊與公開的基礎。本頁則深入 Laravel 13 的 ServiceProvider、FileLoader、Translator 的實作。
loadTranslationsFrom() 是註冊載入來源,publishes() 是註冊檔案的複製目的地。使用者不必為了使用翻譯而一定要執行 vendor:publish。

以命名空間發布 PHP 翻譯

若要擁有套件專屬的鍵,請使用 PHP 陣列格式與命名空間。以下是名為 Acme\Courier 的套件範例。
在 lang/ja/messages.php 準備日文的預設值。
在 lang/en/messages.php 也準備作為備援的英文。
在服務提供者的 boot() 中註冊載入與選用的公開。
使用端需指定命名空間、檔案名稱與陣列鍵。語言代碼依照 Laravel 的設定使用 ja,這與本文件網站 URL 所使用的 jp 不同。
命名空間 courier 是 loadTranslationsFrom() 的第 2 個參數,並不會依 Composer 的套件名稱自動決定。

PHP 翻譯不會整個取代檔案

在使用端應用程式中,若使用標準語言目錄,只需在 lang/vendor/courier/ja/messages.php 寫入要變更的鍵。即使變更了語言目錄,也使用 $this->app->langPath('vendor/courier') 底下的位置。
在此範例中只有 queued 會改變,failed 則使用套件的日文翻譯。

FileLoader 的載入順序

ServiceProvider::loadTranslationsFrom() 會在 Translator 解析後註冊命名空間。實際取得檔案則是在請求翻譯時才進行。 FileLoader::loadNamespaced() 會載入已註冊套件的語言檔,並將該陣列傳給 loadNamespaceOverrides()。接著讀取載入器各語言路徑中的 vendor/{namespace}/{locale}/{group}.php,並以 array_replace_recursive() 取代。 標準的 TranslationServiceProvider 會依序將框架的語言路徑與應用程式的語言路徑傳給載入器。即使有擴充功能註冊了額外路徑,之後載入的覆寫陣列也會優先使用相同的鍵。
若未註冊命名空間,FileLoader::loadNamespaced() 會回傳空陣列。僅在 lang/vendor/courier 放置檔案,無法彌補服務提供者的註冊遺漏。此外,若其他套件註冊了相同的命名空間,註冊目標會被取代,因此請選擇不會衝突的名稱。

JSON 翻譯沒有套件專屬的命名空間

以句子作為鍵的 JSON 翻譯,請以下列方式註冊目錄。這是與前述 PHP 翻譯不同的另一種選擇。
套件的 lang/ja.json 範例如下。
loadJsonTranslationsFrom() 沒有命名空間參數。已註冊的 JSON 翻譯會與其他套件及應用程式共用相同的鍵空間。

JSON 的覆寫位置是應用程式的 ja.json

FileLoader::loadJsonPaths() 會先讀取已註冊的 JSON 路徑,再讀取一般的語言路徑,並進行 array_merge()。在標準設定中,應用程式 lang/ja.json 中相同的字串鍵會覆寫套件的值。
  • 若多個套件使用相同的字串鍵,之後載入的 JSON 值會優先。請避免依賴提供者順序的設計。
  • lang/vendor/courier/ja.json 不是標準 JSON 載入器的覆寫位置。即使將 PHP 用的公開設定直接沿用於 JSON,這個位置也不會被自動讀取。
  • 即使以 publishes() 將套件的 JSON 公開到應用程式的 lang/ja.json,檔案內容也不會被合併。為了不破壞既有翻譯,請引導使用者只新增必要的鍵。
Translator::get() 會先確認所請求語言的 JSON,若找不到則以 PHP 格式的鍵進行搜尋。它不會像 PHP 翻譯那樣依序搜尋到備援語言的 JSON。若以英文句子作為 JSON 的鍵,請與沒有翻譯時會顯示原文鍵的標準行為加以區分。
PHP 翻譯的命名空間會將其他套件的 PHP 鍵分隔開來。不過,由於 Translator::get() 會先檢查 JSON 的完全相符鍵,若在 JSON 中定義 courier::messages.delivery.queued 這類鍵,將會優先於 PHP 端。通常應採取不混用句子鍵與 PHP 格式鍵的方針。

在不破壞已公開翻譯的情況下更新

對於想一次公開 PHP 翻譯的使用者,可以引導他們使用縮小對象範圍的指令。
不過,若複製所有預設值,這些複本之後也會成為覆寫值。即使在套件端修正錯字,只要相同的鍵仍留在已公開的檔案中,就看不到新的值。另一方面,複本中沒有的新鍵則會由套件端補上。
若只需變更少數文字,比起公開所有檔案,只在覆寫檔案中放置必要的鍵更容易納入更新。這是運用 PHP 翻譯部分覆寫的維運方式。
在長期維護中,請依下列順序設計更新。
  1. 維持鍵與命名空間 — 刪除或移動鍵會影響使用者的 __() 呼叫與覆寫位置。請考慮新增鍵並保留舊鍵的過渡期間。
  2. 維持預留位置 — 將 :name 改為 :recipient 時,呼叫端的取代陣列也需要變更。請不要將其視為只修改翻譯檔。
  3. 比對已公開檔案的差異 — 比較使用者的覆寫與新的預設值。刪除不再需要的覆寫鍵,即可恢復為套件的值。
  4. 避免無條件重新公開 — 以 --force 重新公開會覆寫使用者的自訂內容。在將 JSON 複製到應用程式檔案的設計中,可能連其他翻譯都會遺失。
  5. 在常駐程序中確認 — Translator::load() 會在實例內保存每個命名空間、群組與語言的陣列。在仍保留已載入 Translator 的程序中,僅變更檔案不一定會重新載入。請依維運方式重新啟動 worker 等。
公開操作的對象選取與覆寫選項請參閱套件的公開資源與更新,版本更新時的相容性判斷則於套件的版本相容性管理中補充說明。

在使用端應用程式中確認的項目

在已註冊服務提供者的驗證用應用程式中,確認下列組合。套件內的測試環境建置請參閱以 Orchestra Testbench 測試 Laravel 套件。 在載入後才建立覆寫檔案的測試中,請避免受到 Translator 既有載入結果的影響。可先準備好檔案再取得,或在每個案例中使用新的應用程式實例進行確認。

參考的一手資料

官方文件確認的是最新的預設分支 13.x,內部實作確認的是參考當時的最新版本 v13.35.0。
最後修改於 2026年10月8日