webduonederland/laravel-missing-translations
A Laravel package that scans your application for missing translation keys and reports them, helping you keep language files complete and catch untranslated strings before they reach production.
Architecture fit. webduonederland/laravel-missing-translations is a developer-tooling package, not a runtime dependency: it registers a service provider and exposes an Artisan command that scans Blade templates and PHP source for translation keys (__(), @lang, trans()) and reports keys that resolve to nothing in the configured lang paths. That places it squarely in the static-analysis / CI-linting layer of a Laravel codebase, alongside PHPStan, Pint, and Pest. It does not sit on the request path, does not touch the database, and does not alter translation resolution at runtime — which is the single most important fact for a TPM: the blast radius of adopting it, or of it breaking, is bounded to the developer workflow.
Integration feasibility. Very low effort. Standard composer require --dev, Laravel package auto-discovery, one published config file, one Artisan invocation. Release 1.3.0 explicitly adds Laravel 13 support, which is the material change here — it removes the version ceiling that would otherwise block adoption on teams already planning a Laravel 13 upgrade. The accompanying "bugfix in config publish" is a quality-of-life fix: it means vendor:publish --tag=config produces a working config rather than a malformed or mis-tagged file. Both changes are additive/compatible; neither is a breaking change.
Technical risk. Low-to-moderate, and concentrated in two areas rather than in the code itself:
@FinnPaes) with a short release history (the changelog link compares 1.1.0…1.2.0 for a 1.3.0 release). Laravel-13 support arriving is a good signal of active maintenance, but the bus factor is 1. Mitigation is cheap: pin the version, keep it require-dev, and accept that a fork is a few hundred lines if the package is abandoned.__("errors.{$code}"), keys from config, keys from a DB) will be reported as missing or silently skipped. A noisy tool gets disabled by the team within two sprints; the assessment should treat "false-positive rate on our codebase" as the primary adoption gate, not installation.Key questions.
lang/en.json), nested vendor namespaces (vendor::file.key), and pluralization (trans_choice)?vendor/ and node_modules/?Stack fit. Assumes a conventional Laravel app or package with lang/ at the project root (Laravel 9+ layout). It is a require-dev dependency only — it should never appear in a production composer.json require block, and there is no reason to ship it to runtime images.
Migration path. Treat as greenfield rather than a migration. There is no incumbent tool to displace, so the path is: install into a single representative service → run report-only → triage output by hand → decide. If a team currently maintains a bespoke grep/PHP script for the same job, run both in parallel for one release cycle and compare output before retiring the script; the custom script may encode project-specific conventions (e.g. a key prefix scheme) that the package will not know about.
Compatibility. 1.3.0 is backward compatible with earlier 1.x. The config-publish bugfix means teams that previously published a broken config should republish and diff — but since the package is new to us, this is a non-issue on first install. The Laravel 13 support is the reason to prefer 1.3.0 over 1.1.0/1.2.0 for any service on or approaching 13, and there is no penalty for using it on 10/11/12 if the constraint permits. Verify the constraint in composer.json at install time rather than trusting the release title: the changelog's compare link (1.1.0...1.2.0) does not match the announced 1.3.0, so confirm the tag actually exists and what it requires.
Sequencing.
Maintenance. Near zero ongoing cost. No runtime footprint, no schema, no data migration, no cron. The only recurring work is a composer update on the normal dev-dependency cadence, plus a re-run of the triage step whenever the package's detection logic changes materially. Budget roughly a day of engineering for the initial spike-and-triage and a few hours per quarter thereafter.
Support. The support story is "self-serve plus fork." With a single maintainer, we should not expect SLAs, rapid issue turnaround, or guaranteed forward-compatibility with future Laravel majors — 1.3.0's Laravel 13 support was delivered, which is reassuring but is one data point. Pin to ^1.3 in composer.json so an unexpected 2.0 cannot break CI silently. Because the package is dev-only and small, the fallback (vendor the code or fork it) is realistic; note this explicitly in the adoption record so the decision is not re-litigated later.
Scaling. Scales linearly with repository size, not with traffic or user count — the "scaling" concern here is CI wall-clock time on large or monorepo codebases. Scope the scan to application source directories and exclude generated code, build artefacts, and third-party paths. For monorepos with multiple Laravel apps, expect to run per-app with distinct configs; a single repo-wide invocation will blend translation namespaces and produce misleading results. On very large repos, run it on a schedule or on changed-paths only rather than on every push.
Failure modes.
vendor:publish with force on an already-configured repo would clobber tuned settings. Use --tag without --force and keep the config in version control.Ramp-up. Effectively nil for developers — one command, output is self-explanatory. The real ramp-up is organisational: agreeing what the check enforces, who triages the initial backlog of missing keys, and whether translation completeness is a release gate. That governance conversation is a day of TPM work and is the difference between a useful lint and a disabled CI job. Recommend: pilot on one service, publish the triage results as the go/no-go artefact, and only then write the check into the team's definition of done.
How can I help you explore Laravel packages today?