Easily manage all your Laravel translation strings with powerful features:
- Translate strings into other languages using OpenAI, Claude, Gemini or custom services.
- Proofread translations to fix grammar and syntax automatically (using OpenAI, Claude, Gemini or custom service).
- Find missing translation strings across locales.
- Detect unused translation keys in your codebase.
- Sort translations in natural order.
- Import & Export translations in a CSV file.
- How does it work?
- Installation
- Configuring the Driver
- Configuring the Locales
- Configuring the Code Scanner
- Sorting and Formatting
- Automatic Translation
- Proofreading Translations
- Identifying Untranslated Translations
- Detecting Missing Translations
- Detecting Dead Translations
- Export to a CSV
- Import from a CSV
This package will directly modify your translation files like /lang/en/messages.php or /lang/fr.json for example.
Both PHP and JSON files are supported.
Advanced features like dead translations detection will scan your entire codebase to find unused translation strings.
Install the package via Composer:
composer require elegantly/laravel-translator --devAdd the following line to your .gitignore file:
storage/.translator.cache
Publish the configuration file:
php artisan vendor:publish --tag="translator-config"This package uses a driver-based architecture. By default, it supports two standard drivers: PHP and JSON.
- Use the
PHPdriver if you store your translation strings in.phpfiles, such as/lang/en/message.php. - Use the
JSONdriver if you store your translation strings in.jsonfiles, such as/lang/fr.json.
You can also create custom drivers for alternative storage methods, such as a database.
Set the default driver in the configuration file:
use Elegantly\Translator\Drivers\PhpDriver;
return [
/**
* Possible values: 'php', 'json', or a class-string implementing Driver.
*/
'driver' => PhpDriver::class,
// ...
];Note
All features are supported in both the PHP and JSON drivers.
By default, this package will attempt to determine the locales defined in your application by scanning your lang directory.
You can customize this behavior in the configuration file.
use Elegantly\Translator\Support\LocaleValidator;
return [
// ...
'locales' => LocaleValidator::class,
// ...
];To set the locales manually, use the following configuration:
return [
// ...
'locales' => ['en', 'fr', 'es'],
// ...
];Service: searchcode.
Features:
Both the detection of dead and missing translations rely on scanning your code.
- Missing translations are keys found in your codebase but missing in translation files.
- Dead translations are keys defined in your translation files but unused in your codebase.
At the moment, this package can only scan the following files:
.php.blade.php
Note
If you use a React or Vue frontend, it would not be able to scan those files, making this feature irrelevant.
The default detector uses nikic/php-parser to scan all your .php files, including the Blade ones.
In order to be able to detect your keys, you will have to use one of the following Laravel function:
__(...),trans(...)trans_choice(...)\Illuminate\Support\Facades\Lang::get(...)\Illuminate\Support\Facades\Lang::has(...)\Illuminate\Support\Facades\Lang::hasForLocale(...)\Illuminate\Support\Facades\Lang::choice(...)app('translator')->get(...)app('translator')->has(...)app('translator')->hasForLocale(...)app('translator')->choice(...)
Or one of the following Laravel Blade directive:
@lang(...)
Here is some example of do's and don'ts:
__('messages.home.title'); // ✅ 'messages.home.title' is detected
foreach(__('messages.welcome.lines') as $line){
// ✅ 'messages.welcome.lines' and all of its children are detected.
}
$key = 'messages.home.title';
__($key); // ❌ no key is detectedSpecify paths to scan for translation keys. By default, both .php and .blade.php files are supported.
return [
'searchcode' => [
'paths' => [
app_path(),
resource_path(),
],
],
];Exclude irrelevant paths for optimized scanning, such as test files or unrelated directories.
return [
'searchcode' => [
'excluded_paths' => [
'tests'
],
],
];Ignore specific translation keys:
return [
'searchcode' => [
'ignored_translations' => [
'countries', // Ignore keys starting with 'countries'.
],
],
];Sort translations with the default driver:
php artisan translator:sortSpecify a driver for sorting:
php artisan translator:sort --driver=jsonSort translations programmatically with the default driver:
use Elegantly\Translator\Facades\Translator;
Translator::sortTranslations(locale: 'fr');Specify a driver:
Translator::driver('json')->sortTranslations(locale: 'fr');Service: translate.
Before translating, configure a translation service. The package supports:
- Prism (prism-php/prism)
- Any Prism provider (OpenAI, Anthropic/Claude, Gemini, Ollama, ...)
Custom translation services can also be implemented.
Enable Prism as your translation service in config/translator.php:
return [
// ...
'translate' => [
'service' => 'prism',
// ...
],
];Choose the provider/model used by the translator:
return [
// ...
'services' => [
'prism' => [
'provider' => env('TRANSLATOR_PRISM_PROVIDER', 'openai'),
'model' => env('TRANSLATOR_PRISM_MODEL', 'gpt-4.1-mini'),
],
],
// ...
];Prism itself reads provider credentials from config/prism.php.
If you haven't published the Prism config yet:
php artisan vendor:publish --tag=prism-configTo translate with Claude via Prism, set the provider to anthropic and pick a Claude model:
return [
// ...
'services' => [
'prism' => [
'provider' => 'anthropic',
'model' => 'claude-3-7-sonnet-latest',
],
],
// ...
];Note
Ensure your ANTHROPIC_API_KEY is configured in config/prism.php (or set in your .env).
To translate with Gemini via Prism, set the provider to gemini and pick a Gemini model:
return [
// ...
'services' => [
'prism' => [
'provider' => 'gemini',
'model' => 'gemini-2.0-flash',
],
],
];Note
Ensure your GEMINI_API_KEY is configured in config/prism.php (or set in your .env).
Translate all missing keys from English to every configured locale:
php artisan translator:translate enForce re-translation of all keys (overwrites existing values):
php artisan translator:translate en --forceTranslate from English to French:
php artisan translator:translate en --target=frTranslate using smaller/larger chunks (defaults to 10):
php artisan translator:translate en --chunk=25Translate using a specific driver:
php artisan translator:translate en --driver=jsonInspect untranslated keys before translating:
php artisan translator:untranslated en frInspect untranslated keys with a specific driver:
php artisan translator:untranslated en fr --driver=jsonAdd a new locale and immediately translate it from an existing source locale:
php artisan translator:add-locale fr en --translateTranslate translations programmatically with the default driver:
Translator::translateTranslations(
source: 'en',
target: 'fr',
keys: ['validation.title', ...]
);Specify a driver for translation:
Translator::driver('json')->translateTranslations(
source: 'en',
target: 'fr',
keys: ['My Title', ...]
);Service: proofread.
Proofreading corrects the grammar and syntax of your translation strings.
This package ships with a Prism-based proofreading service (prism-php/prism), and custom services can also be implemented.
Enable it by setting translator.proofread.service to prism, and configure Prism as described in Configuring Prism.
Proofread all strings in the target locale (English).
php artisan translator:proofread enProofread translations with the default driver:
Translator::proofreadTranslations(
locale: 'fr',
keys: ['auth.email', ...]
);Specify a driver:
Translator::driver('json')->proofreadTranslations(
locale: 'fr',
keys: ['My Title', ...]
);Find keys defined in one locale but missing in another.
Display all keys defined in the source locale (English) but not in the target locale (French).
php artisan translator:untranslated en frTranslator::getUntranslatedTranslations(source: 'en', target: 'fr');Service: searchcode.
Configuration: Configuring the Code Scanner
Missing translations are keys found in your codebase but missing in translation files.
Find keys defined in your codebase but missing in your locale (English) using your default driver:
php artisan translator:missing enSpecify a driver:
php artisan translator:missing en --driver=jsonAdd the missing keys to your driver:
php artisan translator:missing en --syncTranslator::getMissingTranslations(locale: 'en');Service: searchcode.
Configuration: Configuring the Code Scanner
Dead translations are keys defined in your locale (English) but unused in your codebase.
php artisan translator:dead enTranslator::getDeadTranslations(locale: 'fr');Service: exporter
Export all your translation strings to a CSV file in the following format:
| key | en | fr |
|---|---|---|
| messages.auth.login | Login | Connexion |
php artisan translator:export /path/to/my/file.csv$path = Translator::exportTranslations('/path/to/my/file.csv');Service: exporter
Import translation strings from a CSV file. Ensure your CSV follows the format below:
| key | en | fr |
|---|---|---|
| messages.auth.login | Login | Connexion |
php artisan translator:import /path/to/my/file.csv$translations = Translator::importTranslations('/path/to/my/file.csv');Run tests using:
composer testSee the CHANGELOG for recent updates.
Check the CONTRIBUTING guide for details.
Report security vulnerabilities via GitHub or email.
This package is licensed under the MIT License. See the License File for more details.
