跳转到正文

WPML

WPML 只能按照语言配置文件中的声明翻译自定义区块的属性。Blockstudio 会将每个字段值存储在区块注释中的 blockstudio.attributes 下,因此每个区块都需要一个条目,将 WPML 指向其文本字段和附件 ID。wp bs wpml config 命令会为每个已注册的区块写入这些条目。

为什么区块需要配置

WPML会从当前启用的主题和每个已启用插件的根目录中名为wpml-config.xml的文件读取配置。对于单文件的必需插件,文件夹名称就是文件名去掉.php后的部分。请参阅语言配置文件和使自定义Gutenberg区块支持翻译。

没有条目的区块会交由WPML自动检测字符串,它会将区块的每个字符串属性提供给翻译。对于包含选择值、文件引用、URL 和CSS类的Blockstudio区块,译者会在真实文本旁看到这些技术值,而翻译后的选择值或类可能会导致区块无法正常工作。

生成配置

打印配置,并将其保存到提供这些区块的主题或插件的根目录中:

命令行
wp bs wpml config > wp-content/themes/my-theme/wpml-config.xml

也可以让命令写入文件:

命令行
wp bs wpml config --file=wp-content/themes/my-theme/wpml-config.xml

一个包含文本字段、图像、链接和重复器的区块:

JSON
{
  "name": "my-theme/cards",
  "title": "Cards",
  "blockstudio": {
    "attributes": [
      { "id": "heading", "type": "text", "label": "Heading" },
      { "id": "gallery", "type": "files", "label": "Gallery", "multiple": true },
      {
        "id": "style",
        "type": "select",
        "label": "Style",
        "options": [
          { "value": "light", "label": "Light" },
          { "value": "dark", "label": "Dark" }
        ]
      },
      {
        "id": "cards",
        "type": "repeater",
        "label": "Cards",
        "attributes": [
          { "id": "title", "type": "text", "label": "Title" },
          { "id": "image", "type": "files", "label": "Image" },
          { "id": "link", "type": "link", "label": "Button" }
        ]
      }
    ]
  }
}

会变成:

XML
<wpml-config>
	<gutenberg-blocks>
		<!-- blockstudio:start -->
		<!-- Generated by wp bs wpml config. Run it again after changing block fields; edits between the markers are replaced. -->
		<gutenberg-block type="my-theme/cards" translate="1" label="Cards">
			<key name="blockstudio">
				<key name="attributes">
					<key name="heading" label="Heading" />
					<key name="gallery">
						<key name="*" type="post-ids" sub-type="attachment" />
					</key>
					<key name="cards">
						<key name="*">
							<key name="title" label="Cards: Title" />
							<key name="image" type="post-ids" sub-type="attachment" />
							<key name="link">
								<key name="title" label="Cards: Button: Link text" />
								<key name="url" type="link" label="Cards: Button: URL" />
							</key>
						</key>
					</key>
				</key>
			</key>
		</gutenberg-block>
		<!-- blockstudio:end -->
	</gutenberg-blocks>
</wpml-config>

style值未声明,因此WPML会原样复制到翻译中。gallery和image ID 也会被复制,渲染区块时,WPML会将每个 ID 替换为当前页面语言对应的附件,因此翻译后的图像可以拥有自己的替代文本。请参阅使自定义Gutenberg区块支持翻译中的“自动转换区块中的 ID”。如果附件没有对应的翻译,WPML会保留原始 ID。

声明内容

命令会读取已注册的区块,此时custom/字段和区块字段已展开,并已应用覆盖项和属性筛选器。扩展添加到Blockstudio区块的字段也会包含在内。扩展添加到核心区块或其他插件区块的字段则不会包含,因为这些区块从WPML或各自所属的插件中获取配置。

字段 声明
text、textarea、richtext、wysiwyg 可翻译文本。
link 将title作为文本,将url与type="link"一起使用,因此WPML会在有可用翻译时将链接替换为对应译文。
files 带有type="post-ids"和sub-type="attachment"的已存附件 ID。使用multiple时,为列表指定名为*的层级;这也匹配字段选择单个文件时存储的单个 ID。
repeater 指定名为*的层级以匹配每一行,并包含行字段的声明。嵌套重复器的工作方式相同。
带有id的group 组内字段,以组 ID 作为键前缀(组cta中的字段text使用cta_text)。
没有id的group,tabs 这些字段没有自己的层级。
注册时将translate设为true的自定义字段类型 可翻译文本,类似text字段。
其他所有内置类型 不声明。WPML会原样复制该值。

没有声明文本字段的区块会获得translate="0"。随后WPML会复制其中的所有值,不会提供任何内容供翻译。其files字段仍会在条目中声明,因为WPML无论translate如何设置,都会转换附件 ID。内部区块仍按常规方式翻译。

未声明的字段:

  • 带有hidden的字段,因为编辑者不会写入这些值。
  • 带有"translate": false的字段,见下文。
  • 自定义字段类型中未将translate设为true的字段。命令会为每个此类字段打印警告,因为只有字段类型才知道其值是否包含文本。对字段显式设置"translate": false也会抑制该字段的警告。见下文。
  • 区块在原生attributes中声明、而非作为Blockstudio字段声明的属性。
  • 字段类型不同的存储键,见下文。

每个文本字段都会被声明,包括保存技术值的字段,例如CSS类,除非它设置了"translate": false。

排除字段

文本字段可能保存必须在所有语言中保持一致的值,例如账号名称、电子邮件地址、锚点或CSS类。WPML会像处理其他文本一样将其提供给翻译,而翻译后的值可能会导致区块无法正常工作。将translate设为false,即可从配置中排除该字段,让WPML将其值原样复制到翻译中:

JSON
{
  "id": "account",
  "type": "text",
  "label": "Account handle",
  "translate": false
}

对于group、tabs或repeater,"translate": false适用于其中的每个字段,包括嵌套容器。子项无法通过"translate": true覆盖已选择排除的容器。对于files字段,false也会排除附件 ID,因此翻译会保留原始附件。

省略translate或将其设为true会保留现有行为:由字段类型决定。它不会让隐藏字段或select等值类型变得可翻译。此选项适用于区块字段和扩展字段,不会隐藏或禁用其编辑器控件,也不会更改其存储值。更改设置后,请再次运行wp bs wpml config,并使用生成的配置更新你的wpml-config.xml。

每个键的label是字段标签,前面带有具有 ID 的外层重复器和组的标签。WPML会在翻译编辑器中将其显示为字段名称。link字段的两个键会在标签中添加Link text和URL。这些后缀会翻译成站点语言,因此请使用译者工作的语言区域设置运行命令。

自定义字段类型

存储纯文本字符串的字段类型会在注册时声明这一点。在定义中将translate设为true,并确保attribute为string:

PHP
bs_register_field_type('acme/headline', [
  'attribute' => 'string',
  'translate' => true,
]);

该命令随后会将此类型的每个字段都声明为可翻译文本。字段仍可设置 "translate": false,将自身排除在外。未启用此选项时,此类型的字段会像以前一样被排除并报告。

更改标签

字段标签是为区块编辑器编写的,可能带有“图像(可选)”之类的提示,而这些提示在翻译编辑器中毫无意义。blockstudio/wpml/config/label 过滤器会在标签写入之前接收每个标签,并附带键的上下文:

  • block:区块名称。
  • path:blockstudio.attributes 下方字段的存储路径,每个重复器行还会有一个 * 层级,例如 cards/*/link。
  • field:字段定义。
  • parents:外层重复器和带 ID 的分组标签。
  • part:文本字段的 text,链接字段两个键的 title 或 url。
PHP
add_filter('blockstudio/wpml/config/label', function ($label, $context) {
  return str_replace(' (optional)', '', $label);
}, 10, 2);

返回空字符串即可排除某个键的标签,这样 WPML 就会显示区块标签。返回非字符串值则会保留原标签。更改过滤器后,请再次运行该命令。

存储键相同的字段

两个字段最终可能使用相同的存储键,例如区块字段和扩展字段具有相同的 id,或者 ID 为 cta 的分组中有字段 text,同时还有 ID 为 cta_text 的字段。只有在明确该键存储的内容时,命令才会声明此类键:

  • 在区块字段中,重复器行之外,Blockstudio 会为每个存储键注册一个属性,因此后面的字段会替换前面的字段,无论它们的类型如何。区块扩展中的字段也遵循相同规则:后面的字段,或后注册的扩展中的字段,会替换前面的字段。
  • 具有相同键的区块字段和扩展字段都会生效。区块模板接收按区块字段定义的值,而扩展则使用自己的字段应用该值。只有当两个字段需要相同声明时,该键才只声明一次:两个字段都是文本字段(text、textarea、richtext 或 wysiwyg),两个都是链接,两个都是 files 字段(任一字段带有 multiple 时,该键会采用 * 层级),或者两个字段都不声明,例如一个 select 和一个 number。两个重复器会按行逐字段比较。标签取自区块字段。
  • 同一重复器各行中具有相同 id 的两个字段也都会生效,并按相同方式比较。

类型不同时,例如区块中的 text 字段与扩展中的 select,存储值可能是文本,也可能是选择项,具体取决于写入该值的控件。命令不会声明该键,并会打印一条警告:

命令行
Warning: Not declared, the fields that store this key have different types: my-theme/cards: tone (text in the block, select in an extension)

重命名其中一个字段,或将两个字段设为相同类型,即可声明该键。

保持配置为最新状态

添加、移除或重命名字段后,请再次运行该命令,并将更新后的文件随主题或插件一同发布。重新生成在 7.7.5 之前创建的配置,以纳入附件 ID 声明。对于原始内容更新后才出现的新字段,已有内容即可进行翻译,具体如上方 WPML 指南所述。

使用 --file 时,命令会创建缺失的文件。对于已有文件,命令只会替换 <!-- blockstudio:start --> 与 <!-- blockstudio:end --> 之间的文本,因此其他区块的章节和条目会保持原样:

XML
<wpml-config>
	<custom-types>
		<custom-type translate="1">book</custom-type>
	</custom-types>
	<gutenberg-blocks>
		<gutenberg-block type="my-plugin/map" translate="1">
			<key name="caption" />
		</gutenberg-block>
		<!-- blockstudio:start -->
		<!-- blockstudio:end -->
	</gutenberg-blocks>
</wpml-config>

要使用尚无标记的现有文件,请在其 gutenberg-blocks 元素内添加这两行标记,或者在文件尚无 gutenberg-blocks 元素时添加一个带有标记的元素。如果缺少标记,或者结果不是有效配置,命令会保持文件不变并报错退出。

手动编写的 Blockstudio 区块条目(例如用于隐藏技术值的 translate="0" 条目)在生成章节涵盖该区块后便不再需要。命令会对每个重复声明的区块发出警告,因此可以移除这些条目。

翻译任务中的图像文本

WPML 会将页面所用图像的文本加入该页面的翻译任务:标题、替代文本、说明文字和描述。任务完成后,WPML 会将译文写入目标语言的附件;如果目标语言尚无对应附件,则会创建一个。请参阅如何翻译媒体。 WPML 会查找内容中的 <img> 标签、图库、特色图像以及它支持的区块中的图像。Blockstudio 区块会在区块注释中存储附件 ID,因此 WPML 找不到其中的图像。

启用 WPML 后,Blockstudio 会将页面区块字段中存储的附件加入已找到的图像 WPML:

  • files 字段(包括隐藏字段),以及带有 media 的 attributes 字段;区块编辑器会将这些相同字段作为媒体加载。
  • 分组、选项卡、重复器行和内部区块中的字段。
  • 扩展的字段,包括核心区块和其他插件的区块中的字段,因为这些值存储在被扩展区块的属性中。

非附件 ID 的值会被排除。无需进行任何配置,也不会涉及 wpml-config.xml。未启用 WPML 时,不会扫描翻译任务,也不会加载媒体集成类。

这与附件 ID 转换彼此独立:生成的 XML 会告知 WPML 应渲染哪个译文附件,而此集成会告知它应将哪些附件文本加入翻译任务。字符串引用和非附件文章的 ID 不会加入媒体任务。在 Blockstudio 区块中,已保存的嵌套字段值优先于顶层值,渲染时也是如此。

只有启用了 WPML > Settings > Media Translation 下的某个图像文本选项时,这些文本才会成为任务的一部分:“自动检测翻译图像文本的最佳选项”或“翻译内容时翻译媒体库文本”。核心区块中的图像也是如此。

Blockstudio 通过筛选器报告图像 wpml_ids_of_media_used_in_post,该筛选器 WPML 会应用于 PostWithMediaFiles 中帖子的媒体。若要将某张图像排除在任务之外,请在优先级高于 10 的同一筛选器回调中移除其 ID:

PHP
add_filter(
	'wpml_ids_of_media_used_in_post',
	function ( $ids ) {
		return array_values( array_diff( $ids, array( 42 ) ) );
	},
	20
);