PHP und UTF-8 - eine Anleitung, Teil 2: Webseiten als UTF-8 ausliefern

Nachdem nun die MySQL-Datenbankverbindung reibungslos mit UTF-8 funktioniert und bevor wir uns im weiteren Verlauf der Serie über PHP und UTF-8 wirklich PHP selber zuwenden, sollen noch ein paar Worte über das korrekte ausliefern einer UTF-8 kodieren Webseite verloren werden. Das Problem, das hier angegangen werden soll ist: Wie erkennt der Browser eigentlich, dass eine Webseite in UTF-8 ist?

Die Antwort ist

  1. Am Content-Type-Feld im HTTP-Header
  2. Nur wenn der HTTP-Header fehlt: Am Content-Type Meta-Tag im HTML-Code

Betrachten wir zunächst den HTTP-Header. HTTP kennt jeder von der Adresseingabe im Browser, und dahinter verbirgt sich ein Protokoll, das regelt, wie Daten vom Server zum Client (in diesem Fall der Browser) transportiert werden. Dazu werden vor dem eigentlichen Inhalt so genannte Header gepackt, die Informationen über den folgenden Inhalt wie auch etwaige Fähigkeiten des Clients liefern. Hier Auszüge des Headers für den Aufruf der Startseite von gerd-riesselmann.net:

HTTP/1.x 200 OK
Date: Thu, 22 Nov 2007 18:20:20 GMT
Last-Modified: Thu, 22 Nov 2007 18:20:20 GMT
Content-Type: text/html; charset=utf-8

Interessant ist für uns lediglich das Feld Content-Type. Dieses legt fest, das im Folgenden Text– und zwar HTML – folgt, der in UTF-8 kodiert ist. Dieses Feld – und erst mal nur dieses! – bringt den Browser dazu, die Seite als UTF-8 anzuzeigen. Wenn hier andere Sachen stehen etwa

Content-Type: text/html; charset=iso-8859-1

wird die Seite entsprechend als Latin1 angezeigt. Dagegen kann man dann auch nichts machen.

Deshalb muss zunächst dafür gesorgt werden, dass der Content-Type-Header richtig gesetzt wird. Dies kann auf mehrere Arten geschehen:

  • Aufseiten des Webservers
  • Durch PHP

Um etwa im Apache-Webserver UTF-8 auszuliefern, benötigen wir die Direktive AddDefaultCharset . Diese kann bei der Definition des Virtual Host in der Apache-Config gesetzt oder mittels einer .htaccess-Datei überschrieben werden. Die Syntax ist einfach:

AddDefaultCharset utf-8

Sollte das Setzen oder Überschreiben mittels .htaccess nicht möglich sein, etwa weil der Provider entsprechende Restriktionen hat, kann der Header auch mittels PHP gesetzt werden:

<?php
header("Content-Type: text/html; charset=utf-8");
?>

Um einen Header mittels PHP senden zu können, darf allerdings noch keine Ausgabe erfolgt sein, also macht man das am besten noch während des Programmsstarts.

Was passiert, wenn ein Content-Type-Eintrag im Header fehlt, etwa weil die Datei von der lokalen Festplatte geöffnet wurde? In diesem Fall greift der Browser auf den HTML-Code zurück, und hier auf einen Meta-Tag, das den Content-Type definiert:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
...
</head>
<body>
...
</body>
</html>

Das Attribut “http-equiv” bedeutet eigentlich, dass der Webserver seinen eigenen Content-Type-Eintrag im Header durch den Wert des Meta-Tags ersetzten soll. Aus naheliegenden Gründen wird das allerdings von keinem Webserver umgesetzt: Jedes Schnipsel HTML zu interpretieren würde einfach zu viel Last bedeuten. Daher greift nur der Browser hierauf zurück, und auch nur, wenn er keinen entsprechenden Header-Eintrag vorfindet.

Erwähnt sei noch, dass für XHML-Seiten das Encoding auch in der XML-Deklaration gesetzt werden kann:

<?xml version="1.0" encoding="utf-8"?>

Allerdings kann der Internet Explorer 6 mit solchen XML-Deklarationen nicht umgehen, weshalb sie für gewöhnlich weggelassen werden.

Published: November 23 2007