Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

mstdmstd's avatar

How to make multi language with filament/spatie-laravel-translatable ?

I need to make multi language admin area laravel 9 app with filament/spatie-laravel-translatable-plugin ^2.17.17 / filament/filament 2.17.17 / "filament/forms": "^2.17.17

Reading https://filamentphp.com/docs/2.x/spatie-laravel-translatable-plugin/getting-started docs I did not find how I can make dynamic list of text inputs for all languages in my system. I need :

  1. get current record in edit mode. In add mode it is empty.
  2. to existing form fields I need to add all my locales as string 100/required fields - to get new fields in generated form, under separate group preferably...
  3. On save I need to join into 1 json fields all my custom locale fields into 1 json fields in which spatie-laravel-translatable-plugin keeps all labels and remove these custom fields from saving.

I tried to review and debug src/Resources/Resource.php and src/Resources/Pages/EditRecord.php trying to find any any hooks where I can add my custom locale fields but failed - that is too complicated.

Any ideas how that can be implemented ?

Than you!

0 likes
3 replies
LaryAI's avatar
Level 58

To create a multi-language admin area in Laravel 9 using filament/spatie-laravel-translatable-plugin, you can follow these steps:

  1. Install the filament/spatie-laravel-translatable-plugin package using composer:
composer require filament/spatie-laravel-translatable-plugin
  1. Create a model for your translatable entity and use the HasTranslations trait provided by the package:
use Illuminate\Database\Eloquent\Model;
use Spatie\Translatable\HasTranslations;

class Post extends Model
{
    use HasTranslations;

    public $translatable = ['title', 'body'];
}
  1. Create a form for your translatable entity using Filament's form builder and add the translatable fields using the translatable method:
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(),
            ]);
    }
}
  1. 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'));
    }
}
  1. In your view, render the form using Filament's form component:
<x-filament-form :form="$form" />
  1. 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 getTranslation method:
$post->getTranslation('title', 'fr');
  1. To add custom locale fields to the form, you can use Filament's ComponentGroup component:
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')),
                    ]),
            ]);
    }
}
  1. To save the custom locale fields as JSON along with the translatable fields, you can use the saving event 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.

mstdmstd's avatar

I try in this way, but got error :

Method Filament\Forms\Components\TextInput::translatable does not exist.

I have added declaration :

...
use Filament\Resources\Concerns\Translatable;
use Spatie\Translatable\HasTranslations;
class BannerResource extends Resource
{
    protected static ?string $model = Banner::class;
    use Translatable;
    ...

In the referenced docs I did not find any translatable method at all...

my model app/Models/Banner.php has all declarations :

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Arr;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;

use Spatie\Translatable\HasTranslations;

class Banner extends Model implements HasMedia
{
    use InteractsWithMedia;
    use HasTranslations;

    protected $table = 'banners';
    protected $fillable
        = [
           ...
        ];
    public $translatable = ['text', 'description'];

Also my resource does not have any

     public function configure(

method, but :

public static function form(Form $form): Form
    {
    ...
2 likes

Please or to participate in this conversation.