接近 / laravel-translatable
Laravel 多语言模型包
Requires
- php: >=5.4.0
- illuminate/support: ~5.1
Requires (Dev)
- orchestra/testbench: ~3.0
- phpunit/phpunit: ~4.0
This package is not auto-updated.
Last update: 2018-02-16 13:29:01 UTC
README
这是一个为可翻译模型提供的 Laravel 包。如果您想将模型的翻译存储到数据库中,这个包适合您。
演示
获取翻译属性
$greece = Country::where('code', 'gr')->first(); echo $greece->translate('en')->name; // Greece App::setLocale('en'); echo $greece->name; // Greece App::setLocale('de'); echo $greece->name; // Griechenland
保存翻译属性
$greece = Country::where('code', 'gr')->first(); echo $greece->translate('en')->name; // Greece $greece->translate('en')->name = 'abc'; $greece->save(); $greece = Country::where('code', 'gr')->first(); echo $greece->translate('en')->name; // abc
填充多个翻译
$data = [ 'code' => 'gr', 'en' => ['name' => 'Greece'], 'fr' => ['name' => 'Grèce'], ]; $greece = Country::create($data); echo $greece->translate('fr')->name; // Grèce
教程
查看laravel-news上关于laravel-translatable的教程: 如何为 Eloquent 添加多语言支持
4 步安装
第 1 步:安装包
通过执行以下命令将包添加到您的 composer.json 中。
composer require approached/laravel-translatable
接下来,将服务提供者添加到 app/config/app.php
Approached\Translatable\TranslatableServiceProvider::class,
第 2 步:迁移
在这个例子中,我们想翻译模型 Country
。我们需要一个额外的表 country_translations
Schema::create('countries', function(Blueprint $table) { $table->increments('id'); $table->string('code'); $table->timestamps(); }); Schema::create('country_translations', function(Blueprint $table) { $table->increments('id'); $table->integer('country_id')->unsigned(); $table->string('name'); $table->string('locale')->index(); $table->unique(['country_id','locale']); $table->foreign('country_id')->references('id')->on('countries')->onDelete('cascade'); });
第 3 步:模型
- 可翻译模型
Country
应该使用 特性Approached\Translatable\Translatable
。 - 翻译模型的约定是
CountryTranslation
。
// models/Country.php class Country extends Eloquent { use \Approached\Translatable\Translatable; public $translatedAttributes = ['name']; protected $fillable = ['code', 'name']; /** * The relations to eager load on every query. * * @var array */ // (optionaly) // protected $with = ['translations']; } // models/CountryTranslation.php class CountryTranslation extends Eloquent { use CompositeKeys; public $timestamps = false; protected $fillable = ['name']; public $incrementing = false; protected $primaryKey = [ 'id', 'locale' ]; }
数组 $translatedAttributes
包含在 "Translation" 模型中翻译的字段名称。
第 4 步:配置
Laravel 4.*
php artisan config:publish approached/laravel-translatable
Laravel 5.*
php artisan vendor:publish
使用此命令初始化配置并修改位于 app/config/packages/approached/laravel-translatable/translatable.php
下的创建的文件。
注意:对地区格式的限制没有任何限制。请随意使用您更喜欢的格式,例如 "eng" 而不是 "en",或 "el" 而不是 "gr"。重要的是定义您的地区并坚持使用。
配置
翻译模型
用于定义翻译模型类的约定是附加关键词 Translation
。
因此,如果您的模型是 \MyApp\Models\Country
,则默认翻译为 \MyApp\Models\CountryTranslation
。
要使用自定义类作为翻译模型,定义翻译类(包括命名空间)作为参数。例如
<?php namespace MyApp\Models; use Approached\Translatable\Translatable; use Illuminate\Database\Eloquent\Model as Eloquent; class Country extends Eloquent { use Translatable; public $translationModel = 'MyApp\Models\CountryAwesomeTranslation'; }
文档
请首先阅读安装步骤,以了解需要创建哪些类。
可用方法
// Before we get started, this is how we determine the current locale. // It is set by laravel or other packages. App::getLocale(); // 'fr' // To use this package, first we need an instance of our model $germany = Country::where('code', 'de')->first(); // This returns an instance of CountryTranslation of using the current locale. // So in this case, french. If no french translation is found, it returns null. $translation = $germany->translate(); // If an german translation exists, it returns an instance of // CountryTranslation. Otherwise it returns null. $translation = $germany->translate('de'); // If a german translation doesn't exist, it attempts to get a translation // of the fallback language (see fallback locale section below). $translation = $germany->translate('de', true); // Alias of the above. $translation = $germany->translateOrDefault('de'); // Returns instance of CountryTranslation of using the current locale. // If no translation is found, it returns a fallback translation // if enabled in the configuration. $translation = $germany->getTranslation(); // If an german translation exists, it returns an instance of // CountryTranslation. Otherwise it returns null. // Same as $germany->translate('de'); $translation = $germany->getTranslation('de', true); // Returns true/false if the model has translation about the current locale. $germany->hasTranslation(); // Returns true/false if the model has translation in french. $germany->hasTranslation('fr'); // If a german translation doesn't exist, it returns // a new instance of CountryTranslation. $translation = $germany->translateOrNew('de'); // Returns a new CountryTranslation instance for the selected // language, and binds it to $germany $translation = $germany->getNewTranslation('it'); // The eloquent model relationship. Do what you want with it ;) $germany->translations();
可用作用域
// Returns all countries having translations in english Country::translatedIn('en')->get(); // Returns all countries not being translated in english Country::notTranslatedIn('en')->get(); // Returns all countries having translations Country::translated()->get(); // Eager loads translation relationship only for the default // and fallback (if enabled) locale Country::withTranslation()->get(); // Returns an array containing pairs of country ids and the translated // name attribute. For example: // [ // ['id' => 1, 'name' => 'Greece'], // ['id' => 2, 'name' => 'Belgium'] // ] Country::listsTranslations('name')->get()->toArray(); // Filters countries by checking the translation against the given value Country::whereTranslation('name', 'Greece')->first(); // Filters countries by checking the translation against the given string with wildcards Country::whereTranslationLike('name', '%Gree%')->first();
魔法属性
要使用魔法属性,您必须在主模型中定义属性 $translatedAttributes
class Country extends Eloquent { use \Approached\Translatable\Translatable; public $translatedAttributes = ['name']; }
// Again we start by having a country instance $germany = Country::where('code', 'de')->first(); // We can reference properties of the translation object directly from our main model. // This uses the default locale and is the equivalent of $germany->translate()->name $germany->name; // 'Germany' // We can also quick access a translation with a custom locale $germany->{'name:de'} // 'Deutschland'
回退语言
如果您想在没有找到翻译时回退到默认翻译,请使用 use_fallback
键在配置中启用它。要选择默认语言,请使用 fallback_locale
键。
配置示例
return [ 'use_fallback' => true, 'fallback_locale' => 'en', ];
您还可以通过设置 $useTranslationFallback
属性来为“是否使用回退”定义每个模型默认值。
class Country { public $useTranslationFallback = true; }
基于国家的回退
从版本 v5.3 开始,可以使用基于国家的语言环境。例如,您可以有以下语言环境
- 英语:
en
- 西班牙语:
es
- 墨西哥西班牙语:
es-MX
- 哥伦比亚西班牙语:
es-CO
这些语言的配置如下所示
'locales' => [ 'en', 'es' => [ 'MX', 'CO', ], ];
我们还可以配置语言和国家之间的“粘合剂”。例如,如果我们更喜欢格式 es_MX
而不是 es-MX
,则配置应如下所示
'locale_separator' => '_',
对于使用 en-MX
格式的语言回退,有何影响?
假设我们的回退语言是 en
。现在,当我们尝试从数据库中检索 es-MX
语言环境的翻译,但不存在时,我们将不会回退到 en
的翻译。可翻译将使用 es
(es-MX
的第一部分)作为回退,并且只有在找不到任何内容时,才会返回 en
的翻译。
附加组件
多亏了社区,已经编写了一些包,使在使用表单时使用可翻译变得更容易
常见问题解答
我需要一些示例代码!
所有包功能的示例可以在 测试中使用的代码 中找到。
我需要帮助!
有任何问题或建议?请随时打开一个 问题。
我想帮忙!
您太棒了!查看存储库并回复问题。您将帮助提供出色的用户体验。 #communityWorks
我遇到了与其他特质方法冲突的情况!
可翻译完全兼容所有类型的 Eloquent 扩展,包括 Ardent。如果您需要帮助将这些扩展与可翻译一起实现,请参阅此 示例。
我如何根据翻译进行排序?
这里的一个提示是先执行 MySQL 查询,然后再执行 Eloquent 查询。
要获取按翻译字段排序的记录列表,您可以这样做
SELECT * from countries JOIN country_translations as t on t.country_id = countries.id WHERE locale = 'en' GROUP BY countries.id ORDER BY t.name desc
相应的 Eloquent 查询如下所示
Country::join('country_translations as t', 't.country_id', '=', 'countries.id') ->where('locale', 'en') ->groupBy('countries.id') ->orderBy('t.name', 'desc') ->with('translations') ->get();
我如何通过翻译字段选择国家?
例如,让我们假设我们想要找到名称等于 '葡萄牙' 的国家。
Country::whereHas('translations', function ($query) { $query->where('locale', 'en') ->where('name', 'Portugal'); })->first();
您可以在 Laravel 的 查询关系文档 中找到更多信息。
为什么在运行迁移时我遇到了 mysql 错误?
如果您看到以下 mysql 错误
[Illuminate\Database\QueryException]
SQLSTATE[HY000]: General error: 1005 Can't create table 'my_database.#sql-455_63'
(errno: 150) (SQL: alter table `country_translations`
add constraint country_translations_country_id_foreign foreign key (`country_id`)
references `countries` (`id`) on delete cascade)
那么您的表使用的是 MyISAM 引擎,该引擎不允许外键约束。MyISAM 是 5.5 版本之前 mysql 的默认引擎。自 版本 5.5 以来,默认使用 InnoDB 存储引擎创建表。
如何修复
对于已经在生产环境中创建的表,更新迁移以更改表的引擎,然后再添加外键约束。
public function up() { DB::statement('ALTER TABLE countries ENGINE=InnoDB'); } public function down() { DB::statement('ALTER TABLE countries ENGINE=MyISAM'); }
对于新表,一个快速解决方案是在迁移中设置存储引擎
Schema::create('language_translations', function(Blueprint $table){ $table->engine = 'InnoDB'; $table->increments('id'); // ... });
然而,最好的解决方案是更新您的 mysql 版本。并且 一定要确保开发和生产环境中的版本相同!