#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, я не знаю, указывали ли вы на это в своем примере.