Localization Service Provider
Translator, locale resolver and file-based language loading services.
Responsibility
Registers FileTranslator, TranslatorInterface, LocaleResolver, LocaleResolverInterface, alias translator and alias locale.resolver. These services provide file-based translations, runtime locale override and locale resolution used by controllers, views, validation, pagination, upload and app messages.
Localization config
Application localization config lives in app/Config/Localization.php. It defines default/fallback locale, supported locales and localized URL settings used by routing URL strategy.
<?php
declare(strict_types=1);
use Lemonade\Framework\Support\Env;
return [
'default_locale' => Env::string('APP_LOCALE', 'cs'),
'fallback_locale' => Env::string('APP_FALLBACK_LOCALE', 'cs'),
'supported_locales' => Env::list('APP_SUPPORTED_LOCALES', ['cs', 'en']),
'url' => [
'enabled' => Env::bool('APP_LOCALIZED_URLS_ENABLED', true),
'include_default_locale' => Env::bool('APP_INCLUDE_DEFAULT_LOCALE_IN_URL', false),
'localized_route_name_prefix' => Env::string('APP_LOCALIZED_ROUTE_PREFIX', 'localized.'),
'locale_parameter' => Env::string('APP_LOCALE_URL_PARAMETER', 'locale'),
'route_prefix' => Env::string('APP_LOCALE_ROUTE_PREFIX', '/{locale}'),
],
];
Language files
FileTranslator loads framework language files from framework/src/Language/{locale}/{group}.php and app files from app/Language/{locale}/{group}.php. App files overlay framework lines with the same keys.
// app/Language/en/messages.php
return [
'welcome' => 'Welcome, {name}.',
'saved' => 'Saved successfully.',
];
// framework/src/Language/en/validation.php
return [
'required' => '{field} is required.',
'valid_email' => '{field} must be a valid email.',
];
Translator usage
Inject TranslatorInterface in services. get() reads group.key; keys without a dot use group messages. Replacements use {name} placeholders.
use Lemonade\Framework\Localization\TranslatorInterface;
final class ExampleService
{
public function __construct(
private readonly TranslatorInterface $translator,
) {}
public function message(): string
{
return $this->translator->get('validation.required', [
'field' => 'email',
]);
}
}
Locale runtime
TranslatorInterface::setLocale() sets a runtime locale override for the translator instance. LocaleResolverInterface::resolve() chooses runtime translator locale first, then localization.default_locale, then localization.fallback_locale; configured locales must be present in localization.supported_locales.
use Lemonade\Framework\Localization\LocaleResolverInterface;
use Lemonade\Framework\Localization\TranslatorInterface;
$translator = $container->get(TranslatorInterface::class);
$translator->setLocale('en');
$locale = $container->get(LocaleResolverInterface::class)->resolve();
Fallback behavior
get() tries the resolved locale first, then fallback locale. If the key is missing in both, it returns the raw key string. group() merges fallback group lines with resolved locale lines, and all() returns all discovered groups for the resolved locale.
Controller usage
Framework controllers expose the translator through $this->translator() and translation lookup through $this->trans(). Keep controller examples tied to translation keys, not hard-coded rendered copy.
$title = $this->translator()->get('messages.welcome', ['name' => 'Ada']);
$label = $this->trans('validation.required', ['field' => 'email']);
View usage
ViewHelpers exposes translations through $helpers->lang(), $helpers->langGroup(), $helpers->langAll() and $helpers->currentLocale(). Use e() when printing translated text into HTML.
<?= e($helpers->lang('messages.welcome', ['name' => 'Ada'])) ?>
<?= e($helpers->lang('validation.required', ['field' => 'email'])) ?>
Framework messages
Validation uses validation.* lines, pagination uses pagination.* lines and upload validators use upload.* lines through TranslatorInterface. Applications can add their own language groups under app/Language/{locale} and reference them with the same group.key syntax.
Localized routes
LocalizationServiceProvider does not register routes, but its LocaleResolverInterface and localization config are used by routing URL generation. UrlGenerator::localizedRoute() works with localized route settings from localization.url.*.