This is a Laravel 4 package for translatable models. Its goal is to remove the complexity in retrieving and storing multilingual model instances. With this package you write less code, as the translations are being fetched/saved when you fetch/save your instance.
If you want to store translations of your models into the database, this package is for you.
!! Version 5 will be stable after laravel 5 is released
Laravel | Translatable |
---|---|
4.0.x | 4.3.x |
4.1.x | 4.4.x |
4.2.x | 4.4.x |
5.0.x | 5.x |
Getting translated attributes
$country = Country::where('iso', '=', 'gr')->first();
echo $country->translate('en')->name; // Greece
App::setLocale('en');
echo $country->name; // Greece
App::setLocale('de');
echo $country->name; // Griechenland
Saving translated attributes
$country = Country::where('iso', '=', 'gr')->first();
echo $country->translate('en')->name; // Greece
$country->translate('en')->name = 'abc';
$country->save();
$country = Country::where('iso', '=', 'gr')->first();
echo $country->translate('en')->name; // abc
Filling multiple translations
$data = array(
'iso' => 'gr',
'en' => array('name' => 'Greece'),
'fr' => array('name' => 'Grèce'),
);
$country = Country::create($data);
echo $country->translate('fr')->name; // Grèce
Add the package in your composer.json by executing the command.
composer require dimsav/laravel-translatable
Next, add the service provider to app/config/app.php
'Dimsav\Translatable\TranslatableServiceProvider',
In this example, we want to translate the model Country
. We will need an extra table country_translations
:
Schema::create('countries', function(Blueprint $table)
{
$table->increments('id');
$table->string('iso');
$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');
});
- The translatable model
Country
should use the traitDimsav\Translatable\Translatable
. - The convention for the translation model is
CountryTranslation
.
// models/Country.php
class Country extends Eloquent {
use \Dimsav\Translatable\Translatable;
public $translatedAttributes = array('name');
protected $fillable = ['iso', 'name'];
}
// models/CountryTranslation.php
class CountryTranslation extends Eloquent {
public $timestamps = false;
protected $fillable = ['name'];
}
The array $translatedAttributes
contains the names of the fields being translated in the "Translation" model.
php artisan config:publish dimsav/laravel-translatable
With this command, initialize the configuration and modify the created file, located under app/config/packages/dimsav/laravel-translatable/config.php
.
Note: There isn't any restriction for the format of the locales. Feel free to use whatever suits you better, like "eng" instead of "en", or "el" instead of "gr". The important is to define your locales and stick to them.
Got any question or suggestion? Feel free to open an Issue.
You are awesome! Watched the repo and reply to the issues. You will help offering a great experience to the users of the package. #communityWorks
Translatable is fully compatible with all kinds of Eloquent extensions, including Ardent. If you need help to implement Translatable with these extensions, see this example.
If you see the following mysql error:
[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)
Then your tables have the MyISAM engine which doesn't allow foreign key constraints. MyISAM was the default engine for mysql versions older than 5.5. Since version 5.5, tables are created using the InnoDB storage engine by default.
For tables already created in production, update your migrations to change the engine of the table before adding the foreign key constraint.
public function up()
{
DB::statement('ALTER TABLE countries ENGINE=InnoDB');
}
public function down()
{
DB::statement('ALTER TABLE countries ENGINE=MyISAM');
}
For new tables, a quick solution is to set the storage engine in the migration:
Schema::create('language_translations', function(Blueprint $table){
$table->engine = 'InnoDB';
$table->increments('id');
// ...
});
The best solution though would be to update your mysql version. And always make sure you have the same version both in development and production environment!
If you want to fallback to a default translation if a translation has not been found, you can specify that on the model using $model->useTranslationFallback = true
.
App::make('config')->set('translatable::fallback_locale', 'en');
$country = Country::create(['iso' => 'gr']);
$country->translate('en')->name = 'Greece';
$country->useTranslationFallback = true;
$country->translate('de')->locale; // en
$country->translate('de')->name; // Greece
You can also overwrite useTranslationFallback
with a second parameter on translate()
, so new translations can be created or existing ones used. Without the second parameter, translate('de')
would return the fallback translation.
App::make('config')->set('translatable::fallback_locale', 'en');
$country = Country::create(['iso' => 'gr']);
$country->useTranslationFallback = true;
$country->translate('en', false)->name = 'Greece';
$country->translate('de', false)->name = 'Griechenland';
$country->translate('de')->locale; // de
$country->translate('de')->name; // Griechenland
When using fill
, this is done automatically for you:
$country = new Country;
$country->useTranslationFallback = true;
$country->fill([
'iso' => 'gr',
'en' => ['name' => 'Greece'],
'de' => ['name' => 'Griechenland'],
]);
$country->translate('de')->locale; // de
$country->translate('de')->name; // Griechenland