incenteev/translation-checker-bundle
Symfony bundle that keeps translations in sync across locales. It scans templates and code to flag missing, unused, and inconsistent messages, works with XLIFF and YAML catalogs, and adds a command you can run in CI to catch translation regressions early.
Architecture fit. Unchanged by v1.10.0. This is a Symfony bundle, not a Laravel package — still the single most important fact for the decision. It ships a Symfony Console command (translation:check) plus a DI extension registered through the bundle system, and its extraction logic targets Twig templates and Symfony's translator service. Laravel has no bundle registry, a different container, and Blade instead of Twig. As-is, it will not boot in a Laravel application. The reusable asset remains the idea and the comparison engine (key set diffing, unused-key detection), not the integration surface. Critically, v1.10.0 contains no feature work — it is a pure compatibility release — so no part of this assessment's integration analysis improves.
Integration feasibility. Three viable paths, in ascending cost, unchanged in ranking:
artisan translations:audit command — reimplement extraction for __(), @lang, trans(), trans_choice(), Blade directives, and JS-side keys. Moderate effort, permanent ownership. Marginally improved by v1.10.0: the fork base is now on PHP ≥8.2 / Symfony ≥6.4, which aligns with Laravel 11/12 runtimes and avoids back-porting legacy shims.lang/ files directly. This path gets slightly riskier, not easier: the package is being actively retargeted at modern Symfony DI/Config APIs, so its internals drift further from anything embeddable outside a Symfony kernel.Technical risk.
stof (Christophe Coevoet), a long-standing Symfony core contributor, and adds Symfony 8 forward-compatibility alongside a deliberate floor bump to PHP 8.2 / Symfony 6.4. This is the behaviour of a maintained package, not an abandoned one. Revise the prior "weak maintenance signal" conclusion accordingly.__("errors.$code")) are inherent to static extraction and will erode trust in the CI gate if not triaged. No extraction changes in this release.Key questions for the team.
Stack fit. Poor out of the box, workable with adaptation — unchanged. Laravel's translation layer (lang/ PHP or JSON files, Translator contract, __() helpers) is conceptually similar but structurally distinct from Symfony's translations/ YAML/XLIFF plus Twig |trans filters. Expect to rewrite the extractor and the file-format readers; the diff algorithm is the only near-drop-in piece. v1.10.0 touches none of that.
Migration path. Do not schedule this as an integration task. Schedule it as a two-day spike: install the package in a throwaway branch, run the checker against a copy of lang/ converted to the expected input, and measure detection accuracy on a real sample of the codebase. The spike output is a build-vs-adopt decision, not a shipped feature. Pin the spike at v1.10.0 or later so the exercise reflects the maintained line rather than a stale tag.
Compatibility. Improved on paper, still orthogonal to our stack. The PHP ≥8.2 floor now matches Laravel 11/12 runtimes, removing a prior source of friction — but the package is Symfony-versioned, so its constraint set remains irrelevant or hostile to a Laravel composer.json. Isolate any trial in a separate directory or CI job to avoid dependency resolution conflicts in the main lockfile. The new Symfony 8 support is a future-proofing data point for Symfony shops; it is neutral for us.
Sequencing. Unchanged:
artisan translations:audit with --missing, --unused, --locale=, non-zero exit code on failure.Maintenance. The calculus shifts modestly but the conclusion holds. Upstream is demonstrably alive and competently stewarded — a real positive if we were a Symfony shop, and a mild positive for a fork because the base is current and secure. It does not change the fact that adopting this package transfers ownership to us at fork time: upstream is tracking Symfony idioms, not Laravel, and a Blade-support PR remains improbable regardless of contributor activity. Budget ongoing ownership of the extraction patterns as the codebase evolves — new helpers, new dynamic-key conventions, and new locale formats will each need attention. Mitigation: fork from ≥v1.10.0 so we inherit a modern PHP floor and current security posture, and keep the fork shallow (extractor only) to make upstream rebases cheap if we ever want them.
Support. Still no vendor, no SLA, and no community of meaningful size (0 dependents). Slightly better than before in that the project has responsive, high-credibility maintainers, so upstream bug reports and security fixes are likely to land. That is a supply-chain comfort, not a support contract for our integration. Internal documentation remains mandatory: how the command works, how to triage false positives, and how to suppress known-acceptable findings (allowlist file).
Scaling. Negligible runtime concern — static analysis over a few thousand strings, finishes in seconds. Not a bottleneck. The scaling cost is cognitive: as locales multiply the report grows and reviewers tune it out. Per-locale summaries and a hard allowlist keep it actionable.
Failure modes.
dev-main.Ramp-up. Low for a single engineer (half a day to understand the checker, one to two days for the spike). Effectively zero for the rest of the team if delivered as an artisan command with a clear README and a warn-only rollout. The v1.10.0 release adds no new surface to learn.
TPM verdict. Reaffirmed with a caveat. v1.10.0 is a health signal, not a capability signal: it proves the package is well maintained and current on PHP 8.2+/Symfony 8, and it improves the quality of the base if we fork — but it adds exactly zero Laravel relevance and no extraction or accuracy improvements. The business value — an automated gate on translation completeness that removes manual QA toil and de-risks i18n releases — is real, but this package remains the wrong vehicle for a Laravel codebase. Fund the spike (pinned at ≥v1.10.0) to harvest the logic; default to a small in-house Artisan command unless the spike proves the port is genuinely cheaper. Do not commit to the bundle as a dependency. Re-review if upstream ever ships framework-agnostic extraction.
How can I help you explore Laravel packages today?