BazingaJsTranslationBundle: serving Symfony translations to JavaScript
A pretty nice way to expose your Symfony translation messages to your client applications.
At a glance
- What is it?
- BazingaJsTranslationBundle is a Symfony bundle that takes the translation catalogues your application already has and exposes them to client-side code, so a frontend can use the same message keys and plural rules as the backend. It suits a Symfony team that wants one source of truth for translations, and it is not a translation management system.
- Who is it for?
- BazingaJsTranslationBundle fits a Symfony application whose JavaScript layer needs the same message keys and plural forms as the server, since the bundle reuses the catalogues you already maintain instead of asking you to keep a second set in a frontend locale file. It is the wrong choice if your translations live somewhere other than Symfony's translator, and it is the wrong choice if you need a translation management workflow, since it does not provide one.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 3 days ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One catalogue, two consumers
BazingaJsTranslationBundle describes itself as a pretty nice way to expose your Symfony translation messages to your client applications.
The problem it solves is one every Symfony project with a JavaScript front end eventually runs into. Symfony's translator holds your messages as key/value pairs inside per-locale catalogue files, and the backend resolves a key at render time. The frontend has no access to that mechanism, so a team ends up with a second place to keep the same strings: a JavaScript locale file, a JSON file, a translation service. Then the two drift, a plural rule is wrong in one of them, and a key exists on one side and not the other.
This bundle's answer is to make the server the single source. The catalogues already in your application are read and made available to the client, so the same key that the Twig template resolves is the key the browser gets. The plural handling comes from Symfony's own translator rather than from a second implementation in JavaScript.
The scope is narrower than a translation platform. There is no editor interface, no workflow for sending strings to translators, no per-user locale management and no remote string store. It is a bridge between a translator you already have and a client that cannot reach it.
It is MIT licensed, written in PHP, and maintained by William DURAND as main author with Jan Sorgalla, Stan Chollet and Kamil Kaproń named as contributors.
How the repository is laid out, and what each piece does
The top-level listing describes the bundle's architecture fairly directly, and reading it tells you more than the readme does.
There is a Command/ directory, which is where the console commands live. There is a Controller/, which is the HTTP side: the route that serves the translations to the browser. A Dumper/ directory holds the component that renders a catalogue into the format the client receives, and a Finder/ directory holds the component that locates the translation files in the first place, which is the part that has to cope with different bundles and projects putting their catalogues in different places.
The DependencyInjection/ directory is the Symfony integration: the bundle extension and the configuration that turns the bundle's options into services. There is Resources/, which contains the views and the documentation, and the documentation entry point named in the readme is Resources/doc/index.md.
Two top-level files are worth calling out. BazingaJsTranslationBundle.php is the bundle class itself, the object Symfony registers. Util.php sits alongside it as shared helper code. There is also an UPGRADE.md at the root, which tells you what changed between major versions, and CONTRIBUTING.md for the contribution process.
The separation of Finder, Dumper and Controller is the design decision worth understanding. Finding the catalogue files, converting them and serving them are three separate concerns with three separate failure modes. A bundle that did all three in one class would be harder to extend: a user with a non-standard catalogue layout would have to replace the whole pipeline rather than just the piece that is wrong. Splitting them means each can be swapped, and it is also why the bundle can support several Symfony versions at once without forking.
The version matrix, and what it tells you about maintenance
The requirements section is unusually precise, and it reads like a project that takes compatibility seriously.
PHP 8.2 or higher and Symfony 6.4 or higher are required, within the 6.x, 7.x or 8.x lines. The readme states directly that projects on older PHP or Symfony versions must upgrade before installing the next release of this bundle. That is a hard boundary rather than a soft preference, and it means the bundle is not installable in a legacy application without a platform upgrade first.
The CI matrix is narrower still. It explicitly tests Symfony 6.4 and 7.4 on PHP 8.2 through 8.5, and Symfony 8.1 on PHP 8.4 through 8.5. The readme explains why the Symfony 8.1 row is narrower: Symfony 8.1 requires PHP 8.4 or higher, even though the bundle's own minimum PHP version remains 8.2.
That distinction matters more than it looks. It means the bundle's floor is set by its own code, while the effective floor in a given environment is set by whichever Symfony version you run. A team on Symfony 8 is on PHP 8.4 whatever the bundle says, and a team that reads the bundle's 8.2 requirement and pins PHP 8.2 will find that Symfony 8 will not install.
The release history shows a major version per Symfony major version: 6.1.0 in August 2024 with the note that it addressed a polyfill.io vulnerability, 7.0.0 in February 2025 for Symfony 7 support, and 8.0.0 in February 2026 for Symfony 8 support. That is a predictable upgrade cadence, one major per year tracking the platform, and it tells you what to expect when the next Symfony release lands.
Getting it into a Symfony application
The readme points at the documentation rather than repeating the setup, and the documentation lives in Resources/doc/index.md inside the repository. It also links the rendered version of that file on GitHub.
What the readme does state is the distribution channel. The badge links to the Packagist page for the package, and the package name is willdurand/js-translation-bundle, which is the Composer name rather than the repository name. That difference matters when you search: the GitHub repository is BazingaJsTranslationBundle and the Composer package is js-translation-bundle.
So the install step is a Composer requirement in your application, and the bundle is then registered in the standard Symfony way, after which its configuration is set in the application configuration under the bundle's own configuration key. The readme does not reproduce the configuration keys or the route attributes, and those details live in Resources/doc/index.md, so the exact option names should be taken from the documentation rather than guessed.
There is a CI badge in the readme pointing at the run-tests workflow, and the repository carries a phpunit.xml.dist at the root, so the test suite runs under PHPUnit with the usual dist configuration for a bundle that is developed outside an application.
The documentation being in the repository rather than on a separate site is a deliberate choice and it has a practical benefit for a bundle at version 8: the docs are read alongside the code at the tag you are actually installing, so an upgrade that changes configuration comes with the matching documentation in the same checkout.
Where BazingaJsTranslationBundle is the wrong tool
The first limitation is that it does nothing for you if your translations are not in Symfony. The bundle reads the catalogues that the Symfony translator uses. A team running Symfony for the API and a separate front end with its own i18n setup, or a team whose strings live in a SaaS translation platform, gets nothing useful from it, because there is no catalogue for it to find.
The second is that it is not a translation management tool, and the gap is worth stating precisely. There is no interface for non-technical people to edit strings, no per-locale workflow, no way to track which strings have been translated for which locale, and no mechanism to know that a key used by the backend is missing in a locale. If your bottleneck is people who do not read code editing a catalogue, this bundle does not address it at all.
The third is the version constraint interacting with your platform. Requiring PHP 8.2 and Symfony 6.4 means the bundle cannot be adopted in a project that still has to run an older stack, and the readme says outright that such projects must upgrade first. For a large application, that upgrade is the real cost of adoption and it dwarfs the bundle itself.
The fourth is that the catalogue still has to reach the client somehow. The bundle exposes messages to client applications, and a client application needs to fetch them, which means there is a network request, a cache decision and a decision about which locale to send. The readme does not document caching headers or the refresh behaviour when a message changes in development, so those details come from the documentation and from the choices you make, not from the bundle.
The fifth is the timing of the release line. 8.0.0 came out on 2026-02-24 and the last push was on 2026-10-19, so there is a substantial gap between the newest major and the most recent work. That is a normal pattern for a bundle that only needs a change when Symfony does, but it does mean an 8.0.0 install does not include the most recent commits.
Editorial conclusion
BazingaJsTranslationBundle fits a Symfony application whose JavaScript layer needs the same message keys and plural forms as the server, since the bundle reuses the catalogues you already maintain instead of asking you to keep a second set in a frontend locale file. It is the wrong choice if your translations live somewhere other than Symfony's translator, and it is the wrong choice if you need a translation management workflow, since it does not provide one. Before adopting it, read Resources/doc/index.md for the current configuration, check the UPGRADE.md file when moving between major versions, and note that the last push was on 2026-10-19 with 8.0.0, the Symfony 8 release, published on 2026-02-24.
Frequently asked questions
What does BazingaJsTranslationBundle do?
It is a Symfony bundle that exposes your Symfony translation messages to your client applications, so JavaScript code can use the same message keys and plural rules as the server side instead of keeping a second set of strings in the front end.
How do I install BazingaJsTranslationBundle?
The Composer package is willdurand/js-translation-bundle, listed on Packagist. Install it with Composer, register the bundle in your Symfony application and set its configuration; the readme points at Resources/doc/index.md in the repository for the configuration keys and the route setup.
What are the requirements for BazingaJsTranslationBundle?
PHP 8.2 or higher and Symfony 6.4 or higher, within the 6.x, 7.x or 8.x lines. CI tests Symfony 6.4 and 7.4 on PHP 8.2 through 8.5 and Symfony 8.1 on PHP 8.4 through 8.5, because Symfony 8.1 itself requires PHP 8.4.
How is BazingaJsTranslationBundle structured?
The repository has a Command/ directory for console commands, a Controller/ for the route that serves the translations, a Dumper/ for rendering a catalogue into the client format, a Finder/ for locating translation files, and DependencyInjection/ for the Symfony integration. The bundle class is BazingaJsTranslationBundle.php and shared helpers live in Util.php.
What licence is BazingaJsTranslationBundle released under?
MIT, with the complete licence text in the LICENSE file inside the bundle. The last push was on 2026-10-19 and the newest release is 8.0.0 from 2026-02-24, which added Symfony 8 support.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/willdurand-bazingajstranslationbundle)Was this useful?