Trabajar con modelos multilenguaje en Laravel 11 es esencial cuando desarrollas aplicaciones para usuarios en diferentes países. Aunque existen paquetes que facilitan esta tarea, también es posible lograrlo sin dependencias externas. En este artículo, veremos cómo estructurar nuestras tablas y modelos para gestionar traducciones de forma eficiente.
#Estructura de la Base de Datos
Primero, necesitamos una estructura de base de datos que incluya una tabla para el modelo principal (por ejemplo, posts
) y otra para las traducciones (post_translations
). De esta forma, almacenamos la información principal en la tabla de posts
y los textos traducidos en post_translations
.
Schema::create('posts', function (Blueprint $table) { $table->id(); $table->dateTime('publish_date')->nullable(); $table->foreignId('user_id')->constrained(); $table->softDeletes(); $table->timestamps();}); Schema::create('post_translations', function (Blueprint $table) { $table->id(); $table->foreignId('post_id')->constrained()->cascadeOnDelete(); $table->string('locale'); $table->string('title'); $table->longText('content'); $table->softDeletes(); $table->timestamps();});
#El Modelo Post
El modelo principal, Post
, se encargará de gestionar las traducciones a través de una relación hasMany
con el modelo PostTranslation
. Además, se utilizará una relación hasOne
para cargar automáticamente la traducción correspondiente al idioma actual.
use Illuminate\Database\Eloquent\Model;use Illuminate\Database\Eloquent\Relations\HasMany;use Illuminate\Database\Eloquent\Relations\HasOne; class Post extends Model{ protected $fillable = ['publish_date', 'user_id']; protected $with = ['currentTranslation']; public function translations(): HasMany { return $this->hasMany(PostTranslation::class); } public function currentTranslation(): HasOne { return $this->translations()->one()->where('locale', app()->getLocale()); } public function author(): BelongsTo { return $this->belongsTo(User::class, 'user_id'); } public function title(): Attribute { return new Attribute( get: fn() => $this->defaultTranslation->title, ); } public function content(): Attribute { return new Attribute( get: fn() => $this->defaultTranslation->content, ); }}
#El Modelo PostTranslation
El modelo PostTranslation
gestionará las traducciones de cada campo de texto en diferentes idiomas. Su relación con el modelo principal Post
será a través de una relación belongsTo
.
use Illuminate\Database\Eloquent\Model; class PostTranslation extends Model{ protected $fillable = ['post_id', 'locale', 'title', 'content']; public function post() { return $this->belongsTo(Post::class); }}
#Guardar Publicaciones con Traducciones
Cuando guardamos una nueva publicación, podemos hacerlo incluyendo todas las traducciones en un solo paso. Esto se puede gestionar desde el controlador de la siguiente manera:
$post = Post::create([ 'publish_date' => now(), 'user_id' => auth()->id(),]); $post->translations()->createMany([ ['locale' => 'en', 'title' => 'English Title', 'content' => 'Content in English'], ['locale' => 'es', 'title' => 'Título en Español', 'content' => 'Contenido en Español'],]);
#Consideraciones Finales
Aunque existen paquetes para manejar la traducción de modelos en Laravel, implementar este enfoque sin dependencias te da más control sobre el código. Además, esta solución es altamente escalable y fácil de personalizar según las necesidades de tu aplicación.