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

Locale Bundle Laravel Package

forci/locale-bundle

forci/locale-bundle is a PHP locale management bundle for multilingual applications. It provides locale configuration and detection utilities to help route users to the right language and integrate localized content, making it easier to build and maintain localized experiences.

View on GitHub
Deep Wiki
Context7

Getting Started

What you're actually holding: forci/locale-bundle is a Symfony bundle (Symfony 3/4 era), not a Laravel package. There is no service provider, no config/locale.php, and no facades. If you're on Laravel, the correct first step is not composer require — it's git clone and read it as a reference implementation. Its value to a Laravel developer is as a ~200-line spec for locale negotiation and fallback; its value as a dependency is close to zero.

If you're on Symfony (the only case where this installs cleanly): add the bundle to config/bundles.php, import its YAML config, and point your framework.default_locale and translator.fallbacks at it. The bundle wires a locale resolver and a request listener; you interact with it via the injected locale service and the translator, not a facade.

Where to look first, in order:

  1. The DI extension class — it tells you exactly which services get registered and under what IDs.
  2. The request listener / LocaleListener integration — this is the real behavior: how the locale is picked from route, then query, then Accept-Language, then default.
  3. The config schema — the only knob surface, and the fastest way to see what the package actually supports vs. what the README implies.

First use case to validate: a request to /fr/products with Accept-Language: de-DE,de;q=0.9 and no ?locale= query. Confirm the resulting Request::getLocale() is fr (route wins), not de (header). If that ordering doesn't match your product requirement, the bundle's opinion is wrong for you and you're better off writing the middleware yourself.

Implementation Patterns

Pattern 1 — Symfony native usage. Inject the bundle's locale service, read the resolved locale, and pass it to Translator::setLocale(). The bundle expects Symfony's LocaleListener to run after it; don't fight that ordering. Config lives in one YAML file with default + fallback locale and a priority list of detection sources.

Pattern 2 — the Laravel port (recommended). The bundle's real logic collapses to a SetLocale middleware:

public function handle($request, Closure $next) {
    $locale = $request->route('locale')
        ?? $request->query('locale')
        ?? $request->getPreferredLanguage(config('app.locales'))
        ?? config('app.fallback_locale');
    App::setLocale($locale);
    return $next($request);
}

$request->getPreferredLanguage() is native and handles Accept-Language q-values correctly — you don't need the bundle for the hardest-looking part. Register the middleware globally (before SubstituteBindings) and you have parity with the bundle's feature set in under two hours.

Pattern 3 — locale-prefixed routing. In Laravel, wrap your frontend routes in Route::prefix('{locale}')->middleware(SetLocale::class)->group(...) and add a Route::pattern('locale', 'en|fr|de|pt-BR') constraint to prevent unmatched paths from reaching the middleware. This is roughly what the bundle does in Symfony with route defaults, but Laravel's route model gives you more explicit control.

Pattern 4 — persistence. Session first (session(['locale' => $locale])), cookie second, header last. Pick an order and document it — the bundle encodes one; you should encode yours explicitly rather than inheriting an undocumented one.

Pattern 5 — if you need more than the simple case. Reach for mcamara/laravel-localization (MIT, actively maintained, real adoption). It covers URL prefixes, hreflang, and the switcher endpoint. Do not bridge this bundle through a service provider to get the same result — you inherit a Symfony constraint pin and zero upstream support.

Testing pattern worth copying: a data-provider matrix of [route locale, query locale, Accept-Language, session, expected] covering regional variants (pt-BR vs pt), an RTL locale (ar, he), an unsupported locale in the header, and a missing translation key. The bundle likely ships something similar; if not, it's the first thing to add to your port.

Gotchas and Tips

  • License is NOASSERTION. This is a stop-ship, not a nitpick. GitHub could not identify an OSI license, which means there may be no grant of commercial use at all. Escalate to legal before any line lands in a repo. If legal clears it, you still own the fork forever.
  • The bundle contract is dead code in Laravel. There is no Kernel::registerBundles() in Laravel, no DI extension auto-loading, no compiler-pass pipeline. Any class extending Symfony\Component\HttpKernel\Bundle\Bundle will never execute. Only plain service classes and value objects are portable — and for this package, that's the minority of the lines.
  • Symfony version drift will bite you. A Symfony 3.4/4.x bundle pins symfony/framework-bundle in ^3|^4; Laravel 10/11 ships Symfony 6/7 components. composer require will fail resolution or force a replace hack that destabilizes every other symfony/* constraint. Check composer.json before spending any time on a bridge; if it references symfony/symfony (the monolith), walk away — it conflicts with Laravel's per-component requirements outright.
  • Silent fallback is the classic defect. When the header is malformed or no locale matches, most implementations drop to the default with no log line. Instrument the fallback path with a counter or log — otherwise a language regression surfaces first as a support ticket from a French user reading English.
  • Cache poisoning. If the locale is derived from a cookie or session, any response cache (Laravel's Cache-Control, a CDN, spatie/laravel-responsecache) must vary on it. Set Vary: Accept-Language and exclude locale-sensitive routes from the cache. This is the single most common production failure in locale middleware and is harder to audit when the logic is behind a third-party bundle.
  • Route generation mismatch. URLs generated for emails, redirects, and sitemaps must include the locale prefix. Write a test that asserts route('products.index', ['locale' => 'fr']) produces /fr/products and not /products. This breaks silently in Laravel because route() helpers don't fail on missing optional segments.
  • Session/cookie desync. If the locale is set in the session on one device and from a cookie on another, users see inconsistent languages. Define a hard resolution order (route → session → cookie → header → default) and put it in the middleware and the test matrix.
  • Regional variants need explicit handling. pt-BR vs pt vs pt-PT: decide whether pt-BR falls back to pt or to the default. The bundle's fallback chain is one opinion; Laravel's lang/{locale}/ directory structure is another. Test both directions.
  • No upstream, no fallback. 1 star, 0 dependents, no release history. Assume zero responsiveness to issues or security reports. If you vendor it, you own the tail of every PHP and framework upgrade forever — weighed against a one-to-two-day native implementation, the math doesn't close.
  • Extension point worth knowing: if you do read it, the useful export isn't the bundle class — it's the negotiation ordering and fallback chain encoded in the listener. Copy that logic, not the code.
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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin