Installation
composer require php-translation/translator
Register the service provider in config/app.php:
'providers' => [
PHPTranslation\Translator\TranslatorServiceProvider::class,
],
Configuration Publish the config file:
php artisan vendor:publish --provider="PHPTranslation\Translator\TranslatorServiceProvider" --tag="config"
Update config/translator.php with your locales and paths:
'locales' => ['en', 'es', 'fr'],
'paths' => [base_path('resources/lang')],
First Use Case
Create a translation file (e.g., resources/lang/en/messages.php):
return [
'welcome' => 'Welcome, :name!',
'errors' => [
'not_found' => 'The resource you requested could not be found.',
],
];
Use in a controller:
use PHPTranslation\Translator\Translator;
public function showWelcome(Translator $translator)
{
return $translator->trans('messages.welcome', ['name' => 'John']);
}
Language Switching Set the locale dynamically:
app('translator')->setLocale('es');
Or use middleware to detect language from Accept-Language header or URL:
public function handle($request, Closure $next)
{
$locale = $request->header('Accept-Language') ?: 'en';
app('translator')->setLocale($locale);
return $next($request);
}
Basic Translation
$translator->trans('messages.welcome', ['name' => 'John']);
// Output: "Welcome, John!"
Pluralization
$translator->transChoice('messages.items', $count, ['count' => $count]);
// Example in `messages.php`:
// return ['items' => '{count} item|{count} items'];
Fallback Logic
Configure fallbacks in config/translator.php:
'fallbacks' => [
'es' => ['ca'],
'fr' => ['en'],
],
If es.messages.welcome is missing, it falls back to ca.messages.welcome, then en.messages.welcome.
Custom Loaders
Register a custom loader in config/translator.php:
'loaders' => [
'json' => PHPTranslation\Translator\Loader\JsonLoader::class,
'database' => App\Loaders\DatabaseLoader::class,
],
Implement LoaderInterface for database/API sources:
class DatabaseLoader implements LoaderInterface {
public function load($locale, $group, $file) {
return DB::table('translations')
->where('locale', $locale)
->where('group', $group)
->where('key', $file)
->pluck('value', 'key')
->toArray();
}
}
Interpolation Use placeholders in translations:
// In messages.php
'greeting' => 'Hello, :name! Today is :date.',
// In code
$translator->trans('messages.greeting', [
'name' => 'John',
'date' => now()->format('Y-m-d'),
]);
Facade Usage Create a facade for cleaner syntax:
// app/Facades/Translator.php
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class Translator extends Facade {
protected static function getFacadeAccessor() {
return 'translator';
}
}
Use in Blade or controllers:
Translator::trans('messages.welcome');
Middleware for Language Detection
namespace App\Http\Middleware;
use Closure;
class SetLocale {
public function handle($request, Closure $next) {
$locale = $request->segment(1) ?: config('app.locale');
app('translator')->setLocale($locale);
return $next($request);
}
}
Register in app/Http/Kernel.php:
protected $middlewareGroups = [
'web' => [
// ...
\App\Http\Middleware\SetLocale::class,
],
];
View Localization
Use @lang in Blade:
@lang('messages.welcome', ['name' => $user->name])
Or create a custom directive:
Blade::directive('t', function ($expression) {
return "<?php echo trans($expression); ?>";
});
Usage:
@t("messages.welcome")
Validation Messages Localize validation errors:
$validator = Validator::make($request->all(), [
'email' => 'required|email',
]);
$validator->setCustomMessages([
'email.required' => trans('validation.email.required'),
]);
Caching Translations Use Laravel’s cache to optimize performance:
$translator->setCache(function () {
return Cache::remember('translations', now()->addHours(1), function () {
return $this->loadTranslations();
});
});
Missing Translation Files
trans() returns the key instead of a value if the file or key is missing.config/translator.php:
'strict' => true,
Or check existence first:
if ($translator->has('messages.welcome')) {
$translator->trans('messages.welcome');
}
Locale Not Found
config/translator.php throws an exception.try {
$translator->setLocale('pt-BR');
} catch (\InvalidArgumentException $e) {
$translator->setLocale('en');
}
File Path Issues
paths in config/translator.php and ensure files are in the correct structure:
resources/
└── lang/
├── en/
│ └── messages.php
└── es/
└── messages.php
Interpolation Errors
:name remains as-is).:name not {name} unless using transChoice).Loader Conflicts
config/translator.php and implements LoaderInterface.Case Sensitivity
messages.Welcome vs. messages.welcome).Fallback Not Working
config/translator.php and ensure the fallback locales are defined.Performance with Large Catalogs
Log Missing Keys Add a listener to log missing translations:
$translator->setMissingListener(function ($locale, $group, $key) {
Log::warning("Missing translation: {$locale}.{$group}.{$key}");
});
Check Loaded Translations Dump the loaded translations for debugging:
dd($translator->getLoader()->getCatalogue($locale)->all());
Validate Translation Files Use a JSON/YAML linter to catch syntax errors before runtime.
Test Locale Switching Verify locale switching works as expected:
$translator->setLocale('es');
assert($translator->getLocale() === 'es');
Default Locale
config/translator.php under 'locale'. Ensure it matches your app’s default.Loader Priorities
config/translator.php. The first loader to return a translation wins.**
How can I help you explore Laravel packages today?