Core

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.yaml. YAML remains only the application-facing input format; the framework still maps it into typed LocalizationConfigDefinition and resolves runtime LocalizationConfig for URL strategy and translator services.

example.php
module: localization
config:
  default_locale:
    $env: APP_LOCALE
    type: string
    default: cs
  fallback_locale:
    $env: APP_FALLBACK_LOCALE
    type: string
    default: cs
  supported_locales:
    $env: APP_SUPPORTED_LOCALES
    type: list
    default:
      - cs
      - en
  url:
    enabled:
      $env: APP_LOCALIZED_URLS_ENABLED
      type: bool
      default: true
    include_default_locale:
      $env: APP_INCLUDE_DEFAULT_LOCALE_IN_URL
      type: bool
      default: false
    localized_route_name_prefix:
      $env: APP_LOCALIZED_ROUTE_PREFIX
      type: string
      default: localized.
    locale_parameter:
      $env: APP_LOCALE_URL_PARAMETER
      type: string
      default: locale
    route_prefix:
      $env: APP_LOCALE_ROUTE_PREFIX
      type: string
      default: /{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.

example.php
// 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.

example.php
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 LocalizationConfig::$defaultLocale, then LocalizationConfig::$fallbackLocale; configured locales must be present in LocalizationConfig::$supportedLocales.

example.php
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.

example.php
$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.

example.php
<?= 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 LocalizationConfig::$url.