Avete mai incontrato sulle pagine web (vostre o altrui) degli strani caratteri senza senso, o lettere sostituite da un riquadro vuoto? Sono problemi legati alla codifica dei caratteri sul web.
Tenteremo qui di semplificare per quanto possibile l’argomento in modo da offrire una comprensione di base del problema e fornire una guida pratica su cosa fare nel vostro ambiente di sviluppo web.
Per chi non avesse voglia di leggersi tutto il papiro ma di saltare alle cose pratiche, la sintesi è qui sotto.
Indice degli argomenti:
Introduzione: da Ascii a Unicode
Cos’è la codifica di carattere
Ogni carattere alfanumerico presente nei documenti di testo sui nostri computer è rappresentato da numeri, cioè sequenze di zeri e uno (bit) presi a gruppi di otto (byte). Se un byte contiene 8 bit, per ragioni matematiche potrà assumere al massimo 256 valori diversi (da 0 a 255, anche se espressi in base binaria. Non è necessario conoscere la base binaria. Basta ricordare che con un byte si possono rappresentare 256 numeri al massimo).
Siccome sul monitor vediamo lettere e non solo numeri, è evidente che da qualche parte il nostro computer compie una trasformazione. Ad ogni numero (byte) nel file del nostro testo viene assegnato un carattere da mostrare a monitor attraverso un certo font. Se per esempio il byte contiene il numero 65 (in decimale), viene mostrata la lettera A maiuscola. Perché proprio la A maiuscola? Questa corrispondenza tra numeri e caratteri viene memorizzata in specifiche tabelle contenute nei sistemi operativi dei computer.
Tabella ASCII base
La più famosa di queste tabelle è la tabella ASCII (definita dall’ANSI), inventata nel 1961 (ma pubblicata nel 1963) da un ingegnere dell’IBM, Robert Bemer. Al numero 65 corrisponde per l’appunto la A maiuscola.
La tabella ASCII di base contiene i riferimenti ai caratteri per i primi 128 numeri rappresentabili con un byte. Questo perché nel 1961 i byte usavano solo 7 bit, e non 8 come oggi, per rappresentare i caratteri alfanumerici. E con 7 bit si possono rappresentare solo i numeri da 0 a 127, appunto. 128 caratteri bastavano per le lettere dell’alfabeto inglese, che non ha accentate o caratteri speciali, con l’aggiunta di qualche decina di caratteri invisibili che servono a comunicare cose come gli a capo, i ritorni di riga, eccetera.
Negli anni è diventato evidente che la tabella ASCII di base non era sufficiente per lingue diverse dall’inglese. Si è prima provato ad espanderla con una tabella ASCII estesa, che, sfruttando l’ottavo bit prima utilizzato per altri scopi, consentiva di definire altri 128 caratteri, fra cui le accentate. Il problema era che questi 256 caratteri complessivi non sono gli stessi nemmeno fra alfabeti europei, figuriamoci se consideriamo gli alfabeti asiatici, mediorientali, russi, ecc. Insomma, la soluzione non era sufficiente per rappresentare tutti i caratteri dei paesi nei quali i computer venivano usati.
Tabella ASCII estesa
Una prima soluzione è stata di mantenere stabile la tabella ASCII di base (i primi 128 caratteri, corrispondenti all’alfabeto inglese) e di prevedere molte diverse tabelle ASCII estese, quante ne servivano nei diversi alfabeti. L’ISO, ente di standardizzazione internazionale, ha così definito le tabelle di codifica cosiddette ISO 8859 (ricalcandole dall’ASCII), con 14 varianti, ognuna per una diversa tabella estesa. La tabella ISO 8859-1, detta Latin-1, è quella che siamo più spesso abituati ad usare per le pagine web, perché rappresenta le accentate più comuni, quelle in uso in Italia, Francia, Spagna. Altre ISO 8859 sono usate nella Repubblica Ceca, in Russia, eccetera.
La babele delle molte tabelle estese
La soluzione “multi-tabella estesa” può anche andar bene se in un documento (o in una pagina web) inseriamo solo caratteri provenienti da solo uno di quegli alfabeti, codificato da una sola tabella estesa. Ma spesso non è così. A volte dobbiamo inserire frammenti di testo provenienti da tabelle diverse. E allora questa soluzione non funziona più. Con la globalizzazione il problema è chiaramente diventato sempre più urgente.
Queste tabelle ASCII estese, che contenevano un repertorio limitato di caratteri e che non potevano essere usate contemporaneamente, non sono una soluzione adeguata per scrivere testi a prova di internazionalizzazione. Per di più i produttori di computer hanno sempre usato versioni leggermente modificate delle tabelle standard, chiamate in modi diversi (per esempio, Microsoft utilizza per i testi di default la tabella Windows-1252, che è una variante della ISO 8859-1).
Spazio di caratteri Unicode e ISO 10646
Una soluzione migliore è venuta da Unicode, un ente che si è posto il problema di descrivere in un’unica tabella, o meglio, in uno spazio concettuale, tutti i caratteri esistenti in tutti gli alfabeti noti, e anche qualcosa di più. Simboli, alfabeti nascenti, futuri, futuribili e ipotetici: tutti sono descritti nello spazio Unicode che comprende più di un milione di caratteri, divisi in “mappe” di 64000 caratteri circa. Uno spazio del genere ha il pregio di assegnare un numero univoco a tutti i caratteri esistenti e non ancora esistenti, in modo che si possano referenziare tutti contemporaneamente.
Ma certo un byte non è più sufficiente a descrivere qualunque numero presente in questo spazio. Per descrivere il carattere corrispondente al punto 1034 dello spazio Unicode, sarebbero necessari almeno due byte. Ma ancora di più (quattro, per la precisione) sarebbero necessari per descriverli tutti.
Va notato che l’intero repertorio dei caratteri definiti in Unicode è stato recepito dalla ISO 10646. Perciò spesso l’insieme di caratteri Unicode è anche definito ISO 10646. I due insiemi vengono di norma anche aggiornati contemporaneamente nel caso di aggiunta di nuovi caratteri.
Distinguere repertorio di caratteri e codifica di carattere
Con Unicode entra in gioco in maniera chiara la distinzione fra repertorio dei caratteri (tutti i caratteri descritti nel sistema Unicode) e codifica del carattere. Le due cose coincidevano in pratica con il sistema ASCII o ISO 8859. Non più in Unicode. Unicode definisce in maniera univoca la corrispondenza fra un preciso carattere (sia esso una lettera latina o un ideogramma cinese) e un numero che rappresenta le coordinate di quel carattere nello “spazio unicode”, cioè il repertorio di caratteri. Ma il modo in cui i numeri sono rappresentati dai byte di in un determinato documento dipende dalla codifica di carattere scelta.
In altre parole, in Unicode sono possibili diverse codifiche di carattere. Esse si riferiscono sempre al medisimo repertorio di caratteri, ma usando un numero di byte differente, per ragioni di spazio, di efficienza. Una codifica Unicode universale, che utilizza 4 byte per tutti i caratteri, è la UCS-4. E’ usata raramente nei documenti, perché in un testo latino occuperebbe 4 volte lo spazio della codifica ASCII.
La codifica UTF-8
Codifiche più usate sono la codifica UTF-8 e la UTF-16. La UTF-16 utilizza 2 byte per memorizzare i primi 65536 caratteri, mentre ne usa 4 per tutti gli altri.
UTF-8 sfrutta invece una importante caratteristica di Unicode, quella di essere parzialmente compatibile con la tabella ASCII. Nota: questa parte è stata corretta in data 13 febbraio 2012: I primi 128 caratteri di Unicode sono infatti uguali all’ASCII di base. UTF-8 può usare un solo byte per i primi 128 caratteri, quelli dell’ASCII base. Usa poi 2 byte per memorizzare altri 1920 caratteri, corrispondenti al latino esteso, al cirillico, greco, romanico, ecc., e 3 byte per i successivi 63488 caratteri (incusi molti ideogrammi orientali). Fine correzione.
Per i caratteri successivi, usati più di rado, adopera 4, 5 o sei byte. Un’altra caratteristica interessante della codifica UTF-8 è che quando usa più di un byte per codificare un carattere, nessuno dei due byte, preso singolarmente, può venir scambiato per un byte ASCII. Il che evita fraintendimenti fastidiosi per i sistemi operativi e i programmi che non comprendono UTF-8. Questo è particolarmente importante per vecchi file di configurazione dei sistemi operativi originariamente non supportanti Unicode.
Si tratta dunque di un’ottima codifica per noi occidentali, equivalente (e compatibile) all’ASCII per le lingue latine, e in grado tuttavia di rappresentare in un medesimo documento qualunque carattere disponibile nel repertorio Unicode.
Codifica di carattere, sistemi operativi e programmi
Quando salviamo un qualunque documento di testo (o comunque contenente informazioni alfanumeriche) dovremmo porci il problema di quale codifica di carattere utilizzare. I programmi autore di solito compiono questa scelta per noi, ma non sempre scelgono bene.
Un tempo i programmi principali erano impostati per usare una codifica di carattere che corrispondeva grosso modo alla codifica ASCII di base per i primi 128 caratteri, e ad una versione più o meno standard della tabella ASCII estesa per gli altri. E il “più o meno” dipende dal fatto che, come detto, i produttori di sistemi operativi preferivano “variare” un po’ la tabella estesa. Questo portava, per esempio, un testo scritto in Word per Windows a non essere visualizzato correttamente in Word per Macintosh, anche se “in teoria” usava sempre la stessa tabella estesa. In realtà, i due sistemi operativi usavano due tabelle estese parzialmente divergenti (e davano un nome diverso all’insieme di 256 caratteri che ne risultava: Windows-1252 per quanto riguarda Microsoft e Mac OS Roman nei vecchi Apple).
In anni più recenti (da Windows 98 SE timidamente e poi con Windows 2000 e successivi, e da Mac OS X) i due principali produttori di computer hanno aggiornato i propri sistemi operativi per supportare pienamente Unicode. Tuttavia, diversi software usano codifiche differenti per i propri documenti. Per usare quella che vogliamo noi bisogna spesso andare nelle opzioni avanzate di salvataggio o nelle preferenze di un programma.
Unicode e il web
Unicode e filiera di pubblicazione delle pagine web
Per quanto riguarda le pagine web, cioè i documenti HTML, il problema investe l’intera filiera di produzione e distribuzione delle pagine. Dal programma che usate come editor HTML, all’eventuale database e linguaggio di scripting per i siti dinamici, fino al server web e al browser usato dall’utente.
Bisogna ricordare che per una pagina web servita dal server al browser il character encoding è definito in maniera diversa rispetto ad una pagina web creata (o salvata) in locale e aperta con il browser sul proprio computer. Ma andiamo con ordine.
Pagine HTML
La codifica di default (cioè quella usata se voi non la specificate) prevista per le pagine HTML (o servite con mime-type text/html, come vedremo più avanti) è ISO 8859-1. L’indicazione di codifica per l’UTF-8 va dunque esplicitamente indicata in HTML e XHTML (quest’ultimo se servito come text/html) con il tag meta:
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
Si noti che UTF-8 è in maiuscolo. Da specifica dovrebbe esserlo, anche se è frequente trovare pagine codificate in minuscolo:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
e non sono note controindicazioni di fatto. La versione corretta è comunque quella in maiuscolo.
La codifica deve essere scritta nello head del documento. Perché la cosa funzioni, però, il documento deve essere salvato con codifica UTF-8 nell’editor testuale, su un computer/sistema operativo in grado di supportare nativamente Unicode (da Mac OSX a Windows Vista in poi, nonché su Linux). Secondo Joel Spolsky il metatag dovrebbe essere la prima cosa che si incontra nel codice dopo i tag di apertura di HTML e HEAD. Infatti, se il title venisse prima, e contenesse caratteri Unicode, potrebbe capitare che il browser li interpreti in maniera errata.
Questo però vale soprattutto per le pagine salvate in locale. Infatti per le pagine online il metatag ha senso solo se il server non specifica il content type negli header http. Che è il prossimo argomento.
Gli header http e il content-type
Sebbene le pagine HTML abbiano il metatag
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
questo non è il metodo corretto per impostare il charset nelle pagine servite online. La precedenza in questa impostazione ce l’ha infatti il server, che invia assieme alla pagina anche delle intestazioni (nascoste all’utente, ma interpretate dal browser) con varie informazioni, fra cui il content-type del documento ed eventualmente (non lo fa sempre, ma dovrebbe) il charset utilizzato.
Il content-type è un campo dello standard MIME che dice al browser come deve interpretare il formato di quel documento. Dice insomma se il flusso di byte che seguono va interpretato come immagine jpeg, pagina HTML, pagina di testo, pagina xml, eccetera. Possiamo pensare, ma solo per capirci, che il content-type equivalga all’uso delle estensioni sul nostro sistema operativo. Se il sistema operativo trova un documento con l’estensione .doc, tenta di aprirlo con Word. Se trova .txt, tenta di aprirlo con il blocco note o con un altro editor testuale predefinito. Insomma, le estensioni servono a dire ai sistemi operativi che tipo di file è e con quale programma aprilo.
Sul web le estensioni non servono. A stabilire che tipo di documento è (e dunque dire al browser se tentare di interpretarlo e con quale motore di parsing, oppure se tentare di scaricarlo) è il content-type contenuto nello header http. Di norma le pagine HTML hanno il content-type text/html. Al content-type text/html è associato un character encoding di default, che non è Unicode, ma ASCII!
Per dire al browser che quella pagina HTML è invece codificata come Unicode, bisogna specificarlo negli header http, dicendogli di non usare la codifica di default ASCII, ma quella Unicode, appunto. Per farlo è però necessario modificare i file di configurazione del server. In Apache, per esempio, si usa:
AddDefaultCharset utf-8
Si noti che la specifica Apache sottolinea che questo header dovrebbe sovrascrivere qualunque metatag contenuto nell’HTML, ma che il comportamento reale dipende dai singoli client. Dunque, in realtà non possiamo trascurare il nostro buon vecchio metatag e affidarci al solo server.
Inoltre è anche buona norma accertarsi che il server invii un charset congruente a quello del metatag usato nell’HTML.
Usare PHP, ASP o JSP per sovrascrivere l’encoding del server
Se non si ha accesso alla configurazione del server ma le pagine sono generate dinamicamente da un linguaggio di scripting (php, asp, jsp, ecc.), è possibile scrivere un’apposita istruzione in cima al documento, che sovrascriva il content-type del server. In php l’istruzione è:
header('Content-type: text/html; charset=utf-8');
In ASP:
<%Response.charset="utf-8"%>
In JSP:
<%@ page contentType="text/html; charset=UTF-8" %>
Ulteriori dettagli (e ulteriori linguaggi) su questa pagina del W3C.
In sintesi: per le pagine web è bene accertarsi che sia lo header http che il metatag del codice, scritto prima del title del documento, impostino il chasert a UTF-8. Se non si ha accesso al file di configurazione del server, e si riesce a verificare che il content-type non viene inviato con la codifica UTF-8, dovremo usare un linguaggio di scripting per sovrascriverlo.
E le pagine XML?
Fin qui abbiamo parlato solo di HTML e di XHTML servito come text/html (per un approfondimento su XHTML vedi sotto). XML è diverso: non usa il metatag che usa l’HTML. Il charset viene definito direttamente nel prologo xml:
<?xml version="1.0" encoding="utf-8"?>
Si noti però che XML, a differenza di HTML, è di default un formato che dovrebbe essere servito come Unicode. Dunque il server, se configurato correttamente, dovrebbe inviare già le pagine con XML con gli header http impostati a definire il charset UTF-8. In caso di conflitto, però, i programmi utente che sono conformi con le specifiche di XML devono dare la precedenza al prologo XML.
Quale content-type usare per le pagine XHTML?
Qualcuno avrà notato che le differenze di content-type fra HTML e XML potrebbero creare qualche problema nell’uso di pagine XHTML. XHTML 1.0 è infatti una riscrittura di HTML 4.01 in XML, con modifiche ed eccezioni che ne consentano la retrocompatibilità. Dobbiamo allora usare il metatag come in HTML per definire la codifica di carattere? O piuttosto il prologo XML come in tutti i documenti XML? O è già il server che se ne occupa?
Il problema non è banale. Infatti la risposta è: “dipende”. Dipende da come è costruito e servito il documento XHTML. Infatti, proprio per ragioni di compatibilità, è consentito servire XHTML con diversi content-type a seconda del rispetto o meno di alcune regole di retrocompatibilità scritte nell’Appendice C delle specifiche di XHTML 1.0.
Se il documento XHTML 1.0 è retrocompatibile con HTML 4.01 e volete che venga interpretato dai browser che interpretano l’HTML, allora la cosa più sicura è servirlo con il content-type text/html.
Si noti che, al di là delle buone intenzioni, questo è praticamente l’unico modo sicuro di servire XHTML 1.0. Infatti alcuni browser non sono di default configurati per interpretare XHTML 1.0 servito come application/xhtml+xml: tentano di scaricare la pagina, anziché di interpretarla. Vale in particolare per Explorer fino alla versione 7.
Senza contare che i browser che invece sono in grado di interpretare anche XHTML 1.0 con application/xhtml+xml sono inflessibili nell’interrompere in tal caso il parsing se sono presenti errori di codice. Ed errori di codice sono anche eventuali caratteri non legali o mal codificati. Dunque è particolarmente rischioso, se non avete una filiera tutta orientata alla gestione corretta di Unicode, servire XHTML 1.0 come application/xhtml+xml (anche con la negoziazione del contenuto, argomento che ci porta fuori tema, ma che in sintesi personalmente sconsiglio se avete siti ad alto traffico e dove sia cruciale evitare interruzioni anche momentanee del servizio).
Non è finita. Infatti, mentre è possibile inserire il metatag
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
nei documenti XHTML 1.0, è sconsigliato (non dalle specifiche, ma dalla pratica) inserire il prologo XML, perché questo attiva il quirk mode in Explorer fino alla versione 6, modificando così la resa visiva delle pagine.
In sintesi: per le pagine XHTML 1.0, accertarsi di rispettare l’appendice C di retro compatibilità con HTML e comportarsi come ci si comporterebbe con HTML. Cioè usare il metatag nel codice e impostare il corretto encoding utf-8 nel content-type text/html associato anche ai file XHTML 1.0.
E le pagine XHTML 1.1?
Quanto detto vale per XHTML 1.0, ma non per XHTML 1.1. Questa più recente versione della specifica, infatti, nel tentativo di correre avanti, è una riscrittura più rigorosa di XHTML 1.0 che non prevede la retro compatibilità con HTML 4.01. Dunque non è consentito che i documenti XHTML 1.1 vengano serviti con il content-type text/html. Essi sono sempre applicazioni application/xhtml+xml, e come tali vanno serviti. Il character encoding di default è UTF-8 per il server, e, per definirlo a livello di documento, bisogna necessariamente usare il prologo XML.
Si sia consapevoli però che l’uso di questa DTD è praticamente quasi impossibile da usare correttamente sul web per il mancato supporto di Explorer. L’unico modo per usarlo correttamente è fare una content-type negotiation sul server, identificando il browser e inviando codici diversi a browser diversi. Ad esempio, servire il codice con la DTD XHTML 1.0 a Explorer, e con la DTD XHTML 1.1 agli altri browser. Questo però spesso è reso assai arduo dall’obbligo di mantenere la retrocompatibilità con l’Appendice C di XHTML 1.0 nei casi in cui lo si debba servire in quel modo per Explorer. L’appendice C impedisce al codice di essere contemporaneamente compatibile con la specifica XHTML 1.0 e 1.1. Se così non fosse, allora le due specifiche non avrebbero senso. Dovreste dunque mantenere due codici distinti (da servire con le due DTD) o usare una routine di conversione al volo. Il rischio di errori o di problemi di mantenimento è così piuttosto alto. E d’altra parte servire XHTML 1.1 come text/html è semplicemente sbagliato. Perciò, dato che non offre vantaggi apprezzabili mentre aumenta i problemi, la cosa più semplice è dire momentaneamente addio all’XHTML 1.1.
Perché non mantenere semplicemente la codifica ISO 8859-1?
Be’, questo è ovviamente possibile, spesso corretto, ma comunque sconsigliato! L’evoluzione del web ha fatto prendere infatti una piega particolare agli eventi. Consideriamo i seguenti fattori:
- Apertura ai contenuti generati dagli utenti. La maggior parte dei vostri contenuti è in italiano (o anche in inglese), ma, di tanto in tanto, qualche commento su un blog o su un forum che ospitate viene lasciato da utenti che scrivono da paesi dell’europa dell’est. Se avete la codifica ISO 8859-1 non verranno visualizzati correttamente.
- Un giorno potreste voi stessi voler pubblicare alcuni contenuti in altre lingue, e allora dovreste comunque porvi il problema
- Se i vostri contenuti verranno un giorno, in qualche forma, serviti in XML (non in XHTML 1.0 servito come text/html, ma in XML vero e proprio), come ad esempio nei feed RSS o ATOM, allora il problema della codifica che avevate lasciato fuori dalla porta nel vostro vecchio HTML codificato come ISO 8859-1 vi rientra improvvisamente dalla finestra, perché XML ha una gestione delle entità carattere diversa da HTML, e di default usa la codifica UTF-8.
- Se aggregate nella vostra pagina HTML contenuti provenienti da feed altrui vi conviene usare UTF-8 (altrimenti siete costretti ad usare una funzione come utf8_decode in php).
- Se dovete interagire con altri ambienti che usano di default UTF-8, come Flash e Flex, è opportuno usare quella codifica.
- Se usate Ajax, ovviamente, lavorando Ajax con frammenti XML, dovrete usare UTF-8.
Entità e referenze numeriche al carattere in XML
In HTML, per semplificare la portabilità e l’interoperabilità dei dati, alcuni caratteri speciali possono essere scritti non direttamente, da tastiera, battendo il tasto corrispondente, ma attraverso sequenze di caratteri ASCII di base che referenziano o il numero (in decimale o in esadecimale) corrispondente nell’insieme di caratteri di riferimento, o attraverso un codice nominale, detto entità.
Ad esempio, la lettera á (a minuscola con accento acuto) può essere scritta in HTML direttamente (e se la codifica è ISO 8859-1 dovrebbe bastare), oppure come entità numerica con l’espressione á
, in decimale, o á
, in esadecimale. E infine come entità nominale: á
.
Quest’ultimo è il modo in cui vi sarete probabilmente abituati a codificare i caratteri accentati, anche perché è il default di molti editor HTML visuali. Be’, dimenticatevelo, perché in XML non è, di default, valido che per pochi caratteri. In particolare, in XML vanno sempre usate le entità per i seguenti caratteri: &
, <
, >
. E volendo è possibile usarlo per le doppie virgolette: &quo;
.
Tutte le altre entità (comprese tutte le entità delle vocali accentate in italiano) possono essere usate solo se preventivamente definite nella DTD referenziata nell’XML, cosa che non è comune e che non è nemmeno consigliabile.
Immaginate che i vostri feed RSS traggano i dati dalla stessa fonte da cui viene generato l’HTML (tipicamente, un campo del database, ma potrebbe anche essere un file di testo separato). Se nella fonte di dati sono presenti entità carattere, dovrete riconvertirle in referenze numeriche o in caratteri Unicode codificati come previsto dalla codifica scelta (normalmente UTF-8) se non volete incorrere in errori di validazione del feed. E l’errore di validazione in XML comporta (da specifiche…) il blocco del parsing da parte dei programmi!
Le referenze numeriche del carattere sono sempre riferite a Unicode
Al contrario è da notare che, qualunque sia la codifica di carattere scelta in HTML o in XML, l’uso della referenza numerica (decimale o esadecimale) è sempre riferita allo spazio Unicode, e dunque è sempre un metodo sicuro per referenziare, nel dubbio, qualunque carattere (ad esempio á
). Tuttavia, non è consigliato usare con troppa facilità queste referenze numeriche per tutti i caratteri, perché:
- Richiedono molti più byte, di solito, della codifica UTF-8. Indipendentemente dal carattere, infatti, bisogna usare dai 4 agli 8 byte per rappresentare le referenze numeriche
- Un uso massiccio delle referenze numeriche anche per i caratteri latini di base renderebbe il codice illeggibile.
Tuttavia, l’universalità, tanto in HTML che in XML, di questo metodo, tipico di questi linguaggi di marcatura, lo rende un efficace passe-partout in casi dubbi, per rappresentare soprattutto simboli rari, accentate, segni tipografici (apostrofi che siano apostrofi e non virgolette, doppie virgolette di apertura e chiusura, caporali, trattini corti e lunghi, ecc.) in maniera compatibile sia con HTML che XML.
Invece le entità (nominali) sono sconsigliate, tranne che per i tre/quattro caratteri visti sopra, perché trattate di default in maniera differente dalle DTD HTML e XML. Dunque non usate é
, á
, e così via, nelle vostre pagine XHTML!
BOM o non BOM?
Nelle opzioni di salvataggio del file dovreste trovare in un menu a tendina l’opzione per salvare il file come UTF-8. A seconda dell’editor potreste trovare due opzioni: UTF-8 con BOM o senza BOM. Il BOM (Byte Order Mark) è una sequenza di byte che viene inserita in testa al documento per specificare in quale modo i caratteri Unicode composti da più di un byte devono essere considerati (in particolare, se il primo byte rappresenta la parte iniziale o finale del numero).
Se tutti i programmi gestissero correttamente il BOM, potremmo ignorare la cosa e affidarci ad una qualunque delle opzioni. Invece non tutti (browser, parser, script vari) comprendono correttamente il BOM, dunque è semplicemente bene ometterlo, scegliendo l’opzione di salvataggio senza BOM.
Alcuni problemi di validazione del codice e/o di apparenza della pagina potrebbero essere causati dal BOM. Ad esempio potreste trovare una riga bianca in cima alla pagina web, o una riga con alcuni caratteri buffi. Se non è un errore Css, è il BOM. Browser diversi si comportano in maniera diversa. Per fare un test e avere un’idea più precisa potete usare queste pagine di test sul sito del W3C. Comunque se vi capita, salvate nuovamente il file con l’opzione senza il BOM.
Il database
L’altro punto del processo di pubblicazione web nel quale le cose possono andare storte è il database. Anche nel database, infatti i contenuti vengono scritti seguendo una certa codifica. Bisogna essere sicuri che il proprio database supporti Unicode e che usi la codifica UTF-8 di default. In mysql dalla versione 4.1 vi è un supporto di Unicode, ma spesso non è l’impostazione predefinita.
Bisogna accertarsi che mysql sia configurato per usare UTF-8 a livello server. Dunque prima di eseguire qualunque query e appena dopo essersi connessi al server, eseguire
SET NAMES 'utf8';
Anche nella creazione di tabelle e campi che possono includere testi, bisogna specificare la codifica UTF-8
Sintesi e approfondimenti
Ragioni per non usare Unicode
Ci sono state anche ragioni per non usare UTF-8 e Unicode. Segnatamente, lo scarso supporto di alcuni vecchi browser (Netscape 4, per esempio) e di alcuni sistemi operativi. Il problema è evidentemente in via di risoluzione, perché tutti i nuovi dispositivi (inclusi i portatili) sono avvertiti ormai da anni del problema e sono pronti per Unicode, anche se magari non al livello di supporto che può far dormire sonni tranquilli. Comunque, a meno che il vostro progetto non abbia come requisito la compatibilità con sistemi e programmi davvero obsoleti, usare UTF-8 è in assoluto la soluzione più sicura.
Una possibile altra ragione per non usare UTF-8 è l’inadeguatezza del vostro ambiente di sviluppo (editor HTML, computer, server, database, linguaggio di scripting, CMS). In tal caso vale il caldo consiglio di aggiornare la strumentazione. In particolare i linguaggi di scripting possono essere un ostacolo duro da superare. In un progetto recentemente affrontato si è evidenziato che porzioni di script ASP si portano spesso con sé definizioni di codifica di carattere che poi non si riesce agevolmente a sovrascrivere a livello di pagina. PHP ha introdotto un supporto a Unicode dalla versione 5, sebbene qualche strumento vi sia anche nella 4, e solo dalla 6 sarà nativamente orientato a Unicode.
Gli stessi database possono costituire un problema. MySql supporta in maniera più robusta Unicode dalla versione 4.1. Può essere necessario riconvertire tutte le tabelle, o cambiare tipologia di alcuni campi, per renderli compatibili all’aumentato numero di byte necessario con i contenuti UTF-8. Il comando COLLATE è stato messo a disposizione per le conversioni di codifica dei caratteri.
Infine, i CMS possono non gestire correttamente Unicode, soprattutto se sono vecchi o ereditano e non correggono i problemi dei linguaggi di scripting o del database. Si stanno inevitabilmente tutti convertendo a UTF-8, ma siamo ancora nel mezzo della transizione.
Ragioni per usare Unicode
Tutte quelle viste fin qui. Inoltre, il fatto di essere compatibile con ISO 8859-1, rende la scelta ancor più facile per noi occidentali di quanto non lo sia per gli orientali. Pare infatti che in Unicode alcuni ideogrammi del cinese tradizionale non siano presenti, e che quindi alcuni sviluppatori cinesi continuino ad usare la codifica Big-5.
Un’ulteriore ragione per usare Unicode ci viene dalla recente conversione all’Euro. La tabella ISO 8859-1 non conteneva infatti tale simbolo. Il che ha obbligato all’introduzione della ISO 8859-15, in tutto uguale alla 8859-1 tranne che per l’inserimento di questo simbolo. In sostanza, anche se usate 8859-1, dal 2001 avreste dovuto passare alla 8859-15 (anche se è probabile che abbiate usato l’entità o la referenza numerica per il simbolo dell’euro). Come dire: l’unico modo per essere sicuri è proprio quella di riferirsi sempre a Unicode.
Considerate che se usate Unicode, nella codifica UTF-8, nelle vostre pagine web, non avete praticamente più bisogno di preoccuparvi di usare le entità nominali o le referenze numeriche dei caratteri speciali. Li potete digitare da tastiera nel vostro editor (che deve supportare Unicode) e ve li ritrovate correttamente visualizzati sulle pagine web. Tutt’ora mi capita invece di incontrare pagine web anche ben fatte, ma che presentino errori evitabilissimi nei caratteri accentati, nelle virgolette e in altri simboli tipografici. In una parte della filiera di pubblicazione di quei siti, evidentemente, non vi è un adeguato supporto a Unicode.
Font e Unicode
Infine, un punto cruciale per la corretta visualizzazione dei caratteri è usare il font giusto. Font e codifica infatti sono due questioni distinte. La codifica riguarda quale carattere associare ad un certo numero espresso in byte, ma la forma effettiva della lettera visualizzata dipende dal font usato. La maggior parte dei font hanno glifi definiti solo per un limitato numero di caratteri. Bisogna usare font compatibili con Unicode. Siccome non è sufficiente che ve li procuriate voi, ma dovete essere relativamente sicuri che siano disponibili anche sul computer dei vostri utenti, la scelta si riduce, per il mondo occidentale, a quelli comunemente già noti (Times New Roman, Arial, Georgia, Verdana, Trebuchet, Lucida). Unicode ha una pagina di informazioni e risorse sul tema dei font Unicode-compliant.
Raccomandazioni finali
Nel web attuale, in occidente, è opportuno per varie ragioni preparare pagine web che usino la codifica UTF-8. Per far questo dovete:
- Accertarvi che tutta la vostra filiera di pubblicazione (editor testuale, database, linguaggio di scripting, configurazione del content-type del server) sia in grado di salvare, leggere e manipolare correttamente i documenti e i dati con la codifica UTF-8
- Se usate editor testuali per creare anche solo parti di pagina web, accertarsi di salvarli come UTF-8 senza il BOM.
- Usare il meta tag
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
nelle vostre pagine HTML o XHTML 1.0, avendo cura di inserirlo subito dopo l’apertura dello<head>
, comunque prima del tag<title>
. - Fare in modo che il vostro server invii le pagine usando lo header
Content-type: text/html; charset=utf-8
. - Se state usando XHTML, evitare di usare le entità carattere che si usano in HTML per i caratteri speciali, ad esempio le accentate (
é
,è
, ecc;) con l’unica eccezione di&
,<
,>
e&quo;
. - Potete invece usare le referenze numeriche (decimali o esadecimali) ai caratteri Unicode; ma in generale, per tutti i nuovi browser e i sistemi operativi più recenti, dovrebbe essere sufficiente digitare semplicemente da tastiera il carattere speciale che vi serve, senza alcuna referenza numerica.
Se tutti questi passaggi sono stati rispettati i vostri caratteri speciali dovrebbero essere correttamente visualizzati in tutti i browser del mondo, ora e per i millenni futuri. Be’, su questo non giuriamo, ma confidiamo che se fra qualche millennio ci saranno dei problemi, nessuno verrà da noi a lamentarsi.