laravel-lang/json-fallback-hotfix
Restore expected JSON translation fallback behavior in Laravel with this Laravel Lang hotfix. It ensures missing JSON keys resolve through your configured fallback locale instead of returning raw keys, helping multilingual apps stay consistent. Drop-in Composer package for affected Laravel versions.
Architecture fit. This is a narrow behavioral shim, not a platform component. It sits inside Laravel's translation layer and corrects JSON-string lookups so a missing key in the active locale resolves through fallback_locale instead of returning the raw key. Architecturally that means it patches adjacent to Illuminate\Translation\Translator rather than integrating with our domain code — no schema, no config contract, no events of its own. For a TPM the correct classification is defect-workaround dependency, temporary by definition, and it should be tracked with an owner and an exit condition, not absorbed into the platform baseline. Its value is that it removes the need for application-level workarounds we would otherwise build ourselves: a custom translator subclass, a __() wrapper with manual fallback, or duplicating every key across every lang/*.json file. That is real engineering cost avoided, but it is avoided by accepting a dependency on framework internals.
Integration feasibility. High. The description advertises a Composer-installable, no-configuration, no-database drop-in that is explicitly safe for existing lang/*.json files. Realistic effort is small — install, verify, and add a regression test — likely a day or two of engineering plus QA on the affected locales. The feasibility question is not "can we install it" but "does it reproduce the exact fallback semantics the product expects": per-key fallback on __()/Lang::get, interaction with Lang::has, replacement parameters, and pluralization/trans_choice edge cases. Those need to be proven against our own key inventory, not inferred from the README.
Technical risk. Moderate, and concentrated in four places.
[source] changes only — consistent with a composer.json constraint and CI matrix widening, i.e. zero runtime behavior change. That is good news for upgrade risk but tells us nothing about whether the patch still behaves correctly against Laravel 13 internals; a green suite after upgrading is not evidence of correctness here.composer.json — or, worse, upstream may change fallback semantics deliberately and the package starts fighting the framework. Either direction requires someone watching.Key questions.
translator, a subclass, or a middleware-level substitution — and is that override order deterministic relative to other localization packages?Lang::has, replacements, trans_choice, or nested/namespaced keys — or only the missing-key path?Stack fit. Strong for any Laravel application that ships lang/{locale}.json files and configures a fallback_locale. Weak-to-irrelevant for teams using PHP-array lang files exclusively, or translations served from a database/CMS. It is a fit for our localization workstream specifically, not a candidate for the shared platform standard — I would not recommend it to teams that don't have the problem.
Migration path. This is a Composer upgrade, not a data or code migration. The only migration worth planning is off our existing workarounds: if engineering has already built a custom translator, a fallback wrapper, or duplicated keys to work around the gap, sequence the package in first, verify parity, then delete the workaround one call-site at a time under test. Do the removal in a separate PR from the install so a rollback doesn't strand half-migrated code.
Compatibility. Require a documented matrix or CI evidence rather than assuming. Confirm the PHP floor alongside Laravel 13 — framework-support releases frequently ride with a runtime bump, and 2.3.0's notes don't mention one. Verify coexisting translation packages (laravel-lang's own commons, spatie/translatable, any custom Translator binding). Where we run multiple Laravel majors across services, we need a CI lane per major we claim to support, not one lane on the newest.
Sequencing.
Lang::has() check plus a route-level test rendering fallback-resolved copy — so the behavior is locked by our suite.^2.3 (not ^2.0) at install time so future resolutions don't land on a release that excludes our framework version.Maintenance. Low code footprint, but maintenance here means dependency governance, not engineering: pin the constraint, monitor releases, watch the Laravel changelog for a native fix, and re-verify after each framework upgrade. Assign an explicit owner. Because the package is a hotfix, put a sunset trigger in the backlog — an upstream Laravel fix, or an agreed review date — so it doesn't become unowned infrastructure that outlives its reason for existing. A one-paragraph ADR recording why it was installed and what removes it is the highest-leverage artifact here.
Support. Moderate and easily underestimated. Translation defects page the support desk before they page engineering, because they are customer-visible in non-English locales and look like content bugs. Support needs three facts in a runbook: the package exists, raw keys appearing in a locale is the signature of a regression here, and rollback is a single-version Composer revert. Without that, these incidents get misrouted to the localization/content team and burn days.
Scaling. Runtime impact should be neutral — an extra lookup only on the miss path; verify rather than assume, and confirm there is no per-request cost under a warm config cache. The operational scaling concern is Octane/long-running workers, where a rebinding performed at boot can behave differently from FPM, and content scaling (locale count, key counts) which is independent of this package.
Failure modes. Ranked by likelihood:
translator after this one, producing order-dependent behavior that differs by environment.Lang::has, replacements, or pluralization handled differently than the product assumes, so fallback "works" but renders wrong copy.Ramp-up. Low for engineers — installation and upgrade are ordinary Laravel package mechanics. The real ramp-up cost is institutional: knowing why the dependency is there and when it leaves. That is a documentation and ownership problem, not a training problem, and it is the single item most likely to be skipped and most likely to cause a future incident.
How can I help you explore Laravel packages today?