Недавно столкнулся с интересной задачей и, думаю, что решение может оказаться кому-то полезным.

Наш сайт использует локализацию + региональность и соответственно ссылки имеют вид:
/ru/minsk/aaa
/by/minsk/aaa
Задача убрать дефолтную локаль(ru) так чтобы все url приняли вид:
/minsk/aaa
/by/minsk/aaa
Stackoverflow дает два варианта:
1) В описании роута в requirements в _locale добавить пустое значение: _locale: ru|by -> _locale: |ru|by
Но в этом подходе url принимает вид: //minsk/aaa, а 2 слеша нам не нужны. Да и нужно убирать локаль из router->context, чтобы сгенерировать url.
2) В аннотациях к контроллеру прописать 2 разных роута.

* @Route("/{region}/{other}", name="route", ...)
* @Route("/{_locale}/{region}/{other}", name="route-with-locale", ...)

Но здесь тоже встает вопрос: «Как генерировать url и какой роут выбирать?». Да и для всех контроллеров придется такие аннотации писать.

Решение состоит из 2х этапов: обработка входящих параметров путем подмены контроллера и генерация ссылок на странице.

Настраивать будем все ресурсы относящиеся к префиксу "/{_locale}/{region}" и которые хранятся в одной папке и описаны в app_web_common:

app_web_common:
    resource: "@AppBundle/Controller/Web/"
    type:     annotation
    prefix:   /{_locale}/{region}
    requirements:
        _locale: ru|by
        region: minsk|brest

1. Обработка входящих параметров
Все url вида "/by/minsk/aaa" будут обрабатываться по обычной схеме через «app_web_common». А урлы, не содержащие локаль, через отдельный роут:

app_web_region_no_locale:
    path:   /{region}/{catchAll}
    defaults:
        _locale: ru|by
        _controller: AppBundle:NoLocale:region
    requirements:
        region: minsk|brest
        catchAll: ".+"

Но вызов контроллера производиться не будет(кроме 404), тк мы перенаправим вызов к другому контроллеру в KernelEvents::CONTROLLER. Поэтому создаем EventListener со своим обработчиком:

    public function matchingWebController(FilterControllerEvent $event)
    {
        $request = $event->getRequest();
        $route = $request->get('_route');
        $pathInfo = $request->getPathInfo();

        if ($route == 'app_web_region_no_locale') {
            $this->setupLocale($this->defaultLocale, $request);
            $path = "/{$this->defaultLocale}{$pathInfo}";

           $data = $this->router->match($path);

           $request->attributes->replace($data);
           unset($data['_controller']);
           $request->attributes->set('_route_params', $data);

           $controller = $this->resolver->getController($request);
           $event->setController($controller);
        }
    }

Если кратко, то:
— берем текущий путь
— добавляем в начало строки префикс локали
— ищем совпадения для нового урла
— заменяем данные в реквесте
— заменяем контроллер

Еще нужно запретить переход по ссылке содержащей дефолтную локаль. Для этого в этом же классе добавим еще один обработчик, но уже KernelEvents::REQUEST:

    public function redirectFromDefaultLocale(GetResponseEvent $event)
    {
        $request = $event->getRequest();
        $queryString = $request->getQueryString();
        $pathInfo = $request->getPathInfo();
        $pathInfoArr = explode('/', $pathInfo);
        $queryString = $queryString ? "?" . $queryString : '';

        // if route contains default locale
        if (isset($pathInfoArr[1]) && $pathInfoArr[1] == $this->defaultLocale) {
            unset($pathInfoArr[1]);
            $this->setupLocale($this->defaultLocale, $request);
            $response = new RedirectResponse($pathInfo . $queryString);
            $event->setResponse($response);
        }
    }

Но все это действительно если есть префикс ввиде {region} как в статье. Но как быть если нет этого префикса?
/ru/aaa
/by/aaa
а нужно:
/aaa
/by/aaa
Здесь все зависит от приложения:
1) можно точно также все перенаправить через app_web_*_no_locale, но уже без региона.
2) Конкретно в нашем приложении есть еще и урлы без локали и региона (/aaa), поэтому мы сначала обрабатываем их, а затем если не находим, то применяем логику из «matchingWebController()»

2. Генерация ссылок
Для этого нужно переопределить класс UrlGenerator.
В параметры добавляем:

    router.class: AppBundle\Routing\Router\Router
    router.options.generator_base_class: AppBundle\Routing\Generator\UrlGenerator\UrlGenerator

И содержимое классов:

class Router extends BaseRouter implements ContainerAwareInterface
{
    private $container;

    public function __construct(ContainerInterface $container, $resource, array $options = array(), RequestContext $context = null)
    {
        parent::__construct($container, $resource, $options, $context);
        $this->setContainer($container);
    }

    public function getGenerator()
    {
        $generator = parent::getGenerator();

        $generator->setContainer($this->container);
        return $generator;
    }

    public function setContainer(ContainerInterface $container = null)
    {
        $this->container = $container;
    }
}

class UrlGenerator extends BaseUrlGenerator implements ContainerAwareInterface
{
    /**
     * @var ContainerInterface
     */
    private $container;

    protected function doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens, array $requiredSchemes = array())
    {
        $defaultLocale = $this->container->getParameter('default_locale');
        // здесь все содержимое родительского метода parent::doGenerate
        // ....
        // заменяем одну строчку $url = $token[1].$mergedParams[$token[3]].$url; на 
        if (!($token[3] == '_locale' && $mergedParams[$token[3]] == $defaultLocale)) {
            $url = $token[1].$mergedParams[$token[3]].$url;
        }
        // ....
    }

    /**
     * @param ContainerInterface|null $container
     */
    public function setContainer(ContainerInterface $container = null)
    {
        $this->container = $container;
    }
}


Если кратко, то если в полученном урле есть дефолтная локаль, то ее удаляем.

Вот и всё.