Extra Table Extended - nevadskiy/laravel-translatable GitHub Wiki

This strategy works in a similar way to Extra Table, but with a slight difference. Translatable fields must be present in both the original entity table and the separate table for translations. The values of translatable attributes in the original table are always considered translations for the fallback locale.

The following picture shows the database schema of this strategy. Columns that contain actual translations are highlighted in blue.

Database structure

Set up

Let's make, for example, a translatable Book model that has 2 translatable attributes: title and description.

The model class may look like this:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Nevadskiy\Translatable\Strategies\ExtraTableExtended\HasTranslations;

class Book extends Model
{
    use HasTranslations; 

    protected $translatable = [
        'title', 
        'description',
    ];
}

And we need 2 tables: books and book_translations.

The simplest books table migration might look like this:

Schema::create('books', function (Blueprint $table) {
    $table->id();
    $table->string('title'); // Used for translations to the fallback locale.
    $table->text('description'); // Used for translations to the fallback locale.
    $table->timestamps();
});

The translatable fields title and description must be present in both tables: books and book_translations.

The book_translations table might look like this:

Schema::create('book_translations', function (Blueprint $table) {
    $table->id();
    $table->foreignId('book_id')->references('id')->on('books');
    $table->string('locale', 2);
    $table->string('title');
    $table->text('description');
    $table->timestamps();

    $table->unique(['book_id', 'locale']);
});

That's all. The model is now ready to work with translations.

Configuration

All configuration options work similarly to the Extra Table strategy.

Restrictions

Note that you cannot create a record for translatable model by setting translations only for custom locale (without translations in fallback locale) because the model requires the fallback translations to be stored in the original entity table.

$this->app->setLocale('uk'); // The fallback locale is considered to be `en`.

$book = Book::create($attributes); // This will fail.

To avoid that you can mark translatable fields as nullable in the database migration or force a model creation in fallback locale and add translations to other locales after that.