Partage
  • Partager sur Facebook
  • Partager sur Twitter

Symfony DoctrineExtensionBundle Translatable

Sujet résolu
    1 décembre 2024 à 14:32:22

    Bonjour,

    J'ai un souci sur l'affichage de mes noms de catégorie dans une autre locale 

    J'utilise la doctrine extension translatable 

    #[ORM\Entity(repositoryClass: CategoryRepository::class)]
    class Category
    {
        #[ORM\Id]
        #[ORM\GeneratedValue]
        #[ORM\Column]
        private ?int $id = null;
    
        #[ORM\Column(length: 255)]
        #[Assert\NotBlank()]
        #[Assert\NotNull()]
        #[Assert\Length(min: 2, max: 255)]
        #[Assert\NoSuspiciousCharacters]
        #[Translatable]
        private ?string $name = null;

    J'ai ma locale par défaut en 'EN'

    Mon fichier services.yaml

    # This file is the entry point to configure your own services.
    # Files in the packages/ subdirectory configure your dependencies.
    
    # Put parameters here that don't need to change on each machine where the app is deployed
    # https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
    parameters:
        locale : 'en'

    mon fichier framework.yaml 

    # see https://symfony.com/doc/current/reference/configuration/framework.html
    framework:
        secret: '%env(APP_SECRET)%'
        #csrf_protection: true
    
        # Note that the session will be started ONLY if you read or write from it.
        session: true
        default_locale: '%locale%' # Remplacez 'en' par la langue par défaut souhaitée
        translator:
            enabled: true
       


    Mon fichier stof_dcotrine_extensions.yaml 

    stof_doctrine_extensions:
        default_locale: '%locale%'
        orm:
            default:
                translatable: true 
                sluggable : true

    J'utilise un UserLocalListerner pour modifier ma locale en fonction de ce que souhaite l'utilisateur. 

    <?php
    
    namespace App\EventListener;
    
    use App\Entity\User;
    use Symfony\Bundle\SecurityBundle\Security;
    use Gedmo\Translatable\TranslatableListener;
    use Symfony\Component\HttpKernel\KernelEvents;
    use Symfony\Component\Translation\LocaleSwitcher;
    use Symfony\Component\HttpKernel\Event\RequestEvent;
    use Symfony\Component\DependencyInjection\Attribute\Autowire;
    use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
    use Psr\Log\LoggerInterface;
    use Symfony\Component\BrowserKit\Request;
    
    final class UserLocalListener
    {
    
        public function __construct(
            #[Autowire(service: 'stof_doctrine_extensions.listener.translatable')]
            private TranslatableListener $translatableListener,
            private readonly Security $security,
            private readonly LocaleSwitcher $localeSwitcher,
            private readonly LoggerInterface $logger
    
        ) {}
    
        #[AsEventListener(event: KernelEvents::REQUEST, priority: 1)]
        public function onKernelRequest(RequestEvent $event): void
        {
            $request = $event->getRequest();
    
            $defaultLocale = $request->getLocale();
    
            $user = $this->security->getUser();
            if ($user && $user instanceof User) {
                $locale = $user->getLocale();
            } else {
                $locale = $request->getSession()->get('_locale', $defaultLocale);
            }
            dump($locale);
            $this->localeSwitcher->setLocale($locale);
            $this->translatableListener->setDefaultLocale($locale);
        }
    }

    Mon UserLocalListener est normalement appelé avant le LocalListener de Stof 

    kernel.request
    2048	
    "
    Symfony\Component\HttpKernel\EventListener
    \
    DebugHandlersListener::configure(?object $event = null): void"
    256	
    "
    Symfony\Component\HttpKernel\EventListener
    \
    ValidateRequestListener::onKernelRequest(RequestEvent $event): void"
    128	
    "
    Symfony\Component\HttpKernel\EventListener
    \
    SessionListener::onKernelRequest(RequestEvent $event): void"
    100	
    "
    Symfony\Component\HttpKernel\EventListener
    \
    LocaleListener::setDefaultLocale(KernelEvent $event): void"
    32	
    "
    Symfony\Component\HttpKernel\EventListener
    \
    RouterListener::onKernelRequest(RequestEvent $event): void"
    16	
    "
    Symfony\Component\HttpKernel\EventListener
    \
    LocaleListener::onKernelRequest(RequestEvent $event): void"
    15	
    "
    Symfony\Component\HttpKernel\EventListener
    \
    LocaleAwareListener::onKernelRequest(RequestEvent $event): void"
    8	
    "
    Symfony\Bundle\SecurityBundle\Debug
    \
    TraceableFirewallListener::configureLogoutUrlGenerator(RequestEvent $event): void"
    8	
    "
    Symfony\Bundle\SecurityBundle\Debug
    \
    TraceableFirewallListener::onKernelRequest(RequestEvent $event)"
    1	
    "
    App\EventListener
    \
    UserLocalListener::onKernelRequest(RequestEvent $event): void"
    0	
    "
    Knp\Bundle\PaginatorBundle\Subscriber
    \
    SlidingPaginationSubscriber::onKernelRequest(RequestEvent $event): void"
    0	
    "
    EasyCorp\Bundle\EasyAdminBundle\EventListener
    \
    AdminRouterSubscriber::onKernelRequest(RequestEvent $event): void"
    0	
    "
    Stof\DoctrineExtensionsBundle\EventListener
    \
    LocaleListener::onKernelRequest(RequestEvent $event): void"



    Et je change la locale en cliquant sur un drapeau de la langue souhaité avec une route 

    Voici le controller qui gère cela 

     #[Route('/locale/{locale}', name: 'app_user_change_locale')]
        public function changelocale(string $locale,  EntityManagerInterface $entityManager, SessionInterface $sessionInterface, Request $request): RedirectResponse
        {
            /** @var User $user */
            $user = $this->getUser();
    
            $locales = ['en', 'fr']; // Ajoute les locales supportées ici
            if (!in_array($locale, $locales)) {
                throw $this->createNotFoundException("Locale '$locale' non supportée.");
            }
    
            if (!$user) {
                // Change la locale dans la session
                $sessionInterface->set('_locale', $locale);
                // Redirige vers la page précédente ou une route par défaut
                $request->setLocale($locale);
                $referer = $request->headers->get('referer');
                return new RedirectResponse($referer ?: '/');
            } else {
                // Mets à jour la locale dans l'entité User
    
                $user->setLocale($locale);
                $entityManager->flush();
                //  $sessionInterface->set('_locale', $locale);
                // Redirige vers la page précédente ou une route par défaut
                $referer = $request->headers->get('referer');
                return new RedirectResponse($referer ?: '/');
            }
        }


    Je génère via les fixtures le nom de mes catégories en 'FR' et 'EN' 

    public function load(ObjectManager $manager)
        {
            $repository = $this->em->getRepository('Gedmo\\Translatable\\Entity\\Translation');
    
    
            $category = new Category();
            $repository->translate($category, 'name', 'en', 'Table EN');
            $repository->translate($category, 'name', 'fr', 'Table FR');
            $category->setIsPublic(1);
            $categories[] = $category;
            $manager->persist($category);
    }

    Pour moi tout est bien enregistré en base de donnée. j'ai dans la table category, le champ 'name' qui est enregistré en EN et dans la table ext_translations le nom qui est enregistré avec ma locale FR 

    Quand j'affiche ma page avec la locale EN le nom "Table EN" s'affiche correctement, par contre lorsque je change de locale en FR le nom 'table FR' ne s'affiche pas, le champ est vide 

    Apres recherche j'ai vu que le souci provenait de la requete que demandait symfony. Alors que ma locale est définie en FR il fait une requete en mettant en paramètre la Locale 'EN' Sauf que dans ma table ext_translations les translations sont avec la locale FR donc il ne trouve rien et il affiche rien (cf ci dessous) 

    2	0.53 ms	
    SELECT e0_.content AS content_0, e0_.field AS field_1 FROM ext_translations e0_ WHERE e0_.foreign_key = ? AND e0_.locale = ? AND e0_.object_class = ?
    Parameters:
    [▼
      "1678"
      "en"
      "App\Entity\Category"
    ]

    Je ne sais pas ce que j'ai mal fait ni comment faire en sorte qu'il demande la bonne locale ? Si quelqu'un a une idée ça me sauverai :) 

    Merci d'avance 

    Bonne journée 

    Eric



    • Partager sur Facebook
    • Partager sur Twitter
      2 décembre 2024 à 11:13:10

      Salut

      Je me méfie de ce que la ligne 43 de ton UserLocalListener soit le problème : pour moi, tu changes la locale par défaut, donc dans ma compréhension tu dis plus ou moins que la table category ne contient plus de l'anglais, mais la langue souhaitée par l'utilisateur — si c'est de l'anglais, pas de souci, mais justement si c'est du français… Or, tu souhaites juste dire que maintenant tu aimerais avoir les données pour une langue sans changer ce paramètre. Si je me souviens bien du processus, il faudrait changer la locale de la session de la requête ($request->getSession()->setLocale()), ce qui est fait automatiquement si tu utilises le paramètre de route _locale — attention, il faut qu'il soit dans les paramètres de route et non "en GET" ni "en POST".

      S'il fallait vraiment faire cela manuellement, la documentation me semble explicite. Peut-être pourrait-on se passer d'un listener global pour mettre la logique dans une seule action, sur la route qui permet le changement de langue ?

      Edit

      Ou alors la route qui permet de "changer de session".

      -
      Edité par Ymox 3 décembre 2024 à 20:30:36

      • Partager sur Facebook
      • Partager sur Twitter
        3 décembre 2024 à 22:44:05

        Bonjour Ymox,

        En effet il suffisait de remplacer la ligne 43 par 

         $request->setLocale($locale);

        En effet la documentation est claire en plus. Je suis passé a coté et j'y ai passé pas mal de temps ^^

        Merci beaucoup pour ton temps. 

        Eric



        • Partager sur Facebook
        • Partager sur Twitter
          3 décembre 2024 à 22:58:13

          Bonjour,

          Sujet résolu

          Tu peux passer le sujet à "résolu" (bouton en haut à droite du sujet) et cliquer sur les pouces levés des messages qui t'ont aidé⋅e ;)
          • Partager sur Facebook
          • Partager sur Twitter

          Symfony DoctrineExtensionBundle Translatable

          × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
          • Editeur
          • Markdown