StofDoctrineExtensionsBundle
StofDoctrineExtensionsBundle copied to clipboard
slug not translated
Hi,
I am using the stofDoctrineExtensionsBundle in order to use the slug and translatable behavior, but i'am encountering issues about the slug translation, i need my slug to be translated for each title of my entity
/**
* @var string
* @Gedmo\Translatable
* @ORM\Column(name="title", type="string", length=255,unique=true)
*
*/
private $title;
/**
* @Gedmo\Translatable
* @Gedmo\Slug(fields={"title"})
* @ORM\Column(length=255,unique=false)
*/
private $slug;
my title is translated but the slug only use the default locale and is not translated
here is my yamel file service configuration
i put the translatableListener after the sluggableListener
services:
# Doctrine Extension listeners to handle behaviors
gedmo.listener.tree:
class: Gedmo\Tree\TreeListener
tags:
- { name: doctrine.event_subscriber, connection: default }
calls:
- [ setAnnotationReader, [ @annotation_reader ] ]
gedmo.listener.sluggable:
class: Gedmo\Sluggable\SluggableListener
tags:
- { name: doctrine.event_subscriber, connection: default}
calls:
- [ setAnnotationReader, [ @annotation_reader ] ]
# KernelRequest listener
extension.listener:
class: A101\Bundle\AccordMetVinBundle\Listener\DoctrineExtensionListener
calls:
- [ setContainer, [ @service_container ] ]
tags:
# translatable sets locale after router processing
- { name: kernel.event_listener, event: kernel.request, method: onLateKernelRequest }
# loggable hooks user username if one is in security context
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
gedmo.listener.timestampable:
class: Gedmo\Timestampable\TimestampableListener
tags:
- { name: doctrine.event_subscriber, connection: default }
calls:
- [ setAnnotationReader, [ @annotation_reader ] ]
gedmo.listener.sortable:
class: Gedmo\Sortable\SortableListener
tags:
- { name: doctrine.event_subscriber, connection: default }
calls:
- [ setAnnotationReader, [ @annotation_reader ] ]
gedmo.listener.loggable:
class: Gedmo\Loggable\LoggableListener
tags:
- { name: doctrine.event_subscriber, connection: default }
calls:
- [ setAnnotationReader, [ @annotation_reader ] ]
gedmo.listener.translatable:
class: Gedmo\Translatable\TranslatableListener
tags:
- { name: doctrine.event_subscriber, connection: default}
calls:
- [ setAnnotationReader, [ @annotation_reader ] ]
- [ setDefaultLocale, [ %locale% ] ]
- [ setTranslationFallback, [ false ] ]
in the documentation i can find this block
<?php
$evm = new \Doctrine\Common\EventManager();
$sluggableListener = new \Gedmo\Sluggable\SluggableListener();
$evm->addEventSubscriber($sluggableListener);
$translatableListener = new \Gedmo\Translatable\TranslationListener();
$translatableListener->setTranslatableLocale('en_us');
$evm->addEventSubscriber($translatableListener);
// now this event manager should be passed to entity manager constructor
but i clearly have no idea where to put this code, the translatable listener isn't already added to the event manager through the doctrine-extensions.yml file ?
I am using a personnalAbstractTranslation
/**
* @ORM\Entity
* @ORM\Table(name="plat_translations",
* uniqueConstraints={@ORM\UniqueConstraint(name="lookup_unique_idx", columns={
* "locale", "object_id", "field"
* })}
* )
*/
class PlatTranslation extends AbstractPersonalTranslation
{
/**
* @ORM\ManyToOne(targetEntity="Plat", inversedBy="translations")
* @ORM\JoinColumn(name="object_id", referencedColumnName="id", onDelete="CASCADE")
*/
protected $object;
}
anyone have an idea ?
- https://github.com/Atlantic18/DoctrineExtensions/issues/415
- https://github.com/Atlantic18/DoctrineExtensions/issues/542
I have the same problem. Although I didn't change any listeners cause as I see in #232 it should work right away. I have just added the code in YML:
fields:
slug:
type: string
length: 255
column: 'mslug'
gedmo:
translatable: {}
slug:
fields:
- title
As I understand it should work, but it doesn't. I have 4 translatable fields, all of them are translated except slug. Any idea what should I do?
You can change to another translation bundle?
Which one?
I use the a2lixI18nDoctrine bundle, i find it easier to use, but you'll have to create your own function in order to create a slug, with a @PrePersist annotation it is very simple
I have searched and tried a while and found a solution for me:
Entity: the slug field gets generated from the name field
use Gedmo\Mapping\Annotation as Gedmo;
use Gedmo\Translatable\Translatable;
/**
* @var string
*
* @Gedmo\Translatable
* @ORM\Column(name="name", type="string", length=150, unique=true)
*/
private $name;
/**
* @Gedmo\Translatable
* @Gedmo\Slug(fields={"name"}, updatable=true)
* @ORM\Column(type="string", unique=true)
*/
private $slug;
config.yml: here you have to set persist_default_translation: true
https://github.com/Atlantic18/DoctrineExtensions/issues/542#issuecomment-12983553
parameters:
locale: en
doctrine:
orm:
auto_generate_proxy_classes: '%kernel.debug%'
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: true
mappings:
gedmo_translatable:
type: annotation
prefix: Gedmo\Translatable\Entity
dir: "%kernel.root_dir%/../vendor/gedmo/doctrine-extensions/lib/Gedmo/Translatable/Entity"
alias: GedmoTranslatable # (optional) it will default to the name set for the mapping
is_bundle: false
gedmo_translator:
type: annotation
prefix: Gedmo\Translator\Entity
dir: "%kernel.root_dir%/../vendor/gedmo/doctrine-extensions/lib/Gedmo/Translator/Entity"
alias: GedmoTranslator # (optional) it will default to the name set for the mapping
is_bundle: false
stof_doctrine_extensions:
default_locale: '%locale%'
translation_fallback: true
persist_default_translation: true # I think this does the trick
orm:
default:
sluggable: true
translatable: true
DefaultController: use ParamConverter
for calling a query which returns correct entity for current locale
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
/**
* @Route("/entry/{slug}", name="entry_detail")
* @ParamConverter("entry", class="AppBundle:Entry", options={"repository_method" = "findOneByCriteria"})
*/
public function entryDetailAction(Request $request, Entry $entry)
{
return $this->render('frontend/entry.html.twig', [
'entry' => $entry,
]);
}
Entity Repository: with the query method to return entity
/**
* Find an entry by criteria
* Need this special function, because of translatable
* https://github.com/stof/StofDoctrineExtensionsBundle/issues/232
*
* @param $params
* @return mixed
*/
public function findOneByCriteria(array $params)
{
$query = $this->createQueryBuilder('e');
$i = 0;
foreach ($params as $column => $value) {
if ($i < 1) {
$query->where("e.$column = :$column");
} else {
$query->andWhere("e.$column = :$column");
}
$query->setParameter($column, $value);
$i++;
}
$query = $query->getQuery();
$query->setHint(\Doctrine\ORM\Query::HINT_CUSTOM_OUTPUT_WALKER, 'Gedmo\\Translatable\\Query\\TreeWalker\\TranslationWalker');
return $query->getOneOrNullResult();
}
I hope this example helps someone.
Still not working today
I'm a bit confused by this problem. I managed to translate the slugs automatically, without any special attention, on a Symfony 4 and this bundle in version 1.3.
However, I'm now trying to implement it on Symfony 6, without success.
The problem seems to be that the SluggableListener doesn't detect any change in the translated field on which the slug depends.
Example:
#[ORM\Column(length: 255)]
#[Assert\NotBlank()]
#[Assert\Length(max: 255)]
#[Gedmo\Translatable()]
private ?string $name = null;
#[Gedmo\Translatable()]
#[Gedmo\Slug(fields: ['name'], updatable: true, unique: true, dateFormat: '')]
#[ORM\Column(length: 255)]
private ?string $slug;
Here, slug won't be translated even if we translate the "name" field because SluggableListener doesn't see it in its changeset fetching (generateSlug function).
$changeSet = $ea->getObjectChangeSet($uow, $object);
For the moment, I'm proposing a not-so-pretty hack:
#[Gedmo\Translatable()]
#[Gedmo\Slug(fields: ['name', 'updatedAt'], updatable: true, unique: true, dateFormat: '')]
#[ORM\Column(length: 255)]
private ?string $slug;
In a entity using Timestampable, it will translate and update the slug..