
# WPML

WPML ne traduit les attributs d’un bloc personnalisé que dans la mesure où un fichier de configuration linguistique les déclare. Blockstudio stocke chaque valeur de champ dans le commentaire du bloc sous `blockstudio.attributes` ; chaque bloc doit donc avoir une entrée qui indique à WPML ses champs de texte et les identifiants de ses pièces jointes. La commande `wp bs wpml config` écrit ces entrées pour chaque bloc enregistré.

## Pourquoi les blocs ont besoin d’une configuration

WPML lit la configuration dans un fichier nommé `wpml-config.xml`, situé dans le dossier racine du thème actif et de chaque extension active. Pour une extension obligatoire qui consiste en un seul fichier, le dossier porte le nom du fichier sans `.php`. Voir [Fichiers de configuration des langues](https://wpml.org/documentation/support/language-configuration-files/) et [Rendre les blocs Gutenberg personnalisés traduisibles](https://wpml.org/documentation/support/language-configuration-files/make-custom-gutenberg-blocks-translatable/).

Un bloc sans entrée est laissé à la détection automatique des chaînes de WPML, qui propose à la traduction chaque attribut de chaîne du bloc. Pour un bloc Blockstudio qui comprend des valeurs de sélection, des références de fichiers, des URL et des classes CSS. Les traducteurs voient ces valeurs techniques à côté du texte réel, et la traduction d’une valeur de sélection ou d’une classe peut endommager le bloc.

## Générer la configuration

Affichez la configuration et enregistrez-la dans le dossier racine du thème ou de l’extension qui fournit les blocs :

```bash
wp bs wpml config > wp-content/themes/my-theme/wpml-config.xml
```

Ou laissez la commande écrire le fichier :

```bash
wp bs wpml config --file=wp-content/themes/my-theme/wpml-config.xml
```

Un bloc contenant un champ de texte, une image, un lien et un répéteur :

```json title="block.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" }
        ]
      }
    ]
  }
}
```

devient :

```xml title="wpml-config.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>
```

La valeur `style` n’est pas déclarée, alors WPML la copie telle quelle dans la traduction. Les identifiants `gallery` et `image` sont également copiés, et WPML remplace chacun d’eux par la pièce jointe correspondant à la langue de la page lors du rendu du bloc, afin qu’une image traduite puisse avoir son propre texte alternatif. Voir « Conversion automatique des identifiants dans les blocs » dans [Rendre les blocs Gutenberg personnalisés traduisibles](https://wpml.org/documentation/support/language-configuration-files/make-custom-gutenberg-blocks-translatable/). Si une pièce jointe n’a pas de traduction, WPML conserve l’identifiant d’origine.

## Ce qui est déclaré

La commande lit les blocs enregistrés après l’expansion des champs `custom/` et des champs de bloc, et après l’application des substitutions et des filtres d’attributs. Les champs que des [extensions](https://blockstudio.dev/fr/docs/extensions/) ajoutent à un bloc Blockstudio sont inclus. Les champs que les extensions ajoutent aux blocs natifs ou aux blocs d’autres extensions ne le sont pas, car ces blocs obtiennent leur configuration depuis WPML ou depuis leur propre extension.

| Champ | Déclaration |
| --- | --- |
| `text`, `textarea`, `richtext`, `wysiwyg` | Texte traduisible. |
| `link` | `title` comme texte et `url` avec `type="link"`, afin que WPML remplace un lien par sa traduction lorsqu’elle existe. |
| `files` | L’identifiant de pièce jointe stocké avec `type="post-ids"` et `sub-type="attachment"`. Avec `multiple`, un niveau nommé `*` pour la liste, qui correspond aussi à l’identifiant unique stocké par le champ lorsqu’un seul fichier est sélectionné. |
| `repeater` | Un niveau nommé `*` qui correspond à chaque ligne, avec les déclarations des champs de ligne. Les répéteurs imbriqués fonctionnent de la même manière. |
| `group` avec un `id` | Les champs du groupe, avec l’identifiant du groupe comme préfixe de clé (`cta_text` pour le champ `text` du groupe `cta`). |
| `group` sans `id`, `tabs` | Les champs, sans niveau propre. |
| Type de champ personnalisé enregistré avec `translate` défini sur `true` | Texte traduisible, comme un champ `text`. |
| Tous les autres types intégrés | Non déclarés. WPML copie la valeur telle quelle. |

Un bloc sans champ de texte déclaré reçoit `translate="0"`. WPML copie alors toutes ses valeurs et ne propose aucune d’entre elles à la traduction. Ses champs `files` restent déclarés dans l’entrée, car WPML convertit les identifiants de pièce jointe, quel que soit le résultat de `translate`. Les blocs internes sont traduits comme d’habitude.

Non déclarés :

- Les champs avec `hidden`, car leurs valeurs ne sont pas écrites par les éditeurs.
- Les champs avec `"translate": false`, voir ci-dessous.
- Les champs de [types de champs personnalisés](https://blockstudio.dev/fr/docs/blocks/attributes/custom-field-types/) qui ne sont pas enregistrés avec `translate` défini sur `true`. La commande affiche un avertissement pour chacun d’eux, car seul le type de champ sait si sa valeur contient du texte. Un `"translate": false` explicite sur un champ supprime également cet avertissement pour ce champ. Voir ci-dessous.
- Les attributs déclarés par un bloc dans son `attributes` natif plutôt que dans des champs Blockstudio.
- Les clés de stockage dont les champs ont des types différents, voir ci-dessous.

Chaque champ de texte est déclaré, y compris ceux qui contiennent une valeur technique telle qu’une classe CSS, sauf s’il définit `"translate": false`.

### Exclure un champ

Un champ de texte peut contenir une valeur qui doit rester identique dans toutes les langues : un identifiant de compte, une adresse e-mail, une ancre, une classe CSS. WPML le propose à la traduction comme tout autre texte, et une valeur traduite peut endommager le bloc. Définissez `translate` sur `false` pour exclure le champ de la configuration, afin que WPML copie sa valeur telle quelle dans la traduction :

```json title="block.json"
{
  "id": "account",
  "type": "text",
  "label": "Account handle",
  "translate": false
}
```

Sur un `group`, un `tabs` ou un `repeater`, `"translate": false` s’applique à tous les champs qu’il contient, y compris les conteneurs imbriqués. Un enfant ne peut pas réactiver un conteneur exclu avec `"translate": true`. Sur un champ `files`, `false` exclut aussi les identifiants de pièce jointe, de sorte que la traduction conserve les pièces jointes d’origine.

Omettre `translate` ou le définir sur `true` conserve le comportement existant : le type de champ décide. Cela ne rend pas traduisibles les champs masqués ou les types de valeur tels que `select`. L’option s’applique aux champs de bloc et d’extension, ne masque ni ne désactive leurs commandes d’édition et ne modifie pas leurs valeurs stockées. Relancez `wp bs wpml config` après avoir modifié le réglage et mettez à jour votre `wpml-config.xml` avec la configuration générée.

La valeur `label` de chaque clé correspond au libellé du champ, précédé des libellés des répéteurs et groupes englobants qui ont un identifiant. WPML l’affiche comme nom du champ dans l’éditeur de traduction. Les deux clés d’un champ `link` ajoutent `Link text` et `URL` au libellé. Ces suffixes sont traduits dans la langue du site : lancez donc la commande avec la langue utilisée par vos traducteurs.

### Types de champs personnalisés

Un type de champ qui stocke une simple chaîne de texte l’indique lors de son enregistrement. Définissez `translate` sur `true` dans la définition, ce qui nécessite que `attribute` soit `string` :

```php title="functions.php"
bs_register_field_type('acme/headline', [
  'attribute' => 'string',
  'translate' => true,
]);
```

La commande déclare ensuite chaque champ de ce type comme texte traduisible. Un champ peut toujours définir `"translate": false` pour s’exclure. Sans cette option, les champs de ce type sont exclus et signalés, comme auparavant.

### Modifier les libellés

Les libellés des champs sont rédigés pour l’éditeur de blocs et peuvent contenir des indications telles que « Image (facultatif) », qui n’ont aucun sens dans l’éditeur de traduction. Le filtre `blockstudio/wpml/config/label` reçoit chaque libellé avant son enregistrement, avec le contexte de la clé :

- `block` : le nom du bloc.
- `path` : le chemin de stockage du champ sous `blockstudio.attributes`, avec un niveau `*` pour les lignes de chaque répéteur, par exemple `cards/*/link`.
- `field` : la définition du champ.
- `parents` : les libellés des répéteurs et groupes englobants avec un ID.
- `part` : `text` pour un champ texte, `title` ou `url` pour les deux clés d’un champ lien.

```php title="functions.php"
add_filter('blockstudio/wpml/config/label', function ($label, $context) {
  return str_replace(' (optional)', '', $label);
}, 10, 2);
```

Renvoyez une chaîne vide pour exclure le libellé d’une clé ; WPML affiche alors le libellé du bloc à la place. Une valeur de retour qui n’est pas une chaîne conserve le libellé d’origine. Relancez la commande après avoir modifié le filtre.

### Champs ayant la même clé de stockage

Deux champs peuvent avoir la même clé de stockage, par exemple un champ de bloc et un champ d’extension ayant le même `id`, ou le champ `text` d’un groupe ayant l’ID `cta` et un champ ayant l’ID `cta_text`. La commande ne déclare une telle clé que lorsque le contenu stocké est sans ambiguïté :

- Parmi les champs d’un bloc, en dehors des lignes de répéteur, Blockstudio enregistre un attribut par clé de stockage ; un champ ultérieur remplace donc un champ antérieur, quel que soit son type. Les champs des extensions d’un bloc suivent la même règle : un champ ultérieur, ou le champ d’une extension enregistrée ultérieurement, remplace le précédent.
- Un champ de bloc et un champ d’extension ayant la même clé restent tous deux actifs. Le modèle du bloc reçoit la valeur telle que définie par le champ du bloc, tandis que l’extension est appliquée avec son propre champ. La clé n’est déclarée qu’une seule fois lorsque les deux champs nécessitent la même déclaration : les deux sont des champs texte (`text`, `textarea`, `richtext` ou `wysiwyg`), les deux sont des liens, les deux sont des champs `files` (avec `multiple` sur l’un ou l’autre, la clé reçoit le niveau `*`), ou aucun des deux n’est déclaré, par exemple un `select` et un `number`. Deux répéteurs sont comparés champ par champ dans leurs lignes. Le libellé provient du champ du bloc.
- Deux champs ayant le même `id` dans les lignes d’un même répéteur restent eux aussi tous deux actifs et sont comparés de la même façon.

Lorsque les types diffèrent, par exemple pour un champ `text` dans le bloc et un champ `select` dans une extension, la valeur stockée est du texte ou une option de sélection, selon le contrôle qui l’a enregistrée. La commande ne déclare pas la clé et affiche un avertissement :

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

Renommez l’un des champs ou attribuez-leur le même type pour que la clé soit déclarée.

## Garder la configuration à jour

Relancez la commande après avoir ajouté, supprimé ou renommé des champs, puis incluez le fichier mis à jour dans le thème ou l’extension. Régénérez les configurations créées avant 7.7.5 pour y inclure les déclarations d’ID de pièce jointe. Après la mise à jour de l’original, les contenus existants affichent de nouveaux champs à traduire, comme indiqué dans le guide WPML ci-dessus.

Avec `--file`, la commande crée le fichier s’il n’existe pas. Dans un fichier existant, elle remplace uniquement le texte entre `<!-- blockstudio:start -->` et `<!-- blockstudio:end -->`, de sorte que les autres sections et les entrées des autres blocs restent inchangées :

```xml title="wpml-config.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>
```

Pour utiliser un fichier existant qui ne contient pas encore de marqueurs, ajoutez une fois les deux lignes de marqueur dans son élément `gutenberg-blocks`, ou ajoutez un élément `gutenberg-blocks` contenant les marqueurs si le fichier n’en a aucun. En l’absence de marqueurs, ou si le résultat ne constitue pas une configuration valide, la commande laisse le fichier inchangé et se termine avec une erreur.

Les entrées des blocs Blockstudio écrites à la main, telles que les entrées `translate="0"` qui masquent des valeurs techniques, ne sont plus nécessaires une fois que la section générée couvre le bloc. La commande signale chaque bloc déclaré plusieurs fois, afin que ces entrées puissent être supprimées.

## Textes des images dans les tâches de traduction

WPML ajoute à la tâche de traduction d’une page les textes des images qu’elle utilise : titre, texte alternatif, légende et description. Une fois la tâche terminée, WPML enregistre les textes traduits sur la pièce jointe dans la langue cible et crée cette pièce jointe si elle n’existe pas encore. Voir [Comment traduire les médias](https://wpml.org/documentation/translating-your-contents/media/).
WPML trouve les images dans les balises `<img>` du contenu, dans les galeries, dans l’image mise en avant et dans les blocs qu’il connaît. Un bloc Blockstudio stocke les ID de pièce jointe dans le commentaire du bloc ; WPML ne les trouve donc pas.

Lorsque WPML est actif, Blockstudio ajoute aux images trouvées les pièces jointes stockées dans les champs des blocs d’une page par cette fonctionnalité WPML :

- Les champs `files`, y compris les champs masqués, et les champs `attributes` avec `media` ; ce sont les mêmes champs que l’éditeur de blocs charge en tant que médias.
- Les champs des groupes, onglets, lignes de répéteur et blocs imbriqués.
- Les champs des [extensions](https://blockstudio.dev/fr/docs/extensions/), y compris ceux des blocs natifs et des blocs d’autres extensions, car leurs valeurs sont stockées dans les attributs du bloc étendu.

Les valeurs qui ne sont pas des ID de pièce jointe sont exclues. Aucune configuration n’est nécessaire et `wpml-config.xml` n’intervient pas. Sans WPML, aucune analyse n’est effectuée pour les tâches de traduction et la classe d’intégration des médias n’est pas chargée.

Cette fonctionnalité est distincte de la conversion des ID de pièce jointe : le XML généré indique à WPML quelle pièce jointe traduite afficher, tandis que cette intégration lui indique quels textes des pièces jointes inclure dans une tâche de traduction. Les références de chaînes et les ID d’articles qui ne sont pas des pièces jointes ne sont pas ajoutés aux tâches de traduction des médias. Pour les blocs Blockstudio, les valeurs enregistrées dans les champs imbriqués sont prioritaires sur les valeurs de premier niveau, comme lors du rendu.

Les textes ne sont inclus dans la tâche que si l’une des options de texte des images sous WPML > Paramètres > Traduction des médias est activée : « Détecter automatiquement les meilleures options pour traduire les textes des images » ou « Traduire les textes de la médiathèque lors de la traduction du contenu », comme pour les images des blocs natifs.

Blockstudio signale les images via le filtre
`wpml_ids_of_media_used_in_post`, qui WPML s'applique aux médias d'un article dans
`PostWithMediaFiles`. Pour exclure une image des tâches, retirez son ID dans un
rappel sur le même filtre avec une priorité supérieure à 10 :

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