yiisoft/translator
Yii Translator provides a clean abstraction for message translation in PHP apps, with support for multiple message categories, locales, and fallback logic. Integrates with Yii components to load, format, and return translated strings consistently across your project.
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?