
# WPML

WPML übersetzt die Attribute eines benutzerdefinierten Blocks nur so weit, wie es eine Sprachkonfigurationsdatei festlegt. Blockstudio speichert jeden Feldwert im Blockkommentar unter `blockstudio.attributes`. Deshalb benötigt jeder Block einen Eintrag, der WPML auf seine Textfelder und Anhang-IDs verweist. Der Befehl `wp bs wpml config` erstellt diese Einträge für jeden registrierten Block.

## Warum Blöcke eine Konfiguration benötigen

WPML liest die Konfiguration aus einer Datei namens `wpml-config.xml` im Stammordner des aktiven Themes und jedes aktiven Plugins. Bei einem Must-use-Plugin, das aus einer einzelnen Datei besteht, trägt der Ordner den Namen der Datei ohne `.php`. Siehe [Sprachkonfigurationsdateien](https://wpml.org/documentation/support/language-configuration-files/) und [Eigene Gutenberg Blocks übersetzbar machen](https://wpml.org/documentation/support/language-configuration-files/make-custom-gutenberg-blocks-translatable/).

Ein Block ohne Eintrag wird der automatischen String-Erkennung von WPML überlassen, die jedes String-Attribut des Blocks zur Übersetzung anbietet. Bei einem Blockstudio-Block gehören dazu Auswahlwerte, Dateiverweise, URLs und CSS-Klassen. Übersetzer sehen diese technischen Werte neben dem eigentlichen Text, und ein übersetzter Auswahlwert oder eine übersetzte Klasse kann den Block beschädigen.

## Konfiguration generieren

Gib die Konfiguration aus und speichere sie im Stammordner des Themes oder Plugins, das die Blöcke bereitstellt:

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

Oder lass den Befehl die Datei schreiben:

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

Ein Block mit einem Textfeld, einem Bild, einem Link und einem Repeater:

```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" }
        ]
      }
    ]
  }
}
```

wird zu:

```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>
```

Der Wert `style` ist nicht deklariert, deshalb kopiert WPML ihn unverändert in die Übersetzung. Auch die IDs `gallery` und `image` werden kopiert, und WPML ersetzt jede davon beim Rendern des Blocks durch den Anhang der Seitensprache, sodass ein übersetztes Bild einen eigenen Alternativtext haben kann. Siehe „IDs in Blöcken automatisch konvertieren“ in [Eigene Gutenberg Blocks übersetzbar machen](https://wpml.org/documentation/support/language-configuration-files/make-custom-gutenberg-blocks-translatable/). Wenn ein Anhang keine Übersetzung hat, behält WPML die ursprüngliche ID bei.

## Was deklariert wird

Der Befehl liest die registrierten Blöcke, nachdem `custom/`-Felder und Blockfelder erweitert und Überschreibungen sowie Attributfilter angewendet wurden. Felder, die [Erweiterungen](https://blockstudio.dev/de/docs/extensions/) zu einem Blockstudio-Block hinzufügen, werden einbezogen. Felder, die Erweiterungen zu Core-Blöcken oder Blöcken anderer Plugins hinzufügen, dagegen nicht, da diese Blöcke ihre Konfiguration von WPML oder ihrem eigenen Plugin erhalten.

| Feld | Deklaration |
| --- | --- |
| `text`, `textarea`, `richtext`, `wysiwyg` | Übersetzbarer Text. |
| `link` | `title` als Text und `url` mit `type="link"`, sodass WPML einen Link durch seine Übersetzung ersetzt, sofern eine verfügbar ist. |
| `files` | Die gespeicherte Anhang-ID mit `type="post-ids"` und `sub-type="attachment"`. Mit `multiple` eine Ebene namens `*` für die Liste, die auch zur einzelnen ID passt, die das Feld speichert, wenn eine Datei ausgewählt ist. |
| `repeater` | Eine Ebene namens `*`, die zu jeder Zeile passt, mit den Deklarationen der Zeilenfelder. Verschachtelte Repeater funktionieren genauso. |
| `group` mit einem `id` | Die Felder der Gruppe, wobei die Gruppen-ID als Schlüsselpräfix dient (`cta_text` für das Feld `text` in der Gruppe `cta`). |
| `group` ohne ein `id`, `tabs` | Die Felder ohne eigene Ebene. |
| Benutzerdefinierter Feldtyp, registriert mit `translate` auf `true` gesetzt | Übersetzbarer Text, wie bei einem `text`-Feld. |
| Jeder andere integrierte Typ | Nicht deklariert. WPML kopiert den Wert unverändert. |

Ein Block ohne deklariertes Textfeld erhält `translate="0"`. WPML kopiert dann alle Werte des Blocks und bietet nichts davon zur Übersetzung an. Seine `files`-Felder werden weiterhin im Eintrag deklariert, weil WPML Anhang-IDs unabhängig davon konvertiert, was `translate` vorgibt. Innere Blöcke werden wie gewohnt übersetzt.

Nicht deklariert:

- Felder mit `hidden`, da ihre Werte nicht von Redakteuren geschrieben werden.
- Felder mit `"translate": false`, siehe unten.
- Felder benutzerdefinierter [Feldtypen](https://blockstudio.dev/de/docs/blocks/attributes/custom-field-types/), die nicht mit `translate` auf `true` registriert sind. Der Befehl gibt für jedes Feld eine Warnung aus, da nur der Feldtyp weiß, ob sein Wert Text enthält. Ein explizites `"translate": false` für ein Feld unterdrückt diese Warnung ebenfalls. Siehe unten.
- Attribute, die ein Block in seinem nativen `attributes` statt als Blockstudio-Felder deklariert.
- Speicherschlüssel, deren Felder unterschiedliche Typen haben, siehe unten.

Jedes Textfeld wird deklariert, auch eines, das einen technischen Wert wie eine CSS-Klasse enthält, sofern es nicht `"translate": false` festlegt.

### Feld ausschließen

Ein Textfeld kann einen Wert enthalten, der in jeder Sprache gleich bleiben muss: einen Accountnamen, eine E-Mail-Adresse, einen Anker oder eine CSS-Klasse. WPML bietet ihn wie jeden anderen Text zur Übersetzung an, und ein übersetzter Wert kann den Block beschädigen. Setze `translate` auf `false`, um das Feld aus der Konfiguration auszuschließen, sodass WPML seinen Wert unverändert in die Übersetzung kopiert:

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

Bei einem `group`, `tabs` oder `repeater` gilt `"translate": false` für jedes enthaltene Feld, auch in verschachtelten Containern. Ein Kindelement kann einen ausgeschlossenen Container nicht mit `"translate": true` überschreiben. Bei einem `files`-Feld schließt `false` auch die Anhang-IDs aus, sodass die Übersetzung die ursprünglichen Anhänge beibehält.

Wenn du `translate` weglässt oder auf `true` setzt, bleibt das bisherige Verhalten erhalten: Der Feldtyp entscheidet. Dadurch werden weder verborgene Felder noch Werttypen wie `select` übersetzbar. Die Option gilt für Block- und Erweiterungsfelder, blendet deren Steuerelemente im Editor nicht aus und deaktiviert sie nicht und ändert auch ihre gespeicherten Werte nicht. Führe `wp bs wpml config` nach einer Änderung der Einstellung erneut aus und aktualisiere dein `wpml-config.xml` mit der generierten Konfiguration.

Der `label` jedes Schlüssels ist die Feldbeschriftung, der die Beschriftungen der umschließenden Repeater und Gruppen mit einer ID vorangestellt werden. WPML zeigt sie im Übersetzungseditor als Feldnamen an. Die beiden Schlüssel eines `link`-Felds ergänzen die Beschriftung um `Link text` und `URL`. Diese Suffixe werden in die Sprache der Website übersetzt. Führe den Befehl daher mit der Locale aus, in der deine Übersetzer arbeiten.

### Benutzerdefinierte Feldtypen

Ein Feldtyp, der eine einfache Textzeichenfolge speichert, gibt dies bei seiner Registrierung an. Setze `translate` in der Definition auf `true`. Dafür muss `attribute` auf `string` gesetzt sein:

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

Der Befehl deklariert dann jedes Feld dieses Typs als übersetzbaren Text. Ein Feld kann weiterhin `"translate": false` setzen, um sich selbst auszuschließen. Ohne die Option werden die Felder dieses Typs wie zuvor ausgeschlossen und gemeldet.

### Beschriftungen ändern

Feldbeschriftungen sind für den Block-Editor gedacht und können Hinweise wie „Bild (optional)“ enthalten, die im Übersetzungseditor keine Bedeutung haben. Der Filter `blockstudio/wpml/config/label` erhält jede Beschriftung vor dem Schreiben zusammen mit dem Schlüsselkontext:

- `block`: der Blockname.
- `path`: der Speicherpfad des Feldes unter `blockstudio.attributes`, mit einer Ebene `*` für die Zeilen jedes Repeaters, zum Beispiel `cards/*/link`.
- `field`: die Felddefinition.
- `parents`: die Beschriftungen der übergeordneten Repeater und Gruppen mit einer ID.
- `part`: `text` für ein Textfeld, `title` oder `url` für die beiden Schlüssel eines Linkfeldes.

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

Gib eine leere Zeichenfolge zurück, um die Beschriftung eines Schlüssels auszuschließen, damit WPML stattdessen die Beschriftung des Blocks anzeigt. Ein Rückgabewert, der keine Zeichenfolge ist, lässt die ursprüngliche Beschriftung bestehen. Führe den Befehl nach einer Änderung des Filters erneut aus.

### Felder mit demselben Speicherschlüssel

Zwei Felder können denselben Speicherschlüssel haben, zum Beispiel ein Blockfeld und ein Erweiterungsfeld mit demselben `id` oder das Feld `text` in einer Gruppe mit der ID `cta` und ein Feld mit der ID `cta_text`. Der Befehl deklariert einen solchen Schlüssel nur, wenn eindeutig ist, was dort gespeichert wird:

- Innerhalb der Felder eines Blocks, außerhalb von Repeater-Zeilen, registriert Blockstudio ein Attribut pro Speicherschlüssel. Ein späteres Feld ersetzt daher ein früheres, unabhängig vom Typ. Bei den Erweiterungen eines Blocks gilt dasselbe: Ein späteres Feld oder das Feld einer später registrierten Erweiterung ersetzt ein früheres.
- Ein Blockfeld und ein Erweiterungsfeld mit demselben Schlüssel bleiben beide wirksam. Die Blockvorlage erhält den Wert so, wie ihn das Blockfeld definiert, während die Erweiterung mit ihrem eigenen Feld angewendet wird. Der Schlüssel wird einmal deklariert, wenn beide Felder dieselbe Deklaration benötigen: Beide sind Textfelder (`text`, `textarea`, `richtext` oder `wysiwyg`), beide sind Links, beide sind `files`-Felder (mit `multiple` bei einem der beiden erhält der Schlüssel die Ebene `*`) oder keines ist deklariert, etwa ein `select` und ein `number`. Zwei Repeater werden Feld für Feld in ihren Zeilen verglichen. Die Beschriftung stammt vom Blockfeld.
- Auch zwei Felder mit demselben `id` in den Zeilen eines Repeaters bleiben beide wirksam und werden auf dieselbe Weise verglichen.

Wenn die Typen unterschiedlich sind, zum Beispiel ein `text`-Feld im Block und ein `select`-Feld in einer Erweiterung, ist der gespeicherte Wert je nach dem Steuerelement, das ihn geschrieben hat, Text oder eine Auswahloption. Der Befehl deklariert den Schlüssel nicht und gibt eine Warnung aus:

```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)
```

Benenne eines der Felder um oder gib beiden denselben Typ, damit der Schlüssel deklariert wird.

## Konfiguration aktuell halten

Führe den Befehl erneut aus, nachdem du Felder hinzugefügt, entfernt oder umbenannt hast, und liefere die aktualisierte Datei mit dem Theme oder Plugin aus. Erzeuge Konfigurationen neu, die vor 7.7.5 erstellt wurden, damit sie Deklarationen für Attachment-IDs enthalten. Inhalte, die bereits vorhanden waren, zeigen neue Felder erst dann zur Übersetzung an, wenn ihr Original aktualisiert wurde, wie oben im WPML-Leitfaden beschrieben.

Mit `--file` erstellt der Befehl eine fehlende Datei. In einer vorhandenen Datei ersetzt er nur den Text zwischen `<!-- blockstudio:start -->` und `<!-- blockstudio:end -->`, sodass andere Abschnitte und Einträge für andere Blöcke unverändert bleiben:

```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>
```

Um eine vorhandene Datei zu verwenden, die noch keine Markierungen enthält, füge die beiden Markierungszeilen einmal in ihr Element `gutenberg-blocks` ein oder füge ein Element `gutenberg-blocks` mit den Markierungen hinzu, falls die Datei keines enthält. Fehlen die Markierungen oder wäre das Ergebnis keine gültige Konfiguration, lässt der Befehl die Datei unverändert und wird mit einem Fehler beendet.

Einträge für Blockstudio-Blöcke, die von Hand geschrieben wurden, etwa `translate="0"`-Einträge zum Ausblenden technischer Werte, sind nicht mehr nötig, sobald der generierte Abschnitt den Block abdeckt. Der Befehl warnt vor jedem Block, der mehrfach deklariert ist, sodass du diese Einträge entfernen kannst.

## Bildtexte in Übersetzungsaufträgen

WPML fügt die Texte der Bilder einer Seite zum Übersetzungsauftrag der Seite hinzu: Titel, Alternativtext, Bildunterschrift und Beschreibung. Nach Abschluss des Auftrags schreibt WPML die übersetzten Texte in den Anhang der Zielsprache und erstellt diesen Anhang, falls noch keiner vorhanden ist. Weitere Informationen findest du unter [Medien übersetzen](https://wpml.org/documentation/translating-your-contents/media/).
WPML findet Bilder in `<img>`-Tags im Inhalt, in Galerien, im Beitragsbild und in den Blöcken, die es kennt. Ein Blockstudio-Block speichert Attachment-IDs im Blockkommentar, daher findet WPML keine davon.

Wenn WPML aktiv ist, fügt Blockstudio die Anhänge hinzu, die seine Felder in den Blöcken einer Seite speichern, und ergänzt damit die gefundenen Bilder WPML:

- `files`-Felder, auch ausgeblendete, und `attributes`-Felder mit `media` – dieselben Felder, die der Block-Editor als Medien lädt.
- Felder in Gruppen, Tabs, Repeater-Zeilen und inneren Blöcken.
- Felder von [Erweiterungen](https://blockstudio.dev/de/docs/extensions/), auch bei Core-Blöcken und Blöcken anderer Plugins, da ihre Werte in den Attributen des erweiterten Blocks gespeichert sind.

Werte, die keine Attachment-ID sind, werden ausgeschlossen. Es ist keine Konfiguration erforderlich, und `wpml-config.xml` ist nicht beteiligt. Ohne WPML wird nichts für Übersetzungsaufträge durchsucht und die Medienintegrationsklasse nicht geladen.

Dies ist unabhängig von der Konvertierung von Attachment-IDs: Das generierte XML teilt WPML mit, welches übersetzte Attachment gerendert werden soll, während diese Integration angibt, welche Attachment-Texte in einen Übersetzungsauftrag aufgenommen werden. Zeichenfolgenverweise und IDs von Beiträgen, die keine Anhänge sind, werden nicht zu Medienaufträgen hinzugefügt. Gespeicherte verschachtelte Feldwerte haben bei Blockstudio-Blöcken Vorrang vor Werten auf oberster Ebene, wie beim Rendern.

Die Texte sind nur dann Teil des Auftrags, wenn eine der Optionen für Bildtexte unter WPML > Einstellungen > Medienübersetzung aktiviert ist: „Beste Optionen für die Übersetzung von Bildtexten automatisch erkennen“ oder „Texte der Mediathek beim Übersetzen von Inhalten übersetzen“, wie bei Bildern in Core-Blöcken.

Blockstudio meldet die Bilder über den Filter `wpml_ids_of_media_used_in_post`, der auf die Medien eines Beitrags in WPML angewendet wird. Um ein Bild von den Aufträgen auszuschließen, entferne seine ID in einem Callback für denselben Filter mit einer Priorität über 10:
`PostWithMediaFiles`

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