Clements: UTF-8 richtig nutzen...

Guten Abend,

ich starte derzeit ein neues Projekt. Dieses Projekt will ich in UTF-8 coden. Ich habe schon sehr viel darüber erfahren u.a. habe ich eine kleine checkliste gefunden, die man einhalten sollte wenn man UTF-8 verwenden will:

1. Die Dateien sollten utf-8 encodet sein
2. An den Anfang der CSS Datei eine "@charset "utf-8";"
3. Daten aus Datenbanken und aus der url ebenfalls utf-8 encoden oder dafür sorgen dass sie als utf-8 ankommen
4. In den Seitenmetatags utf-8 angeben "<meta http-equiv="content-type" content="text/html; charset=utf-8">"
5. Bei jeder PHP seite am Anfang einen Contenttype Header mitsenden "header("content-type: text/html; charset=UTF-8");"
6. In der php.ini " default_charset = "utf-8" " setzten
7. Apache auf utf-8 Ausgabe umstellen

Die erste große frage ist ob das alles ist, oder ob ihr noch tipps für mich habt?

Außerdem wollte ich fragen ob mir jemand die ersten drei Punkte etwas genauer erklären kann.

Zum 2. Punkt kann ich nur sagen das ich mir die Quelltexte vieler Seiten angeschaut habe, die mit UTF-8 laufen und ich habe diesen Vermerk nie gefunden.

--
lg clements
  1. echo $begrüßung;

    1. Die Dateien sollten utf-8 encodet sein

    Das ist logisch. Wenn man Kodierung X verwenden will, muss man sie auch verwenden, sonst kommt gelegentlich Müll raus. Den muss man nicht sofort merken, weil einige Kodierungen besonders im Bereich von reinem ASCII (Byte-Werte von 0 bis 127) gleich sind. Wichtig ist, dass alle Beteiligten darüber informiert sind, welche Kodierung vorliegt, damit es nicht zu Missinterpretation und Datenverlust kommt.

    1. An den Anfang der CSS Datei eine "@charset "utf-8";"
      Zum 2. Punkt kann ich nur sagen das ich mir die Quelltexte vieler Seiten angeschaut habe, die mit UTF-8 laufen und ich habe diesen Vermerk nie gefunden.

    ASCII ist eine Untermenge von UTF-8. Solange keine Nicht-ASCII-Zeichen vorkommen, reicht es, den Text als ASCII auszuzeichnen. Das dürfte in den von dir beobeachteten Fällen der Fall sein. Außerdem wirkt hier ebenfalls die Kodierungsangabe im HTTP-Header vorrangig vor der Angabe in der Datei. Letztere ist vor allem dann nützlich, wenn kein HTTP-Header mehr da ist, z.B. nach einer lokalen Speicherung. Das gilt auch für Punkt 4 und 5.

    1. Daten aus Datenbanken und aus der url ebenfalls utf-8 encoden oder dafür sorgen dass sie als utf-8 ankommen

    Hier ist das DBMS gefordert. Kann es mit UTF-8 umgehen, muss man ihm mitunter noch mitteilen, dass man es auch zu verwenden gedenkt, denn die Standardeinstellung ist das nicht unbedingt. Kann es nicht mit UTF-8 umgehen, kann man es in der Regel trotzdem verwenden. Allerdings darf man dann nicht erwarten, dass es Dinge richtig macht, bei denen es auf die korrekte Interpretaion der Zeichen ankommt (z.B. Sortierung und String-Funktionen).

    1. In den Seitenmetatags utf-8 angeben "<meta http-equiv="content-type" content="text/html; charset=utf-8">"
    2. Bei jeder PHP seite am Anfang einen Contenttype Header mitsenden "header("content-type: text/html; charset=UTF-8");"

    siehe oben.

    1. In der php.ini " default_charset = "utf-8" " setzten

    Diese Konfiguration bewirkt das gleiche wie Punkt 5. Eins von beiden ist also überflüssig.

    1. Apache auf utf-8 Ausgabe umstellen

    Das ist sicher eine falsche Formulierung. Der Apache ändert nichts am Inhalt der Dokumente. Gemeint ist hier ebenfalls die Auszeichnung im HTTP-Header durch eine an den Content-Type angehängte Charset-Angabe. Das ist also ebenfalls das gleiche wie unter Punkt 5 und 6. Es wird durch die 3-fache Konfiguration nicht besser oder richtiger. Man hat nun aber drei Stellen, die man beim Ändern beachten muss. Allerdings hat man beim Provider nicht immer die Möglichkeit alle drei Stellen verändern zu können.

    Die erste große frage ist ob das alles ist, oder ob ihr noch tipps für mich habt?

    UTF-8 und Probleme damit, meist weil man nicht alles beachtet hat, ist nichts Neues, weswegen das hiesige Archiv oftmals schon die Anwort kennt.

    PHP kann noch nicht wirklich mit UTF-8 umgehen. Das wird es erst mit Version 6 können. Bis dahin gibt es einige Einschränkungen bei der Stringverarbeitung. Zeichen, die in UTF-8 mit zwei Bytes kodiert werden, werden von PHP als zwei Zeichen angesehen. Trennt man einen String, z.B. weil man nur die ersten 50 Zeichen darstellen will, und erwischt dabei ein 2-Byte-UTF-8-Zeichen genau in der Mitte, ...

    (Deine Frage berührt mehrere Themengebiete, aber Barrierefreiheit nun grade nicht.)

    echo "$verabschiedung $name";

    1. Hi dedlfix,

      erstmal ein ganz ganz großes danke für die top antwort. Auf einen Punkt wollte ich nochmal zu sprechen kommen:

      1. Daten aus Datenbanken und aus der url ebenfalls utf-8 encoden oder dafür sorgen dass sie als utf-8 ankommen

      Hier ist das DBMS gefordert. Kann es mit UTF-8 umgehen, muss man ihm mitunter noch mitteilen, dass man es auch zu verwenden gedenkt, denn die Standardeinstellung ist das nicht unbedingt. Kann es nicht mit UTF-8 umgehen, kann man es in der Regel trotzdem verwenden. Allerdings darf man dann nicht erwarten, dass es Dinge richtig macht, bei denen es auf die korrekte Interpretaion der Zeichen ankommt (z.B. Sortierung und String-Funktionen).

      heist das, dass ich alle POST und GET daten mit dieser Funktion behandeln muss: "utf8_decode" und alle Daten die aus der DB kommen mit "utf8_encode" ?

      --
      clements
      1. echo $begrüßung;

        Hier ist das DBMS gefordert. Kann es mit UTF-8 umgehen, muss man ihm mitunter noch mitteilen, dass man es auch zu verwenden gedenkt, denn die Standardeinstellung ist das nicht unbedingt. Kann es nicht mit UTF-8 umgehen, kann man es in der Regel trotzdem verwenden. Allerdings darf man dann nicht erwarten, dass es Dinge richtig macht, bei denen es auf die korrekte Interpretaion der Zeichen ankommt (z.B. Sortierung und String-Funktionen).

        heist das, dass ich alle POST und GET daten mit dieser Funktion behandeln muss: "utf8_decode" und alle Daten die aus der DB kommen mit "utf8_encode" ?

        Der Vorteil von UTF-8 gegenüber beispielsweise ISO 8859-1 ist, dass damit wesentlich mehr Zeichen kodiert werden können. Diese Funktionen wandeln zwischen den genannten Kodierungen hin und her. Das ist nicht in jedem Fall möglich, da ISO 8859-1 nur 256 Zeichen darstellen kann. Alle Zeichen, die darin nicht definiert sind, gehen bei einer Umwandlung aus UTF-8 verloren oder werden durch ein Ersatzzeichen repräsentiert, aus dem das ursprüngliche Zeichen nicht wiederhergestellt werden kann. Dein Ziel ist also, derartige Konvertierungen zu vermeiden, ansonsten lohnt sich UTF-8 nicht.

        Einem DBMS, das definitiv nicht mit UTF-8 umgehen kann (beispielsweise MySQL bis einschließlich Version 4.0) kann auf Latin1 (= ISO 8859-1) gestellt werden und bekommt UTF-8-Daten einfach so durchgereicht. Es wird sie als Bytefolge speichern und auch so wieder rausgeben. Solange keine Sortierung oder String-Funktionen verwendet werden sollen, sollte das DBMS damit kein Problem haben.

        Ein DBMS, das damit umgehen kann (beispielsweise MySQL ab Version 4.1), sollte man so konfigurieren, dass es die Feldinhalte als UTF-8 behandelt und auch auf der Verbindung zwischen sich und den Clients UTF-8 spricht. Ansonsten kann es zu Datenverlust durch Missinterpretationen oder durch eine automatisch durchgeführte Konvertierung (siehe oben) kommen.

        Konsultiere bitte das Handbuch deines Systems, was es zum Thema Zeichensatz und -kodierung zu sagen hat.
        Falls es sich um MySQL handelt, ist dieses Kapitel nicht gerade klein. Die Zusammenfassung lautet: Beim Erstellen von Tabellen und Feldern Stringfeldern die Kodierungs- bzw. Kollationsangabe angeben (z.B. utf8_general_ci oder utf8_unicode_ci) und beim Verbindungsaufbau explizit UTF-8 einstellen (SET NAMES utf8 als erstes Statement senden). (Diese Zusammenfassung entbindet dich nicht von der Lektüre des Handbuchs :-)

        echo "$verabschiedung $name";

      2. Hallo Clements,

        heist das, dass ich alle POST und GET daten mit dieser Funktion behandeln muss: "utf8_decode" und alle Daten die aus der DB kommen mit "utf8_encode" ?

        Das sollte man verhindern.

        In <form>ularen kann man das accept-charset-Attribut verwenden. Gibt man diesem den Wert utf-8 sollte der Browser die Formulardaten bereits richtig kodieren.

        Grüße, Tomas.