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.
/fr/, /de-de/), and fallback behavior determine how cheaply a new language becomes a new market. This package is only relevant insofar as it shortens that plumbing, and it doesn't shorten it much.Accept-Language-driven default with manual override, or an explicit picker only. Any locale layer encodes one opinion on that UX — a product decision, not just a technical one.App::setLocale(), lang/ files, __(), and Request::getPreferredLanguage() already first-party. This sits in "too small to buy, too trivial to depend on" territory — worth recording as a decision so it stops resurfacing in backlog grooming.Consider it as a reference implementation to read, not a dependency to install:
-bundle suffix and Forci's origins point there) auditing locale bundles — though symfony/translation plus a LocaleListener already covers this.Look elsewhere — or write it yourself — when:
NOASSERTION: GitHub could not identify a recognized OSI license. That is a legal stop-ship item for a commercial product, not a nitpick. There may be no grant of rights at all.Kernel::registerBundles(), no DI extension auto-loading, no compiler passes. Bundle plumbing is dead code here; only plain service classes port, and you'd rebind them manually in a ServiceProvider. Meanwhile a Symfony 3.4/4.x constraint set won't resolve against Laravel 10/11's Symfony 6/7 components.mcamara/laravel-localization covers locale-prefixed routing far more completely, with real adoption, active maintenance, and a clear MIT license. That's the correct answer if you need more than the basics.To executives: This is a small, unmaintained third-party component for locale routing, and it's built for Symfony rather than our Laravel stack. Its license is unidentified, which means we cannot legally ship it without review. Recommendation: do not adopt. The capability is a few days of our own work — a middleware, a route prefix, and session persistence — and building it removes both the legal question and the abandonment risk. It has no bearing on our localization budget, which is dominated by translation and content, not routing.
To engineering: Treat forci/locale-bundle as a design reference, not a dependency. Read it for conventions on locale negotiation and fallback, then implement locale-aware middleware in-house (~1–2 engineer-days) using App::setLocale(), Request::getPreferredLanguage(), route ->prefix('{locale}'), and session persistence. Zero dependency risk, tests under our control. A bridge is technically possible — register only the portable service classes, ignore the bundle class, pin the transitive Symfony constraints — but it buys a permanent maintenance liability for a few hundred lines. The 1-star / 0-dependent profile and NOASSERTION license disqualify it from production regardless of code quality; if someone wants to vendor specific logic, flag it to legal for a license determination before any code lands in the repo.
Failure modes to design against in whatever we build: silent locale fallback (unmatched Accept-Language dropping to default with no log line — instrument it), cache poisoning (locale varies by session/cookie, so set Vary: Accept-Language or exclude the route from cache), locale-prefixed URL generation mismatches in emails and sitemaps, raw translation keys surfacing once a partially translated locale is enabled, and session/cookie desync from an undefined resolution order. These are implementation-independent, but easier to verify in code we own.
Sequencing: Week 0 — license gate (legal) and a half-day source audit if anyone insists on evaluating further. Week 1 — decision checkpoint, defaulting to native over bridge. Week 1–2 — implement and test, including regional variants (pt-BR vs pt), RTL locales, and missing-translation fallback. Week 2 — record the decision and the rejected dependency so the next engineer doesn't rediscover this package.
How can I help you explore Laravel packages today?