Symfony 路由:何时/何处设置 _locale 属性

Symfony Routing: When / where is _locale attribute set

我正在使用 Symfony 2.8 开发一个 WebApp 项目。我想在页面中添加不同的语言。根据用户的语言环境,所有 routes/URLs 都应从 /some/url 更改为 /locale/some/url, e.g./en/some/url`。

在添加语言之前,主路由文件如下所示:

<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">

    <!-- Routes for the public pages -->
    <import
        resource="@AppBundle/Resources/config/routing/public_routes.xml" />

    ...
</routes>

并且 public_routes.xml 具有以下内容:

<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">

    <route id="home" path="" methods="GET">
        <default key="_controller">AppBundle:Default:home</default>
    </route>

    <route id="public_price" path="/price" methods="GET">
        <default key="_controller">AppBundle:Default:price</default>
    </route>

    <route id="public_about" path="/about" methods="GET">
        <default key="_controller">AppBundle:Default:about</default>
    </route>

    ...
</routes>

到目前为止,很简单。现在我在路由中添加了以下内容以添加本地化:

<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">

    <!-- Home route to redirect to the right route -->
    <route id="home_redirect" path="" methods="GET">
        <default key="_controller">AppBundle:Default:home</default>
    </route>

    <!-- Routes for the localized public pages -->
    <import
        resource="@AppBundle/Resources/config/routing/public_routes.xml"
        prefix="/{_locale}" />

    ...
</routes>

因此 public 页面的导入扩展了 prefix="/{_locale}",它会自动将当前语言环境添加到来自 public_routes.xml 的所有路由。

这很好用。我现在可以导航到 /en/en/price/en/about

但是仍然必须是 "empty" 路线。否则域本身将不再有有效路由。 (BTWpath=""path="/"有区别吗?)

这是由新的 home_redirect 路由及其控制器处理的:

public function homeAction(Request $request) {
    $locale = $request->attributes->get('_locale');
    if (!$locale) {
        // Try to get the preferred language from the request
        $locale = MySettings::getLanguage($request);               
        return $this->redirectToRoute('home', array('_locale' => $locale));
    } elseif (!MySettings::checkLanguage($locale)) {
        // Invalid Locale...
        throw $this->createNotFoundException();
    }

    return $this->render('AppBundle:Default:homepage.html.twig');
}

因此,如果为请求设置了 _localehomeAction 会检查该语言是否受支持或抛出错误。如果未设置 _localehomeAction 会尝试从请求中获取当前的 _locale(例如,从浏览器接受的语言)。

问题: 上述解决方案适用于 / 的所有调用。在这种情况下 _locale 未设置,因此调用被重定向到 /someLocale/,例如`/zh/.

但是:对/somepage的所有调用也由homeAction处理。这是因为 somepage 被解释为语言环境!因此 homeAction 被调用为 $request->attributes->get('_locale') == 'somepage'。这显然行不通。

因此,如果有人呼叫旧的 URL /about 而不是新的 /en/about,路由系统会将此呼叫与路由 home 和 _locale about 并且找不到该页面。

Symfony 从 URL 中提取 _locale 的确切位置?是否可以拦截这种提取并使其更智能一些?例如。忽略所有长度超过 2 个字母的 "locales"?

谢谢!

简单地利用路由定义

requirementsdefault属性

因此您可以为所有路线设置{_locale}

  requirements:
    _locale: fr|en
  defaults: { _locale: fr}

在此 yml 示例中,如果未提供 _locale,则默认为 "fr",例如 / 并且由于要求 about 不会匹配为 _locale