商业翻译/translatable

可翻译的 Eloquent 模型。

4.0.2 2022-12-08 13:39 UTC

README

可翻译的 Eloquent 模型

Total Downloads Build Status CircleCI StyleCI ScrutinizerCI GitHub issues GitHub release (latest SemVer) MIT License

此包提供了一种强大且透明的管理 Eloquent 中多语言模型的方法。

它利用 Laravel 加强的全局作用域将翻译属性连接到每个查询,而不是像某些替代包那样利用关系。因此,只需一个查询即可获取翻译属性,无需为翻译表创建单独的模型,这使得此包更容易使用。

快速演示

要启用模型中的翻译,您首先需要根据约定准备您的模式。之后,您可以引入 Translatable 特性

use Laraplus\Data\Translatable;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use Translatable;
}

这就完成了!无需其他配置。翻译属性将自动缓存,并且所有查询都将返回翻译属性

Post::first();
$post->title; // title in the current locale

Post::translateInto('de')->first();
$post->title; // title in 'de' locale

Post::translateInto('de')->withFallback('en')->first();
$post->title; // title in 'de' if available, otherwise in 'en'

由于翻译连接到查询,因此也可以非常容易地通过翻译属性进行过滤和排序

Post::where('body', 'LIKE', '%Laravel%')->orderBy('title', 'desc');

甚至仅返回翻译记录

Post::onlyTranslated()->all()

所有基本 CRUD 操作都提供了一些辅助函数。有关所有可用选项,请参阅下方的完整文档

版本

安装

此包可以用于 Laravel 或 Lumen 应用程序,以及任何其他使用 Laravel 数据库组件https://github.com/illuminate/database的应用程序。可以通过 composer 安装此包

composer require landinsicht/translatable

Laravel 中的配置

尽管如此,您仍然可以手动将服务提供程序添加到 /config/app.php 配置文件的 providers 键中,以便在 Laravel 中自动发现此包

'providers' => [
    // Other providers
    Laraplus\Data\TranslatableServiceProvider::class,
],

您还可以通过发布 translatable.php 配置文件来配置一些其他选项

php artisan vendor:publish --provider="Laraplus\Data\TranslatableServiceProvider" --tag="config"

打开配置文件以检查所有可用设置:https://github.com/spletna-postaja/translatable/blob/master/config/translatable.php

Laravel 之外的配置

在 Laravel 之外使用此包时,您可以使用 TranslatableConfig 类进行配置

TranslatableConfig::currentLocaleGetter(function() {
    // Return the current locale of the application
});

TranslatableConfig::fallbackLocaleGetter(function() {
    // Return the fallback locale of the application
});

您还可以调整一些其他设置。要查看所有可用选项,请检查 Laravel 的服务提供程序:https://github.com/spletna-postaja/translatable/blob/master/src/TranslatableServiceProvider.php

创建迁移

为了利用多语言模型,您需要以某种方式准备数据库表。每个可翻译表都由可翻译属性和非可翻译属性组成。虽然非可翻译属性可以正常添加到您的表中,但可翻译字段需要放在它们自己的表中,表名应遵循约定。

以下是一个针对 posts 表的示例迁移:

Schema::create('posts', function(Blueprint $table)
{
    $table->increments('id');
    $table->datetime('published_at');
    $table->timestamps();
});

Schema::create('posts_i18n', function(Blueprint $table)
{
    $table->integer('post_id')->unsigned();
    $table->string('locale', 6);
    $table->string('title');
    $table->string('body');
    
    $table->primary(['post_id', 'locale']);
});

默认情况下,翻译表必须以_i18n后缀结尾,尽管这可以在之前提到的配置文件中更改。翻译表必须始终包含指向父表的键以及一个locale字段(也可以配置),该字段将存储已翻译属性的本地化。不允许在翻译模型上使用递增键。需要定义一个包含locale和指向父模型的引用外键的复合键。您可以定义外键约束,但该软件包也可以不使用它们正常工作。

重要:请确保没有翻译属性与任何未翻译属性名称相同,因为这会破坏查询。这也适用于时间戳(不应添加到翻译表中,而应仅添加到主表中)和递增键(不允许在翻译表中)。

配置模型

为了让您的模型意识到翻译属性,您需要引入Translatable特性。

use Laraplus\Data\Translatable;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use Translatable;
}

您可以定义一个包含$translatable属性的数组,但该软件包设计为无需它也可以工作。在这种情况下,翻译属性将自动从数据库模式中确定并无限期缓存。如果您正在使用缓存方法,请不要忘记每次更改模式时清除缓存。

默认情况下,如果模型未翻译成当前本地化,则将选择回退翻译。如果没有可用的翻译,则对于所有可翻译属性将返回null。如果您想更改这种行为,您可以选择修改translatable.php配置文件或在“按模型”基础上调整行为。

class Post extends Model
{
    use Translatable;
    
    protected $withFallback = false;
    
    protected $onlyTranslated = true;
}

CRUD 操作

选择行

要选择可翻译模型的行,您可以使用所有常用的Eloquent查询助手。可翻译属性将以您的当前本地化返回。有关如何在Laravel中配置本地化的更多信息,请参阅官方文档:https://laravel.net.cn/docs/6.0/localization

Post::where('active', 1)->orderBy('title')->get();

查询助手

默认情况下,上述查询还将返回当前或回退本地化中没有翻译的记录。要仅返回翻译行,您可以更改defaults.only_translated配置选项为true,或使用onlyTranslated()查询助手。

Post::onlyTranslated()->get();

有时您可能想完全禁用回退翻译。为此,您可以更改defaults.with_fallback配置选项为false,或使用withoutFallback()查询助手。

Post::withoutFallback()->get();

上述两个助手都有它们的对立形式:withUntranslated()withFallback()。您还可以为withFallback()助手提供一个可选的$locale参数,以更改默认回退本地化。

Post::withUntranslated()->withFallback()->get();
Post::withUntranslated()->withFallback('de')->get();

有时您可能希望以不同于当前本地化的本地化检索翻译。为了实现这一点,您可以使用translateInto($locale)助手。

Post::translateInto('de')->get();

如果您根本不需要翻译属性,您可以使用withoutTranslations()助手,这将从您的查询中删除可翻译的全局作用域。

Post::withoutTranslations()->get();

按翻译属性过滤和排序

通常,您可能希望按翻译属性过滤查询结果。此软件包允许您使用所有常用的Eloquent where子句。即使使用回退翻译,这也会起作用,因为where子句中的所有列都将自动包裹在ifnull语句中,并使用适当的表名作为前缀。

Post::where('title', 'LIKE', '%Laravel%')->orWhere('description', 'LIKE', '%Laravel%')->get();

相同的逻辑也适用于order by子句,它们也将自动转换为正确的格式。

Post::orderBy('title')->get();

注意:如果您使用whereRaw子句,我们无法自动格式化您的表达式,因为我们不解析whereRaw表达式。相反,您需要手动包含适当的表前缀。

插入行

在当前本地化中创建新模型时,您可以使用正常的Laravel语法,就像您正在向单个表中插入行一样。

Post::create([
    'title'        => 'My title',
    'published_at' => Carbon::now(),
]);

如果您想将记录存储在替代本地化中,您可以使用createInLocale($locale, $attributes)助手。

Post::createInLocale('de', [
    'title'        => 'Title in DE',
    'published_at' => Carbon::now(),
]);

通常,您需要将新记录及其所有翻译一起存储。为此,您可以将可翻译属性作为 create() 方法的第二个参数列出。

Post::create([
    'published_at' => Carbon::now()
], [
    'en' => ['title' => 'Title in EN'],
    'de' => ['title' => 'Title in DE'],
]);

上述所有助手也有它们的 force 形式,允许您绕过大量赋值保护。

Post::forceCreate([/*attributes*/], [/*translations*/]);
Post::forceCreateInLocale($locale, [/*attributes*/]);

更新行

在当前区域设置中更新记录就像更新单个表一样简单。

$user = User::first();

$user->title = 'New title';
$user->save();

如果您想更新另一个区域设置的记录,可以使用 saveTranslation($locale, $attributes) 助手,该助手将更新现有翻译或创建新的(如果尚不存在)。

$user = User::first();

$user->saveTranslation('en', [
    'title' => 'Title in EN'
]);

$user->saveTranslation('de', [
    'title' => 'Title in DE'
]);

还有一个可用的 forceSaveTranslation($locale, $attributes) 助手,可以绕过大量赋值保护。

要一次性更新多行,您还可以使用查询构建器。

User::where('published_at', '>', Carbon::now())->update(['title' => 'New title']);

要使用查询构建器更新不同的区域设置,可以调用 transleteInto($locale) 助手。

User::where('published_at', '>', Carbon::now())->translateInto('de')->update(['title' => 'New title']);

删除行

删除行非常简单。按照常规操作进行,翻译将与父行一起自动删除。

$user = User::first();

$user->delete();

要一次性删除多行,您还可以使用查询构建器。翻译将自动清理。

User::where('published_at', '>', Carbon::now())->delete();

翻译作为关系

有时,您可能希望检索某个特定模型的全部翻译。幸运的是,该包实现了 hasMany 关系,这可以帮助您做到这一点。

$user = $user->first();

foreach ($user->translations as $translation) {
    echo "Title in {$translation->locale}: {$translation->title}";
}

当您希望访问特定区域设置的属性时,可用 translate($locale) 助手。

$user = $user->first();

$user->translate('en')->title; // Title in EN
$user->translate('de')->title; // Title in DE

当使用关系时,您通常希望在查询中不连接翻译属性而预加载它。有一个 withAllTranslations() 助手可以实现这一点。

User::withAllTranslations()->get();

注意:目前对使用关系更新和插入新记录的支持有限。相反,您可以使用上述描述的助手。

作者和维护

该项目的作者和主要开发人员是 Anže Časar

该项目由 Spletna postaja 支持,这是一家网络开发公司。

此项目由 Spletna postaja 支持,这是一家网站开发公司,也从事 网站制作在线商店制作

Twitter

许可证

此项目是开源软件,根据 MIT 许可证 许可。

MIT License