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

Filament Language Switcher Laravel Package

tomatophp/filament-language-switcher

A configurable language switcher for Filament panels that lets users change the app locale from the topbar or user menu. Supports custom language lists, flags, RTL layouts, and simple Laravel localization integration.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. The package is a thin, well-bounded surface: a Filament panel plugin that renders a header dropdown, a single config file as the locale allowlist, one nullable column on the users table, and a switch route that persists the signed-in user's preference. Architecturally it is a passenger, not a platform — it swaps Laravel's string locale and nothing else. It does not do tenant locale, session locale, Accept-Language/geo negotiation, content translation, or RTL layout direction. As a TPM, scope it as admin-panel infrastructure and explicitly rule those adjacent concerns out of the ticket, or the "small language switcher" work item will silently absorb a localization subsystem.

Integration feasibility. High, provided the stack gate is cleared. Install is composer require tomatophp/filament-language-switcher:^5.0, one artisan install command, and a ->plugin(...) call in the panel provider — realistically a half-day for a competent Laravel dev including reading the source end to end. The real feasibility question is not effort, it is the hard dependency: v5 requires Filament v5, Livewire 4, Laravel 12/13, and PHP 8.2+. If the admin panel is not on Filament 5, this package cannot be adopted as-is.

Technical risk. Three items belong on the risk register with owners and dates:

  1. Pre-v5 security finding. Releases before v5.0.0 instantiated any class named in the request and allowed one user to change another user's language. Any pre-v5 copy in production is an open finding, not a backlog item. The v5 fix — self-only switching, 403 for guests, unconfigured locales rejected, model/model_id ignored — is the headline reason to move.
  2. The 4.x branch is unconfirmed. Release notes state v4 code is preserved there; they do not state the security fix was backported. Until that is confirmed in writing, "we'll stay on Filament v4 and keep the old branch" is a documented risk acceptance requiring named sign-off, not a default.
  3. Bus factor. 37 stars, zero dependents, MIT, effectively a single maintainer. External validation is thin. The counterweight is genuine — a new test suite with coverage, screenshots, and an active hardening release — but budget for the possibility of forking. Keeping the integration thin (one column, one config file, no custom logic layered inside) is what makes that budget small.

Key questions to close before sign-off.

  • Is the admin panel on Filament 5 / Livewire 4 / Laravel 12+ / PHP 8.2+, or is that migration independently funded and dated?
  • Has anyone confirmed in writing whether the v5 security fix exists on 4.x?
  • Does the user model use the default language column on users, or will we need an override? (Confirm in a test right after install, before anything is built on top.)
  • Is locale a per-user preference by product intent? If the answer is per-tenant or per-session, this package is the wrong tool and no amount of customization makes it the right one.
  • Which panels get the switcher? Admin only, or also customer-facing? Adding it to a customer panel converts an internal preference into a customer-visible toggle.

Integration Approach

Stack fit. Adopt only on the far side of the Filament 5 / Livewire 4 / Laravel 12 upgrade. Pin the constraint to ^5.0 rather than a floating range — the meaningful change in this package is a security change, and a routine composer update should not get to decide when you cross that line. Treat the pin as a one-line product guardrail protecting against an unplanned replatform.

Migration path. Three tracks, chosen deliberately rather than by default:

  • Already on Filament 5 (or upgrading now): add the package as a rider on that migration. Lowest total cost.
  • On Filament v4 with the upgrade funded this quarter or next: schedule the switcher immediately after the upgrade lands, not before, and not as a blocker for it.
  • Intentionally staying on Filament v4 for a quarter or more: the package no longer tracks that path by default. Log the pre-v5 exposure as a security finding, get explicit written sign-off on the 4.x branch's patch status, and accept that you may be maintaining a fork.

Compatibility and pre-upgrade audit. Before or during cutover, deliberately hunt for pre-v5 habits: guest-facing switch links, generated URLs carrying model/model_id, bookmarks and dashboards that rely on one user changing another's language. The fix makes those flows stop working — correctly — and the difference between "found in an audit" and "found in a bug report" is a support incident. Also confirm the published migration's column name, type, and nullability against the actual user model; a non-default column name is the single most likely reason to read the source or override.

Sequencing.

  1. Confirm stack gate and secure written confirmation on 4.x patch status.
  2. Pin ^5.0, install, publish config, read the migration.
  3. Decide the apply-on-request strategy — if the package ships no middleware, add one that resolves the user's stored locale, validates it against the config allowlist, and falls back to app.locale. Without that guard, a stale row written before a config change bypasses the route-level rejection.
  4. Register the plugin per panel, admin first.
  5. Land the four security regression tests (guest 403, target-user ignored, unconfigured locale rejected, null-locale fallback) in CI alongside the install PR, not after.
  6. Run the install command locally only. In a deploy pipeline, publish and let your normal php artisan migrate be its own observable step — the install command runs migrations in-process, which is convenient on a laptop and opaque in CI.
  7. Defer RTL layout direction to a separate ticket driven from the resolved locale in the blade layout. The package switches strings; it does not flip direction.

Operational Impact

Maintenance. Day-to-day work is 90% config: the locale array, translated display names, and show_flags. That is a good place to be — a non-engineer-adjacent change touching one file. Two standing obligations: refresh config:cache whenever the locale array changes, and periodically re-check the upstream repo. With one maintainer and zero dependents, assign a named internal owner for the integration and a lightweight quarterly review of upstream releases. Keep the integration thin so that taking ownership later is a fork of a dropdown, not of a subsystem.

Support. Expect the support queue to be config drift, not defects. Document a fixed debug order for on-call: route:list (route name and middleware) → distinguish 403 from 302 (403 means middleware is working; 302 means the user isn't authenticated, which is a different bug entirely) → check the user row → check the config array. Most tickets resolve there. Also publish the allowlist semantics plainly: a locale present in lang/ but absent from the config is not switchable by design, and support will otherwise field "the translation exists but nobody can pick it" as a bug.

Scaling. Negligible on the hot path — one column read per request and a dropdown render. The scaling risk is process state, not load. Under Octane or long-lived queue workers, locale is per-process; set it per request or job and reset at the boundary, or one user's language leaks into the next request. Any per-user caching keyed on rendered output must include locale. Do not build tenant, session, or Accept-Language negotiation inside this package — add those alongside if the roadmap calls for them.

Failure modes.

  • Unsupported combination: v5 on a Filament v4 app. Mitigated by the version pin and the stack gate.
  • Silent regression to old behavior: pre-v5 switch links or generated URLs quietly breaking after upgrade. Mitigated by the audit and the CI tests.
  • Stale stored locale: a row holding a value no longer in the config. Mitigated by the middleware fallback and by preferring null over backfilling — null keeps the app.locale fallback live, so a future APP_LOCALE change propagates to users who never chose.
  • Rendering without behavior: v5 fixed the switcher disappearing when the current locale isn't configured, but "renders" is not "behaves." Normalize the resolved locale to a configured value in middleware.
  • Cosmetic-only affordance: with show_flags on, a missing flag leaves a visible gap. Verify the switcher with flags both on and off and make sure a label, not a flag, is the primary affordance.
  • Unmaintained upstream: single maintainer walks away. Mitigated by the thin integration and a fork budget.

Ramp-up. Essentially zero for anyone who knows Filament panel providers — the source is readable end to end in about ten minutes, and there is nothing to learn beyond one config file and one column. Plan two onboarding artifacts rather than training: a short README section covering the config allowlist, the fallback middleware, and the pin, plus the security test suite as living documentation of intended behavior. The real ramp-up cost is the Filament 5 migration underneath it, which is a separate and much larger program.

Where it earns its keep operationally. Localization QA and demos: a reviewer flips language in the topbar and validates translations on their own account — no shared demo user, no "changed the locale for everyone" incident, no juggling test accounts. That is a genuine, recurring saving, and it is the strongest operational argument for adopting rather than hand-rolling.

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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource