hardchor/expose-translation-bundle
A small Symfony bundle that exposes your application's translation catalogs—useful for making message strings available to frontend JavaScript or external clients. Lightly adopted, so review the source for supported formats, routes, and integration details before relying on it in production.
What this package actually is. hardchor/expose-translation-bundle is a Symfony bundle, not a Laravel package. It is a fork of willdurand/expose-translation-bundle (later BazingaExposeTranslationBundle), which registers a route that dumps the Symfony Translator's message catalogues into a JavaScript global (Translator) so templates can call Translator.trans('key'). It depends on symfony/http-kernel, symfony/routing, symfony/dependency-injection, and symfony/translation, and bootstraps through a Symfony Kernel + Bundle registration. That distinction is the single most important finding for this evaluation.
Architecture fit. Effectively zero for a Laravel codebase. Laravel's translation layer (Illuminate\Translation\Translator, lang/*.php, __()), routing, config publishing, and service-provider lifecycle are structurally different from Symfony's bundle contract. There is no ServiceProvider, no config/expose_translation.php, no vendor:publish path, and no facades. The concept (serialize server-side catalogues for the front end) translates cleanly; the code does not.
Integration feasibility. Low. Pulling the bundle into a Laravel app is technically possible on the dependency axis — Laravel already ships several Symfony components — but the package expects a Symfony kernel to register the bundle and compile its container extension. Adapting it means writing a Laravel service provider wrapper around the bundle's controller and duplicating the container-extension logic. A realistic estimate is 5–10 engineer-days for an initial port plus permanent fork ownership, to arrive at functionality that already exists as a maintained, first-class Laravel solution.
Technical risk. High, and concentrated in maintenance rather than runtime:
| Risk | Assessment |
|---|---|
| Upstream vitality | Fork with 1 star, 0 dependents; parent repo archived and superseded by Symfony UX / symfony/translation tooling |
| PHP/Laravel version coverage | No evidence of PHP 8.2/8.3 or Laravel 10/11 compatibility; likely dev-master only |
| Security response | No advisory channel, no CVE process, single unnamed maintainer — unacceptable for code on a request-serving route |
| Fork divergence | No clear delta from parent; provenance and patch history unverifiable |
| Bus factor | 1 |
Key questions for the requester.
symfony/ux-translator or the maintained upstream?Recommendation. Do not adopt. Reimplement the capability natively; treat this repository as a design reference only.
Stack fit. The idiomatic Laravel equivalents cover the same ground with maintained dependencies:
laravel-vue-i18n — compiles lang/ into front-end bundles via Vite; best fit for Vue + Inertia or Vite SPAs.spatie/laravel-js-translations — generates JS translation objects and a Blade directive; closest conceptual match to this bundle.@json — a ~30-line controller returning __('messages') for a locale, cached and CDN-fronted. Adequate for small catalogues.symfony/ux-translator — only if the stack is genuinely Symfony.For most Laravel apps the first two are the correct answer; the decision hinges on build-time vs. runtime delivery.
Migration path. Port the contract, not the code. Concretely:
trans(key, params, domain, locale) semantics — so existing front-end call sites keep working.| pluralization, %param% placeholders) onto Laravel's (lang/{locale}/{file}.php, :param placeholders, trans_choice). These are not identical — pluralization rules and placeholder syntax differ, so a mechanical swap will silently break strings.Compatibility. Pin nothing until a spike confirms: PHP version floor, whether the bundle even installs against Laravel's pinned Symfony component major versions, and whether symfony/dependency-injection version constraints conflict with the Laravel framework's own. Expect a conflict; resolve by abandoning the bundle rather than downgrading framework components.
Sequencing.
Maintenance. Adoption means permanent fork ownership: security patching, PHP major upgrades, and Symfony component drift, all against a 1-star upstream that will not move. Budget ongoing maintenance, not a one-time integration.
Support. No vendor, no SLA, no issue triage, no CVE feed. Any production incident traced to this code is resolved entirely in-house, including the case where a framework upgrade breaks it mid-cycle.
Scaling. The runtime model is an HTTP route that serializes the full catalogue per request. Without caching this is a per-request CPU and payload cost on every page load — tolerable at low volume, wasteful at scale, and a thundering-herd risk on cold caches. Mitigations: Cache-Control: public, max-age, ETag on catalogue hash, CDN offload, or eliminate the endpoint entirely by emitting JSON at build time. For a Laravel app, build-time emission is strictly better and removes the route from the attack surface.
Failure modes.
| Mode | Symptom | Detection |
|---|---|---|
| Domain/locale not found | Empty translator object; raw keys (messages.welcome) render in UI |
Key-existence contract test in CI |
| Placeholder syntax mismatch | :name or %name% left uninterpolated in output |
Snapshot tests on rendered strings |
| Route unreachable / 500 | Translator global undefined; JS throws on first trans() call |
Front-end error budget; synthetic check |
| Stale catalogue after deploy | Users see previous release's strings | Cache-busting key tied to build hash |
| Unescaped catalogue output | XSS if translations are user-editable | Output encoding review; CSP |
Global Translator collision |
Shadowed by another library; silent wrong-behaviour | Namespace the global on reimplementation |
Ramp-up. An engineer unfamiliar with Symfony bundles needs 1–2 days to understand the container extension and route registration — time spent understanding code that will be discarded. For the concept, ramp-up is near zero; for the package, the learning investment has negative return.
Bottom line for planning. The opportunity score of 30.35 overstates readiness: with 1 star, 0 dependents, and a package score of 0.005, this is an abandoned fork on the wrong framework. The correct TPM decision is to close the integration ticket, log the underlying need (front-end access to translation catalogues), and route it to a maintained Laravel-native solution with a CI contract test. Expected delivery: 2–3 engineer-days, versus 5–10 plus indefinite ownership for the port.
How can I help you explore Laravel packages today?