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

Language Switcher Plugin Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

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:

  1. routes/ — the switch endpoint(s) and their names.
  2. src/Http/Middleware/ — how the locale is persisted (session, cookie, or both).
  3. resources/views/ — the switcher partial you will actually render.
  4. The published config file — the locale list and any route toggles.

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

Implementation Patterns

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');

Gotchas and Tips

  • Archived means untested on modern stacks. PHP 8 and Laravel 9+ removed helpers this era of code used (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.
  • Session not persisting is almost always the route living outside the web middleware group. The switch endpoint must have StartSession in its stack or the choice vanishes on the next request.
  • Cookie and session can disagree. If the package writes both, clearing one on logout leaves the other. Flush both in your logout handler, or the next anonymous request inherits the last user's language.
  • 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')).
  • Route caching. Package route files containing closures break 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.
  • Locale list duplication. The package config, config/app.php, and your DB user preference can all list locales. Pick the config key as canonical and derive the rest.
  • RTL is not covered. Switching to ar or he changes strings only. Set dir="rtl" yourself in the layout based on app()->getLocale().
  • Debugging checklist: 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).
  • Extension points are limited to what was published: the config file, the Blade views, and the middleware binding. There is no event system or driver pattern here — which is another argument for owning the logic yourself and treating the package as a reference implementation of the switcher partial.
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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib