Search code examples
symfonyadminlocalesonata

Sonata Admin locale change with admin user's locale


I build a i18n admin site with sonata admin bundle. Now i wanna change my locale and translation with admin user's locale set. Such as , i have two admin users one is en(userA), and another is zh(UserB). user's locale is set en/zh in User admin dashboard respectively。

My admin service :

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 ]]

Then my Resources/translations/AcmeStoreBundle.en.xliff and Resources/translations/AcmeStoreBundle.zh.xliff just like so:

<?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>

Then, i loggin admin by UserA, the message (product name ) is ok. But i loggin by UserB the message is still en locale( product name) . Of course, I can change the global locale in parameters.yml (%locale%) for userB, But this is not good for userA .

So, how can i change my site's locale(message or translation) with diffrent admin's user locale ? Thanks in advance.


Solution

  • You could extend the login success handler and set the user's locale in the session. For example:

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

    UPDATE: Make sure to point to this listener in your 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
    

    Then add login success handler class:

    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);
        }
    }
    

    Then you could create a LocaleListener similar to or exactly the same as the one in the Symfony documentation. The only difference is, if you will never define _locale in your routes you could change:

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

    to just

    $request->setLocale($request->getSession()->get('_locale', $this->defaultLocale));