igaster/laravel-translate-eloquent

v1.2.8 2019-10-25 13:37 UTC

This package is auto-updated.

Last update: 2024-08-26 00:17:03 UTC


README

Laravel License Downloads Build Status Codecov

在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);
} 

待办事项

  • 级联删除模型 + 翻译 已修复
  • 请求多个键的预加载...
  • 有想法吗?给我发个请求...