flobbos / laravel-translatable-db
A Laravel package for multilingual models
Requires
- php: ^8.1
- illuminate/contracts: ^10.0|^11.0|^12.0|^13.0
- illuminate/database: ^10.0|^11.0|^12.0|^13.0
- illuminate/http: ^10.0|^11.0|^12.0|^13.0
- illuminate/support: ^10.0|^11.0|^12.0|^13.0
Requires (Dev)
- orchestra/testbench: ^8.0|^9.0|^10.0|^11.0
- phpunit/phpunit: ^10.5|^11.5|^12.5|^13.0
README
Database-backed translated Eloquent attributes, resolved by a language id instead of a locale string.
This package started as a fork of dimsav/laravel-translatable. It only reads translated attributes. It does not manage CRUD forms or translation persistence.
Compatibility
| Laravel | Package |
|---|---|
| 13.x | 2.x |
| 12.x | 2.x |
| 11.x | 2.x |
| 10.x | 2.x |
| 5.3-9.x | 1.x |
Laravel 10 support means the package requires PHP ^8.1. Laravel itself may require a higher PHP version for newer framework releases.
Installation
composer require flobbos/laravel-translatable-db:^2.0
Laravel auto-discovery registers the service provider. Publish the config only when you need to override defaults:
php artisan vendor:publish --provider="Flobbos\TranslatableDB\TranslatableDBServiceProvider"
Tables
Example for a translated Country model:
Schema::create('languages', function (Blueprint $table) { $table->id(); $table->string('locale')->unique(); $table->string('name'); }); Schema::create('countries', function (Blueprint $table) { $table->id(); $table->string('code')->unique(); $table->timestamps(); }); Schema::create('country_translations', function (Blueprint $table) { $table->id(); $table->foreignId('country_id')->constrained()->cascadeOnDelete(); $table->foreignId('language_id')->constrained()->cascadeOnDelete(); $table->string('name'); $table->unique(['country_id', 'language_id']); });
If your default language lives on the main model table, add the translated column there and enable native fallback on the model:
public $fallbackAttributes = ['name'];
Then set:
'native_mode' => true,
Models
namespace App\Models; use Flobbos\TranslatableDB\TranslatableDB; use Illuminate\Database\Eloquent\Model; class Country extends Model { use TranslatableDB; public $translatedAttributes = ['name']; public $fallbackAttributes = ['name']; protected $fillable = ['code']; }
namespace App\Models; use Illuminate\Database\Eloquent\Model; class CountryTranslation extends Model { public $timestamps = false; protected $fillable = ['language_id', 'name']; }
By convention, Country uses CountryTranslation. Override it when needed:
public $translationModel = CountryText::class;
Usage
$country = Country::where('code', 'gr')->first(); app()->setLocale('en'); echo $country->name; // Greece app()->setLocale('de'); echo $country->name; // Griechenland echo $country->getAttribute('name:2'); // Explicit language id
Configuration
Important defaults:
'use_db' => true, 'language_model' => App\Models\Language::class, 'locale_key' => 'language_id', 'locale_column' => 'locale', 'use_fallback' => true, 'fallback_locale_id' => 1, 'middleware_default' => false, 'to_array_always_loads_translations' => false,
With database mode enabled, the middleware resolves app()->getLocale() through your language model and stores the matching id on the request.
With database mode disabled, configure languages directly:
'use_db' => false, 'language_array' => [ 'de' => ['name' => 'Deutsch', 'language_id' => 1], 'en' => ['name' => 'English', 'language_id' => 2], ],
Middleware
The middleware is no longer pushed globally by default in 2.x.
Register it where translated route content needs automatic language id resolution:
use Flobbos\TranslatableDB\Middleware\LanguageIdentification; Route::middleware(LanguageIdentification::class)->group(function () { // translated routes });
If you really want the old global behavior:
'middleware_default' => true,
Polymorphic Translations
Implement PolyTrans and set the morph name:
namespace App\Models; use Flobbos\TranslatableDB\Contracts\PolyTrans; use Flobbos\TranslatableDB\TranslatableDB; use Illuminate\Database\Eloquent\Model; class Country extends Model implements PolyTrans { use TranslatableDB; public $translationModel = Translation::class; protected $translationForeignKey = 'translatable'; }
Testing
composer test
