Skip to main content

Laravel i18n:國際化與在地化完整指南

從第一個語系檔案到生產環境:設定 Laravel 翻譯系統、處理複數、修復 JSON 回退缺陷,並為地區變體新增智能語系回退鏈。

1

瞭解 Laravel 翻譯系統

Laravel 內建支援兩種檔案格式的翻譯系統:PHP 陣列和 JSON。PHP 檔案使用按功能組織的嵌套鍵(auth.failed、validation.required)。JSON 檔案使用來源字串作為鍵,更簡單但不支援嵌套。

Terminal
composer create-project laravel/laravel my-app
cd my-app

# Laravel includes i18n out of the box
# No extra packages needed for basic usage
Laravel 翻譯系統位於 lang/ 目錄(Laravel 9 及更高版本)或 resources/lang/(Laravel 8 及更早版本)。框架會自動偵測目錄。如果兩者都存在,lang/ 優先。
2

設定語系

在 config/app.php 中設定應用程式的預設語系和回退語系。當前語系缺少翻譯鍵時,會使用回退語系。設定應用程式支援的語系,並新增中介軟體以偵測和設定使用者的首選語系。

config/app.php
// config/app.php
return [
    'locale' => 'en',            // Default locale
    'fallback_locale' => 'en',   // Fallback when key is missing
    'faker_locale' => 'en_US',

    // Available locales (for your language switcher)
    'available_locales' => ['en', 'de', 'ja', 'es', 'fr', 'pt-BR'],
];
app/Http/Middleware/SetLocale.php
// app/Http/Middleware/SetLocale.php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class SetLocale
{
    public function handle(Request $request, Closure $next)
    {
        $locale = $request->segment(1); // e.g. /de/about

        if (in_array($locale, config('app.available_locales'))) {
            app()->setLocale($locale);
        }

        return $next($request);
    }
}
3

使用翻譯函式

Laravel 提供三種字串翻譯方式:__() 輔助函式(推薦)、trans() 函式和 @lang Blade 指令。三者都接收翻譯鍵和可選替換參數。在 PHP 程式碼和 Blade 範本中使用 __();在 Blade 中無需轉義 HTML 時使用 @lang。

lang/en/messages.php
// lang/en/messages.php
return [
    'welcome' => 'Welcome to our application',
    'greeting' => 'Hello, :name!',
    'nav' => [
        'home' => 'Home',
        'about' => 'About',
        'settings' => 'Settings',
    ],
];

// lang/de/messages.php
return [
    'welcome' => 'Willkommen in unserer Anwendung',
    'greeting' => 'Hallo, :name!',
    'nav' => [
        'home' => 'Startseite',
        'about' => 'Über uns',
        'settings' => 'Einstellungen',
    ],
];
新程式碼應優先使用 __(),而不是 trans()。__() 同時適用於 PHP 和 JSON 翻譯檔案,trans() 僅適用於 PHP 檔案。在 Blade 範本中,@lang 指令等同於 {'{ __() }'},但語法略為簡潔。
4

處理複數

Laravel 使用豎線分隔複數形式。最簡單的形式是 'apples' => '有一個蘋果|有多個蘋果'。對於顯式範圍,使用 'apples' => '{0} 沒有蘋果|{1} 一個蘋果|[2,*] :count 個蘋果'。trans_choice() 輔助函式或 Str::plural() 會根據數量選擇正確形式。

lang/en.json
// lang/en.json
{
    "Welcome back!": "Welcome back!",
    "You have :count new notifications": "You have :count new notifications",
    "Copyright :year :company": "Copyright :year :company"
}

// lang/de.json
{
    "Welcome back!": "Willkommen zurück!",
    "You have :count new notifications": "Sie haben :count neue Benachrichtigungen",
    "Copyright :year :company": "Copyright :year :company"
}
Laravel 內建的複數處理對於大多數語言僅能正確處理簡單的 one/other 規則。對於具有複雜複數形式的語言(阿拉伯語有 6 種、俄語有 4 種、波蘭語有 3 種),需要定義所有必需的 CLDR 複數類別,否則使用者會看到語法錯誤的文字。
5

新增語系回退鏈

Laravel 內建回退僅從當前語系轉到 fallback_locale,沒有中間步驟。缺少某個鍵時,pt-BR 使用者會看到英語,而不是完全可用的 pt-PT 翻譯。laravel-locale-chain 在載入時對可設定回退鏈中的翻譯進行深度合併,解決此問題。

resources/views/example.blade.php
{{-- Simple translation --}}
<h1>{{ __('messages.welcome') }}</h1>

{{-- With variables --}}
<p>{{ __('messages.greeting', ['name' => $user->name]) }}</p>

{{-- Using @lang directive --}}
<h2>@lang('messages.nav.home')</h2>

{{-- JSON translations (use the string itself as key) --}}
<p>{{ __('Welcome back!') }}</p>

{{-- Pluralization --}}
{{ trans_choice('{0} No items|{1} One item|[2,*] :count items', $count) }}

{{-- Inside Blade components --}}
<x-button>{{ __('messages.nav.settings') }}</x-button>
6

自動翻譯

完成 Laravel i18n 設定後,使用 AI 翻譯語系檔案。將源語系檔案交給 AI 助手,或在 CI/CD 管線中使用 i18n Agent CLI。PHP 和 JSON 翻譯檔案均受支援。

config/locale-chain.php
// Install locale chain package
composer require i18n-agent/laravel-locale-chain

// config/locale-chain.php
return [
    'chains' => [
        'pt-BR' => ['pt-BR', 'pt', 'en'],
        'zh-Hant-TW' => ['zh-Hant-TW', 'zh-Hant', 'zh', 'en'],
        'es-419' => ['es-419', 'es', 'en'],
    ],
];

// In AppServiceProvider::boot()
use I18nAgent\LocaleChain\LocaleChainServiceProvider;

// The package automatically deep-merges translations
// across the chain: pt-BR -> pt -> en
採用漸進式翻譯——新增新鍵時,只翻譯差異內容,不要重新產生所有檔案。這樣可保留經人工審核的翻譯,並避免不必要的改動。

常見問題

硬編碼單數/複數邏輯

使用 $count == 1 ? 'item' : 'items' 而不是 trans_choice(),會在 0 為單數(法語)、有 3 種以上複數形式(俄語、波蘭語)或有 6 種形式(阿拉伯語)的語言中失效。請始終使用 Laravel 複數語法並定義所有必需形式。

JSON 翻譯不會回退

Laravel 的 fallback_locale 僅適用於 PHP 翻譯檔案。JSON 翻譯使用來源字串作為鍵,因此缺失翻譯會傳回鍵本身(英語文字),而不是在回退語系中尋找。這意味著 JSON 翻譯沒有真正的語系回退。使用 laravel-locale-chain 修復此問題。

未瞭解優先順序便混用 PHP 和 JSON

當 PHP 和 JSON 檔案中存在相同鍵時,PHP 優先。這會導致令人困惑的行為:更新 JSON 檔案沒有效果,因為 PHP 檔案遮蓋了它。請為每個功能命名空間選擇一種格式並堅持使用。

立即試用 i18n Agent

將翻譯檔案拖放到此處

JSON, YAML, PO, XML, CSV, Markdown, Properties

或點擊選擇檔案

目標語言

無需註冊即時估價

Laravel i18n 常見問題