jbboehr / phpstan-lost-in-translation
PHPStan extension for validating Laravel translation keys, replacements, choices, locales, files, and Blade usage
Package info
github.com/jbboehr/phpstan-lost-in-translation
Type:phpstan-extension
pkg:composer/jbboehr/phpstan-lost-in-translation
Requires
- php: ^8.1
- ext-mbstring: *
- phpstan/phpstan: ^1.12 || ^2.0
- salsify/json-streaming-parser: ^8.3
- symfony/finder: ^6 || ^7
- symfony/intl: ^6 || ^7
Requires (Dev)
- composer-runtime-api: *
- brick/varexporter: *
- friendsofphp/php-cs-fixer: ^3.95
- jbboehr/doctrine-of-the-second-sun: dev-master
- larastan/larastan: ^2.11 || ^3.4
- laravel/framework: ^9 || ^10 || ^11 || ^12 || ^13
- orchestra/testbench: ^7.55 || ^8.36 || ^9.14 || ^10.3 || ^11.0
- phpbench/phpbench: ^1.4
- phpstan/extension-installer: ^1.4
- phpstan/phpstan-deprecation-rules: ^1.2.1 || ^2.0
- phpstan/phpstan-phpunit: ^1.4.2 || ^2.0.6
- phpstan/phpstan-strict-rules: ^1.6.2 || ^2.0.4
- phpunit/phpunit: ^9.6 || ^10.5 || ^11.5
- slevomat/coding-standard: ^8.18
- squizlabs/php_codesniffer: ^3.13
- tomasvotruba/bladestan: >=0.6
- webmozart/assert: ^1.11
This package is auto-updated.
Last update: 2026-08-16 01:59:51 UTC
README
phpstan-lost-in-translation
A PHPStan extension for statically checking Laravel translations. It finds missing and possibly unused translation keys, validates replacements, plural choices, locales, encodings, and translation files, and can inspect calls in Blade templates through Bladestan.
What it catches
- missing translations, including likely omissions from the base locale;
- translation keys that are unused or cannot be inferred statically;
- unused replacements and replacement keys that match multiple casing variants;
- malformed or incomplete plural choices;
- unknown locales, locale conflicts, and invalid character encodings; and
- invalid translation-file values and parse failures.
Installation
The 0.x series remains experimental while its public configuration and diagnostics settle. Install the 0.1 release
line so later minor releases do not introduce unexpected pre-1.0 compatibility changes:
composer require --dev jbboehr/phpstan-lost-in-translation:^0.1
When phpstan/extension-installer is installed, Composer registers the
extension automatically. Otherwise, include it explicitly from phpstan.neon:
includes: - vendor/jbboehr/phpstan-lost-in-translation/extension.neon
Quick example
Calls with statically inferable keys are checked against the application's translation files.
<?php __('missing translation string');
$ phpstan analyse ------ ------------------------------------------------------------------------- Line example.php ------ ------------------------------------------------------------------------- 3 Missing translation string "missing translation string" for locales: ja 🪪 lostInTranslation.missingTranslationString ------ -------------------------------------------------------------------------
Compatibility
The validation matrix covers PHPStan 1.12 and 2.x with these Laravel and PHP combinations:
| Laravel | Tested PHP versions |
|---|---|
| 9 | 8.1–8.2 |
| 10 | 8.1–8.3 |
| 11 | 8.2–8.5 |
| 12 | 8.2–8.5 |
| 13 | 8.3–8.5 |
Recommended integrations
Core PHP translation-call analysis does not require either integration:
- Larastan improves Laravel-aware type inference.
- Bladestan enables translation analysis inside reachable Blade templates.
Supported translation APIs
| Form | Support |
|---|---|
__('key') |
Supported |
trans('key') |
Supported |
trans_choice('key', $count) |
Supported |
$translator->get('key') |
Supported when PHPStan infers Laravel's translator contract |
$translator->choice('key', $count) |
Supported when PHPStan infers Laravel's translator contract |
Lang::get('key') |
Supported |
Lang::choice('key', $count) |
Supported |
Blade __() and @lang |
Supported through Bladestan |
Configuration
The defaults enable higher-confidence missing-key, replacement, choice, locale, encoding, and translation-file checks. After addressing those findings, stricter checks can be enabled independently:
parameters: lostInTranslation: unusedTranslationStrings: true disallowDynamicTranslationStrings: true requireCompletePluralForms: true
See the configuration reference for every option and default.
Documentation
- Getting started covers installation, compatibility, recognized APIs, and adoption.
- Translation keys covers missing, unused, base-locale, dynamic, and fuzzy checks.
- Blade templates covers Bladestan and the nested-analysis compatibility bridges.
- Replacements and plural choices defines replacement and choice validation.
- Locales and translation files covers locale policy, layouts, encoding, and loader errors.
- Configuration lists every supported option and default.
Development
Enter the default PHP 8.1 shell and use an ordinary mutable Composer installation:
nix develop composer install vendor/bin/phpunit vendor/bin/phpstan
Run the complete routine suite, including the supported PHP/Laravel matrix and isolated consumers, with:
nix flake check --keep-going -L
Build and verify the user guide from the PHP 8.2 documentation shell:
nix develop .#documentation --command composer docs:check
See CONTRIBUTING.md and the mutation-testing guide for the remaining development workflows.
References
This project is based on and inspired by coding-socks/lost-in-translation.
License
phpstan-lost-in-translation is licensed under the GNU Affero General Public License version 3 with the Romic
Exception: AGPL-3.0-only WITH romic-exception.
The Romic Exception permits phpstan-lost-in-translation to be linked or combined with other code without subjecting that other code to the AGPL merely because of the linking or combination. Modifications to the covered project remain subject to the Project License, including its source-availability requirements for modified versions made available over a computer network. See LICENSE.md and docs/LICENSE_EXCEPTION.md.
Contribution terms and the optional CLA route are documented in CONTRIBUTING.md. Alternative licenses may be available from the Project Steward.
