Изменение локали администратора Sonata с локалью пользователя-администратора

Я создаю сайт администратора i18n с пакетом администратора сонаты. Теперь я хочу изменить свою локаль и перевод с установленной локалью пользователя-администратора. Например, у меня есть два пользователя-администратора, один — en (userA), а другой — zh (UserB). локаль пользователя устанавливается en/zh в панели администратора пользователя соответственно。

Моя служба администратора:

services:
    sonata.admin.post:
        class: Acme\StoreBundle\Admin\PostAdmin
        tags:
            - { name: sonata.admin, manager_type: orm, group: "Content", label: "Project", label_translator_strategy: sonata.admin.label.strategy.underscore }
        arguments:
            - ~
            - Acme\StoreBundle\Entity\Product
            - ~
        calls:
            - [ setTranslationDomain, [AcmeStoreBundle]]
            - [ setLabelTranslatorStrategy, [ @sonata.admin.label.strategy.native ]]

Затем мои Resources/translations/AcmeStoreBundle.en.xliff и Resources/translations/AcmeStoreBundle.zh.xliff точно так же:

<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>label.product.name</source>
                <target>Product Name</target>  ##---> zh is diffrent here!!!
            </trans-unit>
        </body>
    </file>
</xliff>

Затем я вхожу в систему с правами администратора от UserA, сообщение (название продукта) в порядке. Но я вхожу в систему с помощью UserB, сообщение все еще находится в локали (название продукта). Конечно, я могу изменить глобальную локаль в parameters.yml (%locale%) для пользователя B, но это не очень хорошо для пользователя A.

Итак, как я могу изменить языковой стандарт моего сайта (сообщение или перевод) с другим языковым стандартом администратора? Заранее спасибо.


person pysome    schedule 23.12.2014    source источник
comment
Где вы храните локаль пользователя в базе данных?   -  person Jason Roman    schedule 23.12.2014
comment
Извините, забыл упомянуть, что я использовал сонату пользовательский пакет чтобы добавить моего администратора сайта, затем я изменяю профиль пользователя (язык) в пользовательской панели администратора сонаты. И я также вижу, что результат изменения в таблице базы данных (fos_user_user) в порядке.   -  person pysome    schedule 23.12.2014


Ответы (2)


Вы можете расширить обработчик успешного входа в систему и установить локаль пользователя в сеансе. Например:

# app/config/config.yml
services:
    login_success_handler:
        parent: security.authentication.success_handler
        class:  MyVendor\MyBundle\LoginSuccessHandler

ОБНОВЛЕНИЕ: обязательно укажите этот прослушиватель в файле security.yml:

# app/config/security.yml
security:
    firewalls:
        secured_area:
            pattern:   ^/
            anonymous: ~
            form_login:
                login_path: login
                check_path: login_check
                success_handler: login_success_handler

Затем добавьте класс обработчика успешного входа в систему:

class LoginSuccessHandler extends DefaultAuthenticationSuccessHandler
{
    public function onAuthenticationSuccess(Request $request, TokenInterface $token)
    {
        $locale = $token->getUser()->getLocale()

        $request->getSession()->set('_locale', $locale);
        $request->setLocale($locale);

        return parent::onAuthenticationSuccess($request, $token);
    }
}

Затем вы можете создать LocaleListener, аналогичный или точно такой же, как в документации Symfony. Единственная разница в том, что если вы никогда не будете определять _locale в своих маршрутах, вы можете изменить:

if ($locale = $request->attributes->get('_locale')) {
    $request->getSession()->set('_locale', $locale);
} else {
    $request->setLocale($request->getSession()->get('_locale', $this->defaultLocale));
}

чтобы просто

$request->setLocale($request->getSession()->get('_locale', $this->defaultLocale));
person Jason Roman    schedule 23.12.2014
comment
Это нормально. Большое спасибо. Кстати, метод onAuthenticationSuccess должен возвращать ответ. Поэтому я добавляю return parent::onAuthenticationSuccess( $request, $token ); в последнюю строку метода; - person pysome; 23.12.2014
comment
Ах да, извините, я как бы сокращал только соответствующие части кода, но это имеет смысл показать. Это именно та строка, которую вы хотели бы вернуть, и я отредактировал свой пост, чтобы включить ее. - person Jason Roman; 23.12.2014

Спасибо, Джейсон. Я сделал это как ваш совет. Но, похоже, что login_success_handler не вызывается полностью。

мой config.yml:

services:
    login_success_handler:
        parent: security.authentication.success_handler
        class:  Acme\StoreBundle\EventListener\LoginSuccessHandler

    acme_locale.locale_listener:
        class: Acme\StoreBundle\EventListener\LocaleListener
        arguments: ["%kernel.default_locale%"]
        tags:
            - { name: kernel.event_subscriber }

И src/Acme/StoreBundle/EventListener/LoginSuccessHandler.php

namespace Acme\StoreBundle\EventListener;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;

class LoginSuccessHandler extends DefaultAuthenticationSuccessHandler
{
    public function onAuthenticationSuccess(Request $request, TokenInterface $token)
    {
        $locale = $token->getUser()->getLocale();
        file_put_contents('/tmp/login.log', $locale, FILE_APPEND);  ## I can't find the log file
        $request->getSession()->set('_locale', $locale);
        $request->setLocale($locale);
    }
}

И src/Acme/StoreBundle/EventListener/LocaleListener.php

namespace Acme\StoreBundle\EventListener;

use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class LocaleListener implements EventSubscriberInterface
{
    private $defaultLocale;

    public function __construct($defaultLocale = 'en')
    {
        $this->defaultLocale = $defaultLocale;
    }

    public function onKernelRequest(GetResponseEvent $event)
    {
        $request = $event->getRequest();
        if (!$request->hasPreviousSession()) {
            return;
        }
        $request->setLocale($request->getSession()->get('_locale', $this->defaultLocale));
    }

    public static function getSubscribedEvents()
    {
        return array(
            // must be registered before the default Locale listener
            KernelEvents::REQUEST => array(array('onKernelRequest', 17)),
        );
    }
}

Что со мной не так? Спасибо.

person pysome    schedule 23.12.2014
comment
К сожалению, я забыл упомянуть, что вы должны указать новый обработчик успеха в файле security.yml. Я обновил свой пост, чтобы включить эту информацию. - person Jason Roman; 23.12.2014