4.6 KiB
4.6 KiB
Internationalization (i18n) Guide
Installation
composer require symfony/translation symfony/yaml
Core Implementation
LocaleConfig Value Object
// src/Core/Application/ValueObjects/LocaleConfig.php
final class LocaleConfig
{
public function __construct(
public readonly string $defaultLocale,
public readonly array $supportedLocales,
public readonly string $fallbackLocale,
) {}
public static function fromEnvironment(): self
{
return new self(
$_ENV['APP_LOCALE'] ?? 'en',
explode(',', $_ENV['APP_SUPPORTED_LOCALES'] ?? 'en,de,fr'),
$_ENV['APP_FALLBACK_LOCALE'] ?? 'en',
);
}
}
Translation Manager
// src/Core/Internalization/TranslationManagerInterface.php
interface TranslationManagerInterface
{
public function trans(string $key, array $parameters = [], ?string $domain = null): string;
public function setLocale(string $locale): void;
public function addResource(string $format, mixed $resource, string $locale, ?string $domain = null): void;
}
// src/Core/Internalization/TranslationManager.php
final class TranslationManager implements TranslationManagerInterface
{
private Translator $translator;
public function __construct(LocaleConfig $localeConfig)
{
$this->translator = new Translator($localeConfig->defaultLocale);
$this->translator->setFallbackLocales([$localeConfig->fallbackLocale]);
$this->translator->addLoader('yaml', new YamlFileLoader());
}
public function trans(string $key, array $parameters = [], ?string $domain = null): string
{
return $this->translator->trans($key, $parameters, $domain);
}
public function setLocale(string $locale): void
{
$this->translator->setLocale($locale);
}
public function addResource(string $format, mixed $resource, string $locale, ?string $domain = null): void
{
$this->translator->addResource($format, $resource, $locale, $domain);
}
}
Bootstrapper
// src/Core/Application/Bootstrapper/TranslationInitializer.php
class TranslationInitializer implements BootstrapperInterface
{
public function bootstrap(InflectableContainer $container): void
{
$container->set(LocaleConfig::class, LocaleConfig::fromEnvironment());
$container->bind(TranslationManagerInterface::class, TranslationManager::class, [LocaleConfig::class]);
$this->loadTranslationFiles($container);
}
private function loadTranslationFiles(InflectableContainer $container): void
{
$manager = $container->get(TranslationManagerInterface::class);
$config = $container->get(LocaleConfig::class);
// Load framework translations
foreach ($config->supportedLocales as $locale) {
$file = dirname(__DIR__, 4) . "/translations/{$locale}/messages.yaml";
if (file_exists($file)) {
$manager->addResource('yaml', $file, $locale, 'messages');
}
}
// Load module translations
foreach (glob(dirname(__DIR__, 3) . '/Modules/*/translations/*/messages.yaml') as $file) {
$parts = explode('/', $file);
$locale = $parts[count($parts) - 2];
$manager->addResource('yaml', $file, $locale, 'messages');
}
}
}
Helper Functions
// src/Core/Internalization/helpers.php
function trans(string $key, array $parameters = []): string {
global $container;
static $translator = null;
$translator ??= $container->get(TranslationManagerInterface::class);
return $translator->trans($key, $parameters);
}
function __(string $key, array $parameters = []): string {
return trans($key, $parameters);
}
Usage
Directory Structure
translations/en/messages.yaml
translations/de/messages.yaml
src/Modules/{Module}/translations/en/messages.yaml
Translation Files (YAML)
# translations/en/messages.yaml
welcome:
title: "Welcome to Foundation"
message: "Hello, %name%!"
user:
profile: "User Profile"
Controller Usage
class WelcomeController implements ControllerInterface
{
public function __construct(private readonly TranslationManagerInterface $translator) {}
public function index(): ResponseInterface
{
$title = $this->translator->trans('welcome.title');
$message = __('welcome.message', ['%name%' => 'John']);
// ...
}
}
Environment Configuration
APP_LOCALE=en
APP_SUPPORTED_LOCALES=en,de,fr
APP_FALLBACK_LOCALE=en