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 Translatable Laravel Package

webard/filament-translatable

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require webard/filament-translatable
    

    Publish the config (if needed):

    php artisan vendor:publish --provider="Webard\FilamentTranslatable\FilamentTranslatableServiceProvider" --tag="config"
    
  2. Model Integration: Add the Translatable trait to your Eloquent model:

    use Webard\FilamentTranslatable\Traits\Translatable;
    
    class Post extends Model
    {
        use Translatable;
    
        public $translatable = ['title', 'content'];
    }
    
  3. First Use Case: Create a Filament resource for your model (e.g., PostResource). The package will automatically add translation fields to the form and table if configured.


Where to Look First

  • Config File: config/filament-translatable.php (for global settings like default locale, fallback behavior).
  • Resource Integration: Check the setupForm() and setupTable() methods in your Filament resource to see how translation fields are injected.
  • Documentation: The README includes a basic usage example and advanced customization.

Implementation Patterns

Workflows

  1. Basic CRUD with Translations:

    • The package auto-detects translatable fields and adds them to Filament forms/tables.
    • Example:
      public static function form(Form $form): Form
      {
          return $form
              ->schema([
                  // Translatable fields are added automatically
                  TextInput::make('title')->required(),
                  RichEditor::make('content'),
              ]);
      }
      
  2. Locale-Specific Forms: Use the TranslatableFields helper to group fields by locale:

    public static function form(Form $form): Form
    {
        return $form
            ->schema([
                TranslatableFields::make('title', 'content')
                    ->locales(['en', 'es', 'fr']),
            ]);
    }
    
  3. Conditional Translations: Dynamically enable/disable translations based on user roles or model state:

    public static function form(Form $form): Form
    {
        return $form
            ->schema([
                TextInput::make('title')
                    ->translatable()
                    ->visible(fn () => auth()->user()->can('translate')),
            ]);
    }
    
  4. Table Localization: Display translations in tables with a dropdown to switch locales:

    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                TextColumn::make('title')
                    ->translatable()
                    ->locale(fn () => request()->get('locale', 'en')),
            ]);
    }
    

Integration Tips

  1. Custom Field Types: Extend the package to support custom Filament fields (e.g., Select, Checkbox):

    use Webard\FilamentTranslatable\Fields\TranslatableField;
    
    class TranslatableSelect extends TranslatableField
    {
        protected static string $fieldType = Select::class;
    
        public static function make(string $name, ?string $label = null): static
        {
            return parent::make($name, $label)->columnSpanFull();
        }
    }
    
  2. API Responses: Use the toArray() or toJson() methods with the translatable option:

    return Post::withTranslations()->get()->toJson(['translatable' => true]);
    
  3. Middleware for Locale: Set a default locale via middleware:

    public function handle(Request $request, Closure $next)
    {
        app()->setLocale(request()->get('locale', config('filament-translatable.default_locale')));
        return $next($request);
    }
    
  4. Seeding Translations: Use the createTranslations() helper in seeders:

    Post::createTranslations([
        'title' => ['en' => 'Hello', 'es' => 'Hola'],
        'content' => ['en' => 'World', 'es' => 'Mundo'],
    ]);
    

Gotchas and Tips

Pitfalls

  1. Field Name Collisions:

    • If a field name conflicts with a non-translatable field (e.g., created_at), explicitly specify the translatable fields in the model:
      public $translatable = ['title', 'content']; // Avoids ambiguity
      
  2. Locale Fallback:

    • Ensure config('filament-translatable.fallback_locale') is set to avoid errors when a translation is missing.
    • Example config:
      'fallback_locale' => 'en',
      
  3. Database Schema:

    • The package uses a json column for translations by default. For large datasets, consider using a dedicated translations table (customize via config('filament-translatable.storage')).
  4. Caching Issues:

    • Clear Filament's cache after adding/removing translatable fields:
      php artisan filament:cache-reset
      
  5. Nested Resources:

    • If using nested resources, ensure the parent resource's setupForm()/setupTable() calls are after the child's to avoid field duplication.

Debugging

  1. Missing Translations:

    • Check if the translatable array in your model includes all fields.
    • Verify the locale is correctly set in the request or config.
  2. Form Not Rendering:

    • Ensure the TranslatableFields helper or translatable() method is called on the field.
    • Check for JavaScript errors in the browser console (Filament 3.x may require additional setup).
  3. Performance:

    • Use withTranslations() sparingly in queries. For tables, use locale() to limit loaded translations:
      $table->columns([
          TextColumn::make('title')
              ->translatable()
              ->locale('en'), // Load only English translations
      ]);
      

Extension Points

  1. Custom Storage Engine: Override the default storage by binding a custom TranslationRepository:

    $this->app->bind(
        Webard\FilamentTranslatable\Contracts\TranslationRepository::class,
        CustomTranslationRepository::class
    );
    
  2. Field Customization: Extend the TranslatableField class to add logic (e.g., validation, conditional rendering):

    class CustomTranslatableField extends TranslatableField
    {
        public function required(): static
        {
            return $this->rule('required');
        }
    }
    
  3. Translation Events: Listen for translation-related events (e.g., translatable.saving, translatable.saved):

    event(new TranslatableSaving($model, $locale, $attributes));
    
  4. Locale Switcher: Add a dynamic locale switcher to your Filament panel:

    use Webard\FilamentTranslatable\Widgets\LocaleSwitcher;
    
    public function getWidgets(): array
    {
        return [
            LocaleSwitcher::make(),
        ];
    }
    

Pro Tips

  1. Bulk Updates: Use the updateTranslations() method for batch updates:

    Post::where('id', 1)->updateTranslations([
        'title' => ['es' => 'Nuevo Título'],
    ]);
    
  2. Fallback Logic: Implement custom fallback logic in the model:

    public function getTitleAttribute($value)
    {
        return $this->getTranslation('title', config('filament-translatable.fallback_locale'));
    }
    
  3. Testing: Use the actingAsTranslator() helper in tests to simulate locale-specific actions:

    $this->actingAsTranslator('es')->create(Post::class, ['title' => 'Prueba']);
    
  4. Localization in API: Pass the Accept-Language header to API requests for consistent responses:

    $response = Http::withHeaders(['Accept-Language' => 'es'])->get('/api/posts');
    
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.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle