bottelet/translation-checker
Laravel dev tool to scan your code for translation strings, detect missing keys in lang files (JSON/PHP), and sync them across locales. Optionally use AI to auto-translate missing entries; otherwise adds null placeholders to keep files consistent.
Start by installing the package in your Laravel project as a dev dependency:
composer require bottelet/translation-checker --dev
Once installed, run the basic command to check for missing translations in your target language:
php artisan translations:check en
This will scan your .blade.php and .php files for translation calls (__() and @lang()), identify missing keys in your language files (e.g., lang/en/messages.php or lang.json), and add them with null values. If you're using translation services, you can opt to auto-translate:
php artisan translations:check fr --translate-missing
First use case: onboarding a new language — add support for a new locale (de, es, etc.) by syncing and translating from your base language (en).
CI Integration: Add php artisan translations:check (with --translate-missing if configured) to your deploy pipeline to prevent merging code with missing translations.
Pre-commit Hook: Use a Git hook to run translations:clean and translations:sort before committing, ensuring consistent, minimal translation files.
Regular Sync Workflow:
__('Welcome home')).php artisan translations:check en --translate-missing to auto-populate missing keys (if using a translation service like DeepL or Google Translate).php artisan translations:sync en --target=fr to propagate the new keys to other languages.Custom File Support: Extend RegexExtractor in AppServiceProvider to scan .vue, .jsx, .ts, or .svelte files containing custom translation helpers (e.g., __t('foo')).
Dynamic Values: Use the /** @translate<...> */ comment for strings containing dynamic values or variable content, e.g.:
/** @translate<User created, User updated, User deleted> */
$message = getUserActionDescription($user);
Config Overrides: Adjust config/translation-checker.php to customize source paths, sorting strategy, or translation service (e.g., switch from default null to GoogleTranslator).
Null defaults: Missing keys default to null (not the key string itself). Laravel’s __() will output the key when translation is missing — but only if the value is null. If you see the key echoed instead of the string, you may have accidentally omitted the key or used invalid syntax.
Blade directives like @lang() are not auto-detected: The extractor only scans __() and trans() calls by default. If you use @lang('key'), you must define a custom regex pattern.
Configuration caches: Run php artisan config:clear if changes to config/translation-checker.php aren’t picked up.
Dynamic translation edge cases: When using __($variable), the checker cannot determine the key. Mitigate with /** @translate */ comments or helper functions (e.g., __t()), but be aware the checker won’t infer values unless explicitly annotated.
Sorting conflicts: If using custom sorting (e.g., natural or case-sensitive), ensure it aligns with your team’s expectations and tools like git diff readability.
Translation service setup: To use --translate-missing, configure environment variables (e.g., TRANSLATION_SERVICE_CLASS, TRANSLATION_API_KEY) — check docs for your provider. If no service is configured, null is used.
Clean carefully: translations:clean removes unused keys from the source file only. It never deletes translations in non-source files — that’s deliberate to avoid data loss. Manual cleanup is recommended for target languages.
How can I help you explore Laravel packages today?