Weave 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

Laravel Translatable Laravel Package

spatie/laravel-translatable

A Laravel trait that makes Eloquent model attributes translatable, storing translations as JSON with no extra table needed. Set and retrieve per-locale values, with fallbacks for missing translations.

View on GitHub
Deep Wiki
Context7

spatie/laravel-translatable adds a HasTranslations trait to Eloquent models, storing translations as JSON columns—no extra tables required. Declare translatable attributes via the #[Translatable] PHP attribute or a public $translatable property, and retrieve values automatically based on the current app locale.

$newsItem->setTranslation('name', 'en', 'Name in English');
$newsItem->name; // Locale-aware value
$newsItem->getTranslation('name', 'nl');
  • Zero schema changes — translations live in existing JSON columns
  • Flexible declaration — use attributes, a property, or both (merged)
  • Locale-aware access — property reads follow app()->setLocale()
  • Explicit retrieval — fetch any locale via getTranslation()
  • Bulk access — pull all translations for a field with getTranslations()
Frequently asked questions about Laravel Translatable
How do I install and set up spatie/laravel-translatable on an Eloquent model?
Require the package with Composer, then add the HasTranslations trait to any Eloquent model that needs translated fields. Declare the translatable columns either with the Translatable PHP attribute or a public $translatable array on the model. No service provider registration, config file, or migration is required to get started. Most teams can instrument their first model in under a day.
Does laravel-translatable create an extra table or require a migration?
No. Translations are stored as a JSON object inside an existing column on the model's own table, so there is no side table, join, or per-locale schema growth. Adding a new locale is a pure data operation rather than a migration. The trade-off is that you lose row-level relational integrity, per-locale indexing, and per-locale audit granularity. For content-shaped models with a handful of translatable fields, that trade is usually worth it.
Should I use the Translatable attribute or the $translatable property?
Both are supported, and when both are present their values are merged and deduplicated. The #[Translatable('name', 'description')] attribute is the modern approach in version 6 and keeps the declaration next to the class, while the legacy public $translatable array still works fine. That overlap makes incremental adoption easy on existing models. Use whichever fits your codebase, but be consistent across models.
How do I set a fallback locale, and why is my model showing the wrong language?
Configure the default once with Translatable::fallback() in a service provider, and override per model via getFallbackLocale() or disable it with $useFallbackLocale. The usual cause of the wrong language in production is silent fallback: a missing translation quietly resolves to the fallback locale or to fallbackAny, which looks like a content bug rather than a missing key. Wire up the missingKeyCallback hook on day one so you get telemetry when a fallback is served. That way gaps surface as alerts instead of as user complaints.
Can I query Eloquent models by a translated value with whereLocale?
Yes. The package ships query scopes including whereLocale, whereLocales, and whereJsonContainsLocale(s), and dot/arrow path notation lets you target nested JSON keys such as meta->description. These scopes compile down to your database's JSON functions, so performance depends on the engine. They are fine for admin filters and modest datasets, but a LIKE-based whereJsonContainsLocale is a UX convenience, not an indexed search strategy at scale.
Does laravel-translatable work with MySQL, PostgreSQL, MariaDB and SQLite?
It works across MySQL 5.7+, MariaDB 10.2.3+, PostgreSQL, and SQLite, but the JSON function behavior and index support differ between them. A query that passes in CI on SQLite can degrade to a full table scan on MySQL once the table grows. Validate your real query patterns against the production engine before they become load-bearing. Generated columns plus indexes, or an external search index, are the usual fix for expensive read paths.
How do I sort or filter an admin list by a translated title?
Translated values live inside a JSON blob, so ordering or range-filtering on them needs generated columns with indexes, or an external search index. The package's JSON scopes help with filtering but will not give you an indexed sort at volume. Plan this early if the admin UI needs sortable translated columns. Otherwise you will find out about the full scan in production.
What happens when two editors save different locales on the same record at once?
The entire translation set is a single column, so concurrent saves of different locales on the same row can overwrite each other with no database-level conflict detection. The package does not solve this for you; it is an explicit design decision. Mitigate with optimistic locking on updated_at or an application-level merge of the changed locale only. Document the behavior so editors are not surprised.
Is spatie/laravel-translatable a replacement for Laravel's lang files?
No, and this distinction matters when reporting to stakeholders. The package translates database content on Eloquent models, while Laravel's lang/ files handle UI strings and validation messages. Adopting a translation package is routinely misread as localization being finished. State clearly that both layers are needed before anyone plans a launch.
Is spatie/laravel-translatable still maintained, and what are the alternatives?
The package comes from Spatie's large open source portfolio, has an active release line, changelog, upgrade guide, and documentation site, and is MIT licensed. Its surface area is small enough to fork or vendor if maintenance ever lapses, so dependency risk is low. If you outgrow the JSON-column model, per-locale rows or a dedicated translation management system with a synced store is the correct alternative. Translation-heavy domains such as thousands of SKUs or vendor handoffs usually need that instead.
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.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo