Laravel (PHP)
Use PolyCLI to translate Laravel's JSON language files automatically.
How it fits together
Laravel supports two translation file formats: PHP array files (resources/lang/en/messages.php) and flat JSON files (resources/lang/en.json). PolyCLI works with the JSON format: one file per language, placed directly in resources/lang/. These files are used by Laravel's __() helper when the key is a full sentence rather than a dotted alias.
Folder structure
resources/lang/
├── en.json ← source file (you maintain this)
├── it.json ← generated by PolyCLI
├── es.json ← generated by PolyCLI
├── fr.json ← generated by PolyCLI
└── .translator-lock.json ← delta tracking — commit this filePolyCLI configuration
Run polycli init in your Laravel project root and enable the phpVariablesoption to activate automatic protection for Laravel's :variable syntax:
{
"sourceLanguage": "en",
"targetLanguages": ["it", "es", "fr", "de"],
"localesPath": "./resources/lang",
"phpVariables": true
}When phpVariables is true, PolyCLI tokenises all :variable patterns before sending strings to the translation API and restores them verbatim in the output. The tokens are never seen by the AI and are not counted toward your credit usage.
Source file example
Laravel JSON translation files use the source-language string as both key and default value. Variables are written as :attribute — for example :name or :count.
{
"Welcome back!": "Welcome back!",
"Hello, :name.": "Hello, :name.",
"Your account has been created.": "Your account has been created.",
"You have :count unread messages.": "You have :count unread messages.",
"The :attribute field is required.": "The :attribute field is required."
}{
"Welcome back!": "Bentornato!",
"Hello, :name.": "Ciao, :name.",
"Your account has been created.": "Il tuo account è stato creato.",
"You have :count unread messages.": "Hai :count messaggi non letti.",
"The :attribute field is required.": "Il campo :attribute è obbligatorio."
}With phpVariables: true, tokens like :name, :count, and :attribute are guaranteed to appear unchanged in every translated file.
Using translations in Laravel
The __() helper looks up the active locale and returns the translated string. Replacements are passed as the second argument.
// Blade template
{{ __('Hello, :name.', ['name' => $user->name]) }}
{{ __('You have :count unread messages.', ['count' => $messages->count()]) }}
// PHP controller
$message = __('Your account has been created.');Running in CI
Add the PolyCLI step before your asset compilation or deployment step. Node.js must be available in the CI environment (it usually is).
- name: Translate
run: npx @polycli/cli run
env:
POLYCLI_API_KEY: ${{ secrets.POLYCLI_API_KEY }}
- name: Build assets
run: npm run buildresources/lang/.translator-lock.json alongside your language files. Without it, every run re-translates the entire source file.