Laravel提供了本地化功能,可以方便地添加多国语言。

实现整站多语言切换流程如下:

  1. 定义语言文件
  2. 用户访问设置语言的链接,系统将用户选择的语言代码存入Session
  3. 使用中间件,在处理每个请求之前,从Session中读取语言代码,并设置系统语言
  4. 之后在控制器、视图等地方只用 __() 函数来访问语言文件中定义的键名

系统配置

首先设置系统默认语言以及未找到语言文件时,使用的语言。

# config\app.php

# 默认语言
'locale' => 'en',
# 语言文件不存在时,使用的语言
'fallback_locale' => 'en',

创建中间件

php artisan make:middleware Localization

# ppp\Http\Middleware\Localization.php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Session;
class Localization
{
    public function handle(Request $request, Closure $next)
    {
        if(Session::has('locale')){
            App::setLocale(Session::get('locale'));
        }
        return $next($request);
    }

注册中间件

由于这个中间件是全局可用,每个请求都要经过它,所以需要在App\Http\Kernel.php中注册。
如果你只需要在某些路径中使用,那就只需在路由中定义。
详见Laravel文档:注册中间件

# app\Http\Kernel.php

    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
            \App\Http\Middleware\Localization::class, # <==新增的语言切换中间件
        ],

        'api' => [
            // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            'throttle:api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
    ];

新增路由

# routes\web.php

Route::get('/language/{locale}',function($locale){
    app()->setLocale($locale);
    session()->put('locale',$locale);
    return back();
})->name('language');

创建语言文件

使用短语

短语使用PHP文件定义。

# resources\lang\zh-CN\message.php

<?php

return [
    'greetings' => '把最真的祝福化作风,吹送到你的身边,把最诚的问候变成雨,飘散到你的窗前,把我的感谢化作万语千言,为你祈祷幸福永远',
    'tooLarge' => ':property 太大了,请减小一点再试',
];

翻译全文

使用JSON文件定义

// resources\lang\zh-CN.json

{
   "Please input valid Email":"请输入正确的邮箱地址",
   "Hello :name":"早上好, :name,不好也可以,随你便",
   "Length":"长度"
}

在视图中使用

创建切换语言的组件

<div class="ui dropdown item">
    <i class="language icon"></i>
    <div class="menu">
        <a href="{{ route('language','zh-CN')}}" class="item"><i class="cn flag"></i></a>
        <a href="{{ route('language','en')}}" class="item"><i class="uk flag"></i></a>
    </div>
</div>

menu.png

最终效果

# resources\views\welcome.blade.php

<div class="ui segment">
    <p>当前语言为: {{ app()->getLocale() }}</p>
    <hr>
    <h3>php文件中定义的:</h3>
    <p>{{ __('message.greetings') }}</p>
    <p>{{ __('message.tooLarge',['property'=>__('Length')]) }}</p>
    <hr>
    <h3>JSON 文件中定义的:</h3>
    <p>{{ __('Please input valid Email') }}</p>
    <p>{{ __('Hello :name',['name'=>'Borne']) }}</p>
    <hr>
    <h3>不存在的字符串</h3>
    <p>{{ __('String not exist') }}</p>
</div>

en.png
由于我们只创建了PHP语言文件的中文版本resources\lang\zh-CN\message.php,当语言是英文时,系统找不到对应的语言文件resources\lang\en\message.php,于是将 __() 函数的参数原样输出。只要创建对应的语言文件就行了。

cn.png
完全没有问题。好耶。 icon_mrgreen.png

参考链接

  1. Laravel localization: A step-by-step guide
  2. 官方文档
文章目录