# UTF-8

# Foire Aux Questions des Tuteurs : Unicode, UTF-8

Cette Foire Aux Questions (FAQ) rassemble entre autres des questions fréquemment posées dans le courrier électronique adressé aux tuteurs concernant Unicode, qui est un standard qui se répand de plus en plus, notamment dans les distributions Linux grand public (et aussi sous Windows).

## Généralités et théorie

### Qu'est-ce que le Standard Unicode ?

Le Standard Unicode est produit par une organisation à but non lucratif (le Consortium Unicode) ayant pour objectif d'attribuer un numéro à tout caractère utilisé dans une langue humaine. Cette entreprise vise à une certaine universalité. Les alphabets de beaucoup de langues sont déjà inscrits dans ce standard. On y trouve évidemment les alphabets latins, grecs et cyrilliques (avec certaines de leurs variantes, par exemple, un caractère comme « œ » y figure, bien qu'il ne soit pas utilisé dans la plupart des autres langues européennes utilisant l'alphabet latin). Beaucoup de langues parlées en Asie figurent aussi dans le standard : des dizaines de miliers de caractères chinois, japonais ou coréens sont définis. Le standard contient bien d'autres alphabets, la consultation des tableaux de caractères (dans la version imprimée du standard ou sur le site officiel) est une véritable source d'émerveillement...

### Qu'est-ce qu'un caractère Unicode ?

Un caractère Unicode est un caractère défini dans le Standard Unicode. On y fait souvent référence par son numéro écrit en hexadécimal précédé de «U+». Par exemple, la lettre latine « a » correspond à U+0061, la lettre cyrillique « Я » correspond à U+042F et le "DEVANAGARI OM" « ॐ » correspond à U+0950. Certains de ces caractères ne s'affichent peut-être pas correctement sur votre écran, cela dépend de plusieurs paramètres, nous reviendrons sur ce point dans les questions suivantes ; il faut cependant garder une chose à l'esprit, le Standard Unicode définit des listes de caractères, donne un nom à chaque caractère (pour « a », c'est "LATIN SMALL LETTER A"), mais en aucun cas, le glyphe devant représenter chaque caractère n'est normalisé, en effet, plusieurs fontes de caractères peuvent être utilisées.

### Qu'est-ce que « UTF-8 » ?

"UTF" est formé des initiales de "Unicode Transformation Format". Les ordinateurs stoquent et échangent leurs données le plus souvent sous forme de suite d'octets, un octet étant constitué 8 bits. Un octet peut donc se être représenté comme un nombre entier compris (au sens large) entre 0 et 255. Si on veut stoquer sur un support informatique un texte constitué de caractères Unicode, il faut choisir un procédé transformant une suite de caractères Unicode en une suite d'octets et réciproquement avoir un procédé pour retrouver la suite de caractères à partir d'une suite d'octets bien formée, ces données constituent ce que l'on appelle un encodage.

L'encodage le plus pratique pour échanger des textes constitués de caractères Unicode est UTF-8. Il associe à tout numéro Unicode une suite d'un ou plusieurs octets (jusqu'à quatre octets pour un seul caractère). Cet encodage est décrit dans la RFC 2279. Une des propriétés importantes de cet encodage est que les caractères dont les numéros sont compris entre 32 et 126 possèdent la même représentation en UTF-8 et dans l'encodage ASCII. L'encodage UTF-8 est donc compatible avec ASCII, dans la mesure où il n'y a rien à faire pour convertir un fichier encodé en ASCII vers UTF-8. Réciproquement, si un octet représentant un nombre compris entre 32 et 126 apparaît dans un fichier encodé en UTF-8, alors c'est forcément pour encoder le caractère ASCII du même numéro.

### Quels types de logiciels gèrent Unicode ?

La question de savoir si un logiciel gère bien Unicode n'a de sens que si celui-ci manipule du texte. Les logiciels les plus concernés sont notamment les éditeurs de texte, les logiciels de traitement de texte, les logiciels de courrier électronique et les navigateurs Web.

## Terminaux Unicode

### Qu'est-ce qu'un terminal Unicode ?

Un terminal (ou un émulateur de terminal) consiste en une interface qui permet de saisir et d'afficher du texte, divers programmes peuvent « tourner » à l'intérieur de ce terminal : un interpréteur de commandes (shell), un logiciel pour gérer ses mails, un éditeur de texte, etc... Le terminal et les programmes qui tournent à l'intérieur d'icelui doivent se mettrent d'accord d'une manière ou d'une autre pour savoir dans quel encodage le texte doit communiquer entre eux, et ce de façon cohérente avec les caractères effectivement affichés à l'écran et le texte saisi par l'utilisatuer.

Un terminal Unicode (ou UTF-8) est un terminal où cet encodage est UTF-8, par opposition aux terminaux « ordinaires » où l'encodage est mono-octet (c'est-à-dire ne permet de représenter qu'un peu moins de 256 caractères différents), le plus souvent `latin-1` en France.

Dans un terminal Unicode, on peut ainsi afficher beaucoup plus de caractères différents que dans un terminal `latin-1`. Cela reste néanmoins une interface en mode texte, on ne pourra ainsi pas afficher correctement du texte dans des langues dont l'écriture utilise des systèmes de ligatures complexes ; pour le reste, cela fonctionne très bien. Il y a quelques subtilités, les caractères chinois/japonais/coréens occupent ainsi deux cases contiguës au lieu d'une seule.

### Comment lancer un terminal Unicode ?

Il existe beaucoup d'émulateurs de terminaux sous Unix, certains savent gérer Unicode, d'autres non. Le programme de référence `xterm` sait faire, pour le lancer de façon à obtenir un terminal Unicode, le plus commode est d'utiliser la commande `uxterm` qui est en général un script qui lance `xterm` avec les bonnes options.

Sous Windows, notons que le programme PuTTY qui est à la fois un client SSH et un émulateur de terminal sait gérer Unicode, il suffit de choisir UTF-8 comme encodage.

Dans les configs conscrits récentes, à partir du Menu, on peut cliquer sur « Fenêtres » puis sur « Terminal Unicode ».

### Comment savoir si je suis dans un terminal Unicode ?

La manière la plus rapide est probablement de taper la suite de touches «xxd`<Enter><Compose><apostrophe>`e`<Enter><Control-D>`». Autrement dit, on lance le programme `xxd` qui va servir à afficher la représentation en hexadécimal du texte que l'on va saisir : on saisit un e accent aigu avec la touche compose, on valide et on ferme avec `<Control-D>`. Si on se trouve dans un terminal `latin-1`, on va voir :

    clipper ~ $ xxd
    é
    0000000: e90a                                     ..

tandis que dans un terminal Unicode, on verra :

    clipper ~ $ xxd
    é
    0000000: c3a9 0a                                  ...

Le `0a` que l'on voit dans les deux résultats représente le caractère `U+00A0` LINE FEED (LF) qui s'encode de la même manière en `latin-1` et en UTF-8. La différence porte donc sur l'encodage du caractère `U+00E9` LATIN SMALL LETTER E WITH ACUTE (le e accent aigu), en `latin-1`, on le représente par un seul octet de valeur hexadécimale `e9` tandis qu'en UTF-8, on a deux octets : `c3` puis `a9`.

Une autre manière de le déterminer consiste à utiliser la sortie du terminal plutôt que son entrée. On va envoyer sur la sortie la représentation en UTF-8 du e accent aigu, si on voit effectivement un e accent aigu, on sera dans un terminal UTF-8, si on voit deux caractères qui n'ont rien à voir (en l'occurence «Ã©»), cela voudra probablement dire que l'on est dans un terminal `latin-1`. Pour faire ce test, on peut utiliser la commande suivante :

    clipper ~ $ printf '\xc3\xa9\n'

### Comment faire fonctionner des programmes dans un terminal Unicode ?

La seule méthode vaguement standardisée pour spécifier aux programmes dans quel encodage est encodé le terminal dans lequel ils fonctionnent est donné par les locales. Pour connaître le réglage des locales que les programmes vont subir, on peut utiliser la commande `locale` (qui existe au moins sous GNU/Linux et sous Solaris). Dans un terminal Unicode, j'obtiens ceci :

    clipper ~ $ locale
    LANG=
    LC_CTYPE=fr_FR.UTF-8
    LC_NUMERIC="C"
    LC_TIME="C"
    LC_COLLATE="C"
    LC_MONETARY="C"
    LC_MESSAGES="C"
    LC_ALL=

Ce qui est important ici, c'est ce qui figure en face de `LC_CTYPE`. La valeur `fr_FR.UTF-8` signifie en gros que j'utilise du français de France (et non du français de Suisse par exemple) encodé en UTF-8. Si `LC_CTYPE` contenait une valeur n'indiquant pas un encodage UTF-8, comme `C`, `en_US` ou encore `fr_FR`, je pourrais changer cette locale en tapant la commande suivante qui permet de modifier la variable d'environnement `LC_CTYPE` :

    clipper ~ $ LC_CTYPE=fr_FR.UTF-8;export LC_CTYPE

La modification s'appliquera pour les applications lancées par la suite dans ce terminal. La variable d'environnement `LC_MESSAGES` peut également être utile, elle indique aux programmes qui en sont conscients dans quelle langue on souhaite qu'ils nous parlent. Par exemple, si on est dans un terminal Unicode et que l'on a défini les variables d'environnement `LC_CTYPE` et `LC_MESSAGES` à `fr_FR.UTF-8`, les messages qu'affichera un logiciel de courrier électronique comme `mutt` seront en français.

### Quand je me logue par `ssh`, les caractères accentués s'affichent n'importe comment ‽

De plus en plus de distributions Linux ont par défaut des terminaux Unicode. Si on se logue sur une autre machine Unix, il faut y faire un réglage de locales pour pouvoir utiliser convenablement certains programmes. Il n'y a rien de prévu au niveau de `ssh` (tant mieux, ça pourrait être pire que rien...) pour définir sur la machine distante une locale cohérente avec l'encodage du terminal dans lequel on travaille. Si ce n'est pas fait, les programmes auront tendance à fonctionner comme dans un terminal `latin-1`, d'où le n'importe quoi. En principe, on doit donc faire manuellement le réglage de locales évoqué ci-dessus.

Dans les configs conscrits récentes (à partir de 2004), un script d'initialisation tente à chaque login distant de procéder à une détection de l'encodage du terminal, si ce programme détecte un terminal Unicode, il définit la variable d'environnement `LC_CTYPE` à `fr_FR.UTF-8` ce qui évite d'avoir à faire à chaque fois le réglage de locales manuellement. Pour éviter toute ambiguité, cette détection d'encodage ne concerne que les connexions vers un ordinateur de l'École.

### Comment lancer des programmes ne gérant pas Unicode dans un terminal Unicode ?

Certains logiciels ne gèrent pas bien du tout Unicode, il faut donc les lancer dans un terminal encodé en `latin-1`. Mais si on est en train de travailler dans un terminal Unicode, on a pas forcément envie d'ouvrir une nouvelle fenêtre de terminal. Le programme `luit` permet d'émuler un terminal `latin-1` à l'intérieur d'un terminal Unicode. Si on est dans un terminal Unicode, on peut ainsi utiliser la commande suivante :

    corvette ~ $ LC_CTYPE=fr_FR luit

Cela ouvre un nouveau shell. Les programmes lancés « à l'intérieur d'icelui » se comporteront vis-à-vis de l'utilisateur comme si celui-ci travaillait dans un terminal encodé en `latin-1` (on peut faire le test pour s'en assurer). On peut lancer par exemple `pine` (qui ne gère pas Unicode) dans ce `luit`. Une fois que l'on en a fini avec ces programmes ne gérant pas Unicode, on peut revenir au terminal Unicode de départ en quittant le shell (`exit` ou `<Control-D>`).

### Comment lire son courrier dans un terminal Unicode ?

Le logiciel de courrier électronique `mutt` fonctionne bien dans un terminal Unicode. Grâce à lui, on peut lire ou envoyer des messages dans des langues exotiques ; Mozilla Mail sait aussi faire, mais c'est en mode graphique.

Le logiciel `pine` ne gère pas Unicode. Il ne peut pas bien fonctionner dans un terminal Unicode. Si on travaille dans un terminal Unicode, mais que l'on souhaite quand même lancer `pine`, il faut absolument transformer provisoirement son terminal en terminal `latin-1` avec `luit`.

Les gourous ont fait en sorte que si on lance la commande `pine` dans un terminal Unicode, le programme `luit` soit utilisé pour émuler un terminal `latin-1`, ce qui fait que l'on peut quand même utiliser normalement `pine` ; cependant, on ne pourra pas y voir ou saisir de caractères exotiques.

## Éditer des fichiers UTF-8

### Quel éditeur utiliser ?

Les dernières versions de Vim et Emacs gèrent bien Unicode, on peut les utiliser pour éditer des fichiers encodés en UTF-8 (ou dans d'autres encodages). La page taper de l'Unicode donne quelques informations sur l'utilisation de ces éditeurs. On peut aussi utiliser yudit qui est un très mauvais éditeur, mais qui est cependant extrêmement bon pour ce qui est du rendu du texte dans beaucoup de langues (on peut lui spécifier une fonte pour chaque alphabet, il gère très bien l'écriture de droite à gauche, les systèmes complexes de ligatures, et il propose un large choix de méthodes d'entrées). En revanche, `pico` (et `nano`) ne gèrent pas Unicode.

La version 21.3 d'Emacs installée actuellement a quelques problèmes dans sa gestion d'Unicode. Il vaut mieux utiliser une version encore plus récente, accessible avec la commande `emacs-22dev`.

### Mon éditeur n'a pas détecté que mon fichier était en UTF-8, comment le lui dire ?

On détecte souvent qu'un programme n'est pas conscient qu'un fichier est encodé en UTF-8 quand chaque caractère accentué est remplacés par deux caractères bizarres (exemple : « CaractÃ©ristique d'Euler-PoincarÃ© »). Il faut alors dire à l'éditeur de reconsidérer le fichier pour le traiter comme de l'UTF-8. Dans Vim, on peut taper `:edit ++enc=utf-8` en mode commande. Dans Emacs, aller dans le menu Options, choisir Mule, puis Set Coding System For Reverting This File Now (`C-x RET r`), taper `utf-8` et valider.

### Je veux enregistrer mon fichier dans un autre encodage. Comment faire ?

Dans Vim, la variable spécifiant l'encodage du fichier que l'on édite est `fileencoding`, on peut ainsi faire `:set fileencoding=latin-1` ou `set fileencoding=utf-8` si on veut changer d'encodage ; cela prendra effet au prochain `:w`. Dans Emacs, aller dans le menu Options, choisir Mule, puis Set Coding System For Saving This Buffer (`C-x RET f`), entrer le nom de l'encodage et valider.

### Comment mettre en page du texte dans des langues exotiques avec LaTeX ?

Avec LaTeX, on peut mettre en page du texte écrit dans des langues exotiques. Sur notre page LaTeX sur les langues exotiques, on trouve la marche à suivre pour obtenir ce résultat à partir d'un fichier TeX encodé en UTF-8 (au moins pour du grec, du cyrillique, du chinois et du japonais).

Des variantes de TeX/LaTeX ont été développées récemment : Omega/Lambda puis Aleph/Lamed. Elles gèrent non plus des suites d'octets (256 valeurs possibles) mais des suites de deux octets (65536 valeurs possibles). On peut ainsi imaginer une grosse fonte virtuelle contenant les glyphes de toutes les langues que l'on va utiliser dans un texte ; les numéros de ces glyphes coïncideraient avec les numéros Unicode des caractères. Aleph et Lamed permettent d'appliquer des filtres au fichier source, on peut ainsi concevoir un filtre qui prend en entrée un fichier texte encodé en UTF-8 et le convertit en une suite de numéros Unicode. Avec une fonte virtuelle du type évoqué précédemment, il n'y aurait plus de grosse difficulté à mettre en page du texte dans des langues exotiques. Cependant, on en est encore qu'aux balbutiements, mais cette petite cuisine a quand même pu être utilisée pour réaliser l'Annuaire des élèves qui contient quelques citations dans des langues n'utilisant pas l'alphabet latin.

## Programmes graphiques

### Quels programmes graphiques gèrent Unicode ?

En mode graphique, beaucoup de programmes sont concernés par Unicode, de façon plus ou moins importante. Les émulateurs de terminaux comme `xterm` le sont évidemment. Plus généralement, beaucoup de programmes doivent afficher du texte dans des langues exotiques, par exemple s'ils ont été conçus pour pouvoir avoir des messages et des menus dans d'autres langues que l'anglais (voir le réglage de la locale `LC_MESSAGES`). Les programmes utilisant les bibliothèques `GTK+` disposent naturellement d'un très bon support d'Unicode ; en effet, les chaînes de caractères manipulées sont encodées en UTF-8 et la bibliothèque Pango (faisant partie de `GTK+`) se charge d'afficher convenablement le texte, ce qui n'est pas trivial du tout (par exemple pour les langues indiennes) même si on a de bonnes fontes de caractères.

### Quelles fontes utiliser pour afficher des caractères Unicode ?

On peut trouver des fontes TrueType libres (packagées par la plupart des distributions Linux), elles couvrent notamment la plupart des langues utilisées en Europe (alphabets latin, cyrillique et grec). Pour utiliser la fonte `FreeMono` dans `xterm`, en supposant que les fontes évoquées ici soient convenablement installées, on peut utiliser la commande `uxterm -fa FreeMono` (pourvu que la version de `xterm` utilisée soit suffisamment récente). Si on veut afficher des caractères provenant d'alphabets non couverts par ces fontes, il faut évidemment utiliser d'autres fontes... On peut regretter que `xterm` ne soit actuellement pas capable d'utiliser plusieurs fontes simultanément (on pourrait lui spécifier une fonte à utiliser pour les alphabets latin, cyrillique et grec et une autre fonte pour les idéogrammes chinois par exemple) ; en revanche, l'émulateur de terminal `rxvt-unicode` peut le faire.

## Unicode et Internet

### Comment insérer un caractère Unicode dans une page Web ?

Il y a deux méthodes. La première consiste à utiliser des entités HTML : si on insère la chaîne de caractères «`&#x203d;`» dans un fichier HTML, le navigateur affiche «‽» comme vous pouvez le constater, si le navigateur est en mesure d'afficher ce caractère Unicode, on devrait ainsi voir le caractère U+203D INTERROBANG. Pour un caractère Unicode quelconque, il suffit de remplacer `203d` par la représentation en hexadécimal du numéro du caractère Unicode. On peut aussi utiliser le numéro sous sa forme décimale : `&#8253;` (‽).

La deuxième méthode consiste à encoder tout le fichier HTML en UTF-8. On saisit alors le caractère Unicode comme n'importe quel autre caractère (ce qui nécessite d'avoir un éditeur UTF-8). Cela suppose d'avoir convenablement déclaré l'encodage du fichier HTML. Cela peut se faire en insérant la balise suivante

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

dans les en-têtes du fichier HTML (entre `<meta>` et `</meta>`). Si le fichier est en XHTML, il faut fermer la balise `<meta>` :

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

et il est recommandable de définir l'encodage du fichier en faisant de plus une déclaration XML sur la première ligne du fichier :

    <?xml version="1.0" encoding="UTF-8"?>

S'il ne s'agit d'insérer qu'une poignée de caractères exotiques, il est sans doute plus pratique d'utiliser des entités HTML pour insérer ces caractères. S'il y en a beaucoup, il devient commode d'utiliser la deuxième méthode pour éditer directement le fichier HTML dans un éditeur gérant l'encodage UTF-8. Notons que les deux méthodes ne sont pas incompatibles, on peut mettre des entités HTML du type ci-dessus dans un fichier HTML, quelque soit son encodage, y compris UTF-8.

### Mon navigateur Web affiche mal mes caractères Unicode. Que faire ?

Certains navigateurs (comme Mozilla) permettent de spécifier une fonte à utiliser pour tel ou tel groupe de langues. Quand on insère du texte dans une langue exotique, on a ainsi intérêt à déclarer la langue dans laquelle est écrit le texte, cela permet au navigateur de choisir directement la bonne fonte à utiliser pour afficher les caractères, au lieu de parcourir toutes les fontes existantes jusqu'à en trouver une qui associe un glyphe au numéro Unicode voulu. Ceci peut donner des résultats horribles : imaginons que vous ayez un texte en grec ancien avec beaucoup d'accents et d'esprits et que la fonte par défaut ne contienne que les caractères grecs de base (sans les accents), on risque de se retrouver avec un mélange du plus mauvais effet entre deux fontes de caractères, la fonte de base utilisée pour les caractères non accentués et une autre pour les caractères plus compliqués ; si le navigateur est prévenu dès le départ que c'est du grec ancien, il fera sans doute mieux.

Pour insérer le mot Hindi बिरयानी dont une transcription est « biryânî », on a utilisé le code suivant :

    <cite lang="hi" xml:lang="hi">&#x92c;&#x93f;&#x930;&#x92f;&#x93e;&#x928;&#x940;</cite>

Les attributs `lang` et `xml:lang` s'appliquent à beaucoup d'autres éléments (X)HTML, `<p>` et `<a>` notamment. Sauf cas particuliers, le code de la langue (dans l'exemple, c'est `hi`) doit être un code à deux lettres figurant dans le standard ISO 639.

### Comment déterminer dans quelle mesure mon navigateur gère Unicode ?

On peut utiliser la page de test Unicode sur le site de David A. Madore. Attention, cependant, ce n'est pas parce que vous voyez plein de caractères exotiques disposés un peu partout que votre navigateur gère parfaitement les langues étrangères censément représentées sur la page, si on regarde plus attentivement certains détails, il arrive souvent que l'on voie des bugs (problèmes dans les fontes de caractères, support rudimentaire de certaines langues, mélange disgracieux entre plusieurs fontes de caractères pour afficher le grec, absence de certaines ligatures, etc...).

## Divers

### Je voudrais mettre des accents dans mes noms de fichiers, et ça me marche pas. Que faire ?

C'est une très mauvaise idée de vouloir mettre des caractères accentués (ou exotiques) dans les noms de fichiers. Le fait de mettre des espaces pose déjà des problèmes, des caractères comme «/», «\» ou «:» sont prohibés sur certains systèmes de fichiers, alors vouloir mettre des accents, ce n'est que chercher des ennuis supplémentaires (notamment quand on veut transférer des fichiers sur un autre ordinateur ou sur une disquette). Bref, à éviter absolument.

Auteur : Joël Riou. Dernière modification le .