latevaweb/laravel-translatable
Add translatable Eloquent attributes backed by a Translations database table. Use a Translatable trait to set/get per-locale values, auto-resolve attributes by current app locale, and store translations via polymorphic relations.
Install the Package
Run composer require latevaweb/laravel-translatable to add the package to your project.
Publish Config and Migrations Execute these commands to set up the required database tables and configurations:
php artisan vendor:publish --provider="LaTevaWeb\Translatable\TranslatableServiceProvider" --tag=config --force
php artisan vendor:publish --provider="LaTevaWeb\Translatable\TranslatableServiceProvider" --tag=migrations --force
Run the migrations:
php artisan migrate
First Use Case: Basic Translation
Add the Translatable trait and define translatable attributes in your model:
use LaTevaWeb\Translatable\Traits\Translatable;
class Product extends Model
{
use Translatable;
public static $translatable = ['name', 'description'];
}
Set translations for a model instance:
$product = new Product();
$product->setTranslation('name', 'en', 'Laptop');
$product->setTranslation('name', 'es', 'Portátil');
$product->save();
Retrieve translations dynamically:
$product->name; // Returns 'Laptop' if app locale is 'en'
$product->getTranslation('name', 'es'); // Returns 'Portátil'
Dynamic Locale Handling Leverage the package’s integration with Laravel’s locale system:
app()->setLocale('es');
$product->name; // Automatically returns 'Portátil'
Mass Assignment with Translations
Use fill() or create() with translations:
$product = Product::create([
'name_en' => 'Smartphone',
'name_es' => 'Teléfono Inteligente',
'description_en' => 'Latest model',
'description_es' => 'Último modelo',
]);
Querying Translated Attributes Filter models by translated attributes:
$products = Product::whereTranslation('name', 'en', 'Laptop')->get();
Fallback Locales
Define a fallback locale in the config (e.g., config/translatable.php):
'fallback_locale' => 'en',
Then retrieve translations with a fallback:
$product->getTranslation('name', 'fr'); // Returns 'Laptop' (fallback to 'en')
Multi-Language Admin Panel Use the package to store and retrieve translations for admin interfaces:
// Admin sets translations
$page->setTranslation('title', 'en', 'Home');
$page->setTranslation('title', 'de', 'Startseite');
$page->save();
// Frontend displays based on user locale
echo $page->title; // Automatically picks 'Home' or 'Startseite'
Localization in API Responses Serialize translated attributes in API responses:
return ProductResource::collection(
Product::withTranslations(['name', 'description'])->get()
);
Seeding Translated Data Seed databases with translations:
$product = Product::create(['slug' => 'prod-123']);
$product->setTranslation('name', 'en', 'Headphones');
$product->setTranslation('name', 'ja', 'ヘッドホン');
$product->save();
Customize Table Names Override default table names in the config:
'tables' => [
'translations' => 'custom_translations',
'models' => 'custom_models',
],
Extend the Trait Add custom logic to the trait by overriding methods:
use LaTevaWeb\Translatable\Traits\Translatable;
class Product extends Model
{
use Translatable;
public function setTranslation($attribute, $locale, $value)
{
// Custom logic before saving
$value = strtoupper($value);
parent::setTranslation($attribute, $locale, $value);
}
}
Use with Eloquent Relationships Combine with polymorphic relationships:
class Translation extends Model
{
public function translatable()
{
return $this->morphTo();
}
}
Cache Translations Cache frequently accessed translations to reduce database load:
$translation = Cache::remember("product_{$product->id}_name_{$locale}", now()->addHours(1), function () use ($product, $locale) {
return $product->getTranslation('name', $locale);
});
Locale Dependency
null or fall back to a default.AppServiceProvider:
public function boot()
{
app()->setLocale(config('app.fallback_locale'));
}
Missing Migrations
TranslationNotFoundException.php artisan migrate after publishing migrations.Attribute Not Defined in $translatable
public static $translatable will silently fail or throw an error.public static $translatable = ['name', 'description', 'meta_title'];
Polymorphic Conflicts
translatable_id or translatable_type column, the package’s migrations may conflict.Performance with Large Datasets
$products = Product::withTranslations(['name'])->get();
Laravel Version Mismatch
Check Database Records Verify translations are stored correctly:
php artisan tinker
>>> \DB::table('translations')->where('translatable_id', $product->id)->get();
Enable Query Logging
Debug SQL queries in AppServiceProvider:
public function boot()
{
\DB::enableQueryLog();
}
Then inspect logs:
>>> \DB::getQueryLog();
Validate Config Ensure the config file is published and correctly set:
php artisan config:clear
Check for Caching Issues Clear caches if translations aren’t updating:
php artisan config:clear
php artisan cache:clear
php artisan view:clear
Use Accessors for Dynamic Logic Override accessors to add logic when fetching translations:
public function getNameAttribute($value)
{
$locale = app()->getLocale();
return $this->getTranslation('name', $locale) ?: $value;
}
Leverage Scopes Create custom scopes for querying translated content:
public function scopeInLanguage($query, $locale)
{
return $query->whereHas('translations', function ($q) use ($locale) {
$q->where('locale', $locale);
});
}
Batch Translation Updates Use chunking for bulk updates:
Product::chunk(200, function ($products) {
foreach ($products as $product) {
$product->setTranslation('description', 'en', 'Updated description');
$product->save();
}
});
Localization in Blade Views Use the package in Blade templates:
<h1>{{ $product->getTranslation('name', session('locale')) }}</h1>
Testing Translations Write tests to verify translations:
public function test_translations()
{
$product = Product::factory()->create();
$product->setTranslation('name', 'en', 'Test Product');
$this->assertEquals('Test Product', $product->name);
}
Extend the Translation Model Add custom
How can I help you explore Laravel packages today?