HỖ TRỢ ĐA NGÔN NGỮ TRONG LARAVEL VỚI ELOQUENT

HỖ TRỢ ĐA NGÔN NGỮ TRONG LARAVEL VỚI ELOQUENT

Laravel Eloquent ORM là một phần rất mạnh mẽ trong Laravel. Mặc định Laravel không hỗ trợ đa ngôn ngữ sẵn cho chúng ta. Tuy nhiên, cũng không quá khó để thêm tính năng đó vào Laravel.
Trước tiên chúng ta xét một bảng không hỗ trợ đa ngôn ngữ:
1
2
3
4
5
6
Schema::create('articles', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name');
    $table->text('text');
    $table->timestamps();
});
Chúng ta có thể dễ dàng làm cho bảng đó có thể hỗ trợ đa ngôn ngữ bằng cách thêm một số cột như sau:
1
2
3
4
5
6
7
8
9
Schema::create('articles', <strong>function</strong> (Blueprint $table) {
    $table->increments('id');
    $table->string('name_en');
    $table->text('text_en');
    $table->string('name_fr');
    $table->text('text_fr');
    $table->boolean('online');
    $table->timestamps();
});
Hiện tại, bảng của chúng ta đã có thể lưu các nội dung đa ngôn ngữ. Nhưng cách này vẫn còn khá hạn chế: mỗi lần chúng ta muốn hỗ trợ thêm ngôn ngữ mới thì chúng ta cần phải thêm trường mới vào các bảng cần lưu nội dung đa ngôn ngữ
Một cách tốt hơn để xử lý vấn đề là tách riêng các trường cần lưu các giá trị đa ngôn ngữ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Schema::create('articles', <strong>function</strong> (Blueprint $table) {
    $table->increments('id');
    $table->boolean('online');
    $table->timestamps();
});
Schema::create('article_translations', <strong>function</strong> (Blueprint $table) {
    $table->increments('id');
    $table->integer('article_id')-&gt;unsigned();
    $table->string('locale')-&gt;index();
    $table->string('name');
    $table->text('text');
    $table->unique(['article_id','locale']);
    $table->foreign('article_id')->references('id')->on('articles')->onDelete('cascade');
});
Sử dụng cách này chúng ta không cần tạo thêm trường khi ứng dụng của cúng ta cần hỗ trợ thêm ngôn ngữ mới
Trường locate dùng để xác định ngôn ngữ của bản ghi.
Hiện tại, ứng dụng của chúng ta đã sẵn sang để lưu các nội dung đa ngôn ngữ, đây là cách chúng ta lấy nội dung đa ngôn ngữ
1
$frenchText = $article->getTranslation('fr')->text;
Cú pháp này tương đối dễ đọc và dễ hiểu. Tuy nhiên chúng ta có thể làm chúng tốt hơn nữa:
1
2
app()->setLocale('fr');
$frenchText = $article->text;
Hãy chú ý là không có sự khác biệt giữa cách lấy nội dung có và không hỗ trợ đa ngôn ngữ.
Bạn có thể tự tạo cho mình một hàm xử lý việc trên. Tuy nhiên thì có một package thực hiện việc này là  laravel-translatable
Sau khi cài đặt, chúng ta cần phải cập nhật model để sử dụng Translatable trait
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// app/Article.php
 
class Article extends Model
{
    use Dimsav\Translatable\Translatable;
    public $translatedAttributes = ['name', 'text'];
 
    ...
}
 
// app/ArticleTranslation.php</em>
 
class ArticleTranslation extends Model
{
    public $timestamps = false;
    ...
}
Sau khi cài đặt xong, chúng ta có thể lưu các nội dung cần hỗ trợ đa ngôn ngữ
1
2
3
4
5
6
7
8
9
10
11
12
Route::get('create', <strong>function</strong>($locale) {
$article = <strong>new</strong> Article();
$article->online = <strong>true</strong>;
$article->save();
foreach (['en', 'nl', 'fr', 'de'] as $locale) {
   $article->translateOrNew($locale)->name = "Title {$locale}";
   $article->translateOrNew($locale)->text = "Text {$locale}";
}
$article->save();
echo 'Created an article with some translations!';
 
});
Chúng ta có thể thấy trong database sau khi chúng ta truy cập đường dẫn ‘/create’, bảng article có 1 bản ghi. Bảng article_translations có 3 bản ghi.
Giờ chúng ta sẽ lấy nội dung đa ngôn ngữ:
1
2
3
4
5
Route::get('{locale}', function($locale) {
    app()->setLocale($locale);
    $article = Article::first();
    return view('article')->with(compact('article'));
});
Thêm view mới với tên là article.blade.php với nội dung như sau
1
2
{{ $article->name }}
{{ $article->text }}
Nguồn: laravel-news.com

Nhận xét