Symfony 5 - 基于浏览器语言的网站翻译后重定向

Symfony 5 - Redirection after website translation based on browser language

我目前正在开发 symfony 5,我已经将我的网站完全翻译成多种语言。我有一个 select 语言的按钮,但我希​​望网站的默认语言是用户的语言(更准确地说是他的浏览器)。 目前我找到了一个解决方案,但它根本不是最优的。

我所做的是,在我的索引中,我检查用户之前是否已经浏览过该站点,如果没有,我将他重定向到 change_locale 路由,该路由会将相关语言作为参数(只有第一次访问才进入条件)

public function index(Request $request): Response
{
    // If this is the first visit to the site, the default language is set according to the user's browser language
    if (!$request->hasPreviousSession()) {
        return $this->redirectToRoute('change_locale', ['locale' => strtolower(str_split($_SERVER['HTTP_ACCEPT_LANGUAGE'], 2)[0])]);
    }

    return $this->render('accueil/index.html.twig');
}

这里我只是在session中注册了变量来改变语言。 而我的问题就在这一步之后。当用户简单地点击站点上的语言更改按钮时,他会返回到上一页(他没有输入 if)。 但是,如果他是第一次来该站点,他会从索引中重定向,当他来到这条路线时,他会输入条件 if (!$request->hasPreviousSession()) 并且...这就是问题所在。因为如果他之前没有访问过任何东西,我无法将他重定向到他正在访问的页面。

 /**
 * @Route("/change-locale/{locale}", name="change_locale")
 */
public function changeLocale($locale, Request $request)
{
    $request->getSession()->set('_locale', $locale); // Storing the requested language in the session

    // If it's the first page visited by the user
    if (!$request->headers->get('referer')) {
        return $this->redirectToRoute('index');
    }

    // Back to the previous page
    return $this->redirect($request->headers->get('referer'));
}

所以我尝试从我的 change_locale 路由中删除此条件,并找到一种方法在请求的 header 中添加指向上一页的属性 'referer' 。 在执行 redirectToRoutechange_locale.

之前,我可以在我的索引中执行此操作

不要使用重定向来设置语言环境。

Symfony 关于 How to Work with the User’s Locale has a great suggestion: use a custom event listener instead. Also read Making the Locale “Sticky” during a User’s Session 的文档。

您可以使用文档中的这个示例:

class LocaleSubscriber implements EventSubscriberInterface
{
    private $defaultLocale;

    public function __construct(string $defaultLocale = 'en')
    {
        $this->defaultLocale = $defaultLocale;
    }

    public function onKernelRequest(RequestEvent $event)
    {
        $request = $event->getRequest();
        if (!$request->hasPreviousSession()) {
            return;
        }

        // try to see if the locale has been set as a _locale routing parameter
        if ($locale = $request->attributes->get('_locale')) {
            $request->getSession()->set('_locale', $locale);
        } else {
            // if no explicit locale has been set on this request, use one from the session
            $request->setLocale($request->getSession()->get('_locale', $this->defaultLocale));
        }
    }

    public static function getSubscribedEvents()
    {
        return [
            // must be registered before (i.e. with a higher priority than) the default Locale listener
            KernelEvents::REQUEST => [['onKernelRequest', 20]],
        ];
    }
}

还有一些免费建议:在 onKernelRequest 方法中,您可以使用 HTTP_ACCEPT_LANGUAGE 来查看用户可能使用的语言,但是(与所有其他用户输入一样!)它可能不可用或不可靠.您可能希望使用来自用户 IP 地址或其他逻辑的信息。