Closed nurtext closed 3 years ago
Hi @nurtext ,
It should be quite simple. Since this bundle is using the same concept as Sylius, you can take a look at Sylius example for adding translations programatically: https://docs.sylius.com/en/1.2/book/architecture/translations.html#how-to-add-a-new-translation-programmatically. It should work here too :) GL
Hi @paullla,
thanks for your help. Unfortunately this won't work, I tried the following:
/** @var Salutation $salutationEntity */
$salutation = new Salutation();
$salutation->setTitle('Mr.');
/** @var SalutationTranslation $salutationTranslation */
$salutationTranslation = new SalutationTranslation();
$salutationTranslation->setLocale('de');
$salutationTranslation->setTitle('Herr');
$salutation->addTranslation($salutationTranslation);
$this->entityManager->flush($salutation);
Which resulted in: In TranslatableTrait.php line 65: No locale has been set and current locale is undefined.
This are my two classes:
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use App\Entity\SalutationTranslation;
use App\Repository\SalutationRepository;
use ApiPlatform\Core\Annotation\ApiResource;
use Symfony\Component\Serializer\Annotation\Groups;
use Locastic\ApiPlatformTranslationBundle\Model\AbstractTranslatable;
use Locastic\ApiPlatformTranslationBundle\Model\TranslationInterface;
/**
* @ApiResource()
* @ORM\Entity(repositoryClass=SalutationRepository::class)
*/
class Salutation extends AbstractTranslatable
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $title;
/**
* @ORM\OneToMany(targetEntity="SalutationTranslation", mappedBy="translatable", fetch="EXTRA_LAZY", indexBy="locale", cascade={"PERSIST"}, orphanRemoval=true)
*
* @Groups({"post_write", "translations"})
*/
protected $translations;
/**
* @return int|null
*/
public function getId(): ?int
{
return $this->id;
}
/**
* @return string|null
*/
public function getTitle(): ?string
{
return $this->getTranslation()->getTitle();
}
/**
* @param string $title
*
* @return self
*/
public function setTitle(string $title): self
{
$this->getTranslation()->setTitle($title);
return $this;
}
/**
* @return TranslationInterface
*/
protected function createTranslation(): TranslationInterface
{
return new SalutationTranslation();
}
}
<?php
namespace App\Entity;
use App\Entity\Salutation;
use Doctrine\ORM\Mapping as ORM;
use App\Repository\SalutationTranslationRepository;
use Symfony\Component\Serializer\Annotation\Groups;
use Locastic\ApiPlatformTranslationBundle\Model\AbstractTranslation;
/**
* @ORM\Entity(repositoryClass=SalutationTranslationRepository::class)
*/
class SalutationTranslation extends AbstractTranslation
{
/**
* @ORM\ManyToOne(targetEntity="Salutation", inversedBy="translations")
*/
protected $translatable;
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string")
*
* @Groups({"post_read", "post_write", "translations"})
*/
private $title;
/**
* @ORM\Column(type="string")
*
* @Groups({"post_write", "translations"})
*/
protected $locale;
/**
* @return int|null
*/
public function getId(): ?int
{
return $this->id;
}
/**
* @param string $title
*
* @return void
*/
public function setTitle(string $title): void
{
$this->title = $title;
}
/**
* @return string|null
*/
public function getTitle(): ?string
{
return $this->title;
}
}
Any ideas what I'm doing wrong here?
Thanks!
Current locale isn't set. When creating translation using API, it happens behind the hood. So I think the solution would be to also set current locale in your code: $salutationTranslation->setCurrentLocale('de');
I tried both setLocale()
and setCurrentLocale()
on the $salutationTranslation
object and both didn't work for me.
I don't have any more ideas :D I'll need to reproduce it and debug the problem. I'll try to do it tomorrow and let you know the results.
Sure, thanks a lot for now :)
Hey @paullla, any news on this one? I tried a few different things on my own, basically creating objects one after another, trying to set different locales using different methods, but none made it work.
Hi @nurtext, I found the problem. You mapped $title
in Salutation
to database, and also called the setter. Fields that are translated need to be mapped to the database in SalutationTranslation
only.
First step is to remove @ORM\Column(type="string")
from $title
in Salutation
Next step is to remove $salutation->setTitle('Mr.');
So the result would be:
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use App\Entity\SalutationTranslation;
use ApiPlatform\Core\Annotation\ApiResource;
use Symfony\Component\Serializer\Annotation\Groups;
use Locastic\ApiPlatformTranslationBundle\Model\AbstractTranslatable;
use Locastic\ApiPlatformTranslationBundle\Model\TranslationInterface;
/**
* @ApiResource()
* @ORM\Entity()
*/
class Salutation extends AbstractTranslatable
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
private $title;
/**
* @ORM\OneToMany(targetEntity="SalutationTranslation", mappedBy="translatable", fetch="EXTRA_LAZY", indexBy="locale", cascade={"PERSIST"}, orphanRemoval=true)
* @Groups({"post_write", "translations"})
*/
protected $translations;
/**
* @return int|null
*/
public function getId(): ?int
{
return $this->id;
}
/**
* @return string|null
*/
public function getTitle(): ?string
{
return $this->getTranslation()->getTitle();
}
/**
* @param string $title
*
* @return self
*/
public function setTitle(string $title): self
{
$this->getTranslation()->setTitle($title);
return $this;
}
/**
* @return TranslationInterface
*/
protected function createTranslation(): TranslationInterface
{
return new SalutationTranslation();
}
}
and creating objects:
$salutation = new Salutation();
/** @var SalutationTranslation $salutationTranslation */
$salutationTranslation = new SalutationTranslation();
$salutationTranslation->setLocale('de');
$salutationTranslation->setTitle('Herr');
$salutation->addTranslation($salutationTranslation);
$this->entityManager->persist($salutation);
$this->entityManager->flush();
@paullla Awesome, now it works! 👍 For some reason I though the concept was to have the translatable entity to hold the original text in the given base locale and to have the translation entity solely for translations.
I'm looking for a programmatic example in order to add new translations e.g. using a command, but I couldn't figure out how to get started. I'd be glad if you could give me a hint on how to start or extend the documentation with an example. Thanks!