vm5/entity-translations-bundle

此包已被废弃,不再维护。作者建议使用 arxy/entity-translations-bundle 包。

此包为您的项目中的实体提供翻译。它是一个包,但也可以独立使用。

安装数: 4,861

依赖: 2

推荐者: 0

安全: 0

星标: 7

关注者: 6

分支: 1

开放问题: 0

类型:symfony-bundle

3.1.0 2021-01-22 10:16 UTC

This package is auto-updated.

Last update: 2021-09-11 20:32:02 UTC


README

Build Status

codecov

一个非常简单的包,允许您翻译实体。

安装

建议安装 X.Y.* 版本 - 此项目遵循 semver - 补丁版本将始终与彼此兼容。次要版本可能包含向后不兼容的更改。
  • composer require arxy/entity-translations-bundle
  • 在 AppKernel.php 中注册包:new Arxy\EntityTranslationsBundle\ArxyEntityTranslationsBundle()
  • 可翻译必须 实现 \Arxy\EntityTranslationsBundle\Model\Translatable
  • 翻译必须 实现 \Arxy\EntityTranslationsBundle\Model\Translation
  • 您必须有一个包含所有语言的实体,它必须 实现 \Arxy\EntityTranslationsBundle\Language
  • 在 config.yml 中包含 services.xml
imports:
    - { resource: "@ArxyEntityTranslationsBundle/Resources/config/services.xml" }

无需配置。当前和备用区域设置来自 Symfony

Symfony 翻译
如何处理用户的区域设置

framework:
    translator:      { fallbacks: ["bg", "de"] }

示例实体

语言

<?php

namespace Example;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="languages")
 */
class Language implements \Arxy\EntityTranslationsBundle\Model\Language
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer", length=11)
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(name="locale", type="string", length=5)
     */
    protected $locale;

    /**
     * @return mixed
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @param mixed $id
     * @return Language
     */
    public function setId($id)
    {
        $this->id = $id;

        return $this;
    }

    /**
     * @return mixed
     */
    public function getLocale(): string
    {
        return $this->locale;
    }

    /**
     * @param mixed $locale
     * @return Language
     */
    public function setLocale($locale)
    {
        $this->locale = $locale;

        return $this;
    }
}

News.php

<?php

namespace Example;

use Doctrine\ORM\Mapping as ORM;
use Arxy\EntityTranslationsBundle\Model\Translatable;
use Arxy\EntityTranslationsBundle\Model\Translation;

/**
 * @ORM\Entity()
 * @ORM\Table(name="news")
 */
class News implements Translatable
{

    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue
     */
    protected $id;


    /**
     * @ORM\OneToMany(targetEntity="NewsTranslation", mappedBy="translatable", cascade={"ALL"}, orphanRemoval=true)
     */
    protected $translations;

    /**
     * @var NewsTranslation
     */
    private $currentTranslation;
    
    public function getTranslations() 
    {
        return $this->translations;
    }
    
    /**
     * This is important, as form has default option: by_reference = false
     * so here we set the mapped side entity. 
     * @param NewsTranslation|null $translation
     */
    public function addTranslation(NewsTranslation $translation) 
    {
        $this->getTranslations()->add($translation);
        $translation->setTranslatable($this);
    }
    
    /**
     * This is also used by form.
     * @param NewsTranslation|null $translation
     */
    public function removeTranslation(NewsTranslation $translation)
    {
        $this->getTranslations()->removeElement($translation);
    }

    /**
    * This method is used by bundle to inject current translation.
    */
    public function setCurrentTranslation(Translation $translation = null): void
    {
        $this->currentTranslation = $translation;
    }
    
    /**
     * @return string|null 
     */
    public function getTitle()
    {
        return !$this->currentTranslation ?: $this->currentTranslation->getTitle();
    }
}

NewsTranslations.php

<?php

namespace Example;

use Arxy\EntityTranslationsBundle\Model\Language;use Doctrine\ORM\Mapping as ORM;
use Arxy\EntityTranslationsBundle\Model\Translation;

/**
 * @ORM\Entity
 * @ORM\Table(name="news_translations")
 */
class NewsTranslation implements Translation
{

    /**
     * @var News
     * @ORM\Id
     * @ORM\ManyToOne(targetEntity="News", inversedBy="translations")
     */
    protected $translatable;

    /**
     * @var Language
     * @ORM\Id
     * @ORM\ManyToOne(targetEntity="Language")
     */
    protected $language;

    /**
     * @var string
     * @ORM\Column(type="string")
     */
    protected $title;

    /**
     * @return News
     */
    public function getTranslatable()
    {
        return $this->translatable;
    }

    /**
     * @param News $translatable
     */
    public function setTranslatable(News $translatable = null)
    {
        $this->translatable = $translatable;
    }

    /**
     * @return Language
     */
    public function getLanguage(): Language
    {
        return $this->language;
    }

    /**
     * @param Language $language
     */
    public function setLanguage(Language $language)
    {
        $this->language = $language;
    }

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

    /**
     * @param string $title
     */
    public function setTitle($title)
    {
        $this->title = $title;
    }
}

然后您可以自行进行翻译

$news = new News();

$englishTranslation = new NewsTranslation();
$englishTranslation->setLanguage($englishLanguage);
$englishTranslation->setTitle('Title on english');
$news->addTranslation($englishTranslation);

$em->persist($news);
$em->flush();

内部 API

如果您希望更改所有管理实体的语言

$this->get('arxy.entity_translations.translator')->setLocale('bg');

您可以更改单个实体的语言

$initializedLocale = $this->get('arxy.entity_translations.translator')->initializeTranslation($entity, 'bg');

$initializedLocale 是实体中初始化的实际区域设置 - 它不一定是 bg,它可以是备用区域设置之一。参数 #2 可以是字符串区域设置或 Language 实体。

您可以取消实体与经理的关联

$this->get('arxy.entity_translations.translator')->detach($entity);

因此,它不会受到区域设置更改的影响。

如果您希望获取单个翻译而不初始化它,可以使用

/** @var $translation \Arxy\EntityTranslationBundle\Model\Translation */
$translation = $this->get('arxy_entity_translations.translator')->getTranslation($entity, 'bg');

参数 #2 可以是字符串区域设置或 Language 实体。

您也可以使用翻译器来翻译对象,而不是使用 setCurrentTranslation。

$translation = $this->get('arxy_entity_translations.translator')->translate($entity, 'field', 'bg');

参数 #3 是可选的。如果省略,则假定当前区域设置。

您也可以使用类而不是键来访问服务

... $this->get(\Arxy\EntityTranslationsBundle\Translator::class) ...

您也可以使用嵌入式 Twig 过滤器在 twig 中进行翻译

{{ news|translate('title')|lower }}
{{ news|translate('title', 'en')|lower }}

或获取整个翻译

{% set translation = news|translation('en') %}
{% if translation %}
  {{ translation.title }}
{% endif %}

使用表单轻松翻译实体

doctrine:
   orm:
        # search for the "ResolveTargetEntityListener" class for an article about this
        resolve_target_entities: 
            Arxy\EntityTranslationsBundle\Model\Language: Example\Language

可翻译应该具有 addTranslationremoveTranslation(见 by-reference如何处理 Doctrine 关联/关系

    public function addTranslation(NewsTranslation $translation)
    {
        if (!$this->translations->contains($translation)) {
            $this->translations->add($translation);
            $translation->setTranslatable($this);
        }
    }


    public function removeTranslation(NewsTranslation $translation)
    {
        $this->translations->removeElement($translation);
        $translation->setTranslatable(null);
    }

翻译应该实现 EditableTranslation 而不是简单的 Translation

use Arxy\EntityTranslationsBundle\Model\EditableTranslation;

class NewsTranslation implements EditableTranslation

加载表单主题(可选)

twig:
    form_themes:
        - '@ArxyEntityTranslations/bootstrap_4_tab_layout.html.twig'

使用 '@ArxyEntityTranslations/bootstrap_3_tab_layout.html.twig' 以支持 Bootstrap 3。

您需要创建翻译的表单。

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class NewsTranslationType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add(
            'title',
            TextType::class,
            [
                'required' => false,
                'constraints' => [
                    new NotBlank(),
                    new SomeBulgarianSymbolConstraint([
                        'groups'=> ['bg']
                    ]) // This will be validated only on bg locale
                    new SomeChineseSymbolConstraint([
                        'groups'=> ['zh']
                    ])  // This will be validated only on zh locale
                ],
            ]
        );
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefault('data_class', NewsTranslation::class); // this is important
        $resolver->setDefault('constraints', [
            new NotNull(
                [
                    'groups' => ['en'], // make only english required
                ]
            ),
        ]);
    }
}

然后您可以

->add(
    'translations',
    \Arxy\EntityTranslationsBundle\Form\Type\TranslationsType::class,
    [
        'entry_type' => NewsTranslationType::class,
        'em' => 'manager_name', // optional
        'query_builder' => function(EntityRepository $repo) {
            return $repo->createQueryBuilder('languages');
        }, // optional
        'entry_language_options' => [
            'en' => [
                'required' => true,
            ]
        ],
    ]
)

在主表单中。

对于特定区域,将required包含在entry_language_options中非常重要,因为只有在语言不为空或为必填时才会触发验证。

当至少有一个字段填写时,假定语言不为空。