slivka-b / laravel-translatable
[分支] 该包提供使用单个数据库表将您的 Eloquent 模型翻译成不同语言的功能。
Requires
- php: ^8.0
- laravel/framework: ^10.0
- slivka-b/laravel-uuid: ^0.1
Requires (Dev)
- friendsofphp/php-cs-fixer: ^2.16
- mockery/mockery: ^1.2
- orchestra/testbench: ^5.0|^6.0
- phpunit/phpunit: ^8.0
This package is auto-updated.
Last update: 2024-09-21 16:38:54 UTC
README
此包是从 nevadskiy/laravel-translatable 分支出来的。
该包提供使用单个数据库表将您的 Eloquent 模型翻译成不同语言的功能。
🍬 特点
- 自动解决当前区域的模型翻译。
- 无需重写现有的迁移、模型或视图。
- 将所有翻译存储在单个 'translations' 表中。
- 与模型访问器 & 变更器 & 转换器一起工作,甚至与 JSON 一起工作。
- 与路由模型绑定一起工作。
- 存档翻译以改善搜索体验。
- 提供有用的事件。
⚙️ 演示
$book = Book::create(['title' => 'Book about giraffes']); // Storing translations app()->setLocale('es'); $book->title = 'Libro sobre jirafas'; $book->save(); // Reading translations app()->setLocale('es'); echo $book->title; // 'Libro sobre jirafas' app()->setLocale('en'); echo $book->title; // 'Book about giraffes'
✅ 要求
- Laravel
9.0
或更高版本 - PHP
8.0
或更高版本
🔌 安装
- 通过 composer 安装此包。
composer require imcity-tech/laravel-translatable
- 可选。如果您不打算为具有 UUID 主键的模型使用翻译,请执行以下操作:
- 发布包迁移
php artisan vendor:publish --tag=translatable
- 在发布的迁移中将行
$table->uuidMorphs('translatable');
替换为$table->morphs('translatable');
。
- 运行迁移命令。
php artisan migrate
🔨 使模型可翻译
- 将
HasTranslations
特性添加到您想要使可翻译的模型中。
<?php namespace App; use Illuminate\Database\Eloquent\Model; use Nevadskiy\Translatable\HasTranslations; class Post extends Model { use HasTranslations; }
- 将
$translatable
数组添加到您的模型中,包含您想要可翻译的属性。
/** * The attributes that can be translatable. * * @var array */ protected $translatable = [ 'title', 'description', ];
最终模型可能看起来像这样
<?php namespace App; use Illuminate\Database\Eloquent\Model; use Nevadskiy\Translatable\HasTranslations; class Post extends Model { use HasTranslations; protected $translatable = [ 'title', 'description', ]; }
📄 文档
默认区域值按常规存储在原始表中。
每个可翻译模型的非默认区域的值存储在单个 translations
表中。
该包从 config('app.fallback_locale')
值中获取默认区域。
自动使用可翻译属性存储和检索模型的翻译
$book = Book::where('title', 'Book about birds')->first(); app()->setLocale('ru'); $book->update(['title' => 'Книга о птицах']); echo $book->title; // 'Книга о птицах' app()->setLocale('en'); echo $book->title; // 'Book about birds'
手动存储和检索模型的翻译
$book = Book::where('title', 'Book about dolphins')->first(); $book->translate('title', 'Книга о дельфинах', 'ru'); echo $book->getTranslation('title', 'ru'); // 'Книга о дельфинах'
读取翻译的方法
创建可翻译模型
请注意,即使当前区域不同,可翻译模型也将始终在 默认 区域中创建。任何翻译都可以仅附加到 现有 模型。
app()->setLocale('de'); Book::create(...); // This will persist model as usual with the default application locale.
显示模型集合
该包自动为您预加载当前区域的翻译,因此您可以像平常一样轻松检索模型集合。
// In a controller app()->setLocale('ru'); $books = Book::paginate(20); // In a view @foreach ($books as $book) {{ $book->title }} // Shows a title in the current locale OR in the default locale if a translation is missing. @endforeach
翻译与模型访问器一起工作
class Book extends Model { // ... public function getTitleAttribute() { return Str::ucfirst($this->attributes['title']); } } $book = Book::create(['title' => 'book about birds']); $book->translate('title', 'книга о птицах', 'ru'); // Using attribute with the current locale app()->setLocale('ru'); echo $book->title; // 'Книга о птицах' // Using getTranslate method echo $book->getTranslation('title', 'ru'); // 'Книга о птицах'
翻译也与模型变更器一起工作
class Book extends Model { public function setDescriptionAttribute($description) { $this->attributes['description'] = Str::substr($description, 0, 10); } } $book = Book::create(['description' => 'Very long description']); $book->translate('description', 'Очень длинное описание', 'ru'); // Using attribute with the current locale app()->setLocale('ru'); echo $book->description; // 'Очень длин' // Using getTranslation method echo $book->getTranslation('description', 'ru'); // 'Очень длин'
删除未使用的翻译
该包自动删除删除的模型的翻译,并尊重 softDeletes,但如果使用查询构建器删除了可翻译模型,其翻译将存在于数据库中。要手动删除所有未使用的翻译,请运行 php artisan translatable:remove-unused
命令。
查询没有翻译的模型
有时您可能需要查询没有 translations
关系的可翻译模型。您可以使用 withoutTranslations
范围来实现这一点。
$books = Book::withoutTranslations()->get();
查询翻译
您可以通过可翻译属性执行可翻译模型的查询。
$books = Book::whereTranslatable('title', 'Книга о жирафах')->get();
它也可以与默认区域的值一起工作。
如果您只想按特定区域查询行,您应该自己传递它。
$books = Book::whereTranslatable('title', 'Книга о жирафах', 'ru')->get();
否则,查询构建器将返回所有可用区域中匹配的行。
您还可以使用不同的运算符来查询翻译。
$books = Book::whereTranslatable('title', 'Book about%', null, 'LIKE')->get(); // or $books = Book::whereTranslatable('title', 'Книги о%', 'ru', 'LIKE')->get();
排序翻译
按当前区域的可翻译属性对模型进行排序。
$books = Book::orderByTranslatable('title')->get();
按特定区域的可翻译属性对模型进行排序。
$books = Book::orderByTranslatable('title', 'desc', 'de')->get();
对于更复杂的查询 - 随意使用 Laravel 关系查询。
禁用自动加载
如果您不想在交互可翻译属性时自动加载或保存翻译,可以禁用此功能。
要为特定模型禁用,请在您的模型中覆盖如下 autoLoadTranslations
或 autoSaveTranslations
方法。
class Post extends Model { use HasTranslations; protected $translatable = ['title']; public function autoLoadTranslations() { return false; } public function autoSaveTranslations() { return false; } }
或全局应用于所有模型。
use Nevadskiy\Translatable\Translatable; class AppServiceProvider extends ServiceProvider { public function boot() { $this->app[Translatable::class]->disableAutoLoading(); $this->app[Translatable::class]->disableAutoSaving(); } }
归档翻译
有时,归档一些不会自动解决的翻译,但可用于搜索功能是有用的。例如,您可以使用以下代码手动存储归档翻译
$post = Post::first(); $post->archiveTranslation('title', 'Old title', 'en');
现在 旧标题
与允许使用 whereTranslatable
范围查找帖子的帖子相关联
Post::whereTranslatable('title', 'Old title')->get();
当不知道区域设置时,您也可以将 null
作为 archiveTranslation
方法的第三个参数传递。如果不传递 null
,则将使用当前区域设置。
路由模型绑定
可翻译模型可以很容易地使用 路由模型绑定 功能解析。
您需要做的全部是设置用于查询模型的所需区域设置,在请求到达 Illuminate\Routing\Middleware\SubstituteBindings::class
中间件之前使用 before。
最简单的解决方案是创建一个新的中间件,例如 SetLocaleMiddleware
,将其附加到您想要解析可翻译模型的路由上,并在 app/Http/Kernel.php
文件中注册中间件,在 \Illuminate\Routing\Middleware\SubstituteBindings::class
类之上。
它可能看起来像这样
// app/Http/Middleware/SetLocaleMiddleware.php public function handle($request, Closure $next) { // Setting the current locale from cookie app()->setLocale($request->cookie('locale')); }
// app/Http/Kernel.php protected $middlewareGroups = [ 'web' => [ // ... default middleware stack \App\Http\Middleware\SetLocaleMiddleware::class, // <--- your middleware \Illuminate\Routing\Middleware\SubstituteBindings::class, // <--- bindings middleware ], ]; protected $middlewarePriority = [ // ... default middleware stack \App\Http\Middleware\SetLocaleMiddleware::class, // <--- your middleware above \Illuminate\Routing\Middleware\SubstituteBindings::class, // <--- bindings middleware below ];
有关排序中间件的更多信息,请参阅 这里。
// routes/web.php Route::get('posts/{post:slug}', 'PostsController@show');
// app/Http/Controllers/PostController.php public function show(Post $post) { // Post model is resolved by translated slug using the current locale. }
使用形态映射
建议为所有可翻译模型使用 morph map
以最小化数据库与应用程序结构之间的耦合。
use Illuminate\Database\Eloquent\Relations\Relation; Relation::morphMap([ 'posts' => Post::class, 'categories' => Category::class, ]);
有关形态映射的更多信息,请参阅 这里。
📑 更新日志
请参阅 更新日志 以获取有关最近更改的更多信息。
☕ 贡献
请参阅 贡献指南 以获取更多信息。
🔓 安全性
如果您发现任何与安全性相关的问题,请通过 电子邮件 而不是使用问题跟踪器与我联系。
📜 许可证
MIT 许可证(MIT)。有关更多信息,请参阅 许可证。