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" 路线。否则域本身将不再有有效路由。 (BTW:path=""
和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');
}
因此,如果为请求设置了 _locale
,homeAction
会检查该语言是否受支持或抛出错误。如果未设置 _locale
,homeAction
会尝试从请求中获取当前的 _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"?
谢谢!
简单地利用路由定义
的requirements
和default
属性
因此您可以为所有路线设置{_locale}
requirements:
_locale: fr|en
defaults: { _locale: fr}
在此 yml 示例中,如果未提供 _locale,则默认为 "fr",例如 /
并且由于要求 about
不会匹配为 _locale
我正在使用 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" 路线。否则域本身将不再有有效路由。 (BTW:path=""
和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');
}
因此,如果为请求设置了 _locale
,homeAction
会检查该语言是否受支持或抛出错误。如果未设置 _locale
,homeAction
会尝试从请求中获取当前的 _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"?
谢谢!
简单地利用路由定义
的requirements
和default
属性
因此您可以为所有路线设置{_locale}
requirements:
_locale: fr|en
defaults: { _locale: fr}
在此 yml 示例中,如果未提供 _locale,则默认为 "fr",例如 /
并且由于要求 about
不会匹配为 _locale