Installation:
composer require wdes/php-i18n-l10n
Ensure your composer.json meets the package’s requirements (PHP 8.1+, Twig 3.20+).
Basic Setup:
I18n extension in your TwigEnvironment:
use Wdes\phpI18nL10n\Twig\Extension\I18n as ExtensionI18n;
$twig->addExtension(new ExtensionI18n());
MoReader plugin:
use Wdes\phpI18nL10n\plugins\MoReader;
use Wdes\phpI18nL10n\Launcher;
$moReader = new MoReader();
$moReader->setTranslations(['key' => 'translated value']);
Launcher::setPlugin($moReader);
First Use Case:
{% trans %} tag in templates:
{% trans %}Homepage{% endtrans %}
echo Launcher::getPlugin()->translate('key');
Locale Configuration:
AppServiceProvider:
app()->setLocale('fr');
$request->setLocale('es');
$moReader->setTranslations([
'dashboard.title' => 'Tableau de bord',
'dashboard.welcome' => 'Bienvenue, {{ name }}!'
]);
$moReader->readFile(base_path('lang/fr/translations.mo'));
config/i18n.php:
'fallbacks' => [
'fr' => ['en'],
'es' => ['en'],
],
public function handle($request, Closure $next) {
$locale = app(\Wdes\phpI18nL10n\LocaleDetector::class)
->detect($request->header('Accept-Language'));
app()->setLocale($locale);
return $next($request);
}
Route::prefix('{locale}')->middleware('set.locale')->group(function () {
// ...
});
$twig->addFunction(new \Twig\TwigFunction(
'pluralize',
[Launcher::getPlugin(), 'pluralize']
));
Usage in Twig:
{{ pluralize('item', count) }}
{% trans %}messages.new{% endtrans %} {# Outputs "Nouveau message" in French #}
$formatter = new \Wdes\phpI18nL10n\Formatter('fr');
echo $formatter->formatDate(new \DateTime(), 'full');
echo $formatter->formatNumber(1000.5, 'currency');
public function register() {
$this->app->singleton(\Wdes\phpI18nL10n\I18n::class, function ($app) {
$moReader = new \Wdes\phpI18nL10n\plugins\MoReader();
$moReader->readFile(base_path('lang/'.app()->getLocale().'.mo'));
return new \Wdes\phpI18nL10n\I18n($moReader);
});
}
// app/Facades/I18nFacade.php
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class I18nFacade extends Facade {
protected static function getFacadeAccessor() {
return \Wdes\phpI18nL10n\I18n::class;
}
}
Usage:
use App\Facades\I18nFacade;
echo I18nFacade::translate('key');
use Wdes\phpI18nL10n\Validator;
$validator = new Validator();
$validator->validate('email', $request->input('email'), 'required|email', [
'email.required' => 'Le champ email est obligatoire.',
]);
Locale Mismatch:
app()->setLocale($request->getPreferredLanguage());
MO File Parsing Errors:
.mo files may crash the MoReader.validateMoFile() method or use the scripts/tools/validate-mo.sh tool.Twig Extension Conflicts:
trans filter if both are registered.$twig->addExtension(new ExtensionI18n('custom_'));
Usage in Twig:
{{ custom_trans('key') }}
Pluralization Edge Cases:
Pluralizer class or use the package’s addPluralRule() method:
Launcher::getPlugin()->addPluralRule('ar', [
'=0' => '{{count}} Item',
'=1' => '{{count}} Item',
'=2' => '{{count}} Items',
'many' => '{{count}} Items',
]);
Performance with Large MO Files:
MoReader instance:
$this->app->singleton(MoReader::class, function () {
$reader = new MoReader();
$reader->readFile($moFilePath);
return $reader;
});
dd(Launcher::getPlugin()->getTranslations());
public function handle($request, Closure $next) {
logger()->debug("Detected locale: {$request->getLocale()}");
return $next($request);
}
$twig = new \Twig\Environment($loader, [
'debug' => config('app.debug'),
]);
Custom Plugins:
Extend BasePlugin to support new translation sources (e.g., database):
class DbReader extends BasePlugin {
public function getTranslations() {
return DB::table('translations')->pluck('value', 'key')->toArray();
}
}
Formatter Extensions: Add custom formatters for niche locales:
$formatter = new \Wdes\phpI18nL10n\Formatter('ja');
$formatter->addRule('date.short', 'Y/m/d');
Locale-Specific Logic: Override default behavior per locale:
Launcher::getPlugin()->on('fr', function ($translator) {
$translator->setFallback('en');
});
Fallback Locales:
Ensure fallback locales are defined in config/i18n.php:
'fallbacks' => [
'fr_CA' => ['fr', 'en'],
'pt_BR' => ['pt', 'en'],
],
MO File Paths:
Use Laravel’s lang_path() helper for consistency:
$moReader->readFile(lang_path('fr/translations.mo'));
Twig Namespace Collisions:
If using both Laravel’s trans
How can I help you explore Laravel packages today?