symfony/translation
Symfony Translation component for internationalizing PHP apps: create a Translator, load messages from arrays, files, or other loaders, handle locales and domains, and translate strings at runtime. Part of the Symfony ecosystem and works well standalone.
Install the package (if not using Laravel’s built-in translation):
composer require symfony/translation
(Note: Laravel already bundles this component; no extra install needed for core functionality.)
Configure locales in config/app.php:
'locale' => 'en',
'fallback_locale' => 'en',
'supportedLocales' => [
'en' => 'English',
'fr' => 'Français',
'es' => 'Español',
],
First translation use case:
resources/lang/{locale}/messages.php:
return [
'welcome' => 'Welcome, :name!',
'validation' => [
'required' => 'The :attribute field is required.',
],
];
{{ __('messages.welcome', ['name' => 'John']) }}
$translated = trans('messages.welcome', ['name' => 'John']);
Dynamic locale switching (e.g., based on user preference):
app()->setLocale($user->locale);
Organize translations by domain (e.g., validation, auth, notifications) for modularity:
// Load a specific domain
$translator->trans('validation.required', [], null, 'validation');
// In Laravel, domains are auto-loaded from `resources/lang/{locale}/{domain}.php`
Leverage Symfony’s loaders for non-PHP formats (e.g., YAML, JSON, XLIFF):
use Symfony\Component\Translation\Loader\YamlFileLoader;
// Add YAML loader for translations
$loader = new YamlFileLoader();
$translator->addLoader('yaml', $loader);
$translator->addResource('yaml', 'path/to/translations.yml', 'fr_FR');
Cache translations for performance (Laravel handles this automatically via FileCache):
$translator = new Translator('en', new FileCache(), new ArrayLoader());
Use placeholders for dynamic content:
// Translation file
'email.subject' => 'Your order #:order_id is confirmed!';
// Usage
trans('email.subject', ['order_id' => 12345]);
Configure fallback locales in config/app.php:
'fallback_locale' => 'en',
If fr_FR translation is missing, it falls back to en.
Override Laravel’s default validation messages:
// resources/lang/fr/validation.php
return [
'required' => 'Le champ :attribute est obligatoire.',
];
Use Symfony’s Intl integration for dates, numbers, and plurals:
use Symfony\Component\Translation\TranslatorInterface;
// Format a date for the current locale
$formattedDate = $translator->transChoice(
'There is {0} no message|{1} one message|[2,*] %count% messages.',
2,
['%count%' => 2]
);
Mock translations in tests:
$translator = $this->createMock(TranslatorInterface::class);
$translator->method('trans')->willReturn('Mocked translation');
$this->app->instance(TranslatorInterface::class, $translator);
Create custom Blade directives for reusable translation logic:
// app/Providers/BladeServiceProvider.php
Blade::directive('transChoice', function ($expression) {
return "<?php echo app('translator')->transChoice({$expression[0]}, {$expression[1]}, {$expression[2]}); ?>";
});
// Usage in Blade
@transChoice('messages.plural', count($items), ['%count%' => count($items)])
laravel-translation-manager.php vendor/bin/translation:push --locale=fr --force
php vendor/bin/translation:pull --locale=fr
Locale Mismatch in URLs
/fr/dashboard), ensure middleware sets the locale:
public function handle($request, Closure $next) {
$locale = $request->segment(1);
if (in_array($locale, config('app.supportedLocales'))) {
app()->setLocale($locale);
}
return $next($request);
}
Caching Issues
php artisan cache:clear
FileCache stores translations in bootstrap/cache/.Missing Fallback Locale
fallback_locale in config/app.php to avoid runtime errors.YAML/JSON Parsing Errors
yaml or json loaders for non-PHP formats:
$translator->addResource('yaml', 'path/to/translations.yml', 'fr_FR');
Pluralization Rules
$translator->transChoice('messages.items', 1, ['%count%' => 1]);
Translation Keys Collisions
auth.login, validation.email).Third-Party Loader Quirks
--force flag to avoid partial file overwrites:
php vendor/bin/translation:push --locale=en --force
Deprecated Methods
TranslatableMessage::__toString() (deprecated in Symfony 8). Use trans() or getMessage() instead.Check Loaded Resources
$resources = $translator->getCatalogue('fr_FR')->getResources();
dump($resources);
Enable Debug Mode
$translator->setFallbackLocale('en');
$translator->setDebug(true); // Logs missing translations
Validate Locale Codes
en_US, fr_CA). Avoid en-us (hyphen vs. underscore).Test Locale-Specific Formatting
IntlDateFormatter for dates:
use Symfony\Component\Intl\Intl;
echo Intl::formatDateTime('2023-01-01', Intl::bestMatch('fr_FR', null, Intl::GREGORIAN, Intl::TRADITIONAL));
Custom Loaders Create a loader for your format (e.g., Markdown):
use Symfony\Component\Translation\Loader\LoaderInterface;
class MarkdownLoader implements LoaderInterface {
public function load($resource, $locale, $domain = 'messages') {
$content = file_get_contents($resource);
return ['content' => Markdown::parse($content)];
}
}
Translation Filters Add filters to modify translations dynamically:
$translator->addFilter('uppercase', function ($message) {
return strtoupper($message);
});
// Usage: trans('message.key', [], 'uppercase')
Event Listeners
Listen to translation events (e.g., translator.message.not_found):
$translator->addListener('translator.message.not_found', function ($event) {
Log::warning("Missing translation: {$event->getId()}");
});
Laravel Service Provider Extend Laravel’s translator binding:
public function register() {
$this->app->extend('translator', function ($translator) {
$translator->addLoader('custom', new CustomLoader());
return $translator;
});
}
$translator->addResource('array', $translations, 'en');
$translator
How can I help you explore Laravel packages today?