Guide : Rendre un Modèle Traduisible

Version : 1.0 Date : 2026-01-25 Story : Epic 5, Story 5.4


Vue d'ensemble

Ce guide explique comment rendre un modèle Eloquent traduisible en utilisant le système de traduction multilingue. En suivant ces étapes, vous pourrez stocker et récupérer des traductions pour les champs de votre modèle.


1. Prérequis

  • Les traductions doivent être activées : TRANSLATIONS_ENABLED=true
  • Le composant BDD doit être activé : TRANSLATIONS_DATABASE_ENABLED=true
  • Le package spatie/laravel-translatable doit être installé

  • 2. Étapes de migration

    Étape 1 : Créer la migration

    Créez une migration pour modifier les colonnes en JSON :

    php artisan make:migration make_{table}_translatable --table={table}
    

    Exemple : Pour la table articles

    <?php

    use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema;

    return new class extends Migration { public function up(): void { Schema::table('articles', function (Blueprint $table) { // Modifier les colonnes en JSON $table->json('title')->nullable()->change(); $table->json('content')->nullable()->change(); $table->json('slug')->nullable()->change(); }); }

    public function down(): void { Schema::table('articles', function (Blueprint $table) { // Revenir en string (perte de données) $table->string('title')->nullable()->change(); $table->text('content')->nullable()->change(); $table->string('slug')->nullable()->change(); }); } };

    Étape 2 : Ajouter le trait au modèle

    <?php

    namespace App\Models;

    use App\Specifics\Shares\Models\Concerns\ConditionallyTranslatable; use Illuminate\Database\Eloquent\Model;

    class Article extends Model { use ConditionallyTranslatable;

    protected $fillable = [ 'title', 'content', 'slug', ];

    protected function getTranslatableFields(): array { return ['title', 'content', 'slug']; } }

    Étape 3 : Configurer les casts (optionnel)

    Si vous voulez que Laravel gère automatiquement le cast JSON :

    protected function casts(): array
    {
        return [
            'title' => 'array',
            'content' => 'array',
            'slug' => 'array',
        ];
    }
    

    Note : Le trait ConditionallyTranslatable gère automatiquement les casts selon l'activation des traductions.

    Étape 4 : Activer pour le modèle

    Fichier : .env

    TRANSLATIONS_MODEL_ARTICLE=true
    

    Ou dans config/translations.php :

    'models' => [
        'article' => env('TRANSLATIONS_MODEL_ARTICLE', true),
    ],
    


    3. Migration des données existantes

    Si vous avez déjà des données dans la table, vous devez les migrer vers le format JSON.

    Option 1 : Utiliser la commande de migration

    php artisan translate:migrate-data --model=Article
    

    Option 2 : Migration manuelle

    use App\Models\Article;

    $articles = Article::all(); $defaultLocale = config('translations.default_locale', 'fr');

    foreach ($articles as $article) { // Récupérer l'ancienne valeur (string) $oldTitle = $article->getRawOriginal('title'); $oldContent = $article->getRawOriginal('content'); $oldSlug = $article->getRawOriginal('slug');

    // Convertir en JSON pour la locale par défaut if ($oldTitle) { $article->setTranslation('title', $defaultLocale, $oldTitle); } if ($oldContent) { $article->setTranslation('content', $defaultLocale, $oldContent); } if ($oldSlug) { $article->setTranslation('slug', $defaultLocale, $oldSlug); }

    $article->save(); }


    4. Utilisation

    Créer avec traductions

    $article = new Article();
    $article->setTranslation('title', 'fr', 'Mon article');
    $article->setTranslation('title', 'es', 'Mi artículo');
    $article->setTranslation('content', 'fr', 'Contenu en français');
    $article->setTranslation('content', 'es', 'Contenido en español');
    $article->save();
    

    Récupérer les traductions

    // Selon la locale courante
    $title = $article->title; // Retourne selon app()->getLocale()

    // Explicitement $titleFr = $article->getTranslation('title', 'fr'); $titleEs = $article->getTranslation('title', 'es');

    // Avec helper $title = trans_model($article, 'title');

    Mettre à jour les traductions

    $article->setTranslation('title', 'fr', 'Nouveau titre');
    $article->save();
    

    Récupérer toutes les traductions

    $allTranslations = $article->getTranslations('title');
    // ['fr' => 'Mon article', 'es' => 'Mi artículo']
    


    5. Utilisation dans Filament

    Voir le Guide Filament pour les détails complets.

    Résumé :

    use App\Filament\Support\TranslatableField;

    ...TranslatableField::makeTextInput('title', 'Titre', fn ($field) => $field->required() ),


    6. Exemple complet

    Modèle

    <?php

    namespace App\Models;

    use App\Specifics\Shares\Models\Concerns\ConditionallyTranslatable; use Illuminate\Database\Eloquent\Model;

    class Product extends Model { use ConditionallyTranslatable;

    protected $fillable = [ 'name', 'description', 'slug', 'price', ];

    protected function getTranslatableFields(): array { return ['name', 'description', 'slug']; } }

    Migration

    Schema::table('products', function (Blueprint $table) {
        $table->json('name')->nullable()->change();
        $table->json('description')->nullable()->change();
        $table->json('slug')->nullable()->change();
        // 'price' reste decimal (non traduisible)
    });
    

    Utilisation

    $product = Product::create([
        'price' => 29.99,
    ]);

    $product->setTranslation('name', 'fr', 'Produit français'); $product->setTranslation('name', 'es', 'Producto español'); $product->setTranslation('description', 'fr', 'Description en français'); $product->setTranslation('description', 'es', 'Descripción en español'); $product->save();

    // Récupérer app()->setLocale('fr'); $name = $product->name; // "Produit français"

    app()->setLocale('es'); $name = $product->name; // "Producto español"


    7. Checklist

  • [ ] Migration créée pour convertir les colonnes en JSON
  • [ ] Trait ConditionallyTranslatable ajouté au modèle
  • [ ] Méthode getTranslatableFields() implémentée
  • [ ] Modèle activé dans .env : TRANSLATIONS_MODEL_{MODEL}=true
  • [ ] Données existantes migrées (si applicable)
  • [ ] Tests effectués

  • 8. Bonnes pratiques

  • Nommage : Utilisez des noms de modèles en minuscules dans la config (article, pas Article)
  • Champs traduisibles : Ne traduisez que les champs de contenu (titre, description, slug). Les champs techniques (ID, dates, prix) ne doivent pas être traduits
  • Slugs : Les slugs doivent être traduits pour une meilleure SEO
  • Fallback : Le système utilise automatiquement un fallback si une traduction est manquante

  • 9. Dépannage

    Les traductions ne sont pas sauvegardées

  • Vérifier TRANSLATIONS_ENABLED=true
  • Vérifier TRANSLATIONS_DATABASE_ENABLED=true
  • Vérifier TRANSLATIONS_MODEL_{MODEL}=true
  • Vérifier que les colonnes sont de type JSON
  • Erreur "Call to undefined method getTranslation()"

  • Vérifier que le trait ConditionallyTranslatable est utilisé
  • Vérifier que getTranslatableFields() retourne un tableau non vide

Prochaines étapes : Consultez le Guide de Traduction BDD pour plus de détails.

Prendre rendez-vous