Das Symptom sieht aus wie eine beschädigte Datenbank: Sie speichern irgendwo in WordPress einen Text mit Gedankenstrich — oder einem Buchstaben wie š, und beim nächsten Ansehen steht dort wörtlich „u2014” oder „u0161” statt des Zeichens. Die Datenbank ist in Ordnung — die Ursache ist enger und viel häufiger, als es aussieht.
Das Symptom
Es zeigt sich meist zuerst dort, wo jemand ein Sonderzeichen von Hand eingibt — ein Platzhalter im Kontaktformular, ein Produkttitel, importierter Inhalt. Beim Speichern sieht im Backend alles richtig aus; nach dem Neuladen der Seite ist das Zeichen verschwunden und ein nackter Hex-Code steht an seiner Stelle.
Zwei Mechanismen, die sich widersprechen
json_encode() — und WordPress’ eigener Wrapper wp_json_encode() — kodiert standardmäßig jedes Zeichen außerhalb des ASCII-Bereichs als \u-Escape: Aus einem Gedankenstrich wird \u2014, aus š wird \u0161. Das ist korrektes, standardkonformes JSON.
Das Problem entsteht einen Schritt später. add_post_meta(), update_post_meta() und update_option() rufen intern vor dem Speichern wp_unslash() auf den Wert auf — der Mechanismus, der WordPress’ automatisches Escaping von $_POST-Daten rückgängig macht. wp_unslash() unterscheidet nicht zwischen einem Backslash, den WordPress selbst hinzugefügt hat, und einem Backslash, der Teil Ihres JSON ist: Es entfernt beide. Aus \u2014 wird wörtlich u2014.
Die Lösung
Die Lösung ist eine Zeile, kein Umbau: json_encode($data, JSON_UNESCAPED_UNICODE), damit das Zeichen ein echtes Zeichen bleibt statt eines Escapes, dazu wp_slash() um den gesamten Aufruf, bevor er an update_post_meta() übergeben wird, damit unslash etwas Harmloses zum Entfernen hat statt Ihres Inhalts.
Wo es sich noch versteckt
Alles, was Daten vor dem Speichern in ein Metafeld oder eine Option JSON-kodiert, ist ein Kandidat — Formular-Builder, Content-Importer, benutzerdefinierte Felder. Der Fehler übersteht Tests unbemerkt, weil Testdaten selten Umlaute oder einen Gedankenstrich enthalten — er zeigt sich erst, wenn jemand tatsächlich echten kroatischen oder deutschen Text schreibt.
Ein Fehler, den der englischsprachige Teil des Webs fast nie findet — ein einziges š oder ein Gedankenstrich genügt, um ihn sichtbar zu machen.