Doctrine Translatable не показывает переведенный текст при изменении локали

#php #symfony #doctrine-orm #doctrine-extensions

#php #symfony #doctrine-orm #doctrine-расширения

Вопрос:

Я использую translatable с doctrine в проекте Symfony. Я смог добавить переводимый объект и сохранить переведенные тексты, но когда я меняю локаль на веб-сайте, тексты не отображаются, хотя, если я повторяю переводы, я могу видеть тексты. Я думаю, что я что-то упускаю.

Код Twig:

 <p>Title: {{ course.getTitle() }}</p>
<p>Translations content:</p>
<ul>
    {% for t in course.getTranslations() %}
        <li>{{  t.getLocale() }}: {{ t.getContent() }}</li>
    {% endfor %}
</ul>
  

Вывод, если я перейду в / en / url, будет:

 Title: my title in en
Translations content:
es: Mi titulo en ES
  

Но если я перейду в / es / url:

 Title:
Translations content:
es: Mi titulo en ES
  

Вы можете видеть, что перевод es есть, но не отображается при вызове getTitle .

У меня есть объект Course и объект CourseTranslation для хранения переводов.

Также я добавил прослушиватель для установки локали по умолчанию и проверил, что выполняется.

 <?php
namespace AppBundleListener;

use SymfonyComponentHttpKernelEventGetResponseEvent;
use SymfonyComponentDependencyInjectionContainerAwareInterface;
use SymfonyComponentDependencyInjectionContainerInterface;

class DoctrineExtensionListener implements ContainerAwareInterface
{
    /**
     * @var ContainerInterface
     */
    protected $container;

    public function setContainer(ContainerInterface $container = null)
    {
        $this->container = $container;
    }

    public function onLateKernelRequest(GetResponseEvent $event)
    {
        $translatable = $this->container->get('gedmo.listener.translatable');
        $translatable->setTranslatableLocale($event->getRequest()->getLocale());
    }
}
  

Код курса:

 /**
 * Course
 *
 * @ORMTable(name="course")
 * @ORMEntity(repositoryClass="AppBundleRepositoryCourseRepository")
 */
class Course implements Translatable
{
    /**
     * @var int
     *
     * @ORMColumn(name="id", type="integer")
     * @ORMId
     * @ORMGeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @GedmoTranslatable
     * @ORMColumn(name="title", type="string", length=255)
     */
    private $title;

    /**
     * @ORMOneToMany(
     *   targetEntity="CourseTranslation",
     *   mappedBy="object",
     *   cascade={"persist", "remove"}
     * )
     */
    private $translations;

    /**
     * Get title
     *
     * @return string
     */
    public function getTitle()
    {
        return $this->title;
    }
    ...


    /** Translatable operations */
    public function getTranslations()
    {
        return $this->translations;
    }

    public function addTranslation(CourseTranslation $t)
    {
        if (!$this->translations->contains($t)) {
            $this->translations[] = $t;
            $t->setObject($this);
        }
    }
}
  

Код перевода курса:

 <?php
namespace AppBundleEntity;

use DoctrineORMMapping as ORM;
use GedmoTranslatableEntityMappedSuperclassAbstractPersonalTranslation;

/**
 * @ORMEntity
 * @ORMTable(name="course_translations",
 *     uniqueConstraints={@ORMUniqueConstraint(name="lookup_unique_idx", columns={
 *         "locale", "object_id", "field"
 *     })}
 * )
 */
class CourseTranslation extends AbstractPersonalTranslation
{
    /**
     * Convenient constructor
     *
     * @param string $locale
     * @param string $field
     * @param string $value
     */
    public function __construct($locale, $field, $value)
    {
        $this->setLocale($locale);
        $this->setField($field);
        $this->setContent($value);
    }

    /**
     * @ORMManyToOne(targetEntity="Course", inversedBy="translations")
     * @ORMJoinColumn(name="object_id", referencedColumnName="id", onDelete="CASCADE")
     */
    protected $object;
}
  

службы yml-кода:

 services:
    extension.listener:
        class: AppBundleListenerDoctrineExtensionListener
        calls:
            - [ setContainer, [ "@service_container" ] ]
        tags:
            # translatable sets locale after router processing
            - { name: kernel.event_listener, event: kernel.request, method: onLateKernelRequest, priority: -10 }

    gedmo.listener.translatable:
        class: GedmoTranslatableTranslatableListener
        tags:
            - { name: doctrine.event_subscriber, connection: default }
        calls:
            - [ setAnnotationReader, [ "@annotation_reader" ] ]
            - [ setDefaultLocale, [ %locale% ] ]
            - [ setTranslationFallback, [ false ] ]
  

Ответ №1:

В Symfony версии 2.7.11 я добавил следующие строки, чтобы сделать переводимую работу

  use GedmoMappingAnnotation as Gedmo;

 /**
  * MyEntity
  *
  * @ORMTable(name="myEntity")
  * @ORMEntity(repositoryClass="AppBundleRepositoryMyEntityRepository")
  * @GedmoTranslationEntity(class="AppBundleEntityMyEntityTranslation")
  */
 class MyEntity{

      /**
       * @ORMOneToMany(
       *   targetEntity="AppBundleEntityMyEntityTranslation",
       *   mappedBy="object",
       *   cascade={"persist", "remove"}
       * )
       * @CopyCollection
       */
      private $translations;

      public function setTranslatableLocale($locale){
           $this->locale = $locale;
      }

      public function getTranslations(){
           return $this->translations;
      }

      public function addTranslation(MyEntityTranslation $t){
           if (!$this->translations->contains($t)) {
                $this->translations[] = $t;
                $t->setObject($this);
           }
      }

      public function setTranslations($translations){
          foreach($translations as $t){
               $this->addTranslation($t);
          }
     }

      public function findTranslation($locale, $field){
           $id = $this->id;
           $existingTranslation = $this->translations ? $this->translations->filter(
                function($object) use ($locale, $field, $id) {
                     return ($object amp;amp; ($object->getLocale() === $locale) amp;amp; ($object->getField() === $field));
           })->first() : null;
           return $existingTranslation;
      }

      /**
       * Remove translation
       *
       * @param AppBundleEntityMyEntityTranslation $translation
       */
      public function removeTranslation(MyEntityTranslation $translation)
      {
           $this->translations->removeElement($translation);
      }
 }
  

Мой класс перевода выглядит так же, как и ваш. Надеюсь, это помогло.

Ответ №2:

Хорошо, проблема найдена.

В классе сущностей я пропустил @GedmoTranslationEntity , поэтому моя сущность должна быть:

 /**
 * Course
 *
 * @ORMTable(name="course")
 * @ORMEntity(repositoryClass="AppBundleRepositoryCourseRepository")
 * @GedmoTranslationEntity(class="CourseTranslation")
 */
class Course implements Translatable
  

@systemasis, я не знаю, указывали ли вы на это в своем примере.