php-translation/symfony-bundle
Symfony bundle for the PHP Translation library. Integrates translation management, storage, and workflows into Symfony apps, with services and console tooling to import/export translations and keep locale files in sync across providers.
Installation Add the bundle via Composer:
composer require php-translation/symfony-bundle
Enable it in config/bundles.php (Symfony) or config/app.php (Laravel via Symfony bridge):
return [
// ...
PhpTranslation\SymfonyBundle\PhpTranslationBundle::class => ['all' => true],
];
Configuration Publish the default config (if needed):
php artisan vendor:publish --provider="PhpTranslation\SymfonyBundle\PhpTranslationBundle" --tag="config"
Update config/php_translation.php to define:
locales (e.g., ['en', 'fr'])default_localepaths (where translation files are stored, e.g., resources/lang).First Translation
Create a translation file (e.g., resources/lang/fr/messages.php):
return [
'welcome' => 'Bienvenue',
];
Use it in a controller or Blade:
$this->translator->trans('messages.welcome');
Define locale-aware routes in routes/web.php:
Route::get('/{locale}/home', function () {
return $this->translator->trans('messages.home');
})->middleware('locale');
Use the locale middleware to set the current locale dynamically.
Use the translator service to fetch translations dynamically:
// In a controller
$greeting = $this->translator->trans('messages.greeting', [
'%name%' => $user->name,
]);
Blade Integration:
{{ trans('messages.greeting', ['%name%' => $user->name]) }}
Configure fallback locales in config/php_translation.php:
'fallbacks' => [
'fr' => ['en'],
'es' => ['en'],
],
If fr translations are missing, it falls back to en.
Bind the Symfony translator to Laravel’s container in AppServiceProvider:
public function register()
{
$this->app->singleton(\Symfony\Contracts\Translation\TranslatorInterface::class,
function ($app) {
return $this->app->make(\PhpTranslation\SymfonyBundle\PhpTranslationBundle::class)
->getTranslator();
}
);
}
Create middleware to set the locale from:
/fr/home)Accept-Language)Example middleware:
public function handle($request, Closure $next)
{
$locale = $request->segment(1) ?? config('app.locale');
app()->setLocale($locale);
return $next($request);
}
Extend Laravel’s validator with translated messages:
$validator = Validator::make($data, [
'email' => 'required|email',
], [
'email.required' => trans('validation.required', ['attribute' => 'Email']),
]);
Return translated errors in API responses:
return response()->json([
'error' => trans('errors.validation_failed'),
'details' => $validator->errors()->toArray(),
], 422);
php artisan cache:clear
php artisan config:clear
php artisan translation:dump to regenerate translation files.session()->put('locale', $locale);
Retrieve it in middleware:
$locale = session('locale', config('app.locale'));
trans() returns the key instead of a value.resources/lang/{locale}/.paths in config/php_translation.php.dd($this->translator->getLocator()->getLocales());
dd($this->translator->getCatalogue()->all());
Set debug: true in config/php_translation.php to log missing translations.
Extend the bundle to load translations from:
Example loader:
use PhpTranslation\Loader\LoaderInterface;
class ApiTranslationLoader implements LoaderInterface
{
public function load($locale, $domain, $theme = null)
{
$translations = $this->fetchFromApi($locale);
return new \Symfony\Component\Translation\MessageCatalogue($locale, $translations);
}
}
Register it in config/php_translation.php:
'loaders' => [
'api' => ApiTranslationLoader::class,
],
Use domains to organize translations (e.g., validation, errors):
$this->translator->trans('validation.required', [], 'validation');
Override pluralization rules for languages like Arabic or Russian:
'pluralization_rules' => [
'ar' => \Symfony\Component\Translation\PluralizationRules::createArabicRules(),
],
Preload translations for all locales in a service provider:
public function boot()
{
$translator = $this->app->make(\Symfony\Contracts\Translation\TranslatorInterface::class);
foreach (config('php_translation.locales') as $locale) {
$translator->getCatalogue($locale);
}
}
transChoice for Plurals$message = trans_choice('messages.item', $count, [
'%count%' => $count,
]);
$translator = Mockery::mock(\Symfony\Contracts\Translation\TranslatorInterface::class);
$translator->shouldReceive('trans')->andReturn('Mocked translation');
$this->app->instance(\Symfony\Contracts\Translation\TranslatorInterface::class, $translator);
$response = $this->get('/fr/home');
$response->assertSee('Bienvenue');
How can I help you explore Laravel packages today?