我需要能够定义/{_locale}
部分是可选的路线。这意味着我需要这些URL使用相同的控制器:
my-domain.com/
(区域设置将由请求侦听器设置)my-domain.com/[any-locale]/
同样如下:
my-domain.com/my-page
(区域设置将由请求侦听器设置)my-domain.com/[any-locale]/my-page
问题是我无法定义两个类@Route
注释,因为Symfony无效/接受它;而且我不能复制我的控制器类中的每一条路线,因为会有很多而且会非常糟糕!
我试过只有一个类注释,但我无法让它工作。以下是我的尝试:
/**
* @Route("/{_locale}", requirements={"_locale": "(\w{2,3})?"})
*/
class DefaultController extends Controller {
/**
* @Route("/")
* @param Request $request
* @return Response
*/
public function indexAction(Request $request) {
return new Response('index '.$request->getLocale());
}
/**
* @Route("/my-page")
* @param Request $request
* @return Response
*/
public function testAction(Request $request) {
return new Response('test '.$request->getLocale());
}
}
结论:
my-domain.com//my-page
才有效)我认为问题是主要的斜线,所以我尝试了这个:
/**
* @Route("{slash_and_locale}", requirements={"slash_and_locale": "\/?(\w{2,3})?"}, defaults={"slash_and_locale": ""})
*/
class DefaultController extends Controller { // ...
结论:
我见过这个(old) question但是还没有提交正确答案:(
有意见的人吗? 真的很有帮助,谢谢!
答案 0 :(得分:1)
这是我最终决定做的事情:
RoutingExtension
或path
方法扩展Symfony的url
以自动选择正确的路线。这是我的双路径配置的样子(注意双路线,第二路线有+locale
后缀):
<?php
// src\AppBundle\Controller\DefaultController.php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
class DefaultController extends Controller {
/**
* @Route("/", name="front_index")
* @Route("/{_locale}/", name="front_index+locale", requirements={"_locale": "\w{2,3}"})
* @return Response
*/
public function indexAction() {
return $this->render('test/domain-translation.html.twig');
}
}
这是我的RoutingExtension
重载:
<?php
// src\AppBundle\Twig\LocaleRoutingExtension.php
namespace AppBundle\Twig;
use AppBundle\Document\Domain;
use Symfony\Bridge\Twig\Extension\RoutingExtension;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
class LocaleRoutingExtension extends RoutingExtension {
/** @var ContainerInterface */
protected $container;
/** @var Domain */
protected $domain;
/** @var Request */
protected $request;
public function setContainer(ContainerInterface $container) {
$this->container = $container;
$this->domain = $this->container->get('app.domain_service')->getDomain();
$this->request = $this->container->get('request_stack')->getMasterRequest();
}
protected function processNameAndParameters($name, $parameters) {
$nameWithLocale = $name . '+locale';
$routes = $this->container->get('router')->getRouteCollection();
$route = $routes->get($nameWithLocale);
if (array_key_exists('no-locale-filter', $parameters) && $parameters['no-locale-filter']) {
unset($parameters['no-locale-filter']);
return array('name' => $name, 'parameters' => $parameters);
}
if (isset($this->domain) && $this->domain->hasMultipleLocales() && isset($route)) {
$name = $nameWithLocale;
$locale = null;
if (!array_key_exists('_locale', $parameters)) {
if (isset($this->request)) {
$locale = $this->request->getLocale();
} else {
$locale = $this->domain->getDefaultLocale();
}
}
$parameters['_locale'] = $locale;
}
return array('name' => $name, 'parameters' => $parameters);
}
public function getPath($name, $parameters = array(), $relative = false) {
$processed = $this->processNameAndParameters($name, $parameters);
return parent::getPath($processed['name'], $processed['parameters'], $relative);
}
public function getUrl($name, $parameters = array(), $schemeRelative = false) {
$processed = $this->processNameAndParameters($name, $parameters);
return parent::getUrl($processed['name'], $processed['parameters'], $schemeRelative);
}
}
我希望这有帮助!
答案 1 :(得分:0)
我在我的项目(yml)中执行此操作
language_selection:
path: /{locale}/{path}
defaults: { _controller: PurchaserBundle:Home:langSelection, path: "" }
requirements:
path: .+
locale: es|ca|en
在控制器中:
public function langSelectionAction($locale, $path)
{
if (in_array($locale, array('es', 'en', 'ca'))) {
return $this->redirect('/' . $path);
}
$this->create404NotFound();
}
这可能是解决问题的基本方法,但有效。所有“默认”路由都有效,如果您使用任何语言环境前缀访问该站点,您的侦听器将更改语言,并且此控制器将以当前语言重定向到正确的路由。
我希望它有所帮助。
答案 2 :(得分:0)
我找到了一种仅通过扩展自定义routingComponent的方法。这样,每个与路由不匹配的网址都将被重试,并使用默认语言环境作为前缀网址
<?php
namespace App\Component;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\Matcher\UrlMatcher as BaseUrlMatcher;
class UrlMatcher extends BaseUrlMatcher
{
public function match($pathinfo)
{
try {
return parent::match($pathinfo);
} catch (ResourceNotFoundException $exception) {
$url = sprintf('/%s%s', 'en', $pathinfo);
return parent::match($url);
}
}
}
在参数中设置新的urlMatcher:
parameters:
# UrlMatcher
router.options.matcher.cache_class: ~
router.options.matcher_class: App\Component\UrlMatcher