How to use multiple locales in your Laravel website
Bài đăng này đã không được cập nhật trong 7 năm
Giới thiệu
Laravel mặc định hỗ trợ một ngôn ngữ hiển thị trên trang web là en
, bài viết này mình sẽ đưa ra các bước thực hiện việc thêm các ngôn ngữ khác cho trang web một cách dễ dàng.
Mỗi ngôn ngữ sẽ có một url kiểu như: domain.com/{locale}
Các bạn chỉ cần copy và chạy thử vì code khá dễ hiểu.
Bước 1: Add your locales
Mở config/app.php
và thêm dòng dưới đây vào ngay dưới dòng 'locale' => 'en',
:
'locales' => explode(',', env('APP_LOCALES', 'id,my,th')),
Đoạn code trên mình sẽ lấy giá trị của APP_LOCALES khai báo trong file .env, nếu không có giá trị thì sẽ lấy giá trị default là 'id,my,th'
đại diện cho 3 ngôn ngữ mình muốn sử dụng là Indonesia, Malaysia, Thailand.
Ngoài ra, trong file app.php
này còn khai báo thêm 1 biến 'fallback_locale' => 'en',
, nó chính là ngôn ngữ mặc định trả về nếu một chuỗi chưa được dịch trong locale của bạn.
Bước 2: Prefix your routes
Bước tiếp theo là thêm prefix cho routes của bạn, nghĩa là thêm tiền tố locale cho url trong trang web của bạn. Để làm được việc này thì bạn cần phải thay đổi method map
bên trong app/Providers/RouteServiceProvider.php
như sau:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Route;
use Illuminate\Http\Request;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
class RouteServiceProvider extends ServiceProvider
{
//...
/**
* Define the routes for the application.
*
* @return void
*/
public function map(Request $request)
{
$this->mapApiRoutes();
$this->mapWebRoutes($request);
//
}
/**
* Define the "web" routes for the application.
*
* These routes all receive session state, CSRF protection, etc.
*
* @return void
*/
protected function mapWebRoutes(Request $request)
{
$locale = $request->segment(1);
$locale = strtolower($locale);
//kiểm tra locale đó có nằm trong mảng locales đã khai báo
if ($locale && in_array($locale, config('app.locales'))) {
$this->app->setLocale($locale); //set đúng locale đó
}
Route::middleware('web')
->namespace($this->namespace)
->prefix('{locale}') //thêm tiền tố locale cho url
->group(base_path('routes/web.php'));
}
//...
}
Bước 3: Create a locale middleware
Tạo file Locale.php
trong middleware bằng dòng lệnh sau:
php artisan make:middleware Locale
Rồi các bạn mở file đó trong app/Http/Middleware/Locale.php
:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Foundation\Application;
class Locale
{
private $app;
public function __construct(Application $app)
{
$this->app = $app;
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
// Make sure current locale exists.
$locale = $request->segment(1);
$locale = strtolower($locale);
if (!in_array($locale, config('app.locales'))) {
return abort(404);
}
$this->app->setLocale($locale);
return $next($request);
}
}
Và để middleware này hoạt động trên tất cả các requests thì ta phải add nó vào trong thuộc tính $routeMiddleware
bên trong app/Http/Kernel.php
:
protected $routeMiddleware = [
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'checkType' => \App\Http\Middleware\CheckType::class,
'locale' => \App\Http\Middleware\Locale::class,
];
Bước 4: Defining Translation Strings
Chỉ cần 3 bước trên là các bạn đã tạo xong multiple locales rồi đó. Giờ chúng ta thử tạo các string để test trên từng ngôn ngữ xem nó có hoạt động đúng như ta mong muốn hay chưa nhé.
Mình thử thêm 1 folder ngôn ngữ id
như dưới đây
/resources
/lang
/en
messages.php
/id
messages.php
en/messages.php
:
<?php
return [
'hello' => 'Hello',
];
id/messages.php
:
<?php
return [
'hello' => 'Halo',
];
Rồi thử cho hiển thị trên view welcome.blade.php
:
{{ trans('messages.hello') }}
Tiếp đến các bạn nhập link: localhost/id
và localhost/en
để xem có gì khác biệt nhé.
Đối với những trang web có lượng dịch lớn, việc định nghĩa những short key như trên dễ bị trùng hay gây ra nhầm lẫn khi lấy chúng, vì lý do này, Laravel cũng cung cấp hỗ trợ xác định chuỗi dịch bằng cách sử dụng bản dịch "mặc định" của chuỗi làm khoá. Các file dịch sẽ không phải là các file php thông thường nữa mà nó sẽ là các file json, với key là cụm từ tham chiếu, value là cụm từ ứng với ngôn ngữ bạn cần dịch.
Ví dụ bạn cần tạo 1 file id.json để chuyển ngôn ngữ sang tiếng Indo:
id.json
:
{
"I love programming.": "Me encanta programar."
}
Lúc đó trong file .blade bạn sẽ gọi nó ra bằng cách: {{ __('I love programming.') }}
hoặc @lang('I love programming.')
.
Bạn cũng có thể truyền thêm các tham số vào trong text cần dịch thì bạn chỉ cần làm như sau:
id.json
:
{
"hello" : "Halo :name",
}
Sau đó ngoài .blade bạn sẽ truyền thêm tham số vào khi gọi nó {{ __('hello', ['name' => 'Trang'] }}
Nhưng nhược điểm của phương pháp này là chỉ có thể dịch ở dạng key: value
, value chỉ có thể là 1 chuỗi chứ không thể là một object. Còn với cách tạo folder trans cho từng nước thì có thể khai báo dạng key: value mà value có thể là 1 mảng và bạn có thể dễ dàng tham chiếu tới nó như dưới đây:
en/messages.php
:
return [
'button' => [
'create' => 'Create',
'update' => 'Update',
],
];
Trong file .blade chỉ cần lấy {{ trans('messages.button.create') }}
là được.Tùy từng mục đích sử dụng mà các bạn có thể chọn 1 trong 2 cách trên.
Bài viết của mình đến đây là kết thúc. Cảm ơn các bạn đã theo dõi!
Tham khảo
All rights reserved