Umlaute falsch dargestellt in der Bildergalerie

 

Du legst eine Kategorie „Thüringer Wald“ an, und auf der Startseite der Galerie steht „Thüringer Wald“. Oder ein eigener Begrüßungstext in der Vorlage zeigt plötzlich eine Raute mit Fragezeichen, wo das „ü“ hingehört. Werden Umlaute falsch dargestellt, ist fast nie der Text selbst schuld. Irgendwo auf dem Weg vom Speichern bis zum Bildschirm hat ein Programm die Bytes nach einer anderen Tabelle gelesen, als sie geschrieben wurden. Das Gute daran: Jedes Fehlerbild hat seine eigene Handschrift, und die verrät dir, wo du suchen musst.

Umlaute falsch dargestellt: Thüringer erscheint als Thüringer oder mit Raute, wenn Speichern und Lesen nicht zusammenpassen

Umlaute falsch dargestellt: das Fehlerbild verrät die Stelle

Ein Umlaut ist für den Computer eine Folge von Bytes. Im heute üblichen UTF-8 besteht das „ü“ aus zwei Bytes, hexadezimal C3 BC. Im älteren latin1 (ISO-8859-1) ist es ein einziges Byte, FC. Solange Schreiber und Leser dieselbe Tabelle benutzen, kommt „ü“ heraus. Benutzen sie verschiedene, entsteht eines der folgenden Bilder. Schau genau hin, was bei dir statt „Thüringer“ steht:

Du siehstWas passiert istWo du suchst
ThüringerUTF-8 gespeichert, als latin1 gelesen: aus C3 BC werden die zwei Zeichen „Ó und „¼“Zeichensatz der Datenbankverbindung oder Angabe im Seitenkopf
Th�ringer (Raute mit Fragezeichen)latin1 gespeichert, als UTF-8 gelesen: das einzelne Byte FC ist in UTF-8 ungültigKodierung der Datei, meist eine als ANSI gespeicherte Vorlage
Th?ringerbeim Umwandeln in einen Zeichensatz ohne „ü“ ersetzt, das Zeichen ist verlorenbeim Import oder Kopieren, Text muss neu eingegeben werden
Thüringerdoppelt kodiert: der Fehler aus Zeile eins wurde gespeichert und noch einmal falsch gelesenDaten in der Tabelle, siehe unten
Thüringerkein Zeichensatzfehler, sondern ein doppelt maskiertes HTML-Zeichenim Code, der den Text ausgibt

Die erste Zeile ist mit Abstand der häufigste Fall, und sie hat eine Faustregel: Steht ein „Ó vor einem zweiten seltsamen Zeichen, war der Text richtig als UTF-8 gespeichert und wurde nur falsch gelesen. Das „ä“ wird so zu „ä“, das „ö“ zu „ö“, das „ß“ zu „ß“. Die Bytes sind intakt, es fehlt nur die richtige Brille. Bei der Raute mit Fragezeichen ist es umgekehrt: Der Browser erwartet UTF-8, bekommt aber ein Byte, das dort nicht vorkommen darf, und setzt ein Ersatzzeichen. Beim schlichten Fragezeichen ist der Buchstabe tatsächlich weg, keine Einstellung holt ihn zurück.

Die vier Übergänge, an denen ein Zeichen kippt

Ein Kategoriename legt einen weiten Weg zurück. Du tippst ihn in ein Formular, der Browser schickt ihn an PHP, PHP reicht ihn über die Datenbankverbindung an MySQL, MySQL legt ihn in einer Tabelle ab. Beim Anzeigen läuft alles rückwärts, und am Ende steht der Text in einer HTML-Seite, die der Browser auslegt. An jedem Übergang gilt eine eigene Angabe zum Zeichensatz:

  • Datei: Feste Texte in Vorlagen und PHP-Dateien sind so kodiert, wie der Editor sie gespeichert hat. Die Datei selbst trägt keine Beschriftung, man sieht ihr den Zeichensatz nicht an.
  • Tabelle: Jede Spalte hat einen Zeichensatz. Weicht er von der Verbindung ab, wandelt MySQL selbst um, solange das Zeichen in beiden Tabellen vorkommt.
  • Seitenkopf: Die Kopfzeile Content-Type vom Server und die Meta-Angabe in der HTML-Seite sagen dem Browser, mit welcher Tabelle er lesen soll.

Die Grafik legt die Fehlerbilder aus der Tabelle oben auf diese Kette. Hervorgehoben wird jeweils ein Übergang, daneben steht, wie „Thüringer“ aussieht, wenn genau dort etwas nicht passt, und ob das Bildergalerie-Script den Übergang selbst regelt.

Animiertes Diagramm der Zeichensatz-Kette: Datei, Verbindung, Tabelle und Seitenkopf werden nacheinander hervorgehoben, jeweils mit ihrem Fehlerbild für Thüringer und dem, was das Script dort regelt
Jedes Fehlerbild gehört zu einem Übergang; Verbindung und Seitenkopf stellt das Script selbst auf UTF-8, die Datei bleibt deine Sache.

Die Kette erklärt auch, warum nach einem Umzug zu einem neuen Hoster plötzlich Umlaute falsch dargestellt werden, obwohl niemand etwas geändert hat. Setzt ein Script den Zeichensatz der Verbindung nicht ausdrücklich, galt beim alten Hoster vielleicht zufällig die passende Voreinstellung, beim neuen nicht mehr.

Von außen nach innen prüfen

Sind auf deiner Seite Umlaute falsch dargestellt, stell nicht alle Stellen auf Verdacht um, sondern geh vom Browser zur Datenbank. So weißt du nach wenigen Minuten, ob die Daten heil sind und nur die Anzeige hakt, oder ob der Schaden schon gespeichert ist.

  1. Öffne mit F12 die Entwicklerwerkzeuge, lade die Seite neu und klick im Reiter „Netzwerk“ auf das Dokument. Unter den Antwort-Headern sollte Content-Type: text/html; charset=UTF-8 stehen.
  2. Öffne mit Strg und U den Quelltext. Steht das kaputte Wort schon dort, kommt es so vom Server, und der Browser ist unschuldig.
  3. Schau dir dieselbe Zeile in phpMyAdmin an. Steht dort „Thüringer“, sind die Daten heil, und der Fehler liegt in Verbindung oder Ausgabe. Steht dort „Thüringer“, ist der Fehler gespeichert.
  4. Betrifft es nur feste Texte der Vorlage, öffne die Datei in einem Editor wie Notepad++ oder VS Code. Die Statusleiste nennt die Kodierung, dort stellst du auf UTF-8 ohne BOM um.

Der dritte Schritt ist der wichtigste, denn er trennt zwei Fälle mit ganz verschiedener Lösung. Heile Daten brauchen nur eine korrigierte Einstellung. Gespeicherte Fehler bleiben, auch wenn danach alle Einstellungen stimmen, und müssen einzeln repariert werden.

Wenn der Fehler schon in der Tabelle steht

Bei drei oder vier betroffenen Kategorien ist Handarbeit der sicherste Weg: Namen in der Verwaltung öffnen, richtig eintippen, speichern. Sind es Hunderte Bildbeschreibungen mit „ü“, lohnt ein SQL-Befehl, der die falsch gelesenen Zeichen wieder in ihre Bytes zurückverwandelt und diese als UTF-8 neu liest. Teste ihn vorher immer mit einem SELECT, etwa SELECT beschreibung, CONVERT(CAST(CONVERT(beschreibung USING latin1) AS BINARY) USING utf8mb4) FROM bilder LIMIT 20;. Stimmt die zweite Spalte, exportierst du die Datenbank und wendest dieselbe Umwandlung als UPDATE nur auf die betroffenen Zeilen an.

Die Auswahl dieser Zeilen braucht eine Sortierung, die Zeichen genau vergleicht. Die übliche behandelt „Ó und „A“ als gleich, eine Bedingung wie LIKE '%Ã%' träfe sonst fast jede Zeile. Bei einer utf8mb4-Spalte schreibst du WHERE beschreibung COLLATE utf8mb4_bin LIKE '%Ã%'. Ältere Installationen haben latin1-Spalten, dort heißt der Zusatz COLLATE latin1_bin, mit utf8mb4_bin bricht MySQL den Befehl ab. Welchen Zeichensatz eine Spalte hat, zeigt phpMyAdmin im Reiter „Struktur“ unter „Kollation“. Auf heile Zeilen angewendet richtet die Umwandlung selbst Schaden an, und Fragezeichen lassen sich auf keinem Weg zurückholen.

Texte, die eine alte Galerie sauber im Zeichensatz ISO-8859-1 gespeichert hat, sind übrigens kein Schaden im Sinne dieses Abschnitts. Das Bildergalerie-Script erkennt solche Texte bei der Ausgabe und wandelt sie selbst in UTF-8 um.

So vermeidest du den Fehler künftig

Ist die Kette einmal durchgehend auf UTF-8, bleibt sie es in der Regel, solange niemand eine Datei im falschen Format speichert. Die Rückfälle, die Betreiber erleben, haben fast immer einen dieser Auslöser:

  • Editor-Voreinstellung: Ältere Windows-Programme speichern neue Dateien als ANSI. Stell die Standardkodierung einmal auf UTF-8 ohne BOM, dann stimmt jede neue Vorlage von Anfang an.
  • Emojis vom Handy: Wer eine Beschreibung mit Emoji tippt, braucht dafür eine utf8mb4-Spalte. Alte latin1-Spalten kennen diese Zeichen nicht. Je nach Servereinstellung wird daraus ein Fragezeichen, oder das Speichern schlägt fehl.
  • Export ohne Zeichensatz: Wer eine Datenbank auf der Kommandozeile sichert, gibt den Zeichensatz mit an, etwa --default-character-set=utf8mb4. Sonst kann der Import beim neuen Hoster falsch lesen.
  • Alte Vorlage weiterverwendet: Eine Vorlage aus früheren Jahren ist oft noch ISO-8859-1-kodiert und trägt eine passende Meta-Angabe im Kopf. Sie passt nicht mehr zu einer Seite, die als UTF-8 ausgeliefert wird.

Werden später doch wieder Umlaute falsch dargestellt, hilft die Handschrift aus der Tabelle oben weiter: Ein „Ó führt zur Verbindung, eine Raute zur Datei, ein Fragezeichen zur Neueingabe.

Was das Bildergalerie-Script selbst regelt

Von den vier Übergängen nimmt dir das Bildergalerie-Script seit Version 3.15 zwei vollständig ab und entschärft einen dritten. Die Datenbankverbindung läuft immer mit utf8mb4, das setzt das Script direkt nach dem Verbinden selbst. Jede Seite der Galerie und der Verwaltung kommt mit der Kopfzeile Content-Type: text/html; charset=UTF-8, und die mitgelieferte Vorlage tpl/bildergalerie.html beginnt mit <meta charset="utf-8">. Eine eigene Zeile mit mysqli_set_charset() musst du also nirgends einbauen. Bleibt die Datei selbst: Wer die Vorlage oder inc/config.php im Editor bearbeitet, entscheidet beim Speichern über den Zeichensatz. Ältere Installationen behalten ihre Tabellen im Zeichensatz latin1, das ist kein Fehler. MySQL wandelt beim Lesen und Schreiben selbst um, nur Zeichen, die latin1 nicht kennt, etwa Emojis, lassen sich dort nicht speichern.

Fehlerbilder und Meldungen, die es nur im Script gibt

Neben den allgemeinen Fehlerbildern kennt die Galerie ein paar eigene. Sie haben mit ihrer Versionsgeschichte und mit den Dateien zu tun, die du selbst bearbeitest:

Was du siehstUrsache im ScriptAbhilfe
Kategorienamen und Beschreibungen mit Umlaut fehlen ganzVersion 3.14 oder älter gab solche Texte leer ausUpdate auf 3.15, danach Browser-Cache und Ordner cache/ leeren
Eigener Text in der Vorlage zeigt eine Raute mit Fragezeichentpl/bildergalerie.html wurde als ANSI gespeichertVorlage als UTF-8 ohne BOM speichern
Cannot modify header information - headers already sentBOM vor <?php in inc/config.phpDatei als UTF-8 ohne BOM speichern
„Der Datenbank-Server unterstützt den Zeichensatz utf8mb4 nicht.“Installer findet einen sehr alten Datenbank-Serverbeim Webhoster eine neuere MySQL- oder MariaDB-Version wählen

Die erste Zeile ist ein Fehlerbild, das in der Tabelle weiter oben fehlt, weil es nur in alten Versionen vorkam: Der Text verschwand ganz, statt verstümmelt zu erscheinen. Seit 3.15 maskiert die Galerie jede Ausgabe ausdrücklich als UTF-8 und wandelt ältere ISO-8859-1-Texte vorher um, statt sie zu verwerfen.

Dateinamen ohne Umlaute sind Absicht

Ein Fall sieht so aus, als würden Umlaute falsch dargestellt, und ist doch keiner: die Dateinamen. Beim Hochladen und beim FTP-Import schreibt die Galerie Umlaute im Namen aus und setzt alles klein. Aus „Kürbisse vor der Scheune.jpg“ wird kuerbisse-vor-der-scheune.jpg, aus einem Ordner „Thüringer Wald“ wird thueringer-wald. Das ist Absicht, denn solche Namen funktionieren auf jedem Server und in jeder Adresse. Die Beschreibung, die die Galerie bei eingeschalteter Einstellung „Dateiname als Beschreibung“ aus dem Namen bildet, behält ihre Umlaute und heißt „Kürbisse vor der Scheune“. Namen, die ein FTP-Programm unter Windows im Zeichensatz Windows-1252 überträgt, wandelt das Script vorher nach UTF-8 um, und die zerlegten Umlaute aus macOS-Dateinamen setzt es wieder zusammen.

Auf dem Server muss außerdem die PHP-Erweiterung mbstring aktiv sein. Sie verarbeitet die Texte mit Umlauten. Fehlt sie, zeigt die Galerie keine falschen Zeichen, sondern bricht mit einem Fehler ab. Bei den meisten Webhostern ist sie eingeschaltet, sonst findest du sie im Kundenmenü bei den PHP-Einstellungen. Wenn du das an einer eigenen Galerie nachvollziehen willst, kannst du das Bildergalerie-Script kostenlos herunterladen und mit einem Testbild namens „Größe über alles.jpg“ ausprobieren.

Häufige Fragen

Welche Frage zuerst kommt, hängt meist davon ab, ob nur einzelne Texte oder ganze Seiten betroffen sind.

Mit welcher Codezeile stelle ich die Datenbankverbindung auf den richtigen Zeichensatz?

Bei mysqli lautet sie mysqli_set_charset($db, 'utf8mb4'); und gehört direkt hinter den Verbindungsaufbau, vor die erste Abfrage. Bei PDO schreibst du den Zeichensatz in die Verbindungsangabe, also charset=utf8mb4 im DSN. Im Bildergalerie-Script ist das schon erledigt, dort brauchst du keine eigene Zeile.

Warum werden nur in Bildtiteln aus der Datenbank Umlaute falsch dargestellt, im restlichen Text aber nicht?

Dann ist die Vorlage richtig gespeichert, und der Fehler sitzt auf dem Weg zwischen Datenbank und Seite. Prüfe in phpMyAdmin, wie der Titel in der Tabelle steht. Ist er dort korrekt, liegt es an der Verbindung, die ohne ausdrücklichen Zeichensatz arbeitet. Steht dort schon „ü“, wurde der Titel einmal falsch gespeichert und muss repariert werden.

Wie korrigiere ich bereits falsch gespeicherte latin1-Daten in größerer Menge?

Mit einer Umwandlung, die die falschen Zeichen in Bytes zurückverwandelt und neu als UTF-8 liest, wie im Abschnitt über gespeicherte Fehler beschrieben. Probiere sie zuerst mit SELECT an 20 Zeilen aus, exportiere dann die Datenbank und wende sie nur auf Zeilen an, die wirklich ein „Ó enthalten. Auf korrekte Texte angewendet verdirbt dieselbe Umwandlung sie.

Muss ich die Tabellen meiner älteren Galerie auf utf8mb4 umstellen?

Nein. Die Galerie arbeitet seit 3.15 mit latin1- und mit utf8mb4-Tabellen, Umlaute erscheinen in beiden Fällen richtig. Lohnend ist die Umstellung nur, wenn du Emojis in Beschreibungen speichern willst. Dann sicherst du zuerst die Datenbank, etwa per Export in phpMyAdmin, und stellst die fünf Tabellen admin, admin_log, bilder, kategorie und einstellung mit ALTER TABLE … CONVERT TO CHARACTER SET utf8mb4 um. Meldet MySQL bei der Tabelle bilder den Fehler 1071, muss der Schlüssel auf dateiname auf 190 Zeichen gekürzt werden.

Verwandte Themen

Zeichensatz, Datenbank und Verbindung hängen eng zusammen. Diese Beiträge erklären die einzelnen Stellen der Kette genauer.