Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Filament Plugin Translatable Inline Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install Dependencies:

    composer require lara-zeus/spatie-translatable parfaitementweb/filament-plugin-translatable-inline
    
  2. Configure Spatie Translatable (if not already set up):

    • Publish config: php artisan vendor:publish --provider="Spatie\Translatable\TranslatableServiceProvider"
    • Set default locales in config/translatable.php.
  3. Enable Plugin in Filament: Register the plugin in app/Providers/FilamentPluginServiceProvider.php:

    Filament::registerPlugin(
        Parfaitementweb\FilamentPluginTranslatableInline\FilamentPluginTranslatableInlinePlugin::make()
    );
    
  4. 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()
            ),
        ]);
    }
    

First Use Case

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.


Implementation Patterns

Core Workflow

  1. Field Wrapping:

    • Use TranslatableContainer to wrap any Filament form field (e.g., TextInput, RichEditor, Select). Example:
      TranslatableContainer::make(
          RichEditor::make('description')
              ->columnSpanFull()
      )
      ->requiredLocales(['en', 'es'])
      
  2. Locale-Specific Validation:

    • Use onlyMainLocaleRequired() to enforce validation only on the primary locale:
      TranslatableContainer::make(
          TextInput::make('name')
      )
      ->onlyMainLocaleRequired()
      
  3. Dynamic Locale Handling:

    • Override getTranslatableLocales() in your resource to dynamically fetch locales:
      public static function getTranslatableLocales(): array {
          return ['en', 'fr', 'de'];
      }
      
  4. Table Repeater Support:

    • Works with nested translatable fields in repeaters:
      Repeater::make('features')
          ->schema([
              TranslatableContainer::make(
                  TextInput::make('feature_name')
              ),
          ])
      

Integration Tips

  • 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));
    })
    

Gotchas and Tips

Common Pitfalls

  1. Double Registration:

    • Error: Class 'TranslatableContainer' not found.
    • Fix: Ensure the plugin is registered before your Filament resources load. Check app/Providers/AppServiceProvider.php for service provider ordering.
  2. Missing Translations Not Highlighted:

    • Cause: JS validation errors may collapse empty locales.
    • Fix: Explicitly set ->requiredLocales() or ensure spatie/translatable config has fallback_locale defined.
  3. State Path Issues in afterStateUpdated:

    • Error: Undefined array key 'slug' when using nested paths.
    • Fix: Use the corrected syntax:
      ->afterStateUpdated(fn (Set $set, Component $component, ?string $state) => {
          $locale = $component->getMeta('locale');
          $set("parent_field.$locale", Str::slug($state));
      })
      
  4. Locale Switcher Conflicts:

    • Cause: Using both the plugin’s inline editor and Filament’s default locale switcher.
    • Fix: Remove the default Translatable trait from your resource and only use TranslatableContainer.
  5. Table Repeater Locale Scope:

    • Issue: Repeater items lose locale context.
    • Fix: Wrap the entire repeater in TranslatableContainer:
      TranslatableContainer::make(
          Repeater::make('items')
              ->schema([
                  TextInput::make('name'),
              ])
      )
      

Debugging Tips

  • 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
    

Extension Points

  1. 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/....

  2. Add New Field Types: Extend the plugin to support custom fields (e.g., Filament\Forms\Components\FileUpload) by:

    • Creating a trait for translatable fields.
    • Registering it in the plugin’s service provider.
  3. 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']);
                }),
        ];
    }
    
  4. 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',
            ])
    )
    

Performance Considerations

  • Large Forms: For forms with >50 translatable fields, consider lazy-loading locales or using AJAX to fetch missing translations.
  • Database Impact: Ensure your translations table has proper indexes on (model_id, locale, key) to avoid slow queries.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky