fnx-software / filament-astrotomic
Filament support for Astrotomic's Laravel Translatable package.
Requires
- php: ^8.2|^8.3|^8.4
- astrotomic/laravel-translatable: ^11.16
- filament/filament: ^4.0
- filament/forms: ^4.0
- filament/tables: ^4.0
- spatie/laravel-package-tools: ^1.15.0
Requires (Dev)
- laravel/pint: ^1.0
- nunomaduro/collision: ^8.0
- orchestra/testbench: ^9.0|^10.0
- pestphp/pest: ^3.0
- pestphp/pest-plugin-arch: ^3.0
- pestphp/pest-plugin-laravel: ^3.0
- pestphp/pest-plugin-livewire: ^3.0
README
This package is an extension for Filament v4+ and laravel-translatable to easily manage multilingual content in your admin panel.
This is an enhanced fork of doriiaan/filament-astrotomic and the original cactus-galaxy/filament-astrotomic, updated for Filament 4 and introducing powerful new features like a reactive LocaleSwitcher
and dedicated components for displaying translated content.
Installation
You can install the package via Composer:
composer require fnx-software/filament-astrotomic
Publish the configuration for astrotomic/laravel-translatable
:
php artisan vendor:publish --tag="translatable"
Configure the locales your app should use in config/translatable.php
:
// config/translatable.php 'locales' => [ 'en', 'es', 'fr', ],
Setup
Adding the Plugin to a Panel
Register the plugin in your Panel Provider:
// app/Providers/Filament/AdminPanelProvider.php use Fnxsoftware\FilamentAstrotomic\FilamentAstrotomicPlugin; use Filament\Panel; public function panel(Panel $panel): Panel { return $panel // ... ->plugins([ FilamentAstrotomicPlugin::make(), ]); }
Customizing the Main Locale (Optional)
By default, the main locale is taken from your config/translatable.php
file. You can override this dynamically when registering the plugin.
Set a static main locale:
FilamentAstrotomicPlugin::make() ->mainLocale('ar')
Set a dynamic main locale (e.g., from database settings):
use App\Models\Setting; FilamentAstrotomicPlugin::make() ->mainLocale(fn () => Setting::where('key', 'default_locale')->first()?->value ?? 'en')
Basic Usage
1. Preparing Your Model
Make your Eloquent model translatable as described in the laravel-translatable documentation.
// app/Models/Post.php use Illuminate\Database\Eloquent\Model; use Astrotomic\Translatable\Contracts\Translatable as TranslatableContract; use Astrotomic\Translatable\Translatable; class Post extends Model implements TranslatableContract { use Translatable; public array $translatedAttributes = ['title', 'content']; protected $fillable = ['author_id']; }
2. Preparing Your Resource
Apply the ResourceTranslatable
trait to your Filament resource class:
// app/Filament/Resources/PostResource.php use Fnxsoftware\FilamentAstrotomic\Resources\Concerns\ResourceTranslatable; use Filament\Resources\Resource; class PostResource extends Resource { use ResourceTranslatable; // ... }
3. Making Resource Pages Translatable
You must also apply the corresponding translatable trait to each of your resource's pages.
List Page:
// app/Filament/Resources/PostResource/Pages/ListPosts.php use Fnxsoftware\FilamentAstrotomic\Resources\Pages\ListTranslatable; use Filament\Resources\Pages\ListRecords; class ListPosts extends ListRecords { use ListTranslatable; // ... }
Create Page:
// app/Filament/Resources/PostResource/Pages/CreatePost.php use Fnxsoftware\FilamentAstrotomic\Resources\Pages\CreateTranslatable; use Filament\Resources\Pages\CreateRecord; class CreatePost extends CreateRecord { use CreateTranslatable; // ... }
Edit Page:
// app/Filament/Resources/PostResource/Pages/EditPost.php use Fnxsoftware\FilamentAstrotomic\Resources\Pages\EditTranslatable; use Filament\Resources\Pages\EditRecord; class EditPost extends EditRecord { use EditTranslatable; // ... }
View Page:
// app/Filament/Resources/PostResource/Pages/ViewPost.php use Fnxsoftware\FilamentAstrotomic\Resources\Pages\ViewTranslatable; use Filament\Resources\Pages\ViewRecord; class ViewPost extends ViewRecord { use ViewTranslatable; // ... }
Form Components
TranslatableTabs
for Localized Fields
To manage translations for your model's attributes, use the TranslatableTabs
component. It automatically creates a tab for each locale.
use Fnxsoftware\FilamentAstrotomic\Schemas\Components\TranslatableTabs; use Fnxsoftware\FilamentAstrotomic\TranslatableTab; use Filament\Forms\Components\TextInput; use Filament\Forms\Components\RichEditor; use Filament\Forms\Form; public static function form(Form $form): Form { return $form->schema([ TranslatableTabs::make() ->localeTabSchema(fn (TranslatableTab $tab) => [ TextInput::make($tab->makeName('title')) ->required($tab->isMainLocale()), // Required only for the main language RichEditor::make($tab->makeName('content')), ]) ]); }
TranslatableSelect
for Relationships
The standard Select::relationship()
component does not work with astrotomic/laravel-translatable
. This package provides a TranslatableSelect
component to correctly load, search, and display options from a translatable BelongsTo
relationship.
use Fnxsoftware\FilamentAstrotomic\Forms\Components\TranslatableSelect; use Filament\Forms\Form; public static function form(Form $form): Form { return $form->schema([ // ... other fields TranslatableSelect::make('country_id') ->translatableRelationship('country', 'name') ->searchable() ->preload() ->label('Country') ->required(), ]); }
This will correctly display the country names in the current locale, and the search functionality will also work on the translated names.
Displaying Translated Content Reactively
This package provides a seamless way to view translated content on your List and View pages using a LocaleSwitcher
action that works with dedicated table columns and infolist entries.
1. Add the LocaleSwitcher
Action
Add the LocaleSwitcher
to the header actions of your List and View pages.
// In your List page (e.g., ListPosts.php) use Fnxsoftware\FilamentAstrotomic\Actions\LocaleSwitcher; use Filament\Actions\CreateAction; protected function getHeaderActions(): array { return [ CreateAction::make(), LocaleSwitcher::make(), // Add this ]; }
2. Use TranslatableColumn
in Tables
The TranslatableColumn
automatically displays the translation for the selected locale and provides out-of-the-box search and sort functionality.
// In your Table definition use Fnxsoftware\FilamentAstrotomic\Tables\Columns\TranslatableColumn; use Filament\Tables\Table; public static function table(Table $table): Table { return $table ->columns([ TranslatableColumn::make('title') ->searchable() ->sortable(), // ... other columns ]); }
3. Use TranslatableEntry
in Infolists
Similarly, use TranslatableEntry
in your infolists to display translated content that reacts to the LocaleSwitcher
.
// In your Infolist definition use Fnxsoftware\FilamentAstrotomic\Infolists\Components\TranslatableEntry; use Filament\Infolists\Infolist; public static function infolist(Infolist $infolist): Infolist { return $infolist ->schema([ TranslatableEntry::make('title'), TranslatableEntry::make('content'), // ... other entries ]); }
Advanced Usage
Custom Locales Per-Resource
Override the getTranslatableLocales()
method in your resource to specify a different set of locales than the global configuration.
public static function getTranslatableLocales(): array { return ['en', 'fr']; }
Modal Forms
To use translatable fields inside modal actions (like an EditAction
on a table row), you must correctly mutate the data.
use App\Models\Post; use Filament\Tables\Actions\EditAction; ->actions([ EditAction::make()->mutateRecordDataUsing(function (Post $record, array $data) { return static::mutateTranslatableData($record, $data); }), ])
Nested Relationship Support
Both TranslatableColumn
and TranslatableEntry
fully support displaying, searching, and sorting translated attributes on nested relationships using dot notation.
TranslatableColumn
with a relationship:
The column will display the country's name, and the search and sort functionality will correctly filter and order the governorates
table based on the name of the related country.
// In your GovernorateResource table TranslatableColumn::make('country.name') ->label('Country') ->searchable() ->sortable(),
TranslatableEntry
with a relationship:
The entry will display the translated name of the related country on the governorate's view page.
// In your GovernorateResource infolist TranslatableEntry::make('country.name') ->label('Country'),
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Credits
- Original Author: Oleksandr Moik (cactus-galaxy)
- Filament v4 Fork: Alary Dorian (Doriiaan)
- Current Maintainer: Fnx-Software
- All Contributors
License
The MIT License (MIT). Please see License File for more information.