igaster / laravel-translate-eloquent
描述
Requires
- illuminate/contracts: ~5.1 | ^6.0
Requires (Dev)
- orchestra/testbench: ~4.0
- phpunit/phpunit: ^8.0
README
在Laravel模型中翻译任何数据库列。您只需一个额外的表来存储所有模型的翻译。
安装
编辑项目的 composer.json
文件以要求
"require": {
"igaster/laravel-translate-eloquent": "~1.0"
}
使用 composer update
安装
设置
第1步:创建翻译表
使用 artisan make:migration translations
创建新的迁移并创建以下表
public function up() { Schema::create('translations', function (Blueprint $table) { $table->increments('id'); $table->integer('group_id')->unsigned()->index(); $table->text('value')->nullable(); $table->string('locale', 2)->index(); // Can be any length! }); } public function down() { Schema::drop('translations'); }
迁移数据库: php artisan migrate
第2步:将可翻译键添加到您的模型中
在迁移中定义任何数量的整数键,您想要存储翻译。实际上,它们是到可翻译的.group_id的外键。以下是一个示例迁移,它将创建一个可翻译键
$table->integer('key')->unsigned()->nullable();
第3步:设置您的模型
将 TranslationTrait
特性应用到您想要具有可翻译键的任何模型,并将这些键添加到 $translatable
数组中
class ExampleModel extends Eloquent { use \igaster\TranslateEloquent\TranslationTrait; protected static $translatable = ['key']; }
现在您可以使用翻译键了!
使用方法
当您访问一个可翻译键时,其翻译将在应用程序的当前区域设置中检索。如果没有定义翻译,则使用Laravel的 'app.fallback_locale'。如果没有找到翻译,则返回空字符串。所以很简单!
处理翻译
$model->key='Monday'; // Set the translation for the current Locale. $model->key; // Get the translation for the current Locale $model->translate('de')->key = 'Montag'; // Set translation in a locale $model->translate('de')->key; // Get translation in a locale $model->translate('de','en')->key; // Get translation in a locale / fallback locale $model->key = [ // Set a batch of translations 'el' => 'Δευτέρα', 'en' => 'Monday', 'de' => 'Montag', ];
重要提示
- 当您第一次创建新的翻译时,您必须保存模型以持久化关系:
$model->save();
。更新翻译或添加新区域时不需要这样做。 - 当您为翻译设置值时,将在
translations
表中创建/更新条目。
创建/更新翻译模型
// Create a model translated to current locale Day::create([ 'name' => 'Πέμπτη', ]); // Create a model with multiple translations Day::create([ 'name' => [ 'el' => 'Σάββατο', 'en' => 'Saturday', ] ]);
您也可以使用 $model->update();
以相同的方式。
Laravel & 区域设置
Laravel区域函数的简要回顾(区域在 app.php
配置文件中定义)
App::setLocale('de'); // Set curent Locale App::getLocale(); // Get curent Locale Config::set('app.fallback_locale','el'); // Set fallback Locale
处理 Translations
对象
您可以使用 igaster\TranslateEloquent\Translations
对象实现相同的功能。
$translations = $model->translations('key'); // Get instance of Translations $translations->in('de'); // Get a translation in a locale $translations->set('el', 'Δευτέρα'); // Set a translation in a locale $translations->has('el'); // Check if a translation exists $translations->set([ // Set a batch of translations 'el' => 'Δευτέρα', 'en' => 'Monday', 'de' => 'Montag', ]);
想要深入了解内部结构?
Translations
对象包含一个键的所有翻译。多个翻译根据相同的group_id
值分组。Translation
对象是一个Eloquent模型(映射到translations
表),它代表一个键在一个区域中的单个翻译。
$translations = new Translations(); // Create a new Translations collection $translations = new Translations($group_id); // or load Translations with $group_id $translations->group_id; // column `translations.group_id` groups all translations for a key $translation = $translations->get('en'); // Get instance of `Translation` (a single translation) $translation->id; // From this model you have access to the actual translations record $translation->value='New Value'; // in your database. You can perform any raw opperation on it.
预加载
您可以使用这些查询范围,就像您想要检索具有相同查询的翻译一样。
Day::findWithTranslation(1,'name'); // Day with id 1 with 'name' translated in the current Locale Day::firstWithTranslation('name'); // First Day from the query with 'name' translated in the current Locale Day::getWithTranslation('name'); // Collection of Day with 'name' translated in the current Locale Day::allWithTranslation('name'); // Collection of Day with 'name' translated in the current Locale // You can specify a locale as an extra parameter in all above scopes: Day::firstWithTranslation('name', 'en'); // First Day from the query with 'name' translated in English // The column name is optional and defaults to first item in your `$translatable` array: Day::firstWithTranslation(); // First Day from the query with the first $translatable column (='name') // translated in the current Locale
注意
- 上面的查询范围应该用作查询的端点,因为它们将返回模型或集合。
- 预加载旨在在从数据库中检索模型时减少读取操作的单个查询。它使用JOIN语句,而不是Eloquent预加载时的两个后续查询。此实现的局限性是,您只能请求单个字段的翻译。
- 如果您的模型有多个应翻译的键,则后续的所有读取操作都将导致额外的查询。
性能考虑
请注意,在考虑数据库性能时,使用单个表格存储所有翻译并非最佳架构。每个翻译都需要对数据库进行单独的查询。如果性能是个问题,您可以检查其他实现方式,如dimsav/laravel-translatable
处理 __get() & __set() 冲突
此特性利用了 __get()
和 __set()
魔法方法来实现其功能。但是,如果您想在模型或另一个特性中实现这些功能,PHP 将会抱怨冲突。为了解决这个问题,在导入特性时,您需要隐藏特性的方法,并从您的 __get()
/ __set()
方法中手动调用它们
use igaster\TranslateEloquent\TranslationTrait { __get as private; __set as private; }
并从您的 __get()
/ __set()
方法中手动调用它们
//--- copy these in your model if you need to implement __get() __set() methods public function __get($key) { // Handle Translatable keys $result=$this->translatable_get($key); if ($this->translatable_handled) return $result; //your code goes here return parent::__get($key); } public function __set($key, $value) { // Handle Translatable keys $this->translatable_set($key, $value); if ($this->translatable_handled) return; //your code goes here parent::__set($key, $value); }
待办事项
级联删除模型 + 翻译已修复- 请求多个键的预加载...
- 有想法吗?给我发个请求...