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>
-
切换用户 locale 并重定向回上一页 */
[Route('/switch/{locale}', name: 'switch_locale')]
public function switch(string $locale, Request $request, SessionInterface $session): RedirectResponse { // 白名单校验(防止任意 locale 注入) $availableLocales = ['en', 'zh', 'fr', 'es']; if (!in_array($locale, $availableLocales, true)) { $locale = 'en'; }
// 存入 session(优先级高于 URL 参数和 Accept-Language) $session->set('_locale', $locale);
// 可选:存入 cookie 延长生命周期(如 30 天) $response = new RedirectResponse($request->headers->get('referer', '/')); $response->headers->setCookie( \Symfony\Component\HttpFoundation\Cookie::create('_locale', $locale, time() + 2592000) );
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 控制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)中添加切换链接:
注意:不要在链接中硬编码 referer —— 重定向逻辑已在控制器中通过 referer 头自动处理,更安全可靠。











