Das eigentliche Problem: WPML + Themify Builder ist nicht wartbar
Wir betreiben eine mehrsprachige Website mit WPML und Dutzenden von Seiten in mehreren Sprachen. Zwei Bugs machen dieses Setup in der Praxis nicht wartbar:
- Hook Content Conditions, die für die Originalseite gesetzt wurden, greifen nie auf übersetzten Seiten – jede Condition müsste manuell für jede Übersetzung dupliziert werden
- Builder-Styles synchronisieren sich nicht automatisch auf übersetzte Seiten – Redakteure müssen nach jeder Layout-Änderung jede übersetzte Seite manuell im Builder öffnen, um die Styles zu übernehmen
Beide Probleme haben dieselbe Ursache: Themify Builder nutzt die von WPML bereitgestellten Integrations-APIs nicht vollständig.
Hintergrund: Wie WPML Seiten verwaltet
WPML verknüpft Seiten sprachübergreifend über Übersetzungsbeziehungen, die über eine dedizierte API zugänglich sind:
// Übersetzung einer Seite in einer anderen Sprache ermitteln
$translated_id = apply_filters('wpml_object_id', $post_id, 'page', false, $lang);
// Aktuelle / Standard-Sprache abfragen
$current_lang = apply_filters('wpml_current_language', null);
$default_lang = apply_filters('wpml_default_language', null);Diese APIs existieren genau dafür, damit Plugins WPML-kompatibel arbeiten können, ohne Logik pro Sprache zu duplizieren.
Bug 1: Hook Content Conditions greifen nicht auf übersetzten Seiten
In themify/class-hook-contents.php baut check_visibility() den Seitenpfad über child_post_name():
// class-hook-contents.php ~Zeile 179
in_array( '/' . self::child_post_name( $query_object ) . '/', $posts )child_post_name() läuft rekursiv über post_parent und konkateniert die post_name-Werte. Auf einer übersetzten Seite liefert das den englischen Slug, z.B.:
/services/production-and-delivery-of-green-hydrogen/Die gespeicherte Visibility Condition enthält aber den deutschen Slug (Standardsprache):
/leistungen/produktion-und-lieferung-von-gruenem-wasserstoff/Der in_array()-Vergleich schlägt immer fehl → Hook Content wird auf übersetzten Seiten nie ausgegeben.
Erwarteter Fix – vor dem Vergleich auf die Originalsprachversion zurückauflösen:
$original_id = apply_filters('wpml_object_id', $query_object->ID, 'page', false, $default_lang);
$original_post = get_post($original_id);
$original_path = '/' . self::child_post_name($original_p