WordPress Sprachdateien erzeugen Fehler in gettext.php
codestyling | 22. Juni 2008 | 16:04
Dieses Problem tritt sehr vielfältig in Erscheinung. Einerseits wird berichtet, dass es sporadisch auftritt aber genauso auch permanent und wird derzeit meist damit gelöst, dass WordPress in englisch betrieben wird.
Um diesen Fehler analysieren zu können, habe ich in Kooperation mit einem betroffenen Blogger eine Fehleranalyse machen können. Vielen Dank an infected für die Unterstützung, denn auf meinem System ist der Fehler leider nicht nachzustellen.
Für diejenigen, die noch keine Vorstellung davon haben, wie der Fehler aussieht, bitte sehr, das sollte euch bekannt sein:
Warning: unpack() [function.unpack]: Type V: not enough input, need 4, have 0 in /www/htdocs/xxx/test2/wp-includes/gettext.php on line 91 Warning: unpack() [function.unpack]: Type V: not enough input, need 4, have 0 in /www/htdocs/xxx/test2/wp-includes/gettext.php on line 91 Fatal error: Maximum execution time of 30 seconds exceeded in /www/htdocs/xxx/test2/wp-includes/gettext.php on line 166
Um sich den Fehler anzunähern, hatte ich die WordPress Datei gettext.php um die Fähigkeit erweitert, ein eigenes Logfile zu schreiben und den Fehler analysierbar zu machen. Dabei hab ich folgende interessante Feststellung gemacht: Die benutzte PHP Funktion substr() liefert nicht immer das gewünschte Ergebnis, sie gibt manchmal einen String zurück, der um genau 1 Byte verschoben ist!
Dies wirkt sich natürlich umgehend auf die Interpretation des binären Strings als Zahl aus. Da für die Verwendung von Sprachdateien erstmal vom Anfang der *.mo Datei 5 integer Werte gelesen werden sollen, haben diese dann logischerweise einen falschen Inhalt:
de_DE.mo (Dateibeginn, hex):
DE 12 04 95 00 00 00 00 5E 08 00 00 1C 00 00 00int: -1794895138 -> hex: FFFFFFFF950412DE (byte order Kennung, korrekt)
int: 1577058304 -> hex: 5E000000 (revision, falsch!)
int: 469762056 -> hex: 1C000008 (Anzahl Texte, falsch !)
int: 201326592 -> hex: 0C000000 (Offset Originaltext Tabelle, falsch!)
int: 687865923 -> hex:29000043 (Offset Übersetzungstext Tabelle, falsch!)
Es ist schon ein starkes Stück, dass eine vielfach benutzte PHP Funktion spontan andere Ergebnisse liefert! Da dies auf dem betroffenen System nur sporadisch passiert, ist mir zwar weiterhin unklar, warum das auftritt, aber wichtiger ist ja wo es passiert. Denn so kann man auch eine Lösung finden, die sowohl performant als auch auch kompatibel zu bestehenden WP 2.5.1 / WP 2.6 Installationen ist.
Wichtig: Dieser Fehler ist kein Fehler von WordPress selbst, sondern ein Problem von PHP in Kombination mit dem Apache Server! Ich hab das an das WP Bugtrac auch gemeldet und hoffe, die Jungs geben das auch an’s PHP Team weiter. http://trac.wordpress.org/ticket/5599
Die Lösung des Problems besteht in einer Anpassung der Datei: /wp-includes/streams.php um dem Fehler aus dem Weg zu gehen. Die Verwendung der substr() Funktion wurde komplett gegen die Verwendung der unpack() Funktion ausgetauscht und eine vergessene Initialisierung der Fileposition ergänzt.
alt:
$data = substr($this->_str, $this->_pos, $bytes);
neu:
$data = array_shift(unpack('@'.$this->_pos.'/A'.$bytes, $this->_str));
Wer das nicht von Hand patchen will oder auf die nächste WP Version warten möchte, kann sich die geänderte Datei auch hier runterladen und in der WP 2.5.1 / WP 2.6 Installation ersetzen. Ich habe diese Änderung mit folgenden Sprachdateien getestet:
- deutsch (de_DE.mo)
- arabisch (ar.mo) wegen rechts nach links Schreibweise
- japanisch (ja.mo) um erweiterte Unicode Zeichen zu haben
WP 2.5.1 gettext patch: patch-wp251-gettext-stream.zip
(ersetzt die bisherige streams.php im Ordner /wp-includes/)
Achtung: Dieser Patch kann auch auf einer WP 2.6 Version angewendet werden, denn in dieser Datei gibt es zwischen WP 2.5.1 und WP 2.6 keine Unterschiede!
Für den Fall, dass der Patch wider Erwarten Probleme bereitet, empfehle ich vorher eine Sicherung der betroffenen Datei. Ich hoffe, ich kann hiermit einigen geplagten Bloggern helfen, wieder Blogs mit funktionierender Sprachdatei zu haben. Feedback und weitere Meldungen von Fehlverhalten in Bezug auf gettext / unpack sind willkommen.
wichtiges Update (20. Juli 2008):
In der Zwischenzeit habe ich rausgefunden, was die Ursache des Problems ist und es hier dokumentiert und erklärt: http://www.code-styling.de/deutsch/wordpress-fehler-durch-sprachdateien-die-ursache






Joern Kretzschmar
23.06.2008 | 23:17Fantastisch, dass endlich jemand eine Lösung dieses leidigen Themas gefunden hat. Super.
Antworten »
Matthias Brusdeylins
23.06.2008 | 23:53Vielen Dank für den Ersatz des fehlerhaften substr().
Kennt jemand den Grund warum und in welchem direkten Zusammenhang substr() fehlerhaft ist? Gibt es hier spezielle Parameter des Apache-Servers bzw. der PHP-Installation die Probleme machen?
Ich frange deswegen:
Ich hatte das substr() schon mal ersetzt, aber dann Probleme an anderer Stelle bekommen (CODE-Ansicht im Texteditor hat mir sporatisch den Inhalt zerhauen). Substr() kommt ja öffters im Wordpress-Code vor…
Kann man einen Befehl wie substr() zentral ersetzen / überschreiben ?
Antworten »
codestyling
24.06.2008 | 00:13Das kommt auf die Art und Weise der Ersetzung an. Da es ja nicht mehr in den *.mo Dateien passiert, wenn man es ändert, ist die Chance groß, dass es dann eine andere Stelle erwischt, die damit nix zu tun hat aber eben auch substr() benutzt.
Das zentral zu ersetzen ist schwierig bis unmöglich. Ich werde, sobald der Fix im Trac angenommen ist, nochmal nachhaken, ob das zum PHP Team geleitet wurde. Falls du an einer Stelle Ersatz für substr() brauchst, kann man das mit dem unpack() von oben emulieren:
$text = "Hallo du Welt.";$s1 = substr($text, 6,2); // -> "du"
$s2 = array_shift(unpack('@6/A2', $text)); // -> "du"
@xxx fährt auf die angegebene Byteposition xxx vom Begin des Strings
/ trennt Anweisung
Ayyy unsigned character der Anzahl yyy zurückliefern
Da das als Array zurückkommt, array( 1 => “du”) lässt man sich den Wert geben.
Aber Achtung! Das geht
a) wenn es ISO charset ist
oder
b) UTF-8 und man die zusätzliche Länge bei 2,3,4 Bytes langen Encodierungen des Sonderzeichen mit berücksichtigt.
Da die *.mo Files dieses berücksichtigen, kann man das auch ersetzen. Im Normalbetrieb eher nicht möglich:
$val = “Über Drüber”; Zeichenlänge: 11 aber Byte Länge 13, denn die Ü|ü haben 2 Byte Kodierung.
Erstaunlich sind die Übereinstimmungen:
Aber da kann vermutlich nur das PHP Team was dazu sagen oder finden.
Antworten »
Tobias
24.06.2008 | 14:18Hallo,
ich finde es super, dass du dich so intensiv mit diesem Fehler beschäftigst. Da ich vor kurzem einen meiner Blogs auf Version 2.5.1 aktualisiert habe, plage ich mich auch mit dem Problem herum.
Ich habe die betroffene Zeile in der streams.php geändert. Soweit so gut.
Nach der Änderung habe ich jedoch das Problem, das der Blog plötzlich im Frontend englisch ist, wenn ich die Archive (also die Monate oder Kategorien) aufrufe.
Hast du das mal bei dir getestet?
Antworten »
codestyling
24.06.2008 | 14:41Also dieser Blog hier läuft mit diesem Patch. Mein Theme bringt seine eigene *.mo Datei mit genauso wie einige Plugins. Mal abgesehen von dem “reply” Link, der im Moment noch nicht übersetzt ist, weil gerade erst im Test und frisch programmiert, sind alle Texte so weit in der korrekten Sprache, die eingestellt ist.
Zu Archiven müsste ich noch schauen, aber die sind ebenfalls Theme gebunden. Manche Themes haben die nicht übersetzt bzw. hart codiert.
Kann man das auf deine Seite sich anschauen ?
Antworten »
Tobias
15.07.2008 | 01:22Ich nutze (noch) das Standard-Theme “default_de” und folglich dessen .mo Datei. Sobald ich den Bugfix einbaue, ist mein Blog wieder plötzlich auf Englisch. Das betrifft das gesamte Frontend, nicht nur die Archive
Hier zu sehen: Link
Antworten »
infected
27.06.2008 | 11:23Es freut mich sehr, dass sich endlich mal jemand der Sache angenommen hat und soviel Engagement zeigt (auch für eine Sache, von der er noch nicht mal selbst betroffen ist). Auch von mir aus nochmals ein herzliches DANKE! Hoffentlich gehören diese Fehler schon bald der Vergangenheit an…
Gruß
Michael
Antworten »
tanaka
28.06.2008 | 22:53jetzt läuft entlich alles wieder so wies laufen muss super hilfe, ein ganz dickes Lob an Dich !!!!!
bewerb dich mal bei WP, einer mit verstand wird dort bestimmt gesucht
cu und nochmal 1000 THX
Antworten »
raha
15.07.2008 | 16:01Perfekte Lösung, ALLERDINGS ist der Blog nach Anwendung des Patches merklich langsamer geworden. Kann man das irgendwo noch optimieren ?
Antworten »
codestyling
15.07.2008 | 16:48Im Moment hab ich noch keine Lösung dafür, das schneller zu bekommen, denn das Schnellste, was mit PHP zu machen ist, wäre eine korrekt funktionierende substr() Funktion. Dieser Patch ist immer noch im Bug-Trac anhängig und es äußert sich einfach niemand von WP dazu.
Ich bin noch am tüfteln, wie man eine weitere Beschleunigung noch hinbekommt, aber einfach wird das nicht.
Wieviel macht der “gefühlte” Unterschied aus ?
Antworten »
raha
16.07.2008 | 09:06Hi codestyling, danke für Deine Antwort. Also man kann durchaus von 1 bis 7 zählen, bevor die Seite dann blitzartig aufgebaut wird. Wenn man die Original-streams.php nimmt, gibts die Verzögerung nicht.
Antworten »
ChristianB
15.07.2008 | 16:42ich habe den oben beschriebenen Patch bei mir auch mal ausprobiert und bin eigentlich sehr zufrieden nur das jetzt, wie auch schon andere festgestellt haben, mein Frontend und Backend plötzlich in Englisch sind. Und das komplett. Ich verwende mehrere Plugins mit eigener Sprachdatei und auch mein Theme ist übersetzt. Irgendwie scheint WP aber diese Dateien zu ignorieren. Nur mal so zum Vergleich, ich verwende: WP 2.5.1, Gengo 2.5.3, Akismet 2.1.5, WP.com Stats 1.2.2, WP-Syntax 0.8, YARQ 2.5.0. Ich bin bei all-inkl auf einem PHP5 Server. In der 2.6er WP Version ist immer noch die substr() Geschichte drinn also wollte ich erstmal noch mit einer Aktualisierung warten.
Gibt es eine Möglichkeit nachzuschauen bei welchem Schritt die Übersetzung hängt, oder warum er die Dateien einfach ignoriert?
Antworten »
codestyling
15.07.2008 | 17:41Also ich hab den Verdacht, das es ein zusätzliches Problem gibt, das mit Gengo (Multiligual Plugin) zu tun hat. Ich werd mir mal die neueste Version davon (bzw. deine Version, falls noch zum Download vorhanden) anschauen und rausfinden, ob es ein Problem provoziert. Zumindest sind mehrere Probleme auf den Autorseiten dokumentiert, die sich in Richtung meiner Vermutung bewegen.
Falls du die Möglichkeit hast, mit Standard Theme und ohne Gengo mal zu testen, würde man bereits jetzt sehen können, ob es daran liegt.
Antworten »
Texas
15.07.2008 | 20:41Hallo ich habe das gleiche Problem. Es ergab sich bei mir nach dem Update von 2.5.1 auf 2.6
jetzt bin ich wieder zurück zur 2.5.1
kann ich mit deinem patch das update bedenkenlos einspielen? oder ändert sich dann bei mir alles auf englisch?
Antworten »
codestyling
15.07.2008 | 21:05Ich hab mir die streams.php der WP 2.6 angesehen und die ist identisch mit der aus WP2.5.1. Somit kann der Patch auch auf einer WP 2.6 angewendet werden. Was das Phänomen mit dem Rückfall auf englisch angeht, bin ich noch am Analysieren. Das kann nicht durch den Patch hervorgerufen werden, da muss es eine weitere Ursache geben!
Antworten »
raha
16.07.2008 | 16:23Habe in der wp-config.php einfach mal die LANG Variable auskommentiert und schon rast das Ding auf deutsch wie verrückt. Allerdings kommt dann - wie schon mehrfach beschrieben - das Admin-If in englisch.
Antworten »
codestyling
20.07.2008 | 17:17Ich habe mittlerweile die Ursache gefunden und hier beschrieben: neuer Artikel: Ursachenforschung
Diese sollte erklären, was und warum das passiert sowie Lösungen bieten. Ein 100% Lösung gibt es nach wie vor noch nicht (denn In Shared Hosting Systemen können andere Domains Probleme machen) aber lest selbst nach.
Antworten »
meinwasser
17.09.2008 | 18:38Kann es sein dass die Word Press Version 2.6.2 wieder den altbekannten Fehler hat?
Ich habe seit heute wieder sporadisch diese Meldung:
Warning: unpack() [function.unpack]: Type V: not enough input, need 4, have 0
Antworten »
codestyling
19.09.2008 | 00:41Das Zustandekommen dieser Probleme habe ich ja nachgewiesen und das WP Team hat meinen vorgeschlagenen Patch auch eingebaut. Jedoch die weiteren im Ursachen-Artikel beschriebenen Probleme bleiben ja bestehen, denn man kann an diese Stelle in WP nicht mehr viel dagegen machen.
Antworten »
meinwasser
19.09.2008 | 20:06Ich habe jetzt deinen Patch in der Version 2.6.2 eingespielt und das Problem ist wieder weg…
Antworten »
Eclipse
09.02.2009 | 13:11Würde das Patch bzw. die Codeänderungen auch mit der neuesten Version 2.7 funktionieren?
Antworten »
codestyling
09.02.2009 | 18:25Sollte auch in WP2.7 funktionieren, bitte ein Backup vorher machen.
Normalerweise sollte das aber bereits behoben sein, vielleicht trifft ja bei dir eine der bereits neu bekannten Ursachen zu. Diese und deren Behandlung sind im Nachfolgeartikel in den Comments beantwortet, ggf. muss ich das nochmal zusammenstellen als Liste, damit das klarer wird.
Dieser Patch verlangsamt das System aber etwas, weshalb nach einer Lösung deiner Ursache zu suchen der bessere Weg wäre.
Antworten »