Zeichen werden falsch dargestellt

Autor: thorn (vom WB Forum)

Die Frage nach falscher Darstellung von Zeichen im Browser dürfte zu den wohl meist gestellten Fragen im WebsiteBaker Forum gehören.

Begriffsklärung (Charset, Kollation)

Nachfolgend eine kurze Erklärung der wichtigsten Begriffe rund um das Thema MySQL und Zeichendarstellung:

  • Character-Set: Der Zeichensatz (genauer gesagt, das Encoding), also z.B. latin1, cp1251, utf8, …
  • Kollation: Die Sortier-Reihenfolge (für Strings, für Vergleiche, …) (z.B. latin1_swedish_ci, utf8_unicode_ci, …).
    Die Kollation ist an den Zeichensatz gebunden, d.h. die Einstellung "latin1_swedish_ci" erzwingt als Character-Set "latin1" (d.h. in der üblichen phpMyAdmin-Ansicht wird durch Einstellen der Kollation auch gleich der Character-Set eingestellt).

Grundeinstellung (Fehlerursachen/Lösungen)

Als Ausgangsbasis ist ein Update auf die letzte WB Version dringend empfohlen. In WebsiteBaker sollte im Backend: Optionen -> Erweiterte Optionen anzeigen -> Zeichensatz die Option UTF-8 eingestellt werden. Andere Zeichensätze sollten auch funktionieren, wirklich sicher fährt man aber nur mit UTF-8. Trotz UTF-8 und WB v2.6.6 können noch folgende Probleme auftauchen:

Fehler 1: Umlaute oder z.B kyrillische Zeichen werden im Browser falsch angezeigt

Ursache Nr. 1: Fehlender Charset im Template.

Überprüfen Sie, ob im Template folgender Code eingebunden ist:

<meta http-equiv="Content-Type" content="text/html; charset=<?php 
if(defined('DEFAULT_CHARSET')) { echo DEFAULT_CHARSET; } else 
{ echo 'utf-8'; }?>" />

Ursache Nr. 2: Apache liefert PHP als ISO-8859-1 aus

Wenn Ursache Nr. 1 ausgeschlossen ist, überprüfen Sie bitte, welchen Zeichensatz der Browser benutzt. Dies wird wahrscheinlich fälschlicherweise ISO-8859-1 sein. Stellt man den Browser-Zeichensatz auf UTF-8 um, wird die Seite richtig angezeigt, bis man die nächste Seite lädt. Eine dauerhafte Abhilfe schafft eine .htaccess Datei im WB-Verzeichnis auf dem Server (dort, wo auch die config.php zu finden ist) mit folgendem Inhalt:

<Files .htaccess>
order allow,deny
deny from all
</Files>
php_value default_charset UTF-8

Damit wird der Apache Server angewiesen, alle von PHP generierten Seiten als UTF-8 auszuliefern.

Fehler 2: Nur einige Zeichen werden falsch dargestellt

Bei Verwendung von Kyrillisch sind z.B. "И" und "ш" betroffen, bei Verwendung von Griechisch z.B. "ή".

Ursache: Ein default-character-set ist in my.ini (oder my.cnf) vorgegeben oder der Benutzer hat eine Datenbank mit einem Character-Set festgelegt

Normalerweise sind diese Angaben nicht vorhanden, und es wird automatisch für beide latin1 angenommen, welche die default-Einstellung ist. Ändert man dies nun nur an einer Stelle (man legt für die Erstellung der Datenbank einen anderen Charater-Set als latin1 fest, benutzt aber keinen Eintrag für default-character-set oder andersherum), kommt es unweigerlich zu Konvertierungsfehlern, die dazu führen, dass scheinbar wahllos einige Zeichen nicht richtig angezeigt werden.

Dies bedeutet, dass nur zwei Möglichkeiten bleiben - insbesondere dann, wenn der Service-Provider einen default-character-set in der my.ini festgelegt hat und dieser von latin1 abweicht:

  • Wenn möglich den default-character-set Eintrag ändern lassen.
  • Beim Anlegen der Datenbank (sofern man dazu überhaupt die nötigen Rechte hat), den Character-Set der Datenbank auf den gleichen Wert einstellen. Ist dies vor der Installation von WB nicht möglich, muss man nachträglich (aber bevor man Inhalte in WB anlegt) den Character-Set von _allen_ Spalten und Tabellen von Hand umstellen. Ebenso muss man - wenn möglich - den Character-Set der Datenbank selbst umstellen. 

Zusammenfassung:
Der default-character-set und der Character-Set der einzelnen Spalten muss übereinstimmen. Dies ist normalerweise der Fall, wenn man die Installation von WB gemäss Anleitung durchführt.

Weiterführende Informationen

Wenn Daten in die Datenbank geschrieben werden, müssen sie zuerst aus dem Zeichensatz der Anwendung in den Zeichensatz der Datenbank (*1) gewandelt werden. Entsprechend müssen, wenn Daten aus der Datenbank gelesen werden, diese in den Zeichensatz der Anwendung zurückgewandelt werden. Vereinfacht (*2) ausgedrückt gibt es also zwei Seiten zu beachten:

  1. den Zeichensatz von WebsiteBaker (Anwendung)
  2. den Zeichensatz der Datenbank (*1)

Normalerweise sollte die Anwendung beim Anlegen der Datenbank und ihrer Tabellen den zu verwendenden Zeichensatz festlegen (sinnvollerweise UTF-8). Ausserdem sollte die Anwendung bei jedem Verbindungsaufbau zur Datenbank ein "SET NAMES ...." durchführen. SET NAMES legt den Character-Set für character_set_client, character_set_results und character_set_connection fest. Damit würden alle Character-Set Probleme beseitigt und man bräuchte sich zu diesem Thema keine weiteren Gedanken zu machen.

Probleme ergeben sich aber daraus, dass WebsiteBaker keine der o.g. Festlegungen trifft. In diesem Fall benutzt MySQL immer den default-Wert "latin1" bzw. die Angabe der Kollation "latin1_swedish_ci".

Benutzt man innerhalb von WebsiteBaker nun ISO-8859-1, so ist dies generell problemlos, da ISO-8859-1 in Latin 1 enthalten ist.
Benutzt man dagegen einen anderen Zeichensatz wie UTF-8, werden die Daten ebenfalls wie bei ISO-8859-1 ohne Konvertierung direkt in die Datenbank geschrieben, weil MySQL nicht weiß, dass es hier eine Konvertierung durchführen müsste.

Beim Auslesen aus der Datenbank werden die Daten auch nicht konvertiert. Und weil hier in beide Richtungen keine Konvertierung stattfindet, funktioniert WebsiteBaker trotz "falscher" Einstellung des connection-character-sets auch mit anderen Zeichensätzen (*3) als ISO-8859-1. Lediglich, wenn man sich die Daten direkt in der Datenbank ansieht, beispielsweise mit phpMyAdmin, sehen die dort gespeicherten Zeichen "kaputt" aus, so wird beispielsweise "Über" als "Ãœber" angezeigt. Dies liegt daran, dass phpMyAdmin die Daten aus dem Zeichensatz der Datenbank zur Ansicht in den Zeichensatz wandelt, den das Betriebssystem (Windows, Linux) als Standard benutzt. Ist dies beispielsweise UTF-8, so führt phpMyAdmin eine Konvertierung Latin 1 -> UTF-8 durch, obwohl die Daten schon als UTF-8 in der Datenbank vorliegen.

Ändert man den Zeichensatz der Datenbank / der Tabellen von Hand beispielsweise auf UTF-8, so wird in dem oben skizzierten Ablauf noch jeweils eine Konvertierung eingefügt, da MySQL annimmt, es müsse von Latin 1 (Client) nach UTF-8 (Datenbank) konvertieren. Bei der Verwendung von ISO-8859-1 innerhalb von WebsiteBaker ist dies unproblematisch. Aber bei Benutzung von UTF-8 bedeutet dies, dass ein String, der in UTF-8 kodiert ist, einer Konvertierung Latin 1 -> UTF-8 unterzogen wird und beim Auslesen der Daten wiederum entsprechend UTF-8 -> Latin 1. Häufig hat man Glück und die Zeichen "überstehen" diese falsche Behandlung. Bei gewissen Zeichen kann jedoch Zeichensalat entstehen…

Dasselbe gilt, wenn man den client-character-set ändert, z.B. durch Verändern der default-character-set Einstellung in der Konfigurations-Datei von MySQL.

Nur wenn man beide Änderungen aufeinander abstimmt (beide auf z.B. UTF-8 oder beide auf z.B. cp1251 einstellt), funktioniert es wieder so wie anfangs für Latin 1 beschrieben.


(*1): Ausschlaggebend ist hier im Endeffekt nur der Column-Character-Set.
(*2): Vereinfacht, weil es wesentlich mehr Einstellmöglichkeiten gibt:
Datenbank-seitig:
- Server-Character-Set
- Database-Character-Set
- Table-Character-Set
- Column-Character-Set
Client-seitig:
- Character-String-Literal-Character-Set
- Client-Character-Set
- Connection-Character_Set
- Results-Character_Set
(*3): Eine Ausnahme scheinen hier die Zeichensätze ISO-2022-JP und -KR zu bilden,
möglicherweise auch BIG5 und GB2312 -- das muss noch genauer geprüft werden.