您知道世界上许多国家拥有不止一种官方语言吗?例如,我的祖国比利时有三种:法语、荷兰语和德语。大多数比利时人也会说英语。
Laravel 的 Eloquent ORM 是 Laravel 中一个非常强大的部分。不幸的是,它没有开箱即用地提供对多语言模型的支持。自己添加该功能并不难。
首先让我们看看没有多语言支持的迁移。
Schema::create('articles', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->text('text'); $table->timestamps();});
我们可以通过为特定语言添加列来轻松地使表保存多种语言。
Schema::create('articles', function (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();});
现在,此表支持以英语和法语存储文本。但是,这种方法有一个重大缺点:每次您想要添加对新语言的支持时,都需要在所有具有多语言支持的表中添加字段。当语言数量开始增长或您有许多多语言表时,这非常麻烦。
更好的方法是将必须翻译的字段分离到另一个表中。
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');});
使用此迁移,您无需在应用程序需要支持额外的语言时创建额外的字段。
locale
字段用于确定存储记录的语言。在这篇文章后面的示例中,我们将在这个字段中存储一个 ISO 代码。
添加具有级联删除的外部键将确保当 articles
表中的记录被删除时,它对应的翻译也将被删除。
好的,现在数据库已准备好存储可翻译的内容,让我们考虑一下我们希望如何使用它。
$frenchText = $article->getTranslation('fr')->text;
这很好,而且可读。但是我们可以做得更好。如果文章模型在应用程序的语言环境为法语时返回文本的法语翻译,将会非常有用。
app()->setLocale('fr');$frenchText = $article->text;
这将使处理可翻译数据变得更加容易。考虑一下这个小视图。
The article with title {{ $article->title }} is {{ $this->online ? 'online' : 'offline' }}.
请注意,使用翻译后的字段和未翻译后的字段没有区别。很好!
您可以自己创建允许这种行为的函数,但是 Dimitris Savvopoulos 创建了一个名为 laravel-translatable 的包,它可以完成所有这些以及更多功能。我在每个项目中都使用它。
在 安装服务提供者 之后,您必须更新您的模型以使用 Translatable
特性。该模型还应该具有一个 $translatableAttributes
属性,其中包含一个包含可以翻译的字段名称的数组。
// app/Article.phpclass Article extends Model{ use \Dimsav\Translatable\Translatable; public $translatedAttributes = ['name', 'text']; ...} // app/ArticleTranslation.phpclass ArticleTranslation extends Model{ public $timestamps = false; ...}
现在所有设置都已完成,我们可以存储一些新的可翻译文章。如果您正在按照步骤操作,请将此路由添加到您的 Laravel 应用程序中。
Route::get('create', function($locale) { $article = new Article(); $article->online = true; $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!';});
浏览到 ‘/create’ 后,您会在数据库中看到 articles
表保存了一条记录。article_translations
表包含三条记录:上面示例中每个语言环境对应一条记录。
现在让我们检索翻译。将此路由添加到您的 Laravel 应用程序中。
Route::get('{locale}', function($locale) { app()->setLocale($locale); $article = Article::first(); return view('article')->with(compact('article'));});
添加一个带有以下内容的 article.blade.php
视图。
<h1>{{ $article->name }}</h1>{{ $article->text }}
当您浏览到 ‘/en’ 时,您将看到文章的英语翻译。浏览到 ‘/nl’、‘/fr’ 或 ‘/de’ 以查看这些语言环境的本地化文章。
恭喜!您现在已经学会了如何向 Eloquent 模型添加多语言支持。我在 GitHub 上创建了一个存储本文所有示例的仓库。如果您想了解更多信息,我建议您阅读 Dimitris 的包自述文件中的示例。仍然渴望获得更多知识?深入研究他在 GitHub 上的包代码。它并不难理解,您可以从中学到很多东西。