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 常见问题