weboccult / laravel-translatable
A Laravel package for easy model translations using morph relationships. Supports multiple languages, caching, validation, and automatic translation loading.
v1.0.0
2025-06-01 09:12 UTC
Requires
- php: ^8.0
- illuminate/cache: ^8.0|^9.0|^10.0
- illuminate/database: ^8.0|^9.0|^10.0
- illuminate/support: ^8.0|^9.0|^10.0
Requires (Dev)
- mockery/mockery: ^1.4
- orchestra/testbench: ^6.0|^7.0|^8.0
- phpunit/phpunit: ^9.0|^10.0
This package is not auto-updated.
Last update: 2025-06-07 09:51:07 UTC
README
A Laravel package for easy model translations using morph relationships. This package allows you to add multilingual support to your Laravel models using a simple trait.
Installation
You can install the package via composer:
composer require weboccult/laravel-translatable
After installing the package, publish the configuration and migration files:
php artisan vendor:publish --provider="WebOccult\LaravelTranslatable\TranslatableServiceProvider"
Then run the migrations:
php artisan migrate
Basic Setup
- Add the
HasTranslations
trait to your model and specify translatable attributes:
use WebOccult\LaravelTranslatable\Traits\HasTranslations; class Department extends Model { use HasTranslations; protected $fillable = [ 'code' // non-translatable field ]; // Define which attributes can be translated protected $translatable = [ 'name', 'description', 'address' ]; }
Usage Examples
1. Creating and Setting Translations
// Create a new department $department = Department::create([ 'code' => 'IT-001' ]); // Method 1: Set translations one by one $department->setTranslation('name', 'Information Technology', 'en'); $department->setTranslation('name', 'Technologies de l\'information', 'fr'); $department->setTranslation('name', 'Tecnología de la Información', 'es'); // Method 2: Set multiple translations at once $department->updateTranslations([ 'name' => [ 'en' => 'Information Technology', 'fr' => 'Technologies de l\'information', 'es' => 'Tecnología de la Información' ], 'description' => [ 'en' => 'Main IT Department', 'fr' => 'Département principal des TI', 'es' => 'Departamento Principal de TI' ] ]); // Method 3: Set multiple fields for same locale $department->setTranslation( ['name', 'description'], ['IT Department', 'Handles all IT operations'], 'en' );
2. Retrieving Translations
// Method 1: Get single translation $name = $department->getTranslation('name', 'en'); // Output: "Information Technology" // Method 2: Get all translations for an attribute $allNames = $department->getAllTranslations('name'); // Output: // [ // 'en' => 'Information Technology', // 'fr' => 'Technologies de l\'information', // 'es' => 'Tecnología de la Información' // ] // Method 3: Load with translations for current locale $departments = Department::withTranslations()->get(); foreach ($departments as $dept) { echo $dept->getTranslation('name'); // Uses current locale } // Method 4: Load with all translations $department = Department::with('translations')->find(1); $translations = $department->translations->groupBy('locale'); // Output: // [ // 'en' => [ // ['attribute' => 'name', 'value' => 'Information Technology'], // ['attribute' => 'description', 'value' => 'Main IT Department'] // ], // 'fr' => [ // ['attribute' => 'name', 'value' => 'Technologies de l\'information'], // ['attribute' => 'description', 'value' => 'Département principal des TI'] // ] // ]
3. Querying with Translations
// Load models with translations for specific locale $departments = Department::query() ->with(['translations' => function($query) { $query->where('locale', 'en') ->whereIn('attribute', ['name', 'description']); }]) ->get(); // Format for API response $formatted = $departments->map(function ($department) { return [ 'id' => $department->id, 'code' => $department->code, 'name' => $department->getTranslation('name', 'en'), 'description' => $department->getTranslation('description', 'en') ]; }); // Output: // [ // { // "id": 1, // "code": "IT-001", // "name": "Information Technology", // "description": "Main IT Department" // } // ]
4. Practical Examples
Example 1: Controller with Translation Handling
class DepartmentController extends Controller { public function store(Request $request) { $department = Department::create([ 'code' => $request->code ]); // Handle translations from form // Input format: // translations = [ // 'name' => [ // 'en' => 'English Name', // 'fr' => 'French Name' // ], // 'description' => [ // 'en' => 'English Description', // 'fr' => 'French Description' // ] // ] $department->updateTranslations($request->translations); return response()->json([ 'department' => $department, 'translations' => $department->translations ]); } public function index() { // Get departments with translations for current locale $departments = Department::withTranslations() ->get() ->map(function ($department) { return [ 'id' => $department->id, 'code' => $department->code, 'name' => $department->getTranslation('name'), 'description' => $department->getTranslation('description') ]; }); return view('departments.index', compact('departments')); } }
Example 2: Blade View Usage
<!-- departments/index.blade.php --> @foreach($departments as $department) <div class="department-card"> <h3>{{ $department->getTranslation('name') }}</h3> <p>{{ $department->getTranslation('description') }}</p> <!-- Show all available translations --> <div class="translations"> @foreach($department->getAllTranslations('name') as $locale => $name) <span class="translation"> {{ $locale }}: {{ $name }} </span> @endforeach </div> </div> @endforeach
Example 3: API Resource
class DepartmentResource extends JsonResource { public function toArray($request) { $locale = $request->get('locale', app()->getLocale()); return [ 'id' => $this->id, 'code' => $this->code, 'translations' => [ 'name' => $this->getAllTranslations('name'), 'description' => $this->getAllTranslations('description') ], 'current_locale' => [ 'name' => $this->getTranslation('name', $locale), 'description' => $this->getTranslation('description', $locale) ] ]; } } // Output: // { // "id": 1, // "code": "IT-001", // "translations": { // "name": { // "en": "Information Technology", // "fr": "Technologies de l'information", // "es": "Tecnología de la Información" // }, // "description": { // "en": "Main IT Department", // "fr": "Département principal des TI", // "es": "Departamento Principal de TI" // } // }, // "current_locale": { // "name": "Information Technology", // "description": "Main IT Department" // } // }
Features
- Easy integration with Laravel models
- Support for multiple translatable attributes
- Efficient relationship-based translation loading
- Flexible query building for translations
- Support for multiple languages
- Bulk translation operations
- Automatic fallback to model attributes
Configuration
You can configure the package by editing the config/translatable.php
file:
return [ 'default_locale' => 'en', 'fallback_locale' => 'en', 'available_locales' => [ 'en' => 'English', 'fr' => 'French', 'es' => 'Spanish', ], ];
License
The MIT License (MIT). Please see License File for more information.