mosamy/translatable

Laravel package that handle the headache of the translation problem.

1.3.0 2023-07-20 12:44 UTC

This package is auto-updated.

Last update: 2025-04-20 16:40:16 UTC


README

Quick and easy way to make an eloquent model translatable

Installation

composer require mosamy/translatable
php artisan migrate

Usage

  • use the translatable trait and add a new Post
  • define the translations attribute in your model

class Post extends Model
{
  use \Mosamy\Translatable\Translatable;
  const TranslatableAttributes = ['title', 'description'];
}

$post= Post::create(['status' => 'active']);

$translation = [
  [
    'en' => [
	    'title' => 'Post Title',
	    'description' => 'Post Description'
    ],
    'fr' => [
	    'title' => 'Titre de l article',
	    'description' => 'Description du poste'
    ],
  ]
];

$post->createTranslations($translation);

Get the translation data directly from database:

$post = Post::find(1);
$post->translations;

or for pretty format:

$post->translations_list;

results will be like that:

{
    "en": {
        "title": "Post Title",
        "description": "Post Description",
    },
    "ar": {
        "title": "Titre de l article",
        "description": "Description du poste",
    }
}

You can search in the translation data by using this method:

$post= Post::whereTranslation('keyword')->get();

by default this method consider that you would search in the TranslatableAttributes defined in your model

if you want to search in specific attributes you can add additional argument.

$post= Post::whereTranslation('keyword', ['description'])->get();
  • the third argument is for the locale
  • by default it will use the default locale
  • you can change this by add an array as a third argument containing one or multiple locales
$post= Post::whereTranslation('keyword', ['description'], ['ar','en'])->get();
  • the 4th argument is for the LIKE option
  • by default it is set to true but you can disable it and search with exactly WHERE condition.
    $post= Post::whereTranslation('keyword', ['description'], ['ar','en'], false)->get();
    

Rules

Sometimes you need to validate the translation inputs. here's some rules which can help you.

UNIQUE by default, locale will set to the second key in translations.ar.name but you can change this by using function setLocale you can also ignore specific ID when update a record

public  function  rules()
{
	return [
	'translations.ar.name'  => ['required', (new \App\Rules\TranslationUnique(new  Post))->setLocale(['ar', 'en'])->ignore($this->id)],
	'translations.en.name'  =>  'required', (new \App\Rules\TranslationUnique(new  Post))->ignore($this->id)
	];
}

Sorting

It's easy to sort by any attribute inside the translations

$post= Post::orderByTranslation('title')->get();
  • by default sorting will execute in ascending order and in the default locale
  • to change chat you can specify the two argument as the sort type and the third argument as the custom locale
$post= Post::orderByTranslation('title', 'desc', 'fr')->get();

Retrieving Translations

When you call an attribute it will be translated in the default locale

$post = Post::find(1);

echo $post->title;
// same as
echo $post->translate('title');

//Post Title

to retrieve a specific translation for an attribute you can use the translate method

$post = Post::find(1);
echo $post->translate('title', 'fr');

//Titre de l article

Get model that contain translation, specific local or the current locale

$post = Post::hasTranslation(); // all that have translation
$post = Post::hasTranslation('en'); // all that have (en) translation
$post = Post::hasCurrentTranslation(); // all in current locale

Retrieve only specific attributes

$post = Post::translateOnly('name');
$post = Post::translateOnly(['name', 'title']);

Delete translations

For any reason you would like to delete the translations you may use the simple laravel eloquent delete method:

$post = Post::find(1);
$post->translations()->delete();
$post->translations()->where('locale', 'fr')->delete();