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 Locale Field Laravel Package

optimistdigital/nova-locale-field

A Laravel Nova field for multilingual admin interfaces. Add locale selection to Nova forms and manage localized resource values with a simple, configurable field from Optimist Digital.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package and add a JSON column to the model you want to localise:

composer require optimistdigital/nova-locale-field
// migration
$table->json('title')->nullable();

// app/Models/Page.php
protected $casts = ['title' => 'array'];

Then drop the field into the Nova resource:

use OptimistDigital\NovaLocaleField\LocaleField;

LocaleField::make('Title', 'title')
    ->locales([
        'en' => 'English',
        'et' => 'Estonian',
        'fi' => 'Finnish',
    ]),

The first use case is a CMS-style resource (Page, Post, Product) where editors fill in a title/body per locale and the whole map {"en": "...", "et": "..."} is stored in one column. Open the Nova resource, switch between locale tabs, and save.

Look first at: the README's exact method names (locales() vs setLocales()), the model's cast, and the stored value in the DB after one save — that JSON is the contract everything else depends on.

Implementation Patterns

  • Single source of truth for locales. Read from config/app.php ('locales' => [...]) or a small config file and pass the same array to every LocaleField. Hard-coded per-field arrays drift and break fallback logic.
  • Accessor with fallback. Reading a locale directly from a JSON column is verbose; wrap it:
    public function translated(string $field): ?string
    {
        return $this->{$field}[app()->getLocale()]
            ?? $this->{$field}['en']
            ?? null;
    }
    
  • Index/detail display. The raw field renders the JSON blob on index columns, which is unreadable. Use ->onlyOnForms() on the LocaleField and add a plain Text field in index()/detail() that calls your translated() accessor.
  • Validation. rules() applies to the whole attribute. Stack a custom rule that iterates locale keys for required-locale checks, and keep generic array rules on the field itself.
  • Slug generation. Generate slugs from the primary locale's value after the field is filled (a saving observer works) rather than trying to derive them per-tab.
  • Don't mix with spatie/laravel-translatable. That package expects one column per locale; this one writes a single JSON map. Use one or the other on any given column.

Gotchas and Tips

  • Archived since Feb 2021. No Nova 4/5 support, no bug fixes, no security patches. Budget for a fork if you're on modern Nova.
  • JSON column, not TEXT. MySQL 5.7+/Postgres work fine; TEXT works only if you cast to array and never query into it.
  • Nova searchable() is effectively useless. The column is JSON, so index searches hit the serialized string. Add a separate plain-text search column if you need index search.
  • "Array to string conversion" on validation failure. Nova rehydrates the field from the request; if the model isn't cast to array you'll get this error the moment a rule fails. Always cast.
  • Normalise empties. Decided whether blank locales are null or "" and normalise in a mutator — otherwise translated() returns "" and hides your fallback.
  • Locale list drift. If the field's locales() and app()->getLocale()/your accessor fallback disagree, you'll get nulls for content that clearly exists. Keep both sourced from one config key.
  • Limited extension points. It's a straightforward form field; for custom tab labels, per-locale placeholders, or conditional locale sets you'll subclass LocaleField and override component() or its form template rather than rely on fluent builders.
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