To create a multi-language admin area in Laravel 9 using filament/spatie-laravel-translatable-plugin, you can follow these steps:
- Install the filament/spatie-laravel-translatable-plugin package using composer:
composer require filament/spatie-laravel-translatable-plugin
- Create a model for your translatable entity and use the
HasTranslationstrait provided by the package:
use Illuminate\Database\Eloquent\Model;
use Spatie\Translatable\HasTranslations;
class Post extends Model
{
use HasTranslations;
public $translatable = ['title', 'body'];
}
- Create a form for your translatable entity using Filament's form builder and add the translatable fields using the
translatablemethod:
use Filament\Forms\Form;
use Filament\Forms\Components\TextInput;
use Spatie\Translatable\HasTranslations;
class PostForm extends Form
{
public function configure()
{
$this
->schema([
TextInput::make('title')
->label(__('Title'))
->translatable(),
TextInput::make('body')
->label(__('Body'))
->translatable(),
]);
}
}
- In your controller, retrieve the record you want to edit and pass it to the form:
use App\Models\Post;
use App\Forms\PostForm;
class PostController extends Controller
{
public function edit(Post $post)
{
$form = new PostForm($post);
return view('posts.edit', compact('form'));
}
}
- In your view, render the form using Filament's
formcomponent:
<x-filament-form :form="$form" />
- When the form is submitted, the translatable fields will be automatically saved as JSON in the database. You can retrieve the translated values using the
getTranslationmethod:
$post->getTranslation('title', 'fr');
- To add custom locale fields to the form, you can use Filament's
ComponentGroupcomponent:
use Filament\Forms\Components\ComponentGroup;
use Filament\Forms\Components\TextInput;
class PostForm extends Form
{
public function configure()
{
$this
->schema([
ComponentGroup::make(__('Translations'))
->schema([
TextInput::make('title')
->label(__('Title'))
->translatable(),
TextInput::make('body')
->label(__('Body'))
->translatable(),
]),
ComponentGroup::make(__('Custom Fields'))
->schema([
TextInput::make('custom_field_1')
->label(__('Custom Field 1')),
TextInput::make('custom_field_2')
->label(__('Custom Field 2')),
]),
]);
}
}
- To save the custom locale fields as JSON along with the translatable fields, you can use the
savingevent of the model:
use Illuminate\Database\Eloquent\Model;
use Spatie\Translatable\HasTranslations;
class Post extends Model
{
use HasTranslations;
public $translatable = ['title', 'body'];
protected static function boot()
{
parent::boot();
static::saving(function ($model) {
$translations = [];
foreach ($model->getTranslatableAttributes() as $attribute) {
foreach ($model->getTranslations($attribute) as $locale => $value) {
$translations[$locale][$attribute] = $value;
}
}
$model->custom_fields = json_encode($translations);
});
}
}
This will save the custom locale fields as JSON in the custom_fields column of the database along with the translatable fields.