Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Translation Audit Laravel Package

simonecerruti/laravel-translation-audit

Audit your Laravel translation files from the command line: spot missing keys, unused strings, duplicate entries, and inconsistencies across locales so every language stays complete and in sync. A lightweight PHP dev tool for cleaner, more reliable localization before shipping.

View on GitHub
Deep Wiki
Context7

Product Decisions This Supports

  • Localization completeness as a release gate. The package's core value is CI-enforceable detection of missing translation keys, so "are we shippable in locale X?" becomes a pass/fail signal in the pipeline rather than a manual QA sweep. This release extends that gate to GitLab with a ready-made job, which removes "our CI is not GitHub Actions" as a blocking objection and makes the check adoptable across more of the org without custom wiring.
  • False-positive budget for automation. The v0.12.7 change routed dynamic keys such as __('payments.'.$method) through Laravel's own translator instead of diffing key lists per locale file, so nested-array keys (validation.password), framework-provided strings, and unreadable locale files no longer generate noise. That remains the reason the gate survives contact with a real team. Any noise-reduction change to a gating check is decision-relevant, because it changes whether engineers tolerate the gate.
  • Per-audit ignore scoping as a policy lever (new, and the most decision-relevant item here). ignore_paths, ignore_locales and ignore_keys can now be mapped to AuditType::Missing or AuditType::Unused, so suppressing noise in one audit no longer silently disables the other. Previously ignoring a path to silence missing-key failures also removed those files from unused detection, letting dead keys accumulate; now 'database/seeders/**' => AuditType::Missing keeps those keys counted as used. Two practical consequences: you can stage adoption (enable the low-risk unused audit first, add the missing audit once the ignore list stabilizes), and you can ignore a locale for missing keys only — e.g. 'en' => AuditType::Missing when the keys are the English text — while still reporting and purging its unused translations.
  • Known accuracy tradeoff to accept explicitly. Keys the translator cannot resolve — notably entries nested under array keys containing dots ('ipmi.type' => ['help' => …]) — are reported as missing. That narrow class of false positives is the price of correct detection of genuinely unresolvable keys. It is now easier to encode as an exception list, because entries can be scoped to AuditType::Missing and left out of the unused audit.
  • A migration hazard worth a checklist item. unused_ignore_paths is gone, merged into ignore_paths, and its defaults (Laravel's own translation files) are now defaults of ignore_paths. A published config that defines its own ignore_paths must add those defaults back, or Laravel's own translation files are reported as unused and removed by translation:purge-unused. This is the one item in the release with a plausible path to user-visible damage (deleted validation messages), so treat it as a required migration step with a reviewed diff, not a nice-to-have.
  • Upgrade stability vs. extension. Delineating the public API ahead of v1.0 — service provider, commands, TranslationKeyResolver, Result contract and results, Data\Translation, the DisplayFormat/SaveFormat enums, InvalidConfigException, AuditType — plus marking everything else @internal and making every concrete class final, is good news for ownership: what you integrate against is now a stated contract, and future upgrades should not break it. The cost is that anything built on the internals (AuditTranslationsResult::withUnused(), jsonSections(), subclassing a command) breaks now. Worth a one-time audit of your integration for internal usage before upgrading.
  • Translation debt cleanup before launches and audits. translation:purge-unused supports a recurring hygiene task: removing dead keys after feature removals, shrinking locale files, and reducing the surface translators must maintain. The per-audit ignore scoping makes the purge safer to reason about, since "counts as used" is now expressible rather than implied.
  • Build vs. buy for i18n tooling. Still a small, single-purpose dev dependency, not a runtime service — cheap to adopt, cheap to reverse. The real cost is CI wiring, the config migration, and the team's willingness to act on failures, not the package itself. This release adds migration cost but lowers ongoing integration cost.
  • Roadmap input for i18n scope. Persistent missing-key reports across releases are a concrete, quantified argument for either hiring translation capacity or narrowing the set of officially supported locales; unused-key counts support the opposite argument — consolidate, don't translate everything.
  • Vendor/translator workflow. Deterministic key detection and purge give you a stable key inventory to hand to an agency or a crowdin-style pipeline, reducing round-trips caused by phantom keys.

When to Consider This Package

Consider it when:

  • You ship a Laravel app in more than one locale, or plan to, and missing keys currently reach production or QA.
  • You want translation completeness enforced in CI rather than by convention — and specifically if you run GitLab CI, where this release now ships a supported job out of the box.
  • Your codebase uses dynamic translation keys heavily (e.g. __('payments.'.$method)); translator-based detection is aimed at that pattern, though it remains heuristic and will not catch keys assembled from untrusted or highly variable input.
  • You have accumulated unused keys after feature removals and want a command-driven purge that can be scoped independently from missing-key reporting.
  • You have, or can build, a small enumerable ignore list — now expressible per audit — for the dot-containing array key false positives.
  • You are willing to do a short, reviewed config migration as part of upgrading to 0.13.

Look elsewhere or defer when:

  • You are single-locale with no near-term localization roadmap — the value is speculative.
  • Your translations live primarily in a TMS or database rather than PHP/JSON files; verify compatibility before committing.
  • You need runtime translation management, editor UI, or machine-translation workflows — this is a developer/CI tool, not an i18n platform.
  • Your integration depends on the internals now marked @internal (e.g. withUnused(), jsonSections()) or on extending a command or result class — those are now final and will break; budget a rewrite against the public API first.
  • Your team will not act on CI failures; an ignored gate is pure overhead.
  • purge-unused cannot be run against a branch you trust — it is destructive, there is no indication of a dry-run guarantee, and the merged ignore_paths defaults make a misconfigured migration actively dangerous. Validate both before enabling it in automation.

Pin to 0.13.x. Pre-1.0 semantics can still shift between minor releases — this release is itself evidence, and it is a breaking one. The upside is that the public surface is now written down, so upgrades after this one should be cheaper.

How to Pitch It (Stakeholders)

For executives: This is a small developer tooling package that catches missing app translations before release, in the same automated pipeline that already runs tests. Two things changed in the latest release. First, it now works on GitLab as well as GitHub, so more teams can adopt it without bespoke setup. Second, the latest fix makes the check easier to tune: teams can silence noise in one check without turning off the other, which is the main reason these gates get switched off. The release also freezes the tool's public interface ahead of a 1.0 milestone — meaning upgrades will be more predictable going forward, at the cost of a short, reviewed configuration migration now. Net effect: fewer untranslated screens reaching customers, less manual QA per release, and a cleaner, smaller list of strings we pay translators to maintain. Cost is a dev dependency, a short CI integration and a one-time migration; no runtime risk, no vendor lock-in.

For engineering: Upgrade deliberately — this is a breaking release. (1) Move any unused_ignore_paths patterns into ignore_paths mapped to AuditType::Unused; a published config with its own ignore_paths must re-add the defaults (lang/*/validation.php etc.), otherwise Laravel's own translation files are reported unused and deleted by translation:purge-unused. (2) Republish workflow assets: the GitHub tag is renamed to laravel-translation-audit-github-workflow, and there is a new laravel-translation-audit-gitlab-workflow publishing to .gitlab/ci/audit-translations.yml. (3) Grep your integration for anything now @internal or final — AuditTranslationsResult::withUnused(), jsonSections(), and subclassing of commands, results or the service provider will no longer work; build only against the stated public API (TranslationKeyResolver, Result, Data\Translation, the enums, InvalidConfigException, AuditType). (4) Use per-audit scoping to phase rollout: enable translation:purge-unused first with AuditType::Unused ignores, then gate on translation:audit once the missing-key ignore list stabilizes. (5) Run purge on a branch and review the diff before merging, and keep unreadable-locale-file silent skips in mind — verify locale paths in CI. Pin to 0.13.x.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource