Characterset: UTF-8

From Edgar BV Wiki
Jump to: navigation, search

Introductie


Een karakter is een leesteken zoals een letter, getal of een symbool. Een karakterset is een groep van karakters zonder numerieke waarden. Zo heb je bijvoorbeeld het Latijnse alfabet of een Cyrillic alphabet.

In een gecodeerde karakterset wordt elke karakter geassiocieerd met een scalaire waarde. Zo heeft het karaker "A" in een ASCII karakterset de letter 65. D

Door de karakter enconding scheme kan een karakter geconverteerd worden naar een digitale representatie zodat deze kunnen worden gebruikt in bestanden, databases en strings. Deze methode wijst iedere karakterwaarde toe aan een opeenvolging van bytes. Zo heeft het karaker "A" in een ASCII karakterset de letter 65 en wordt gecodeerd naar een byte (0x41) in ISO 8859-1 (Latin 1).

In sommige gevallen is de encoding methode nog complexer: In UTF-8 heeft het karakter "á" de waarde 255 en zal geencodeerd worden als 2 bytes 0xC3 and 0xA1. UTF-8 heeft een multibyte 8-bit encoding waar een unicode scalaire waarde kan worden toegewezen aan een opvolging van 1 tot 4 bytes.

Dddd.jpg

Conclusie


Wanneer je een tekst opslaat worden de leestekens door een karakterset bepaald en deze zo ook opgeslagen, bijvoorbeeld in ISO 8859-1 (Latin 1) Als MSWord, Firefox of Internet Explorer dit bestand laad en een andere kararketset gerbuikt dan gebruikt bij het schrijven (bijv: UTF-8) dan zullen de karakters niet juist getoond worden omdat de scalaire waardes aan andere karakters worden geassioceerd. Dus zal je bij het tonen van de tekst moeten opgeven welke karakterset je gebruikt. Bij MSWord vindt hij dit als het goed is zelf wel uit. Om dit in browsers goed te laten tonen zal je dit zelf moeten aangeven. Dit kan doormiddel de META Tag in de "<head>" te plaatsen:

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

Dit zou het moeten oplossen denk je. Maar niets is minder waar. Als je in firefox gaat kijken kan je volgens de paginainfo dit te weten krijgen denk je:


Content type.jpg


Mooi! alles wijst naar UTF-8. Je hebt het immers opgegegeven... Maar als je nu dezelfde pagina upload naar een andere server kan je ineens hier tegen aanlopen.


Content type 2.jpg


Nu zie je dat nog steeds de Content-type: UTF-8 is maar de encoding ISO-8859-1 is. Het probleem onstaand in de headers, waarin de informatie wordt meegegeven van de server naar de cliënt, deze wordt door de browser als eerste uitgelezen en daarna pas de HTML pagina. Je moet er voor zorgen dat je ook de HTTP-Header ook de UTF-8 encoding mee geeft. Dit kan je op de server instellen of een nieuwe Content-Type header toewijzen:

Server configuratie (Apache, Standaard httpd.conf).

#AddDefaultCharset On
AddDefaultCharset UTF-8


OF een Virtual host definitie:

VirtualHost *>
  ServerName mijnserver
  DocumentRoot /home/sites/mijnsites
  AddDefaultCharset utf-8
  php_value default_charset utf-8
  php_value mbstring.internal_encoding utf-8
</VirtualHost>


OF een Content-Type header toewijzen

// Setting the Content-Type header with charset
  header('Content-Type: text/html; charset=utf-8');


EN Om te zien wat de standaard encoding van Mysql is:

SHOW VARIABLES LIKE 'character_set_database'; 
SHOW VARIABLES LIKE 'character_set_client';

EN Om de beschikbare karaktersets in mysql te zien

SHOW CHARACTER SET; 
SHOW COLLATION LIKE 'utf8%';

EN Om standaard karakterset in te stellen voor mysql (Server (/etc/my.cnf)):

[mysqld]
...
default-character-set=utf8
default-collation=utf8_general_ci

EN UTF-8 Database/tabel maken/veranderen

Database:
(CREATE | ALTER) DATABASE ... DEFAULT CHARACTER SET utf8 
Table:

(CREATE | ALTER) DATABASE ... DEFAULT CHARACTER SET utf8


EN Nadat je in php een mysql database connectie hebt gemaakt met een utf-8 database:

mysql_query("SET NAMES 'utf8'");


Er is in mysql een functie om karaktesets te converteren:

INSERT INTO utf8table (utf8column) 
SELECT CONVERT(latin1field USING utf8) 
FROM latin1table;

Na dit alles te hebben aangepast moet je ook nog de php.ini aanpassen:

default_charset = utf-8



TIP: Ook is het een goed idee om bij alle forms ook de accept-charset atrribute toe te wijzen met UTF-8.


<form accept-charset="utf-8">

Dan hebben we nog de UTF-8 encode functie in php die een ISO-8859-1 string converteerd naar UTF-8 Hierna kan je deze altijd terugconverteren van kan met utf8_decode.

   $str = utf8_encode($string);   


Een andere (betere) manier dan de utf8_decode functie zou kunnen zijn met iconf:

<?php
$myUnicodeString = "Åäö";
echo iconv("UTF-8", "ISO-8859-1", $myUnicodeString);
?>

Dit zou de bovenstaande variabele moeten weergeven in ISO-8859-1.


PHP BUGS

[18 Feb 2003 11:20am UTC] mail2rk at gmx dot de

Try following:

<?

$xml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>";
$xml .= "<root>my € sign</root>";
echo utf8_encode($xml);

?>

in the output the EURO sign won't show up.

While if you save the php file as utf8 and drop the 
utf8_encode method, the xml string will be shown properly.

[18 Feb 2003 11:24am UTC] moriyoshi@php.net

utf8_encode() only supports iso-8859-1 to UTF-8 conversion, whilst the
charset that covers euro sign is iso-8859-15.
Try iconv extension instead.



Verder in engels:

The basic problem PHP has with character encoding is it has a very simple idea of what the notion of a character is: that one character equals one byte. Being more precise, the problem is most of PHP‘s string related functionality (see common_problem_areas_with_utf-8 for further details) make this assumption but to be able to support a wide range of characters (or all characters, ever, as Unicode does), you need more than one byte to represent a character.

An example in code. From Sam Ruby’s i18n Survival Guide, he recommends using the string Iñtërnâtiônàlizætiøn for testing. Counted with your eye, you can see it contains 20 characters;


Iñtërnâtiônàlizætiøn
12345678901234567890


But counted with PHP‘s strlen function...


<?php
echo strlen('Iñtërnâtiônàlizætiøn');
?>


PHP will report 27 characters. That’s because the string, encoded as UTF-8, contains multi-byte characters which PHP‘s strlen function will count as being multiple characters. (! met php5 gaat dit wel goed.)

link http://www.phpwact.org/php/i18n/charsets


Aanvullingen

Beste Paul,


Ik zie dat je nogal wat aanpassingen maakt in php.ini en httpd.conf en my.conf om alles naar utf-8 toe te moven.
Nu is het zo dat de standaard Debian mysql install met collation latin1_swedish_ci werkt ipv 
utf8_general_ci. Ook wat apache en php als debian standaard gebruikt zal wel anders zijn als utf-8. 
Volgens mij krijg je dus problemen als je programma's in een non-standaard charset bouwt en naar andere servers 
toe wilt uploaden, omdat je alleen de apache / php env variables aan kan passen in je script 
(als je de server admin zo ver krijgt dat 'ie je dat toestaat in de virtualhost setting).


Dus, zit je op te zetten voor een utf-8 standaard voor development 
of heb je een oplossing voor sites / databases die in utf-8 zijn geschreven?


Met vriendelijke groet,
 Robin Edgar
 

 
He Robin,


Nee we hoeven niet speciaal alle servers in utf-8 in te stellen. 
In de uitleg staat inderdaad beschreven, hoe je een volledig utf-8 web-omgeving zou moeten kunnen installeren 
maar ook heb ik alternatieven beschreven; 
Er staat ook hoe je een utf-8 website kan plaatsen zonder server aanpassingen te maken:


- door een metatag in te stellen
- en als de server niet standaard op utf-8 staat dan moet je dit in de pagina doormiddel van een php-header definieren.
- Bij het maken van databases, tabellen, laden en toevoegen van data in mysql kan je handmatig opgeven welke 
charset je wilt gebruiken.




Heb je een site met allemaal losse webpagina's en kost het teveel tijd om in al deze pagina's meta-tags en headers 
toe te voegen heb je altijd een optie om een virtual host definitie aan te maken. 
Daarnaast kan je dan ook een .htaccess bestand gebruiken om voor php te charset in te stellen.


Misschien willen we ooit in de toekomst een verse nieuwe webserver utf-8 als standaard laten ondersteunen dan kan 
dat door de php.ini, my.cnf en httpd.conf aan te passen. 
Daarnaast is deze beschrijving ook handig voor als je rare teksten blijft krijgen en je krijgt het niet goed. 
Je kan al deze punten, instellingen en configuratiebesten nalopen wat waar staat ingesteld en of dat juist is.


Lees hier meer over het encoderen en decoderen van UTF-8 gerelateerde data voor bijv. in databases:

UTF-8 encoderen en decoderen