Tutorial: occhio al charset!

Le diverse codifiche di caratteri causano grattacapi dall’alba dei tempi, ma ne sanno qualcosa soprattutto gli sviluppatori WEB, quando trovano strani simboli al posto delle lettere accentate!

Iniziamo dal principio. Perché i caratteri (numeri, lettere e simboli) che utilizziamo tutti i giorni sui nostri computer possano essere memorizzati e trasmessi devono essere codificati in modo numerico. L’associazione fra ciascun carattere e il numero che lo identifica si chiama charset o codifica dei caratteri. Per esempio, alla lettere A può corrispondere il numero 65, alla B il numero 66 e così via.

Fin qui niente di complicato, no?
No! Perché purtroppo di codifica non ce n’è una sola. Troverete tanti approfondimenti online, se siete curiosi. La pagina su Wikipedia offre una buona panoramica.
Non esiste uno standard? – chiederete voi. La risposta è sì, ed il problema è proprio l’opposto: ci sono tanti standard che possono essere utilizzati e la maggior parte dei software che vi servono (Server Web, DBMS, editor di testo) ne supportano più di uno, ma quando questi software non sono d’accordo fra loro, succedono disastri, come le lettere accentate che spariscono e questo è il meno perché in altri contesti potremmo andare incontro a perdita d’informazione o malfunzionamenti nei programmi! Del resto immaginate di dover decifrare un messaggio con una tabella dei codici sbagliata, non è possibile!
Non ci addentriamo in troppi dettagli. Vi basti sapere che per i siti Web utilizziamo più comunemente due codifiche standard: ISO-8859-1 e UTF-8. Il primo è un set di caratteri che comprende i simboli utilizzati in Europa Occidentale ed il secondo è una codifica Unicode, un sistema che mira a includere più caratteri possibile fra quelli utilizzati nel mondo.

Vediamo ora come mettere d’accordo i nostri programmi in modo da avere risultati puliti, senza fare casino con i caratteri speciali!
La codifica standard per HTML è l’ISO-8859-1, mentre per XML è UTF-8. Come se non bastasse l’ISO-8859-1 non comprende simboli come €, Š, š, Ž, ž, che sono stati aggiunti con la codifica ISO-8859-15, spesso preferita alla precedente per questa ragione.
Ora, dato che UTF-8 presenta indubbi vantaggi, primo assoluto il fatto di consentire l’utilizzo di tutti i caratteri che possono servirci – o potrebbero in futuro – mediante la stessa codifica, questo tutorial si baserà su questo standard. Fra l’altro, sta lentamente soppiantando le altre codifiche, quindi lo considero un passo verso uno standard definitivo. Questa guida in effetti è stata ispirata dal recente cambiamento introdotto in PHP 5.4 nelle funzioni htmlspecialchars ed htmlentities, che fino alla precedente versione assumevano di default la codifica ISO-8859-1 ed ora UTF-8. Il cambiamento non è roba da poco, dato che queste funzioni sono largamente utilizzate e io stesso ho avuto un bel da fare per aggiornare del codice preesistente.

Immaginiamo di creare un sito in PHP con database MySQL. Forse altri linguaggi, altri tool ed altre situazioni possono rendere superflua questa guida, ma i principi sono sempre utili.

Database
Per prima cosa creeremo il database. Se usiamo phpmyadmin possiamo scegliere la “collation” per il database da un menu a tendina. A questo proposito, la collation complica ulteriormente il discorso sugli standard. Come apprendiamo dal manuale di MySQL, una collation è un set di regole per la comparazione di caratteri all’interno di un set. Il discorso non è banale e la scelta della collation va fatta in base alle sue qualità rispetto a quelle che ci servono. Ogni utente è invitato a leggere la documentazione del DBMS che intende usare. Nel frattempo, possiamo usare utf8_unicode_ci che per un uso generale va più che bene. Ovviamente quando scegliamo la collation abbiamo automaticamente scelto il set di caratteri a cui si riferisce. Se volessimo usare ISO-8859-15 potremmo scegliere latin1_swedish_ci.
La query per la creazione del database sarà

CREATE DATABASE nome_db DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;

Da questo momento le tabelle create all’interno di questo DB ed i loro campi useranno di default il charset impostato. In ogni caso è possibile specificare charset e collation per ogni tabella e per ogni suo campo di testo, vi rimando al manuale di MySQL per affrofondimenti.

Formato dei file
Ora è il momento di pensare alla pagina Web che userà il nostro database. Per iniziare, è molto importante che la codifica del file che creiamo sia coerente con quella che vogliamo dare al nostro sito, altrimenti sulla pagina non avremmo i risultati sperati. Tutti gli editor seri consentono di scegliere la codifica col quale salvare il file. Se intendete creare le vostre pagine senza usare un IDE in particolare ma solo un editor di testo, vi consiglio Notepad++ per Windows, mentre su Linux dovrebbe andar bene anche quello della vostra distribuzione. Sia gedit che kwrite o kate hanno questa possibilità. Su alcuni si sceglie la codifica quando si salva, su altri da subito. In quest’ultimo caso fatelo prima di iniziare se non volete che i caratteri speciali siano distorti. Scegliete UTF-8 e se il programma consente anche questa scelta, impostatelo perché non inserisca il BOM nel file. Si tratta di un codice che indica il formato del file, ma non è indicato sui siti Web perché potrebbe comparire sul browser come carattere sconosciuto e dare problemi con PHP.

Indicazione del charset nella pagina
Come accennato prima, ogni linguaggio ed ogni protocollo hanno dei charset di default, ma anche se si è sicuri di usare quelli, è buona abitudine specificarli per migliore chiarezza, e per evitare di incappare in impostazioni diverse.. insomma, per garantire l’interoperabilità! Per quanto riguarda la nostra pagina, non potrebbe essere più semplice. Inseriamo all’interno del tag head il seguente tag:

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

Questo tag aggiunge informazioni invisibili all’utente ma molto utili al browser per la corretta interpretazione della pagina. Innanzitutto specifica che il file è un documento di testo che contiene direttive in linguaggio html e poi ovviamente aggiunge che la codifica è UTF-8.

Charset della connessione al database
L’ultimo sforzo è quello di far sì che il charset usato dal DBMS per comunicare con la nostra applicazione sia lo stesso che intendiamo usare noi al suo interno. Anche in questo caso c’è un default ma dipende dalla nostra particolare configurazione ed è bene specificare il charset esplicitamente in modo che la nostra pagina giri su qualsiasi server, senza vincoli di impostazioni.
Il modo in cui eseguiamo questo passaggio dipende dalle librerie che utilizziamo.
Se usiamo la classica estensione mysql di PHP, subito dopo la chiamata a mysql_connect, possiamo inserire l’istruzione

mysql_set_charset('utf8');
oppure
mysql_query('SET NAMES "utf8"');
Per entrambe è possibile specificare l’ID della connessione, se serve, come secondo parametro.

Attenzione!
Il charset scelto potrebbe usare più di un byte per codificare il singolo carattere. UTF-8 per esempio codifica i caratteri in modo variabile, da 1 a 4 byte. Questo si riflette soprattutto nella manipolazione di stringhe. Se per esempio chiamate la funzione strlen(‘È’) nel vostro file codificato in UTF-8 noterete che il risultato è 2 e non 1 come potevate aspettarvi! Fortunatamente in PHP abbiamo a disposizione l’estensione mbstring (MultiByte String) che consente di eseguire le normali operazioni sulle stringhe in qualsiasi codifica. Inseriamo in testa alla nostra pagina

<?php
header("Content-type: text/html; charset=UTF-8");
mb_internal_encoding('UTF-8');
?php>
Ora se chiamiamo la funzione mb_strlen(‘È’) avremo 1 come ci aspettiamo!

Migrare un sito preesistente?
Ci sono tanti sostenitori del passaggio a UTF-8 “perché sarebbe meglio”. Secondo me non esiste una ragione a priori. Qualche anno fa trovavamo ISO-8859-15 di default un po’ ovunque, mentre oggi lo standard de facto sta diventando UTF-8. Potremmo decidere di adeguare il nostro sito oppure no, se ci conviene, ma un normale sito in italiano o al più italiano/inglese non ne ha molto bisogno. Comunque, l’operazione non è banale e dobbiamo fare attenzione che ciò che facciamo non comporti di rovinare il lavoro già fatto. Meglio fare una copia del sito e dell’eventuale database prima di iniziare. Per prima cosa dovremmo convertire i file delle nostre pagine. Notepad++ ha un’opzione apposta per convertire un file di testo in UTF-8 e possiamo ottenere lo stesso anche con KWrite. Occorrerà fare qualche prova per assicurarsi che tutto si conservi correttamente. Dopodiché dovremmo aggiornare i meta tag nelle nostre pagine. La parte più delicata è il database, dato che probabilmente avremo tanti dati al suo interno. Vi consiglio di leggere questo articolo. Io ho semplicemente cambiato collation al database ed ai suoi campi ed i testi sono stati preservati senza problemi. Ovviamente non potremo mai migrare un testo in UTF-8 con caratteri giapponesi in ISO-8859-15 perché quest’ultimo non ha i simboli che ci servono, questo dovrebbe essere ovvio! Servirà anche una revisione del codice per assicurarci di usare correttamente le funzioni di manipolazione delle stringhe, quindi a questo punto forse vale il buon vecchio principio di non toccare ciò che funziona. Se non fosse per quel cambiamento introdotto da PHP non mi sarebbe mai venuto nemmeno in mente di mettervi in testa un’idea simile!

È tutto
Spero che questo tutorial serva a rendere le idee più chiare su quest’aspetto che sembra più complicato in apparenza di quanto non sia. L’importante è tenere a mente tutte le regole di coerenza spiegate e controllare la documentazione riguardo alle funzioni che usiamo per manipolare le stringhe per assicurarci che non si aspettino un charset differente. Ricordate anche di chiedervi come avviene un’eventuale comunicazione fra il vostro codice ed altre applicazioni: potreste trovarvi a dover applicare le stesse regole anche in quei casi!

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *