De site van H.J. de Boer

Homepage van H.J. de Boer > Frontpage

Unicode: standaard voor tekst-encodering


Een groot probleem van het huidige internet is het gebruik van verschillende tekensets (charsets) in verschillende werelddelen. In West-Europa wordt voornamelijk de tekenset iso-8859-1 (Latin 1) gebruikt, waarin zich letters, cijfers en symbolen bevinden die hier het vaakst gebruikt worden. Ook het euroteken maakt bijvoorbeeld deel uit van die tekenset. Het gaat dus om een voorgedefinieerde serie karakters, waarvan elke computer weet wat hij ermee moet doen, als hem bekend is uit welke tekenset deze tekens komen en hoe ze dus opgeslagen zijn. Als dat niet bekend is, of als de tekst is opgeslagen in een tekenset die zelf onbekend is voor de computer, dan zal hij bij sommige karakters niet weten hoe hij die moet weergeven. Ga je mooi de mist in. Dan krijg je allemaal regels als "??? ?????? ??". En dat leest nogal lastig... Alle problemen als: "hij kan mijn mailtjes niet lezen wanneer ik accenten gebruik" ontstaan doordat een of andere programmeur geen rekening ermee heeft gehouden dat als je niet vertelt of een bepaalde tekststring is ge-encodeerd volgens utf-8, ascii, iso 8859-1 of Windows 1252, je deze tekst niet correct kunt weergeven. Je kunt zelfs het einde ervan niet bepalen.

Een oplossing voor deze Babylonische spraakverwarring is het consequente gebruik van de tekenset UTF-8. Deze standaardset werkt met 8-bits encodering, waarmee eigenlijk al deze problemen verleden tijd kunnen zijn. Als alle websites, e-mailclients en andere tekstprogramma's deze tekenset maar standaard zouden gebruiken. utf-8 kan omgaan met elk bestaand karakter ter wereld en bovendien is er ruimte om de set uit te breiden met extra tekens, zo gauw deze gestandaardiseerd zijn. Voor een korte inleiding over dit onderwerp kun je dit artikel van Anne van Kesteren lezen. Alle tekens die nu in de database van hjdeboer.nl stonden, waren opgeslagen als iso-8859-1, omdat dat nu eenmaal de standaard tekenset voor deze geografische regio is. In Japan zal men misschien echter moeite hebben om mijn pagina's goed binnen te krijgen en bovendien is niet bekend hoe lang bepaalde tekens blijven bestaan voordat ze het veld moeten ruimen voor nieuwere, aangezien de ruimte bij de tekensets uit de serie iso-8859-* niet onbeperkt is.

In principe is conversie naar utf-8 eenvoudig, aangezien de eerste 128 karakters uit die tekenset hetzelfde zijn als de eerste 128 van de eerder genoemde West-Europese charset en hetzelfde als de oer-encodering us-ascii. Het overgrote deel van de tekens wordt dus wél netjes omgezet, als je van de West-Europese naar de Unicode tekenset gaat. Een aantal tekens zoals é, á, ó, ë, ï en dergelijke letters moeten daarna nog met de hand gewijzigd worden. Die zitten namelijk in utf-8 op een andere plaats en de encodering van de West-Europese tekenset komt bij die tekens dus niet overeen. In de ene tekenset neemt een bepaald teken namelijk maar één byte in, waar het zelfde teken in een andere tekenset bijvoorbeeld twee bytes kan innemen, afhankelijk van de manier van encoderen. Vandaar dat die tekens als '?' worden weergegeven wanneer je aan je webpagina's opdraagt om de tekst als Unicode te serveren. Maar goed, het omzetten van bestaande, reeds in de database opgeslagen teksten is in principe wel gauw te doen.

Verder moet aan elke PHP-pagina worden verteld dat de pagina als utf-8 ge-encodeerd en verstuurd moet worden:

php:

1
<?
header("content-type:text/html; charset=utf-8");
?>

Alleen het veranderen van het meta-element in de head-sectie van het HTML is mijns inziens eigenlijk niet voldoende als PHP en Apache de pagina's niet standaard als Unicode versturen. Als de meta-tag namelijk staat op meta http-equiv="content-type" content="text/html;charset=utf-8" dan verander ik de headers pas als de browser eigenlijk al begonnen is het met het parsen van de pagina. Door met PHP te forceren dat de header veranderd wordt vóór het versturen van de pagina, ontvangt de browser al de goede header voordat hij überhaupt één karakter van de pagina gaat interpreteren. Dat is naar mijn idee dan ook de meest aangewezen manier om de tekenset te bepalen, wanneer de server daar niet voldoende op ingesteld is. Als je op élke pagina de juiste header gebruikt, dan wordt alle tekst die door de browser wordt weergegeven als Unicode gepresenteerd, maar misschien evenzo belangrijk: tekst die je via textarea's invoert om in op te slaan, worden op die manier ook als Unicode in je database gepropt.

Nu had ik één groot probleem bij de overgang naar de nieuwe encodering van deze pagina's. PHP is namelijk standaard ingesteld op de West-Europese charset. Dat wist ik niet en het was voor mij onbelangrijk... tot vanmiddag dus. Om te voorkomen dat mensen in de reacties HTML kunnen gebruiken en daarmee de layout van mijn pagina's vernaggelen, trekt de OML-parser deze reacties door de PHP-functie htmlentities() heen. Deze functie zet onder andere de < en > waarmee HTML-tags gemaakt worden om naar &lt; en &gt; zodat deze als tekst worden opgevat in plaats van als functionele HTML. Nix mis mee, dat ging altijd goed. Deze functie zet echter ook & om naar &amp; omdat anders XML-parsers, browsers en validators op hun bek gaan. Echter, de functie doet dat, uitgaande van de West-Europese charset. Als ik een tekst in utf-8 door die functie trek, dan vernaggelt de functie bepaalde tekens uit die tekst, omdat hij niet goed weet dat dat gewone letters zijn in utf-8. Dat gebeurde dus vanmiddag ook keer op keer en het duurde even voor ik doorhad dat het aan die functie lag. De oplossing hiervoor was het volgende:

php:

1
2
3
4
5
6
7
<?
function custom_htmlentities ($text)
{
    $text = htmlentities ($textENT_QUOTES'UTF-8');
    return $text;
}

$reactie = custom_htmlentities ($reactie);
?>


Hiermee geef ik aan de PHP-functie aan dat het ding zijn werk doet, uitgaande van utf-8. Voordat ik dat gefixt had, werd bijvoorbeeld een 'é' in tekst die door deze functie heen gehaald was weergegeven als ©. Juist... twee rare karakters. Nu, toen dit probleem eenmaal opgelost was ben ik eerst met wat andere dingetjes bezig gegaan, maar het is belangrijk om in de gaten te houden dat PHP wat hulp nodig heeft als je alles in Unicode wilt gaan doen!

Verder hebben sommigen van jullie al gemerkt dat hjdeboer.nl afgelopen week nogal eens 'stuk' was. Na mijn tentamen van dinsdag 16 november ben ik begonnen met het herschrijven van het JavaScript-menu bovenin naar een totaal op CSS gebaseerd menu. Dat menu was XHTML 1.0 strict compliant en toen ik dat klaar had, bedacht ik me dat ik wel eens een begin kon maken met datgene waartoe ik in de post over Firefox en Internet Explorer heb opgeroepen: standaardisatie en het gebruik van XHTML om Internet Explorer langzaam uit te rangeren. Om mijn eigen pleidooi maar te volgen heb ik eerst een voorzichtig begin gemaakt... het is een enorme klus namelijk. Voor zover ik nu kan zien zijn alle openbare pagina's na een dag of vijf pielen allemaal XHTML 1.0 strict valid! Nu de beheerspagina's nog, maar dat komt allemaal wel. Zo lang dat allemaal nog niet consequent klaar en gecontroleerd is, verzend ik alles nog met het MIME-type text/html, ook naar browsers die application/xhtml+xml wél aankunnen. Alle pagina's die ik namelijk nog niet herschreven heb, zouden anders onherroepelijk een XML-fout opleveren. Als alle pagina's eenmaal XHTML valid zijn, dan komt dat wel. Tegen die tijd besluit ik dan ook wel of ik een paar aanpassinkjes doe naar XHTML 1.1, zodat ik alles als application/xhtml+xml moet versturen en Internet Explorer uit kan sluiten. Vooralsnog heb ik de layout in hoge mate cross browser compatible gemaakt.

Tot slot: het gebruik van utf-8 is belangrijk. Standaardisatie is belangrijk. Voor nu en voor de toekomst van het internet. Een tijdelijke site om even wat statische content op te stallen kan zonder standaarden en Unicode tekst-encodering. Een site die langer mee wil dan de dag van vandaag, moet anticiperen op de toekomst en zich conformeren aan standaarden die uniform en uitbreidbaar zijn.