yiisoft/translator
yiisoft/translator is a lightweight PHP translation library for managing messages, locales, and pluralization. Integrates with Yii and PSR-style components, supports multiple message sources and fallback locales, and is suitable for apps and libraries needing i18n.
Installation Add the package via Composer:
composer require yiisoft/translator
Register the service provider in config/app.php:
'providers' => [
// ...
Yiisoft\Translator\Translator::class,
],
Basic Configuration
Define translations in a structured directory (e.g., resources/lang/):
resources/
└── lang/
├── en/
│ └── messages.php
└── es/
└── messages.php
Example messages.php (English):
return [
'welcome' => 'Welcome to our application!',
'greeting' => 'Hello, :name!',
];
First Translation
Inject the Translator into a controller or service:
use Yiisoft\Translator\Translator;
public function __construct(private Translator $translator) {}
public function greet(string $name): string
{
return $this->translator->translate('greeting', ['name' => $name]);
}
Call it in a route:
Route::get('/greet/{name}', [YourController::class, 'greet']);
Language Switching Set the locale dynamically (e.g., via middleware):
$translator->setLocale('es'); // Switch to Spanish
Hierarchical Structure: Use nested arrays for modular translations (e.g., resources/lang/en/auth.php):
return [
'login' => [
'title' => 'Sign In',
'submit' => 'Login',
],
];
Translate with:
$this->translator->translate('auth.login.title');
Fallbacks: Define a fallback locale in config (e.g., en):
$translator->setFallbackLocale('en');
Placeholders: Use named placeholders (e.g., :name, :count):
$this->translator->translate('greeting', ['name' => 'John']);
Translation file:
'greeting' => 'Hello, :name! You have :count messages.',
Pluralization: Support plural rules (e.g., resources/lang/en/rules.php):
return [
'messages' => [
'{0} No messages',
'{1} One message',
'[2,Inf] {0} messages',
],
];
Usage:
$this->translator->translate('messages', [], 5);
Service Binding: Bind the translator to Laravel’s container in AppServiceProvider:
public function register()
{
$this->app->singleton(Translator::class, function ($app) {
return new Translator(
new FileMessageSource('resources/lang'),
$app['config']['app.locale']
);
});
}
View Composers: Load translations for views:
public function compose(View $view)
{
$view->with('translations', $this->translator->getCatalog());
}
Form Requests: Validate with translated messages:
public function messages()
{
return [
'required' => trans('validation.required'),
];
}
$translator->setCatalogCache(new FileCache('runtime/cache/translations'));
MessageSource for dynamic translations:
class DatabaseMessageSource implements MessageSource
{
public function getMessage(string $category, string $message, array $params = []): string
{
// Fetch from DB and return translated message
}
}
Missing Fallback Locale
$translator->setFallbackLocale('en');
Case Sensitivity in Keys
// Fails if defined as 'welcome' but called as 'Welcome'
$this->translator->translate('Welcome');
Circular Dependencies in Plural Rules
{0} or {1}.File Permissions
runtime/cache directory is writable:
chmod -R 775 runtime/cache
Check Loaded Catalog Dump the current catalog to verify translations are loaded:
dd($this->translator->getCatalog());
Validate Translation Files
Use PHP’s var_dump to inspect loaded files:
var_dump(require 'resources/lang/en/messages.php');
Locale-Specific Issues
Use Translation Keys in Code
translator->translate() or the trans() helper (if integrated).Leverage Laravel’s trans() Helper
If using Laravel, alias the translator for convenience:
// In AppServiceProvider
app()->bind('trans', function () {
return app(Translator::class);
});
Usage:
trans('messages.welcome');
Environment-Specific Translations
Override translations per environment (e.g., resources/lang/en/dev.php for development-specific messages).
Validation Messages Extend Laravel’s validator with custom translated messages:
Validator::extend('custom_rule', function ($attribute, $value, $parameters, $validator) {
return $value > 0;
});
Validator::replacer('custom_rule', function ($message, $attribute, $rule, $parameters) {
return trans('validation.custom_rule', ['attribute' => $attribute]);
});
Performance Optimization
$translator->setCatalogCache(new FileCache('runtime/cache/translations', 3600)); // 1-hour cache
$translator->setCatalogCache(null);
Testing Translations
public function testTranslations()
{
$translator = new Translator(new FileMessageSource('tests/lang'), 'en');
$this->assertEquals('Welcome!', $translator->translate('welcome'));
}
Extending with Custom Functions
$translator->setCustomFunction('format_date', function ($date) {
return trans('dates.format', ['date' => $date->format('F j, Y')]);
});
Usage:
$this->translator->translate('custom.format_date', ['date' => now()]);
How can I help you explore Laravel packages today?