crayon/nova-language-management
A Laravel Nova package for managing your application's languages and translations directly from the Nova admin panel. Add, edit, enable, or disable locales and keep localization files organized without touching code. A lightweight way to handle multi-language sites inside Nova.
Treat this package as an admin-facing locale registry for Nova, not as a translation-string system. Confirm that in the source before adopting it.
composer.json in the repo/package and check Nova, Laravel, and PHP constraints.src/ for the Nova tool class, service provider, migrations, config, models, and policies.composer require crayon/nova-language-management
Register the tool in app/Providers/NovaServiceProvider.php inside tools() if the package does not auto-register it. Use the exact tool class from the package README/source.php artisan vendor:publish --provider="Crayon\\NovaLanguageManagement\\..."
php artisan migrate
Do not publish blindly; inspect the service provider’s boot() method first.// Example shape; use the package model/table after inspecting source.
foreach ([
['code' => 'en', 'name' => 'English', 'active' => true, 'default' => true],
['code' => 'fr', 'name' => 'French', 'active' => true, 'default' => false],
] as $language) {
Language::updateOrCreate(['code' => $language['code']], $language);
}
en, fr, and de in Nova, then add middleware that resolves the current locale from the authenticated user, session, Accept-Language, or the default active language.Where to look first:
README.mdsrc/ for the Nova tool and service providerdatabase/migrations/ for the languages table schemaconfig/ for cache, table, or middleware optionscomposer.json for Nova/Laravel compatibility1. Build a small locale resolver around the package.
The package manages available languages; your app still needs to decide which one is active per request.
public function handle($request, Closure $next)
{
$supported = Cache::rememberForever('languages.active_codes', function () {
return Language::where('active', true)->pluck('code')->all();
});
$default = Cache::rememberForever('languages.default_code', function () {
return Language::where('default', true)->value('code') ?? config('app.fallback_locale');
});
$locale = $request->user()?->locale
?? $request->session()->get('locale')
?? $this->fromAcceptLanguage($request, $supported)
?? $default;
if (! in_array($locale, $supported, true)) {
$locale = $default;
}
app()->setLocale($locale);
Carbon::setLocale($locale);
return $next($request);
}
Register it after session/auth middleware for web routes. For APIs, use Accept-Language and do not rely on session state.
2. Use Nova as the admin workflow, not as runtime config.
Typical admin flow:
Give the tool a Gate/policy so only trusted admins can change locales.
3. Cache the active locale list and invalidate on writes.
A database query on every request is unnecessary. If the package model fires standard Eloquent events, add an observer:
class LanguageObserver
{
public function saved(Language $language): void
{
Cache::forget('languages.active_codes');
Cache::forget('languages.default_code');
}
public function deleted(Language $language): void
{
Cache::forget('languages.active_codes');
Cache::forget('languages.default_code');
}
}
If the package does not fire usable events, wrap writes in your own service/action and clear cache there.
4. Pair language management with a real translation strategy.
This package should not be expected to store translated UI strings. Use one of:
lang/ files for static translations.spatie/laravel-translation-loader or a custom database translation table for editable strings.spatie/laravel-translatable for model content.Keep the concerns separate: languages/locales are configuration; translations are content.
5. Add a user language preference through a normal Nova field.
Expose a locale select on the user resource populated from active languages. Validate against active codes on save. Then let middleware prefer the user’s stored locale over the session.
6. Seed idempotently for every environment.
Use updateOrCreate by ISO code, not by display name. Keep codes consistent: en, fr, de, not English, French, etc.
7. Treat deployments as locale changes.
Include migrations/seeds for baseline languages and run cache clears after deploy:
php artisan migrate --force
php artisan db:seed --class=LanguageSeeder --force
php artisan optimize:clear
composer.json constraints against your Nova/Laravel/PHP versions. Do not assume Nova 5 or Laravel 11+ support.Accept-Language, then default.config('app.fallback_locale') aligned with the package’s default locale, or make the package default authoritative and document it.RefreshDatabase and seed active/default languages because middleware may query the language table. Test invalid locale, inactive locale, missing default, and API Accept-Language.composer show crayon/nova-language-management
php artisan route:list --path=nova
php artisan tinker
# check app()->getLocale(), config('app.locale'), active language rows
php artisan optimize:clear
<html lang>, JavaScript i18n, or localized routes. Handle those in your Blade/Inertia/Vue layer and route groups.How can I help you explore Laravel packages today?