sandstorm/gedmotranslatableconnector

该包最新版本(4.2.0)没有可用的许可证信息。

连接器,使 Gedmo Translatable 能够与 Neos Flow 一起工作

4.2.0 2023-05-03 09:42 UTC

README

由 Sebastian Kurfürst,sandstorm|media 提供。感谢 Web Essentials 最初赞助此工作。目前由 @swisscomeventandmedia 维护

在 Neos Flow 框架中使用 Gedmo.Translatable 比预期要复杂一些。这个小包封装了必要的步骤。

入门

只需包含此包,然后根据他们的文档说明使用 Gedmo Translatable(例如,使用 @Gedmo\Translatable 注解):https://github.com/Atlantic18/DoctrineExtensions/blob/master/doc/translatable.md

确保在安装此包后在 Data/Temporary 中完全清除代码缓存!

此外,确保创建一个 doctrine 迁移,该迁移创建 ext_translations SQL 表;例如,运行 ./flow doctrine:migrationgenerate

查看示例包:https://github.com/sandstorm/GedmoTest.

此连接器支持 Gedmo Translatable 提供的所有高级选项。

模型注解

只需使用 Gedmo\Mapping\Annotation\Translatable 注释您要本地化的模型属性。

    /**
     * @var string
     * @Gedmo\Translatable
     */
    protected $title;

翻译模型(低级)

    /**
     * Doctrine's Entity Manager. Note that "ObjectManager" is the name of the related interface.
     *
     * @Flow\Inject
     * @var ObjectManager
     */
    protected $entityManager;

    public function updateAction(Event $event) {
        /* @var $repository TranslationRepository */
        $repository = $this->entityManager->getRepository('Gedmo\\Translatable\\Entity\\Translation');
        $repository->translate($event, 'name', 'de', 'Deutscher Titel');
    }

设置当前语言

为了设置 查看 的当前语言,注入 Gedmo\Translatable\TranslatableListener 类并在其上设置当前语言:$translatableListener->setTranslatableLocale('de');

翻译管理

同时编辑多种语言

  • 混合使用 Trait Sandstorm\GedmoTranslatableConnector\TranslatableTrait 并将 \Sandstorm\GedmoTranslatableConnector\Translatable 实现到您的模型中,例如
/**
 * @Flow\Entity
 */
class MyModel implements \Sandstorm\GedmoTranslatableConnector\Translatable {
  use \Sandstorm\GedmoTranslatableConnector\TranslatableTrait;
  
  // make sure some properties have Gedmo\Translatable annotations
}
  • 此 trait 添加了 getTranslations()setTranslations() 方法,允许获取和设置模型的其它翻译。

  • 现在,您可以通过将表单元素绑定到 translations.[language].[fieldname],轻松地编辑多种语言,例如,这就像以下这样做

Name (default): <f:form.textfield property="name" /><br />
Name (de): <f:form.textfield property="translations.de.name" /><br />
Name (en): <f:form.textfield property="translations.en.name" /><br />

持久化编辑后的翻译

默认启用的 instantTranslation 设置下,翻译在调用 setTranslation 方法时立即更新和持久化。这通常可能不是理想的,因为它立即持久化实体。禁用此设置并调用 TranslatableManagerflush() 方法以根据您的需求持久化更改。

在另一个区域获取对象

如果您已在一个特定区域加载了对象,但后来需要将对象更改为另一个区域,可以调用方法 reloadInLocale($locale)(该方法定义在 trait Sandstorm\GedmoTranslatableConnector\TranslatableTrait 内部)

$myModel->getName(); // will return the language which was set at the time where $myModel was fetched

$myModel->reloadInLocale('de');
$myModel->getName(); // will return *german*

翻译关联

警告:此功能尚不稳定;请测试并提供反馈!

通常,指向其他领域模型(如图像或资产)的关联不是可翻译的;但 Translatable 只适用于简单属性。

然而,TranslatableConnector 包含一些功能使关联的翻译工作;通过使用一个小技巧:**我们在领域模型中存储目标对象的标识符,并从该标识符手动加载/存储**。

它按以下方式工作

  1. 确保您的域类添加了 TranslatableTrait

  2. 例如,为了使 Asset 引用可翻译,创建一个新属性 assetIdentifier,它是一个字符串,将包含资产标识符。这个属性应该被标记为 Gedmo\Translatable

  3. 然后,您需要配置 translationAssociationMapping,这告诉系统虚拟属性 asset 应该在内部存储为 assetIdentifier

  4. 此外,创建如以下所示的 assetOnSaveassetOnLoad 方法,这些方法将不同的表示形式进行转换

下面是完整示例

class Event {
    use TranslatableTrait;
    
    /**
     * @var array
     * @Flow\Transient
     */
    protected $translationAssociationMapping = array(
        'assetIdentifier' => 'asset'
    );
    
    /**
     * @Gedmo\Translatable
     * @var string
     */
    protected $assetIdentifier;

    /**
     * @Flow\Inject
     * @var AssetRepository
     */
    protected $assetRepository;

    /**
     * @Flow\Inject
     * @var PersistenceManagerInterface
     */
    protected $persistenceManager;

    /**
     * @Flow\Inject
     * @var PropertyMapper
     */
    protected $propertyMapper;


    /**
     * @return \Neos\Media\Domain\Model\Asset
     */
    public function getAsset() {
        return $this->assetOnLoad($this->assetIdentifier);
    }

    /**
     * !!! This accepts the raw array as the user uploaded it; as we need to trigger the property mapper inside
     *     assetOnSave manually.
     *
     * @param array $asset
     */
    public function setAsset($asset) {
        $this->assetIdentifier = $this->assetOnSave($asset);
    }

    /**
     * This method is called in two places:
     * - inside setAsset()
     * - automatically by the TranslatableTrait
     * 
     * @param array $asset
     */
    public function assetOnSave($asset) {
        $asset = $this->propertyMapper->convert($asset, 'Neos\Media\Domain\Model\AssetInterface');
        if ($asset === NULL) {
            $this->assetRepository->remove($asset);
            return NULL;
        } elseif ($this->persistenceManager->isNewObject($asset)) {
            $this->assetRepository->add($asset);
            return $this->persistenceManager->getIdentifierByObject($asset);
        } else {
            $this->assetRepository->update($asset);
            return $this->persistenceManager->getIdentifierByObject($asset);
        }
    }

    /**
     * This method is called in two places:
     * - inside getAsset()
     * - automatically by the TranslatableTrait
     * 
     * @param array $asset
     */
    public function assetOnLoad($assetIdentifier) {
        return $this->assetRepository->findByIdentifier($assetIdentifier);
    }
}

内部工作原理

(作为进一步参考 -- 如果我们对相关部分的 Flow Framework 进行一些修改,这也可以被简化)

  • Settings.yaml: 从反射中忽略 Gedmo 命名空间,添加 Translatable 监听器作为 Doctrine 事件监听器。这部分对于使用其他 Gedmo Doctrine 扩展也是相当标准的。

  • Objects.yaml: 将 TranslatableListener 标记为单例,这样您就可以将其注入到您的类中并设置当前语言。这部分也很直接。

  • Package.php: 使 Gedmo Translatable 的实体为 Doctrine 和反射所知。这部分实现相当复杂,请参阅类中的内联文档了解如何实现。

其他建议

  • 在处理 Gedmo Translatable 时使用 ORM 查询提示,以提高查询速度。
  • 如果您有大量具有许多翻译的大型数据集,请使用 翻译实体