Laravel 多语言切换
Laravel本地化
实现整站多语言切换流程如下:
- 定义语言文件
- 用户访问设置语言的链接,系统将用户选择的语言代码存入Session
- 使用中间件,在处理每个请求之前,从Session中读取语言代码,并设置系统语言
- 之后在控制器、视图等地方只用 __() 函数来访问语言文件中定义的键名
系统配置
首先设置系统默认语言以及未找到语言文件时,使用的语言。
# 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>
最终效果
# 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>
由于我们只创建了PHP语言文件的中文版本resources\lang\zh-CN\message.php
,当语言是英文时,系统找不到对应的语言文件resources\lang\en\message.php
,于是将 __() 函数的参数原样输出。只要创建对应的语言文件就行了。
完全没有问题。好耶。
参考链接
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。