如何在 Eloquent 中添加多语言支持
发布于 作者: Freek Van der Herten
您知道世界上有许多国家拥有不止一种官方语言吗?例如,我的祖国比利时有三种:法语、荷兰语和德语。大多数比利时人也说英语。
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 的包的 README 文件中的示例。仍然渴望了解更多知识?深入研究他的包代码。它并不难理解,而且您会从中吸取很多知识。