Search code examples
phpsymfonysonata-adminsonata

Symfony2, Sonata : translate and show translated roles name


The first step is more about Symfony2,

I have different Roles :

role_hierarchy:
    ROLE_INVESTOR: [ROLE_USER]
    ROLE_PROJECT_OWNER: [ROLE_USER]
    ROLE_ADMIN: [ROLE_USER, ROLE_SONATA_ADMIN]
    ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_SONATA_ADMIN, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH, SONATA]

I would like a french translation for each of them.

Either using roles.fr.yml, roles.fr.xml or roles.fr.xliff (not sure which one has to be used).

this is my actual yml :

'ROLE_PROJECT_OWNER': Porteur de projet
'ROLE_INVESTOR': Investisseur
'ROLE_USER': Utilisateur

or 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="" >
        <body>
            <trans-unit id="ROLE_PROJECT_OWNER">
                <source>ROLE_PROJECT_OWNER</source>
                <target>Porteur de projet</target>
            </trans-unit>
        </body>
    </file>
</xliff>

(Both have not been tested)

Then i would like to show them in Sonata Admin, for now it is not user friendly at all :

Roles

This is how they are "auto" listed in this part :

/**
 * {@inheritdoc}
 */
protected function configureListFields(ListMapper $listMapper)
{
    $listMapper
        ->addIdentifier('username')
        ->add('email')
        ->add('enabled', null, array('editable' => true))
        ->add('locked', null, array('editable' => true))
        ->add('roles', null, array('editable' => true))
        ->add('createdAt')
        ->add('_action', 'actions', array(
            'actions' => array(
                'show' => array(),
                'edit' => array(),
                'delete' => array(),
            )
        ))
    ;
}

So it is not obvious how to add their related translations.

Any ideas how to do?

UPDATE :

I managed to have something more readable but not yet translated using custom template (Sonata Doc).

{% block field %}
<div>
    {% for role in object.roles %}
    <strong>{{ role }}</strong> <br/>
    {% endfor %}
</div>
{% endblock %}

Solution

  • You could also set the translation domain in your Admin class like :

    protected function configureListFields(ListMapper $listMapper)
    {
        $listMapper
            ->addIdentifier('username')
            ->add('email')
            ->add('enabled', null, array('editable' => true))
            ->add('locked', null, array('editable' => true))
            ->add('roles', null, array('editable' => true), array('translation_domain' => 'roles')))
            ->add('createdAt')
            ->add('_action', 'actions', array(
                'actions' => array(
                    'show' => array(),
                    'edit' => array(),
                    'delete' => array(),
                )
            ))
        ;
    }
    

    If it works, you might not even need to override the template. Details in the Sonata Admin doc : http://sonata-project.org/bundles/admin/master/doc/reference/translation.html#overriding-the-translation-domain

    UDPATE

    To translate filters you have to do something like:

    if your roles are from an entity

    protected function configureDatagridFilters(DatagridMapper $filterMapper)
    {
        $filterMapper
            ->add('roles', null, array('translation_domain' => 'roles'), 'entity')
        ;
    }
    

    if your roles are not from an entity

    protected function configureDatagridFilters(DatagridMapper $filterMapper)
    {
        // get all your availables roles
        $roles = array('ROLE_OWNER' => 'ROLE_OWNER');
        $filterMapper
            ->add('roles', 'doctrine_orm_choice', array('translation_domain' => 'roles'), 'choice', array('choices' => $roles))
        ;
    }
    

    I don't know if the translation will be available in the last case, you might need to translate in your controller the value of the roles.

    Details from the documentation : http://sonata-project.org/bundles/doctrine-orm-admin/master/doc/reference/filter_field_definition.html

    UDPATE 2

    Here is a more detailed explaination for the second case, you have to create a method where you translate the value of your array. For example :

    class ChallengeManager
    {
        public function getStatuses($translate = false)
        {
            $statuses = array(
                ChallengeInterface::STATUS_DRAFT => 'challenge.status.draft',
                ChallengeInterface::STATUS_PUBLISHED => 'challenge.status.published',
                ChallengeInterface::STATUS_PENDING => 'challenge.status.pending',
                ChallengeInterface::STATUS_FINISHED => 'challenge.status.finished',
                ChallengeInterface::STATUS_PUBLISHING => 'challenge.status.publishing'
            );
    
            if ($translate == true) {
                $statusesTranslated = array();
                foreach ($statuses as $key => $status) {
                    $statusesTranslated[$key] = $this->translator->transChoice($status, 0);
                }
                return $statusesTranslated;
            }
            return $statuses;
        }
    }
    
    class ChallengeAdmin
    {
        protected configureDatagridFilters(DatagridMapper $datagridMapper)
        {
             $statuses = $this->getConfigurationPool()->getContainer()->get('managers.challenge_manager')->getStatuses(true);
             $datagridMapper
                 ->add('status',
                        'doctrine_orm_choice',
                        array(),
                        'choice',
                        array('choices' => $statuses))
        }
    }
    

    I use a service to handle the translations and retrieve the statuses, and I use it in my Sonata Admin.

    Didn't find a better way at the moment to do the translations for choice fields.