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

Laravel Translatable Db Laravel Package

flobbos/laravel-translatable-db

Store model translations in a dedicated database table with Laravel. flobbos/laravel-translatable-db adds a simple translatable trait, helpers, and query support so you can persist and retrieve localized fields cleanly without JSON columns.

View on GitHub
Deep Wiki
Context7

Getting Started

First Steps

  1. Installation

    composer require flobbos/laravel-translatable-db
    

    Publish the config and migrations:

    php artisan vendor:publish --provider="Flobbos\LaravelTranslatable\LaravelTranslatableServiceProvider"
    php artisan migrate
    
  2. Basic Model Setup Extend your model with Flobbos\LaravelTranslatable\Translatable trait and define translatable fields in $translatable:

    use Flobbos\LaravelTranslatable\Translatable;
    
    class Post extends Model
    {
        use Translatable;
    
        protected $translatable = ['title', 'content'];
    }
    
  3. First Usage Create a post with translations:

    $post = Post::create([
        'title' => 'English Title',
        'content' => 'English Content',
    ]);
    
    $post->translate('es', [
        'title' => 'Título en Español',
        'content' => 'Contenido en Español',
    ]);
    
  4. Retrieving Translations Fetch a translation by locale:

    $post->getTranslation('es')->title; // "Título en Español"
    

    Or use the localize() helper:

    $post->localize('es')->title; // Same result
    

Implementation Patterns

Common Workflows

  1. Dynamic Translation Handling Use translatable() to dynamically add/remove translatable fields:

    $model->translatable(['new_field']); // Add
    $model->translatable(null); // Reset
    
  2. Locale Fallbacks Configure fallbacks in config/translatable.php:

    'fallback_locale' => 'en',
    'fallbacks' => [
        'es' => 'en',
        'fr' => 'en',
    ],
    

    Then fetch translations with fallback:

    $post->localize('es')->title; // Falls back to 'en' if 'es' missing
    
  3. Scopes for Localized Queries Use the translated() scope to filter by translations:

    Post::translated('title', 'like', '%English%')->get();
    
  4. API Responses Serialize translations in API responses:

    return Post::withTranslations()->get();
    

    Or manually:

    return $post->toArray(['translations']);
    
  5. Form Requests Validate and bind translations in form requests:

    public function rules()
    {
        return [
            'title' => 'required',
            'translations.es.title' => 'required',
        ];
    }
    
    public function prepareForValidation()
    {
        $this->merge([
            'translations' => json_decode($this->input('translations'), true),
        ]);
    }
    

Integration Tips

  • Laravel Scout: Override toSearchableArray() to include translations.
  • Nova/Livewire: Use withTranslations() in queries for admin panels.
  • Validation: Use translatable.* rules for nested validation.
  • Caching: Cache localized responses with Cache::rememberForever().

Gotchas and Tips

Pitfalls

  1. Migration Conflicts

    • If manually creating translations table, ensure it matches the package’s schema:
      Schema::create('translations', function (Blueprint $table) {
          $table->id();
          $table->string('locale')->index();
          $table->json('attributes');
          $table->foreignId('translatable_id')->constrained()->onDelete('cascade');
          $table->unique(['translatable_id', 'locale']);
      });
      
  2. Mass Assignment Risks

    • Always whitelist translatable fields in $fillable or use $guarded.
    • Example:
      protected $fillable = ['title', 'content'];
      
  3. Locale-Specific Queries

    • Avoid querying translations directly (e.g., Translation::where(...)). Use the provided scopes instead.
  4. JSON Field Limitations

    • The attributes column uses JSON, which may cause issues with very large translations. Consider splitting into separate columns if needed.
  5. Model Events

    • Translations trigger savingTranslation, savedTranslation, etc. Listen carefully to avoid infinite loops:
      $model->setAttribute('title', 'New Title');
      $model->save(); // Triggers translation events
      

Debugging Tips

  1. Check for Missing Translations Use hasTranslation('es') to verify:

    if (!$post->hasTranslation('es')) {
        // Handle missing translation
    }
    
  2. Inspect Raw Translations Dump the translations relationship:

    dd($post->translations);
    
  3. Enable Query Logging Temporarily enable debug mode in config/translatable.php:

    'debug' => true,
    
  4. Clear Cached Compiled Views If translations aren’t updating, run:

    php artisan view:clear
    

Extension Points

  1. Custom Storage Override getTranslationsTable() in your model:

    protected function getTranslationsTable()
    {
        return 'custom_translations';
    }
    
  2. Custom Attribute Handling Extend the trait to modify how attributes are stored:

    use Flobbos\LaravelTranslatable\Translatable as BaseTranslatable;
    
    trait CustomTranslatable
    {
        use BaseTranslatable;
    
        protected function getTranslatableAttributes()
        {
            return array_merge($this->$translatable, ['custom_field']);
        }
    }
    
  3. Add Scopes Extend the query builder in your model:

    public function scopeActiveTranslations($query)
    {
        return $query->whereHas('translations', function ($q) {
            $q->where('locale', app()->getLocale());
        });
    }
    
  4. Custom Serialization Override toArray() or toJson() to format translations:

    public function toArray()
    {
        return array_merge(parent::toArray(), [
            'translations' => $this->translations->pluck('attributes', 'locale'),
        ]);
    }
    

Performance Considerations

  • Eager Loading: Always use withTranslations() when fetching models with translations.
  • Indexing: Ensure locale and translatable_id are indexed in the translations table.
  • Batch Updates: Use updateTranslations() for bulk updates:
    $posts->each->updateTranslations('es', ['title' => 'Updated']);
    
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.
nasirkhan/laravel-sharekit
directorytree/privacy-filter-classifier
directorytree/privacy-filter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony