fsi / translatable
处理翻译的库
Requires
- php: ^8.1
- ext-intl: *
- beberlei/assert: ^3.2
Requires (Dev)
- ext-pdo_sqlite: *
- codeception/codeception: ^5.1
- codeception/module-asserts: ^3.0
- codeception/module-doctrine: ^3.1
- codeception/module-symfony: *
- doctrine/dbal: ^3.4
- doctrine/doctrine-bundle: ^2.4
- doctrine/lexer: ^1.2|^2.0|^3.0
- doctrine/orm: ^2.9|^3.0
- doctrine/persistence: ^2.0|^3.0
- fsi/files: ^2.0.4
- guzzlehttp/psr7: ^2.0
- monolog/monolog: ^1.25
- nyholm/psr7: ^1.4
- oneup/flysystem-bundle: ^4.4
- php-http/guzzle7-adapter: ^1.0
- php-http/httplug-bundle: ^1.20
- phpstan/phpstan: ^1.10.39
- phpstan/phpstan-beberlei-assert: ^1.0
- phpstan/phpstan-doctrine: ^1.3
- phpstan/phpstan-phpunit: ^1.3
- phpunit/phpunit: ^9.5
- psr/http-client: ^1.0
- squizlabs/php_codesniffer: ^3.7
- symfony/asset: ^4.4.30|^5.4|^6.0
- symfony/config: ^4.4.30|^5.4|^6.0
- symfony/console: ^4.4.30|^5.4|^6.0
- symfony/dependency-injection: ^4.4.30|^5.4|^6.0
- symfony/finder: ^4.4.30|^5.4|^6.0
- symfony/form: ^4.4.30|^5.4|^6.0
- symfony/framework-bundle: ^4.4.30|^5.4|^6.0
- symfony/http-client: ^4.4.30|^5.4|^6.0
- symfony/http-foundation: ^4.4.30|^5.4|^6.0
- symfony/http-kernel: ^4.4.30|^5.4|^6.0
- symfony/mime: ^4.4.30|^5.4|^6.0
- symfony/monolog-bundle: ^3.7
- symfony/property-access: ^5.4|^6.3
- symfony/routing: ^4.4.30|^5.4|^6.0
- symfony/translation: ^4.4.30|^5.4|^6.0
- symfony/twig-bundle: ^4.4.30|^5.4|^6.0
- symfony/validator: ^4.4.30|^5.4|^6.0
- twig/twig: ^3.7
README
该组件旨在为多种语言提供创建可翻译对象的方法。该理念主要有两个概念 - 可翻译和翻译。可翻译的对象其数据存储在一个翻译对象集合中,每个对象对应一个单独的区域。每个这些都有一个独立的配置对象,其中存储了所有必要的信息,这些信息描述了两者之间的关系。这些是TranslatableConfiguration
和TranslationConfiguration
,可以通过ConfigurationResolver
检索。
可翻译对象的生存周期由Entity
目录中的一些专用类处理,这些类是TranslationLoader
、TranslationUpdater
和TranslationCleaner
。它们将
- 设置可翻译对象的当前区域设置
- 从翻译中加载数据(如果存在的话)
- 创建新的翻译或更新现有的翻译
- 删除空的翻译对象
但是,它们不能单独工作,需要通过订阅者连接到您正在使用的任何存储机制(ORM、ODM等)。目前,只有Doctrine / Symfony组合提供了开箱即用的集成。
哪些字段可以是可翻译字段?
当涉及到存储时,所有以下内容的映射/配置都应该包含在翻译实体文件中,而不是可翻译。
默认情况下
- 标量值(字符串、整数、浮点数),
- 对象(尽管它们的存储可能需要通过某些集成来处理),
WebFile
对象从fsi/files
组件将工作并持久化/删除与翻译实体一起,
与Doctrine一起
- 嵌入式(嵌套),尽管嵌入式本身不能有翻译,因为没有标识符,
- 一对一关系,
- 集合关系,
示例实体
让我们考虑一个具有ArticleTranslation
翻译的可翻译Article
实体的例子
declare(strict_types=1); namespace Tests\Entity; use DateTimeImmutable; use FSi\Component\Translatable\Integration\Doctrine\ORM\ProxyTrait; class Article { use ProxyTrait; private ?int $id = null; private ?string $locale = null; private ?DateTimeImmutable $publicationDate = null; private ?string $title = null; private ?string $description = null; // getters and setters will probably be required for whatever // mechanism you use for modifying the object, though are not // required by the component itself } declare(strict_types=1); namespace Tests\Entity; class ArticleTranslation { private ?int $id = null; private ?string $locale = null; private ?string $title = null; private ?string $description = null; private ?Article $article; // getters and setters are not required }
如你所见,它们几乎是一致的,除了可翻译中的$publicationDate
字段和翻译中的$article
字段。这是因为$publicationDate
不是可翻译字段(它直接存储在可翻译对象中),而$article
作为将翻译绑定到可翻译对象的方式。这两个字段都有locale
字段:可翻译存储当前区域,翻译存储创建时的区域。
为了使组件能够识别这些对象作为可翻译-翻译对,您需要定义它们的配置。当使用Symfony时,这可以像这样简单地完成
fsi_translatable: entities: Tests\Entity\Article: localeField: locale # this can be skipped for a default value of locale fields: [title, description] disabledAutoTranslationsUpdate: false # optional and false by default translation: localeField: locale # also can be skipped class: Tests\FSi\ArticleTranslation relationField: article
重要
- 两个对象都需要有相同的字段。不可能将可翻译字段映射到翻译实体中的不同字段。
- 翻译对象不能有必需的构造函数参数。
如果您想手动创建配置,您需要向ConfigurationResolver
提供一个包含必要数据的TranslatableConfiguration
对象的集合。
用法(Doctrine + Symfony)
除非您直接在Kernel类中加载您的束和配置,否则您需要在config/bundles.php
中加载Translatable束
return [ // Doctrine and Symfony bundles FSi\Component\Translatable\Integration\Symfony\TranslatableBundle::class => ['all' => true] ];
然后添加一个config/packages/fsi_translatable.yaml
文件
fsi_translatable: entities: # configuration for specific entities, see above for an example
当然,您可以通过PHP手动加载配置,但目前不支持XML配置。
之后,组件将主要自动运行。当创建一个新的可翻译对象,并且任何一个可翻译字段被填写时,将通过 LocaleProvider
对象获取当前区域设置,创建一个新的翻译实例,然后将可翻译对象的相关内容复制到其中。在随后的可翻译对象加载过程中,数据将从存储的翻译中重新加载。对可翻译对象中可翻译字段的任何修改将自动更新现有翻译。如果 LocaleProvider
提供的区域设置不同,将创建一个新的翻译。
如果出于某种原因您需要直接获取单个/所有翻译对象,可以通过 TranslationProvider
来实现。
如果移除了一个可翻译对象,将通过 Doctrine 的实体管理器(通过 TranslationManager
)清除所有翻译,因此任何监听翻译实体生命周期事件的订阅者也将被触发。
重要
- 如果您有可翻译的集合字段,您必须在翻译对象构造函数中 初始化 它们。
区域设置获取和持久化
Symfony 的 LocaleProvider
实现将尝试从三个来源获取区域设置
- 它将检查持久化的区域设置(关于这一点稍后详细说明)。
- 如果找不到,它将从
RequestStack
中获取一个当前的Request
对象,并从该对象中检索区域设置。 - 如果没有当前的
Request
(这对于控制台命令和一些测试环境将是这种情况),它将返回FrameworkBundle
中的默认区域设置。
如果您想手动设置从 LocaleProvider
返回的区域设置,调用 LocaleProvider::saveLocale()
方法将将其持久化到服务中,直到下一次请求。您也可以手动调用 LocaleProvider::resetSavedLocale()
来清除它。
禁用自动翻译更新
如果您更喜欢手动创建翻译,并且不想让它们被可翻译实体的内容覆盖,可以在其配置中将 disableAutoTranslationsUpdate
选项设置为 true
。这将防止在刷新操作期间创建或更新翻译,但仍然会在当前区域设置存在翻译实体的情况下,将翻译实体的内容填充到可翻译实体中。