ssh
, les caractères
accentués s'affichent n'importe comment ‽
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).
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...
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.
"UTF" est formé des initiales de "Unicode Transformation Format". Les ordinateurs stockent et échangent leurs données le plus souvent sous forme de suite d'octets, un octet étant constitué 8 bits. Un octet peut donc être représenté comme un nombre entier compris (au sens large) entre 0 et 255. Si on veut stocker 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.
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.
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 mettre d'accord d'une manière ou d'une autre pour savoir dans quel encodage le texte est échangé entre eux, et ce de façon cohérente avec les caractères effectivement affichés à l'écran et le texte saisi par l'utilisateur.
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.
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.
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 :
sas ~ $ xxd
é
0000000: e90a ..
tandis que dans un terminal Unicode, on verra :
sas ~ $ 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 :
sas ~ $ printf '\xc3\xa9\n'
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 :
sas ~ $ 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
:
sas ~ $ 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.
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.
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.
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 » 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>
).
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
.
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.
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.
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.
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.
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, aujourd'hui abandonnées, puis XeTeX et LuaTeX. Toutes ces variantes ont pour but de supprimer la limitation de TeX à 256 caractères par police. Aleph gère ainsi des suites de deux octets (65536 valeurs possibles), XeTeX et LuaTeX lisent par défaut les fichiers encodés avec UTF-8. Le succès de XeTeX et LuaTeX est dû notamment à la possibilité d'y utiliser à la fois les polices fournies avec TeX et les polices TrueType ou OpenType plutôt utilisées dans les logiciels de traitement de texte traditionnels. Il devient ainsi possible de taper des textes multilingues, ou dans les langues à idéogrammes sans devoir affronter le casse-tête de la gestion des polices avec LaTeX.
XeTeX permet en outre, grâce à un système appelé TeCKit, d'appliquer des filtres aux fichiers sources. Cela permet d'utiliser une translittération dans le fichier source tout en obtenant les bons caractères dans le fichier d'arrivée.
Grâce à XeTeX, on a pu ainsi réaliser l'Annuaire des élèves qui contient quelques citations dans des langues n'utilisant pas l'alphabet latin.
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.
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.
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
«‽
» 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 : ‽
(‽).
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.
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">बिरयानी</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.
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...).
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.