bbs-lab/nova-translation
Laravel Nova package for managing translations in your admin panel. Edit and organize multilingual content, localization strings, and translated resource values from one Nova interface, so teams can maintain Laravel apps in multiple languages without switching tools or juggling separate translation...
This is a maintenance release (v5.4.1) for bbs-lab/nova-translation, a Laravel Nova integration for managing translated model attributes (typically alongside spatie/laravel-translatable). There are no new features or breaking changes — it is a boot-timing fix for the model observer the package registers.
Start here:
composer require bbs-lab/nova-translation and confirm your Nova major version matches the package branch (v5.x targets Nova 4/5-era APIs).php artisan vendor:publish --tag="nova-translation-config"), which is where the supported locale list lives. Keep it aligned with config/app.php and spatie/laravel-translatable's fallback locale.HasTranslations trait and declares the attributes in $translatable — the package edits those JSON columns, it does not create a parallel translations table.NovaServiceProvider::tools() if you are using the global management view).First use case: take one resource with two translatable columns (e.g. title, body on Article), add the translation field, and verify you can switch locale in the Nova detail view, edit, save, and see the raw JSON column update. Do this before rolling it across resources — the field's behaviour on create vs. update is the thing most likely to surprise you.
Upgrade note: if you are on ≤5.4.0, upgrading is low-risk and specifically recommended if you saw observers not firing or behaving inconsistently when models were resolved early in the request lifecycle.
fields() method rather than relying on the tool to cover everything; it keeps authorization and validation co-located with the rest of the resource.locales() override if exposed) and derive your app.locales from the same array, so a new locale is one edit rather than three.whenBooted, you no longer need any manual Model::observe(...) wiring in a service provider. If you wrote your own translation observer or a saving hook to work around the old timing, delete it after upgrading — otherwise you will get double writes.RefreshDatabase, create a model with setTranslation('title', 'fr', '...'), then assert against getTranslations('title') (raw array) rather than getTranslation() (which applies fallback). Set the locale explicitly in the test rather than relying on the default.update ability; gate who can edit translations the same way you gate the underlying model, since translators are often a separate user group from authors.updated events firing twice on a translation save. Check with Model::getEventDispatcher()->hasListeners('eloquent.updated: App\Models\Article').boot() and be aware the package's observer may be attached afterwards. Do not assume the package observer exists when your provider's boot() runs.php artisan config:clear in a cached environment. This is the most common "my new locale doesn't appear" report.$translatable mismatch fails silently. A field pointing at a column not listed in $translatable (or a non-json column) will render but not persist as expected. Verify the schema column type and the trait array together.getTranslation() returns the fallback string when a locale is blank, so an "empty" translation can look populated. Use getTranslations()/getTranslationsWithoutFallback() when you need the truth.'title' => 'required' apply to the array, not per locale. Use nested rules keyed by locale if you need "required in the primary locale only", or you will block saves on partially translated content.php artisan about (Nova + package versions) → config published and locales correct → model trait and $translatable correct → observer registered (dump the event dispatcher) → raw DB row updated. That sequence isolates nearly every report.composer.json if you ship on Octane or long-running workers; boot-timing fixes are exactly the class of change worth controlling deliberately.How can I help you explore Laravel packages today?