Parlons de votre projet
Partitech Sonata Extra Bundle

Sonata Extra Bundle : gérer des administrations multilingues

Le bundle fournit un trait pour les classes admin et un trait pour les entités. Ensemble, ils ajoutent les champs et les actions nécessaires à la gestion de plusieurs variantes linguistiques. Les locales proviennent des sites Sonata Page. L’administration ...

Le bundle fournit un trait pour les classes admin et un trait pour les entités. Ensemble, ils ajoutent les champs et les actions nécessaires à la gestion de plusieurs variantes linguistiques.

Les locales proviennent des sites Sonata Page. L’administration affiche alors les variantes disponibles et permet de relier les enregistrements d’un même groupe de traduction.

Écrans

  • Édition d’une traduction dans le site sélectionné Multilanguage_edit.png
  • Liste des contenus dans la locale sélectionnée Liste_multilingue.png
  • Création d’une traduction depuis la variante courante Multilanguage_create_translation.png

Exemple d’implémentation pour une classe admin simple

Fichier d'entité

<?php

namespace App\Entity;

use App\Repository\SimpleTestRepository;
use Doctrine\ORM\Mapping as ORM;

use Partitech\SonataExtra\Traits\EntityTranslationTrait;

#[ORM\Entity(repositoryClass: SimpleTestRepository::class)]
class SimpleTest
{
    use EntityTranslationTrait;

    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    // ...
}

Fichier admin

<?php

declare(strict_types=1);

namespace App\Admin;

use Partitech\SonataExtra\Attribute\AsAdmin;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Admin\AdminInterface;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Show\ShowMapper;

use Partitech\SonataExtra\Controller\Admin\TranslationController;
use Partitech\SonataExtra\Traits\AdminTranslationTrait;

#[AsAdmin(
    manager_type: 'orm',
    label: 'Simple Entity',
    model_class:  \App\Entity\SimpleTest::class,
)]
final class SimpleTestAdmin extends AbstractAdmin
{
    use AdminTranslationTrait;

    // ...
}

Il suffit d’ajouter les traits aux classes admin et entité. Ensuite, exécutez les commandes suivantes :

bin/console doctrine:schema:update --force
bin/console cache:clear

Si vous avez déjà un contrôleur, ajoutez simplement le trait de contrôleur

class MenuController extends Controller
{
    use \Partitech\SonataExtra\Traits\ControllerTranslationTrait;
}

Vous pouvez également appeler l'action de création de traduction en utilisant le contrôleur étendu en tant que service

use \Partitech\SonataExtra\Controller\Admin\TranslationController;
class MenuController extends Controller
{
    use \Partitech\SonataExtra\Traits\ControllerTranslationTrait;

    private $TranslationController;

    #[Required]
    public function autowireDependencies(
        TranslationController $TranslationController
    ): void {

        $this->TranslationController = $TranslationController;
    }

    public function createTranslationAction($id, $from_site, $to_site, $fqcn): Response
    {
        return $this->TranslationController->createTranslationAction($id, $from_site, $to_site, $fqcn);
    }
}

Configuration de l'administrateur

Le trait possède sa propre configuration. Si vous avez une méthode de configuration dans votre administrateur, assurez-vous simplement d'appeler la configuration du trait comme suit :

#[AsAdmin(
    manager_type: 'orm',
    group: 'Admin',
    label: 'Test',
    model_class: \App\Entity\Test::class
)]

final class TestAdmin extends AbstractAdmin
{
    use AdminTranslationTrait;
    
    protected function configure(): void
    {
        $this->configureTrait();
        $this->setTemplate('edit', '@PartitechSonataMenu/CRUD/edit.html.twig');
    }
}

Configuration de la route administrateur

Le trait ajoute sa propre route pour créer des traductions. Si les utilisateurs ajoutent également des routes, ils doivent configurer leurs routes comme suit :

#[AsAdmin(
    manager_type: 'orm',
    group: 'Admin',
    label: 'Test',
    model_class: \App\Entity\Test::class
)]
final class TestAdmin extends AbstractAdmin
{
    use AdminTranslationTrait;

    protected function configureRoutes(RouteCollectionInterface $collection): void
    {
        $this->configureTraitRoutes($collection);
        $collection->remove('show');
    }

    // ...
}

L’appel à configureTraitRoutes() ajoute les routes nécessaires avant la configuration de vos propres routes. Cela n'est nécessaire que si configureRoutes est implémenté dans la classe admin.

Compatibilité de la traduction automatique

La fonctionnalité multilingue est compatible avec notre outil de traduction automatique via l'« API de traduction » (voir service_intelligent.md).

Ajoutez l’attribut #[Translatable] pour rendre un champ éligible à la traduction automatique via l'API, en utilisant le fournisseur de l'application (voir service_intelligent.md).

use Partitech\SonataExtra\Attribute\Translatable;

#[ORM\Column(type: 'text', nullable: true)]
#[Translatable]
private ?string $description=null;


// ...

Cette fonctionnalité est compatible avec les relations OneToMany. Dans ce cas, ajoutez l'annotation à la fois sur la relation d'entité et sur les champs de l'entité liée.

Lors d’une traduction, l’objet est d’abord cloné, puis traduit. Le clonage automatique convient à un objet simple ; pour une entité complexe, implémentez explicitement la méthode __clone(). L'arborescence du menu ne peut pas être clonée sans une fonction de clonage interne.

À propos des champs slug

Comme le slug doit être unique, lors du processus de clonage, le processus recherche une méthode $object->getSlug(). Si la méthode existe, le processus vérifie si le terme a été traduit ou non. Si le terme est le même, il préfixera la valeur avec sa locale.

    if (method_exists($clonedObject, 'setSlug') && $clonedObject->getSlug()==$object->getSlug()) {
        $slugger = new AsciiSlugger();
        $slug=$slugger->slug($this->site->getLocale().'-'.$clonedObject->getSlug())->lower();
        $clonedObject->setSlug($slug);
    }

Intégration multilingue de la classification Sonata

Pour conserver les informations de traduction de SonataClassificationTag et SonataClassificationCategory, utilisez les classes admin fournies par Sonata Extra.

Dans la configuration sonata_classification.yaml, gardez votre configuration comme suit :

sonata_classification:
    class:
        category: App\Entity\SonataClassificationCategory
        collection: App\Entity\SonataClassificationCollection
        context: App\Entity\SonataClassificationContext
        tag: App\Entity\SonataClassificationTag

Dans votre entité, assurez-vous d'ajouter le trait :

  • SonataClassificationTag.php
<?php

declare(strict_types=1);

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\DBAL\Types\Types;
use App\Repository\SonataClassificationTagRepository;
use Sonata\ClassificationBundle\Entity\BaseTag;
use Partitech\SonataExtra\Traits\EntityTranslationTrait;
#[ORM\Entity(repositoryClass: SonataClassificationTagRepository::class)]
#[ORM\Table(name: 'classification__tag')]
#[ORM\HasLifecycleCallbacks]
class SonataClassificationTag extends BaseTag
{
    use EntityTranslationTrait;

    #[ORM\Id]
    #[ORM\Column(type: Types::INTEGER)]
    #[ORM\GeneratedValue]
    protected ?int $id = null;

    public function getId(): ?int
    {
        return $this->id;
    }
}

  • SonataClassificationCategory.php
<?php
namespace App\Entity;

use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Sonata\ClassificationBundle\Entity\BaseCategory;
use Partitech\SonataExtra\Traits\EntityTranslationTrait;

#[ORM\Entity]
#[ORM\Table(name: 'classification__category')]
class SonataClassificationCategory extends BaseCategory
{
    use EntityTranslationTrait;
    #[ORM\Id]
    #[ORM\Column(type: Types::INTEGER)]
    #[ORM\GeneratedValue]
    protected ?int $id = null;

    public function getId(): ?int
    {
        return $this->id;
    }
}

Utilisez les classes admin de tags et catégories fournies par Sonata Extra. N'UTILISEZ PAS le tag et la catégorie admin du package sonataClassification. Ils n'auront pas les champs de suivi nécessaires pour le multilingue.

  • sonata_admin.yaml
            cms:
                icon: fa fa-pencil
                label: CMS
                keep_open: true
                items:
                    - Partitech\SonataExtra\Admin\ArticleAdmin
                    - sonata.page.admin.page
                    - sonata.page.admin.shared_block
                    - Partitech\SonataExtra\Admin\SliderAdmin
                    - Partitech\SonataExtra\Admin\FaqCategoryAdmin
                    - Partitech\SonataExtra\Admin\TagAdmin
                    - Partitech\SonataExtra\Admin\CategoryAdmin

Point de contrôle

Avant d’ajouter une traduction, vérifiez que les sites Sonata Page portent les locales attendues et qu’une seule entrée du groupe est définie comme version par défaut. Testez ensuite la création, l’édition et la navigation entre variantes avec un utilisateur aux droits limités.

Partager cet article