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

backpack/language-switcher

A Backpack for Laravel add-on that adds a language switcher dropdown to your admin panel's top bar, letting admins switch between configured locales for the interface or translated content. Simple configuration ties it to Laravel's localization system and your available languages.

View on GitHub
Deep Wiki
Context7

Getting Started

backpack/language-switcher is a deliberately tiny, MIT-licensed Backpack addon: it renders a dropdown in the admin top bar, and when you pick a locale it stores it in the session and applies it with App::setLocale() on subsequent requests. That's it. There is no content translation, no URL strategy, no locale negotiation, no hreflang — those remain your job. Treat it as "a dropdown plus a two-line middleware," because that's roughly what you're installing.

What changed in 2.1.0: the only functional change is official Backpack v7 support (PR #21), plus a README refresh. No API changes, no deprecations, no new features — so existing Backpack 6 installs on 2.0.x have no reason to rush the upgrade, and the mental model above is unchanged. The practical consequence is a version-alignment rule you should encode in composer.json before anything else:

  • Backpack 6 project → backpack/language-switcher 2.0.x works; 2.1.x should also work but is untested-by-you.
  • Backpack 7 project → you need ^2.1, because 2.0.x predates v7 support entirely.

Because the package is small (a few dozen stars, negligible dependents), the fastest way to get productive is still to read the source before you configure it: the service provider, the middleware, the single Blade view, and the route it registers. Ten minutes of reading removes all of the guesswork about config keys and view names — and this is doubly true on v7, where the surrounding Backpack config surface moved and the README may lag the code.

Minimal path:

  1. composer require backpack/language-switcher:^2.1 on a Backpack 7 app (or let Composer resolve on Backpack 6). Confirm your Laravel constraint is satisfied — 2.1.0's composer.json is the authority, not the release notes.
  2. Publish the config (and views if you plan to restyle): php artisan vendor:publish --provider="Backpack\LanguageSwitcher\LanguageSwitcherServiceProvider".
  3. Register the middleware so it runs on admin requests — in Backpack 6 the common path is the middleware array in config/backpack/base.php or the backpack middleware group; on v7 verify which config file now owns that group before editing, and confirm with php artisan route:list -v | grep -i admin that your middleware actually appears on the dashboard route.
  4. Add the switcher to the top bar by referencing its Blade view from the relevant Backpack UI config key, or by overriding the topbar view in resources/views/vendor/backpack/.... On v7, publish the views and look at the rendered topbar before assuming the v6 override path is still correct — theme changes are exactly where "supported" and "identical" diverge.
  5. Populate the locales list the dropdown reads from — typically config('app.locales') or the package's own config key. Keep this in a single helper/config so the dropdown, fallback_locale, and your lang/ directories never drift apart.

Where to look first: the published config file (locale list + flag/emoji mapping), the route (php artisan route:list | grep -i lang), and the middleware. First real use case is the obvious one — an editor on a bilingual admin wants to see the panel in Spanish; you add es, click the flag, and Backpack's own UI strings come from lang/es on the next request.

Implementation Patterns

Admin-only switching (the default, safest). Mount the middleware only on Backpack routes. The public site stays on app.fallback_locale. This is the right choice for 80% of installs — the switcher is a convenience for admins, not a public feature.

Site-wide locale via one shared session key. If you do want the front end to follow the admin choice, don't try to stretch the package's route; move the middleware into the web group and make sure it reads the same session key. A 15-line middleware of your own is usually cleaner than reusing theirs:

public function handle($request, Closure $next)
{
    $locale = $request->session()->get('locale', config('app.fallback_locale'));
    if (in_array($locale, config('app.locales'))) {
        App::setLocale($locale);
    }
    return $next($request);
}

Pin the addon alongside Backpack. Since 2.1.0 exists solely to track Backpack v7, treat the two as a unit: bump backpack/crud and backpack/language-switcher in the same PR, and re-run your admin smoke test (switch locale, reload, assert app()->getLocale()) after every Backpack minor. A v7 upgrade with the addon left at 2.0.x is the most likely near-term breakage.

Persist a per-user preference. Add a locale column to users, set the session from it on login, and write it back in a listener on Illuminate\Auth\Events\Login / when the switch route is hit. The session-only model loses the choice when the browser closes or the session expires.

Keep content translation separate. The switcher localizes strings. For database content use spatie/laravel-translatable (or per-locale rows) and make sure both systems key off the same locale code and the same session key — otherwise you get a French UI showing German content.

Combine with URL strategies when SEO matters. The package's switch route is a POST/redirect-to-previous affair; it produces a session state change, not a crawlable URL. If you need shareable, indexable per-language URLs, build your own /{locale}/... route prefix and let the switcher only write the session as a fallback.

Restyle via view override. The dropdown is one Blade file. Publish the views, swap flags for emoji or a select component if you want, and don't fight the package's markup. On v7 the surrounding topbar/theme markup differs, so re-publish and diff rather than copying v6 overrides forward.

Gotchas and Tips

  • Locale codes must match exactly. pt_BR vs pt-BR vs pt-br is the single most common failure: App::setLocale('pt-BR') silently falls back when no matching lang/pt-BR directory exists, so the dropdown "works" but nothing changes. Normalize once, in one config key.
  • Version alignment is now the top risk. 2.1.0 = "Backpack v7 support." If the dropdown doesn't render or the middleware never runs after a v7 upgrade, check the installed addon version first (composer show backpack/language-switcher) before debugging your own config.
  • v7 config surface moved. Backpack 6 guidance about config/backpack/base.php and config/backpack/ui.php may not map 1:1 onto v7. Read the config files that actually exist in your app (php artisan vendor:publish again, or inspect vendor/backpack/.../config) instead of applying v6 instructions from blog posts and older READMEs.
  • Session dependence kills stateless paths. API routes, queue jobs, mail rendering, and crawlers won't see the choice — they'll use fallback_locale. Explicitly set the locale wherever you render mailables or notifications.
  • Middleware ordering. Anything that reads App::getLocale() at boot — menu builders registered in a service provider, View::share()'d labels, cached nav configs — runs before the switcher middleware. Build locale-dependent menus inside a middleware, or expect the first request after a switch to show stale labels.
  • config:cache and route:cache. Adding a locale to config without clearing the cache leaves the dropdown unchanged in production and is maddening to diagnose locally against a cached deployment.
  • Duplicated switcher. Older Backpack versions bundled a language switcher in core. Check before installing; two dropdowns is a surprisingly common bug report — and worth re-checking after a v7 jump, since core UI changed.
  • Missing translations aren't this package's fault. Backpack ships its own admin translations; if a panel label stays English after switching, the vendor lang file for your locale is incomplete — that's a backpack/* issue, not a switcher bug.
  • Open redirects. Redirecting to url()->previous() after a switch can bounce off-site if the referer is attacker-controlled. Compare against url('/') or use a named route.
  • Response caching. If you cache full responses by URL, you'll serve the wrong language. Vary on the session cookie or the locale cookie.
  • Testing. Don't simulate clicks; assert with $this->withSession(['locale' => 'es'])->get('/admin/dashboard') and $this->assertSame('es', app()->getLocale()). After the v7 bump, add one test that asserts the switcher dropdown markup is present in the topbar — that catches the "supported but silently not mounted" class of regression.
  • Extension points, ranked by cost: publish and edit the view → replace the middleware in config → write the 20 lines yourself. Given the package's size and low adoption, vendoring the concept is entirely reasonable; you're not losing an ecosystem by dropping it — and 2.1.0's single-purpose release (one integration PR) is a good reminder of how thin the wrapper really is.
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.
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
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle