parfaitementweb/filament-plugin-translatable-inline
Filament addon for LaraZeus Spatie Translatable that lets you edit translations inline under each field. Makes translatable fields obvious, speeds up editing, and highlights missing locales. Works with Filament v4/v5 via a TranslatableContainer wrapper.
Install Dependencies:
composer require lara-zeus/spatie-translatable parfaitementweb/filament-plugin-translatable-inline
Configure Spatie Translatable (if not already set up):
php artisan vendor:publish --provider="Spatie\Translatable\TranslatableServiceProvider"config/translatable.php.Enable Plugin in Filament:
Register the plugin in app/Providers/FilamentPluginServiceProvider.php:
Filament::registerPlugin(
Parfaitementweb\FilamentPluginTranslatableInline\FilamentPluginTranslatableInlinePlugin::make()
);
Wrap Fields in TranslatableContainer:
use Parfaitementweb\FilamentPluginTranslatableInline\Forms\Components\TranslatableContainer;
public static function form(Form $form): Form {
return $form->schema([
TranslatableContainer::make(
TextInput::make('title')
->required()
),
]);
}
Edit a translatable model (e.g., Post) with inline translations for title and content fields. The plugin auto-detects translatable fields and renders them in a collapsible inline panel per locale.
Field Wrapping:
TranslatableContainer to wrap any Filament form field (e.g., TextInput, RichEditor, Select). Example:
TranslatableContainer::make(
RichEditor::make('description')
->columnSpanFull()
)
->requiredLocales(['en', 'es'])
Locale-Specific Validation:
onlyMainLocaleRequired() to enforce validation only on the primary locale:
TranslatableContainer::make(
TextInput::make('name')
)
->onlyMainLocaleRequired()
Dynamic Locale Handling:
getTranslatableLocales() in your resource to dynamically fetch locales:
public static function getTranslatableLocales(): array {
return ['en', 'fr', 'de'];
}
Table Repeater Support:
Repeater::make('features')
->schema([
TranslatableContainer::make(
TextInput::make('feature_name')
),
])
Hybrid Dropdown/Inline Mode: Use the plugin only in edit forms while keeping dropdown selectors in list views for consistency:
// In list view (dropdown)
TextInput::make('title')->translatable()->searchable()
// In edit form (inline)
TranslatableContainer::make(TextInput::make('title'))
Conditional Translations:
Disable translations for specific fields via ->translatable(false):
TranslatableContainer::make(
TextInput::make('slug')
->translatable(false) // Non-translatable
)
Custom Styling:
Override CSS via resources/css/filament/translatable-inline.css:
.filament-translatable-inline .locale-tab {
background: #f0f0f0;
}
Livewire Hooks:
Access the current locale in afterStateUpdated:
->afterStateUpdated(fn (Set $set, Component $component, ?string $state) => {
$locale = $component->getMeta('locale');
$set("translated_$locale", Str::slug($state));
})
Double Registration:
Class 'TranslatableContainer' not found.app/Providers/AppServiceProvider.php for service provider ordering.Missing Translations Not Highlighted:
->requiredLocales() or ensure spatie/translatable config has fallback_locale defined.State Path Issues in afterStateUpdated:
Undefined array key 'slug' when using nested paths.->afterStateUpdated(fn (Set $set, Component $component, ?string $state) => {
$locale = $component->getMeta('locale');
$set("parent_field.$locale", Str::slug($state));
})
Locale Switcher Conflicts:
Translatable trait from your resource and only use TranslatableContainer.Table Repeater Locale Scope:
TranslatableContainer:
TranslatableContainer::make(
Repeater::make('items')
->schema([
TextInput::make('name'),
])
)
Check Component Meta: Dump the component’s meta to debug locale access:
->afterStateUpdated(fn (Set $set, Component $component) => {
dd($component->getMeta()); // Look for 'locale' key
})
Validate Spatie Config:
Ensure config/translatable.php has:
'locales' => ['en', 'es', 'fr'],
'fallback_locale' => 'en',
Clear Filament Cache: After plugin updates, run:
php artisan filament:cache-reset
Custom Locale Tabs: Override the default tab UI by publishing the plugin’s views:
php artisan vendor:publish --tag="filament-translatable-inline-views"
Then modify resources/views/vendor/filament-plugin-translatable-inline/....
Add New Field Types:
Extend the plugin to support custom fields (e.g., Filament\Forms\Components\FileUpload) by:
Bulk Translation Actions: Use Filament’s action system to add bulk translation features:
public static function getActions(): array {
return [
TranslatableBulkAction::make()
->label('Translate All')
->action(function (Collection $records) {
$records->each->translate(['title' => 'New Title']);
}),
];
}
Locale-Specific Defaults:
Set default values per locale using default():
TranslatableContainer::make(
TextInput::make('description')
->default([
'en' => 'Default English text',
'es' => 'Texto predeterminado en español',
])
)
translations table has proper indexes on (model_id, locale, key) to avoid slow queries.How can I help you explore Laravel packages today?