本地化
簡介
預設情況下,Laravel 應用程式骨架不包含 lang 目錄。如果您想自定義 Laravel 的語言檔案,可以透過 lang:publish Artisan 命令釋出它們。
Laravel 的本地化功能提供了一種便捷的方式來獲取不同語言的字串,使您可以輕鬆地在應用程式中支援多種語言。
Laravel 提供了兩種管理翻譯字串的方法。首先,語言字串可以儲存在應用程式的 lang 目錄下的檔案中。在該目錄中,可以為應用程式支援的每種語言設定子目錄。這是 Laravel 管理內建功能(例如驗證錯誤訊息)翻譯字串所採用的方法。
1/lang2 /en3 messages.php4 /es5 messages.php
或者,翻譯字串也可以定義在放置於 lang 目錄中的 JSON 檔案內。採用這種方法時,應用程式支援的每種語言在該目錄下都將擁有一個對應的 JSON 檔案。對於擁有大量可翻譯字串的應用程式,建議使用此方法。
1/lang2 en.json3 es.json
我們將在本文件中討論這兩種管理翻譯字串的方法。
釋出語言檔案
預設情況下,Laravel 應用程式框架中不包含 lang 目錄。如果您想要自定義 Laravel 的語言檔案或建立自己的語言檔案,應該透過 lang:publish Artisan 命令來生成 lang 目錄。lang:publish 命令將在您的應用程式中建立 lang 目錄,併發布 Laravel 所使用的預設語言檔案集。
1php artisan lang:publish
配置區域設定 (Locale)
應用程式的預設語言儲存在 config/app.php 配置檔案中的 locale 配置選項中,通常透過 APP_LOCALE 環境變數進行設定。您可以根據應用程式的需要自由修改此值。
您還可以配置“回退語言”,當預設語言不包含給定的翻譯字串時,將使用該語言。與預設語言一樣,回退語言也在 config/app.php 配置檔案中配置,其值通常透過 APP_FALLBACK_LOCALE 環境變數設定。
您可以使用 App 外觀(Facade)提供的 setLocale 方法在執行時修改單個 HTTP 請求的預設語言。
1use Illuminate\Support\Facades\App; 2 3Route::get('/greeting/{locale}', function (string $locale) { 4 if (! in_array($locale, ['en', 'es', 'fr'])) { 5 abort(400); 6 } 7 8 App::setLocale($locale); 9 10 // ...11});
確定當前區域設定
您可以使用 App 外觀上的 currentLocale 和 isLocale 方法來確定當前區域設定,或檢查區域設定是否為給定值。
1use Illuminate\Support\Facades\App;2 3$locale = App::currentLocale();4 5if (App::isLocale('en')) {6 // ...7}
複數語言
您可以指示 Laravel 的“複數轉換器”(被 Eloquent 和框架的其他部分用於將單數字符串轉換為複數字串)使用除英語之外的其他語言。這可以透過在應用程式的服務提供者之一的 boot 方法中呼叫 useLanguage 方法來實現。複數轉換器目前支援的語言有:french(法語)、norwegian-bokmal(挪威博克馬爾語)、portuguese(葡萄牙語)、spanish(西班牙語)和 turkish(土耳其語)。
1use Illuminate\Support\Pluralizer; 2 3/** 4 * Bootstrap any application services. 5 */ 6public function boot(): void 7{ 8 Pluralizer::useLanguage('spanish'); 9 10 // ...11}
如果您自定義了複數轉換器的語言,則應顯式定義 Eloquent 模型的 資料表名稱。
定義翻譯字串
使用短鍵
通常,翻譯字串儲存在 lang 目錄下的檔案中。在該目錄中,應為應用程式支援的每種語言建立一個子目錄。這是 Laravel 管理內建功能(如驗證錯誤訊息)的翻譯字串所使用的方法。
1/lang2 /en3 messages.php4 /es5 messages.php
所有的語言檔案都會返回一個鍵值對陣列。例如:
1<?php2 3// lang/en/messages.php4 5return [6 'welcome' => 'Welcome to our application!',7];
對於因地區而異的語言,您應該按照 ISO 15897 標準命名語言目錄。例如,英式英語應該使用“en_GB”而不是“en-gb”。
使用翻譯字串作為鍵
對於擁有大量可翻譯字串的應用程式,如果為每個字串定義一個“短鍵”,在檢視中引用這些鍵時會變得令人困惑,並且為應用程式支援的每個翻譯字串不斷髮明新鍵也很麻煩。
因此,Laravel 還支援使用字串的“預設”翻譯作為鍵來定義翻譯字串。使用翻譯字串作為鍵的語言檔案作為 JSON 檔案儲存在 lang 目錄中。例如,如果您的應用程式有西班牙語翻譯,您應該建立一個 lang/es.json 檔案。
1{2 "I love programming.": "Me encanta programar."3}
鍵 / 檔案衝突
您不應定義與其它翻譯檔名衝突的翻譯字串鍵。例如,在存在 nl/action.php 檔案但不存在 nl.json 檔案的情況下,為“NL”區域設定翻譯 __('Action'),會導致翻譯器返回 nl/action.php 的全部內容。
獲取翻譯字串
您可以使用 __ 輔助函式從語言檔案中獲取翻譯字串。如果您使用“短鍵”來定義翻譯字串,則應使用“點”語法將包含該鍵的檔案和鍵本身傳遞給 __ 函式。例如,讓我們從 lang/en/messages.php 語言檔案中獲取 welcome 翻譯字串:
1echo __('messages.welcome');
如果指定的翻譯字串不存在,__ 函式將返回翻譯字串的鍵。因此,在上面的例子中,如果翻譯字串不存在,__ 函式將返回 messages.welcome。
如果您使用的是 預設翻譯字串作為翻譯鍵,則應將字串的預設翻譯傳遞給 __ 函式:
1echo __('I love programming.');
同樣,如果翻譯字串不存在,__ 函式將返回傳遞給它的翻譯字串鍵。
如果您使用的是 Blade 模板引擎,可以使用 {{ }} 回顯語法來顯示翻譯字串:
1{{ __('messages.welcome') }}
替換翻譯字串中的引數
如果您願意,可以在翻譯字串中定義佔位符。所有佔位符都以 : 為字首。例如,您可以定義一個帶有名稱佔位符的歡迎訊息:
1'welcome' => 'Welcome, :name',
要在獲取翻譯字串時替換佔位符,可以將替換陣列作為第二個引數傳遞給 __ 函式:
1echo __('messages.welcome', ['name' => 'dayle']);
如果您的佔位符包含所有大寫字母,或者只有首字母大寫,翻譯後的值也將相應地大寫:
1'welcome' => 'Welcome, :NAME', // Welcome, DAYLE2'goodbye' => 'Goodbye, :Name', // Goodbye, Dayle
物件替換格式化
如果您嘗試提供一個物件作為翻譯佔位符,該物件的 __toString 方法將被呼叫。__toString 方法是 PHP 內建的“魔術方法”之一。然而,有時您可能無法控制特定類的 __toString 方法,例如當您互動的類屬於第三方庫時。
在這種情況下,Laravel 允許您為該特定型別的物件註冊自定義格式化處理程式。要實現這一點,您應該呼叫翻譯器的 stringable 方法。stringable 方法接受一個閉包,該閉包應指定它負責格式化的物件型別。通常,stringable 方法應該在應用程式 AppServiceProvider 類的 boot 方法中呼叫:
1use Illuminate\Support\Facades\Lang; 2use Money\Money; 3 4/** 5 * Bootstrap any application services. 6 */ 7public function boot(): void 8{ 9 Lang::stringable(function (Money $money) {10 return $money->formatTo('en_GB');11 });12}
複數化
複數化是一個複雜的問題,因為不同語言對於複數形式有各種複雜的規則;然而,Laravel 可以根據您定義的複數規則來幫助您以不同的方式翻譯字串。使用 | 字元,您可以區分字串的單數和複數形式:
1'apples' => 'There is one apple|There are many apples',
當然,在使用 翻譯字串作為鍵 時,也支援複數化:
1{2 "There is one apple|There are many apples": "Hay una manzana|Hay muchas manzanas"3}
您甚至可以建立更復雜的複數化規則,為多個數值範圍指定翻譯字串:
1'apples' => '{0} There are none|[1,19] There are some|[20,*] There are many',
在定義了帶有複數化選項的翻譯字串後,您可以使用 trans_choice 函式獲取給定“數量 (count)”對應的行。在此示例中,由於數量大於 1,因此返回翻譯字串的複數形式:
1echo trans_choice('messages.apples', 10);
您還可以在複數化字串中定義佔位符屬性。這些佔位符可以透過將陣列作為第三個引數傳遞給 trans_choice 函式來替換:
1'minutes_ago' => '{1} :value minute ago|[2,*] :value minutes ago',2 3echo trans_choice('time.minutes_ago', 5, ['value' => 5]);
如果您想顯示傳遞給 trans_choice 函式的整數值,可以使用內建的 :count 佔位符:
1'apples' => '{0} There are none|{1} There is one|[2,*] There are :count',
覆蓋擴充套件包的語言檔案
一些擴充套件包可能附帶它們自己的語言檔案。與其更改擴充套件包的核心檔案來調整這些行,不如透過將檔案放置在 lang/vendor/{package}/{locale} 目錄中來覆蓋它們。
例如,如果您需要覆蓋名為 skyrim/hearthfire 的擴充套件包中 messages.php 的英文翻譯字串,您應該將語言檔案放在:lang/vendor/hearthfire/en/messages.php。在此檔案中,您只需定義想要覆蓋的翻譯字串。任何您未覆蓋的翻譯字串仍將從擴充套件包的原始語言檔案中載入。