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

Nova Translatable Laravel Package

optimistdigital/nova-translatable

Nova Translatable brings multilingual editing to Laravel Nova, wrapping text, textarea, and other fields in locale tabs so you can manage translations for spatie/laravel-translatable models directly inside the Nova admin panel.

View on GitHub
Deep Wiki
Context7

Product Decisions This Supports

  • Localization roadmap scoping. This package is the admin-editing layer for a multilingual content model. It answers a narrow but recurring question — how do editors enter and review translated copy in Nova? — and nothing more. It does not deliver localized routing, hreflang, SEO metadata pipelines, translation memory, or workflow/approval tooling. Treat it as one line item in an i18n roadmap, not the roadmap itself. The roadmap item it does unblock is "editors can author content in N languages without engineering tickets."

  • Build vs. buy on admin UI. Without it, the alternative is hand-rolling locale tabs, a locale switcher, per-locale validation, and the save/reload round-trip on top of spatie/laravel-translatable inside Nova. That work is unglamorous, easy to underestimate, and never a differentiator. MIT license, small surface, near-zero acquisition cost — this is a clear "adopt" against a "build" that would cost days per resource and drift from upstream. The one real cost is coupling to Nova majors, which is a maintenance line item, not a build line item.

  • Feature-level decisions it enables. Multi-market content authoring, per-locale copy review before publish, locale-complete QA on product/category/page records, and market-specific naming for catalogs. If a roadmap item reads "support N languages in the admin," this package is the smallest credible increment — one resource, two columns, two to three locales proves the tab switcher, per-locale validation, and save/reload round-trip in about twenty minutes of smoke testing.

  • Repeatable content blocks are now in scope (3.1.0+). Native Nova Repeatable support moves this from "translated attributes" to "translated structured content" — hero sections, feature lists, FAQ entries — which is where most marketing pages actually live. This is a roadmap-enabling change, but the nested surface is newer code. Scope it to one resource first and personally exercise: add a row and fill one locale, partial-row translation, reorder after partial translation, deletion of half-filled rows, and per-row-per-locale validation errors landing on the right tab. If any of that is odd, fall back to flat translatable columns for that resource and revisit after the next release. Do not put nested Repeatable + Translatable on a launch-critical path in the same quarter you adopt it.

  • Editorial workflow decisions it surfaces. ->rules('required') fires on every locale, so a naive rule list blocks save until all languages are filled — editors then type "TODO" into four languages, which is worse than empty because it looks done. This forces a deliberate product call with a named owner: required everywhere as a hard content gate, or required nowhere plus a publish-readiness check in a NovaRequest. "Required in the default locale, optional elsewhere" is not something the field gives you; it needs a custom rule inspecting the JSON payload by locale key. Budget for that if the business rule is real.

  • Media localization decision. Wrapping an Image field produces N upload controls and N files on disk for what a designer assumed was "one hero image." Either keep media outside the wrapper (one asset, localized caption/alt only) or consciously adopt and document the per-locale asset model. This is a product decision hiding inside a field definition — surface it in the spec, not in code review, and get design sign-off before an editor discovers it.

  • Locale scope per resource. Global config is rarely right everywhere: a "Site Settings" resource may need two languages while a product catalog needs five. Per-field ->locales([...]) overrides let you keep the global list broad and narrow per resource, which is also the escape hatch for resources that shouldn't expose every configured locale to editors. Cheaper than a permissions system for a small ops team.

  • QA and content-ops cycle time. Because index/detail views render whichever locale the JSON happens to resolve to, "which language am I looking at?" becomes a recurring QA tax. Five lines of explicit locale columns (Title (EN)) removes it from every cycle — a small, high-leverage investment that pays back per release.

  • Sorting and filtering are a scoping boundary, not a bug. sortable() and filterable() don't work meaningfully on a JSON column. If admins need to sort product names, that requires a materialized title_en generated column or an accessor-backed field — a schema decision to make before promising a sortable catalog table, not after.

When to Consider This Package

Adopt when all of the following hold:

  • You run a licensed Laravel Nova install. This is a Nova field; it does nothing outside one.
  • You already use spatie/laravel-translatable, with translated attributes in JSON columns and the HasTranslations trait wired up. The package renders a UI over that storage — it does not create the schema or the trait. If that foundation isn't in place, fix it first; it's the single most common reason the field "doesn't work."
  • Your translation need is editor-entered copy on a handful of resources, not machine translation, vendor TMS integration, or an approval workflow.
  • You have a small ops/editorial team (or can approximate one with a per-user ->locales([...]) override based on the current user or a ?locale= param). The field always shows all configured locales in one form; if you need genuinely per-editor locale contexts or role-based locale permissions, that's custom work.
  • You can absorb the Nova-major upgrade risk — pin the exact package version and keep one smoke-test resource (a flat translatable field plus a Repeatable-backed one) in your manual QA script for every Nova bump. Community fields lag Nova majors, and 3.1.0 widened the blast radius by depending on Nova's Repeatable internals.

Look elsewhere or defer when:

  • No Nova license, or Nova is on the way out. If the admin UI is being replaced or rewritten, do not add field-level dependencies to it.
  • Translations come from a TMS or external vendor and editors are reviewing, not authoring. The tab-switcher model is built for authoring; a sync/inbox pattern fits review workflows better.
  • You need per-locale permissioning, translation status/state machines, or publish gating per language. Those are resource-level concerns to build on top, and the package won't carry you there.
  • You need sortable/filterable multilingual columns at the database level. That's a schema design problem (generated columns, separate translation tables), not a Nova field problem.
  • Nested Repeatable + Translatable is on the critical path this quarter. The capability exists but is newer code; adopt flat translatable fields first and stage the structured-content case.

A reasonable de-risking path: one resource, two fields, two to three locales, prove the tab switcher, per-locale validation, and the save/reload round-trip in a single sitting. That catches misconfigured columns, missing $translatable entries, and cached config in one pass, before any commitment to Repeatable, file fields, or cross-tab reactive configuration. Confine usage to fields() in resources — no service-provider hacks, no overriding internals — so that if upstream stalls, forking or replacing is a mechanical edit across a handful of files rather than an archaeology project.

How to Pitch It (Stakeholders)

For executives — the one-liner: This is a free, MIT-licensed admin UI layer that lets our editors enter translated content in Laravel Nova without engineering involvement. It converts "add language support" from a multi-week custom build into a config change plus a per-resource wrapper, and it makes our existing spatie/laravel-translatable investment actually usable by non-technical staff.

The business case in three points:

  1. Cheap to acquire, cheap to abandon. MIT license, small codebase, near-zero cost. The realistic alternative is days of custom Nova field development per resource that will never be a differentiator and will drift from upstream.
  2. Unblocks a roadmap item that's currently gated on engineering. Multi-market authoring, per-locale copy review, and locale-complete QA all become editor self-service instead of ticket-driven.
  3. The risk is bounded and named. The real risk surface is a Nova major upgrade, not day-to-day use. We mitigate with exact version pinning and a two-field smoke-test resource in the QA script. If upstream stalls, the codebase is small enough to fork or replace in a handful of files.

For engineering — what it actually is: A thin Nova field wrapper around spatie/laravel-translatable. It provides locale tabs, a locale switcher, and per-locale form inputs over JSON columns. It assumes the model trait and JSON schema already exist — it does not create them. Configuration is a locale map in config/nova-translatable.php (remember config:clear), with per-field ->locales() overrides for resources that need a narrower list. Usage stays inside fields() behind Translatable::make([...]), so the blast radius is contained. Note the vendor rename: older docs say optimistdigital/nova-translatable; new installs use outl1ne/nova-translatable — same package, don't churn a working composer.json for the rename.

For engineering — the caveats to plan around, not discover:

  • required fires on every locale. We need an explicit rule strategy, and "required in default locale only" means a custom NovaRequest rule against the JSON payload.
  • Empty string vs. null breaks Spatie fallbacks; Nova submits '' for untouched inputs. Check the raw JSON column first when fallbacks misbehave.
  • sortable()/filterable() don't work on JSON columns. Sorting multilingual columns needs materialized generated columns — a schema decision, not a field tweak.
  • Reactive fields across tab boundaries are fragile; keep dependsOn() chains inside the same Translatable group and verify in the browser.
  • Slugs don't auto-generate per locale — wire that in a model observer or NovaRequest hook.
  • Don't build CI around rendering the Nova form (license requirement, awkward internals). Test the model layer and NovaRequest rules with plain PHPUnit; cover the field with a short manual checklist.

For design and content ops — the decisions we need from you before build:

  • Media: one hero image per record with localized alt/caption, or a distinct asset per locale? The field gives you per-locale uploads by default; that's rarely what was meant.
  • Required-ness: is a hard gate across all locales a feature (content completeness) or a footgun (editors typing "TODO")? If the answer differs by locale, say so now — it's custom rule work.
  • Locale scope: which resources genuinely need all N languages, and which need a narrower set? This drives per-resource overrides and editor UX.

The recommended first commitment: one resource, two to three fields, two to three locales, behind a smoke test of add → switch locale → fill → save → reload. If that passes cleanly, expand to a second resource and a Panel layout mixing translatable and non-translatable fields. Hold Repeatable-backed structured content until that first resource has been through a full editorial cycle.

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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource