wirelab/language_switcher-plugin
A lightweight language switcher plugin for Laravel and Filament applications. It adds a ready-to-use switcher UI for moving between your configured locales, letting visitors and panel users change language on the fly without writing custom code.
Confirm the package is still installable before anything else. It is archived, last tagged in November 2017, so it targets the Laravel 5.4–5.5 era. Check composer.json in the repo for the illuminate/support constraint and the autoload namespace, then attempt the install on a throwaway branch:
composer require wirelab/language_switcher-plugin
Two registration paths exist depending on your Laravel version. If the package ships a providers entry in its extra.laravel block, auto-discovery handles it on 5.5+. Otherwise add the provider (read src/ for the exact FQCN — usually Wirelab\LanguageSwitcher\...ServiceProvider) to config/app.php.
Then publish whatever it exposes:
php artisan vendor:publish --provider="Wirelab\LanguageSwitcher\LanguageSwitcherServiceProvider"
Look at these four places first, because on a package this small they are the entire surface area:
routes/ — the switch endpoint(s) and their names.src/Http/Middleware/ — how the locale is persisted (session, cookie, or both).resources/views/ — the switcher partial you will actually render.First use case: drop the published partial into your layout's header, hit the switch route in a browser, and verify app()->getLocale() changed and survived a full page reload. If it survives reload, the middleware is wired correctly; if not, that is your first fix (see Gotchas). Confirm with:
php artisan route:list | grep -i lang
Persistence via middleware. The core value of the package is the middleware that reads a chosen locale and calls App::setLocale(). Register it in the web group so it runs after StartSession:
// app/Http/Kernel.php
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Session\Middleware\StartSession::class,
// ...
\Wirelab\LanguageSwitcher\Http\Middleware\SetLocale::class,
],
];
Middleware ordering matters more than the switcher UI: the locale must be set before the controller renders messages, validation errors, or Carbon-formatted dates. If you see a page where the nav is translated but validation errors are not, the middleware is running too late in the stack.
Rendering the switcher in a layout. Loop the configured locales rather than hardcoding links:
@foreach (config('language_switcher.locales', ['en', 'fr', 'de']) as $locale)
<a href="{{ route('language.switch', $locale) }}"
class="{{ app()->getLocale() === $locale ? 'font-bold' : '' }}">
{{ strtoupper($locale) }}
</a>
@endforeach
Prefer a POST switch for anything stateful. A GET link that mutates the session is cacheable and prefetchable. Wrap it in a form with @csrf and have the route redirect back:
<form method="POST" action="{{ route('language.switch') }}">
@csrf
<select name="locale" onchange="this.form.submit()">
@foreach (config('language_switcher.locales') as $locale)
<option value="{{ $locale }}" @selected(app()->getLocale() === $locale)>
{{ $locale }}
</option>
@endforeach
</select>
</form>
Set the locale from user preference at login. The package only handles the interactive switch. For returning users, store the choice on the users table and set it in a Login event listener or a small middleware, rather than relying on a cookie that expires.
Do not combine with a URL-prefix localizer. If you also use mcamara/laravel-localization (or your own /en/... prefix), you now have two sources of truth — session and URL segment — and they will disagree on deep links. Pick one. The package suits session-based switching on a single canonical URL; the prefix approach suits SEO. They are not complementary.
Wrap it. Because the package is archived, put a thin layer between it and your app: your own SetLocale middleware that either delegates to the package's or reimplements ten lines of logic, and your own Blade partial that @includes or replaces the published one. When you eventually replace the package, you change one file.
Testing. Assert both the session write and the rendered locale:
$this->post(route('language.switch'), ['locale' => 'fr'])
->assertRedirect()
->assertSessionHas('locale', 'fr');
$this->withSession(['locale' => 'de'])->get('/')->assertSee('Hallo');
array_get, string helpers via Illuminate\Support\Str migration, untyped property assumptions). Run the test suite against your actual Laravel version on a branch before committing to it. If it fails, the middleware is roughly fifteen lines — reimplement rather than patch.web middleware group. The switch endpoint must have StartSession in its stack or the choice vanishes on the next request.url()->previous() loops. A switcher on the page it redirects back to can bounce between locales if the referer is the switch route itself. Always pass an explicit fallback: redirect()->back(fallback: route('home')).php artisan route:cache. Check routes/ before enabling it in production; if there are closures, register the route yourself in routes/web.php and disable the package's.config/app.php, and your DB user preference can all list locales. Pick the config key as canonical and derive the rest.ar or he changes strings only. Set dir="rtl" yourself in the layout based on app()->getLocale().dd(app()->getLocale()) in a view composer; php artisan route:list for the endpoint; check config('app.fallback_locale') is not silently masking a broken switch; confirm the published view is the one being rendered (publish overwrites silently).How can I help you explore Laravel packages today?