Multilingual with Laravel Eloquent
Bài đăng này đã không được cập nhật trong 3 năm
Hiện nay, yêu cầu hỗ trợ đa ngôn ngữ đã trở lên phổ biến hơn và có nhiều framework hỗ trợ việc hiển thị đa ngôn ngữ.
Bằng việc tạo ra các file, thư mục chứa nội dung đa ngôn ngữ ứng với các key
, laravel cho phép lập trình viên thể hiện trang web của mình bằng nhiều ngôn ngữ khác nhau. Tuy nhiên việc này chỉ giới hạn trong các thành phần cố định như: title
, button
, message
. Đối với việc hiển thị nôi dung hay text thì laravel chưa hỗ trợ.
Tuy nhiên, cũng không quá khó khăn để thực hiện việc này bằng tay
.
Đầu tiên, chúng ta tạo một migration
chưa hỗ trợ multilingual
:
Schema::create('articles', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->text('text');
$table->timestamps();
});
Cách đơn giản nhất để bảng articles
này hỗ trợ nhiều ngôn ngữ là chúng ta thêm các cột tương ứng cho các ngôn ngữ mà chúng ta muốn hỗ trợ. Ví dụ, chúng ta muốn hỗ trợ 2 ngôn ngữ là English
và Tiếng Việt
:
Schema::create('articles', function (Blueprint $table) {
$table->increments('id');
$table->string('name_en');
$table->text('text_en');
$table->string('name_vi');
$table->text('text_vi');
$table->boolean('online');
$table->timestamps();
});
Bây giờ, bảng này đã hộ trợ cho việc lưu text
với 2 ngôn ngữ là English
và Tiếng Việt
. Đây là cách đơn giản nhất tuy nhiên nó sẽ gặp phải nhiều vấn đề khi chúng ta muốn thêm một hoặc nhiều ngôn ngữ mới, chúng ta phải thay đổi tất cả các bảng cần hỗ trợ đa ngôn ngữ.
Có một cách tốt hơn để thực hiện việc này là chúng ta lưu các trường cần được translate
vào một bảng khác với flag chứa locale
tương ứng.
Schema::create('articles', function (Blueprint $table) {
$table->increments('id');
$table->boolean('online');
$table->timestamps();
});
Schema::create('article_translations', function (Blueprint $table) {
$table->increments('id');
$table->integer('article_id')->unsigned();
$table->string('locale')->index();
$table->string('name');
$table->text('text');
$table->unique(['article_id','locale']);
$table->foreign('article_id')->references('id')->on('articles')->onDelete('cascade');
});
Với cách trên chúng ta không cần phải thêm bất kì trường (field
) nào vào cơ sở dữ liệu nếu chúng ta cần hỗ trợ thêm ngôn ngữ nào khác.
Cột locale
sử dụng để xác định ngôn ngữ của record
trong bảng.
Chúng ta đã setup xong cơ sở dữ liệu cho các dữ liệu đa ngôn ngữ. Tiếp theo chúng ta cần lấy chúng ra tương ứng với từng ngôn ngữ.
// app/Article.php
class Article extends Model
{
...
public function articleTranslations()
{
$this->hasMany(ArticleTranslation::class, `article_id`);
}
public function getTranslation($locale = 'en')
{
return $this->articleTranslations()->where('locale', $locale)->first();
}
...
}
// Somewhere
$vietnameseText = $article->getTranslation('vi')->text;
Câu lệnh ở trên cho phép chúng ta lấy dữ liệu với ngôn ngữ vi
, cách này đã khá là ổn, tuy nhiên nó vẫn khá dài.
Chúng ta không muốn lặp đi lặp lại việc sử dụng phương getTranslation()
ở trên. Rất may mắn, chúng ta có cách khác đơn giản và tiện dụng hơn để lấy các dữ liệu đa ngôn ngữ bằng việc sử dụng Translatable Trait được viết bởi Dimitris Savvopoulos.
Thêm package vào file composer.json
bằng lệnh:
composer require dimsav/laravel-translatable
Tiếp thep, chúng ta thêm service provider
vào file app/config/app.php
:
// app/config/app.php
'providers' => [
...
Dimsav\Translatable\TranslatableServiceProvider::class,
]
...
Sau khi thêm service provider
, chúng ta cần cập nhật lại các model
để sử dụng Translatable
Trait, các model
cần phải có property $translatableAttributes
chứa các field
đa ngôn ngữ:
// app/Article.php
...
use Dimsav\Translatable\Translatable:
class Article extends Model
{
use Translatable;
public $translatedAttributes = ['name', 'text'];
...
}
// app/ArticleTranslation.php
class ArticleTranslation extends Model
{
public $timestamps = false;
...
}
app()->setLocale('vi');
$vietnameseText = $article->text;
Các bạn có thể thể thấy không có gì khác việc chúng ta lấy dữ liệu khác trong bảng như $article->online
.
Route::get('{locale}', function($locale) {
app()->setLocale($locale);
$article = Article::first();
return view('article')->with(compact('article'));
});
Trong view article.blade.php
:
<h1>{{ $article->name }}</h1>
{{ $article->text }}
Done! Vậy là chúng ta đã thực hiện xong việc lưu trữ và lấy các dữ liệu đa ngôn ngữ bằng eloquent
All rights reserved