Easily manage all your Laravel translation strings:
- Translate strings into other languages (DeepL, OpenAI, or any custom service).
- Proofread your translation strings and automatically fix grammar and syntax (OpenAI or any custom service).
- Find missing translation strings across all your locales.
- Detect unused translation keys (keys not used anywhere in your codebase).
- Sort your translations in natural order.
You can install the package via Composer:
composer require-dev elegantly/laravel-translator --dev
If you’re not using this package in production, add the following lines to your .gitignore
file:
.translator.cache
Next, publish the config file with:
php artisan vendor:publish --tag="translator-config"
Here’s the content of the published config file:
return [
/*
|--------------------------------------------------------------------------
| Language Paths
|--------------------------------------------------------------------------
|
| This is the path where your translation files are stored. In a standard Laravel installation, you should not need to change it.
|
*/
'lang_path' => lang_path(),
/*
|--------------------------------------------------------------------------
| Auto Sort Keys
|--------------------------------------------------------------------------
|
| If set to true, all keys will be sorted automatically after any file manipulation such as 'edit', 'translate', or 'proofread'.
|
*/
'sort_keys' => false,
/*
|--------------------------------------------------------------------------
| Third-Party Services
|--------------------------------------------------------------------------
|
| Define the API keys for your third-party services. These keys are reused for both 'translate' and 'proofread'.
| You can override this configuration and define specific service options, for example, in 'translate.services.openai.key'.
|
*/
'services' => [
'openai' => [
'key' => env('OPENAI_API_KEY'),
'organization' => env('OPENAI_ORGANIZATION'),
'request_timeout' => env('OPENAI_REQUEST_TIMEOUT'),
],
'deepl' => [
'key' => env('DEEPL_KEY'),
],
],
/*
|--------------------------------------------------------------------------
| Translation Service
|--------------------------------------------------------------------------
|
| These are the services that can be used to translate your strings from one locale to another.
| You can customize their behavior here, or you can define your own service.
|
*/
'translate' => [
/**
* Supported: 'openai', 'deepl', 'MyOwnServiceClass::name'
* Define your own service using the class's name: 'MyOwnServiceClass::class'
*/
'service' => null,
'services' => [
'openai' => [
'model' => 'gpt-4o',
'prompt' => "
As an experienced copywriter and translator specializing in website copy, your task is to translate the provided content from a specific website.
Your translations should maintain the original tone while being adapted to the target language, ensuring they are both relevant and clear.
The content will be provided in JSON format, and you must translate it to the locale '{targetLocale}'.
Ensure that all JSON keys remain preserved and unchanged.
",
],
],
],
/*
|--------------------------------------------------------------------------
| Proofreading Service
|--------------------------------------------------------------------------
|
| These are the services that can be used to proofread your strings.
| You can customize their behavior here, or you can define your own service.
|
*/
'proofread' => [
/**
* Supported: 'openai', 'MyOwnServiceClass::name'
* Define your own service using the class's name: 'MyOwnServiceClass::class'
*/
'service' => null,
'services' => [
'openai' => [
'model' => 'gpt-4o',
'prompt' => '
Fix the grammar and syntax of the following JSON string while respecting the following rules:
- Never change the keys.
- Do not escape or modify HTML tags.
- Do not escape or modify special characters or emojis.
- Do not change the meaning or tone of the sentences.
',
],
],
],
/*
|--------------------------------------------------------------------------
| Search Code / Dead Code Service
|--------------------------------------------------------------------------
|
| These are the services that can be used to detect dead translation strings in your codebase.
| You can customize their behavior here, or you can define your own service.
|
*/
'searchcode' => [
/**
* Supported: 'php-parser', 'MyOwnServiceClass::name'
*/
'service' => 'php-parser',
/**
* Files or directories to include in the dead code scan.
*/
'paths' => [
app_path(),
resource_path(),
],
/**
* Files or directories to exclude from the dead code scan.
*/
'excluded_paths' => [],
/**
* Translation keys to exclude from dead code detection.
* By default, the default Laravel translations are excluded.
*/
'ignored_translations' => [
'auth',
'pagination',
'passwords',
'validation',
],
'services' => [
'php-parser' => [
/**
* To speed up detection, all the results of the scan will be stored in a file.
* Feel free to change the path if needed.
*/
'cache_path' => base_path('.translator.cache'),
],
],
],
];
Before translating anything, you must choose and set up a translation service.
This package includes two services by default:
- OpenAI
- DeepL
However, you can create your own service if needed.
First, configure the OpenAI key in the config file or define the environment variables:
return [
// ...
'services' => [
'openai' => [
'key' => env('OPENAI_API_KEY'),
'organization' => env('OPENAI_ORGANIZATION'),
'request_timeout' => env('OPENAI_REQUEST_TIMEOUT'),
],
],
// ...
]
First, configure the DeepL key in the config file or define the environment variable:
return [
// ...
'services' => [
// ...
'deepl' => [
'key' => env('DEEPL_KEY'),
],
],
// ...
]
php artisan translator:translate
use Elegantly\Translator\Facades\Translator;
// Translate strings defined in PHP files
Translator::translateTranslations(
source: 'fr',
target: 'en',
namespace: 'validation',
keys: ['title', ...]
);
// Translate strings defined in JSON files
Translator::translateTranslations(
source: 'fr',
target: 'en',
namespace: null,
keys: ['title', ...]
);
This package allows you to proofread (i.e., fix grammar and syntax) your translation strings.
Currently, the package includes one service:
- OpenAI
However, you can create your own service if needed.
First, configure the OpenAI key in the config file or define the environment variables:
return [
// ...
'services' => [
'openai' => [
'key' => env('OPENAI_API_KEY'),
'organization' => env('OPENAI_ORGANIZATION'),
'request_timeout' => env('OPENAI_REQUEST_TIMEOUT'),
],
],
// ...
]
php artisan translator:proofread
use Elegantly\Translator\Facades\Translator;
// Proofread translation strings defined in PHP files
Translator::proofreadTranslations(
locale: 'fr',
namespace: 'auth',
keys: ['title', ...]
);
// Proofread translation strings defined in JSON files
Translator::proofreadTranslations(
locale: 'fr',
namespace: null,
keys: ['title', ...]
);
php artisan translator:missing
// Compare /fr/validation.php and /en/validation.php
Translator::getMissingTranslations(
source: 'fr',
target: 'en',
namespace: 'validation'
);
// Compare /fr.json and /en.json
Translator::getMissingTranslations(
source: 'fr',
target: 'en',
namespace: null
);
Important
The dead code detector cannot detect translation keys if you use string interpolation, such as __("countries.{$user->country})
.
This package scans your entire codebase to find unused translation keys. You can customize its behavior to:
- Include or exclude specific paths.
- Exclude translation keys.
Include all paths where translation keys are likely to be used.
Both .php
and .blade.php
files are supported. You can customize the paths scanned in the config:
return [
// ...
'searchcode' => [
/**
* Files or directories to include in the dead code scan.
*/
'paths' => [
app_path(), // Scan the entire /app directory
resource_path(), // Scan the entire /resource directory
],
// ...
]
// ...
];
To optimize or speed up the scan, you can exclude certain paths. This is particularly useful for:
- Test files that do not rely on your translation files.
- Entire subdirectories unrelated to your translations.
Tip
Excluding paths will speed up the scanner.
Sometimes, translation strings are not used in the codebase, but you don’t want to consider them as unused. For example, you might store all country names in /countries.php
.
Sometimes, the scanner might not detect your translation strings when using string interpolation, such as __("countries.{$user->country})
.
In these cases, you can ignore translation keys in the config:
return [
// ...
'searchcode' => [
// ...
'ignored_translations' => [
'countries', // Ignore all translation keys starting with 'countries'.
],
// ...
]
// ...
];
php artisan translator:dead
// Compare /fr/validation.php and /en/validation.php
Translator::getDeadTranslations(
locale: 'fr',
namespace: 'validation'
);
// Compare /fr.json and /en.json
Translator::getDeadTranslations(
locale: 'fr',
namespace: null
);
php artisan translator:sort
use Elegantly\Translator\Facades\Translator;
// Sort translations from `/fr/validation.php`
Translator::sortTranslations(
locale: 'fr',
namespace: 'validation'
);
// Sort translations from `/fr.json`
Translator::sortTranslations(
locale: 'fr',
namespace: null
);
composer test
Please see CHANGELOG for more information on recent changes.
Please see CONTRIBUTING for details.
Please report any security vulnerabily to me via github or email.
This package is licensed under the MIT License. Please see the License File for more details.