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

Vendra Localization Laravel Package

misaf/vendra-localization

misaf/vendra-localization is a Laravel package that adds localization support to Vendra applications, making it easier to manage locales, translations, and multilingual content. Install and configure it to add language switching and localized strings to your project.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install and publish: composer require misaf/vendra-localization, then run php artisan vendor:publish --provider="Misaf\VendraLocalization\VendraLocalizationServiceProvider" (or the interactive vendor:publish prompt) to get the config file and the language stubs. Tags vary between releases — run php artisan vendor:publish without arguments first and pick the vendra-localization-* entries rather than guessing tag names.

  • Look here first, in this order:

    1. config/vendra-localization.php — the supported-locale map, fallback, and detection order are almost always the only things you need to touch.
    2. The service provider — to see which contracts are bound (locale resolver, negotiator) that you can swap.
    3. The middleware class — to confirm whether it writes to session, cookie, or only resolves per-request.
  • Register the middleware. Laravel 11+: append it to the web group in bootstrap/app.php. Laravel 10: add the alias in app/Http/Kernel.php and place it in web after StartSession and ShareErrorsFromSession.

  • First use case: negotiate the request locale from Accept-Language, persist the user's choice in session, and let app()->getLocale() propagate to __(), validation messages, Blade, and Carbon. Verify in tinker:

    app()->setLocale('pt_BR');
    __('validation.required'); // should resolve from lang/pt_BR/validation.php
    
  • Smoke test the whole chain with a request that sends Accept-Language: pt-BR,pt;q=0.9,en;q=0.8 and assert both the rendered translation and the Content-Language header, otherwise you'll only discover negotiation bugs in production.

Implementation Patterns

  • Middleware-based negotiation is the default and usually the right one. Configure detection order (route param → session → user column → Accept-Language → fallback) in config instead of writing your own if chain in a controller.
  • Persisting the preference. Add a nullable locale column to users, update it in a POST /locale/{locale} controller, and have your resolver read the authenticated user before falling back to Accept-Language. Validate the incoming locale against array_keys(config('vendra-localization.locales')) — never trust the raw string into setLocale().
  • Localized routing. Wrap routes in a /{locale} group with a ->whereIn('locale', $supported) constraint driven by the same config array. Pair with URL::defaults(['locale' => app()->getLocale()]) in a middleware so route('posts.show', $post) keeps the prefix automatically.
  • Translatable content. For models (products, categories, pages), use JSON columns plus the package's translation trait/accessor so $product->name resolves against the current locale with a fallback. Keep one canonical column (name_en) for search/sort if you need indexed queries.
  • Language switcher in Blade. Iterate the config array, render <a href="{{ route('locale.switch', $code) }}">, and emit <link rel="alternate" hreflang="…"> tags from the same loop — a switcher without hreflang is half the SEO benefit.
  • API / stateless endpoints. Put the middleware on api without session writes, keyed strictly on Accept-Language, and echo the resolved locale back in Content-Language. This keeps caching predictable.
  • Deferred locale for mail and jobs. Request locale does not survive the queue. Capture the locale at dispatch time ($job->locale = app()->getLocale()) or wrap sends in Mail::locale($user->locale)->to(...).
  • Tests. Use $this->withHeader('Accept-Language', 'pt-BR') and $this->assertSame('pt_BR', app()->getLocale()). Add a locale-switch feature test that posts an unsupported locale and asserts a 400/422 rather than a silent fallback.

Gotchas and Tips

  • Locale format mismatch is the #1 bug. HTTP uses pt-BR, Laravel/PHP gettext directories use pt_BR. Normalize in one place (a small normalize() on your resolver) before it reaches setLocale() or your lang/ lookup.
  • Middleware ordering. Resolving locale before StartSession silently loses the persisted preference — you get "it works until you reload" reports. Also be aware that route-model binding for localized slugs needs the locale set before SubstituteBindings.
  • Config cache in production. Editing config/vendra-localization.php on the server does nothing until php artisan config:cache is re-run. Conversely, after a package upgrade always run php artisan optimize:clear before debugging "the fix didn't apply."
  • Route cache. Dynamic locale constraints built from a config array are fine, but closures in locale-switch routes will break route:cache. Check php artisan route:cache in CI.
  • Missing JSON keys fall back to the key itself (__('checkout.title') returns checkout.title), not to your fallback locale. Ensure every key exists in the fallback file and add a test that diffs key sets between locales.
  • Locale leaks between tests. app()->setLocale() is sticky; reset to config('app.fallback_locale') in tearDown() or you'll get order-dependent green builds.
  • Formatting is separate. Dates/numbers go through Carbon/NumberFormatter and won't follow Laravel's locale automatically in every version — set it explicitly where formatting matters (invoices, exports).
  • Upgrade guidance for v1.12.3. The release notes for this version are a changelog link only (v1.10.0…v1.12.3), so two minor bumps are rolled into one upgrade: read the compare diff for new config keys, changed resolver contracts, and deprecations before bumping. Pin with "misaf/vendra-localization": "^1.12", republish config without --force (diff and merge manually), clear caches, then run your locale-negotiation and translation-coverage tests. Treat it as a feature release, not a patch — even though the version number ends in .3.
  • Extension points worth knowing: swap the locale resolver via container binding rather than forking the middleware, subclass the middleware to add tenant/user logic, and listen for any LocaleChanged-style event to invalidate per-locale caches (menu caches, sitemaps, hreflang maps) instead of rebuilding them on every request.
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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
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