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é

- Liste des contenus dans la locale sélectionnée

- Création d’une traduction depuis la variante courante

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.