Symfony UX Autocomplete – 使用KnpLabs Translatable的choice_label

huangapple go评论78阅读模式
英文:

Symfony UX Autocomplete - choice_label with KnpLabs Translatable

问题

自动完成选项标签不翻译

平台为Symfony 6.3,使用UX Autocomplete 2.9

我的问题

我的问题:我有一个Symfony UX Autocomplete表单字段,choice_labels以翻译的形式存储在数据库中。我无法使choice_label的翻译工作。它始终默认为英语(我的默认区域设置)。

我已安装并正常使用了KnpLabs Translatable。

我的当前设置:

  • FunctionProfile实体
  • FunctionProfileTranslation实体 -> 包含一个翻译的名称字段。
  • TrainingPickerType表单 -> 包括FunctionProfileAutocompleteField
  • FunctionProfileAutocompleteField -> 包含在TrainingPickerType中

为了确保,以下是实体和表单的代码的部分:

//App\Entity\FunctionProfile.php

namespace App\Entity;

use App\Repository\FunctionProfileRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Contract\Entity\TranslatableInterface;
use Knp\DoctrineBehaviors\Model\Translatable\TranslatableTrait;

#[ORM\Entity(repositoryClass: FunctionProfileRepository::class)]
class FunctionProfile implements TranslatableInterface
{
    use TranslatableTrait;

    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    //等等。

    public function __toString(): string
    {
        return $this->translate(null, false)->getName();
    }

    //等等。
}

它的伙伴:

<?php

namespace App\Entity;

//App\Entity\FunctionProfileTranslation.php

use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Contract\Entity\TranslationInterface;
use Knp\DoctrineBehaviors\Model\Translatable\TranslationTrait;

#[ORM\Entity]
class FunctionProfileTranslation implements TranslationInterface
{
    use TranslationTrait;

    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column(type: 'integer')]
    private $id;

    #[ORM\Column(length: 255)]
    private ?string $name = null;

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getName(): string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }
}

现在是表单部分,这个主要表单包括不按照我想要的方式工作的子表单字段:

<?php

//App\Form\TrainingPickerType.php

namespace App\Form;

use App\Form\Field\FunctionProfileAutocompleteField;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Contracts\Translation\TranslatorInterface;

class TrainingPickerType extends AbstractType
{
    private TranslatorInterface $translator;
    private UrlGeneratorInterface $router;

    public function __construct(TranslatorInterface $translator, UrlGeneratorInterface $router)
    {
        $this->translator = $translator;
        $this->router = $router;
    }

    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $locale = $options['locale'];
        $builder
            ->setAction($this->router->generate('app_api_get_training_pick_dialog'))
            ->add('functionProfile', FunctionProfileAutocompleteField::class, [
                'label' => $this->translator->trans('Function Profiles', locale: $locale),
                'attr' => ['class' => 'none', 'placeholder' => $this->translator->trans('Start typing or select an option...', locale: $locale),],
                'label_attr' => ['class' => 'block text-sm font-medium leading-6 text-white'],
            ])
        ;
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'locale' => null
        ]);
    }
}

这里的表单行为正常,区域设置设置为需要的任何内容,标签都很好地翻译,等等。

这个包括的表单字段是问题所在:

<?php

namespace App\Form\Field;

use App\Entity\FunctionProfile;
use App\Repository\FunctionProfileRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\UX\Autocomplete\Form\AsEntityAutocompleteField;
use Symfony\UX\Autocomplete\Form\ParentEntityAutocompleteType;

#[AsEntityAutocompleteField]
class FunctionProfileAutocompleteField extends AbstractType
{
    private RequestStack $requestStack;

    public function __construct(RequestStack $requestStack)
    {
        $this->requestStack = $requestStack;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $request = $this->requestStack->getCurrentRequest();
        $query = $request->query->get('query');
        $locale = $request ? $request->getLocale() : 'nl';
        
        $resolver->setDefaults([
            'class' => FunctionProfile::class,
            'multiple' => true,
            'choice_translation_domain' => true,
            'choice_label' => function (FunctionProfile $functionProfile) use ($locale) {
                $functionProfile->getTranslations();
                return $functionProfile->translate($locale)->getName();
            },
            'query_builder' => function(FunctionProfileRepository $functionProfileRepository) use ($locale, $query) {
                $qb = $functionProfileRepository->createQueryBuilder('functionProfile')
                    ->join('functionProfile.translations', 't', 'WITH', 't.locale = :locale')
                    ->setParameter('locale', $locale);

                if (!empty($query)) {
                    $qb->andWhere('t.name LIKE :search')
                        ->setParameter('search', '%' . $query . '%');
                }

                return $qb;
            },
        ]);
    }

    public function buildView(FormView|\Symfony\Component\Form\FormView $view, FormInterface|\Symfony\Component\Form\FormInterface $form, array $options): void
    {
        $view->vars['attr']['class'] = ''; // 删除任何现有的类
    }

    public function getParent(): string
    {
        return ParentEntityAutocompleteType::class;
    }
}

当我输入查询时,会进行搜索。自动完成选项会显示出来。但它们始终是英文的,即使我手动设置了不同的区域设置,比如 "nl",结果仍然相同:所有choice_labels都是英文的。

您可能能够提供的任何指导或帮助将不胜感激!

我尝试过的

我已经在KnpLabs translatable文档中搜索解决方案,但没有找到解决方

英文:

Autocomplete choice labels don't translate

Platform is Symfony 6.3, with UX Autocomplete 2.9

My issue

My issue: I have a Symfony UX Autocomplete form field, the choice_labels are stored in translated form in the database. I cannot get the choice_label translation to work. It always defaults to English (my default locale).

I have KnpLabs Translatable installed & working.

My current setup:

  • FunctionProfile Entity
  • FunctionProfileTranslation Entity -> contains a translated name field.
  • TrainingPickerType Form -> includes FunctionProfileAutocompleteField
  • FunctionProfileAutocompleteField -> included in TrainingPickerType

Just to make sure, the entities and the forms (removed unneccessary parts of the code):

&lt;?php
//App\Entity\FunctionProfile.php
namespace App\Entity;
use App\Repository\FunctionProfileRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Contract\Entity\TranslatableInterface;
use Knp\DoctrineBehaviors\Model\Translatable\TranslatableTrait;
#[ORM\Entity(repositoryClass: FunctionProfileRepository::class)]
class FunctionProfile implements TranslatableInterface
{
use TranslatableTrait;
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
//etc.
public function __toString(): string
{
return $this-&gt;translate(null, false)-&gt;getName();
}
//etc.

And it's friend:

&lt;?php
namespace App\Entity;
//App\Entity\FunctionProfileTranslation.php
use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Contract\Entity\TranslationInterface;
use Knp\DoctrineBehaviors\Model\Translatable\TranslationTrait;
#[ORM\Entity]
class FunctionProfileTranslation implements TranslationInterface
{
use TranslationTrait;
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: &#39;integer&#39;)]
private $id;
#[ORM\Column(length: 255)]
private ?string $name = null;
public function getId(): ?int
{
return $this-&gt;id;
}
public function getName(): string
{
return $this-&gt;name;
}
public function setName(string $name): self
{
$this-&gt;name = $name;
return $this;
}
}

Now for the form part, this main form includes the child form field that's not doing what I want it to do:

&lt;?php
//App\Form\TrainingPickerType.php
namespace App\Form;
use App\Form\Field\FunctionProfileAutocompleteField;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
class TrainingPickerType extends AbstractType
{
private TranslatorInterface $translator;
private UrlGeneratorInterface $router;
public function __construct(TranslatorInterface $translator, UrlGeneratorInterface $router)
{
$this-&gt;translator = $translator;
$this-&gt;router = $router;
}
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$locale = $options[&#39;locale&#39;];
$builder
-&gt;setAction($this-&gt;router-&gt;generate(&#39;app_api_get_training_pick_dialog&#39;))
-&gt;add(&#39;functionProfile&#39;, FunctionProfileAutocompleteField::class, [
&#39;label&#39; =&gt; $this-&gt;translator-&gt;trans(&#39;Function Profiles&#39;, locale: $locale),
&#39;attr&#39; =&gt; [&#39;class&#39; =&gt; &#39;none&#39;, &#39;placeholder&#39; =&gt; $this-&gt;translator-&gt;trans(&#39;Start typing or select an option...&#39;, locale: $locale),],
&#39;label_attr&#39; =&gt; [&#39;class&#39; =&gt; &#39;block text-sm font-medium leading-6 text-white&#39;],
])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver-&gt;setDefaults([
&#39;locale&#39; =&gt; null
]);
}
}

The form hereabove behaves as it should, the locale is set to whatever it needs to be, labels are translated nicely, etc.

This included form field is the issue:

&lt;?php
namespace App\Form\Field;
use App\Entity\FunctionProfile;
use App\Repository\FunctionProfileRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\UX\Autocomplete\Form\AsEntityAutocompleteField;
use Symfony\UX\Autocomplete\Form\ParentEntityAutocompleteType;
#[AsEntityAutocompleteField]
class FunctionProfileAutocompleteField extends AbstractType
{
private RequestStack $requestStack;
public function __construct(RequestStack $requestStack)
{
$this-&gt;requestStack = $requestStack;
}
public function configureOptions(OptionsResolver $resolver)
{
$request = $this-&gt;requestStack-&gt;getCurrentRequest();
$query = $request?-&gt;query-&gt;get(&#39;query&#39;);
$locale = $request ? $request-&gt;getLocale() : &#39;nl&#39;;
$resolver-&gt;setDefaults([
&#39;class&#39; =&gt; FunctionProfile::class,
&#39;multiple&#39; =&gt; true,
&#39;choice_translation_domain&#39; =&gt; true,
&#39;choice_label&#39; =&gt; function (FunctionProfile $functionProfile) use ($locale) {
$functionProfile-&gt;getTranslations();
return $functionProfile-&gt;translate($locale)-&gt;getName();
},
&#39;query_builder&#39; =&gt; function(FunctionProfileRepository $functionProfileRepository) use ($locale, $query) {
$qb = $functionProfileRepository-&gt;createQueryBuilder(&#39;functionProfile&#39;)
-&gt;join(&#39;functionProfile.translations&#39;, &#39;t&#39;, &#39;WITH&#39;, &#39;t.locale = :locale&#39;)
-&gt;setParameter(&#39;locale&#39;, $locale);
if (!empty($query)) {
$qb-&gt;andWhere(&#39;t.name LIKE :search&#39;)
-&gt;setParameter(&#39;search&#39;, &#39;%&#39; . $query . &#39;%&#39;);
}
return $qb;
},
]);
}
public function buildView(FormView|\Symfony\Component\Form\FormView $view, FormInterface|\Symfony\Component\Form\FormInterface $form, array $options): void
{
$view-&gt;vars[&#39;attr&#39;][&#39;class&#39;] = &#39;&#39;; // Remove any existing classes
}
public function getParent(): string
{
return ParentEntityAutocompleteType::class;
}
}

When I enter a query, the search happens. The autocomplete options are presented. But they're always in English, even if I manually set a different locale like "nl", the outcome remains the same: all choice_labels are in English.

Any guidance or help you may be able to provide would be super welcome!

What I have tried

I have searched the KnpLabs translatable docs for solutions, but couldn't find any solutions.

I have verified that (outside of the form field), the translated versions of the entity appear; as an example;

Symfony UX Autocomplete – 使用KnpLabs Translatable的choice_label

Neatly returns Banana when I run:

$test = $functionProfileRepository-&gt;findOneBy([&quot;id&quot; =&gt; 187]);
dd($test-&gt;translate(&#39;en&#39;)-&gt;getName());

And Banaan when I run:

$test = $functionProfileRepository-&gt;findOneBy([&quot;id&quot; =&gt; 187]);
dd($test-&gt;translate(&#39;nl&#39;)-&gt;getName());

I tried retrieving the choice_labels in a separate function and then add those to the choice_label option, but to no avail.

    public function getTranslatedLabel(FunctionProfile $functionProfile)
{
$request = $this-&gt;requestStack-&gt;getCurrentRequest();
$locale = $request ? $request-&gt;getLocale() : &#39;nl&#39;;
return $functionProfile-&gt;translate($locale)-&gt;getName();
}

I'm sorta out of idea's now.

I know about https://github.com/a2lix/TranslationFormBundle but my colleagues indicated not wanting to use it unless absolutely needed, citing bad experiences with earlier versions of the bundle. But if we must, we will use it.

答案1

得分: 0

我有点愚蠢。我的$request->getLocale()还不粘性。按照这个EventSubscriber的说明,一切都正常工作:https://symfony.com/doc/current/session.html#creating-a-localesubscriber

英文:

Okay, so I was a bit stupid. My $request->getLocale() wasn't sticky yet. Everything works as it should implementing this EventSubscriber: https://symfony.com/doc/current/session.html#creating-a-localesubscriber

huangapple
  • 本文由 发表于 2023年7月20日 21:42:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/76730511.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定