Как работать с локалью пользователя

Локаль текущего пользователя хранится в запросе и доступна через объект Request:

1
2
3
4
5
6
use Symfony\Component\HttpFoundation\Request;

public function indexAction(Request $request)
{
    $locale = $request->getLocale();
}

Чтобы установить локаль пользователя, вам может захотеться создать пользовательский слушатель событий так, чтобы он был установлен до того, как он понадобится любым другим частями системы (т.е. переводчику):

1
2
3
4
5
6
7
public function onKernelRequest(GetResponseEvent $event)
{
    $request = $event->getRequest();

    // некоторая логика для определения $locale
    $request->setLocale($locale);
}

Прочтите Making the Locale "Sticky" during a User's Session для более детальной информации о том, как сделать так, чтобы локаль пользователя "прилипла" к его сессии.

Note

Установка локали используя $request->setLocale() в контроллере - это слишком поздно для того, чтобы повлиять на переводчика. Либо установите локаль через слушателя (как выше), либо через URL (см. дальше), либо вызовите setLocale() напрямую в сервисе translator.

Смотрите раздел The Locale and the URL ниже, чтобы узнать о том, как установить локаль с помощью маршрутизации.

локаль и URL

Так как вы можете хранить локаль пользователя в сессии, может возникнуть соблазн использовать тот же URL для отображения ресурса на разных языках, основываясь на локали пользователя. Например, http://www.example.com/contact может отображать содержимое на английском для одного пользователя, и на французском - для другого. К сожалению, это нарушает основоположное правило Сети: определённый URL должен возвращать один и тот же ресурс невзирая на пользователя. Чтобы ещё больше усложнить проблему: какую версию содержимого нужно индексировать поисковыми системами?

Лучшей политикой будет включть локаль в URL. Это полностью поддерживается системой маршрутизации при использовании параметра _locale:

  • YAML
    1
    2
    3
    4
    5
    6
    # app/config/routing.yml
    contact:
        path:     /{_locale}/contact
        defaults: { _controller: AppBundle:Contact:index }
        requirements:
            _locale: en|fr|de
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    <!-- app/config/routing.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="contact" path="/{_locale}/contact">
            <default key="_controller">AppBundle:Contact:index</default>
            <requirement key="_locale">en|fr|de</requirement>
        </route>
    </routes>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    // app/config/routing.php
    use Symfony\Component\Routing\RouteCollection;
    use Symfony\Component\Routing\Route;
    
    $collection = new RouteCollection();
    $collection->add('contact', new Route(
        '/{_locale}/contact',
        array(
            '_controller' => 'AppBundle:Contact:index',
        ),
        array(
            '_locale' => 'en|fr|de',
        )
    ));
    
    return $collection;
    

При использовании специального параметра _locale в маршруте, соответствующая локаль автоматически устанавливается в запросе и может быть извлечена с помощью метода getLocale(). Другими словами, если пользователь посещает URI /fr/contact, локаль fr будет автоматически установлена как локаль текущего запроса.

Теперь вы можете использовать локаль для создания маршрутов к другим переведенным страницам в вашем приложении.

Tip

Прочтите Параметры сервис-контейнеров, чтобы узнать, как избежать жесткого кодирования требования _locale во всех ваших маршрутах.

Установка локали по умолчанию

Что, если локаль пользователя не была определена? Вы можете гарантировать, что локаль установлена на каждом запросе пользователя, определив default_locale для фреймворка:

  • YAML
    1
    2
    3
    # app/config/config.yml
    framework:
        default_locale: en
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    <!-- app/config/config.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:framework="http://symfony.com/schema/dic/symfony"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            http://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/symfony
            http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <framework:config default-locale="en" />
    </container>
    
  • PHP
    1
    2
    3
    4
    // app/config/config.php
    $container->loadFromExtension('framework', array(
        'default_locale' => 'en',
    ));
    

Эта документация является переводом официальной документации Symfony и предоставляется по свободной лицензии CC BY-SA 3.0.