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

Servergrovelocalebundle Laravel Package

servergrove/servergrovelocalebundle

ServerGroveLocaleBundle is a Symfony/PHP bundle for detecting, storing, and switching user locales. It helps localize routes and responses using browser preferences, session, and URL parameters, with simple configuration for multilingual applications.

View on GitHub
Deep Wiki
Context7

Getting Started

This package is a Symfony bundle (not Laravel) that auto-detects a visitor's preferred locale from the Accept-Language header (optionally falling back to GeoIP) and stores it in the session so the choice persists across requests. If you're coming from Laravel, mentally map it to a middleware that runs on every request and sets App::setLocale() — the concept is identical, only the wiring differs.

Minimal setup:

  1. Install via Composer

    composer require servergrove/servergrove-locale-bundle
    
  2. Register the bundle in app/AppKernel.php (Symfony 2/3) or config/bundles.php (Symfony 4+):

    new ServerGrove\Bundle\LocaleBundle\ServerGroveLocaleBundle(),
    
  3. Configure it — the absolute minimum is declaring which locales you support:

    # config.yml
    server_grove_locale:
        locales: [en, es, pt_BR, fr]
        default_locale: en
    
  4. First use case: a multi-language marketing site where you want the first hit to respect the browser language rather than forcing a redirect splash page. Point your translator locale at whatever the listener sticks in the session, and every subsequent request stays in the user's chosen language.

Where to look first: the bundle's LocaleListener (registered on kernel.request) is the heart of it — read that class before anything else. Everything else is config and session wiring.

Implementation Patterns

Trust the session, fall back to headers. The canonical pattern is: on each request, check the session for an existing _locale; if present, honor it. Otherwise parse Accept-Language, match against your configured locales, and persist the winner. This gives you "detect once, respect forever" — the behavior users expect. The bundle does this automatically once configured.

GeoIP as a secondary signal. When accepting Accept-Language is unreliable (shared kiosks, VPNs, mis-set OS language), enable the GeoIP fallback. You'll need either the PECL geoip extension or a MaxMind database file, and you'll configure the path/provider in the bundle config. Order of precedence is typically: session → Accept-Language → GeoIP → default.

Language switcher integration. Expose a controller action that writes the chosen locale into the session under the same key the bundle reads, then redirects back. Because the listener short-circuits when a session value exists, this gives you a clean manual override that survives navigation without fighting the auto-detection.

// Manual override endpoint
public function switchAction(Request $request, $locale)
{
    $request->getSession()->set('_locale', $locale);
    return $this->redirect($request->headers->get('referer'));
}

Wire it into routing. Set _locale as a route requirement/default so generated URLs and the translator agree with the session value:

contact:
    path: /{_locale}/contact
    defaults: { _locale: en }
    requirements: { _locale: en|es|pt_BR|fr }

Testing pattern. Because the listener keys off Accept-Language and the session, functional tests should craft requests with explicit HTTP_ACCEPT_LANGUAGE headers and assert on the resulting _locale — don't rely on ambient defaults.

Gotchas and Tips

This is Symfony-only. Don't try to drop it into a Laravel app. If you're genuinely on Laravel, you'll replicate the idea with a middleware plus a small locale-parsing package — the value here is the reference implementation, not drop-in code.

Abandoned / low maintenance. 13 stars and no recent activity means: pin the version, vendor it, and expect to maintain it yourself. Audit the Accept-Language parsing — naive explode(',') handling is a common bug in older bundles and will mis-rank locales with quality values (q=0.8).

Session ordering matters. The listener must run after the session is started. If you see "session not started" errors, confirm your framework.session config and that the listener priority is sane — a lower priority than the session listener.

locales must exactly match your translation/route locales. A typo like pt_BR vs pt-BR (hyphen vs underscore) silently breaks matching and every request falls back to default. Log the detected locale during bring-up to catch this.

GeoIP extension is optional but easy to misconfigure. If you enable GeoIP without the PECL extension installed or without a valid database path, some versions throw instead of gracefully falling back. Test with the feature both on and off, and keep the default-locale fallback as a hard safety net.

Caching gotcha. If you put pages behind a full-page HTTP cache, the _locale-dependent Vary header must include Accept-Language, or the first visitor's language gets cached for everyone.

Extension points. Subclass or decorate the listener if you need custom precedence (e.g., a user-profile locale beating the session), and override the session key if it collides with your own _locale handling. The bundle is small enough that forking a single class is a reasonable escape hatch.

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.
unabomber/timezone
delatbabel/contacts
astritzeqiri/g-recaptcha
kevinongko/laravel-genode
developeruz/laravel-analytics
robbiep/afterthedeadline
frankkessler/incontact-laravel-oauth2-rest
jlxh/laravel-userlog
davidmgilo/timetables
qylinfly/role-permission
reflect-digital/conduit
takashato/laravel-vietqr
aitor24/laralang
kraenzle-ritter/entity-relations
dindigital/din-image
pomirleanu/image-colors
sawmainek/laravel-api-generator
delatbabel/jsonresponses
mouhamedfd/permissions-generator
eduplus/qr