Laravel 11 本地化 & 通过中间件实现多语言国际化

作者: 温新

图书: 【Laravel 11 实战】

阅读: 32

时间: 2024-11-21 10:51:08

本篇文章将演示如何在 Laravel 11 应用中使用本地化来实现多语言支持。

Laravel Localization 可以实现将应用程序内容翻译成不同的语言,并在各种语言之间进行切换,从而实现多语言切换。

以下案例将实现中文、英文、法语、意大利语之间的切换。

安装项目

创建项目时,选择 Laravel Breeze

$ laravel new local
$ cd local

发布语言文件

1)生成语言文件

$ php artisan lang:publish

该命令会在 app 目录生成 lang 目录和相关语言文件。

2)定义语言文件

lang/en/messages.php

<?php

return [
    "users"             => "Users",
    "users_list"        => "Users Listing",
    "dashboard"         => "Dashboard",
    "dashboard_message" => "You're logged in!"
];

lang/fr/messages.php

<?php

return [
    "users"             => "Utilisateurs",
    "users_list"        => "Liste des utilisateurs",
    "dashboard"         => "Tableau de bord",
    "dashboard_message" => "Vous êtes connecté!"
];

lang/it/messages.php

<?php

return [
    "users"             => "Utenti",
    "users_list"        => "Elenco degli utenti",
    "dashboard"         => "Pannello di controllo",
    "dashboard_message" => "Hai effettuato l'accesso!"
];

lang/zh_CN/messages.php

<?php

return [
    "users"             => "用户",
    "users_list"        => "用户列表",
    "dashboard"         => "面板",
    "dashboard_message" => "面板消息!"
];

创建中间件

这一步最为关键,需要在中间件中检查语言并进行设置。

1)生成中间件

$ php artisan make:middleware SetLocale

2)中间件处理逻辑

app/Http/Middleware/SetLocale.php

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Symfony\Component\HttpFoundation\Response;

class SetLocale
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        // 检查会话中是否存在 'locale' 设置
        if($request->session()->has('locale')){
            // 设置应用程序的语言环境为会话中存储的值,默认为 'zh_CN'
            App::setLocale($request->session()->get('locale', 'zh_CN'));
        }

        return $next($request);
    }
}

3)注册中间件

bootstrap/app.php

<?php

use App\Http\Middleware\SetLocale;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware) {
        // 注册中间件
        $middleware->web(append: [
            SetLocale::class
        ]);
    })
    ->withExceptions(function (Exceptions $exceptions) {
        //
    })->create();

添加路由

routes/web.php

<?php

use App\Http\Controllers\LanguageController;
use App\Http\Controllers\ProfileController;
use App\Http\Controllers\UserController;
use Illuminate\Support\Facades\Route;

...

Route::middleware('auth')->group(function () {
	...
        
    Route::get('lang', [LanguageController::class, 'change'])->name("change.lang");
    Route::get('users', [UserController::class, 'index'])->name('users.index');
});

require __DIR__.'/auth.php';

创建控制器

1)生成控制器

$ php artisan make:controller LanguageController
$ php artisan make:controller UserController

2)编写控制器方法

app/Http/Controllers/LanguageController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Session;

class LanguageController extends Controller
{
    /**
     * 更改应用的语言设置
     *
     * @param Request $request
     * @return RedirectResponse
     */
    public function change(Request $request): RedirectResponse
    {
        $lang = $request->input('lang', 'zh_CN');

        if (!in_array($lang, ['zh_CN','en', 'it', 'fr'])) {
            abort(400);
        }

        Session::put('locale', $lang);

        return redirect()->back();
    }
}

app/Http/Controllers/UserController.php

<?php

namespace App\Http\Controllers;

use Illuminate\View\View;

class UserController extends Controller
{
    /**
     * 用户列表
     * 
     * @return View
     */
    public function index(): View
    {
        return view("users");
    }
}

创建并更新视图文件

resources/views/layouts/navigation.blade.php

<nav x-data="{ open: false }" class="bg-white border-b border-gray-100">
    ...
    
   <!-- Settings Dropdown -->
    <div class="hidden sm:flex sm:items-center sm:ms-6">
        <x-dropdown align="right" width="48">
            <x-slot name="trigger">
                <button class="inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-gray-500 dark:text-gray-400 bg-white dark:bg-gray-800 hover:text-gray-700 dark:hover:text-gray-300 focus:outline-none transition ease-in-out duration-150">
                    @php($languages = ['en' => 'English', 'fr' => 'French', 'it' => 'Italian','zh_CN'=>'中国'])
                    <div>选择语言: {{ $languages[Session::get('locale', 'en')] }}</div>

                    <div class="ms-1">
                        <svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
                            <path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
                        </svg>
                    </div>
                </button>
            </x-slot>

            <x-slot name="content">
                <x-dropdown-link :href="route('change.lang', ['lang' => 'zh_CN'])">
                    中文
                </x-dropdown-link>
                <x-dropdown-link :href="route('change.lang', ['lang' => 'en'])">
                    English
                </x-dropdown-link>
                <x-dropdown-link :href="route('change.lang', ['lang' => 'fr'])">
                    French
                </x-dropdown-link>
                <x-dropdown-link :href="route('change.lang', ['lang' => 'it'])">
                    Italian
                </x-dropdown-link>
            </x-slot>
        </x-dropdown>

        ...
    </div>
    ...
</nav>

resources/views/dashboard.blade.php

<x-app-layout>
    <x-slot name="header">
        <h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
            {{ __('messages.dashboard') }}
        </h2>
    </x-slot>

    <div class="py-12">
        <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
            <div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
                <div class="p-6 text-gray-900 dark:text-gray-100">
                    {{ __("messages.dashboard_message") }}
                </div>
            </div>
        </div>
    </div>
</x-app-layout>

resources/views/users.blade.php

<x-app-layout>
    <x-slot name="header">
        <h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
            {{ __('messages.users') }}
        </h2>
    </x-slot>

    <div class="py-12">
        <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
            <div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
                <div class="p-6 text-gray-900 dark:text-gray-100">
                    {{ __('messages.users_list') }}
                </div>
            </div>
        </div>
    </div>
</x-app-layout>

启动服务并测试

$ php artisan serve

现在,注册一个用户并进行登录,之后就可以选择语言进行切换了。

请登录后再评论