sandstorm / gedmotranslatableconnector
连接器,使 Gedmo Translatable 能够与 Neos Flow 一起工作
Requires
- gedmo/doctrine-extensions: ^3.0
- neos/flow: ^7.0
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
方法时立即更新和持久化。这通常可能不是理想的,因为它立即持久化实体。禁用此设置并调用 TranslatableManager
的 flush()
方法以根据您的需求持久化更改。
在另一个区域获取对象
如果您已在一个特定区域加载了对象,但后来需要将对象更改为另一个区域,可以调用方法 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 包含一些功能使关联的翻译工作;通过使用一个小技巧:**我们在领域模型中存储目标对象的标识符,并从该标识符手动加载/存储**。
它按以下方式工作
-
确保您的域类添加了
TranslatableTrait
。 -
例如,为了使
Asset
引用可翻译,创建一个新属性assetIdentifier
,它是一个字符串,将包含资产标识符。这个属性应该被标记为Gedmo\Translatable
。 -
然后,您需要配置
translationAssociationMapping
,这告诉系统虚拟属性asset
应该在内部存储为assetIdentifier
。 -
此外,创建如以下所示的
assetOnSave
和assetOnLoad
方法,这些方法将不同的表示形式进行转换
下面是完整示例
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 和反射所知。这部分实现相当复杂,请参阅类中的内联文档了解如何实现。