Traduzir blocos Gutenberg adicionais
Gato AI Translations for Polylang pode traduzir posts baseados em blocos.
O plugin vem com suporte para muitos blocos por padrão. Para tudo além disso — seus próprios blocos personalizados, ou blocos de plugins de terceiros que não incluem um wpml-config.xml — você pode estender o suporte via hooks PHP.
Traduzir strings
Para registrar atributos traduzíveis adicionais para um bloco, use o filtro gatompl:gutenberg_block_type_translatable_attribute_regexes.
Por que expressões regulares?
Um bloco Gutenberg é persistido em post_content como um comentário HTML que carrega os atributos JSON do bloco, seguido pelo HTML renderizado do bloco, por exemplo:
<!-- wp:my-plugin/my-block {"title":"Hello"} -->
<div class="wp-block-my-plugin-my-block">Hello</div>
<!-- /wp:my-plugin/my-block -->Traduzir um bloco significa encontrar a substring específica a traduzir dentro desse markup, substituí-la pela sua tradução e deixar todo o resto intocado (nome do bloco, outros atributos, estrutura HTML, blocos ao redor). As expressões regulares são a forma como o plugin identifica exatamente qual substring substituir: o texto antes e depois do valor é capturado em grupos, e o próprio valor é a parte que é trocada.
Atributos de string padrão (armazenados no JSON do bloco)
Se a propriedade é uma string normal armazenada nos atributos JSON do bloco, passe true e o plugin usará sua expressão regular padrão.
Por exemplo, para traduzir os atributos daysLabel, hoursLabel, minutesLabel e secondsLabel do bloco kadence/countdown — cujo markup se parece com este:
<!-- wp:kadence/countdown {"uniqueID":"_abc123","date":"2026-12-31 00:00:00","daysLabel":"Days","hoursLabel":"Hours","minutesLabel":"Minutes","secondsLabel":"Seconds"} -->
<div class="wp-block-kadence-countdown">…</div>
<!-- /wp:kadence/countdown -->…registre os atributos assim:
add_filter(
'gatompl:gutenberg_block_type_translatable_attribute_regexes',
static function (array $regexes): array {
$regexes['kadence/countdown'] = [
'daysLabel' => true,
'hoursLabel' => true,
'minutesLabel' => true,
'secondsLabel' => true,
];
return $regexes;
}
);O valor true é expandido internamente para esta expressão regular padrão:
#(<!-- wp:%3$s \{.*?\"%2$s\":\")%1$s(\".*?\}/?-->)#…onde os marcadores são:
%1$s→ o valor do atributo%2$s→ o nome do atributo%3$s→ o nome do bloco
Para o atributo daysLabel em kadence/countdown, os marcadores são substituídos assim: %3$s → kadence/countdown, %2$s → daysLabel, %1$s → Days, produzindo:
#(<!-- wp:kadence/countdown \{.*?\"daysLabel\":\")Days(\".*?\}/?-->)#Apenas Days é substituído; o nome do bloco, os outros atributos e o comentário de fechamento são preservados pelos grupos de captura.
A forma da expressão regular é:
#(tudo antes)valor do atributo(tudo depois)#Strings armazenadas no HTML do bloco
Se o valor não está armazenado nos atributos JSON, mas dentro do HTML renderizado, forneça sua própria expressão regular. Você pode usar %s (em vez de %1$s) onde vai o valor do atributo, e ter o nome do bloco e o nome do atributo codificados diretamente na expressão regular.
Exemplo — traduzir o atributo content do bloco generateblocks/text. Seu markup se parece com este — note que Hello world não está no JSON, ele fica entre as tags renderizadas:
<!-- wp:generateblocks/text {"uniqueId":"abc123","tagName":"p"} -->
<p class="gb-text">Hello world</p>
<!-- /wp:generateblocks/text -->A expressão regular padrão nunca encontraria essa substring, então você fornece a sua própria:
add_filter(
'gatompl:gutenberg_block_type_translatable_attribute_regexes',
static function (array $regexes): array {
$regexes['generateblocks/text'] = [
'content' => '#(<!-- wp:generateblocks/text [^>]*?-->\n?<[a-z0-9]+ ?[^>]*?>)%s(</[a-z0-9]+>\n?<!-- /wp:generateblocks/text -->)#',
];
return $regexes;
}
);Quando o mesmo valor aparece em múltiplos lugares
Se o mesmo atributo aparece tanto nos atributos JSON quanto no HTML (ou em dois lugares diferentes), passe um array de expressões regulares — cada uma precisa ser acionada para que cada cópia da string seja traduzida.
Por exemplo, no bloco generateblocks/media, alt e title são armazenados tanto dentro de htmlAttributes no JSON quanto como atributos HTML no <img> renderizado:
<!-- wp:generateblocks/media {"mediaId":42,"htmlAttributes":{"alt":"Cat sitting","title":"My cat"}} -->
<figure class="gb-media"><img src="…" alt="Cat sitting" title="My cat"></figure>
<!-- /wp:generateblocks/media -->Duas expressões regulares por atributo — uma mirando o JSON, outra mirando o <img> — garantem que ambas as cópias permaneçam sincronizadas após a tradução:
add_filter(
'gatompl:gutenberg_block_type_translatable_attribute_regexes',
static function (array $regexes): array {
$regexes['generateblocks/media'] = [
'htmlAttributes.alt' => [
'#(<!-- wp:generateblocks/media \{.*?\"htmlAttributes\":\{.*?\"alt\":\")%s(\".*?\}.*?\} -->)#',
'#(<!-- wp:generateblocks/media [^>]*?-->\n?.*<img [^>]*alt=\")%s(\"[^>]*?>.*\n?<!-- /wp:generateblocks/media -->)#',
],
'htmlAttributes.title' => [
'#(<!-- wp:generateblocks/media \{.*?\"htmlAttributes\":\{.*?\"title\":\")%s(\".*?\}.*?\} -->)#',
'#(<!-- wp:generateblocks/media [^>]*?-->\n?.*<img [^>]*title=\")%s(\"[^>]*?>.*\n?<!-- /wp:generateblocks/media -->)#',
],
];
return $regexes;
}
);Se o valor do atributo é um objeto JSON, você pode mirar uma sub-propriedade específica usando um . (ponto) no nome do atributo, como mostrado acima com htmlAttributes.alt e htmlAttributes.title em generateblocks/media.
Desativar a tradução de um atributo traduzido automaticamente
Passar false ou null remove a tradução de um atributo que o plugin de outra forma traduziria automaticamente. Isso é útil, por exemplo, para excluir um atributo de string específico da tradução automática em blocos somente PHP, ou para blocos importados de um wpml-config.xml cujos atributos declarados você não quer traduzir:
add_filter(
'gatompl:gutenberg_block_type_translatable_attribute_regexes',
static function (array $regexes): array {
// Disable translation of the `header` attribute on the
// `my-plugin/duplicate-alert` block (either form works)
unset($regexes['my-plugin/duplicate-alert']['header']);
$regexes['my-plugin/duplicate-alert']['implications'] = false;
return $regexes;
}
);Traduzir referências a entidades
Referências a entidades (um ID de post/mídia/termo/menu armazenado em um atributo de bloco) podem ser remapeadas para a entidade correspondente no idioma de destino no momento da tradução. Use um dos seguintes filtros dependendo do tipo de referência:
| Tipo de referência | Filtro |
|---|---|
| Custom posts e mídia | gatompl:gutenberg_block_type_custompost_and_media_reference_attribute_regexes |
| Termos de taxonomia | gatompl:gutenberg_block_type_taxonomy_term_reference_attribute_regexes |
| Menus por ID | gatompl:gutenberg_block_type_menu_reference_by_id_attribute_regexes |
| Menus por slug | gatompl:gutenberg_block_type_menu_reference_by_slug_attribute_regexes |
Cada filtro recebe a mesma estrutura que o filtro de atributos traduzíveis (true para a expressão regular padrão, uma string ou array para expressões regulares personalizadas).
Por exemplo, o bloco woocommerce/single-product armazena o produto vinculado como um productId numérico:
<!-- wp:woocommerce/single-product {"productId":42} /-->Quando o post é traduzido, esse 42 (o produto no idioma de origem) precisa ser remapeado para seu equivalente no idioma de destino (digamos 87). Marque productId como uma referência de custom post para que o plugin capture e troque o ID no momento da tradução:
add_filter(
'gatompl:gutenberg_block_type_custompost_and_media_reference_attribute_regexes',
static function (array $regexes): array {
$regexes['woocommerce/single-product'] = [
'productId' => true,
// …ou uma expressão regular personalizada se `productId` não estiver armazenado no formato JSON padrão:
// 'productId' => '#(<!-- wp:woocommerce/single-product \{.*?\"productId\":)%s([,\}].*? /?-->)#',
];
return $regexes;
}
);Use o mesmo padrão para os outros tipos de referência. Cada tipo tem o mesmo aspecto no markup do bloco — um ID numérico ou um slug embutido no JSON — o que difere é como o plugin o resolve no idioma de destino:
<!-- wp:my-plugin/related-category {"categoryId":17} /-->
<!-- wp:my-plugin/menu-picker {"menuId":5} /-->
<!-- wp:my-plugin/menu-picker {"menuSlug":"main-nav"} /-->// Taxonomy term reference
add_filter(
'gatompl:gutenberg_block_type_taxonomy_term_reference_attribute_regexes',
static function (array $regexes): array {
$regexes['my-plugin/related-category'] = [
'categoryId' => true,
];
return $regexes;
}
);
// Menu reference by ID
add_filter(
'gatompl:gutenberg_block_type_menu_reference_by_id_attribute_regexes',
static function (array $regexes): array {
$regexes['my-plugin/menu-picker'] = [
'menuId' => true,
];
return $regexes;
}
);
// Menu reference by slug
add_filter(
'gatompl:gutenberg_block_type_menu_reference_by_slug_attribute_regexes',
static function (array $regexes): array {
$regexes['my-plugin/menu-picker'] = [
'menuSlug' => true,
];
return $regexes;
}
);Descobrindo os nomes dos atributos
A maneira mais rápida de encontrar os nomes dos atributos e como eles são armazenados é executar a query GraphQL Translate custom posts e examinar o campo de resposta blockFlattenedDataItems para o bloco em questão.
Consulte o guia Recuperando dados do page builder para traduzir para saber como executar essa query e ler seu resultado.
Contornando blocos cujos atributos precisam de processamento
Os hooks acima pressupõem que o valor do atributo exposto via blockFlattenedDataItems já é o valor a traduzir (um escalar ou array).
Se o valor está encapsulado — por exemplo, o atributo armazena <li>Some text</li> e você quer que apenas Some text seja traduzido — você precisa extraí-lo primeiro via o filtro gatompl:gutenberg_block_flattened_data_item_attributes.
O bloco generateblocks/image é um exemplo real: seus atributos alt e title não são expostos como atributos independentes, eles ficam dentro do HTML de innerContent e precisam ser extraídos com uma expressão regular.
add_filter(
'gatompl:gutenberg_block_flattened_data_item_attributes',
static function (?\stdClass $attributes, string $blockTypeName, \stdClass $blockDataItem): ?\stdClass {
if ($attributes === null || $blockTypeName !== 'generateblocks/image') {
return $attributes;
}
$innerContent = $blockDataItem->innerContent ?? null;
if (!is_array($innerContent) || !isset($innerContent[0]) || !is_string($innerContent[0])) {
return $attributes;
}
$html = $innerContent[0];
if (preg_match('#<img [^>]*alt="([^"]*)"[^>]*?>#', $html, $matches) === 1 && $matches[1] !== '') {
$attributes->alt = $matches[1];
}
if (preg_match('#<img [^>]*title="([^"]*)"[^>]*?>#', $html, $matches) === 1 && $matches[1] !== '') {
$attributes->title = $matches[1];
}
return $attributes;
},
10,
3
);Uma vez que alt e title existam no objeto de atributos, os hooks baseados em expressões regulares acima podem mirá-los como qualquer outro atributo.
Onde encontrar exemplos
As próprias integrações do plugin são boas referências reais. Explore estes arquivos dentro do plugin que você instalou:
- Expressões regulares de atributos de bloco:
wp-content/plugins/gato-ai-translations-for-polylang/src/Constants/BlockTypeAttributeValues.php - Pré-processamento de atributos de bloco:
wp-content/plugins/gato-ai-translations-for-polylang/src/ConditionalOnContext/LicenseIsActive/Hooks/CoreBlockFlattenedDataItemAttributesHookSet.php