Symfony 4 中实现本地化语言切换需定义路由和控制器存储 locale 到 session 或 cookie,配置框架启用 locale 解析,并通过 LocaleSubscriber 事件订阅器在请求时统一设置 locale,最后在 Twig 模板中生成切换链接。

在 Symfony 4 中实现本地化语言切换,核心是修改用户会话或请求中的 locale,并确保后续请求能正确识别该语言。控制器中不直接“切换语言”,而是接收语言参数、验证、存储(如到 session 或 cookie),再重定向回原页面或首页。
1. 定义语言切换路由和控制器动作
在 config/routes.yaml 中添加路由:
switch_locale: path: /switch/{locale} controller: App\Controller\LocaleController::switch requirements: locale: en|zh|fr|es创建控制器 src/Controller/LocaleController.php:
namespace App\Controller;
<p>use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Routing\Annotation\Route;</p><p>class LocaleController
{
/**</p><ul><li><p>切换用户 locale 并重定向回上一页
*/</p><h1>[Route('/switch/{locale}', name: 'switch_locale')]</h1><p>public function switch(string $locale, Request $request, SessionInterface $session): RedirectResponse
{
// 白名单校验(防止任意 locale 注入)
$availableLocales = ['en', 'zh', 'fr', 'es'];
if (!in_array($locale, $availableLocales, true)) {
$locale = 'en';
}</p><p>// 存入 session(优先级高于 URL 参数和 Accept-Language)
$session->set('_locale', $locale);</p><p>// 可选:存入 cookie 延长生命周期(如 30 天)
$response = new RedirectResponse($request->headers->get('referer', '/'));
$response->headers->setCookie(
\Symfony\Component\HttpFoundation\Cookie::create('_locale', $locale, time() + 2592000)
);</p><p>return $response;
}
}2. 配置框架自动识别 locale
在 config/packages/framework.yaml 中启用 locale 解析:
# 自动从 session、cookie、URL、Accept-Language 推导 locale
# 注意:顺序决定优先级(越靠前越优先)
translator:
fallbacks: ['en']
paths: ['%kernel.project_dir%/translations']
# 强制使用 session 中的 _locale(推荐)
default_locale: en
# 不要设为 null;保持默认值,由 LocaleSubscriber 控制</font>3. 使用事件订阅器统一设置 request locale(推荐)
创建 src/EventSubscriber/LocaleSubscriber.php,确保每次请求都正确设置 locale:
namespace App\EventSubscriber;
<p>use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpFoundation\Session\SessionInterface;</p><p>class LocaleSubscriber implements EventSubscriberInterface
{
private $defaultLocale;</p><pre class='brush:php;toolbar:false;'>public function __construct(string $defaultLocale = 'en')
{
$this->defaultLocale = $defaultLocale;
}
public function onKernelRequest(RequestEvent $event): void
{
$request = $event->getRequest();
$session = $request->getSession();
// 1. 优先从 session 获取
if ($session instanceof SessionInterface && $session->has('_locale')) {
$locale = $session->get('_locale');
}
// 2. 其次检查 cookie(与控制器写入一致)
elseif ($request->cookies->has('_locale')) {
$locale = $request->cookies->get('_locale');
}
// 3. 最后 fallback 到默认或 Accept-Language(可选)
else {
$locale = $this->defaultLocale;
}
$request->setLocale($locale);
}
public static function getSubscribedEvents(): array
{
return [
KernelEvents::REQUEST => [['onKernelRequest', 20]],
];
}}
4. 模板中生成语言切换链接
在 Twig 模板(如 templates/base.html.twig)中添加切换链接:
<ul class="lang-switcher">
<li><a href="{{ path('switch_locale', {locale: 'en'}) }}">English</a></li>
<li><a href="{{ path('switch_locale', {locale: 'zh'}) }}">中文</a></li>
<li><a href="{{ path('switch_locale', {locale: 'fr'}) }}">Français</a></li>
</ul>注意:不要在链接中硬编码 referer —— 重定向逻辑已在控制器中通过 referer 头自动处理,更安全可靠。


















