Unicode 5.0 en pratique
 2100511408, 9782100511402 [PDF]

  • 0 0 0
  • Gefällt Ihnen dieses papier und der download? Sie können Ihre eigene PDF-Datei in wenigen Minuten kostenlos online veröffentlichen! Anmelden
Datei wird geladen, bitte warten...
Zitiervorschau

DÉVELOPPEMENT ÉTUDES

UNICODE 5.0 EN PRATIQUE Algeria-Educ.com Codage des caractères et internationalisation des logiciels et des documents

Patrick Andries Préface de Mark Davis

andries.fm Page I Mardi, 11. mars 2008 12:07 12

andries.fm Page I Mardi, 11. mars 2008 12:07 12

UNICODE 5.0 EN PRATIQUE Codage des caractères et internationalisation des logiciels et des documents

andries.fm Page II Mardi, 11. mars 2008 12:07 12

SOA Le Guide de l’architecte du SI 2e édition Xavier-Fournier Morel, Pascal Grojean, Guillaume Plouin, Cyril Rognon 368 pages Dunod, 2008

WPF Le développement d’interfaces riches Introduction à Silverlight SUPINFO Laboratoire des technologies.NET 208 pages Dunod, 2008

Manager la sécurité du SI Planifier, déployer, contrôler, améliorer Matthieu Bennasar, Alain Champenois, Patrick Arnould, Thierry Rivat 272 pages Dunod, 2007

andries.fm Page III Mardi, 11. mars 2008 12:07 12

UNICODE 5.0 EN PRATIQUE Codage des caractères et internationalisation des logiciels et des documents

Patrick Andries Consultant et membre du Consortium Unicode

Préface de Mark Davis Président et cofondateur du Consortium Unicode

andries.fm Page IV Mardi, 11. mars 2008 12:07 12

Toutes les marques citées dans cet ouvrage sont des marques déposées par leurs propriétaires respectifs.

Illustration de couverture : Le Rocher Percé, Gaspésie, Québec, Canada Source : Elodie.Pauwels©Filopix.com

© Dunod, Paris, 2008 ISBN 978-2-10-053831-7

Préface

Lorsque Patrick m’a demandé de préfacer son livre, j’étais quelque peu tiraillé car je craignais fort de souffrir à cause de mon français un peu rouillé ! Mais je connais Patrick depuis des années et je savais que son travail serait intéressant et bien ficelé. Il a une longue expérience du développement dans le domaine de l’internationalisation, notamment grâce à son rôle de premier plan dans la création de l’un des premiers navigateurs Internet multilingues. En même temps, il a la bosse de la communication, ayant donné plusieurs conférences bien structurées et écrit plusieurs articles fort clairs sur Unicode et l’internationalisation. En plus de ses penchants et de son enthousiasme, il montre aussi un intérêt marqué — et a connu du succès — pour la promotion de langues et d’écritures africaines comme le touareg et le tifinaghe. Ce que j’ai trouvé a dépassé mes attentes. En plus de traiter des questions importantes du standard Unicode lui-même, ce livre est une mine d’informations sur les aspects pratiques de l’utilisation d’Unicode et de l’internationalisation des logiciels en général. Notamment, le livre commence par un résumé utile des principaux concepts et enjeux du standard Unicode et d’autres standards d’internationalisation apparentés, résumé rédigé dans un langage bien plus fluide que les standards euxmêmes qui sont pour le moins arides ! Mais il va beaucoup plus loin. Cet ouvrage dans son ensemble constitue un complément précieux de ces standards : des descriptions solides de l’utilisation d’Unicode dans divers programmes, mais aussi de l’interface entre Unicode et le monde des polices de caractères, des concepts et problèmes relatifs à l’internationalisation des logiciels, et bien plus encore. Et, bien sûr, une attention particulière aux caractères et aux problèmes d’importance pour les francophones. En outre, le texte est si clairement écrit que même mon français peu assuré s’est avéré à la hauteur…

Unicode est une des pierres angulaires du logiciel moderne ; sa compréhension est importante autant pour les programmeurs que pour les utilisateurs. Sans fanfare, Unicode a complètement transformé les fondements du logiciel et des communications au cours de la dernière décennie. Dès que vous lisez ou écrivez quelque chose sur un ordinateur, vous utilisez Unicode. Dès que vous effectuez une recherche avec Google, Yahoo!, MSN, Wikipédia ou bien d’autres sites, vous utilisez Unicode. Nous avons entrepris Unicode avec un but simple : unifier les centaines de manières de coder des caractères qui existaient en les remplaçant par un standard unique et universel. Les codages de caractères préexistants étaient à la fois incomplets et incohérents : à chaque fois que du texte devait passer d’un programme ou d’un système à un autre, il y avait un sérieux risque de corruption. La gestion de codages particuliers était codée en dur dans les programmes, rendant le développement, les tests et la maintenance de ces versions internationales difficiles, coûteux, voire cauchemardesques. En fin de compte les lancements de produit dans les marchés étrangers étaient à la fois onéreux et tardifs, au grand dam autant des éditeurs que de leurs clients. Les pays en développement souffraient particulièrement : le soutien des petits marchés était tout simplement impossible. La situation a changé radicalement avec Unicode. Dorénavant, les programmes n’ont plus qu’à utiliser une seule représentation pour tout le texte, représentation qui gère toutes les langues du monde. Un programme peut facilement être structuré de façon à être rapidement déployé dans plusieurs langues. Ainsi, de multiples versions linguistiques d’un logiciel peuvent maintenant être développées presque simultanément et à coût marginal grandement réduit, même dans le cas de programmes extrêmement complexes comme Microsoft Office ou OpenOffice. Des compagnies comme Google peuvent traiter toutes les langues du monde avec une seule représentation uniforme. Les utilisateurs y gagnent énormément quant à la variété de programmes disponibles et à leur qualité. À mesure qu’Unicode et les logiciels le mettant en œuvre ont pris de l’ampleur, l’ensemble est inévitablement devenu plus complexe. On fait face à une jungle de sigles et de concepts déconcertants : NDI (IDN), HTTP, XML, HTML, CSS, ICU, OpenType, BIDI, PMB (BMP), IOO (BOM), CLDR, FNC (NFC), UCA, UTF, LSC (ZWF), etc. Ce livre trace un sentier dans cette jungle. Je ne connais pas d’autre ressource moderne, ni en anglais ni en français, regroupant une telle gamme de sujets utiles, et les expliquant de façon si claire et si accessible à un large public. J’espère que vous apprécierez cet ouvrage autant que moi.

Mark Davis, Ph. D. Président et cofondateur du Consortium Unicode

Table des matières Avant-propos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . XVII Première partie – Introduction Chapitre 1 – Concepts de base et terminologie . . . . . . . . . . . . . . . . . . . . . . . . .

3

1.1

Pourquoi Unicode ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3

1.2

Absence de codage universel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5

1.3

Langue et écriture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3.1 Notation, écriture, transcription et translittération. . . . . . . . . . . . . . . 1.3.2 Qu’est-ce qu’un caractère ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3.3 Graphème, caractère et glyphe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3.4 Terminologie de l’apparence des caractères. . . . . . . . . . . . . . . . . . . . . 1.3.5 Classification des caractères . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3.6 Caractères romains, latins, italiques et gothiques . . . . . . . . . . . . . . . . 1.3.7 Écriture CJC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6 7 8 9 11 11 12 13

1.4

Unicode, en quelques mots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.4.1 Ce qu’Unicode est... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.4.2 Ce qu’Unicode n’est pas.... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14 14 14

1.5

Apprivoiser les polices Unicode. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.5.1 Afficher des caractères Unicode . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.5.2 S’assurer que sa police est une police Unicode . . . . . . . . . . . . . . . . . . 1.5.3 Où trouver des polices multi-écritures supplémentaires ? . . . . . . . . . . 1.5.4 Absence de glyphe pour un caractère . . . . . . . . . . . . . . . . . . . . . . . . . 1.5.5 Incorporation des polices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16 16 17 18 20 21

1.6

Saisir des caractères Unicode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.6.1 Claviers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

22 25

VIII

Unicode 5.0 en pratique

1.6.2 1.6.3

Méthodes d’entrée extrême-orientales . . . . . . . . . . . . . . . . . . . . . . . . Tableau de caractères . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

28 29

Internationalisation et localisation . . . . . . . . . . . . . . . . . . . . . . . . . . . .

32

Chapitre 2 – Répertoires et jeux de caractères codés. . . . . . . . . . . . . . . . . . . . .

35

1.7

2.1

Terminologie. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.1 Répertoire de caractères . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.2 Jeu de caractères codés, code et codage . . . . . . . . . . . . . . . . . . . . . . .

35 36 36

2.2

L’ASCII. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.1 ISO 646 et « variantes nationales de l’ASCII » . . . . . . . . . . . . . . . . 2.2.2 « ASCII 8 bits » . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

37 39 39

2.3

Les codes ISO/CEI 8859. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3.1 ISO/CEI 8859-1 ou ISO Latin-1. . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3.2 ISO/CEI 8859-15 ou ISO Latin-9. . . . . . . . . . . . . . . . . . . . . . . . . .

40 41 43

2.4

Windows Latin 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

44

2.5

EBCDIC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

46

2.6

KOI8-R . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

47

2.7

ISO/CEI 2022 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

47

2.8

ISO/CEI 10646 et Unicode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

49

2.9

GB 18030, l’« Unicode chinois ». . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

51

Deuxième partie – L’essentiel d’Unicode Chapitre 3 – Structure d’Unicode. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

55

3.1

Principes directeurs. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

55

3.2

Caractères normalisés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2.1 Plan multilingue de base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2.2 Plans complémentaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2.3 Nombre de caractères normalisés . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2.4 Unicode 5.1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

56 57 61 61 62

3.3

Caractères . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3.1 Caractère abstrait et caractère codé . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3.2 Caractères combinatoires et diacritiques . . . . . . . . . . . . . . . . . . . . . . 3.3.3 Suite de caractères de base et diacritiques. . . . . . . . . . . . . . . . . . . . . . 3.3.4 Caractères combinatoires multiples . . . . . . . . . . . . . . . . . . . . . . . . . .

64 64 65 66 66

3.4

Principes de conception d’Unicode . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.4.1 Universalité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

67 68

Table des matières

3.4.2 3.4.3 3.4.4 3.4.5 3.4.6 3.4.7 3.4.8 3.4.9 3.4.10

IX

Efficacité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Caractères et non glyphes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sémantique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Texte brut . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ordre logique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Unification. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Composition dynamique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Stabilité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Convertibilité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

69 70 70 71 71 72 72 74 75

Chapitre 4 – Modèle de codage, propriétés des caractères et tri . . . . . . . . . . . .

77

4.1

Modèle de codage des caractères . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.1 Répertoire de caractères abstraits. . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.2 Jeu de caractères codés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.3 Mot, octet, seizet, codet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.4 Forme en mémoire des caractères . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.5 Mécanisme de sérialisation de caractères . . . . . . . . . . . . . . . . . . . . . .

77 80 80 80 81 84

4.2

Propriétés des caractères . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.1 Voir les propriétés grâce à BabelMap . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.2 Catégorie générale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.3 Casse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.4 Classe combinatoire canonique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.5 Directionalité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.6 Réflexion bidi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.7 Classes de coupure de lignes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.8 Coupure de lignes et segmentation de texte . . . . . . . . . . . . . . . . . . . . 4.2.9 Cohérence des propriétés. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

86 86 88 91 94 95 96 96 99 100

4.3

Formes normalisées. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.1 La concaténation n’est pas fermée . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.2 Formes de normalisation et base de données. . . . . . . . . . . . . . . . . . . . 4.3.3 Stabilité des formes normalisées. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.4 Invariance des caractères latins de base . . . . . . . . . . . . . . . . . . . . . . . 4.3.5 Compositions exclues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

101 103 103 103 104 104

4.4

Le tri et le repérage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.4.1 Tri et comparaison binaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.4.2 Tri et comparaison lexicographiques. . . . . . . . . . . . . . . . . . . . . . . . . . 4.4.3 Ça ne peut quand même pas être si compliqué ?. . . . . . . . . . . . . . . . . 4.4.4 La solution – un tri à quatre niveaux. . . . . . . . . . . . . . . . . . . . . . . . .

105 106 106 106 107

X

Unicode 5.0 en pratique

4.4.5 4.4.6 4.4.7 4.4.8 4.4.9

Les éléments de tri et les clés de tri. . . . . . . . . . . . . . . . . . . . . . . . . . . La table DUCET. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Expansions et contractions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mise en œuvre du tri Unicode. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Personnalisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

109 110 111 112 113

4.5

Conformité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

113

4.6

Le standard Unicode : mode d’emploi . . . . . . . . . . . . . . . . . . . . . . . . . . 4.6.1 Liste des noms de caractère . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.6.2 Images dans les tableaux et dans les listes de caractères . . . . . . . . . . . 4.6.3 Renvois . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.6.4 Renseignements sur les langues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.6.5 Décompositions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

115 115 116 116 117 117

Troisième partie – Caractères remarquables Chapitre 5 – Lettres et signes diacritiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

123

5.1

Latin étendu et API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

123

5.2

Lettres modificatives. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

124

5.3

Clones à chasse des diacritiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

125

5.4

Écriture grecque . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

125

5.5

Signes diacritiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5.1 Diacritiques généraux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5.2 Supplément de diacritiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5.3 Diacritiques destinés aux symboles . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5.4 Demi-signes diacritiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

127 128 129 129 130

Chapitre 6 – Ponctuation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

131

6.1

Ponctuation Latin-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.1 Guillemet anglais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.2 Croisillon . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.3 Perluète . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.4 Apostrophe. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.5 Astérisque et obèle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.6 Trait d’union-signe moins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.7 Arrobe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.8 Clones de diacritique. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.9 Paragraphe et pied-de-mouche. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.10 Symbole degré et ordinal masculin . . . . . . . . . . . . . . . . . . . . . . . . . . .

131 132 132 132 132 133 134 134 134 135 136

Table des matières

XI

6.1.11 Point médian . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.12 Trait d’union conditionnel. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.13 Ponctuation appariée . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

137 138 140

6.2

Guillemets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2.1 Usages européens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2.2 Usage extrême-oriental . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

140 140 142

6.3

Espaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.3.1 Espace mot et espace insécable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.3.2 Les différents caractères d’espacement . . . . . . . . . . . . . . . . . . . . . . . . 6.3.3 Ajustement de l’espacement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.3.4 Espaces fines en français. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.3.5 Espace sans chasse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.3.6 Disposition des espaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

142 143 144 146 146 149 149

6.4

Autres signes typographiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.4.1 Points de suspension et points de conduite . . . . . . . . . . . . . . . . . . . . . 6.4.2 Traits d’union et tirets. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.4.3 Puces, barre de fraction, ponctuation doublée . . . . . . . . . . . . . . . . . . 6.4.4 Ponctuation archaïque . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

151 151 152 154 154

6.5

Caractères de coupure de lignes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

155

Chapitre 7 – Symboles et notations. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

157

7.1

Symboles de type lettre. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

157

7.2

Symboles monétaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

159

7.3

Mathématique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

159

7.4

Musique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

161

Chapitre 8 – Caractères techniques spéciaux . . . . . . . . . . . . . . . . . . . . . . . . . . .

163

8.1

Caractères de commande . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.1.1 Commandes C0 et suppression . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.1.2 Commandes C1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

163 163 164

8.2

Gluon et diacritique invisible bloquant . . . . . . . . . . . . . . . . . . . . . . . . . 8.2.1 Gluon de mots (U+2060) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.2.2 Diacritique invisible bloquant (U+034F) . . . . . . . . . . . . . . . . . . . . .

165 165 165

8.3

Caractères spéciaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.3.1 Délimiteurs d’annotation interlinéaire . . . . . . . . . . . . . . . . . . . . . . . . 8.3.2 Non-caractères. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

166 167 168

8.4

Positions non attribuées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

168

XII

Unicode 5.0 en pratique

8.5

Caractères déconseillés et désuets . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

169

8.6

Zones à usage privé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

169

8.7

Indicateur d’ordre des octets. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

170

8.8

Étiquettes linguistiques. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

171

Quatrième partie – Applications et techniques liées à Unicode Chapitre 9 – Préciser la langue, l’écriture et le pays . . . . . . . . . . . . . . . . . . . . .

177

9.1

ISO 639 – indicatifs de langue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

178

9.2

ISO 3166 – indicatifs de pays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

180

9.3

M.49 – Indicatifs de pays et de régions. . . . . . . . . . . . . . . . . . . . . . . . . .

181

9.4

ISO 15924 – indicatifs d’écriture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

181

9.5

RFC 4646 – Étiquettes de langue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

182

9.7

BCP 47 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

184

Chapitre 10 – Unicode et les protocoles Internet . . . . . . . . . . . . . . . . . . . . . . .

187

10.1 De l’utilité des métadonnées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

187

10.2 Les premiers protocoles Internet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

188

10.3 Type de médias Internet/type MIME . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.3.1 Visualiser les entêtes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.3.2 Les types de média ou types de contenu . . . . . . . . . . . . . . . . . . . . . . . 10.3.3 L’information sur le codage de caractères (« charset »). . . . . . . . . . . . 10.3.4 Les entêtes relatifs au surcodage de transfert . . . . . . . . . . . . . . . . . . . 10.3.5 Le surcodage des entêtes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.3.6 Recettes de dépannage. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

189 189 191 192 193 197 198

10.4 Codage de caractères sur le Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.4.1 Entêtes HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.4.2 Préciser le codage de caractères dans HTTP . . . . . . . . . . . . . . . . . . . 10.4.3 Vérifier les entêtes HTTP. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.4.4 Quel codage utiliser pour mes pages web ? . . . . . . . . . . . . . . . . . . . . . 10.4.5 Balise meta. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.4.6 Préciser le codage dans XHTML et XML . . . . . . . . . . . . . . . . . . . . . 10.4.7 Conflits des définitions de codage. . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.4.8 Configuration de serveurs web . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

200 200 201 202 204 204 205 206 207

10.5 HTTP internationalisé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.5.1 La négociation de langue. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.5.2 Les entêtes reliés aux caractères. . . . . . . . . . . . . . . . . . . . . . . . . . . . .

210 210 219

Table des matières

XIII

10.6 Adresses internationalisées. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.6.1 Noms de domaine et DNS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.6.2 Internationaliser les URI. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.6.3 Noms de domaine internationalisés (NDI) . . . . . . . . . . . . . . . . . . . . 10.6.4 Menaces informatiques : hameçonnage et parodie . . . . . . . . . . . . . . . 10.6.5 Caractères non ASCII dans les chemins des IRI . . . . . . . . . . . . . . . .

220 220 222 224 226 229

10.7 La locale POSIX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

232

Chapitre 11 – Unicode et (X)HTML, XML, CSS. . . . . . . . . . . . . . . . . . . . . . .

239

11.1 Préciser le codage en (X)HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.1.1 HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.1.2 XHTML – le prologue XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.1.3 Préciser le codage en CSS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

239 240 240 244

11.2 Préciser la langue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2.1 HTML et XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2.2 Passages dans une autre langue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2.3 Documents bilingues. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2.4 La langue dans l’entête HTTP ou l’attribut lang ? . . . . . . . . . . . . . .

245 245 245 246 247

11.3 Préciser la directionalité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

248

11.4 Stylage sensible à la langue. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.4.1 Les sélecteurs CSS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.4.2 Utilisation des sélecteurs de langue . . . . . . . . . . . . . . . . . . . . . . . . . .

249 249 250

11.5 Schémas XML internationalisés. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.5.1 Texte dans les attributs XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.5.2 Les éléments qui ne contiennent qu’une chaîne . . . . . . . . . . . . . . . . . 11.5.3 Prévoir l’attribut xml:lang. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.5.4 Prévoir un élément de type span . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.5.5 Ne pas créer d’éléments de présentation. . . . . . . . . . . . . . . . . . . . . . . 11.5.6 Prévoir xml:id sur tous les éléments traduisibles . . . . . . . . . . . . . .

251 251 252 252 252 252 253

11.6 Notation des caractères . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.6.1 Appels d’entités HTML : souvent de peu d’utilité . . . . . . . . . . . . . . . 11.6.2 Appels de caractère : à n’utiliser que rarement. . . . . . . . . . . . . . . . . . 11.6.3 Quand les appels de caractère et d’entité sont utiles . . . . . . . . . . . . . . 11.6.4 Entités en XHTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

253 255 256 256 258

11.7 Caractère ou balisage ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.7.1 Unicode contient trop de caractères . . . . . . . . . . . . . . . . . . . . . . . . . . 11.7.2 Caractères de commande en HTML et XHTML . . . . . . . . . . . . . . .

258 258 259

XIV

Unicode 5.0 en pratique

11.7.3 Autres caractères permis et interdits en XML . . . . . . . . . . . . . . . . . . 11.7.4 Caractères incompatibles avec le balisage. . . . . . . . . . . . . . . . . . . . . . 11.7.5 Caractères de compatibilité Unicode . . . . . . . . . . . . . . . . . . . . . . . . .

260 261 263

11.8 Réglage de l’algorithme bidi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.8.1 Bref rappel de l’algorithme bidi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.8.2 Désactiver l’algorithme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.8.3 Cas problématiques – les neutres mal placés . . . . . . . . . . . . . . . . . . . 11.8.4 Éditer du texte bidi balisé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.8.5 Emboîtement des passages bidi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.8.6 Caractères de commande bidi et balisage . . . . . . . . . . . . . . . . . . . . . . 11.8.7 Les feuilles de styles CSS et le bidi. . . . . . . . . . . . . . . . . . . . . . . . . . .

263 264 268 269 270 271 273 273

11.9 Formulaire « universel » . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.9.1 Créer un formulaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.9.2 Accept-charset sur la balise form . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.9.3 Inclusion de caractères étrangers au charset. . . . . . . . . . . . . . . . . 11.9.4 Solution : n’envoyer et n’accepter que de l’UTF-8 . . . . . . . . . . . . . .

275 275 278 279 279

Chapitre 12 – Internationalisation des logiciels . . . . . . . . . . . . . . . . . . . . . . . . .

283

12.1 Internationaliser ?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.1.1 PNB par langue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.1.2 L’adaptation de logiciels à la pièce . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.1.3 Internationalisation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.1.4 Quelques a priori culturels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.1.5 Localisation ou adaptation culturelle . . . . . . . . . . . . . . . . . . . . . . . . .

283 283 284 284 285 286

12.2 Les langages de programmation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.2.1 Les caractères dans C et C++. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.2.2 Les caractères dans Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.2.3 Les caractères dans C# et la plateforme .NET . . . . . . . . . . . . . . . . . 12.2.4 Bibliothèques d’internationalisation, le cas ICU. . . . . . . . . . . . . . . . . 12.2.5 Propriétés de caractères en Java/ICU . . . . . . . . . . . . . . . . . . . . . . . . 12.2.6 Unicode dans les expressions régulières . . . . . . . . . . . . . . . . . . . . . . . 12.2.7 UnicodeSet en ICU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.2.8 Normalisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.2.9 Comment supprimer les accents d’un texte ? . . . . . . . . . . . . . . . . . . . 12.2.10 Créer des noms de domaine internationalisés . . . . . . . . . . . . . . . . . . . 12.2.11 Les transformations ICU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

287 287 289 291 292 293 295 296 297 298 299 299

12.3 Profil culturel ou locale. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.3.1 Concept et nécessité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

302 302

Table des matières

12.3.2 12.3.3 12.3.4 12.3.5 12.3.6 12.3.7

XV

Définir une Locale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Définir une Locale avec ICU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Locale sur .NET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Locale implicite. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Changer la casse d’une chaîne de caractères. . . . . . . . . . . . . . . . . . . . Correspondance de casse non localisée. . . . . . . . . . . . . . . . . . . . . . . .

303 303 304 305 305 306

12.4 Isoler les données culturelles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.4.1 Pourquoi extraire ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.4.2 Les « ResourceBundle » . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.4.3 Définition de ResourceBundle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.4.4 Accès aux ResourceBundle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.4.5 Découverte et recherche des ResourceBundle . . . . . . . . . . . . . . . . . . . 12.4.6 Où sont stockées les ressources ? . . . . . . . . . . . . . . . . . . . . . . . . . . . .

307 307 307 308 309 309 310

12.5 Formater les messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.5.1 Formats prédéfinis de date et heure . . . . . . . . . . . . . . . . . . . . . . . . . . 12.5.2 Formater la date et l’heure à l’aide de motifs . . . . . . . . . . . . . . . . . . . 12.5.3 Formater et analyser chiffres et montants . . . . . . . . . . . . . . . . . . . . . 12.5.4 Variabilité de l’ordre des mots dans les langues. . . . . . . . . . . . . . . . . . 12.5.5 Messages variables et internationalisés. . . . . . . . . . . . . . . . . . . . . . . . 12.5.6 Gestion de l’accord en nombre . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

312 312 313 316 318 319 322

12.6 Comparaison et tri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.6.1 Tri en Java ou ICU pour Java. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.6.2 Comparer des chaînes en ignorant les accents . . . . . . . . . . . . . . . . . . 12.6.3 Personnaliser le tri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.6.4 Ignorer la ponctuation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.6.5 Tri des tableaux de données à plusieurs champs . . . . . . . . . . . . . . . . . 12.6.6 Améliorer la performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

325 325 327 327 330 331 333

12.7 Frontières de texte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.7.1 La classe BreakIterator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.7.2 Exemples : détecter les frontières de phrase et de mot . . . . . . . . . . . . . 12.7.3 Personnaliser la détection de frontières. . . . . . . . . . . . . . . . . . . . . . . .

334 334 336 338

12.8 CLDR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

339

12.9 Les exceptions et l’i18n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

340

12.10 Conversion de données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.10.1 Entrées/sorties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.10.2 Écrire de l’Unicode avec des OutputStream. . . . . . . . . . . . . . . . . . . .

342 342 344

XVI

Unicode 5.0 en pratique

12.10.3 String.getBytes() et l’analyseur XML . . . . . . . . . . . . . . . . . . . . . . . . 12.10.4 Maîtrise de la conversion grâce à java.nio . . . . . . . . . . . . . . . . . . . . .

345 346

12.11 L’interface utilisateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.11.1 Foisonnement du texte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.11.2 Neutralité culturelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.11.3 Internationalisation des images et des icônes . . . . . . . . . . . . . . . . . . .

347 347 348 349

12.12 À ne pas internationaliser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

350

Chapitre 13 – Unicode et les polices. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

355

13.1 Caractères et variantes de glyphes . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

355

13.2 Sélecteurs de variante. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

356

13.3 Impact sur le choix de police . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.3.1 Police de repli . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.3.2 Police de substitution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.3.3 Police liée . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.3.4 CSS et ses « polices liées » . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.3.5 Utiliser un équivalent canonique . . . . . . . . . . . . . . . . . . . . . . . . . . . .

356 357 357 358 358 359

13.4 Ligatures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.4.1 Liant et antiliant. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.4.2 Liaison cursive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.4.3 Liant, antiliant et les écritures brahmies. . . . . . . . . . . . . . . . . . . . . . . 13.4.4 Filtrage des liants et antiliants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.4.5 Liant et antiliant dans les polices . . . . . . . . . . . . . . . . . . . . . . . . . . . .

359 360 362 363 364 364

13.5 Pas d’expédients ASCII, de l’Unicode !. . . . . . . . . . . . . . . . . . . . . . . . .

365

13.6 Passage des caractères aux glyphes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.6.1 Des caractères et non des glyphes . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.6.2 Fonctionnement d’un moteur de rendu . . . . . . . . . . . . . . . . . . . . . . . 13.6.3 Les polices de glyphes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

366 366 367 371

13.7 Processus de rendu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

378

13.8 Un moteur de rendu : Uniscribe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

380

13.9 Adobe et Uniscribe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

382

13.10 Fonctionnalités et règles OpenType. . . . . . . . . . . . . . . . . . . . . . . . . . . .

382

13.11 Intégrer le tout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

385

Bibliographie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

389

Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

391

Avant-propos

Omniprésence d’Unicode Depuis une bonne dizaine d’années, Unicode a discrètement métamorphosé le domaine des logiciels et des protocoles de communication. Là, où il y a dix ans à peine, existait une pléthore de codages de caractères différents, souvent incompatibles entre eux, Unicode a apporté simplicité et unicité de codage. Tous les grands systèmes d’exploitation utilisent désormais Unicode, les traitements de texte comme Open Office et Office de Microsoft en font de même. Que vous consultiez Wikipedia, lisiez votre courriel sur Google, recherchiez l’internet avec Yahoo!, vous utilisez Unicode. Avant l’avènement d’Unicode, les programmes étaient souvent conçus pour ne prendre en charge qu’un jeu de caractères précis utilisé dans un marché particulier. Viser le marché international supposait le développement d’un grand nombre de versions parallèles. Concevoir, tester et entretenir en parallèle ces versions étaient un véritable cauchemar : il fallait souvent corriger le même problème dans chacune de ces versions. Unicode permet désormais de ne plus développer qu’une seule version de son produit qui permet de prendre en charge plusieurs langues et d’assurer l’échange d’information sur une échelle planétaire.

À qui s’adresse ce livre ? Les lecteurs de ce livre devraient avoir une bonne connaissance du fonctionnement des ordinateurs. Toutefois, il n’est pas nécessaire qu’ils soient programmeurs bien que de nombreux programmeurs puissent tirer parti de ce livre dans la conception de leurs logiciels. Ce livre ne se veut pas une traduction du standard Unicode — disponible gratuitement en ligne autant en anglais que, pour une grande partie, en français —

XVIII

Unicode 5.0 en pratique

mais plutôt une introduction à Unicode pour certains aspects et un complément au standard Unicode pour d’autres. Introduction plus concise, parfois, nous l’espérons, plus facile d’abord que le texte du standard Unicode, elle se destine d’abord au public francophone et se concentre sur les grandes écritures qui sauront l’intéresser : l’écriture latine, la grecque, l’arabe, les symboles mathématiques, physiques et musicaux sans toutefois négliger d’introduire les idéogrammes chinois. Complément aussi, car, si le standard Unicode est principalement destiné aux concepteurs qui voudraient écrire des programmes qui mettent en œuvre des aspects du standard Unicode, par exemple comment afficher correctement l’arabe ou le birman dans un traitement de texte ou un système d’exploitation, le standard Unicode passe sous silence de nombreux aspects pratiques cruciaux pour ceux qui ne veulent qu’utiliser ces logiciels Unicode, comme les navigateurs web ou les bibliothèques Java, et non les concevoir. Ce livre s’adresse à plusieurs publics parmi lesquels :

• Des informaticiens de métier, des analystes, des gestionnaires en informatique désireux de comprendre et de travailler avec Unicode. Qu’il s’agisse de conversion de données patrimoniales, de création de logiciels internationalisés ou de sites web multilingues ou encore tout simplement de travailler dans un environnement qui utilise Unicode, ce qui est de plus en plus le cas avec des technologies modernes comme XML, C# ou Java.

• Des personnes qui travaillent sur des textes multilingues ou des textes spécialisés : base de données multilingue, textes contenant des symboles mathématiques ou d’autres signes spéciaux, (même les textes juridiques contiennent beaucoup de caractères Unicode). Parmi ces utilisateurs typiques, on retrouvera des typographes, des bibliothécaires et des universitaires dans les facultés de lettres qui travaillent sur des textes multilingues.

• Des enseignants en informatique qui désirent mieux comprendre les différents aspects liés à Unicode et à l’internationalisation et pensent introduire leurs étudiants à ces sujets. Il n’existe à peu près aucun bon livre sur les jeux de caractères et l’internationalisation en français, une des conséquences de ce manque est l’absence de ces sujets dans les programmes universitaires alors que ces techniques sont pourtant de plus en plus demandées. Une bonne compréhension des bases d’Unicode et de l’internationalisation devrait faire partie du bagage de tout bon informaticien.

Structure du livre Le livre est divisé en quatre parties : Introduction, L’essentiel d’Unicode, Caractères remarquables et Applications et techniques liées à Unicode.

Avant-propos

XIX

Introduction Le but de cette partie divisée en deux chapitres est de présenter brièvement les concepts de base, d’introduire la terminologie et de décrire les raisons qui ont poussé à la création et au succès d’Unicode : la pléthore des jeux de caractères. Le premier chapitre de cette partie constitue également une prise en main d’Unicode : montrer comment l’utilisation peut être facile, comment afficher des caractères Unicode et les saisir. Cette partie est cruciale pour prendre la mesure d’un sujet tel qu’Unicode et l’internationalisation des documents et des logiciels. Le deuxième chapitre présente les principaux jeux de caractères qui ont précédé Unicode et qui pour certains sont toujours utilisés. Au-delà de l’intérêt historique, ce chapitre permet d’expliquer de nombreux problèmes de conversion toujours très actuels, il peut également servir de référence lors de la conversion de données entre Unicode et, par exemple, les jeux de caractères codés de MS Windows.

L’essentiel d’Unicode Constituée de deux autres chapitres, la deuxième partie présente l’essentiel d’Unicode. Ce qu’il faut que tout utilisateur averti d’Unicode comprenne d’Unicode. Nous avons voulu résumer et rendre plus accessible le standard Unicode qui peut parfois paraître abstrus et complexe. Le chapitre 3 présente la structure d’Unicode : comment s’organisent les près de 100 000 caractères qu’Unicode définit désormais. On y explique ensuite les différences entre les différents types de caractères : les caractères de base, les diacritiques. Ce chapitre se penche ensuite sur les principes de conception d’Unicode : quels caractères ont été retenus, lesquels furent rejetés et pourquoi ? Le chapitre 4 introduit ce qu’on nomme le modèle de caractères d’Unicode et explique la différence entre les différents formats codés d’Unicode : UTF-8, UTF-16 et UTF-32. Il présente ensuite les principales propriétés attachées aux caractères qui facilitent leur traitement ainsi que les formes normalisées d’Unicode qui permettent de comparer des chaînes de caractères Unicode qui pourraient être identiques bien que codées de manières différentes pour des raisons de compatibilité avec les codages patrimoniaux qu’Unicode a dû incorporer. Le chapitre 4 décrit également brièvement un algorithme important d’Unicode : celui qui permet de trier correctement les chaînes de caractères. Enfin, on présente comment un processus doit traiter les caractères Unicode pour qu’on puisse dire qu’il se conforme à Unicode et comment lire les tableaux de caractères Unicode.

Les caractères remarquables La troisième partie regroupe quatre chapitres qui traitent des principaux types de caractères qui pourraient intéresser les lecteurs de cet ouvrage. Le premier de ces chapitres, le chapitre 5, se penche sur les lettres latines, l’alphabet phonétique et les diacritiques qui intéresseront non seulement les francophones, mais également de nombreux auteurs qui doivent transcrire des langues « exotiques » à l’aide de

XX

Unicode 5.0 en pratique

l’alphabet latin étendu. Suivent ensuite deux sections — le choix est un peu arbitraire étant donné la taille de cet ouvrage — qui décrivent, l’une l’écriture grecque qui non seulement fait partie de notre culture (encore enseignée comme cours à option dans nos écoles) mais présente des défis intéressants en matière de casse et l’autre approfondit le sujet complexe des diacritiques. Le chapitre 6 décrit les différents signes de ponctuation utilisés en français et la majorité des langues qui utilisent l’écriture latine. Certains de ces caractères de ponctuation sont également universels : ceux qui régissent la coupure de ligne. Le chapitre 7 introduit les principaux symboles utilisés dans les notations mathématiques, physiques et la musique. Quant au chapitre 8, il décrit les principales techniques d’Unicode : les caractères de commande hérités du Latin-1, ainsi que des caractères originaux d’Unicode comme l’Indicateur d’ordre des octets (IOO), le gluon de mots et même de ce qui peut apparaître comme une contradiction les « non-caractères ». Le chapitre 8 se termine par une description des caractères déconseillés et désuets et par les zones qu’Unicode a réservées à un usage privé.

Applications et techniques liées à Unicode C’est la partie la plus importante du livre : elle comprend cinq chapitres qui traitent de différentes normes et techniques connexes à Unicode. Le chapitre 9 définit les différentes normes qui permettent d’indiquer la langue (ISO 639), le pays (ISO 3166) et l’écriture (ISO 15924) d’un texte. Ainsi que les standards qui rassemblent et unifient ces normes : le RFC 4646 et le BCP 47. Le chapitre 10 décrit comment préciser la langue et le codage dans les documents échangés sur Internet. Il aborde également les techniques du côté serveur liées à la négociation automatique de langue, c’est-à-dire comment un serveur Internet peut fournir la page dans la langue préférée du client quand plusieurs versions linguistiques de cette page existent. Enfin, le chapitre se clôt sur une discussion de l’internationalisation des adresses Internet. En d’autres mots, comment utiliser les caractères Unicode dans les noms de domaine tels que ou . Quant au chapitre 11, il se concentre, à la différence du chapitre précédent qui s’intéressait aux protocoles Internet et aux serveurs, sur les techniques d’internationalisation des pages Internet et des documents XML : comment en préciser la langue, la directionalité quand elle est en arabe ou en hébreu, comment y référer aux caractères Unicode, quand il est préférable d’utiliser du balisage plutôt que des caractères Unicode, comment maîtriser l’affichage d’un texte en arabe ou en hébreu, et enfin comment écrire un formulaire HTML « universel » qui permet la saisie de tous les caractères Unicode. L’internationalisation des logiciels est abordée au chapitre 12 : il s’agit ici de présenter les principales techniques et outils qui permettent de concevoir des logiciels qui pourront prendre en charge de nombreuses langues et être prêts pour le marché

Avant-propos

XXI

mondial. L’internationalisation n’implique nullement la traduction des programmes, mais plutôt le développement de ces programmes selon une architecture logicielle qui permettra de traiter de nombreuses langues (trier des noms étrangers, les saisir, les comparer) et, le cas échéant, de traduire facilement l’interface utilisateur de ces programmes. Le dernier chapitre, le chapitre 13, se penche sur la manière dont Unicode et les polices interagissent. Comment passe-t-on d’une suite de caractères Unicode au résultat affiché ? Comment maîtriser cet affichage (on parle aussi du rendu), plus particulièrement quand il s’agit d’afficher des écritures « exotiques » ou d’utiliser des fonctionnalités plus poussées comme le crénage ou la formation de ligature ?

Comment lire ce livre ? Bien qu’on puisse lire le livre du premier chapitre au dernier et ainsi jouir d’un panorama complet de ce qu’est Unicode et ses techniques connexes, on peut imaginer différents itinéraires de lecture. Les chapitres essentiels pour tous les lecteurs sont les chapitres 1 Concept de base et terminologie, 3 Structure d’Unicode et 4 Modèle de codage, propriétés et caractères de tri. Les autres chapitres sont relativement indépendants au prix, parfois, de certaines répétitions pédagogiques et de renvois vers d’autres chapitres où le lecteur trouvera un complément d’information. Chaque chapitre est suivi d’un bref résumé de plusieurs paragraphes qui permet au lecteur pressé de ne pas lire au complet un chapitre qui lui paraîtrait accessoire ou ennuyeux tout en apprenant l’essentiel. Par ailleurs des petits encarts soulignent les points importants ou les pièges à éviter au sein des chapitres. Le lecteur pressé peut considérer les chapitres sur les caractères remarquables comme des chapitres de référence auxquels il reviendra à loisir quand il se trouvera confronté aux caractères décrits dans ces chapitres. Nous pensons cependant que le chapitre 8, Caractères techniques spéciaux, est fortement recommandé à tous les lecteurs. Les concepteurs et administrateurs de site web trouveront la lecture des chapitres 9, 10 et 11 instructive. Les programmeurs chargés de l’internationalisation de logiciels devraient lire les chapitres 9 et 12. Ceux qui désirent créer une police pour leur écriture préférée ou veulent comprendre comment fonctionne une police OpenType profiteront de la lecture du chapitre 13.

Conventions adoptées dans ce livre

• Texte à chasse fixe et à barre latérale — Le texte à chasse fixe et à barre gauche latérale représente du code dans l’acception la plus large de ce terme. Ainsi, l’extrait suivant représente-t-il du code XML :

Panneau de configuration > Polices) et cliquez avec le bouton droit puis choisissez Propriétés, la boîte de dialogue illustrée par la figure 1.4 apparaîtra.

Figure 1.4 – Fenêtre de propriétés de police sous MS Windows

Malheureusement, Microsoft a décidé de ne pas traduire celle-ci complètement ! Si vous cliquez sur l’onglet « CharSet/Unicode » vous remarquerez que la police (de la famille Arial) est indexée par des valeurs Unicode (« Font Encoding Type = Unicode (ISO 10646-2 ») et qu’elle comprend non seulement des caractères latins, mais également grecs et cyrilliques. Il existe un autre outil gratuit, BabelMap, qui permet également ce type de découverte. Il est téléchargeable ici . Une fois téléchargé et installé, lancez-le (nous l’utiliserons encore !). Cliquez sur Outils>Analyse de police. La fenêtre de la figure 1.5 apparaît.

18

Chapitre 1. Concept de base et terminologie

Figure 1.5 – Analyse de police sur BabelMap

Vous pourrez alors analyser la police courante et voir tous les blocs Unicode qu’elle prend en charge. Si les caractères affichés pour un bloc ne correspondent pas aux noms de caractères : vous voyez des caractères arabes à la place de caractères latins, par exemple, votre police n’est pas Unicode (c’est-à-dire qu’elle n’est pas indexée à l’aide de valeurs Unicode, voir § 13.5, Pas d’expédients ASCII, de l’Unicode !). Cet outil permet également, comme c’est le cas dans la capture d’écran, de vérifier la couverture d’un bloc à travers toutes les polices installées sur votre système. Ceci n’est pas possible avec l’outil de Microsoft. Dans l’exemple précédent, on voit le résultat de l’analyse du bloc arabe. On remarque que la police Times New Roman comprend 208 glyphes (pour les 235 caractères du bloc arabe), mais que la police MV Boli n’en reprend que trois. Il s’agit d’une police pour le thâna, une écriture en partie d’inspiration arabe utilisée aux Maldives pour écrire le divéhi ou maldivien, une langue indo-iranienne.

1.5.3

Où trouver des polices multi-écritures supplémentaires ? Il est possible que votre système n’ait pas de police assez riche pour afficher les caractères dont vous avez besoin. La première chose à faire, si votre système d’exploitation est MS Windows, est de vous assurer que Windows a été configuré pour prendre en charge un maximum de langues. Si ce n’est pas le cas, il vous faudra ajouter des polices supplémentaires.

1.5 Apprivoiser les polices Unicode

19

Sur Windows XP, procéder de la façon suivante :

• Sélectionner Démarrer > Panneau de configuration > Options régionales et linguistiques.

• Cliquer sur l’onglet

Langues, on y voit deux cases : « écritures complexes1

et écrites de droite à gauche » et « langues d’Extrême-Orient » (chinois japonais coréen, CJC). Cocher sur la case correspondant aux écritures qui vous intéressent. Le système installera les polices correspondantes ainsi que les modules algorithmiques nécessaires à une bonne prise en charge de ces langues. Appuyer sur OK.

• Il se peut que le système vous demande ensuite d’insérer le cédérom de Windows ou de préciser l’endroit où ces fichiers d’installation se trouvent. Suivez les instructions. Windows Vista a intégré dans sa distribution standard ces écritures complexes et ces langues d’Extrême-Orient (CJC) en y ajoutant de nombreuses nouvelles écritures et au moins une police pour chacune. Parmi ces nouvelles écritures prises en charge par Windows, on retrouve : l’éthiopien, le khmer, le lao, le mongol, l’oriya, le ouïgour (à l’aide de l’écriture arabe), le singhalais, le tibétain, le syllabaire autochtone canadien et le yi. MS Office installe également de nombreuses polices très riches, dont Arial Unicode MS qui couvre de très nombreuses écritures. Il existe d’autres polices gratuites ou offertes comme « partagiciel » qui prennent en charge un très grand nombre d’écritures :

• Code 2000 — — Cette police comprend des glyphes pour la quasi-totalité d’Unicode 4.0 sauf ce qui est dans la police Code 2001, techniquement on dit qu’elle comprend des glyphes pour tout le PMB (Plan multilingue de base) d’Unicode 4.0, nous reviendrons sur le terme PMB par la suite, il suffit de savoir à ce stade que presque tous les caractères Unicode sont codés dans ce plan. La qualité de la police est relativement médiocre, mais il s’agit d’une bonne police de derniers recours. Il est recommandé de la télécharger (et si possible de laisser une obole à son créateur bénévole).

• Code 2001 — — Cette police comprend surtout des glyphes pour des écritures anciennes.

• Cardo — — Police destinée aux spécialistes des lettres classiques (grec, italique, latin, alphabet phonétique international, hébreu).



1. À savoir l’arabe, l’arménien, le géorgien, l’hébreu, les écritures de l’Inde, le thaï et le vietnamien.

20

Chapitre 1. Concept de base et terminologie

• Charis SIL — — Prend en charge quasiment toutes les langues utilisant les écritures latine, cyrillique, et l’alphabet phonétique international.

• DéjàVu — — Prend en charge le latin, le grec, le cyrillique, les écritures africaines romanisées, l’arabe, l’hébreu, le n’ko, le tifinagh, etc.

• Doulos SIL — — Prend en charge le latin, le cyrillique, l’alphabet phonétique international, les écritures africaines romanisées.

• Gentium SIL — — Prend en charge le latin, l’alphabet phonétique international, le grec, les écritures africaines romanisées.

1.5.4

Absence de glyphe pour un caractère Il arrive parfois qu’un programme ne puisse pas afficher des caractères Unicode stockés dans un document. Ce peut être dû au fait que le texte est mal décodé (mojibaké), qu’il n’existe pas de caractère Unicode pour ce numéro de caractère ou que les polices associées à ce document n’ont pas de glyphe pour un caractère Unicode légitime. Rappelons au passage que CSS et XSL-FO permettent d’associer une liste de polices à un document ou à des passages de celui-ci. Le logiciel utilisera les polices dans l’ordre dans lequel elles sont mentionnées. Soit donc un passage HTML libellé de la sorte1 :

L’esclave en grec : ὁ δοῦλος.



Le navigateur affiche le texte en français en utilisant la police Batang, il affiche également les caractères non accentués grecs en Batang, car ils se trouvent dans cette police. Les caractères accentués en sont, toutefois, absents, le navigateur se tourne alors vers la seconde police SBL Greek qui elle les contient. Notez que ce changement de police ne produit pas un résultat très esthétique, il s’agit d’un pisaller. Pour éviter ce problème, il suffit d’inverser la liste des polices :

Lʼesclave en grec : ὁ δοῦλος.



Figure 1.6 – Choisir une police complète et harmonieuse

1. Nous avons, par désir de concision, orné le

d’un style particulier. Une feuille de style CSS isolera habituellement ce style et l’appliquera à tous les paragraphes du document de la sorte : p { font-family : "SBL Greek", Batang, serif; }

1.5 Apprivoiser les polices Unicode

21

La police SBL Greek comprend tous les caractères grecs accentués nécessaires, les mots « ὁ δοῦλος » s’affichent donc sans changement inopportun de police. Elle comprend d’ailleurs tous les autres caractères latins, la phrase entière s’affiche dans une police conçue pour afficher du grec accentué et du latin de façon harmonieuse. Si, dans notre exemple, un caractère venait encore à manquer (il n’est ni dans SBL Greek, ni dans Batang), le navigateur se replierait alors sur n’importe quelle police à empattements puisque nous avons mentionné « serif » comme dernière police. Si aucune police à empattements ne permet d’afficher un caractère, le navigateur se tournera vers sa police de dernier recours. Si celle-ci ne contient aucun glyphe pour un caractère du texte, le navigateur affichera habituellement un glyphe pour indiquer l’impossibilité d’en trouver un : un « ? », un « □ » ou encore un « ᪽ ». Il n’y a pas qu’en HTML que des caractères peuvent manquer. C’est également le cas pour d’autres documents électroniques comme les PDF ou les fichiers de traitement de texte, si des polices mentionnées dans le document en question ne sont pas disponibles. MS Word affiche alors typiquement un carré blanc : « □ ».

1.5.5

Incorporation des polices Pour pallier ce problème, une technique consiste à incorporer les polices nécessaires à l’affichage d’un document dans ce même document. Ce n’est pas le comportement habituel des traitements de texte, car cette incorporation de polices peut considérablement alourdir le document. Habituellement, les traitements de texte supposent que les polices sont installées sur le système local et ils n’incluent que des références à ces polices dans le document, sans inclure les polices elles-mêmes. Il existe, toutefois, au moins un cas où l’on peut vouloir inclure la police dans le document de traitement de texte, il s’agit des cas où, pour des raisons de droit d’auteur, l’on ne désire pas transmettre (et donc donner) une police, mais l’on veut cependant que le document s’affiche correctement chez son correspondant. Si l’incorporation automatique des polices n’est pas souvent souhaitable pour les fichiers de traitement de texte, elle est cruciale pour les documents PDF qui se targuent de pouvoir s’afficher sur toutes les plateformes de manière identique. Cette incorporation n’est cependant pas obligatoire1. Les fichiers PDF n’incorporent habituellement pas ce qu’il est convenu d’appeler les 14 fontes PostScript standard : Times Roman (italique, gras, gras italique, romain), Courier (italique, gras, gras italique, romain), Helvetica (italique, gras, gras italique, romain), Symbol et Zapf Dingbats. Tous les logiciels d’affichage de fichier PDF doivent incorporer ces polices et il est donc inutile que tous les fichiers les incorporent.

1. Ainsi, pour les applications industrielles qui envoient de très nombreux fichiers qui utilisent quasi systématiquement les mêmes polices, il est possible d’installer ces polices sur le serveur d’impression qui transforme les fichiers PDF en images tramées pour les imprimantes qui lui sont reliées et éviter de la sorte que chaque fichier PDF envoyé à ce serveur contienne à chaque fois toutes ces polices.

22

Chapitre 1. Concept de base et terminologie

Notons enfin que l’incorporation de police est souvent optimisée : seuls les glyphes d’une police donnée qui sont réellement utilisés dans le document sont incorporés, on parle alors de jeu partiel incorporé. Cela allège, bien sûr, d’autant le document qui incorpore les portions de police en question. Ceci est essentiel avec les polices idéographiques, dites CJC, car ces polices contiennent un très grand nombre de glyphes. Toutes les polices ne sont pas incorporables dans des documents. Si elles le sont, vous pourrez alors, par exemple, les inclure dans des documents MS Word 2003 en le mentionnant parmi les options de sauvegarde (Fichier > Enregistrer sous... > Outils > Options d’enregistrement, puis cocher Incorporer les polices TrueType). Avec MS Word 2007, il faut cliquer sur l’icône Microsoft Office, en haut à gauche, puis cliquer sur Options Word > Enregistrement puis cocher Incorporer les polices dans le fichier.1 Il est sage de décocher cette option une fois le document enregistré, car cette option s’appliquera à toutes les futures sauvegardes quel que soit le fichier, ce qui est en général totalement superflu. Pour déterminer si une police est incorporable, utiliser l’utilitaire de propriétés de police que nous avions déjà vu précédemment (figure 1.3). Malheureusement, l’incorporation des polices n’a jamais vraiment décollé dans le domaine de l’HTML peut-être parce qu’aucune norme n’est apparue suffisamment tôt dans ce domaine. Microsoft a développé sa propre solution peu répandue : WEFT qui n’est pas prise en charge par Firefox. D’autres techniques d’incorporation existent, plus particulièrement sIFR2 qui combine JavaScript, CSS et Flash ou encore Glyphgate (), un module à ajouter au serveur qui gère les pages HTML et qui, au pire, envoie des images du texte à afficher pour les polices qui ne seraient pas prises en charge correctement par votre navigateur3. Pour plus de détails sur ce sujet, voir le chapitre 10, Fontes et pages web, de l’ouvrage de Yannis Haralambous cité dans la bibliographie.

1.6

SAISIR DES CARACTÈRES UNICODE Il existe de nombreuses manières de saisir des caractères Unicode. Celles-ci varient selon le programme, le document ou la plateforme. Plusieurs peuvent exister en parallèle. Celles-ci s’opposent souvent par deux qualités : la simplicité ou l’universalité. La méthode la plus simple est souvent le clavier avec une touche gravée (ou une petite combinaison de touches) affectée à un caractère. Étant donné le nombre limité de touches gravées, c’est évidemment de loin la méthode la moins universelle. Une

1. Dans MS Word 2003 comme dans MS Word 2007, il existe une case à cocher qui permet de « ne pas incorporer les polices système communes », il s’agit ici des polices livrées avec MS Windows et non des quatorze fontes PostScript standard. 2. Voir . 3. Voir le site de l’Assemblée législative du Nunavut pour un exemple de site géré par GlyphGate et capable d’afficher de l’inuktitut (esquimau) même sur un navigateur dépourvu de police appropriée : .

1.6 Saisir des caractères Unicode

23

méthode universelle — mais peu mnémotechnique — est de mentionner le numéro des caractères Unicode que l’on veut saisir. On peut, grosso modo, classer les différentes manières de saisir des caractères en six grandes catégories : 1) Clavier — Il s’agit ici d’une combinaison de touches. Elle peut comprendre l’utilisation de touches mortes comme « Alt », « Alt Gr » ou « Ctrl ». 2) Méthode d’entrée — Les méthodes d’entrée sont utilisées dans les langues idéographiques. L’utilisateur précise souvent en orthographe phonétique le mot chinois (par exemple en pinyin) ou par une suite de portions du caractère (dans le cas de la méthode des « quatre coins »). Comme plusieurs caractères chinois partagent typiquement une même prononciation, l’utilisateur doit le plus souvent choisir parmi les choix proposés par la méthode pour conclure la saisie. 3) Menu — L’utilisateur parcourt une série de menus et choisit une option qui insère un caractère particulier. Certains éditeurs HTML (comme le Composeur de Mozilla) utilisent cette méthode qui ne permet, toutefois, que d’insérer un nombre très limité de caractères différents. 4) Appel de caractère — Série de caractères facilement accessibles à tous les utilisateurs (souvent réduite aux seuls caractères ASCII de base) qui sera interprétée par la suite comme un caractère d’une autre valeur. C’est ainsi que la chaîne de caractères « È » sera interprétée comme un « È » par les analyseurs HTML et XML, 00C8 étant la valeur hexadécimale Unicode du caractère « È ». 5) Sélection à partir d’un tableau — On appelle un module d’un programme (par le moyen d’un menu) qui affiche ensuite une grille de caractères. On peut ensuite pointer sur une case du tableau pour choisir le caractère désiré parmi les caractères voisins. Cette option permet d’insérer plus de caractères que le simple menu (l’option 3), qui ne permet que de choisir un caractère parmi une courte liste affichée dans un menu déroulant par exemple. 6) Clavier virtuel — Un petit clavier s’affiche à l’écran et on peut sélectionner les touches grâce au clavier ou en cliquant sur les touches affichées à l’écran. C’est un peu une forme hybride du clavier standard et du tableau à l’écran. Le tableau 1.4 résume différentes options d’insertion de caractères Unicode.

24

Chapitre 1. Concept de base et terminologie

Tableau 1.4 – Méthodes pour insérer des caractères Unicode Catégorie

Contexte

Méthode

Remarques

Appel

CSS

\41B

Notation hexadécimale, se termine après 4 chiffres (0-F) ou au premier caractère qui n’est pas un chiffre hexadécimal. L’espace qui suit cet appel de caractère est « avalé ». \41B est la lettre cyrillique Л. Voir aussi, § 11.6, Notation des caractères.

Appel

HTML

é

Appel d’entité, correspond à « é ».

Appel

Java

\u041B

Le Л cyrillique.

Clavier

Windows

Alt-133

Correspond à « à » (numéro décimal en CP 850, un codage hérité de MS DOS).

Clavier

Windows

Alt-0133

Correspond à « … » (numéro décimal en Windows Latin 1, voir § 2.4, Windows Latin 1).

Menu + Tableau

Windows

Démarrer > Programmes > Accessoires > Outils système > Table des caractères

Cocher la case « Affichage avancé », sélectionner par numéro ou par bloc le caractère.

Clavier

Word en français

41B Alt-C

Le numéro hexadécimal du caractère Unicode suivi d’Alt-C est transformé en Л.

Menu + Tableau

Word 2003

Insertion > Caractères spéciaux

Menu + Tableau

Word 2007

Insertion > Symbole > Autres symboles…

Clavier

Wordpad et Word en anglais

41B Alt-X

Correspond à Л, ne fonctionne pas dans MS Word français.

Appel

Perl

chr(0x263C)

Correspond au soleil blanc « ☼ ».

Appel

TeX ou LaTeX

\biguplus

U+2A04 Ე UNION N-AIRE AVEC

Appel

XML, HTML



Appel de caractère numérique hexadécimal (U+00B6 pied-demouche).

Appel

XML, HTML



Appel de caractère numérique décimal (U+00B6 pied-de-mouche).

Sélectionner par numéro ou par bloc le caractère.

PLUS.

1.6 Saisir des caractères Unicode

1.6.1

25

Claviers

Claviers préinstallés Votre système d’exploitation comprend de très nombreuses définitions de clavier. Habituellement, une seule de ces définitions est activée : celle qui correspond aux touches gravées sur votre clavier. Il est cependant tout à fait possible d’ajouter d’autres définitions de clavier pour d’autres langues et que vous pourrez utiliser à loisir. Ceci signifie, implicitement, que les touches de clavier n’envoient pas directement des numéros de caractère au système d’exploitation, mais des numéros de touche que le pilote de clavier interprète en fonction de la définition de clavier active. Dans MS Windows XP, l’ajout de clavier se fait par le même menu d’Options régionales et linguistiques (Démarrer > Panneau de configuration > Options régionales et linguistiques) sous l’onglet Langues, dans Services de texte et langues d’entrée, cliquer sur Détails. Choisir ici les langues et les dispositions de clavier qui vous conviennent. Dans MS Windows Vista, l’ajout de clavier se fait par l’onglet Clavier et langues : (Démarrer > Panneau de configuration1 > Clavier et langues) puis en cliquant sur le bouton Modifier les claviers… Choisir ici les langues et les dispositions de clavier qui vous conviennent. Si vous installez plusieurs claviers, il est également utile de faire apparaître au bas de l’écran la barre des langues qui vous permettra de changer rapidement de clavier. Pour ce faire, dans Windows XP, toujours dans fenêtre de Détails où vous avez ajouté des claviers, sous Préférences, cliquer sur Barre de langue, puis dans la boîte de dialogue Paramètres de la barre de langue, cocher la case Afficher des icônes supplémentaires de la barre de langue dans la zone de notification. Cliquer sur OK à trois reprises.

Pour faire apparaître cette barre des langues dans Windows Vista, cliquer sur l’onglet Barre de langues, puis cocher les options adéquates. Pour changer de clavier, vous pourrez alors cliquer sur la barre de langue et manuellement changer de clavier ou alterner entre les claviers à l’aide de touches de raccourci (typiquement les touches Alt de gauche + Maj). Attention — Cette dernière option explique pourquoi il est déconseillé d’installer des claviers supplémentaires sur la machine d’autrui sans l’avertir, puisque cette personne pourra avoir la désagréable surprise de se voir subitement taper en une langue exotique après avoir, par inadvertance, tapé sur les touches de changement de clavier.

1. En mode classique, passer par le niveau intermédiaire Options régionales linguistiques, puis continuer avec l’onglet Clavier et langues.

et

26

Chapitre 1. Concept de base et terminologie

Figure 1.7 – Choisir un autre clavier et préciser une autre langue

Habituellement à chaque langue n’est associé qu’un clavier et le simple fait de choisir une langue suffit à choisir un clavier. Toutefois, si vous souhaitez avoir accès à plusieurs dispositions de clavier pour une même langue (français AZERTY et français canadien QWERTY), un petit clavier apparaît à côté du code langue dans la barre de langue. Ce clavier vous permettra de choisir manuellement la disposition de clavier que vous préférez pour cette langue. Dans l’exemple précédent, le système définit deux dispositions de clavier possibles pour l’arabe (marocain), nous avons choisi la variante à 101 touches (la variante à 102 touches pourrait être utilisée avec un clavier externe, par exemple). Le même principe existe sous Mac OS X, consultez pour un exemple d’installation et de sélection d’un clavier tifinagh (l’écriture touarègue).

Claviers virtuels Maintenant que vous avez installé un clavier étranger, si vous sélectionnez ce clavier, les lettres gravées sur les touches de votre clavier sont probablement de peu d’utilité. Idéalement, au changement de clavier, les lettres sur les touches devraient changer. On l’a tenté à l’aide de diodes électroluminescentes1, malheureusement ce genre de clavier n’a pas réussi à s’imposer. À la place, la plupart des systèmes proposent des claviers virtuels. Pour afficher le clavier virtuel qui correspond au clavier courant sous Windows XP, cliquer sur Démarrer, pointer sur Tous les programmes, sur Accessoires, sur Accessibilité, puis cliquer sur Clavier visuel. Sous Windows Vista, cliquer sur Démarrer, pointer sur Tous les programmes > Accessoires > Options d’ergonomie > Clavier visuel. Le clavier virtuel sert non seulement d’aide-mémoire, mais il permet aussi la saisie en pointant et cliquant sur les touches représentées sur ce clavier visuel. La figure 1.8 correspond au clavier visuel pour le clavier marocain arabe.

1. Disponibles ici .

1.6 Saisir des caractères Unicode

27

Figure 1.8 – Clavier visuel marocain arabe

Définir son propre clavier Le format réduit de ce livre ne permet pas de décrire la manière de composer soi-même un nouveau pilote de clavier. C’est aujourd’hui chose assez facile sur les systèmes modernes pour les claviers à la disposition relativement simples. Si vous désirez créer un pilote de clavier pour Windows, utilisez l’utilitaire MSKLC1. Sur Mac OS/X (versions 10.2 et ultérieures), deux utilitaires : Ukelele2 et KeyLayoutMaker3. Les claviers tifinaghs mentionnés ici4 ont été créés à l’aide de MSKLC pour Windows et Ukelele pour Mac OS X.

Méthode d’insertion directe par numéro de caractère Dans MS Word et MS Wordpad, par exemple, si vous connaissez la valeur (hexadécimale) Unicode d’un caractère, vous pouvez insérer directement ce caractère dans votre document à l’aide du raccourci clavier Alt-X (Alt-C dans Word en français) :

• Tapez la valeur (hexadécimale) Unicode du caractère. La chaîne de valeur peut également commencer par U+.

• Appuyez sur Alt-X (Alt-C dans Word en français). L’application remplace la chaîne située à gauche du point d’insertion par le caractère spécifié. Remarquez qu’un raccourci particulier à l’éditeur dans lequel vous désirez saisir, ou une macro définie après l’installation, un caractère à l’aide d’Alt-X (ou Alt-C) pourrait masquer cette méthode de saisie du système d’exploitation. La substitution Alt-X est fournie par un module appelé Uniscribe dont nous parlerons par la suite (voir § 13.8, Un moteur de rendu : Uniscribe). Il existe également deux méthodes de saisie plus anciennes sur Windows qui utilisent des numéros de caractères décimaux. Il s’agit des méthodes Alt-n et Alt-0-n. 1. 2. 3. 4.

28

Chapitre 1. Concept de base et terminologie

Ces méthodes fonctionnent avec la quasi-totalité des applications, contrairement à la méthode d’Alt-X qui dépend de l’utilisation par le programme du module d’écriture complexe appelé Uniscribe. La méthode Alt-n, quand n est ≤ 255, précise le caractère dans la page DOS locale, il s’agit de CP 850 pour les systèmes francophones où Alt-133 correspond à « à ». Dans certains programmes plus récents de Windows, le n peut être plus grand que 255. Il s’agit alors de la valeur décimale Unicode du caractère. Alt-8470 correspond ainsi à « № » (U+2116 symbole numéro). Ceci fonctionne dans MS Word et Wordpad sur Windows XP et Vista. La méthode Alt-0-n précise le caractère dans la page Windows locale (Latin-1 pour les systèmes français, Windows 1251 en Russie). Dans ce cas-ci, le n doit toujours être plus petit ou égal à 255. Alt-0133 correspond sur une machine Windows francophone aux points de suspension « … ».

1.6.2

Méthodes d’entrée extrême-orientales Une méthode d’entrée est un programme utilisé pour permettre la saisie des milliers de caractères différents des langues dites CJC (chinois, japonais, coréen), à partir d’un clavier normal à 101 touches. Un éditeur de méthode d’entrée est constitué à la fois d’un moteur qui convertit les frappes de touches en caractères phonétiques et idéographiques, et d’un dictionnaire des mots idéographiques les plus usités. Au fur et à mesure que l’utilisateur frappe sur les touches, le moteur de l’éditeur de méthode d’entrée tente de reconnaître le ou les caractères et de les convertir en idéogrammes à l’aide du dictionnaire et de différents algorithmes. Sous MS Windows, on ajoute et on active une méthode d’entrée de la même manière que les claviers (figure 1.7). Après avoir sélectionné la méthode d’entrée (un type de clavier chinois dans l’exemple suivant), il est alors possible de commencer à saisir des idéogrammes. Dans notre cas, nous avons choisi une méthode phonétique d’entrée, on tape du pinyin et la méthode affiche l’idéogramme qui y correspond le mieux. Si ce choix n’est pas adéquat, l’utilisateur peut choisir un autre idéogramme manuellement.

Figure 1.9 – Méthode d’entrée pour idéogrammes

Dans l’exemple de la figure 1.9, l’utilisateur vient de taper « zhong » et la méthode d’entrée a substitué à cette transcription pinyin l’idéogramme Ё. L’utilisateur, à l’aide d’une touche (flèche vers l’arrière ici), a ensuite voulu choisir un autre idéogramme correspondant à « zhong ». C’est pourquoi l’éditeur de méthode d’entrée propose en dessous du point d’insertion les meilleurs autres idéogrammes qui correspondent à « zhong ».

1.6 Saisir des caractères Unicode

1.6.3

29

Tableau de caractères Il existe de nombreuses applications qui permettent de choisir des caractères à partir d’un tableau. Une fois n’est pas coutume, commençons par le cas du Mac OS X 10.2 qui possède une jolie palette de caractères livrée en standard qui permet de sélectionner des caractères Unicode et de les insérer dans la fenêtre d’édition1. Pour Windows, il existe un tableau de caractères offert par le système d’exploitation et un autre offert par MS Office. Le tableau de caractères de MS Windows permet la recherche de caractères par leur nom (ISO 10646 en français). On peut ainsi donc facilement trouver toutes les flèches disponibles dans une police. La version d’Office, pour sa part, comprend également une liste de caractères fréquemment utilisés qui ne sont pas accessibles à l’aide des claviers habituels.

Tableau de caractères Windows Windows offre un outil de sélection de caractères à l’aide d’une grille de caractères. Pour y avoir accès passer par Programmes > Accessoires > Outils système > Table des caractères. Une fois la grille affichée, cocher de préférence la case Affichage avancée. Double-cliquer sur les caractères que vous désirez voir copier dans le pressepapiers. Selon l’application cible, il est aussi possible de copier immédiatement le caractère sélectionné en le glissant vers cette application. Dans l’exemple de la figure 1.10, on a sélectionné toutes les flèches répertoriées dans la police Lucida Sans Unicode afin de pouvoir choisir la meilleure. Pour plus d’informations sur l’utilisation de cet outil, cliquez sur le bouton Aide de la fenêtre. Malheureusement, l’outil de Windows ne vous permet pas d’insérer des caractères ajoutés à Unicode après la sortie du système d’exploitation ou même quelques années auparavant. Ceci signifie par exemple qu’on ne peut sélectionner aujourd’hui sous Windows XP des caractères tifinaghs dans une police berbère ou touarègue qui code ces caractères avec les valeurs approuvées par Unicode depuis 2005.

Tableau de caractères MS Office On accède au tableau Unicode des applications Office 2003 en choisissant l’option du menu principal Insertion, puis Caractères spéciaux... Dans Office 2007, passer par le menu Insertion > Symbole > Autres symboles… Ensuite, dans toutes les versions d’Office, choisir l’onglet Caractères spéciaux pour insérer des caractères typographiques fréquents, mais absents des claviers européens, la liste est courte et donc plus pratique à consulter qu’un long tableau reprenant tous les caractères Unicode. Cette même liste énumère les raccourcis qui permettent d’entrer la plupart de ces caractères à l’aide de quelques touches. Exemple : Ctrl--(c’est-à-dire « Ctrl » suivi du « - ») pour insérer le trait d’union conditionnel.

1. Pour plus de détails, voir .

30

Chapitre 1. Concept de base et terminologie

Figure 1.10 – Table des caractères de MS Windows

Pour passer à la grille des caractères Unicode, cliquer à l’endroit où vous souhaitez insérer le symbole, dans le menu Insertion, cliquer sur Caractères spéciaux, puis sur l’onglet Symboles. Dans la zone Police, cliquer sur la police souhaitée. Si vous utilisez une police qui comprend plus de 255 caractères, comme Arial ou Times New Roman, la liste Sous-ensemble s’affiche. Cette liste vous permet de choisir parmi de nombreux caractères, y compris des caractères grecs et russes (alphabet cyrillique), s’ils sont disponibles. Enfin, double-cliquer sur le caractère que vous souhaitez insérer. Lorsque vous sélectionnez un caractère Unicode sous l’onglet Symboles, le numéro du caractère s’affiche dans la zone Code1 du caractère. Si vous connaissez déjà le numéro du caractère, vous pouvez le taper directement dans cette zone pour accéder au caractère Unicode. Malheureusement, l’outil d’Office ne vous permet pas d’insérer des caractères ajoutés à Unicode après la sortie de votre version d’Office ou même quelques années auparavant. C’est pourquoi si votre machine est une machine Windows nous vous recommandons vivement l’option suivante : BabelMap.

1. Il s’agit d’un fâcheux anglicisme de la part de Microsoft, car en français un code est un ensemble de règles, un recueil de lois, un système de symboles, pas un élément de cet ensemble ou de ce système.

1.6 Saisir des caractères Unicode

31

Tableau de caractères BabelMap BabelMap est probablement l’outil le plus complet sous Windows pour la recherche de caractères Unicode. On peut bien sûr, comme pour toutes les palettes de caractères, cliquer sur une case et copier le caractère correspondant dans un tampon, mentionner un numéro de caractère et le voir s’afficher pour ensuite le copier, afficher les caractères d’une écriture particulière et en choisir un ou encore chercher un caractère par son nom comme dans l’outil de Windows. Mais, là où BabelMap semble imbattable, c’est dans la recherche poussée des caractères. On peut ainsi chercher un caractère non seulement en fonction de son nom officiel, mais aussi de ses synonymes non officiels, des commentaires qui lui sont associés dans les tableaux officiels, selon sa propriété. On peut ainsi afficher tous les signes de ponctuation ou tous les symboles monétaires pour une version particulière d’Unicode ! Les options de recherche sont innombrables1.

Copier-coller et presse-papiers Une autre manière de saisir des caractères est de les copier d’un document qui les contient déjà ! C’est en fait ce que vous faites après avoir sélectionné des caractères dans une application comme BabelMap. Dans Windows, on copie le texte sélectionné à l’aide de Ctrl-c dans ce qu’on appelle le presse-papiers et on colle le contenu du presse-papiers dans une fenêtre à l’aide de Ctrl-v. Les applications qui ajoutent du contenu au presse-papiers peuvent copier ce même contenu sous plusieurs formats (RTF, image, HTML, texte brut « ANSI »2, texte brut Unicode, etc.) pour augmenter le nombre d’applications susceptibles de copier ces données. Dans le cas de BabelMap, l’information n’est copiée que sous la forme de texte brut Unicode, mais de nombreuses autres applications copient le texte avec leur formatage (par exemple en RTF ou HTML). Quand vient le temps de recopier ce texte du presse-papiers vers votre traitement de texte, celui-ci copiera habituellement le texte formaté dans votre document. Cela est souvent utile, mais cela peut-être également très déplaisant, car vous voilà soudain avec du texte dont le formatage ne respecte peut-être pas du tout votre gabarit et qui pourrait contenir des hyperliens dont vous n’avez que faire. Pour éviter ce désagrément, copier d’abord le texte du presse-papiers vers un éditeur de texte brut (comme TextPad ou NotePad) celui-ci ne sélectionnera pas la version formatée du presse-papiers mais la version en texte brut, puis réselectionner ce que vous venez de copier, le copier dans le presse-papiers (Ctrl-c) et enfin le coller (Ctrl-v). Cette fois-ci, il sera dépouillé de tout formatage.

1. Pour plus de détails, voir . 2. Ce nom déroutant et erroné est perpétué par Microsoft dans le sens de code de caractères propriétaires Windows, dans le cas des codes sur 8 bits ils sont proches des codes ISO/CEI. Contrairement à leur nom, ces codes n’ont pas été normalisés par l’ANSI, l’organisme de normalisation américain.

32

Chapitre 1. Concept de base et terminologie

MS Word 2003 et Open Office permettent de s’en tirer autrement : il faut non plus copier le texte du presse-papiers à l’aide de Ctrl-v, mais grâce à Edition > Collage spécial, puis choisir Texte Unicode sans mise en forme (Texte non formaté dans Open Office). Pour MS Word 2007, passer par le menu Accueil > Coller > Collage spécial (Alt-Ctrl-v).

1.7

INTERNATIONALISATION ET LOCALISATION L’internationalisation (mot souvent abrégé en i18n – la lettre initiale « i » du mot suivie des 18 lettres intermédiaires et le tout terminé par un « n » final) est un terme général qui désigne le processus qui consiste à préparer les logiciels afin qu’il puisse servir plus d’une culture, afficher plus d’une langue, s’utiliser sur plus d’un marché. C’est un processus technique qui ne requiert aucun talent de traducteur. Une des techniques de base de l’internationalisation consiste à extraire du code d’un programme tous les messages qu’il affichera et de les regrouper dans un fichier séparé qui pourra être traduit sans devoir modifier (ou même consulter) le code de ce programme. D’autres techniques d’internationalisation consistent à structurer le code de telle façon qu’il emploie des services (des bibliothèques logicielles) euxmêmes internationalisés pour ce qui est du tri, du formatage des dates et montants afin que le code ne dépende plus d’une langue particulière. La localisation (l10n) est l’adaptation d’un logiciel à destination d’une culture, ou d’une langue particulière. Cette culture particulière se nomme la « locale » en jargon informatique. Plus l’i18n est bien conçue, plus la localisation est techniquement facile à effectuer. La localisation implique principalement la traduction, mais elle ne se limite pas à cette activité, l’adaptation peut également s’intéresser aux aspects suivants :

• • • •

la modification des formats de date ou de montant ; la modification de la devise ; le tri des données qui pourrait devoir être adapté ; l’utilisation judicieuse de couleurs, d’icônes, de symboles adaptés à la culture cible ;

• les modifications imposées par la loi du pays visé, etc. Nous étudierons les techniques d’internationalisation au chapitre 12.

1.7 Internationalisation et localisation

33

Résumé Dans ce chapitre nous avons d’abord vu ce qui a justifié la création d’Unicode : la multiplicité des jeux de caractères, multiplicité qui soulève de nombreuses difficultés lors de l’échange de données et la conception de logiciels internationalisés. Le mot caractère prend de nombreux sens et il est important de les distinguer du mot « glyphe » (ou œil) qui représente une forme particulière d’un caractère et du terme « graphème » (ce que l’utilisateur perçoit comme une lettre, une entité distinctive de son écriture). Dans certains cas, comme le « c’h » breton, un graphème est composé de plusieurs caractères dans le sens d’éléments d’un jeu de caractères. Les typographes utilisent une terminologie particulière pour décrire la dimension et l’apparence d’un caractère, les termes les plus importants sont : – l’approche (le blanc imprimé avant ou après un caractère), – le talus (le blanc imprimé au-dessus ou en dessous d’un caractère), – la chasse (la largeur du rectangle dans lequel s’inscrit le caractère imprimé, ce rectangle comprend les approches droite et gauche), – le corps (la hauteur de ce rectangle, ce rectangle comprend les talus de pied et de tête), – les empattements (les petits traits aux extrémités d’un jambage). On oppose le texte brut (sans balisage, sans formatage) au texte riche (balisé ou formaté). Afin de bien fixer les idées, nous avons brièvement décrit Unicode (un code de près de 100 000 caractères, une série de propriétés affectées à ces caractères et une série d’algorithmes de référence) et surtout ce qu’Unicode n’est pas : Unicode n’est ni un produit, ni un format de mise en pages ni une solution miracle aux problèmes de traduction de logiciel ou de documents. Par la suite, nous avons vu comment saisir des caractères sur Windows et dans plusieurs logiciels et langages de programmation et comment s’assurer qu’une police était bien une police Unicode. Pour conclure, nous avons décrit ce qu’on nomme les caractères latins (ceux qu’on utilise en français et en anglais), les caractères chinois, coréens et japonais également appelés caractères han ou idéogrammes CJC. Enfin, nous avons introduit deux termes importants dans le domaine qui nous concerne et qu’il faut distinguer : l’internationalisation (la préparation des logiciels, des documents pour qu’ils puissent traiter plus d’une écriture, plus d’une langue) et la localisation (l’adaptation linguistique et culturelle d’un document ou d’un logiciel, elle suppose le plus souvent la traduction). Une bonne internationalisation facilite la localisation.

2 Répertoires et jeux de caractères codés

Objectif Il existe actuellement une grande variété de jeux de caractères qui servent à coder les textes électroniques. Ce chapitre trace une brève histoire des jeux de caractères, plus particulièrement de ceux qui permettent d’écrire le français, et énumère les caractères. À la lumière de cette multiplicité, on verra comment Unicode a radicalement simplifié l’échange de données multilingues. Nous introduisons également quelques notions élémentaires à toute discussion sur les jeux de caractères : qu’est-ce qu’un répertoire de caractères, un jeu de caractères codés, un code ? Certains pourraient se demander s’il est encore utile de décrire ces jeux de caractères historiques dans un livre consacré à Unicode. Le fait est que ces jeux de caractères demeurent importants aujourd’hui. En effet, on les retrouve encore très souvent dans les systèmes d’exploitation les plus modernes. Ainsi faut-il encore souvent convertir des données entre Unicode et ces jeux de caractères patrimoniaux.

2.1

TERMINOLOGIE Avant de passer en revue les principaux jeux de caractères utilisés avant l’avènement d’Unicode, il nous faut introduire quelques notions de base qui nous permettront de mieux décrire et comprendre les différences entre ces jeux de caractères : notamment la différence entre les répertoires et les codes de caractères.

36

2.1.1

Chapitre 2. Répertoires et jeux de caractères codés

Répertoire de caractères Un répertoire de caractères est un ensemble de caractères auxquels on n’a pas attribué de numéro. Les 26 lettres de l’alphabet français de base (non accentué), avec leurs formes minuscules et majuscules, forment un répertoire de caractères. a b c d e A

Figure 2.1 – Répertoire de caractères

2.1.2

Jeu de caractères codés, code et codage On appelle jeu de caractères codés un répertoire de caractères auquel on a associé à chacun de ses éléments un numéro (un nombre entier supérieur ou égal à zéro). Ces numéros ne doivent pas nécessairement être consécutifs, des trous peuvent exister. L’affectation de ces valeurs peut être considérée comme arbitraire, elle est cependant fixe pour un jeu donné de caractères codés. Ce numéro de caractère porte également le nom de point de code, de valeur scalaire, de codet, d’élément de code ou de position de code. On a le choix !

Գ 0

a

2

b 3

c d

7 5

e A

4

Code ou codage de caractères Figure 2.2 – Relation entre répertoire de caractères et codage

2.2 L’ASCII

37

On désigne sous le nom de code ou de codage de caractères, l’association entre un répertoire de caractères et la valeur scalaire (le numéro) de chacun de ces caractères. Le codage est la fonction d’application des caractères du répertoire dans l’ensemble des naturels. Le jeu de caractères codés est l’ensemble des paires (caractère, numéro). Dans la pratique, on ne distinguera pas le codage du jeu de caractères codés pour autant qu’on précise bien « codés » sinon parler de « jeu de caractères » ou de « charset » pour désigner un code particulier est pour le moins ambigu. En effet, les gens considèrent souvent le terme de « jeu » comme un synonyme de « répertoire » ; or il s’agit ici d’un jeu de caractères codés d’une manière bien précise alors qu’un même répertoire peut être représenté par plusieurs jeux de caractères codés.

2.2

L’ASCII L’ASCII (American Standard Code for Information Interchange) est la norme de codage de caractères en informatique la plus connue, la plus largement compatible et celle dont l’échange sur Internet est encore le plus sûr. L’ANSI, l’organisme de normalisation américain, a défini le code ASCII. La création de ce code à 7 bits (ou dit aussi à 7 moments) remonte à la fin des années 1950. Il connut ensuite plusieurs versions. Dans sa version de 1963, plusieurs positions étaient encore non affectées. En 1967, l’ANSI en publie une nouvelle version qui ne connaîtra plus que de légères modifications. On se réfère souvent aujourd’hui à cette norme sous le nom d’ANSI X3.4-1986, bien que le nom officiel de la version actuelle soit ANSI INCITS 4-1986 (R2002). L’ASCII a été conçu comme un code à 7 bits qui permet donc le codage de 27 soit 128 caractères. À l’origine, les données ASCII étaient parfois tassées dans des septets ce qui permettait par exemple de stocker 5 septets dans un mot de 36 bits. Aujourd’hui, les caractères ASCII sont stockés dans des octets dont le premier bit (le plus significatif) est habituellement à zéro. Ce premier bit a également servi de bit de parité pour détecter les erreurs de transmission, toutefois cette technique ne s’utilise plus guère. Si le code ASCII permet le codage de 128 caractères, il ne compte que 94 caractères imprimables (si on considère que l’espace n’est pas un caractère imprimable) codés1 de 0x21 à 0x7E. Les autres positions sont prises par 34 caractères de commande (représentés par des boîtes en pointillés dans le tableau 2.1) : les 32 premiers de 0x00 à 0x1F, regroupés dans un ensemble appelé C0, l’espace 0x20 et le dernier 0x7F.

1. Rappelons – voir l’avant-propos de cet ouvrage – que les nombres du type 0xYY représentent des chiffres hexadécimaux (d’où le « x » dans le nombre). Le caractère 0x21 a donc une valeur hexadécimale de 21 et de 33 en décimal.

38

Chapitre 2. Répertoires et jeux de caractères codés

Tableau 2.1 – L’ASCII à 7 bits 0 0x 1x 2x

1

2

3

4

5

6

7

8

9

A

B

C

D

E

F

     ! « # $ % & ‘ ( ) * +  - . / 

1

2

3

4

5

6

7

8

9








?

4x #

A

B

C

D

E

F

G

H

I

J

K

L

M

N

O

5x 3

Q

R

S

T

U

V

W

X

Y

Z

[

\

]

^

_

6x

C

a

b

c

d

e

f

g

h

i

j

k

l

m

n

o

7x

p

q

r

s

t

u

v

w

x

y

z

{

|

}

¯



3x

Ces caractères de commandes s’utilisaient avec des périphériques tels que les perforateurs de ruban, téléscripteurs et les anciens moniteurs. On trouve par exemple :

• 0x00  nul, ce caractère permettait de laisser des blancs sur le ruban qui pouvait servir à introduire des corrections. Il servit plus tard de remplissage après un caractère dont le traitement pouvait prendre quelque temps (par exemple un retour de chariot ou un passage à la ligne). Il sert aujourd’hui souvent de caractère de fin de chaîne, plus particulièrement en langage C/C++.

• 0x07 sonnerie pour activer la sonnerie d’un télex. • 0x0D  Retour de chariot et 0x0A  Passage à la ligne. Ces deux commandes étaient complémentaires,  déplaçait verticalement le curseur pour passer à la ligne sans déplacement de colonne, alors que  replaçait le curseur au début de la ligne — en colonne 0 — sans passage à la ligne. Dans les langages comme C et C++, ces deux commandes sont représentées par la chaîne « \r\n ». Sur Mac OS (avant Mac OS X) ainsi que d’autres systèmes d’exploitation antérieurs comme Apple II et Commodore 54,  indiquait seul la fin de ligne alors que, sur MS-DOS et MS Windows et plusieurs protocoles de communications, ce caractère précède  pour indiquer la fin de ligne.

• 0x7F  suppression pour supprimer un code erroné en trouant toutes les positions du caractère précédent sur le ruban perforé. Plusieurs de ces caractères étaient donc très liés à une technique aujourd’hui désuète : celle des rubans perforés par exemple. Ils ne sont pratiquement plus utilisés à cette fin. Seuls le caractère nul et les caractères de passage à la ligne et de retour de chariot sont encore d’usage courant aujourd’hui.

2.2 L’ASCII

2.2.1

39

ISO 646 et « variantes nationales de l’ASCII » L’ISO (ou Organisation internationale de normalisation1) a normalisé de nombreuses variantes nationales de l’ASCII grâce à sa norme ISO/CEI2 646. Dans le tableau 2.1, on aura remarqué que la trame de fond de certaines cases est en gris. Ces dix cases sont réservées par l’ISO 646 à des caractères d’usage national. On en retrouve une sélection dans le tableau 2.2. Il faut remarquer que la version de référence (IRV) de l’ISO 646 n’est pas équivalente à l’ASCII puisqu’elle code un ¤ symbole monétaire (neutre) à la place du dollarL’expression « norme nationale de l’ASCII » est, stricto sensu, impropre : il s’agit de normes distinctes qui s’inspirent de l’ASCII, mais qui portent des noms très différents qui ne mentionnent pas l’ASCII. On notera l’incohérence de l’affectation des codes même parmi les pays francophones. C’est une des raisons qui a poussé la France à abandonner sa version de l’ISO 646 (Z62010/1982) au profit de l’ASCII américain en 1983. La grande multiplicité de valeurs affectées par ces codes ISO 646 aux dix positions « nationales » crée souvent des problèmes d’échange. Il se peut ainsi qu’un texte contenant la chaîne vecteur[2] s’affiche sous la forme de vecteurâ2ê si le logiciel d’affichage considère que la chaîne est codée dans une des versions canadiennes de l’ISO 646.

2.2.2

« ASCII 8 bits » On voit souvent écrit le terme « ASCII 8 bits ». Ce terme ne convient pas. L’ASCII est sans équivoque un code à 7 bits significatifs. Si des caractères ASCII sont stockés dans des octets, le 8e bit est habituellement à zéro, mais comme on l’a vu il peut aussi servir de bit de parité. Quoi qu’il en soit, ce 8e bit ne fait pas partie de la valeur du caractère ASCII. L’ASCII 8 bits désigne souvent, à tort, des jeux de caractères à 8 bits dont les 128 premières positions correspondent aux valeurs ASCII. Nous verrons dans les sections suivantes deux codes différents auxquels on se réfère souvent comme de l’« ASCII 8 bits » : ISO/CEI 8859-1 et Windows-1252. Il vaudrait mieux parler de codes « fondés sur l’ASCII ».

1. Le nom anglais de l’ISO est l’International Organization for Standardization. C’est à dessein que le nom abrégé de cette organisation internationale ne se réfère ni aux initiales de son nom en anglais, ni à celles en français, mais à l’élément « iso » présent dans de nombreux termes techniques de plusieurs langues avec le sens d’égalité et donc, avec un peu d’imagination diplomatique, au recours à une norme : « isotherme », « isométrique », etc. 2. Pour alléger le texte, nous omettrons souvent le sigle CEI dans les normes qui sont à la fois celles de l’ISO et de la CEI (Commission électrotechnique internationale).

40

Chapitre 2. Répertoires et jeux de caractères codés

Tableau 2.2 – ISO 646 – l’IRV et ses variantes nationales

2.3

23

24

40

5B

5C

5D

5E

60

7B

7C

7D

7E

Version de référence (IRV)



f

#

>

?

@

A

C

^

|

`

a

Allemagne (DIN 66003)





i

†

˜

ž

A

C

¦

¸

¾

¡

Belgique





¢

r

‰

i

A

C

«

LM

ª

a

Canada (CSA Z243.4 n°1)





¢

¤

‰

¬

°



«

»

ª

½

Canada (CSA Z243.4 n°2)





¢

¤

‰

¬

‹



«

»

ª

½

Espagne (IBM)





y

c

“

‰



C

v

³

©

j

États-Unis (ANSI X3.4)





#

>

?

@

A

C

^

|

`

a

France (NF Z62010/1982)

e



¢

r

‰

i

A

w

«

»

ª

j

Royaume Uni (BS 4730)

e



#

>

?

@

A

C

^

|

`

a

Suède (SEN 850200 B)



f

#

†

˜

‡

A

C

¦

¸

§

q

Suède (SEN 850200 C)



f

‹

†

˜

‡

ž

«

¦

¸

§

¾

LES CODES ISO/CEI 8859 L’ISO a défini au courant des années 1980 une série de jeux de caractères codés sur 8 bits : la famille ISO/CEI 8859. Ces codes sont encore très utilisés sur de nombreuses plateformes, plus particulièrement dans le monde Unix et Linux. Les 128 premières positions de tous les codes ISO/CEI 8859 sont les mêmes : elles correspondent à l’ASCII. L’intervalle 0x80 à 0x9F contient des caractères de commande rares qui forment l’ensemble C1 de l’ISO 6429.

2.3 Les codes ISO/CEI 8859

2.3.1

41

ISO/CEI 8859-1 ou ISO Latin-1 La pléthore de codes ISO 646 incompatibles entre eux a conduit l’ISO à définir un code à 8 bits qui pourrait mieux prendre en charge les langues de l’Europe occidentale. C’est pourquoi, outre les 128 caractères de l’ASCII, l’ISO Latin-1 comprend de nombreux caractères accentués ainsi que quelques caractères de ponctuation. Ces nouveaux caractères sont tous codés dans l’intervalle de positions 0xA0 à 0xFF. Le tableau 2.3 représente les 128 caractères supérieurs de l’ISO 8859-1. Le premier caractère de cet intervalle, 0xA0 espace insécable a la même apparence que l’espace ASCII, mais il ne peut servir à couper une ligne lors de la composition du texte qui le contient. Un logiciel conforme ne peut donc couper la ligne à l’espace au milieu de « 5 kg », si cet espace est un 0xA0 espace insécable. À la position 0xAD, on trouve le caractère de formatage  trait d’union conditionnel, ce caractère prend l’apparence d’un trait d’union habituel — s’il coïncide avec la fin d’une ligne lors de la composition — ou n’a pas d’apparence graphique dans les autres cas ; on dit alors qu’il n’a pas d’œil1. Le Latin-1 ne prend malheureusement pas complètement en charge le français : il manque les lettres Œ et œ (cf. Œuvre et cœur) et le y tréma majuscule (cf. l’auteur PIERRE LOUŸS). Tableau 2.3 – Partie supérieure de l’ISO/CEI 8859-1 0 8x 9x Ax

1

2

3

4

5

6

7

8

9

A

B

C

D

E

F

   ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬  ® ¯

Bx

°

±

²

³

´

μ



·

¸

¹

º

»

¼

½

¾

¿

Cx

À

Á

Â

Ã

Ä

Å

Æ

Ç

È

É

Ê

Ë

Ì

Í

Î

Ï

Dx

Ð

Ñ

Ò

Ó

Ô

Õ

Ö

×

Ø

Ù

Ú

Û

Ü

Ý

Þ

ß

Ex

À

á

â

ã

ä

å

æ

Ç

è

é

ê

ë

ì

í

î

ï

Fx

Ð

ñ

ò

ó

ô

õ

ö

÷

ø

ù

ú

û

ü

ý

þ

ÿ

1. L’œil est la partie d’un caractère qui s’imprime sur le support.

42

Chapitre 2. Répertoires et jeux de caractères codés

Le protocole HTTP1 précise que l’ISO 8859-1 est le codage implicite en l’absence de toute mention d’un paramètre charset dans le champ d’entête Content-Type. Dans la pratique, cette recommandation s’est révélée inapplicable, car certains serveurs ne permettent pas l’envoi d’un paramètre charset alors qu’ils retournent des pages qui ne sont pas codées en 8859-1 et que d’autres n’ont pas été configurés pour envoyer ce paramètre. Ceci explique que les navigateurs ne peuvent se baser sur l’absence d’un paramètre charset pour afficher correctement le document envoyé.

Les autres codes ISO/CEI 8859 L’ISO 8859-1 est un membre de l’ensemble des codes ISO 8859. Les autres codes ISO 8859-n conçus pour prendre en charge des écritures alphabétiques sont tous codés sur 8 bits et partagent les mêmes valeurs de 0x00 à 0x9F. Le tableau 2.4 énumère les différentes parties de la norme ISO 8859. Tableau 2.4 – Les codes de caractères de l’ISO/CEI 8859 Norme

Nom de l’alphabet

Description

ISO 8859-1

Alphabet latin n° 1

Europe occidentale

ISO 8859-2

Alphabet latin n° 2

Europe centrale

ISO 8859-3

Alphabet latin n° 3

Maltais et espéranto

ISO 8859-4

Alphabet latin n° 4

Balte (danois, estonien, finnois, suédois)

ISO 8859-5

Alphabet latin/cyrillique

Russe, bulgare, biélorusse.

ISO 8859-6

Alphabet latin/arabe

Arabe

ISO 8859-7

Alphabet latin/grec

Grec moderne (monotonique)

ISO 8859-8

Alphabet latin/hébreu

Hébreu et yidiche (sans voyelle)

ISO 8859-9

Alphabet latin n° 5

Turc (Latin-1 moins 6 lettres islandaises, remplacées par 6 lettres turques)

ISO 8859-10

Alphabet latin n° 6

Nordique (lapon, islandais, esquimau)

ISO 8859-11

Alphabet latin/thaï

Thaï

Il n’y a pas de partie 12, elle devait coder la dévanâgarî, mais ce projet fut abandonné. ISO 8859-13

Alphabet latin n° 7

Balte (estonien, finnois, letton, lituanien)

ISO 8859-14

Alphabet latin n° 8

Celte (gallois, cornique, gaélique)

ISO 8859-15

Alphabet latin n° 9

Version « euro » du Latin-1, Europe occidentale, mais particulièrement le français (voir § 2.3.2).

ISO 8859-16

Alphabet latin n° 10

Balkans (roumain, croate et slovène)

1. RFC 2616, section 3.7.1.

2.3 Les codes ISO/CEI 8859

2.3.2

43

ISO/CEI 8859-15 ou ISO Latin-9 Le deuxième code de la famille ISO 8859 qui peut intéresser les francophones est l’ISO/CEI 8859-15, également appelé le Latin-9 (ou parfois de manière officieuse le Latin-01). Il s’agit d’une légère modification du Latin-1 qui ajoute le symbole monétaire de l’euro, ainsi que quelques lettres accentuées qui manquaient pour le français2 et les mots russes translittérés en finnois et en estonien. L’« Ÿ » ne s’utilise en français que dans de rares mots écrits en capitales : par exemple les communes de MOŸ-DE-L’AISNE, L’HAŸ-LES-ROSES, l’auteur PIERRE LOUŸS ou le nom de l’illustre et ancienne famille de CROŸ. Ce code est destiné aux mêmes langues que le Latin-1. Le tableau 2.5 résume les différences entre le Latin-1 et le Latin-9. Tableau 2.5 – Différences entre l’ISO 8859-1 et l’ISO 8859-15 N° hexa

Latin-1

Nom du caractère Latin-9

Latin-9

A4

¤

symbole euro



A6

¦

lettre majuscule latine s caron

Š

A8

¨

lettre minuscule latine s caron

š

B4

´

lettre majuscule latine z caron

Ž

B8

¸

lettre minuscule latine z caron

ž

BC

¼

digramme soudé majuscule latin oe

Œ

BD

½

digramme soudé minuscule latin oe

œ

BE

¾

lettre majuscule latine y tréma

Ÿ

Il est important de noter que même l’ISO/CEI 8859-15 ne permet pas d’écrire un texte français de qualité typographique. En effet, plusieurs caractères fréquemment utilisés dans les textes français, comme les tirets cadratin (« — ») et demi-cadratin (« – ») , manquent. Le codage suivant essaie de pallier ces lacunes communes aux jeux de caractères codés ISO 8859.

1. Numéro soutenu avec une certaine malice par certains délégués à l’ISO lors des premières ébauches de cette norme, ils l’avaient ainsi surnommée parce qu’elle aurait dû voir le jour avant le Latin-1 mal conçu pour le français. En fin de compte, la norme devint l’alphabet latin n° 9, tout neuf... 2. Voir pourquoi dans Jacques André, ISO Latin-1, norme de codage des caractères européens ? Trois caractères en sont absents, dans Cahier GUTenberg, n° 25, 1996, p. 65-77.

44

2.4

Chapitre 2. Répertoires et jeux de caractères codés

WINDOWS LATIN 1 Microsoft a défini une série de codes similaires à la famille de l’ISO 8859. Sa version de l’alphabet Latin n° 1 est le code Windows Latin 1 également connu sous le nom de Windows-1252. On le désigne aussi sous le nom de CP-1252, CP1252 ou code page 1252. Le terme code page (« page de code ») est le terme utilisé par IBM pour désigner ses jeux de caractères codés propriétaires. Windows Latin 1 diffère de l’ISO 8859-1 par le remplacement des caractères de commande situés dans l’intervalle [0x80-0x9F] par des caractères typographiques et des lettres utiles en Europe occidentale. Windows a publié plusieurs variantes, celle qui est reproduite au tableau 2.6 est la plus récente : elle comprend le symbole de l’euro. Parmi les autres caractères du Windows Latin-1, on retrouve les caractères introduits par le Latin-9. Tableau 2.6 – Différences entre l’ISO 8859-1 et Windows Latin 1 0 8x 9x

1

€ ‘

2

3

4

5

6

7

8

9

A

B

C

D

E



ƒ









ˆ



Š



Œ

Ž













˜



š



œ

ž

F

Ÿ

Il est très fréquent de mal étiqueter — par exemple à l’aide du paramètre charset de HTTP — des données Windows Latin 1 et de les faire passer pour des données en ISO 8859-1. Or l’envoi de caractères de la plage [0x80-0x9F] peut poser problème si le programme qui les reçoit s’attend à recevoir du Latin-1 : celui-ci pourra les ignorer, les transcrire en ce qui semble être des caractères corrects ou, ce qui est plus rare, les traiter comme des caractères de commande. La plupart des navigateurs Internet et des logiciels de messagerie interprètent les caractères de commandes C1 de l’ISO 8859-1 comme des caractères Windows-1252 afin de palier ces erreurs d’étiquetage. On appelle parfois Windows Latin 1 le jeu de caractères ANSI, il s’agit d’une grave erreur. L’ANSI, comme nous l’avons vu précédemment, est l’organisme de normalisation américain. Or celui-ci n’a jamais adopté Windows Latin 1. Microsoft aurait utilisé ce terme, car Windows-1252 s’inspirait à l’origine d’un projet de norme de l’ANSI qui allait devenir l’ISO-8859-1. Le tableau 2.7 décrit les caractères ajoutés par Windows-1252 à l’ISO Latin-1, il fournit également le numéro de caractère Unicode de ces ajouts et le nom ISO 10646 (Unicode) abrégé de ces caractères. Bien que Windows-1252 soit le jeu de caractères le plus riche que nous ayons vu jusqu’à présent, les typographes nous apprennent qu’une écriture alphabétique nécessite près de quatre à cinq cents caractères différents, ce qui est hors de portée des jeux de caractères codés sur 8 bits.

2.4 Windows Latin 1

45

Tableau 2.7 – Caractères ajoutés par Windows Latin 1 à l’ISO 8859-1 N° hexa

Win 1252

N° Unicode

80



U+20AC

82



U+201A

83

ƒ

U+0192

F hameçon

84



U+201E

85

U+2026 U+2020

Obèle

87

… † ‡

Guillemet-virgule double inférieur Points de suspension

U+2021

Double obèle

88

ˆ

U+02C6

89



U+2030

Lettre modificative accent circonflexe Symbole pour mille

8A

Š

U+0160

Majuscule s caron

8B



U+2039

8C

Œ

U+0152

8E

Ž

U+017D

Guillemet simple vers la gauche Digramme soudé majuscule oe Majuscule z caron

91



U+2018

92



U+2019

93



U+201C

94



U+201D

95

U+2022 U+2013

Tiret demi-cadratin

U+2014

Tiret cadratin

U+02DC

Petit tilde

U+2122

Marque de commerce anglaise

9A

• – — ˜ ™ š

Guillemet-apostrophe double culbuté Guillemet-apostrophe double Puce

U+0161

Minuscule s caron

9B



U+203A

9C

œ

U+0153

9E

ž

U+017E

Guillemet simple vers la droite Digramme soudé minuscule oe Minuscule z caron

9F

Ÿ

U+0178

86

96 97 98 99

Nom du caractère abrégé Symbole euro Guillemet-virgule inférieur

Guillemet-apostrophe culbuté Guillemet-apostrophe

Majuscule y tréma

Commentaire

Guillemet ouvrant dans certaines langues. Florin (Pays-Bas), symbole de fonction. Guillemet ouvrant dans certaines langues.

Cette lettre chasse (voir § 5.2, Lettres modificatives). Dans les mesures de salinité, d’alcoolémie. Tchèque, estonien, finnois, slovaque, etc.

E dans o (français). Tchèque, estonien, finnois, slovaque, etc.

Préconisé pour représenter l’apostrophe.

Ce caractère chasse.

Guillemet fermant dans certaines langues. E dans o (français). Tchèque, estonien, finnois, slovaque, etc. Français (L’HAŸ-LES-ROSES), igbo.

46

2.5

Chapitre 2. Répertoires et jeux de caractères codés

EBCDIC En 1964, IBM a conçu et lancé son propre jeu de caractères codés appelé EBCDIC (Extended Binary Coded Decimal Interchange Code) pour ses ordinateurs de la série 360. Le répertoire des caractères à l’origine était identique à celui de l’ASCII, mais le codage en différait : les signes ne se voyaient pas affecter les mêmes numéros et l’EBCDIC a été prévu comme un codage sur 8 bits dès l’origine. Ce jeu de caractères codés est toujours utilisé par IBM. Au fil des années, IBM a défini plus de cinquante variantes de l’EBCDIC afin de satisfaire chacun des marchés qu’il ciblait. Ces variantes laissaient intactes les lettres non accentuées de l’EBCDIC originel et les chiffres tout en ajoutant des caractères dits « nationaux » de façon parfois déroutante. C’est ainsi que la version belge (CP 274) avait un répertoire identique à la version française précédant l’introduction de l’euro (CP 297), si ce n’est pour huit signes1 dont les positions étaient interverties ! Le tableau 2.8 illustre la dernière version française de l’EBCDIC qui comprend l’euro. Il existe un jeu de caractères inspiré de l’EBCDIC destiné au japonais qui ne conserve toutefois pas toutes les lettres originelles. Il s’agit de l’EBCDIK qui élimine les lettres latines minuscules et ajoute les katakanas de demi-chasse. C’est-à-dire les signes d’un des deux syllabaires japonais2 utilisés habituellement pour transcrire les mots étrangers (européens ou chinois) qui, à l’affichage, n’occupent que la moitié de la place prise par un idéogramme. Tableau 2.8 – Version française de l’EBCDIC (CP 1147) 0 4x

1



2

3

4

5

6

7

8

9

A

B

C

D

E

F

¤

¦

#

£

¥

§

?

³

r











5x



^

¬

­

`

¯

°

±

®

¡

i







A

6x





„

†

‚

ƒ

…

‡

‰

“

»





B

!

"

7x

º

‹

Œ



Š





‘

Ž

w



e

¢



8x

š

D

E

F

G

H

I

J

K

L

m

}

²

¿

À

s

9x

>

M

N

O

P

Q

R

S

T

U

l

|

¨

z

ˆ



Ax

C

j

V

W

X

Y

Z

[

\

]

c



’

Ÿ

 

p

Bx

d



g

y

k

@

x

~



€

n

|

q

a

v

™

Cx

«

$

%

&

'

(

)

*

+

,



¸

´

µ

·

Dx

ª

-

.

/

0

1

2

3

4

5

 ¹

½

¾

h

¼

Á

Ex

©

¹

6

7

8

9

:

;


signe supérieur à dont la pointe indique toujours le côté le plus petit. Pour conserver cette propriété, il faut inverser le glyphe qui correspond à ce caractère quand il est utilisé dans un contexte droite-àgauche. C’est ainsi que « a > b » s’écrit « ‫ » ﺍ < ﺏ‬en arabe où « ‫ » ﺍ‬représente le « a » et « ‫ » ﺏ‬le « b ». La propriété binaire normative Réflexion bidi ?(« Bidi Mirrored »), affichée dans BabelMap, indique si le caractère en question doit être réfléchi à l’affichage dans un contexte droite-à-gauche. La base de données d’Unicode précise également une autre propriété, informative cette fois-ci à l’aide du fichier « BidiMirroring.txt ». Cette propriété propose un caractère dont le glyphe pourrait servir à afficher le glyphe miroir d’un autre caractère dans un contexte droite-à-gauche. Les lignes suivantes, extraites du fichier Unicode, « BidiMirroring.txt1 », indiquent qu’un « ] » peut être utilisé pour afficher un « [« et vice-versa : 005B; 005D # LEFT SQUARE BRACKET 005D; 005B # RIGHT SQUARE BRACKET

4.2.7

Classes de coupure de lignes La dernière propriété fondamentale des caractères Unicode sur laquelle nous allons nous pencher ici est celle liée à la coupure de lignes. Il s’agit d’un ensemble de classes qui sont utilisées par l’algorithme de coupure de lignes d’Unicode (UAX n° 142). Le tableau 4.4 énumère quelques-unes des plus importantes classes de coupure de lignes pour les textes non CJC. Tableau 4.4 – Quelques classes de coupure de lignes Symbole

Signification

Exemples

BK

Coupure forcée (obligatoire)

(séparateur de lignes) et (séparateur de paragraphes)

CL

Ponctuation fermante

), ], }

CR

Retour chariot

U+000D

EX

Exclamation, interrogation

!, ?

IS

Séparateur infixe

, (virgule), : (deux-points)

LF

Passage à la ligne

U+000A

1. Ce fichier se trouve ici : . 2. Consultable ici . Une UAX est une Annexe au standard Unicode (« Unicode Standard Annex »), elle fait partie intégrante du standard Unicode.

4.2 Propriétés des caractères

97

Symbole

Signification

Exemples

NL

Ligne suivante

U+0085

SP

Espace

U+0020

SY

Symbole sécable

/

ZW

Espace à chasse nulle

U+200B (espace sans chasse)

L’UAX n° 14 définit ensuite une série de règles qui définissent les points de coupe permis ou interdits entre deux classes de caractères. Certaines de ces règles peuvent être ignorées ou personnalisées d’autres sont obligatoires. Chaque règle a un numéro. Celle reproduite ci-après est la règle LB4. Chaque règle est décrite à l’aide des classes de coupure de lignes et d’un opérateur (l’opérateur « ! » ici indique l’obligation de couper la ligne), enfin elle est accompagnée d’une description en langage naturel. LB 4 Toujours couper après une coupure forcée (mais jamais entre CR et LF). BK !

Les règles de l’UAX n° 14 utilisent trois opérateurs (tableau 4.5). Tableau 4.5 – Opérateurs utilisés dans les règles de coupure de lignes

! Coupure obligatoire à la position précisée × Coupure interdite à la position précisée ÷ Coupure permise à la position précisée On applique les règles dans l’ordre de leur définition (à savoir LB5 avant LB6). Dès qu’une règle est satisfaite, le processus s’arrête. On trouvera ci-après quelques règles typiques définies par Unicode, les douze premières (LB1 à LB12) ne peuvent pas être modifiées, à partir de la règle LB13 il est permis de remplacer la règle en fonction de la culture visée et de l’application qui met en œuvre l’UAX 14. LB 5 Traiter CR suivi de LF, ainsi que CR, LF et NL comme une coupe obligatoire CR × LF CR ! LF ! NL ! LB 6 Ne pas couper avant un passage à la ligne obligatoire × ( BK | CR | LF | NL ) […] // fin des règles non personnalisables, LB13 est personnalisable LB 13 Ne pas couper avant «]» ni «!» ni «;» ni «/», même après des espaces × CL × EX × IS × SY

98

Chapitre 4. Modèle de codage, propriétés des caractères et tri

Il est utile de rappeler qu’il existe une multitude de façons de couper des lignes et qu’il n’est pas obligatoire d’utiliser l’algorithme de coupure de lignes proposé par Unicode. Toutefois, certains caractères existent uniquement ou principalement dans Unicode pour permettre de maîtriser la coupure de lignes (les espaces sécable et insécable ainsi que le trait d’union conditionnel viennent tout de suite à l’esprit) et leur sémantique ne peut être modifiée. Le sous-ensemble de règles non personnalisables de l’algorithme de coupure de lignes d’Unicode exprime de façon rigoureuse le comportement, entre autres, des caractères Unicode qui régissent la coupure de lignes dont nous parlions précédemment et dont on trouve une description plus longue dans le § 6.5, Caractères de coupure de lignes. L’algorithme a été soigneusement conçu pour fournir des points de coupure raisonnables dans les situations ordinaires. Toutefois, la coupure de mot n’est pas prise en charge. De même, les écritures d’Asie du Sud-Est (le thaï, le lao, etc.) qui n’utilisent pas d’espace entre les mots nécessitent l’utilisation d’un dictionnaire pour mettre en œuvre la coupure de lignes et leur coupure de lignes n’est pas non plus prise en charge par l’UAX n° 14. En cela, la coupure de lignes thaïe est semblable à la coupure de mot qui, dans de nombreuses langues, comme l’anglais et l’allemand, requiert également la consultation d’un dictionnaire. Des bibliothèques comme ICU, disponible en Java et C/C++, dont nous reparlerons au chapitre 12 consacré à l’internationalisation, mettent en œuvre l’algorithme de l’UAX n° 14. Nous ne pensons donc pas — étant donné le format réduit de ce livre — qu’il vaille la peine de passer en revue ici, en plus de détails, les règles de l’UAX nº 14, il vaut sans doute mieux décrire les résultats de cet algorithme pour en comprendre le fonctionnement de manière intuitive et en connaître certaines limitations.

Limitations de l’algorithme de coupure de lignes Comme nous l’avons mentionné précédemment, l’algorithme de coupures de ligne Unicode, grâce aux classes de coupure de lignes, fournit le plus souvent des résultats parfaitement raisonnables. Prenons un exemple simple. Nous représenterons ici les points de coupe potentiels fournis par l’UAX nº 14 par des barres verticales « | ». |Il |y |a |vingt-|quatre |heures |dans |une |journée.| On remarque que l’algorithme nous indique que l’on peut couper la ligne en début et en fin de texte ainsi qu’après chaque blanc et le trait d’union. Jusqu’ici tout va bien. Prenons maintenant un autre exemple : |Le |fichier |est |dans |le |répertoire /|usr/|~pandries.| Ici les choses vont déjà moins bien : l’algorithme ne permet pas (par défaut) de couper avant le premier « / » du nom du répertoire, alors qu’il s’y trouve un blanc pourtant parfaitement adéquat. Si vous consultez la règle LB 13 reproduite précédemment, vous remarquerez qu’elle dit « × SY » ce qui se lit « pas de coupure avant la classe SY », classe qui comprend la barre oblique. Heureusement, cette règle peut être modifiée. Une adaptation simple consisterait à toujours permettre la coupe

4.2 Propriétés des caractères

99

après une espace sécable et à plutôt forcer l’utilisation de l’espace insécable quand on veut absolument empêcher la coupe devant la barre oblique précédée d’un blanc. Notons enfin que l’algorithme est insuffisant pour mettre en œuvre la coupure de lignes qui respecterait les règles de la typographie française professionnelle. Voyons ce dernier exemple : |Finira-|t-|on |par |savoir |que |a/|s |c’est-|à-|dire |« aux |soins |de » |ne |doit |pas |être |coupé ?| Trois points de coupe ne sont pas légitimes selon les guides typographiques francophones :

• On sépare les verbes accompagnés d’un t euphonique avant cette lettre et non après, on devrait donc n’avoir qu’un seul point de coupe dans « Finira-|t-on »1.

• Selon le même principe, « c’est-à-dire » se divise « c’est-|à-dire » pour éviter la proximité des deux traits d’union en fin de ligne.

• On ne peut séparer les lettres abréviatives successives2, on ne peut donc couper « a/s » et les coupures ne peuvent que l’entourer : « |a/s| ».

4.2.8

Coupure de lignes et segmentation de texte Il est important de ne pas confondre la coupure de lignes que nous avons abordée précédemment et la segmentation de texte en unités « logiques » comme le graphème (« le caractère comme le perçoit l’utilisateur »), le mot et la phrase (tableau 4.6). Si l’UAX n° 14 définit des règles de coupure de lignes, il revient à l’UAX n° 29 de définir des directives de segmentation en graphèmes, mots et phrases. Tableau 4.6 – Types de segment Graphèmes

a, ch (en slovaque), kw, â

Mots

aujourd’hui, serpents, en-tête

Phrase

Pour qui sont ces serpents qui sifflent sur vos têtes ?

Ces unités s’avèrent utiles dans différentes applications, notamment le traitement de texte pour :

• Situer le début et la fin du mot que l’utilisateur vient de sélectionner. • Compter le nombre de graphèmes (ou de caractères), de mots ou de phrases. • Déterminer jusqu’où se déplacer dans le texte stocké en mémoire quand l’utilisateur appuie sur la touche « flèche » pour avancer ou reculer d’un graphème.

• Dresser la liste des différents mots d’un texte. • Mettre en majuscule la première lettre de chaque mot, etc. 1. § 706 du Guide du typographe (romand), Lausanne, 2000. 2. § 708 du Guide du typographe (romand), Lausanne, 2000.

100

Chapitre 4. Modèle de codage, propriétés des caractères et tri

Il est très important de distinguer coupure de lignes et frontière de mot :

• Points de coupure de lignes : |Ces |chefs-|d’œuvre |sont-|ils |visibles |ce |soir ?| • Frontières de mot : |Ces| |chefs-d’œuvre| |sont|-|ils| |visibles| |ce| |soir| ? Les directives proposées par Unicode en matière de segmentation de textes sont, une fois de plus, des approximations efficaces qui peuvent — et souvent devraient — être modifiées pour une langue ou un environnement particulier. Toutefois, ces directives sont très utiles car elles définissent une manière raisonnable et rapide de découper les textes Unicode dont le répertoire, rappelons-le, comprend environ 100 000 caractères ! L’accès à ces fonctionnalités de segmentation est rendue possible grâce des blibliothèques en Java et ICU, il s’agit des BreakIterator (voir § 12.7.1, La classe BreakIterator). Enfin, il existe une catégorie de coupure qu’Unicode ne définit pas : la coupure de mot (la division de mot) en dehors du respect du trait d’union conditionnel (voir § 6.1.12, Trait d’union conditionnel). Il revient à un protocole de haut niveau de définir les divisions à l’intérieur des mots et d’insérer, par exemple, des traits d’union conditionnels dans le texte aux endroits où cette division de mot est permise. En français, cette « syllabation graphique », comme la nomme le Grevisse, est en grande partie algorithmique ; toutefois dans de nombreuses langues, cette division suit des principes étymologiques qui nécessitent un dictionnaire. C’est le cas de l’allemand qui réprouve pour le mot « Fluchtorte » (les refuges) la division « Fluch-torte » (le gâteau-blasphème) et lui préfère la version plus étymologique de « Flucht-orte » (les lieux de fuite). Rappelons qu’en anglais on divise, par exemple, le mot « record » différemment selon qu’il s’agit d’un nom (« rec-ord ») ou d’un verbe (« re-cord »).

4.2.9

Cohérence des propriétés Le standard Unicode est le fruit de nombreux compromis. Il doit concilier l’uniformité de traitement de caractères similaires et la compatibilité par rapport à la manière dont les caractères hérités de codages préexistants sont utilisés dans ces anciens jeux de caractères. Il doit aussi concilier parfois les avis très tranchés des délégués participant aux comités de normalisation. Ce tour d’équilibriste entraîne, on le comprend, quelques anomalies dans les propriétés de caractère. Ainsi, certaines paires de caractères auraient-elles pu être considérées comme canoniquement équivalentes, mais on les a laissées distinctes pour des raisons de compatibilité avec des normes qui les considéraient comme telles. C’est le cas de l’U+00B5 µ symbole micro (à distinguer de U+03BC µ lettre minuscule grecque mu) placé par Unicode dans la catégorie générale « Ll » (lettre minuscule) alors qu’il s’agit ici d’un symbole. Autre singularité : le U+00B5 ˜ symbole micro a une correspondance de compatibilité vers U+03BC Ο lettre minuscule grecque mu, alors qu’U+2126 Ω symbole ohm a une correspondance canonique vers U+03A9 Ω lettre majuscule grecque oméga, bien qu’il s’agisse dans les deux cas de symboles techniques issus de lettres grecques.

4.3 Formes normalisées

4.3

101

FORMES NORMALISÉES Afin de garantir une compatibilité aller-retour entre les normes préexistantes et Unicode, ce dernier définit parfois plusieurs caractères qui correspondent à des entités qui ne sont que des variantes visuelles (« glyphiques ») d’un même caractère. Unicode prévoit pour ces caractères des équivalences dites de compatibilité. L’apparence de ces caractères étant quelque peu différente, les remplacer par un autre caractère entraîne, en l’absence de balisage supplémentaire, une perte potentielle d’information de formatage. Le ml disposé en carré – ≱(U+3396) – est une variante de compatibilité de m (U+006D) suivi de ℓ minuscule l de ronde (U+2113). Unicode, rappelons-le (voir §3.4.8, Composition dynamique), définit également des correspondances canoniques entre les caractères qui sont considérés comme strictement identiques (et qui ne diffèrent donc même pas au niveau visuel). É (U+00C9) est une variante canonique de E (U+0045) + ́ (U+0301). Unicode précise à partir de ces deux types d’équivalence deux formes de décomposition des caractères nécessaires quand on désire comparer des chaînes de caractères :

• La décomposition canonique d’un caractère est réversible et n’entraîne aucune perte d’information. Elle peut donc être utilisée dans l’échange normalisé de textes. En effet, cette forme permet d’effectuer une comparaison numérique (binaire) tout en conservant une équivalence canonique avec le texte non normalisé d’origine. La décomposition canonique d’une chaîne de caractères est la transposition successive et récursive de chaque caractère par sa valeur canonique correspondante jusqu’à ce que ces transpositions renvoient vers elles-mêmes, suivie de sa mise en ordre canonique.

• La décomposition de compatibilité permet d’effectuer une comparaison numérique (binaire) tout en conservant cette fois-ci une équivalence de compatibilité avec le texte non normalisé d’origine. Cette dernière forme peut s’avérer utile en maintes occasions puisqu’elle permet d’éliminer des différences qui ne sont pas toujours pertinentes. Les caractères katakana à pleine chasse et à demi-chasse ont les mêmes décompositions de compatibilité et sont donc compatibles ; ils ne sont toutefois pas canoniquement équivalents puisque leurs chasses diffèrent. La décomposition de compatibilité d’une chaîne de caractères est la transposition successive et récursive de chaque caractère par sa valeur canonique et de compatibilité correspondante jusqu’à ce que ces transpositions renvoient vers elles-mêmes, suivie de sa mise en ordre canonique. Ces deux formes transposent les caractères vers des caractères décomposés. Il existe également des formes de normalisation qui transposent les caractères vers des caractères composés (s’ils existent). Pour ce faire, il suffit de faire suivre les deux formes de décompositions introduites précédemment d’une composition canonique (E + ́ est donc transposé vers É).

102

Chapitre 4. Modèle de codage, propriétés des caractères et tri

En faisant suivre ou non les deux formes de décomposition par une composition canonique, on obtient un total de quatre formes de normalisation. Ces quatre formes portent un nom (tableau 4.7). Les deux formes normalisées vers les caractères composés se nomment C et KC. Le résultat de l’une est l’équivalent canonique du texte d’origine, le résultat de l’autre est son équivalent de compatibilité. Le K de KD et de KC représente le mot compatibilité (suggéré par l’allemand kompatibel) alors que le C renvoie aux deux C de composition canonique. Le D, lui, se réfère à la décomposition. Tableau 4.7 – Les quatre formes de normalisation

Décomposition canonique Décomposition de compatibilité

Sans composition canonique

Suivie d’une composition canonique

D

C

KD

KC

Les programmes doivent toujours considérer comme égales des chaînes Unicode qui sont canoniquement équivalentes. Une des façons les plus simples de s’en assurer est de normaliser toutes les chaînes de caractères, car si les chaînes sont normalisées leurs formes canoniques (C ou D) ont alors exactement la même représentation binaire. La forme de normalisation à utiliser dépend de l’application et de la plateforme en question. La forme la plus fréquente est la forme C car cette forme canonique recomposée est compacte et d’ordinaire compatible avec les jeux de caractères préexistants1, c’est d’ailleurs la forme choisie par le W3C pour les standards du Web. Les autres formes s’avèrent utiles dans d’autres contextes de comparaison textuelle. Le tableau 4.8 illustre les formes normalisées de la chaîne « affligé » dont on a codé le ffl sous la forme d’une ligature assez commune2. Tableau 4.8 – Formes normalisées d’« affligé » Nom

Chaîne normalisée

D

a + ffl + i+ g + e + ́

C

a + ffl + i+ g + é

KD

a + f +f + l + i+ g + e + ́

KC

a + f +f + l + i+ g + é

1. Par exemple le Windows 1252 utilisé par défaut sur les plateformes Windows francophones pour stocker les données. 2. Cette ligature est un caractère de compatibilité inclus à des fins de transcodage, Unicode recommande de l’éviter. Ceci ne signifie pas bien sûr qu’une police OpenType ne pourra pas afficher cette ligature en tant que glyphe.

4.3 Formes normalisées

4.3.1

103

La concaténation n’est pas fermée La concaténation des chaînes n’est fermée dans aucune des formes de normalisation. Ceci signifie que la concaténation de deux chaînes normalisées ne fournit pas nécessairement une chaîne normalisée. Considérons les exemples du tableau 4.9. Tableau 4.9 – La concaténation n’est pas fermée Forme Chaîne 1

C

e

D

e+ ̂

Chaîne 2

Concaténation

̂ ̣ (point souscrit)

Normalisation correcte

e+̂

ê

e+̂+̣

e+̣+ ̂

À moins de limiter le répertoire, il est impossible de concevoir une forme de normalisation dans laquelle la concaténation simple soit fermée. Au besoin, on peut cependant écrire une fonction spécialisée qui produit une concaténation normalisée. Par contre, la sélection de sous-chaînes est fermée dans l’ensemble des chaînes normalisées, quelle que soit la forme de normalisation utilisée.

4.3.2

Formes de normalisation et base de données Les formes de normalisation Unicode jouent un rôle primordial dans les bases de données et d’autres systèmes de gestion de documents. En effet, les bases de données possèdent des index utilisés pour accélérer grandement l’accès à ces données. Pour être valables, ces index doivent renvoyer à des données bien formées ; ceci signifie notamment que des chaînes équivalentes (en termes de normalisation des données) doivent apparaître au même endroit dans l’index. C’est ainsi qu’un « é », par exemple, doit être considéré égal à la suite de caractères « e + ́ ». Les requêtes structurées d’une base de données sont également optimisées à l’aide d’algorithmes complexes afin de regrouper plus rapidement des données provenant de dizaines, parfois de centaines, de tables. Ces optimisations supposent également que les données sont bien formées. Les formes de normalisation sont le mécanisme qui permet à ces méthodes de fonctionner correctement.

4.3.3

Stabilité des formes normalisées Il est crucial que les formes de normalisation demeurent stables. Ceci signifie que, si une chaîne Unicode est normalisée dans une forme précisée (C, D, KC, KD) pour une version Unicode donnée, elle doit le demeurer pour toutes les versions ultérieures d’Unicode. En d’autres termes, si l’on prend l’exemple d’un identificateur normalisé sous une des quatre formes Unicode, on est assuré que la même normalisation de cet identificateur produira le même résultat quelle que soit la version Unicode à venir.

104

Chapitre 4. Modèle de codage, propriétés des caractères et tri

Cette stabilité ne s’applique, toutefois, qu’aux chaînes de caractères Unicode qui ne comprennent que des positions de code affectées à des caractères. En effet, si une chaîne Unicode comprenait des positions non affectées lors de sa normalisation, la normalisation de celle-ci pourrait être différente dans une version ultérieure d’Unicode, une fois un caractère affecté à une ou plusieurs de ces positions à l’origine libres. Pour s’assurer de cette exigence, Unicode définit une version d’Unicode qui sert de base. Il s’agit de la version 3.1.0 de la base de données Unicode. Voyons les effets de cette politique de stabilité et supposons qu’une prochaine version d’Unicode ajoute un caractère précomposé Q-caron. Les chaînes de caractères normalisées sous la forme C ou KC et qui contenaient Q suivi d’un caron n’utiliseront pas le caractère Q-caron puisqu’il n’existait pas de composition canonique vers Q-caron définie dans la version de composition de référence (Unicode 3.1.0). Bien qu’il soit possible d’ajouter de nouvelles compositions canoniques dans des versions ultérieures d’Unicode pour autant qu’elles respectent l’exigence de compatibilité en amont, Unicode décourage fortement la codification de nouvelles lettres composées même dans ce cas.

4.3.4

Invariance des caractères latins de base Les lettres latines correspondant à l’ASCII sont dépourvues de toute décomposition et aucune suite de caractères ne contenant que ces lettres latines de base ne peut faire partie d’une composition. Ceci signifie, par exemple, que les mots réservés d’un langage qui n’utilise que ces caractères ASCII demeurent inchangés même si le texte qui les contient est normalisé. C’est la raison pour laquelle, par exemple, l’accent circonflexe ASCII (qui chasse) n’a pas de correspondance vers un espace suivi d’un diacritique accent circonflexe (U+0302), bien que cette correspondance existe pour le tréma (U+00A8) qui ne fait pas partie du bloc de base [00..7F]. Sans cette restriction, des langages historiques qui n’acceptent que l’ASCII dans leur syntaxe ne pourraient analyser correctement des expressions comme « A^2 » après leur normalisation selon la forme KC puisque l’opérateur « ^ » deviendrait un espace suivi d’un diacritique non ASCII !

4.3.5

Compositions exclues Quatre classes de caractère sont exclues de toute composition lors de la normalisation. Ils sont énumérés dans le fichier CompositionExclusions.txt de la base de données Unicode. On les classe ainsi :

• Les caractères précomposés qui ne constituent pas généralement les formes privilégiées d’une écriture particulière. Il s’agit surtout de caractères des écritures de la péninsule indienne et de l’hébreu.

• Les caractères précomposés rajoutés après la version 3.0 d’Unicode. Pour des raisons de stabilité, ces caractères sont exclus de toute composition. On en

4.4 Le tri et le repérage

105

compte 14 aujourd’hui, principalement des symboles musicaux. Si ces caractères n’étaient pas exclus de nouvelles compositions canoniques, on pourrait prendre un fichier créé et normalisé sous la forme C à l’époque d’Unicode 3.0 (ou une version antérieure), le reconvertir aujourd’hui sous la forme normalisée C avec des compositions supplémentaires et obtenir un résultat différent ! Ce qui est bien sûr contraire à l’idée même de la normalisation dont le but est que deux chaînes équivalentes aient une représentation normalisée identique.

• Les singletons, ces caractères précomposés dont la décomposition consiste en un seul caractère (par exemple, le symbole U+212A K symbole kelvin qui a comme décomposition canonique le K majuscule habituel U+004B). Ces singletons représentent des doublons introduits dans Unicode pour des raisons de compatibilité avec des jeux de caractères historiques (qui contenaient euxmêmes ces doublons). En les excluant de la composition, on décourage dans les faits leur utilisation puisqu’ils disparaissent des chaînes composées lors de la normalisation. Il existe actuellement près de 1 000 singletons dans Unicode ; la grande majorité est formée de caractères CJC.

• Les décompositions sans tête, à savoir les caractères dont la décomposition canonique commence par un caractère dont la classe combinatoire n’est pas zéro, il s’agit donc de diacritiques. On cherche de la sorte à incorporer ces diacritiques dans une forme précomposée qui comprend le caractère de base (c’est l’idée de la composition après tout !) plutôt qu’à composer des diacritiques multiples précomposés (ces décompositions sans tête). Il n’existe que quatre caractères dans cette classe pour l’instant. U+0344 ̈́ diacritique grec tréma accent est le cas le plus connu. Attention — S’il est vrai que la forme C compose habituellement des lettres auxquelles se joignent des diacritiques. Il arrive que la forme C rallonge le texte : ‫( שׁ‬U+FB2A) a comme forme C ‫( ש‬U+05E9) + ׁ (U+05C1). Cette particularité s’explique par le fait que U+FB2A est une composition exclue et qu’il n’existe pas d’autre forme précomposée du chine (schin) à point chine (schin). Si vous désirez voir comment des chaînes Unicode sont transformées sous les quatre formes de normalisation, le formulaire suivant pourrait vous intéresser : .

4.4

LE TRI ET LE REPÉRAGE Le tri et le repérage se recoupent, car tous deux mettent en œuvre des degrés d’équivalence entre des termes à comparer. Dans le cas du repérage, l’équivalence définit la correspondance entre deux termes. Pour le tri, l’équivalence définit la proximité des termes d’une liste triée. Il faut distinguer deux types de comparaison : la comparaison binaire et la comparaison lexicographique. On utilise la comparaison et le tri lexicographiques (ou du dictionnaire) quand on affiche des résultats aux utilisateurs, car leurs résultats sont assez différents de ceux de leur

106

Chapitre 4. Modèle de codage, propriétés des caractères et tri

contrepartie binaire. En outre, les versions lexicographiques doivent s’adapter à la tradition lexicographique des utilisateurs. Cette tradition peut varier d’une culture à l’autre : on ne trie pas de la même manière en suédois qu’en allemand. Nous y reviendrons.

4.4.1

Tri et comparaison binaires Dans le cas binaire, on recherche une manière rapide et simple d’ordonner des résultats de manière bien définie. Les différentes formes transformées d’Unicode (UTF-8, UTF-16, UTF-32) ne trient pas de la même manière en binaire. S’il est vrai que l’UTF-8, l’UTF-16 sans seizet d’indirection et l’UTF-32 trient les données de la même manière, c’est-à-dire dans l’ordre des numéros de caractères, il n’en va pas de même dès que l’UTF-16 utilise des seizets d’indirection. En effet les caractères auxquels se réfèrent ces seizets auront tous une valeur supérieure au plus grand des caractères du PMB alors qu’ils seront triés avant les caractères du PMB qui ont une valeur supérieure à 0xDFFF, la limite supérieure des seizets d’indirection. On pourrait donc trouver dans les résultats d’un tri binaire opérant sur des caractères UTF-16 des caractères musicaux [1D100..1D1FF] triés avant les caractères de la zone à usage privé [E000..F8FF] ou des idéogrammes de compatibilité CJC [F900..FAFF], etc.

4.4.2

Tri et comparaison lexicographiques Les équivalences utilisées dans le cas du tri ou de la comparaison lexicographique — grosso modo celle d’un dictionnaire — dépendent toujours de l’application considérée et de la langue. En effet, si l’allemand trie le « Ä » au début de l’alphabet, le suédois le trie après Z. Au sein d’une même langue, on n’ordonne pas toujours les chaînes de la même manière (il suffit de penser à l’ordre des chiffres et des noms propres dont les formes voisines sont regroupées dans un annuaire téléphonique). Toute norme de tri se doit de prendre en compte cette grande variabilité.

4.4.3

Ça ne peut quand même pas être si compliqué ? On pourrait penser que le tri est une chose simple et que de composer, par exemple, un annuaire téléphonique serait chose aisée. Et pourtant ! Le Soleil de Québec rapportait le 18 décembre 2003 que l’annuaire téléphonique produit par une société locale (TELUS) triait Dubé après Dubuisson et Bédard après Bzdera... Embarras de ladite société et plus de 300 000 annuaires au pilon ! On imagine ce qui a pu se passer : on a simplement trié les noms sur leurs valeurs binaires, or « é » a une valeur supérieure à toutes les lettres non accentuées. D’ailleurs, on peut dire que quelle que soit la langue, on s’assure en utilisant un tri binaire de livrer des résultats erronés. Car même en anglais (que l’on pourrait naïvement croire facile à trier), le tri lexicographique présente des complications. Prenons cette table triée en ordre binaire :

4.4 Le tri et le repérage

107

Co-op Co-star Container Coop Copenhagen O’Connor Oberst Van Damme Vandenberg Vice versa Vice-president van der Haal On se rend bien compte que cet ordre n’est pas du tout intuitif : coop et co-op doivent se trier à des positions proches l’une de l’autre, mais pas identiques (« coop » est une cage à poule et non une coopérative). Pourquoi tous les noms en « van » ne sont-ils pas triés ensemble ? Pourquoi O’Connor précède-t-il Oberst ? Un tri lexicographique correct de l’anglais arrangerait sans doute ces noms dans l’ordre suivant : Container Coop Co-op Copenhagen Co-star Oberst O’Connor Van Damme Vandenberg van der Haal Vice-president Vice versa On voit ici que les différences liées à l’insertion d’espace, de trait d’union, d’apostrophe et même de casse1 sont moins importantes, dans le tri lexicographique, que celles incarnées par les lettres de base.

4.4.4

La solution – un tri à quatre niveaux C’est le constat que certaines différences sont moins importantes que d’autres qui a conduit plusieurs chercheurs2 et normalisateurs à proposer, indépendamment l’un de 1. Il ne faut pas croire que cela ne se présente que lorsqu’on trie des noms propres. Un prie-Dieu avec sa majuscule (et son trait d’union) se trie bien entre « priapée » et « prier ». 2. Mark Davis chez Apple en 1983 et Alain Labonté auteur de la norme canadienne CAN/CSA Z243.4.1 basée sur ses travaux antérieurs.

108

Chapitre 4. Modèle de codage, propriétés des caractères et tri

l’autre, un modèle de tri à plusieurs niveaux. L’ISO/CEI 146511 utilise ce modèle. L’algorithme de tri Unicode (UCA) a adopté par la suite la solution proposée par l’ISO en la complétant. Les quatre niveaux proposés par l’ISO/CEI 14651 sont les suivants : Lettre de base > accent > casse > caractères spéciaux. Ce qui se lit de la façon suivante : les lettres de base sont plus importantes que les accents que portent ces lettres, ces accents sont plus importants que la casse des lettres en question. Les caractères comme le trait d’union, l’espace ou l’apostrophe, ou tout autre caractère spécial inclus dans une chaîne de caractères sont considérés au quatrième niveau quand toutes les chaînes sont égales aux trois premiers niveaux. Enfin, en cas d’égalité stricte aux quatre premiers niveaux, il est possible de départager les caractères grâce à leur numéro binaire ou à une autre convention indépendante du codage. Le tableau 4.10 fournit quelques exemples. Tableau 4.10 – Les quatre niveaux de tri Niveau

Description

Exemples

1

Caractère de base

e Espacement > Échelle. Sous Word 2007, Ctrl-D (ou bien Accueil > bouton lanceur de la boîte de dialogue Police), onglet Espacement des caractères > Échelle. Ensuite, choisir un facteur de réduction de l’espace insécable pour en faire une espace fine, disons 50 %, et cliquer sur OK. Maintenant que nous avons une espace fine insécable, nous allons l’utiliser dans la fonctionnalité de remplacement automatique de MS Word 20031 : Outils > Options de correction automatique… > (Onglet) Correction automatique. Si l’espace insécable réduite est toujours sélectionnée, elle est copiée dans la boîte de droite (Par), elle est pour l’instant invisible. Cocher l’option Texte mis en forme, l’espace fine apparaît alors sous la forme d’un « ° » comprimé. Dans la boîte Remplacer, saisir une suite de caractères rarement utilisés ensemble, mais facilement accessibles à l’aide votre clavier (« ££ », « ¦¦ », « || », etc.). Cliquer ensuite sur Ajouter et puis sur OK. Voilà le tour est joué ! Essayez et imprimez le résultat pour voir s’il est satisfaisant (peut-être voudrez-vous changer le facteur de réduction, car 50 % peut ne pas donner un bon résultat).

Réduire automatiquement l’espacement devant la ponctuation haute On peut appliquer le même principe pour modifier automatiquement l’espacement de tous les signes de ponctuation haute (« ! », « ? », « ; »). Dans ce cas, il faut d’abord saisir l’espace insécable et un signe de ponctuation haute, réduire uniquement la taille de l’espace insécable et puis sélectionner à la fois cette espace réduite et son signe de 1. L’accès à la même fonctionnalité est différent dans Word 2007. Il faut alors cliquer sur le bouton Microsoft Office puis cliquer sur Options Word > Vérification et Options de correction automatique.

148

Chapitre 6. Ponctuation

ponctuation haut avant de passer à Options de correction automatique… Et ici, à nouveau cocher l’option Texte mis en forme et remplacer le signe de ponctuation haute seul, par la sélection (l’espace réduite et ce même signe). Ce n’est pas tout. Il faut également s’assurer de mettre hors fonction l’outil de correction automatique de MS Word qui insère des espaces autour des signes de ponctuation. Pour cela, il faut aller dans Options de correction automatique… > (Onglet) Lors de la frappe et s’assurer que la case Guillemets «» par des guillemets « » n’est pas cochée, elle l’est à l’installation de MS Word. En effet, quand cette option est cochée et que le texte que vous saisissez est du français1, Word insère automatiquement des espaces insécables normales — non fines — devant les signes de ponctuation haute même si cette option ne mentionne que les guillemets dans son libellé.

Insérer l’espace fine insécable dans HTML+CSS Il existe deux manières d’obtenir l’effet d’une espace fine insécable à l’aide de balisage en HTML+CSS : utiliser une espace insécable normale et réduire sa chasse ou utiliser une espace fine sécable et la rendre sécable. L’espace insécable normale vaut en règle générale un tiers de cadratin (0,33 em) et l’espace insécable fine un quart (0,25 em), parfois légèrement moins. Dans les exemples suivants nous diminuerons donc la chasse de l’espace insécable normale de 0,08 em : fine ?

ou xxx ?

ou xxx ?

La seconde option de cette alternative consiste à rendre insécable l’espace fine sécable standard. Pour les applications qui mettent en œuvre l’UAX n° 14 (voir § 4.2.7, Classes de coupure de ligne) — comme Microsoft Explorer 7 — ceci n’est pas nécessaire devant la ponctuation haute française, mais cela le devient devant l’appel à une note ou comme séparateur de milliers si on ne se contente pas de l’espace insécable habituel. Pour rendre insécable l’espace fine on pourra faire comme suit : 100 000

ou, mais la balise n’est pas standard, 100 000

1. Soit parce que vous avez précisé cette langue manuellement ou laissé Word la détecter automatiquement. Voir, sous Word 2003, la boîte de dialogue sous Outils > Langue > Langue. Dans Word 2007, Révision > groupe Vérification (à gauche) > icône globe terrestre avec une coche rouge.

6.3 Espaces

149

La première méthode — celle qui modifie letter-spacing — est plus universelle, car l’espace insécable standard est mieux pris en charge dans les navigateurs que l’espace fine sécable. La version 6 de l’explorateur Internet de Microsoft affiche, par exemple, un carré à la place d’une espace fine. Toutefois, ce problème semble être résolu dans la version 7 de MSIE où une espace insécable de bonne chasse (0,25 cadratin) apparaît même quand la police courante ne comprend pas de glyphe pour U+2009. Firefox 2 prend également en charge   et même   (l’espace fine insécable) sans que des glyphes correspondants doivent être présents dans la police courante. MSIE 7 ne prend pas en charge   et affiche un carré à la place.

6.3.5

Espace sans chasse U+200B espace sans chasse indique une frontière de mot, mais il est à chasse nulle. Les espaces sans chasse sont conçues pour les langues qui ne séparent pas les mots à l’aide d’espaces visibles, comme le thaï ou le japonais. Quand un texte est justifié, l’espace sans chasse n’a aucun effet sur l’interlettrage (cf. la tradition française ou japonaise). Il se peut qu’à la suite d’une justification il faille avec certaines écritures, comme le thaï ou le khmer, blanchir un peu plus autour de l’espace sans chasse. Cette méthode se distingue de l’utilisation de caractères à chasse fixe, comme U+2002 espace demi-cadratin dont la chasse est constante et qu’il ne faut pas élargir pendant la justification. Ce caractère peut indiquer des points de coupure dans de longues URL pour mieux maîtriser les points de coupure (par exemple après une barre oblique « / ») et éviter des coupures de ce style : http://www.diplomatie.gouv.fr/fr/conseils-aux-voyageurs_909/pay s_12191/afrique-du-sud_12193/index.html

Il ne faut pas confondre ce caractère avec le U+00AD trait d’union conditionnel, car lorsqu’une ligne est coupée après une espace sans chasse aucun trait d’union n’apparaît.

6.3.6

Disposition des espaces Le tableau 6.5 résume la valeur et la disposition typique des espaces en typographie française selon l’Imprimerie Nationale et Aurel Ramat.

150

Chapitre 6. Ponctuation

Tableau 6.6 – Espacement autour des signes français Avant

Signe ,

pas de blanc . pas de blanc U+202F espace fine insécable U+202F espace fine insécable U+202F espace fine insécable U+00A01 espace mots insécable U+00202 espace justifiante U+0020 espace justifiante U+00A0 espace mots insécable U+0020 espace justifiante U+0020 espace justifiante

; ! ? : – « » (

pas de blanc [ )

pas de blanc ] pas de blanc U+202F espace fine insécable U+00A0 espace mots insécable U+00A0 espace mots insécable U+00A0 espace mots insécable

Après U+0020 espace justifiante U+0020 espace justifiante U+0020 espace justifiante U+0020 espace justifiante U+0020 espace justifiante U+0020 espace justifiante U+0020 espace justifiante U+00A0 espace mots insécable U+0020 espace justifiante

* appel de note % h (heure) $, €

: (heure) pas de blanc U+00A0 cl, cm, kg... (unités) espace mots insécable 000 U+202F espace fine insécable (tranche de trois chiffres)

pas de blanc U+0020 espace justifiante U+0020 espace justifiante U+0020 espace justifiante U+0020 espace justifiante U+00A03 espace mots insécable U+0020 espace justifiante pas de blanc U+0020 espace justifiante U+202F espace fine insécable

123

1. Cette espace doit être non dilatable ce que U+00A0 est généralement, mais cela n’est pas garanti. Certains auteurs, voir l’Encyclopédie de la chose écrite, recommandent plutôt ici une espace fine insécable. 2. Certains auteurs, voir l’Encyclopédie de la chose écrite, recommandent plutôt ici une espace fine. 3. Uniquement si le « h » est suivi de minutes.

6.4 Autres signes typographiques

6.4 6.4.1

151

AUTRES SIGNES TYPOGRAPHIQUES Points de suspension et points de conduite

Points de suspension La manière d’afficher les points de suspension peut varier en fonction de la tradition typographique, les points constitutifs seront ainsi parfois plus rapprochés dans certaines traditions que d’autres. Le glyphe utilisé pour U+2026 points de suspension dans les tableaux ISO/Unicode a un écartement moyen. En typographie française les points de suspension ne sont pas plus séparés que trois points normaux successifs : « ... ». Certaines polices (Times New Roman) adoptent une convention anglo-saxonne qui consiste à espacer ces points : « … », MS Word semble l’imposer même en français en remplaçant trois points successifs par un U+2026 qui dans la plupart des polices est trop espacé pour la tradition française. La police Code 2000 n’a pas ce défaut. On peut également éliminer la règle de Word qui remplace trois points par un U+202F en allant dans Options de correction automatique > (onglet) Correction automatique et puis faire défiler la liste des substitutions jusqu’à trouver remplacer … par … et puis appuyer sur Supprimer et enfin OK. Il existe une forme verticale des points de suspension qui peut servir quand le texte s’écrit de haut en bas (ou de bas en haut). Il s’agit de U+FE19 ແ forme de présentation de points de suspension verticaux. Ce caractère ne devrait être utilisé que dans les cas où le moteur de rendu ne parvient pas à choisir correctement la variante de glyphe de U+2026 adéquate au sens de l’écriture. Il ne faut pas confondre U+FE19 avec U+205D ᐳ trois-points verticaux qui sert de délimiteur dans les anciens manuscrits grecs, il porte aussi le petit nom de « symbole trois acrophonique épidaurien ». Enfin, il faut encore distinguer ces caractères d’U+22EE ⋑ trois points suspendus qui indique l’élision de rangées ou de colonnes d’une matrice en algèbre linéaire, U+22EE ne devant être utilisé que dans le contexte mathématique.

Points de conduite Par analogie de forme, on imagine parfois que les lignes de points de conduite sont constituées de points de suspension. C’est inexact : dans une « ligne pointée », le nombre de points n’est pas nécessairement un multiple de trois et une espace forte sépare habituellement chaque point [ . . . . . . . . . . . .], faute de quoi, on obtient, à la rigueur, une ligne à découper selon le pointillé […………………]. Exemple :

Crayons . . . . . . . . . . . . . . . . . . . . . 20 €

Attention à l’espace insécable forte entre le dernier signe des mots situés à gauche et le premier point de conduite : elle permet de discerner d’éventuels points abréviatifs, qui sont collés à la dernière lettre.

152

Chapitre 6. Ponctuation

Les points de conduite sont habituellement produits automatiquement par les logiciels de mise en pages ou les langages de description de page comme XSL-FO (fo:leader). En règle générale, il n’est donc pas judicieux d’aligner ces points de comblement à la main à l’aide de U+2024 . point de conduite simple, U+2025 .. point de conduite double et U+2026 ... points de suspension dont l’espacement pourrait être, de toute façon, irréguliers, inélégants ou incorrects.

6.4.2

Traits d’union et tirets Tout comme pour les espaces, à la notion abstraite de tiret, Unicode a ajouté les glyphes typographiques usuels hérités des codages patrimoniaux. En raison de sa prévalence dans les jeux de caractères préexistants, U+002D trait d’union-signe moins est le signe le plus fréquemment utilisé pour représenter le trait d’union. Comme nous l’avons plus haut, voir § 6.1.6, Trait d’union-signe moins, ce signe est ambigu et il est, en règle générale, rendu avec une chasse intermédiaire. Rappelons que les typographes appellent le trait d’union « division ». Unicode reprend une série de caractères traits d’union comme U+2010 trait d’union et U+2011 trait d’union insécable à des fins de compatibilité avec les normes actuelles, en l’occurrence le XCCS, jeu de caractères normalisé de Xerox, qui a souvent servi de modèle au début d’Unicode. Il possède la même valeur sémantique que U+2010 trait d’union, mais il ne peut être coupé en fin de ligne. U+2012  tiret numérique a également été inclus pour des raisons de compatibilité : il a le même sens (ambigu) que U+002D - trait d’union-signe moins, mais sa chasse est celle des chiffres (s’ils sont de chasse fixe). U+2013 ῶ tiret demicadratin s’emploie en anglais dans la notation des intervalles tels que 1914–1918. En français, on emploie dans ce cas une division normale sauf évidemment parmi les gens qui copient le Chicago Manual of Style. Il faut le distinguer de l’opérateur arithmétique U+2212 ⇵SIGNE MOINS, même si les typographes ont pris l’habitude de confondre les deux. Pour des raisons de compatibilité lors de l’interprétation des formules comme « x = a – b », on peut être confronté aux caractères U+002D - trait d’union-signe moins, U+2212 ⇵ signe moins et U+2012  tiret numérique qui devront tous être interprétés comme synonymes avec le sens de signe moins. On emploie U+2014 — tiret cadratin pour représenter une incise — comme celle-ci — au sein d’une phrase. On le tape souvent à la machine à écrire sous la forme de trois traits d’union. Cet emploi d’un tiret cadratin a tendance à se perdre aujourd’hui au profit du tiret demi-cadratin, notamment dans la presse, mais pas dans les ouvrages de qualité. Le tiret demi-cadratin est souvent représenté à la machine par deux traits d’union. On trouve des traits d’union et des tirets dans plusieurs blocs de caractères Unicode. Le tableau 6.7 reprend une liste des tirets Unicode.

6.4 Autres signes typographiques

153

Tableau 6.7 – Liste de traits et tirets Unicode Numéro U+002D U+005F U+007E

Œil B ~

U+00AD U+058A U+05BE U+1806

ӡ ԍ

U+2010



U+2011



U+2012 U+2013





– U+2014 — U+2015



U+203E



U+2053 U+207B



U+208B



U+2212





U+2E17 ṁ

U+301C U+3030

᾵ Έ

Nom abrégé Trait d’union-signe moins

Remarques Signe ambigu, de chasse intermédiaire entre la chasse du trait d’union et du signe moins. Tiret bas (soulignement) Voir U+203E. Tilde Caractère qui chasse, pas le diacritique, voir § 5.3, Clones à chasse des diacritiques. Trait d’union conditionnel Pour indiquer une division à privilégier. Trait d’union arménien Trait d’union conditionnel pour l’arménien. Maqaf Hébreu. Trait d’union conditionnel Trait d’union conditionnel, s’affiche au début mongol todo de la seconde ligne. Trait d’union La version non ambiguë de la division comme dans « chef-d’œuvre ». Trait d’union insécable Idem à U+2010, mais pas de coupure de lignes admise. Tiret numérique À la chasse des chiffres, s’ils ont la même chasse. Tiret demi-cadratin Représentation moderne d’une incise – comme celle-ci – au sein d’une phrase. En anglais s’utilise pour les intervalles, en français l’intervalle utilise un tiret plus court. Tiret cadratin Représentation traditionnelle d’une incise — comme celle-ci — au sein d’une phrase. Sert aussi pour indiquer un changement d’interlocuteur dans des dialogues. Barre horizontale Pour indiquer un changement d’interlocuteur dans des dialogues. Tiret en chef (tiret suscrit) Équivalent suscrit du U+005F tiret-bas. Ce caractère chasse, il ne faut pas le confondre avec U+0305 ̅ diacritique tiret haut. Comme tous les tirets souscrits et suscrits, une suite d’un de ces caractères forme une ligne horizontale continue, à la différence de l’U+0304 ̄ diacritique macron dont une suite forme une ligne horizontale discontinue. Tiret ondé Grand tilde. Exposant signe moins Symbole mathématique, équivalent de compatibilité du U+2012 en exposant. Indice signe moins Symbole mathématique, équivalent de compatibilité du U+2012 en indice. Signe moins Opérateur mathématique, chasse adaptée au signe moins. Trait d’union double oblique Utilisé en linguistique du Proche-Orient. Ressemble au trait d’union pour la fraktur (le « gothique ») qui, pour sa part, se code à l’aide du U+002D ou U+2010 mais prendra la forme de U+2E17 dans une police fraktur. Trait d’union en esse Caractère CJC de chasse idéographique. Trait d’union ondulé Caractère CJC de chasse idéographique.

154

6.4.3

Chapitre 6. Ponctuation

Puces, barre de fraction, ponctuation doublée

Barre de fraction On forme une fraction en plaçant une barre, U+2044 ‧ barre de fraction entre les chiffres qui la composent : 2/3, 3/9, etc. Cette fraction peut être représentée sous différentes formes comme une unité : ¾ ou Ä. La forme précise de présentation dépend d’informations supplémentaires de formatage. Si le logiciel d’affichage ne parvient pas à associer à la fraction un seul glyphe, on peut alors se replier sur une représentation linéaire (par exemple 3 / 4). S’il faut séparer la fraction d’un nombre qui la précède, on peut alors insérer une espace (de chasse appropriée : normale, fine, sans chasse, etc.). Ainsi, 1 + espace sans chasse + 3 + barre de fraction + 4 peut être affiché 1¾.

Ponctuation doublée Unicode comprend plusieurs caractères de ponctuation doublée1 dont la décomposition de compatibilité est formée de deux signes de ponctuation : U+203C ‟ double point d’exclamation, U+2048 ᐟ point d’interrogation-exclamation et U+2049 ᐠ point d’exclamation-interrogation. Ces signes de ponctuation doublée sont inclus dans Unicode afin de faciliter la mise en œuvre de textes affichés verticalement dans le cas du mongol et des textes CJC que l’on peut choisir d’afficher ainsi.

Puces La puce est habituellement représentée par U+2022   puce. Unicode code des formes supplémentaires de puce au sein du bloc consacré à la ponctuation générale : U+2023 ಶ puce triangulaire, U+204C ᐣ puce noire tronquée à droite et ainsi de suite. On utilise également souvent U+00B7 · point médian comme une petite puce. La puce marque le début de paragraphes au formatage particulier, souvent des listes. En typographie française, où les puces n’existaient pas, ces listes sont plutôt marquées par des tirets cadratin. Les puces peuvent prendre de très nombreux aspects : images, vignettes ainsi que des formes plus conventionnelles. On emploie souvent, de façon un peu directive, U+261E ᤺index blanc pointant vers la droite pour faire ressortir une remarque dans un texte.

6.4.4

Ponctuation archaïque Unicode comprend de nombreux signes de ponctuation archaïque. La signification de ces signes peut varier en fonction de l’écriture qui les utilise. Les scribes utilisaient souvent les signes U+205B ᐱquatre-points en croix et U+205C ᐲcroix pointée dans les marges des manuscrits afin de souligner un passage.

1. À ne pas confondre avec la ponctuation double (ou haute) : « ! », « ? », « ; ».

6.5 Caractères de coupure de lignes

155

On trouve également des signes de ponctuation archaïque dans les blocs Runes [U+16A0..U+16FF], Nombres égéens [U+10100..U+1013F] et Cunéiformes [U+12000..U+120FF]. Veuillez aussi consulter la description du bloc Grec, § 5.4, Écriture grecque.

6.5

CARACTÈRES DE COUPURE DE LIGNES Récapitulons ici les caractères Unicode qui régissent la coupure de lignes dans un texte mis en pages, soit par empêchement d’une coupure inopinée ou par suggestion d’une coupure. Tableau 6.8 – Caractères qui forcent, empêchent ou permettent la coupure de lignes

Numéro

Nom ISO 10646

Description

U+000A

Passage à la ligne

Ambigu : coupe la ligne ou passe à un nouveau paragraphe.

U+000B

Tabulation verticale

Coupe la ligne dans MS Word.

U+000C

Saut de page, page suivante

Passe à une nouvelle page, coupe implicitement la ligne.

U+000D

Retour de chariot

Ambigu : coupe la ligne ou passe à un nouveau paragraphe.

U+0085

À la ligne

Passe à la ligne sur certains systèmes.

U+00A0

espace insécable

Comme U+0020, mais empêche la coupure de lignes.

U+00AD

trait d’union conditionnel

Invisible (sauf si une coupure a lieu), indique un point de coupure permis.

U+200B

espace sans chasse

Invisible, indique un point de coupure permis.

U+2010

trait d’union

Coupure possible après ce signe.

U+2011

trait d’union insécable

Comme U+2010, mais empêche la coupure de lignes.

U+2028

séparateur de lignes

Sans ambiguïté, mais peu utilisé.

U+2029

séparateur de paragraphes

Sans ambiguïté, mais peu utilisé.

U+202F

espace insécable étroite

Comme U+00A0, mais espace fine, empêche la coupure de lignes.

U+2060

gluon de mots

Comme U+00A0, mais de chasse nulle (invisible).

156

Chapitre 6. Ponctuation

Résumé U+00AD - trait d’union conditionnel indique un point de coupure de mot potentiel. La forme que prendra ce trait d’union conditionnel, si une coupure de mot y survient, varie en fonction de la tradition lexicographique de la langue que représente le texte : en français on affichera un trait d’union « - », mais il est possible que dans d’autres traditions ce caractère reste invisible. Dans le contexte des textes bidirectionnels ou verticaux, il est impératif d’interpréter sémantiquement plutôt que graphiquement les signes de ponctuation appariés tels que les parenthèses (U+0028, U+0029), les crochets (U+005B, U+005D) ou les accolades (U+007B, U+007D). La U+0028 (parenthèse gauche s’affichera donc « ) » dans un contexte arabe (droite à gauche). Unicode code plusieurs espaces de chasse variée dans l’intervalle [U+2000.. U+200A]. Quelques-uns de ces caractères sont des doublons (U+2001 et U+2003). La typographie moderne n’utilise plus vraiment ces caractères à chasse fixe, elle laissera le plus souvent faire l’algorithme de justification quitte à régler les cas difficiles à l’aide de paramètres, notamment grâce à du balisage qui permet de préciser une largeur arbitraire. U+00A0 espace insécable empêche la coupure autour de lui. Le caractère U+200B espace sans chasse indique une frontière de mot, mais il est à chasse nulle. Les espaces sans chasse sont conçues pour les langues qui ne séparent pas les mots à l’aide d’espaces visibles, comme le thaï ou le japonais. Quand un texte est justifié, l’espace sans chasse n’a, en règle générale, aucun effet sur l’interlettrage. On peut rendre insécable une espace sécable en l’entourant de deux U+2060 gluon de mots. Le gluon de mots est similaire à U+00A0, mais il est de chasse nulle, il est invisible.

7 Symboles et notations

Objectif Unicode comprend un grand ensemble de symboles mathématiques, logiques physiques, monétaires et musicaux. Ce chapitre présente quelques-uns de ces symboles les plus fréquents.

7.1

SYMBOLES DE TYPE LETTRE Ce bloc [U+2100..U+214F] contient des symboles qui s’inspirent de lettres latines, grecques et hébraïques. Nombre de ces symboles ne sont codés que pour des raisons de compatibilité. En général, il est fortement déconseillé d’utiliser ces symboles de type lettre quand les caractères à représenter ne sont qu’une variante de présentation d’autres caractères codés. En d’autres termes, contrairement à ce que d’aucuns pensent, ces lettres ne sont pas « meilleures » que les lettres normales. Ainsi U+212A K symbole kelvin n’est-il en rien meilleur que U+004B K lettre majuscule latine k. En effet, Unicode code des écritures. Or la manière d’écrire un Kelvin est depuis belle lurette d’utiliser un K majuscule, pas un symbole distinct, pas une forme de glyphe caractéristique à cet usage, mais un K ordinaire. U+212A K symbole kelvin n’est codé que pour des raisons de compatibilité avec des jeux de caractères asiatiques pré-Unicode. Cette situation est très différente de celle des signes de ponctuation ambigus que nous avons décrits auparavant comme U+0027 ‘ apostrophe ou U+002D - trait d’union-signe moins et pour lesquels on préconise l’emploi d’autres caractères dans

158

Chapitre 7. Symboles et notations

certains cas : U+2019 ’ guillemet-apostrophe pour l’apostrophe typographique courbée et U+2212 − signe moins pour le signe arithmétique. Les caractères ASCII pour l’apostrophe et le trait d’union-signe moins sont des compromis des années soixante, quand on voulait loger un maximum de caractères dans 7 bits, on les a donc surchargés de plusieurs sens. La désunification de ces caractères ASCII se justifie par de réelles distinctions dans l’écriture telle qu’elle existe hors du codage, au premier chef l’apparence et la chasse différentes des signes unifiés. Il vaut donc mieux utiliser un K normal (U+004B) qu’un symbole Kelvin, ne fûtce que parce que le K latin est présent, en pratique, dans toutes les polices alors que U+212A en est souvent absent. De même, dans les équations, les formules ou d’autres contextes, il faut employer les formes alphabétiques normales dans le style approprié pour représenter des unités. Ainsi, pour représenter le symbole degré Celsius « °C », il faut utiliser la suite U+00B0 ° symbole degré + U+0043 C lettre majuscule latine c plutôt qu’U+2103 ᒑ degré celsius. Pour la recherche, on traitera ces deux suites comme identiques. U+2116 № symbole numéro s’utilise en cyrillique, où il prend la forme №, ainsi que dans certaines normes asiatiques, où il apparaît sous l’aspect d’un ഥ. En français, on utilise un « N » majuscule ou minuscule, selon le contexte, suivi d’un o supérieur (No ou no; au pluriel Nos ou nos) et non du symbole degré (N° ou n°). Les applications qui s’échangent des données patrimoniales doivent traiter ces différentes représentations du symbole numéro comme étant équivalentes. Voir également § 6.1.10, Symbole degré et ordinal masculin. U+2118 ധ fonction elliptique de weierstrass est dérivé d’un p de Chancellerie en bas-de-casse. Le nom anglais de ce caractère script capital p est erroné : il ne s’agit pas d’une majuscule. En typographie extrême-orientale, les symboles de type lettre s’affichent avec une pleine chasse ; ils occupent ainsi une cellule CJC complète. En composition verticale, ces symboles restent « debout » alors que des lettres normales équivalentes pivotent. Les symboles de type lettre n’ont pas nécessairement les mêmes propriétés de directionalité que les lettres normales ; ainsi les symboles des quatre cardinaux transfinis (ൄേ, U+2135..U+2138) utilisés dans les textes mathématiques n’ont-ils pas la directionalité droite-à-gauche forte des lettres hébraïques dont elles sont issues. Ce bloc comprend également des signes codés qui ne sont en fait que des variantes stylistiques de lettres, phénomène rare dans Unicode. On retrouve ainsi des lettres gothiques, ajourées et de ronde (ou anglaises) employées comme symboles mathématiques (voir § 7.3, Mathématique). Le codage de ces variantes stylistiques entérine l’usage courant qui les considère comme des symboles autonomes par rapport aux lettres normales. Il s’agit de constantes bien connues, par exemple U+211D ബ r majuscule ajouré qui représente l’ensemble des nombres réels, ou de variables au sens particulier bien distinct de celui des lettres romaines équivalentes dans un texte mathématique.

7.2 Symboles monétaires

7.2

159

SYMBOLES MONÉTAIRES Le bloc [U+20A0..U+20CF] contient les symboles monétaires qui ne sont pas codés dans d’autres blocs. Quand Unicode respecte la structure d’une norme existante, comme dans les blocs ASCII, Latin 1 et thaï, les symboles monétaires demeurent codés dans ces blocs et on ne retrouve donc pas ces caractères dans le bloc des symboles monétaires. Unicode utilise un numéro de caractère unique pour chaque symbole distinct, même s’il représente plusieurs monnaies. Plusieurs devises sont représentées à l’aide de symboles barrés. Il existe souvent alors de petites variantes d’un même symbole, c’est le cas d’U+0024 $ symbole dollar (ainsi que d’U+00A3 £ symbole livre) qui peut comporter une ou deux barres verticales ainsi que d’autres variantes graphiques. Unicode considère ces variantes comme des variations typographiques et ne prévoit qu’un seul caractère, même si le même symbole dollar représente ou a représenté au moins quatre devises différentes : le milreis, le dollar, la piastre et l’escudo. Tableau 7.1 – Variabilité des symboles dollar et livre Police

7.3

Glyphe

Arial

$

£

Arno

$

£

Bodoni MT Black

$

£

Brush Script MT

$

£

Cardo

$

£

Calibri

$

£

Charlemagne Std

$

£

MATHÉMATIQUE La notation mathématique emploie un jeu de caractères alphanumériques de base qui comporte :

• l’ensemble des chiffres latins de base (0-9) [U+0030..U+0039] ; • l’ensemble des lettres latines minuscules et majuscules de base (a-z, A-Z) [U+0061..U+007A] et [U+0041..U+005A] ;

• les lettres majuscules grecques A-Ω [U+0391..U+03A9], ainsi que U+2207 ේ nabla et la variante du thêta U+03F4 θ symbole grec thêta majuscule ;

• les lettres minuscules grecques α-ω [U+03B1..U+03C9], ainsi que U+2202

⇥dérivée partielle et les six variantes glyphiques de ε, θ, κ, φ, ρ et π : U+03F5 ϵ, U+03D1ϑ, U+03F0ϰ, U+03D5ϕ, U+03F1 ϱet U+03D6ϖ.

160

Chapitre 7. Symboles et notations

Seules les formes non accentuées des lettres s’utilisent en mathématiques parce que les accents génériques, tels que l’accent aigu, font obstacle aux diacritiques mathématiques habituels. Ces diacritiques mathématiques comprennent, entre autres, l’accent circonflexe, le macron et le point (simple ou double) suscrit, ce dernier dénote en physique les dérivées par rapport à une variable de temps. Les symboles mathématiques comportant des diacritiques se représentent toujours par des suites de caractères combinatoires. En plus du jeu de base, la notation mathématique utilise également quatre caractères dérivés de l’hébreu [U+2135..U+2138]. On utilise à l’occasion, d’autres caractères alphabétiques ou numériques, comme U+0428 Ш lettre majuscule cyrillique cha, U+306E け syllabe hiragana no ou les chiffres arabo-hindî [U+06F0.. U+06F9]. Toutefois, ces caractères ne s’utilisent que sous leur forme de base. Unicode comprend également de très nombreux caractères mathématiques dans le plan multilingue complémentaire (plan nº 1). Il s’agit des Symboles mathématiques alphanumériques [U+1D400..U+1D7FF]. Ce bloc contient un grand nombre de symboles de type lettre utilisés en mathématiques, plus particulièrement comme variables. Les caractères de ce bloc ne sont destinés qu’à la notation mathématique ou technique ; on ne devrait pas les retrouver dans des textes non techniques. Dans les langages de balisage, comme MathML (Mathematical Markup Language), ces caractères doivent s’utiliser directement, il ne faut pas y faire référence à l’aide d’entités de référence ou avoir recours à leur composition à partir des lettres de base latines assorties de balises de style. En effet, la notation mathématique fait appel à un certain nombre d’alphabets latins et grecs qui — même s’ils peuvent au premier coup d’œil passer pour de simples variantes de polices de caractères — ont souvent un sens différent qu’il faut conserver dans le texte brut (en l’absence de tout balisage) et donc dans Unicode. Ainsi, la lettre H peut-elle apparaître en romain (H), en gras (H), en ajouré (ø), en gothique (ã), en italique (H) ou de ronde (ച ). Dans un document donné, chacun de ces caractères possède une signification distincte, en règle générale sans rapport avec celle des autres H. Le H romain représente donc une variable différente du H gras. Si ces attributs devaient disparaître dans un texte mathématique normal, le sens du texte s’en trouverait altéré. Sans ces distinctions, une formule pour l’hamiltonien comme :



ച = dτ (εE2 + µH2) se transformerait en cette équation intégrale pour l’inconnue H :



H = dτ (εE2 + µH2) Coder ces deux signes dans Unicode permet de conserver de telles distinctions dans du texte brut (c’est-à-dire sans balisage). Notons que la première équation est une intégrale de volume et qu’un V souscrit en faciliterait sans doute la lecture. Les opérateurs en exposant ou indice ne font, cependant, pas partie d’Unicode. Il est impossible de représenter cette intégrale avec cet indice à l’aide d’un texte Unicode brut ; il faut avoir recours à un protocole de haut niveau comme MathML.

7.4 Musique

7.4

161

MUSIQUE Les symboles musicaux codés dans Unicode englobent la notation musicale occidentale contemporaine (notation « ovale ») et ses précurseurs : la notation grégorienne (le plain-chant, notation « carrée ») et la notation proportionnelle (notation « losangée »)1. Les symboles musicaux occidentaux classiques constituent la plus grande partie des symboles musicaux d’Unicode. S’y ajoutent des compléments courants à ce répertoire classique : les altérations de quart de ton, les têtes de note « bloc » et les têtes de note « façonnées » à l’américaine (les shape-notes2). Les difficultés liées à la représentation graphique des partitions, et notamment celle de la hauteur de ton, sont telles qu’Unicode ne définit pas, à dessein, de codage pour la hauteur de ton musicale. Le bloc des symboles musicaux fournit un jeu d’éléments communs utiles à l’échange et au traitement. Le codage de la hauteur de ton et la mise en page de la structure musicale résultante impliquent non seulement la définition de la relation verticale entre les diverses notes simultanées, mais également, quand plusieurs portées sont employées, celle entre les diverses parties instrumentales. Ceci est du ressort de protocoles de haut niveau qui peuvent puiser parmi les éléments graphiques de ce bloc. L’absence d’indication de hauteur de ton n’est pas une lacune, mais une caractéristique essentielle du codage. On peut considérer la plupart des symboles musicaux comme de simples caractères à chasse au sein d’un texte ou d’un exemple, même si, dans une mise en pages musicale complète, leur comportement est plus complexe. Certains caractères ne sont conçus que pour s’adjoindre à d’autres et produire ainsi des suites de caractères qui représentent à la fois des notes et leur articulation. On peut saisir, traiter et afficher les symboles musicaux d’une manière analogue à celle utilisée pour les symboles mathématiques. Incorporés à un texte, la plupart des symboles deviennent de simples caractères à chasse sans propriété particulière. Pour une souplesse maximale, le jeu de caractères inclut à la fois des valeurs de note précomposées et des primitives à partir desquelles on peut composer des notes complètes. On fournit les versions précomposées principalement pour des raisons de commodité. Néanmoins, si on normalise d’une façon quelconque le texte, tous les caractères seront décomposés.

1. Encore appelée notation mensurale ou mesurée (musica mensurata), elle s’oppose au plain-chant (musica plana) par l’attribution à chaque signe d’une durée relative. 2. Aide de lecture utilisée principalement dans les livres de cantiques protestants aux États-Unis. Chaque forme de tête de note y correspond à une note de la gamme (il n’est donc pas nécessaire de savoir décoder l’armure de la clé).

162

Chapitre 7. Symboles et notations

Tableau 7.2 – Unicode comprend des primitives musicales précomposées Glyphes

fl = ÿ + Â ‡=ÿ+Â+Ó A = ÿ + Â + Ó + Ì.

Précomposé

Décomposé

U+1D15F noire

U+1D158 tête de note noire + U+1D165 hampe

U+1D160 croche

U+1D158 tête de note noire + U+1D165 hampe + U+1D16E crochet-1

U+1D160 croche + U+1D16D point d’augmentation

U+1D158 tête de note noire + U+1D165 hampe + U+1D16E crochet-1 + U+1D16D point d’augmentation

Résumé Unicode comprend de très nombreux caractères techniques, plusieurs ont été codés pour des raisons de compatibilité avec des jeux de caractères fondateurs. C’est le cas, par exemple, de U+212A K symbole kelvin et de U+2103 °C degré celsius. Ces lettres, codées pour des raisons de convertibilité, ne sont pas « meilleures » que les lettres normales. Ainsi U+212A K symbole kelvin n’est-il en rien meilleur que U+004B K lettre majuscule latine k. Au contraire, alors que U+004B sera présent dans pratiquement toutes les polices, U+212A en sera le plus souvent absent. Cette situation est très différente des lettres et symboles dont le sens dépend de leur apparence comme U+2115 ℕ n majuscule ajouré qui représente l’ensemble des nombres naturels et que l’on ne peut représenter à l’aide d’un N normal sans perte d’information. Dans le même ordre d’idées, Unicode comprend de très nombreux caractères mathématiques dans le plan multilingue complémentaire (plan nº 1). Il s’agit des Symboles mathématiques alphanumériques [U+1D400..U+1D7FF]. Ces lettres-symboles s’utilisent plus particulièrement en mathématiques comme variables où leur apparence est importante (la variable ¶ sera différente de la variable é). Les caractères de ce bloc ne sont destinés qu’à la notation mathématique ou technique ; on ne devrait pas les retrouver dans des textes non techniques. Notons également qu’Unicode ne permet pas de représenter graphiquement les équations mathématiques dans toute leur complexité, cette tâche est dévolue à des protocoles de haut niveau comme MathML. Les symboles musicaux codés dans Unicode englobent la notation musicale occidentale contemporaine (notation « ovale ») et ses précurseurs : la notation grégorienne (le plain-chant, notation « carrée ») et la notation proportionnelle (notation « losangée »). Une nouvelle fois, Unicode ne permet pas de représenter les partitions musicales : il ne code par exemple pas la position des symboles normalisés sur la portée. Cette tâche est du ressort d’un protocole de haut niveau.

8 Caractères techniques spéciaux

Objectif Unicode comprend un grand nombre de caractères techniques spéciaux qui ne correspondent pas à des écritures humaines, mais à des fonctions de commande ou à des zones à usage privé. Ce chapitre présente les principaux caractères techniques d’Unicode comme l’indicateur d’ordre des octets (BOM ou IOO), le GLUON de mots et le diacritique invisible bloquant. Il décrit également une distinction importante entre les caractères désuets et les caractères déconseillés. Enfin, ce chapitre introduit les positions de code dont le nom peut, a priori, suprendre : les non-caractères.

8.1 8.1.1

CARACTÈRES DE COMMANDE Commandes C0 et suppression Unicode n’attribue pas de sens particulier à ces codets de commande, mais les prévoit uniquement afin de permettre leur transmission sans perte, Unicode n’ajoute ni ne soustrait rien à leur sémantique. En règle générale, le sens des commandes C0 (U+0000..U+001F) et de suppression (U+007F) dépend de l’application qui les utilise. Toutefois, en absence de contexte particulier, on peut les interpréter conformément à la sémantique établie par la norme ISO/CEI 6429 :1992. C’est ainsi

164

Chapitre 8. Caractères techniques spéciaux

que, par exemple, U+0009 TABULATION HORIZONTALE s’utilise souvent munie d’une même signification, c’est pourquoi Unicode la prend en compte. Il existe une correspondance bi-univoque simple entre les codets de commande à 7 bits (ou à 8 bits pour les commandes C1 que nous verrons ci-après) et les codets de commande Unicode : on ajoute le nombre nécessaire de zéros au début de chaque code de commande à 8 bits lors de sa transformation en unité de stockage. En UTF-16, cela signifie l’ajout de 8 bits à zéro, en UTF-32 de 24 bits à zéro.

Fonction changement de ligne Un ou plusieurs codets de commande U+000A passage à la ligne, U+000D retour de chariot ou l’équivalent Unicode du NL EBCDIC représentent la fonction changement de ligne. Une fonction de changement de ligne peut, selon l’application, se comporter comme un séparateur de lignes ou de paragraphes. Le codage précis de la fonction de changement de ligne dépend du domaine d’application, voir l’UAX n° 13, « Unicode Newline Guidelines » sur le site Internet du consortium Unicode.

Séparateur de lignes et de paragraphes Unicode prévoit deux caractères blancs univoques U+2028 séparateur de lignes et U+2029 séparateur de paragraphes pour signaler la séparation des lignes et des paragraphes. On les considère comme les formes canoniques d’indication de frontière de ligne et de paragraphe dans les textes Unicode bruts. Une nouvelle ligne suit chaque séparateur de lignes, un paragraphe chaque séparateur de paragraphes. Ces caractères étant des séparateurs, il n’est pas nécessaire qu’un d’entre eux précède le premier paragraphe ou la première ligne ou encore suive le dernier paragraphe ou la dernière ligne. En effet, cette insertion signifierait qu’une ligne vide précède ou suit. On peut séparer les paragraphes d’un texte à l’aide du séparateur de paragraphes. Il est de la sorte possible de créer des fichiers de texte brut qui, à la réception, peuvent être composés avec des largeurs de ligne différentes selon la zone d’affichage disponible. Le séparateur de lignes peut servir à signaler une fin de ligne obligatoire (voir également § 6.5, Caractères de coupure de ligne).

8.1.2

Commandes C1 Lors du passage du système de codage à 7 bits ASCII à un système à 8 bits, l’ISO/ CEI 4873 (sur lequel repose la famille des normes de caractères 8859) a incorporé 32 codes de commande supplémentaires dans l’intervalle 0x80-0x9F. À l’instar des codes de commande C0, le standard Unicode n’attribue pas de sens particulier à ces codes de commande, mais les prévoit uniquement afin de permettre leur transmission sans perte, Unicode n’ajoute ni ne soustrait rien à leur sémantique. En règle générale, le sens des commandes C1 [U+0080..U+009F] dépend de l’application qui les utilise. Toutefois, en absence d’un contexte particulier, on peut les interpréter conformément à la sémantique établie dans la norme ISO/CEI 6429:1992.

8.2 Gluon et diacritique invisible bloquant

8.2 8.2.1

165

GLUON ET DIACRITIQUE INVISIBLE BLOQUANT Gluon de mots (U+2060) Le gluon de mots (U+2060) se comporte comme l’espace insécable (U+00A0), car il indique l’absence de frontière de mots, en revanche, contrairement à U+00A0, le gluon de mots n’a pas de chasse. La fonction de ce caractère consiste à empêcher la division entre les deux caractères qui en sont voisins sauf si un de ceux-ci est un passage à la ligne forcé. Le gluon de mots joue donc le rôle d’une espace insécable sans chasse. On pourra donc insérer un gluon de mots après le troisième caractère du texte « mot+suffixe » pour s’assurer que l’on ne coupe pas la ligne entre le « t » et le « + ». Le gluon de mots sert également à indiquer l’insécabilité de caractères qui n’ont pas de variante insécable. C’est ainsi qu’on peut encadrer U+2009 espace fine ou U+2015 Ὸ barre horizontale d’un U+2060 pour les rendre insécables. Le gluon de mots doit être ignoré sauf dans le contexte de la division de mots ou de lignes. Ceci signifie, notamment, que ce caractère n’a aucun effet sur la formation de ligatures. Il faut ignorer le gluon de mots dans les contextes qui ne sont pas reliés à coupure de mot ou de lignes. Jusqu’à Unicode 3.2, U+FEFF était le seul codet avec le sens de « gluon de mots ». Depuis lors, Unicode recommande que l’emploi de U+FEFF soit réservé à celui d’indicateur d’ordre des octets (IOO, BOM en anglais) et de ne plus utiliser que U+2060 gluon de mots pour indiquer l’insécabilité.

8.2.2

Diacritique invisible bloquant (U+034F) Le gluon de mots (U+2060) ne doit pas être confondu avec l’U+034F diacritique invisible bloquant qui lui non plus n’a pas d’œil. U+034F diacritique invisible bloquant (abrégé en DIB) a plusieurs fonctions :

• Il affecte le tri des caractères qui le jouxtent quand on trie ces caractères selon l’ordre d’une langue particulière, ou lorsqu’on compare ou recherche des chaînes contenant U+2060 et il permet de différencier des suites qui seraient sinon canoniquement équivalentes. Lors des tris, sa principale fonction est d’éviter la formation de contraction. Par exemple, bien que le « ch » corresponde à une seule unité de tri, ce qu’on nomme une contraction, dans les tableaux de tri pour le tchèque, la suite sera trié en tchèque comme un « c suivi par un h » sans modification particulière des tableaux de tri. Ainsi, « chemie » (chimie) se trie-t-il entre « had » (serpent) et « informatika » (informatique) en tchèque, mais « chevigny » sera trié parmi les « c », avant « d » et bien sûr avant les « ch » sans diacritique invisible bloquant.

• L’insertion d’un U+034F diacritique invisible bloquant au milieu d’une suite de diacritiques empêche le réordonnancement canonique de ces diacritiques. Ceci peut se révéler utile dans les rares cas où il faut conserver l’ordre des

166

Chapitre 8. Caractères techniques spéciaux

diacritiques que la normalisation éliminerait. On peut par exemple distinguer la suite de points hébreux d’une suite grâce à l’insertion d’un diacritique invisible bloquant : . La présence du DIB empêche le réordonnancement normal dans l’ordre croissant des classes combinatoires canoniques (à savoir 14 pour le hirik et 17 pour le patah) : . Cette insertion causera également des différences dans le tri de chaînes comportant un DIB. Le diacritique invisible bloquant permet également de distinguer le tréma de l’umlaut1 dans les rares cas où cela est nécessaire (par exemple, les bases de données bibliothécaires allemandes qui contiennent de nombreux noms propres étrangers). Il faut se rappeler, que pour des raisons pratiques, Unicode ne distingue pas le tréma de l’umlaut. Les applications qui doivent distinguer ces deux diacritiques peuvent considérer que = , ce est alors équivalent dans le tri traditionnel pour l’allemand à (Börse = Boerse) alors que l’« o » à tréma (comme le « ö » dans Laokoön) pourra être considérée comme une variante au second niveau de tri du .

8.3

CARACTÈRES SPÉCIAUX Le bloc Caractères spéciaux [U+FFF0..U+FFFF] ne comprend que quelques caractères à la nature assez particulière :

• De U+FFF0 à U+FFF8 des positions non attribuées, réservées à une éventuelle future normalisation.

• De U+FFF9 à U+FFFB, trois caractères d’annotation interlinéaire, décrits § 8.3.1, Délimiteurs d’annotation interlinéaire.

• U+FFFC, le caractère de remplacement d’objet indique dans le flux textuel le point où insérer un objet. Tous les renseignements reliés à cet objet se situent en dehors du flux des données de caractères. Ce caractère factice joue le rôle d’un repère ou d’un pointeur vers l’information de formatage qui se rapporte à cet objet. Les tableaux de caractères de l’ISO 10646 et Unicode représentent ce caractère sous la forme suivante : . À noter qu’Unicode conseille d’utiliser des non-caractères ou des balises appropriées plutôt que l’U+FFFC, voir § 8.3.1, Délimiteurs d’annotation interlinéaire, pour une brève explication sur les raisons qui justifient ce conseil.

• U+FFFD, le caractère de remplacement à utiliser pour signaler, lors d’une conversion de données vers Unicode, qu’un caractère du jeu de caractères source n’a pas d’équivalent Unicode. Le glyphe indicatif de ce caractère 1. Rappelons qu’en allemand l’umlaut marque l’inflexion d’une voyelle, son changement de qualité (um « autour » + Laut « son ») alors que le tréma (das Trema) sert à séparer deux voyelles qui, autrement, formeraient une unité, voir par exemple « die Alëuten » prononcé [aleˈuːtən] alors que, sans ce tréma, toujours facultatif, un lecteur pourrait prononcer ce mot [alɔɪtən]. En pratique le tréma ne s’utilise en allemand qu’avec des mots étrangers.

8.3 Caractères spéciaux

167

est ᪽. Dans la mesure du possible, utilisez un U+FFFD pour indiquer l’échec de conversion quand le résultat est en Unicode et un 0x1A pour un résultat dans un codage basé sur l’ASCII.

• U+FFFE et U+FFFF : deux non-caractères parmi les 66 décrits au § 8.3.2, Non-caractères.

8.3.1

Délimiteurs d’annotation interlinéaire L’idée derrière les caractères d’annotation est de permettre que des passages dans un texte brut soient annotés par une série de caractères qui surmonteraient typiquement le texte annoté à la manière des Ruby ou des furigana japonais qui indiquent la prononciation de certains kanji. Chacun des trois délimiteurs d’annotation [U+FFF9.. U+FFFB] ressemble donc à une petite balise. Prenons un exemple en français et voyons comment indiquer la prononciation du patronyme de l’auteur au-dessus de celui-ci (le patronyme!) : [ãdRi:s] L’auteur se nomme Andries. On peut obtenir cet effet en HTML à l’aide de balises dans les navigateurs qui prennent en chargent la notation Ruby1 :

L’auteur se nomme Andries[ãdRi:s].



Intuitivement, on voit que la balise comprend un texte annoté (délimité par l’élément ) et un texte annotant (élément ) qui le surmonte. Voyons maintenant comment définir la même annotation à l’aide de délimiteurs d’annotations Unicode exprimés à la façon de chaînes Java2 : L’auteur se nomme\ufff9Andries\ufffa[ãdRi:s]\ufffb

Définissons maintenant les trois caractères :

• U+FFF9 ancre d’annotation interlinéaire indique le début d’une annotation et du texte annoté (le en HTML).

• U+FFFA séparateur d’annotation interlinéaire sépare le texte annoté du texte annotant, ce caractère correspond au de l’exemple en HTML.

• U+FFFB terminateur d’annotation interlinéaire signale la fin d’un texte annotant et de l’annotation ( en HTML).

1. C’est le cas d’Internet Explorer 6 et 7, pour Firefox 2 téléchargez une extension, voir . Les annotations Ruby sont définies ici : . 2. Comme nous le verrons plus loin, la notation Java \uxxxx n’accepte que quatre chiffres hexadécimaux, le « A » dans « Andries » ne peut donc faire partie d’une séquence d’échappement hypothétique \ufff9A.

168

Chapitre 8. Caractères techniques spéciaux

L’utilisation des délimiteurs d’annotation dans les textes bruts est fortement déconseillée sans accord préalable entre l’expéditeur et le destinataire car, en l’absence d’un tel accord, le contenu risque d’être mal interprété. Il est important de noter que, dès leur conception, les délimiteurs d’annotation n’étaient pas destinés à être échangés entre processus, mais devaient servir de repères temporaires internes. Depuis la version 3.1 d’Unicode, il existe une bien meilleure façon d’aborder le problème de l’annotation d’un texte et d’autres semblables comme les Caractères de remplacement : 32 positions consécutives du PMB ont été désignées comme « non-caractères » (voir § 8.3.2, Non-caractères). Par définition, ces 32 caractères ne devant pas faire partie d’un texte échangé avec un processus externe, ils peuvent donc servir de repère sans qu’on puisse les confondre avec des données. Employer les délimiteurs d’annotation dans un texte brut pose en effet problème : les processus d’affichage existants pourraient les ignorer ou les remplacer et changer ainsi le sens du texte. L’utilisation des délimiteurs d’annotation dans un texte balisé est également problématique, car l’information de formatage (où placer l’annotation, par exemple) ne fait pas partie des annotations Unicode. Dans le cas de texte HTML, il est préférable d’utiliser les balises Ruby définies à cet effet. Notez que ni Firefox ni Internet Explorer n’afficheront à la Ruby une chaîne annotée avec les trois caractères d’annotation interlinéaire d’Unicode.

8.3.2

Non-caractères Les non-caractères sont des positions du code qui sont à jamais réservées à l’usage interne d’Unicode. Ces valeurs ne peuvent être transmises, mais elles peuvent être utilisées par un processus pour son usage interne. À la réception d’un non-caractère, il est conseillé de l’éliminer ou de l’ignorer (voir § 4.5, Conformité). Il existe 66 non-caractères. Les non-caractères se trouvent codés aux 34 positions suivantes : U+nFFFE et U+nFFFF (où n est compris entre 0 et 1016) et, depuis Unicode 3.1, aux 32 positions suivantes supplémentaires [U+FDD0..U+FDEF]. La présence d’U+FFFE au début d’un flux de données Unicode suggère fortement que les octets doivent être inversés avant toute interprétation. En effet, U+FFFE correspond à un U+FEFF indicateur d’ordre des octets dont les octets sont inversés alors que l’échange du non-caractère U+FFFE est interdit. Les valeurs U+FFFF et U+10FFFF correspondent chacune à la valeur maximale d’une forme naturelle en mémoire. À savoir, respectivement UTF-16 pour U+FFFF et UTF-32 pour U+10FFFF. Le fait que ces valeurs représentent la valeur maximale de leur forme de stockage respective les prédestine, d’une certaine manière, à servir de sentinelles qui indiquent, par exemple, la fin d’une liste de caractères Unicode.

8.4

POSITIONS NON ATTRIBUÉES Il s’agit des codets auxquels on n’a pas encore attribué de fonction. Un processus conforme ne doit pas utiliser ces positions. Si votre programme a besoin de positions

8.5 Caractères déconseillés et désuets

169

pour des besoins internes ou même pour des échanges de gré à gré, il doit utiliser les zones à usage privé (voir § 8.6, Zones à usage privé).

8.5

CARACTÈRES DÉCONSEILLÉS ET DÉSUETS Un caractère déconseillé ou à éviter est un caractère inclus dans Unicode, le plus souvent pour des raisons de compatibilité avec des codages préexistants importants, qu’Unicode et l’ISO/CEI 10646 déconseille formellement d’utiliser. L’inclusion par erreur d’un caractère peut également expliquer le fait qu’on le déclare « déconseillé ». Unicode 5.0 déconseille l’utilisation des caractères suivants : deux diacritiques latins (U+0340, U+0341) prévus au départ comme représentation de tons vietnamiens et aujourd’hui remplacés par les diacritiques génériques équivalents, des erreurs de codage pour le khmer (U+17A3 voyelle pleine khmère ‘A’ et U+17D3 signe khmer pathamasat), les caractères de sélection de forme [U+206A..U+206F] dont le but était de contrôler l’apparence des caractères arabes. Notons que le terme anglais dans Unicode pour « déconseillé » est deprecated, il donne parfois l’impression aux francophones que le caractère dit « deprecated » sera bientôt éliminé, il n’en est rien. En effet, en vertu du principe de stabilité (voir § 3.4.9, Stabilité), Unicode garantit la prise en charge des données codées avant que ces caractères n’aient officiellement été déclarés déconseillés. Ces caractères ne seront donc jamais supprimés, mais leur emploi dans de nouvelles données est bien désormais contre-indiqué. Un caractère désuet est un caractère parfaitement valable, mais qui n’est plus que rarement utilisé dans l’orthographe contemporaine d’une écriture. Un caractère « désuet » latin typique est le U+017F ſ lettre minuscule latine s long que l’on retrouve fréquemment en style romain et en italique jusqu’au XVIIIe siècle. Aujourd’hui, il n’est plus guère utilisé qu’en style gothique (fraktur) où, par exemple, Wachstube (« tube de cire ») s’oppose à Wachſtube (« corps de garde »). En effet, le s long indique qu’il fait partie du même morphème que la lettre suivante, ici stube, « pièce, chambre, corps » alors que le s rond marque la fin d’un morphème wachs « cire ».

8.6

ZONES À USAGE PRIVÉ La zone à usage privé du PMB [U+E000..U+F8FF] est réservée aux programmeurs et aux utilisateurs qui ont besoin d’échanger des caractères qui ne sont pas normalisés. Les points de code de cette zone sont réservés à un usage privé, ils n’ont pas de sémantique précise interprétable si ce n’est par accord entre les parties concernées. Il n’existe pas de tableaux de caractères pour cette zone, car les caractères codés dans cette zone sont définis de gré à gré. Les positions du code suivantes appartenant aux plans complémentaires [U+F0000..U+FFFFD] et [U+100000..U+10FFFD] sont également réservés à l’usage privé. En UTF-16, on y accède à l’aide des seizets d’indirection.

170

Chapitre 8. Caractères techniques spéciaux

Il se peut que des versions ultérieures du standard Unicode codent parmi les caractères normaux des caractères définis auparavant par un fabricant dans une des zones à usage privé, si leur utilisation est devenue assez répandue. Les positions de code dans cette zone sont définitivement réservées à un usage privé — le consortium Unicode n’avalisera jamais l’affectation de ces codets pour normaliser des caractères officiels. Contrairement aux non-caractères, les caractères des zones à usage privé peuvent être transmis.

8.7

INDICATEUR D’ORDRE DES OCTETS Le caractère U+FEFF peut servir à :

• Indiquer l’ordre des octets. En effet, certaines architectures d’ordinateur rangent les octets dans ce qu’il est convenu d’appeler l’ordre gros-boutiste ; d’autres dans l’ordre petit-boutiste. Selon l’architecture, un texte Unicode peut aussi bien se sérialiser en ordre gros-boutiste que petit-boutiste. Toutefois, cet ordre de sérialisation n’est pas toujours signalé ce qui pose problème dans l’échange de données entre des systèmes d’architectures différentes (voir § 4.1.5, Mécanisme de sérialisation de caractères).

• Préciser le jeu de caractères. Parfois, le jeu de caractères utilisé dans un flux de caractères codés (comme dans un fichier) n’est pas précisé. On sait seulement que le flux comprend du texte, mais le jeu de caractères précis est inconnu. Dans ces deux cas, on peut se servir du caractère U+FEFF comme d’une signature pour indiquer l’ordre des octets et le jeu de caractères en utilisant la sérialisation UTF-16 décrite § 4.1.4, Forme en mémoire des caractères. Ce système fonctionne, car sa valeur à octets inversés, U+FFFE, est toujours une valeur Unicode illégale ; on peut donc, quand on est confronté à cette valeur, en conclure que le fichier a été lu dans le mauvais ordre de sérialisation ou que le fichier n’est pas un texte Unicode bien formé. En sérialisation UTF-16, U+FEFF dès le début d’un fichier ou d’un flux indique explicitement l’ordre des octets. C’est donc, en règle générale, une bonne idée de l’inclure. On peut se servir de la suite d’octets FE16FF16 comme d’une signature indiquant que le fichier contient du texte Unicode. En effet, cette suite est excessivement rare au début des fichiers de texte qui utilisent d’autres codages, qu’il s’agisse de jeux à un, à deux ou à multiples octets ; on ne risque donc pas d’être induit en erreur par de vraies données textuelles. Ainsi, pour les systèmes qui utilisent l’ISO Latin-1 (ISO/ CEI 8859-1) ou la page de code 1252 ANSI de MS Windows la suite d’octets FE16FF16 correspond à « þÿ » (thorn, y tréma), or le « ÿ » n’est normalement utilisé qu’en français après une autre voyelle (jamais un thorn) ou en néerlandais comme variante (peu orthodoxe ou archaïsante) du « ij » (à nouveau jamais après un thorn). Pour les anciens systèmes qui emploient le jeu de caractères romain Macintosh d’Apple ou le codage standard d’Adobe, cette suite représente « ˛ ˇ » (ogonek, hacek) ; enfin pour les systèmes qui utilisent d’autres pages de code habituelles IBM PC (par exemple, CP 437 ou CP 850), cette suite correspond à « ■ » (carré noir, espace insécable).

8.7 Indicateur d’ordre des octets

171

En UTF-8, l’IOO (Indicateur d’ordre des octets) correspond à la suite d’octets EF16BB16BF16. Bien que la sérialisation ne pose pas de problème en UTF-8, cette suite peut servir à détecter le jeu de caractères quand celui-ci n’est pas explicitement signalé. Tout comme dans le cas de l’IOO en UTF-16, cette suite est extrêmement rare au début des fichiers de texte codés dans les autres jeux de caractères. Ainsi, dans les systèmes qui emploient la page de code 1252 ANSI de MS Windows, la suite EF16BB16BF16 correspond-elle à la suite « ï«¿ » (i tréma, guillemet ouvrant, point d’interrogation renversé). Tableau 8.1 – Signatures des formes de stockage Unicode Forme de stockage

Signature

UTF-8

EF BB BF

UTF-16 gros-boutiste

FE FF

UTF-16 petit-boutiste

FF FE

UTF-32 gros-boutiste

00 00 FE FF

UTF-32 petit-boutiste

FF FE 00 00

Si l’IOO n’avait comme seule fonction que l’indication d’ordre des octets, on pourrait le supprimer une fois l’ordre des octets et le jeu de caractères connus. Malheureusement, pour des raisons historiques, l’indicateur d’ordre d’octets a également eu le sens d’une espace sans chasse insécable avant la codification de l’U+2060 gluon de mots. La conservation d’un IOO peut produire un fâcheux effet de bord quand on effectue un copier-coller. C’est, par exemple, le cas quand il passe du sens d’indicateur d’ordre des octets en début de texte à celui d’espace sans chasse insécable au milieu d’un texte. C’est pourquoi on recommande de considérer tout U+FEFF initial comme un indicateur d’ordre des octets et de le supprimer avant de traiter le texte qui le contient. On ne peut en faire autant des U+FEFF au sein du texte, puisqu’il faut continuer à les traiter là comme des espaces sans chasse insécables malgré le codage du U+2060 gluon de mots. Notons enfin, l’ancienne convention qui consistait à utiliser deux U+FEFF successifs en début de texte pour y indiquer une espace insécable sans chasse dès le début du texte, les applications doivent continuer à prendre en charge cette convention.

8.8

ÉTIQUETTES LINGUISTIQUES Les caractères de ce bloc [U+E0000..U+E007F] fournissent un mécanisme d’étiquetage linguistique au sein des textes bruts Unicode. Toutefois, leur utilisation est fortement déconseillée. Les caractères de ce bloc doivent s’utiliser avec des protocoles particuliers. Il est interdit de les employer en l’absence de ces protocoles ou avec n’importe quel protocole qui fournirait un autre mécanisme d’étiquetage linguistique, comme HTML ou XML. En outre, on exagère souvent le besoin d’insérer des informations

172

Chapitre 8. Caractères techniques spéciaux

linguistiques dans les données textuelles brutes par exemple pour distinguer des kanjis surunifiés, kanjis qui peuvent être désunifiés grâce à un autre mécanisme : les sélecteurs de variante (voir § 13.2, Sélecteurs de variante). Ce bloc comprend des clones des caractères ASCII qu’Unicode définit comme des étiquettes invisibles (sans chasse et sans effet graphique). Ces clones permettent d’écrire le nom d’une langue associé aux caractères suivants. On peut, par exemple, utiliser U+E0066 (clone de « f ») et U+E0072 (clone de « r ») pour indiquer qu’une suite de caractères subséquents est en français. Les étiquettes linguistiques doivent se conformer au RFC 4646, qui définit la syntaxe des étiquettes linguistiques à utiliser sur Internet. Nous reviendrons en plus de détails sur le RFC 4646 au chapitre suivant (voir § 9.5, RFC 4646 – Étiquettes de langue). Le RFC 4646 utilise les indicatifs de langue définis dans l’ISO 639 et (facultativement) les indicatifs de pays définis dans l’ISO 3166 pour former des étiquettes du type « fr-BE » (français de Belgique), « zhcmn » (chinois mandarin ou putonghua) ou encore, plus compliqué, « zh-yue-HantHK » (chinois cantonais en écriture traditionnelle comme à Hong-Kong). Les processus conformes ne sont pas obligés d’interpréter ces étiquettes, toutefois s’ils sont interprétés alors ils doivent l’être conformément à Unicode. Il existe un utilitaire gratuit, LTag1, destiné aux systèmes Windows. Il est conçu pour les éditeurs de texte Unicode brut comme Notepad (sous Windows 2000 et XP) ou SC UniPad. Il permet à l’utilisateur de créer des étiquettes linguistiques du plan 14 à l’aide d’une interface utilisateur conviviale, sans devoir se soucier de leur syntaxe, d’obscures abréviations ou des suites de seizets d’indirection. Ces caractères sont fortement déconseillés car ils introduisent la notion d’état : l’effet d’une étiquette s’étend sur jusqu’à cette étiquette soit explicitement annulée ou le texte prenne fin. Ceci rend toute opération de copier-coller plus complexe. Abstenez-vous donc d’utiliser ces caractères d’étiquetage linguistique et utilisez plutôt du balisage pour indiquer la langue d’un texte.

1.

Résumé

173

Résumé Unicode n’attribue pas de sens particulier aux caractères de commande C0 et C1, mais les prévoit uniquement afin de permettre leur transmission sans perte, Unicode n’ajoute ni ne soustrait rien à leur sémantique. Ce sens dépendra, en règle générale, de l’application qui utilisera ces caractères. Le gluon de mots (U+2060) se comporte comme l’espace insécable (U+00A0), car il indique l’absence de frontière de mots, en revanche, contrairement à U+00A0, le gluon de mots n’a pas de chasse. La fonction de ce caractère consiste à empêcher la division entre les deux caractères qui en sont voisins sauf si un de ceux-ci est un passage à la ligne forcé. Le gluon de mots (U+2060) ne doit pas être confondu avec l’U+034F diacritique invisible bloquant qui lui non plus n’a pas d’œil. U+034F diacritique invisible bloquant (abrégé en DIB) a deux fonctions principales : d’une part modifier l’ordonnancement (le tri) des caractères qui le jouxtent en évitant la formation de contractions et d’autre part empêcher le réordonnancement des diacritiques qu’il sépare lors de la mise en ordre canonique de ceux-ci. Unicode prévoit aussi des caractères d’annotation linéaire. L’utilisation des délimiteurs d’annotation dans les textes bruts est fortement déconseillée sans accord préalable entre l’expéditeur et le destinataire, on préfère déléguer cette fonction à un protocole de haut niveau comme HTML et la notation Ruby. Selon la polarité des machines, un texte Unicode peut aussi bien se sérialiser en UTF-16 ou en UTF-32 selon l’ordre gros-boutiste que petit-boutiste. Toutefois, cet ordre de sérialisation n’est pas toujours signalé ce qui pose problème dans l’échange de données entre des systèmes d’architectures différentes. Inclure le caractère U+FEFF comme premier caractère d’un texte permet d’indiquer l’ordre des octets. Ce caractère sert également de signature, pour indiquer qu’il s’agit d’un texte Unicode ; c’est ainsi qu’U+FEFF est également utilisé en UTF-8, forme qui ne souffre pourtant pas du problème de polarité. Les 66 non-caractères définis par Unicode sont des positions du code qui sont à jamais réservées à l’usage interne des processus Unicode. Ces valeurs ne peuvent être transmises, mais elles peuvent être utilisées par un processus pour son usage interne. La présence d’U+FFFE au début d’un flux de données Unicode suggère fortement que les octets doivent être inversés avant toute interprétation. En effet, U+FFFE correspond à un U+FEFF indicateur d’ordre des octets dont les octets sont inversés alors que l’échange du non-caractère U+FFFE est interdit. Les zones à usage privé sont réservées aux programmeurs et aux utilisateurs qui ont besoin d’échanger des caractères qui ne sont pas normalisés. Les points de code de ces zones sont réservés à un usage privé, ils n’ont pas de sémantique précise interprétable si ce n’est par accord entre les parties concernées. Contrairement aux non-caractères, les caractères des zones à usage privé peuvent être transmis.

Un caractère déconseillé ou à éviter est un caractère inclus dans Unicode, le plus souvent pour des raisons de compatibilité avec des codages préexistants importants, qu’Unicode et l’ISO/CEI 10646 déconseille formellement d’utiliser. Un caractère désuet est un caractère parfaitement valable, mais qui n’est plus que rarement utilisé dans l’orthographe contemporaine d’une écriture. Un processus conforme ne doit pas utiliser les positions non attribuées par Unicode. Si votre programme a besoin de positions pour des besoins internes ou même pour des échanges de gré à gré, il doit utiliser les zones à usage privé. Les caractères du bloc [U+E0000..U+E007F] fournissent un mécanisme d’étiquetage linguistique au sein des textes bruts Unicode. Toutefois, leur utilisation est fortement déconseillée et on leur préfère l’envoi de cette information linguistique à l’aide d’un protocole de haut niveau comme HTTP, HTML ou XML.

QUATRIÈME PARTIE

Applications et techniques liées à Unicode

9 Préciser la langue, l’écriture et le pays

Objectif Préciser la langue, ainsi que d’autres informations culturelles comme le pays d’où provient le scripteur, et les appliquer à des données Unicode permet : – de résoudre les ambiguïtés d’affichage (exemple : « désunifier » les caractères CJC) ; – de rendre la synthèse vocale possible ; – afficher la bonne version linguistique d’une page Internet ; – de mieux effectuer la coupure de lignes et de mots ; – d’obtenir de meilleurs résultats quand on classe, cherche ou trie ces données ; – permettre la correction orthographique, la transcription en braille. En règle générale, on peut dire que la langue est orthogonale au codage de caractères : connaître le codage d’un texte ne permet pas d’en deviner la langue. C’est ainsi qu’un texte codé en Latin-1 peut très bien être en anglais, en espagnol ou en français, voire les trois à la fois. Dans les paragraphes qui suivent, nous allons passer en revue les normes qui établissent la manière de préciser la langue et d’autres métadonnées culturelles d’importance. Ces normes nous serviront dans les chapitres techniques suivants qui traitent des protocoles Internet, de l’internationalisation de HTML et XML et, enfin, de l’internationalisation des logiciels. Le dernier chapitre de cette partie traite des polices et du passage d’un flux de caractères Unicode à une série de glyphes.

178

9.1

Chapitre 9. Préciser la langue, l’écriture et le pays

ISO 639 – INDICATIFS DE LANGUE L’ISO 639 est une norme internationale qui définit des indicatifs pour la représentation des noms de langues. Elle est actuellement composée de trois parties. Sa première partie, l’ISO 639-11 (alpha-2), utilise des codets ou indicatifs sur deux caractères, et les associe à des noms de langue en français et en anglais. L’ISO 639-22 (alpha-3) utilise des codets sur trois caractères et connaît deux formes de codages possibles : ISO 639-2/B (bibliographique) et ISO 639-2/T (terminologique). En règle générale, les indicatifs bibliographiques ressemblent à ceux définis par la norme américaine Z39.53 et s’inspirent des noms qui désignent ces langues en anglais, alors que les indicatifs terminologiques ressemblent aux noms que ces langues se donnent. Enfin, l’ISO 639-33 complète l’ISO 639-2 ; seuls des noms en anglais sont associés aux nouveaux indicatifs, bien que la base de données de l’Ethnologue4 d’où sont tirés ces codes possède souvent des noms français pour les langues parlées dans les zones francophones comme l’Afrique occidentale ou centrale. Tableau 9.1 – Les différentes parties de l’ISO 639 Partie

Type d’indicatif

Nombre d’indicatifs

Exemples

ISO 639-1

à deux lettres

136

« fr » pour le français, « wa » pour le wallon, « ar » pour l’arabe.

ISO 639-2

à trois lettres

484

« fre » et « fra » pour le français, « ber » pour le berbère

ISO 639-3

à trois lettres

7581

« fra » pour le français, « rif » pour le rifain, « acf » pour le créole français des Antilles.

L’ISO 639 n’est pas un registre stable. On y ajoute, de temps à autre, de nouveaux indicatifs et plusieurs langues en ont changé. C’est le cas de l’hébreu, de l’indonésien et du yidiche qui, pour deux d’entre eux, sont passés à des indicatifs qui s’inspirent de leur nom ou graphie en anglais plutôt que dans la langue en question (de « iw » à « he » et de « ji » à « yi »). Les logiciels doivent prendre en charge les deux versions de ces indicatifs et les considérer comme synonymes.

1. Liste non officielle sur . 2. Liste sur . 3. Liste sur . 4. Voir .

9.1 ISO 639 – Indicatifs de langue

179

Tableau 9.2 – Quelques indicatifs tirés de l’ISO 639-1 Indicatif ISO 639-1

Langue

ar

arabe

de

allemand

el

grec

en

anglais

es

espagnol

fr

français

It

italien

jp

japonais

nl

néerlandais

pt

portugais

ru

russe

vi

vietnamien

zh

chinois

Vingt-deux langues ont dans l’ISO 639-2 deux codets (indicatifs) différents : l’un bibliographique (ISO 639-2/B) et l’autre terminologique (ISO 639-2/T). C’est le cas du français qui s’écrit « fre » (bibliographique) ou « fra » (terminologique). Il faut considérer, à nouveau, ces indicatifs comme synonymes. En pratique, ces doublons sont rarement utilisés puisque ces langues ont également un indicatif de deux lettres (ISO 639-1) et que les normes et standards préconisent alors l’utilisation de celui-ci. L’ISO 639-2 prévoit une zone à usage local qui s’étend de « qaa » à « qtz », l’ISO n’affectera ces codets à aucune langue normalisée. Ces indicatifs peuvent être utilisés par accord commun entre des tiers. Dans les applications qui utilisent les codets de langue ISO 639, il est préférable d’utiliser en premier lieu un indicatif alpha-2 de l’ISO 639-1, s’il existe. Si ce n’est le cas, on choisira le codet alpha-3 de l’ISO 639-2/B. Enfin, en dernier ressort, on pourra utiliser les indicatifs alpha-3 de la norme ISO 639-3.

180

9.2

Chapitre 9. Préciser la langue, l’écriture et le pays

ISO 3166 – INDICATIFS DE PAYS Les indicatifs de pays normalisés par l’ISO 3166-11 forment un deuxième type de renseignement culturel. L’ISO 3166-1 comprend trois répertoires différents : alpha-2, alpha-3 et numérique-3. L’ISO 3166-1 alpha-2 définit une série d’indicatifs de pays sur deux lettres, c’est la liste qui nous intéresse ici. Alpha-3 précise des codets de pays sur trois lettres. Il existe également une norme ISO 3166-2, codée à l’aide de quatre lettres, qui permet de désigner des subdivisions de pays. Tableau 9.3 – Quelques indicatifs de pays ISO 3166-1 à deux lettres Pays

Indicatif

Algérie

DZ

Allemagne

DE

Andorre

AD

Belgique

BE

Canada

CA

États-Unis d’Amérique

US

Espagne

ES

France

FR

Italie

IT

Liban

LB

Luxembourg

LU

Maroc

MA

Maurice

MU

Monaco

MC

Tunisie

TN

Royaume-Uni

GB

Suisse

CH

1. On peut consulter gratuitement la liste officielle complète à l’adresse suivante : .

9.3 ISO 15924 – Indicatifs d’écriture

181

Les codets ISO 3166-1 (sur deux lettres) correspondent habituellement aux noms de domaine de tête par pays (en anglais, « Country Coded Top Level Domains », abrégé en ccTLD) utilisés dans l’attribution des adresses Internet (voir le « fr » dans « dunod.fr »). Il existe quelques exceptions dont la plus notable est sans doute celle du Royaume-Uni qui a un indicatif 3166 égal à « GB » (Grande-Bretagne), mais dont le domaine Internet est « .uk » (« United Kingdom », Royaume-Uni). On remarque que, à l’instar de l’ISO 639, l’ISO 3166 n’est pas un ensemble figé d’indicatifs, certains pays naissent (par exemple à la suite de l’éclatement de l’Union soviétique), d’autres changent de nom et voient leur indicatif tomber en désuétude ou être repris par un autre pays. C’est le cas des Territoires des Afars et Issas, aujourd’hui Djibouti, dont le codet AI a été repris par l’île d’Anguilla. Il en va de même du codet GE, anciennement attribué aux îles Gilbert et Ellice devenues Tuvalu, et maintenant utilisé par la Géorgie. On imagine facilement les problèmes de données historiques qui utiliseraient les codets 3166 pour indiquer un pays. Ce genre de complication est d’ailleurs à la source d’une récente norme internet sur laquelle nous reviendrons bientôt : le RFC 4646.

9.3

M.49 – INDICATIFS DE PAYS ET DE RÉGIONS Les codets ONU M.49 sont des indicatifs à trois chiffres attribués par la division de la statistique de l’ONU. Ils ne correspondent pas toujours à des pays ; le codet 001, par exemple, représente le monde entier, 002 l’Afrique et 015 l’Afrique septentrionale. Le codet à trois chiffres d’un pays défini dans l’ISO 3166-1 numérique-3 est identique au codet M.49 défini pour le même pays. Toutefois, certains indicatifs M.49 n’ont pas de correspondance ISO 3166-1 quand ils représentent une région supranationale ou infranationale. Ainsi, les îles Anglo-Normandes dont l’indicatif M.49 est 830 n’ontelles pas de codet ISO 3166-1 car, bien qu’indépendantes du Royaume-Uni, elles ne forment pas une seule entité politique autonome, mais deux bailliages indépendants — Guernesey et Jersey — dont le lien est leur suzerain, la reine Elizabeth II. En revanche, Guernesey (un des bailliages et une entité politique autonome) a bien un même indicatif M.49 et ISO 3166-1 numérique-3 : 8311.

9.4

ISO 15924 – INDICATIFS D’ÉCRITURE L’ISO 15924 définit un indicatif pour près de 150 systèmes d’écriture différents. Nous en reproduisons quelques-uns dans le tableau 9.4, la liste complète peut être consultée à l’adresse suivante : . Rappelons que le français, par exemple, relève de l’écriture latine (Latn).

1. Liste complète officielle ici : .

182

Chapitre 9. Préciser la langue, l’écriture et le pays

Tableau 9.4 – Quelques indicatifs d’écriture Indicatif

9.5

Signification

Arab

Arabe

Copt

Copte

Cyrl

Cyrillique

Grek

Grec

Hani

Idéogrammes japonais

Hans

Idéogrammes chinois simplifiés

Hant

Idéogrammes chinois traditionnels

Latf

Latin brisé (« fraktur » ou gothique)

Latn

Latin

Tfng

Tifinagh (tifinar)

RFC 4646 – ÉTIQUETTES DE LANGUE L’Internet Engineering Task Force, en abrégé IETF, littéralement le « Détachement d’ingénierie d’Internet », est un regroupement informel d’experts qui élabore les standards de l’Internet. Les Request For Comment (RFC, les demandes de commentaires) sont une série de documents portant sur l’Internet émis par l’IETF. Peu de ces RFC sont des standards, mais tous les standards de l’Internet sont enregistrés en tant que RFC. Chaque RFC porte un numéro séquentiel unique. Une fois adopté, un RFC n’est jamais modifié ou retiré. Si un RFC doit être modifié, on publie un autre RFC (avec un autre numéro) qui le remplace. C’est ce qui c’est produit en 2006 quand le RFC 4646 a complété et remplacé le RFC 3066 qui définissait déjà des étiquettes linguistiques. Toutes les étiquettes de langue définies selon le RFC 3066 restent conformes au RFC 4646. Les étiquettes de langue du RFC 4646 consistent en une série de sous-étiquettes séparées par des traits d’union, les étiquettes ne sont pas sensibles à la casse. Voici un aperçu des règles de construction des étiquettes définies par le RFC 4646 (nous expliquerons cette « grammaire » ci-après).

9.5 RFC 4646 – Étiquettes de langue

Une étiquette de langue consiste en étiqlang -ou- usage-privé -ou- patrimonial étiqlang

183

; étiquette générative ; une étiquette privée ; anciennes valeurs enregistrées

= (langue ["-" écriture] ["-" région] *("-" variante) *("-" extension) ["-" usage privé])

langue

= "fr", "ale"... ; codets ISO 639 le plus court ou ; une valeur enregistrée auprès de l’IANA

écriture

= "Latn", "Cyrl", "Hant"... ; codets ISO 15924 (4 lettres)

région

= "US", "CS", "FR"... ; codets ISO 3166 à 2 lettres "419", "019"... ; codets ONU M.49 à 3 chiffres

variante

= "rozaj", "1996"... ; plusieurs sous-étiquettes permises ; de 4 à 8 alphanumériques

extension

= une lettre suivie de sous-étiquettes, plusieurs extensions sont permises pour une même étiquette de langue.

usage-privé = "x-" suivi de sous-étiquettes, autant que nécessaires, peuvent être en début ou en fin d’étiquette, mais pas au milieu. patrimonial = étiquettes reprises de l’ancien registre qui ne sont pas des doublons (une liste fermée).

Chaque type de sous-étiquette a une longueur précise et des restrictions quant à son contenu. L’étiquette commence toujours par la sous-étiquette « langue » qui peut être un codet ISO 639-1, ISO 639-2 ou une autre valeur enregistrée auprès de l’IANA1. Elle peut être suivie de différentes sous-étiquettes. Il existe à l’heure actuelle cinq types de sous-étiquettes qui peuvent suivre l’indicatif de langue2 : l’écriture, la région, les variantes, les extensions et l’usage privé. L’ordre, la longueur et le contenu de chaque sous-étiquette sont bien établis. Toutes les sous-étiquettes légitimes sont consignées dans un registre unique tenu à jour par l’IANA, plutôt que les différentes agences de mise à jour des normes ISO comme c’était le cas pour le RFC 3066. Pour la sous-étiquette « langue », l’IANA n’enregistre qu’un seul codet par langue, alors que l’ISO pouvait en avoir normalisé plusieurs (trois

1. L’IANA est un organisme américain responsable de la gestion de l’espace d’adressage IP d’Internet et d’autres ressources requises par les protocoles de communication sur Internet. 2. Pour être tout à fait complet, la grammaire ci-dessus devrait indiquer que l’indicatif de langue peut être composé non seulement d’un indicatif ISO 639 (ou d’une valeur enregistrée à l’IANA), mais également d’une « extlang » après un « - ». Toutefois, ces extlangs n’ont jamais été officiellement enregistrés par l’IANA et ils seront probablement abandonnés dans la prochaine version du RFC 4646.

184

Chapitre 9. Préciser la langue, l’écriture et le pays

pour le français par exemple : « fr », « fra » et « fre »). Si un codet ISO à deux lettres est disponible, celui-ci apparaîtra dans le registre plutôt que le codet à trois lettres. Voici l’entrée pour la sous-étiquette de langue « es » dans le registre de l’IANA : %% Type: language Subtag: es Description: Spanish Description: Castilian Added: 2005-10-16 Suppress-Script: Latn %%

La ligne « Suppress-Script » indique qu’il ne faut pas mentionner l’écriture de cette langue quand elle est égale à « Latn ». Ceci afin de décourager la prolifération d’étiquettes pléonastiques comme « es-Latn ». La règle d’or quand on crée des étiquettes linguistiques se résume à toujours utiliser la forme la plus courte possible. Il faut éviter de préciser les sous-étiquettes comme la région, l’écriture ou les autres sous-étiquettes facultatives, sauf si elles apportent une information utile. Ainsi faut-il utiliser « ja » pour le japonais et non « ja-JP » à moins que vous teniez absolument à dire qu’il s’agit du japonais parlé au Japon... Le tableau 9.5 énumère quelques étiquettes linguistiques. Les changements les plus importants par rapport au précurseur du RFC 4646, c’est-à-dire le RFC 3066, ont trait au fait que la syntaxe du RFC 4646 est désormais plus rigoureuse que celle de son prédécesseur, que l’IANA tient à jour de manière permanente, stable et gratuite un seul registre unifié et qu’aucun codet ne disparaîtra ou ne sera affecté à une autre entité. L’Internet impose que « cs-CS », une fois valide, reste valide bien que la Tchécoslovaquie ait disparu, en tant qu’entité politique distincte, après l’enregistrement des codets en question. Le registre de l’IANA continue de suivre les normes de l’ISO mentionnées précédemment, mais il ne supprime jamais une sous-entrée et des règles claires ont été établies si des conflits entre ce registre et les listes de l’ISO venaient à surgir.

9.7

BCP 47 Pour éviter qu’une norme ne mentionne un RFC qui risque de devenir désuet, l’IETF recommande aujourd’hui aux auteurs de normes de renvoyer dans le texte de ces normes à des Best Current Practice (« les Meilleures pratiques actuelles ») plutôt qu’à d’autres RFC. Les numéros de BCP ne changent pas, mais leur dernière version suit les derniers développements dans leur domaine. Le BCP 47 regroupe les meilleures pratiques actuelles liées à l’indication de langue d’un document, d’une partie de document ou d’un objet. Le BCP 47 est composé des RFC 4646 et 4647 qui remplacent le RFC 3066, désormais désuet, lequel avait déjà remplacé le RFC 1766. Nous avons le vu contenu du RFC 4646 ci-dessus. Le RFC 4647, quant à lui, stipule comment comparer les étiquettes linguistiques définies par le RFC 4646.

9.7 BCP 47

185

La prochaine version du BCP 47 devrait comprendre le RFC 4646bis qui remplacera le RFC 4646. Ce nouvel RFC est bien avancé, il introduira les codes de langue de l’ISO 639-3 ; une étiquette patrimoniale comme « zh-yue » (chinois cantonais) y sera remplacée par « yue » (cantonais). Tableau 9.5 – Quelques étiquettes linguistiques Étiquette

Explications

fr

Le français.

ja

Le japonais.

i-enochian

Exemple d’étiquette patrimoniale : l’énochien104.

zh-Hant

Le chinois en écriture chinoise traditionnelle.

zh-Hans

Le chinois écrit à l’aide de l’écriture chinoise simplifiée.

sr-Cyrl

Le serbe en cyrillique.

sr-Latn

Le serbe en latin.

sl-Latn-IT-nedis

Le dialecte slovène de Nadiza écrit en latin tel qu’utilisé en l’Italie (étiquette non recommandée puisque le « Latn » est redondant pour le slovène, en d’autres termes l’entrée pour « sl » dans le registre de l’IANA a un « Suppress-Script » pour « Latn »).

Sl-IT-nedis

Comme ci-dessus, mais sans l’écriture redondante et déconseillée. Cette étiquette est donc meilleure que celle ci-dessus.

de-CH-1901

L’allemand en Suisse écrit avec la variante orthographique de 1901.

zh-yue-Hant-HK

Le cantonais en écriture chinoise traditionnelle à Hong Kong (« zh-yue » est ici un code patrimonial).

1. L’énochien ou « langue des anges » est une langue occulte proposée par les alchimistes anglais John Dee et Edward Kelley au XVIe siècle. Il possède son propre alphabet qu’Unicode n’a pas inclus (on le considère comme une simple transposition de l’aphabet anglais). Le codet i-enochian est un indicatif linguistique, pas un indicatif d’écriture.

186

Chapitre 9. Préciser la langue, l’écriture et le pays

Résumé Indiquer la langue d’un texte ou d’un passage de ce texte s’avère utile pour de nombreux processus, qu’il s’agisse de la vérification orthographique, du repérage de texte comme Google, de trier ce texte ou encore d’en permettre la synthèse vocale. La syntaxe des étiquettes linguistiques est définie par le BCP 47 qui est actuellement constitué des RFC 4646 et 4647. Chaque étiquette linguistique est composée d’une ou plusieurs « sous-étiquettes » séparées par des traits d’union. Si l’on excepte les étiquettes à usage privé et les étiquettes patrimoniales conservées pour des raisons de compatibilité arrière, les sous-étiquettes doivent se présenter dans l’ordre suivant : – une sous-étiquette qui représente la langue ; – une sous-étiquette optionnelle qui représente l’écriture ; – une sous-étiquette optionnelle pour la région ; – une série optionnelle de sous-étiquettes représentant les variantes ; – une série optionnelle de sous-étiquettes représentant des extensions ; – une série optionnelle de sous-étiquettes à usage privé. Exemples : es représente l’espagnol, fr-CA est le français au Canada, zh-Hant-HK est le chinois écrit en chinois simplifié à Hong-Kong.

10 Unicode et les protocoles Internet

Objectif Ce chapitre décrit la manière dont l’information relative au codage de caractères est transmise à l’aide des protocoles Internet (MIME et HTTP) qu’il s’agisse de courriers électroniques ou de pages web. Nous verrons aussi comment préciser la négociation de langues et de codages de caractères. Nous décrirons la manière dont les caractères sont transmis dans les entêtes et les URL. Nous aborderons enfin le sujet des noms de domaine internationalisés et des URL internationalisées.

10.1 DE L’UTILITÉ DES MÉTADONNÉES L’information transmise sur Internet est codée sous forme numérique. Il s’agit en fin de compte d’octets et de bits. Sans information sur le codage adopté lors de la numérisation, le destinataire devra se résoudre à deviner le format des données, ce qui entraîne souvent des erreurs. Il faut se souvenir que les données peuvent aussi bien présenter des données textuelles que des images ou du code binaire. Il se pourrait que vous utilisiez l’Internet depuis belle lurette sans n’avoir jamais eu de problèmes avec les codages parce que les valeurs d’« usine » sont correctes dans la majorité des cas. Ainsi, il est fort probable que votre logiciel de messagerie envoie vos courriels en ISO-8859-1 (le Latin-1) ou Windows 1252. En l’absence d’étiquette indiquant le jeu de caractères, le logiciel de messagerie de votre correspondant interprétera sans doute votre message comme du texte brut codé en Windows 1252. Et tout se passera parfaitement, car l’ISO-8859-1 est un sous-ensemble de Windows 1252.

188

Chapitre 10. Unicode et les protocoles Internet

Les choses se compliquent quand le codage transmis est totalement différent : l’utilisateur se rendra compte qu’il y a un problème, mais il n’aura la plupart du temps pas d’autre solution que d’essayer manuellement toute une série de codages jusqu’à ce qu’il obtienne un texte lisible. Mais a-t-il exactement le codage qu’il faut ? En effet, il est souvent facile de comprendre un texte, même s’il est mal codé, voire parfois de ne pas se rendre compte du fait qu’il est mal codé. Prenons l’exemple d’un correspondant qui vous envoie un message en français codé à l’aide d’ISO-8859-15 (le Latin-9) sans entête, votre logiciel ou vous-même décidez de décoder celui-ci comme du Windows 1252, tout semble lisible. Mais voilà, il se peut très bien que le document qu’on vous envoie contienne un S caron « Š » qui est codé à la position 0xA6 en Latin-9, mais que votre logiciel affichera comme une barre discontinue « ¦ » puisqu’il s’agit du caractère Latin-1 codé à cette position. Il est possible que vous ne vous rendiez jamais compte que le fichier reçu est corrompu. Toutes ces considérations ont poussé les architectes des protocoles à ajouter — assez tardivement malheureusement — des métadonnées sous la forme d’entêtes aux messages transmis pour en indiquer le type et le codage.

10.2 LES PREMIERS PROTOCOLES INTERNET Les premiers protocoles de l’Internet qui permettaient de transférer du texte ne prévoyaient habituellement pas l’utilisation d’autres caractères que les caractères ASCII et n’avaient donc pas ressenti le besoin de permettre l’identification du codage utilisé dans la transmission des textes. Comme c’est encore le cas pour FTP qui ne permet de distinguer qu’entre texte brut en « ASCII » ou EBCDIC et fichier binaire1. Ainsi, lorsqu’on télécharge un fichier texte avec FTP, le protocole ne permet pas de savoir si ce fichier est codé en Windows 1252, en KOI8-R ou encore en UTF-8. Le courrier électronique Internet, une des plus anciennes applications, est fondé sur le protocole SMTP (RFC 821 remplacé par le RFC 2821 depuis 2001) et sur un format de message standardisé connu sous le nom de document constitutif (le format RFC 822, devenu RFC 2822 depuis 2001). Ces deux standards Internet spécifiaient explicitement l’usage exclusif du jeu de caractères ASCII, ce qui ne permettait que la transmission de textes bruts en anglais. Le RFC 822 et son successeur, le RFC 2822, décrivent un ensemble d’entêtes composés d’un nom et d’une valeur séparés par un deux-points. Ces entêtes sont séparés du corps du message par une ligne blanche. Tous les entêtes sont en ASCII pur et ne permettent donc pas de lettres accentuées.

1. FTP permet de préciser si un fichier est en « ASCII » (ou EBCDIC) ou en binaire. Si les systèmes source et cible n’utilisent pas la même convention pour indiquer le passage à la ligne, la transmission en mode « ASCII » effectuera les conversions nécessaires. En mode binaire, cette conversion n’a pas lieu et le transfert est complètement transparent, ce qui est approprié pour des images, des programmes, des nombres au format binaire, données où la notion de ligne de texte ne joue pas. Quand on parle ici d’ASCII, il faut comprendre le jeu de caractères local basé sur ASCII (qui a donc les retours de chariot et de passage à la ligne au même endroit que l’ASCII) ; sur MS Windows, par exemple, cela signifie Windows 1252 pour une machine française.

10.3 Type de médias Internet/type MIME

189

Il y eut une tentative infructueuse (ESMTP) d’étendre le protocole SMTP pour permettre la transmission de caractères à 8 bits, cette méthode n’a été adoptée que lentement en pratique, pour plusieurs raisons liées notamment à son caractère optionnel et le besoin pour les agents de messagerie de négocier le passage à 8 bits. Ce qui a réellement permis la transmission de messages codés dans d’autres codages que l’ASCII fut l’avènement de MIME1. Celui-ci normalisait enfin la transmission d’informations sur le codage réellement utilisé à l’expédition d’un courriel, ce qui permet au destinataire de décoder le message sans incertitude. MIME devint vite universel — même auprès des anglophones qui se sentaient bien à l’aise avec l’ASCII jusque-là — parce qu’il permettait également la transmission fiable d’images, de son, de vidéos, de fichiers binaires d’applications, etc.

10.3 TYPE DE MÉDIAS INTERNET/TYPE MIME Comme nous l’avons vu, MIME définit des mécanismes pour l’envoi de diverses sortes d’information dont des textes écrits dans des langues autres que l’anglais et des données binaires comme des fichiers contenant des images, des sons, des films ou des programmes informatiques. Les entêtes définis par MIME forment également une composante fondamentale des protocoles de communications comme HTTP qui doivent préciser le type de données transmises même s’il ne s’agit pas de courriels.

10.3.1

Visualiser les entêtes

Regardons à quoi peuvent ressembler les entêtes MIME associés à un message contenant plusieurs caractères Unicode (figure 10.1). Les logiciels de messagerie les cachent habituellement et ne font apparaître que l’objet du message, l’expéditeur, la date d’envoi et la date de réception. Chaque logiciel permet, à sa façon, de les révéler. Dans Thunderbird2, on peut appuyer sur le petit signe « + » qui apparaît à gauche de l’objet du message (si vous avez activé l’option « En-têtes complets ») ou passer par le menu « Affichage » puis « Code source du message » (Ctrl+U). C’est cette dernière option que nous avons choisie dans la seconde illustration (figure 10.2). D’autres programmes de messagerie utilisent parfois d’autres méthodes pour faire apparaître les entêtes ou afficher le message en format « brut » ou « source ». Généralement, l’option appropriée se trouve dans le menu « Fichier » ou « Affichage ». Dans le cas de MS Outlook Express, on y accède par le menu « Fichiers » suivi de « Propriétés ».

1. La Multipurpose Internet Mail Extension (Extension polyvalente aux courriers Internet) ou MIME est défini par cinq RFC : RFC 2045, RFC 2046, RFC 2047, RFC 2048 et RFC 2049. Cependant, le RFC 2048 est désormais désuet, il a été remplacé par les RFC 4288 et 4289. Il existe, de surcroît, une vingtaine d’autres RFC liés au format MIME. Voir . 2. Dans Microsoft Outlook 2007, cliquer avec le bouton droit sur le message et choisir « Options des messages… ».

190

Chapitre 10. Unicode et les protocoles Internet

Figure 10.1 – Boîte aux lettres avec courriel Unicode

Nous discuterons en détail des entêtes de messageries ou entêtes MIME par la suite. À ce stade, pour une première approche, trois entêtes seuls nous intéressent :

• L’entête « MIME-version » qui indique que le corps du message est en format MIME (la version 1.0 pour être précis).

• L’entête « Content-Type » qui précise que ce message est du texte brut (pas balisé), codé en UTF-8 et qu’il est peut-être paragraphé format=flowed1, ce qui signifie que le message peut être reformaté selon certaines règles, contrairement au format=fixed où les lignes ont une structure fixe qui ne peut être reformatée.

• L’entête « Content-Transfer-Encoding » qui indique que les unités de codage UTF-8 ont été transmises sous la forme d’octets 8 bits (plutôt qu’à l’aide d’un surcodage de transfert comme le Quoted-Printable ou le Base64, voir plus loin pour le détail). Autre point d’intérêt : la manière dont a été codé l’objet du message. En effet, le nom des entêtes de messages et leurs valeurs sont toujours en caractères ASCII (7 bits). Les valeurs qui contiennent des données non ASCII doivent utiliser la syntaxe « encoded-word » de MIME (RFC 2047) à la place des valeurs textuelles standards. Nous verrons dans les paragraphes suivants comment la phrase « Envoyer des caractères Unicode » a pu devenir « Envoyer des =?UTF8?B?Y2FyYWN0w6hyZXMgVW5pY29kZQ==?= ».

1. Ce type de format est défini par le RFC 3676 qui précise comment coder les messages pour qu’ils soient lisibles à la fois, d’une part, à l’aide d’un logiciel de présentation « simplet » et, d’autre part, reformatables pour un affichage dans les meilleures conditions. En gros, un espace à la fin d’une ligne indique que le saut de ligne suivant est optionnel et qu’il peut être remplacé. Ce format permet également de traiter le cas des citations introduites par un caractère « > » qui doivent être reformatées.

10.3 Type de médias Internet/type MIME

191

Figure 10.2 – Code source d’un courriel Unicode

10.3.2 Les types de média ou types de contenu Parmi la liste d’entêtes, la ligne d’entête la plus importante est sans nul doute celle appelée Content-Type (type de contenu), qui informe le client du type de données que le serveur lui transmet : texte HTML, texte simple, image GIF, son AU, etc. Les types de média Internet, à l’origine appelés « types MIME », permettent de décrire le format de fichiers envoyés sur Internet. Prévue à l’origine pour l’envoi de courriels plus riches que les textes bruts en ASCII du SMTP originel, leur utilisation a été étendue à d’autres protocoles comme HTTP et SIP1. Un type de média est composé d’au moins deux parties : un type (par exemple text), un sous-type (html) et un ou plusieurs paramètres optionnels. Ainsi, les sous-types du type text peuventils être accompagnés d’un paramètre charset pour préciser leur codage de caractères (UTF-8, ISO-8859-1) et les sous-types de multipart définissent souvent un boundary (une sentinelle) qui délimite les différentes parties du message.

1. SIP est la forme abrégée du Session Initiation Protocol défini par les RFC 3261 et 3265. SIP est le standard ouvert de VoIP (voix sur IP) le plus répandu.

192

Chapitre 10. Unicode et les protocoles Internet

Tableau 10.1 – Les principaux types de média définis à l’heure actuelle Type principal

Désigne

application

Format de données qui dépend d’une application. Il peut s’agir de données binaires ou non. Le sous-type application/octet-stream désigne des données binaires à la structure inconnue ou non définie, application/javascript désigne un programme JavaScript. Quant à application/xhtml+xml, il permet de désigner un fichier XHTML (successeur d’HTML).

audio

Représente de l’audio : musique ou parole.

image

Une image, un dessin, une photographie. Le sous-type image/png représente une image au format PNG.

message

Un message Internet comme un courriel ou un message destiné à un forum Usenet ainsi que ses entêtes.

model

Dessins 3D, model/vrml indique des données VRML, langage de description d’univers virtuels en trois dimensions.

multipart

Désigne un message constitué de plusieurs parties. Chaque partie peut être d’un type différent, y compris de type text. Les parties sont délimitées par une chaîne séparatrice, il est impératif que la valeur de ce séparateur n’apparaisse pas dans le contenu du message.

text

Données qui ne sont composées que de caractères. Le balisage de ces données est permis, mais ce n’est pas le cas du sous-type text/plain. Parmi les autres sous-types : text/css, des feuilles de style en cascade, text/htmlGHVSDJHVHTML.

video

Des données vidéo, par exemple video/mpeg.

10.3.3 L’information sur le codage de caractères (« charset ») Chaque fois que l’on traite du texte, son interprétation correcte exige de connaître, outre son type de base MIME, la manière dont les caractères ont été codés. MIME prévoit à cet effet un paramètre appelé charset (abréviation de character set, jeu de caractères). Ce paramètre se joint au type sur la ligne Content-Type. Comme nous l’avons vu plus haut, ce terme de « charset » est quelque peu trompeur, car il peut faire penser à un jeu, à un répertoire abstrait alors qu’il s’agit ici aussi de la manière de coder ce répertoire de caractères. Tous les textes de type text et message devraient donc être accompagnés d’un paramètre qui précise le codage de caractères adoptés dans la transmission des caractères de la façon suivante : Content-Type: text/plain; charset=UTF-8

En clair, on a affaire ici à du texte brut codé en UTF-8. La casse des lettres est sans importance dans les noms de codage et ils ne peuvent pas contenir d’espace. Les espaces après les séparateurs « ; » et « : » sont facultatifs. Le registre complet des « charsets », tenu à jour par l’IANA, se trouve à l’adresse suivante : . On remarque que de nombreux codages possèdent des synonymes (des alias). L’ISO Latin-1 peut s’appeler ISO_8859-1, latin1 ou même IBM819 bien que la forme préférée du nom de ce codage, selon ce registre, est ISO-8859-1.

10.3.4 Les entêtes relatifs au surcodage de transfert Plusieurs entêtes permettent de préciser les éventuels surcodages de transfert (comme la compression du message) utilisés dans la transmission du message. Content-Encoding sert à indiquer le surcodage effectué sur le contenu à la source, plus particulièrement la compression. Il s’agit d’un entête propre à HTTP qui ne s’applique pas au courriel. Exemple :

Content-Encoding: gzip.

Les courriels MIME utilisent un autre entête Content-Transfer-Encoding pour indiquer comment les octets sont transmis sur ce qui est à la base un protocole ASCII (SMTP). Les valeurs définies pour cet entête sont énumérées dans le tableau 10.21, une nouvelle fois ces valeurs ne sont pas sensibles à la casse. Tableau 10.2 – Les principaux types de média définis à l’heure actuelle Valeur

Signification

7bit

Envoyer les données comme des entités de 7 bits, signifie « absence de surcodage », c’est la valeur implicite en l’absence d’une ligne d’entête Content-Transfer-Encoding. Les données envoyées sont composées de courtes lignes comprenant chacune un maximum de 998 octets séparés par des séparateurs de lignes .

8bit

Envoyer les octets tels quels, en l’absence de surcodage de transfert. Cette valeur peut être utilisée pour transmettre des données comme le Latin-1 avec des caractères non ASCII (supérieurs à 0x7F). Les données envoyées sont composées de courtes lignes comprenant chacune un maximum de 998 octets séparés par des séparateurs de lignes .

base64

Les octets ont été codés selon la méthode Base64, elle est basée sur le RFC 4648. Plus de détails ci-après.

binary

Données binaires sans restriction de longueur, envoyées telles quelles, sans surcodage de transfert.

quoted-printable

Les octets ont été codés selon la méthode quoted-printable, elle est basée sur le RFC 1521/2045. Plus de détails ci-après.

Un entête Content-Transfer-Encoding: 7bit signifie que le message ne comprend que des octets dont la valeur se trouve dans l’intervalle 0x01 à 0X7F (pas

1. La liste officielle tenue à jour : .

194

Chapitre 10. Unicode et les protocoles Internet

de NUL). Il permet jusqu’à 998 octets par ligne, chaque ligne est délimitée par un 0x0D (retour de chariot) suivi d’un 0x0A (passage à la ligne), ces deux caractères de commande ne peuvent d’ailleurs apparaître qu’en fin de ligne et dans cet ordre. Un entête Content-Transfer-Encoding: 8bit annonce de la même manière que le message comprend des données respectant les mêmes contraintes que celles indiquées par 7bit, si ce n’est que les données peuvent comprendre des octets dont la valeur est supérieure à 0x7F. Content-Transfer-Encoding: binary n’est pas permis pour les courriels SMTP (mais bien en HTTP), on utilisera plutôt base64 et quoted-printable malgré leurs inefficacités respectives. Ce type de surcodage de transfert indique une suite arbitraire d’octets sans limites de longueur ou de contenu.

On pourrait s’étonner que l’on puisse envoyer des entités de 8 bits (comme dans notre message illustratif de la figure 10.2) lors que SMTP est un protocole sur 7 bits. Il faut savoir qu’à la fin des années 1990, les serveurs SMTP ont été mis à jour pour des raisons de sécurité et que cette mise à jour cessait également de tronquer les données à 7 bits. S’il existe encore un risque que les données de courriel transmis sur 8 bits voient leur 1er bit tronqué, il est aujourd’hui minime. Il en va autrement du contenu binaire (binary) qui ne respecte pas la même structure que le 7bit : son contenu n’est pas découpé en ligne d’au plus 998 octets. Quoted-Printable et Base64 ont été conçus pour coder des suites d’octets dans un format qui passe correctement par le canal SMTP à 7 bits. Les deux paragraphes suivants décrivent ces deux formats plus en détail.

Quoted-Printable Le Quoted-Printable (ou QP pour les intimes) est un surcodage d’octets, et non un codage de caractères en tant que tel. Il permet de transférer des suites d’octets sur un canal prévu pour 7 bits. Il est conçu pour être modérément efficace et déchiffrable par un humain quand il code du texte comportant principalement des caractères ASCII, avec de rares caractères non ASCII. QP permet de coder tous les octets, peu importe leur valeur. De manière plus concrète, ceci signifie qu’il est possible d’utiliser QP pour surcoder de l’UTF-8 et de le transmettre par un canal qui mutilerait le premier bit des octets. Quoted-Printable transforme une chaîne d’octets en une chaîne d’octets, mais on dira habituellement que le résultat est une suite de caractères ASCII qui servent en quelque sorte de chiffrement. QP laisse intacts la plupart des caractères visibles ASCII (et donc les caractères UTF-8 qui y correspondent). Le Quoted-Printable dénote les caractères non ASCII à l’aide de la notation suivante : =xx (où xx sont deux chiffres hexadécimaux). Le xx représente la valeur de l’octet dénoté. Le « = » est bien le caractère signe égal à. Notons enfin que certains caractères ASCII sont également représentés sous cette forme, c’est le cas de la sonnerie (0x07) qui doit être codé de la façon suivante : =07.

10.3 Type de médias Internet/type MIME

195

On trouvera une brève description des règles qui définissent ce surcodage :

• Les lignes codées en QP ne peuvent pas dépasser 76 caractères en sortie. Pour permettre de découper les lignes plus longues, QP utilise un passage à la ligne « virtuel » : par convention grâce à la présence d’un signe « = » comme dernier caractère d’une ligne. Ces signes de fin de ligne virtuelle ainsi que les passages à la ligne qui les suivent ne font pas partie du message d’origine et peuvent donc être éliminés à la réception par un agent utilisateur (ex. : votre logiciel de messagerie) pour restituer la ligne dans sa forme d’origine.

• Si des données contiennent un passage à la ligne, on les représente à l’aide des octets 0x0D 0x0A (retour de chariot, passage à la ligne) dans la chaîne en sortie (et non à l’aide des caractères « échappés » =0D =0A).

• Le signe égal à (0x3D) doit être codé =3D afin d’éviter toute ambiguïté avec le caractère d’échappement (« = »).

• La tabulation (0x09) et l’espace (0x20) peuvent être représentés tels quels, à moins qu’un de ceux-ci n’apparaisse en fin d’une ligne, auquel cas il doit être codé =09 ou =20 respectivement. Prenons un exemple et supposons que vous vouliez envoyer un message dont le corps est « Été comme hiver » codé en UTF-8 et surcodé en Quoted-Printable. Votre destinataire, s’il observe le code source du message envoyé, verra : Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable … =C3=89t=C3=A9 comme hiver

Le « É » initial apparaît dans le corps du message sous la forme de =C3=89 qui correspond au U+ 00C9 codé en UTF-8 (0xC3 0x89). Bien évidemment, le logiciel de messagerie se chargera habituellement de décoder le message et affichera les accents du mot « Été » de manière lisible.

Base 64 Base64 est un surcodage de transfert défini par le RFC 4648. Il code une série d’octets en entrée à l’aide d’une suite de caractères ASCII choisis parmi un jeu de 64 caractères « visibles » sélectionnés pour leur présence et leur innocuité sur la majorité des systèmes. Base64 permet de surcoder des données (UTF-8, Latin-1, UTF-16, même de l’ASCII) qui peuvent être ensuite transmises et traitées là où des octets UTF-8, par exemple, pourraient causer des désagréments. On utilise ce codage principalement pour les courriels, car comme nous le verrons les protocoles comme HTTP ont été conçus pour assurer le transport transparent d’octets. L’algorithme du Base64 peut s’exprimer succinctement de la façon suivante : 1. On lit les trois octets suivants. S’il manque des données, on remplit les positions manquantes de zéros binaires.

196

Chapitre 10. Unicode et les protocoles Internet

2. On divise ces 24 bits en quatre groupes de 6 bits. 3. On interprète chaque groupe comme un entier positif (de 0 à 63) qui sert d’indice d’accès pour trouver le caractère « inoffensif » correspondant dans la chaîne suivante : « ABCDEFGHIJKLMNOPQRSTUVWYZ abcdefghijklmnopqrstuvwxyz0123456789+/ ». On remarquera que cet ensemble de caractères interprétés comme des caractères ASCII est extrêmement sûr puisqu’il fait partie du jeu invariant de l’ASCII (voir § 2.2, L’ASCII) et qu’il ne comprend pas de caractères de commande. 4. S’il ne reste plus qu’un ou deux octets (plutôt que les trois habituels) à la fin du tampon de lecture, on insère autant de octets à zéro en fin de chaîne qu’il manquait d’octets. Les zéros binaires introduits qui forment des clés sur six bits complètement à zéro sont enfin remplacés par autant de « = ». Cette convention indique au décodeur que les zéros insérés ne faisaient pas partie du message d’origine. Ceci garantit aussi que le message envoyé et surcodé en Base64 sera toujours un multiple de quatre octets.

Exemple Prenons un exemple, surcodons en Base64 le mot « Été » codé en Latin-1. Texte

É

t

é

Octets

C9

74

E9

Bits

1 1 0 0 1 0 0 1 0 1 1 1 0 1 0 0 1 1 1 0 1 0 0 1

Clé sur 6 bits

50

23

19

41

Base64

y

X

T

p

Comme cet exemple l’illustre, Base64 code 3 octets (0xC9, 0x74, 0xE9) en quatre caractères ASCII transportables « yXTp ». Si nous prenons, la chaîne « Été comme hiver » codée en UTF-8 et non plus en Latin-1 comme ci-dessus, on obtient après application de la méthode Base64 la chaîne suivante interprétée à l’aide du codage ASCII (il ne s’agit bien sûr pas vraiment de données ASCII) : w4l0w6kgb3UgaGl2ZXI= On notera le « = » final puisque puisque la longueur de la chaîne UTF-8 en entrée n’est pas un multiple de 3. Elle contient en effet 17 octets, car chaque lettre accentuée prend ici deux octets.

10.3 Type de médias Internet/type MIME

197

Voyons ce qui se produit quand on chiffre « Ét » codé en Latin-1, qui n’a pas une longueur multiple de 3 octets, à l’aide du surcodage Base64. Texte

É

t

Octets

C9

74

Bits

00

1 1 0 0 1 0 0 1 0 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0

Clé sur 6 bits

50

23

16

00

Base64

y

X

Q

=

À titre d’exercice, on vérifiera que « É » codé en Latin-1 et surcodé en Base64 donne « yQ== ». Il existe quelques variantes à ce surcodage :

• Dans les courriels, on découpe les chaînes Base64 en ligne de 76 caractères pour que tous les logiciels de messagerie puissent accepter ces chaînes.

• La variante « appropriée pour les noms de fichiers et d’URL » remplace dans l’alphabet Base64 le « + » par le « - » trait d’union-signe moins et le « / » par un « _ » tiret bas.

10.3.5 Le surcodage des entêtes Le RFC 2822 précise que les noms des entêtes de messages et leurs valeurs doivent toujours écrits en caractères ASCII. Les valeurs qui contiennent des données non ASCII doivent utiliser la syntaxe encoded-word de MIME défini dans le RFC 2047. Cette méthode utilise des chaînes de caractères ASCII aussi bien pour préciser le codage d’origine des caractères (le « charset ») que le contenu surcodé pour le transfert. Sa syntaxe est la suivante : =????=

où représente tout codage inscrit au registre de l’IANA. En règle générale, il s’agit du même codage que celui adopté pour le corps du message. Quant à , il peut valoir « Q » un surcodage similaire au Quoted-Printable ou « B » pour le surcodage Base64. Enfin, est le texte d’origine codé en surcodage « Q » ou Base64.

198

Chapitre 10. Unicode et les protocoles Internet

Le format « Q » diffère légèrement du Quoted-Printable par la force des choses. En effet, les caractères « ? » et « = » servent de délimiteurs dans la syntaxe encodedword, ils ne peuvent donc apparaître tels quels dans le texte surcodé. De même, pour des raisons de compatibilité avec d’anciens analyseurs d’entêtes, le caractère espace ASCII ne devrait pas non plus être utilisé, car il est parfois traité comme un séparateur. Pour alléger le surcodage et le rendre plus lisible, on utilise le caractère tiret bas (_) pour représenter l’espace plutôt que =20. Le format encoded-word ne s’utilise pas pour surcoder les noms d’entête MIME ou SMTP, car ceux-ci sont toujours en anglais (exemple : From:, To:) et donc en ASCII. Quand le message est visualisé sur un client de messagerie non anglophone, le nom des entêtes doit être traduit par ce logiciel. C’est ainsi que le texte source suivant : From: "=?iso-8859-1?Q?M=E9t=E9oM=E9dia?=" To: "=?iso-8859-1?Q?Fran=E7ois_Mass=E9" Subject: =?iso-8859-1?Q?M=E9t=E9o_du_Sault_des_Ab=E9naquis?=

sera interprété et pourra être présenté sous cette forme : Expéditeur : Météomédia Destinataire : François Massé Objet : Météo du Sault des Abénaquis

10.3.6 Recettes de dépannage Il se peut que des problèmes surviennent lors de la réception de messages MIME. Imaginons que vous sachiez que le message est écrit en français, mais que visiblement il a été mutilé. Étant écrit en français, il est fort probable qu’il contienne un « é ». Repérez ensuite des caractères visiblement faux et qui pourraient avoir pris la place d’un « é » (U+00E9). Le tableau 10.3 vous aidera à déterminer la transformation inopportune qu’aura subie votre message.

10.3 Type de médias Internet/type MIME

199

Tableau 10.3 – Recettes de dépannage Reçu

Interprétation

e

L’expéditeur a peut-être ôté l’accent à la source pensant qu’un « é » ne parviendrait pas intact au destinataire. Ce remède de cheval est tout à fait inutile de nos jours comme nous l’avons vu.

i

Les données à la source étaient en Latin-1 ou un codage similaire comme le Latin-9 ou Windows 1252, mais le 1er bit de l’octet a été tronqué. Cela peut se produire sur de vieilles passerelles de messageries qui « masquent » le bit le plus significatif. On voit donc 0xE9 transformé en 0x69 qui correspond à i dans tous les codages qui s’inspirent de l’ASCII. Une solution consiste à ne pas transmettre en 8bit, mais à utiliser un surcodage comme quoted-printable ou base64. Ceci est de moins en moins nécessaire.

(rien)

Il est possible que les données aient été codées à l’aide d’une page de code DOS (par exemple 850) dans lequel le « é » est codé à la position 0x82. Si ces données sont transmises et interprétées comme du Latin-1, cette position est réservée à un caractère de commande. Un logiciel strict pourrait afficher ce caractère de commande, l’interpréter ou l’éliminer. Les logiciels plus laxistes interprètent ces données comme du Windows Latin-1, ce qui pose d’autres problèmes, voir ci-dessous.

é

Le « Ã » est indicatif d’un caractère UTF-8. Les caractères « Ã » et « © » correspondent aux octets 0xC3 et 0xA9 respectivement. En règle générale, ceci signale des données UTF-8 interprétées comme du Latin-1 par votre logiciel client. Pour corriger ce problème dans un agent de messagerie comme Thunderbird, aller dans Affichage puis dans le menu énumérant les codages (« Encodage des caractères ») et essayer la valeur UTF-8.

Θ

Il s’agit du caractère 0xE9 de la page de code DOS 437. On a donc ici un document codé en Latin-1 (ou un codage similaire) mal interprété comme du CP 437.



Il s’agit probablement d’un document en page de code DOS 850 où le « é » est codé à la position 0x82 et interprété comme du Windows 1252 (ou Windows Latin-1) dans lequel la position 0x82 est attribuée au guillemet-virgule inférieur (le caractère U+201A en Unicode).

Ž

On a sans doute affaire à des données dans un ancien codage Macintosh (Mac Roman) où le « é » est codé à la position 0x8E. Votre programme l’interprète comme du Windows 1252 (Latin-1) où cette position correspond au Z caron (encore appelé Z haček). Si votre programme interprétait cet octet comme de l’ISO 8859-1, il serait sans doute invisible, car il s’agit là d’un caractère de commande, voir « (rien) ».

=E9

Il s’agit d’un document codé en Latin-1 (ou codage similaire) et surcodé en QuotedPrintable.

=C3=A9

Le document est codé en UTF-8 et surcodé en Quoted-Printable.

é

Les données sont en HTML, le codage peut varier.

é

Les données sont en HTML ou en XML, le codage peut varier.

200

Chapitre 10. Unicode et les protocoles Internet

10.4 CODAGE DE CARACTÈRES SUR LE WEB HTTP/1.1, la version actuelle du protocole, est décrite dans le RFC 2616. Contrairement à son nom anglais (HyperText Transfer Protocol), HTTP ne se borne pas à assurer la transmission d’hypertexte. Il peut en effet transporter des données vidéo, audio ou des exécutables. Le travail principal de HTTP est de gérer les échanges entre clients et serveurs Web, permettant aux premiers d’exprimer des requêtes et aux seconds de répondre en retournant les documents demandés, accompagnés de suffisamment de métadonnées pour que le client puisse les interpréter correctement. En outre, il est souhaitable que les requêtes elles-mêmes puissent contenir des métadonnées afin de préciser les préférences du client que le serveur pourra interpréter de façon à mieux satisfaire les requêtes.

Figure 10.3 – Échange HTTP entre un client et un serveur

Le dialogue entre un serveur HTTP et un client (un navigateur web le plus souvent) se déroule de la façon suivante (figure 10.3) :

• Le client contacte le serveur à son adresse IP et au port adéquat (par défaut le port 80 pour HTTP).

• Une fois la connexion établie, le client envoie une requête HTTP 1.1 (ᆰ). Dans notre cas, le client désire obtenir (GET) une page (Tableaux-4.1.htm) située à la racine des pages de ce serveur. La ligne Host: est utilisée si votre serveur héberge différents sites web sur la même machine. Le premier argument du GET est l’URL relative qui commence après la barre de fraction « / » qui suit le nom du serveur dans l’URL absolue. Le second argument est la version du protocole HTTP.

• Si tout se déroule correctement et que la page est disponible, le serveur

renvoie (ᆱ) un message « 200 » (la réponse suit) accompagné de métadonnées indiquant par exemple la longueur du message et son type. La page demandée suit ces entêtes et en est séparée par une ligne blanche. En cas d’échec, le message sera souvent « 404 » (page inexistante).

10.4.1

Entêtes HTTP

Les serveurs web répondent aux requêtes en provenance de leurs clients (habituellement des navigateurs Internet comme Internet Explorer, Firefox ou Opera) en

10.4 Codage de caractères sur le Web

201

précisant le type de données qu’ils fournissent à l’aide de l’entête Content-Type: que nous avons déjà étudié lors de notre description des entêtes MIME. Un serveur qui renvoie une image au format GIF doit l’accompagner d’un entête de ce type : Content-Type: image/gif

Le navigateur, à la réception de cette information, sait d’emblée ce qu’il doit faire des données qui lui parviennent. Si ces données indiquent une page HTML (ContentType: text/html), il pourra l’afficher directement dans une fenêtre. Pour les images, elles seront, selon le cas, incorporées au document HTML qui les contient ou une fenêtre de dialogue apparaîtra invitant l’utilisateur à préciser ce qu’il faut faire de l’image : la sauvegarder ou la visualiser à l’aide d’une application particulière. Il arrive parfois, cependant, que la réponse du serveur ne contienne pas de tel entête, le navigateur doit alors deviner ce qu’il vient de recevoir. Certains navigateurs, plus particulièrement celui de Microsoft, devinent le type de contenu même en présence d’un entête Content-Type en utilisant le suffixe de l’URL (par exemple .wav) et en balayant le début du contenu pour en vérifier le type. Il se peut — par exemple quand des images GIF sont envoyées comme du text/plain et que le navigateur s’en rend compte après son balayage — que le Content-Type soit ignoré. Pour plus de détails, voir . Habituellement, cela ne cause pas de difficultés quand le suffixe du fichier correspond au contenu du fichier. Toutefois, le comportement intelligent de ces navigateurs peut constituer un obstacle si vous décidez de servir comme du texte brut (text/plain) un fichier qui ressemble à du HTML et, dans d’autres cas, ceci peut représenter un risque de sécurité. Pour éviter ce genre de surprise, depuis MS Windows XP SP2, l’Explorateur Internet ne promeut plus un fichier déclaré à l’aide d’un type connu vers un type de fichier de privilèges supérieurs. C’est ainsi qu’un document déclaré comme du texte brut (text/plain) ne sera jamais promu en text/html. Il existe, toutefois, un désagrément indirect lié à cette logique de MSIE : les auteurs de pages qui se fient au jugement de MSIE pourraient ne pas vérifier que leur serveur renvoie des entêtes HTTP corrects, ce qui peut poser des problèmes avec les autres navigateurs plus circonspects et qui ne sont pas dotés de la même logique pour deviner le type de données envoyées.

10.4.2 Préciser le codage de caractères dans HTTP MIME prévoit un paramètre appelé charset (abréviation de character set, jeu de caractères) qui se joint au type sur la ligne Content-Type. Exemple : Content-Type: text/html; charset=iso-8859-1

Malheureusement, ce paramètre est souvent absent dans la pratique courante du Web contemporain. La raison en est historique : le Web à l’origine n’utilisait que l’ISO 8859-1, et ce codage est devenu implicite et même mentionné comme tel jusque dans les RFC 1945 et 2616. Les concepteurs — européens ou américains —

202

Chapitre 10. Unicode et les protocoles Internet

de serveurs HTTP ne se sont pas donné la peine de rendre obligatoire la mention du codage (du charset), trouvant l’ISO 8859-1 suffisante pour leurs besoins. Aujourd’hui, le codage implicite n’est plus l’ISO 8859-1, il n’y en a d’ailleurs pas puisque, en pratique, on en utilise plusieurs à ce titre. Que se passe-t-il en l’absence de ce paramètre charset ? Le navigateur utilise un codage implicite ou déclaré explicitement lors d’un réglage préalable. Les navigateurs permettent aussi de régler manuellement le codage associé à une page après son affichage. Avec MSIE Explorer, par exemple, si une page apparaît mal décodée dans la fenêtre du navigateur et que vous connaissez le codage adéquat, il vous suffit de le corriger manuellement en choisissant Affichage > Codage et de choisir le codage approprié. Notez que si vous avez décoché la première option dans le menu Codage (à savoir Détection automatique), ce changement s’appliquera à toutes les prochaines pages que vous afficherez : leur codage sera celui que vous venez de sélectionner manuellement et non ceux précisés par le serveur qui les envoie. Pour prendre à nouveau en considération les informations de codage envoyées par le serveur, cochez à nouveau l’option Détection automatique. Pour Firefox 2, la correction manuelle se fait de manière semblable. Si vous soupçonnez le codage d’une page d’être inexact, aller dans le menu Affichage > Encodage de caractères et puis choisissez le codage approprié. Vous remarquerez que la première option est également Détection automatique, tout comme dans MSIE, mais le sens en est légèrement différent. Même si cette option est (Désactivée), Firefox utilise l’entête HTTP qui lui est transmis pour afficher le document reçu, le choix manuel de codage n’affecte ici que les pages qui ne déclarent aucun charset. Choix manuel qui est d’ailleurs modifié par la première page qui mentionne un charset. Quant à l’option Détection automatique quand elle est activée, elle permet à Firefox de deviner le codage en l’absence de charset, plusieurs techniques existent pour deviner le codage et même la langue (naturelle, humaine) d’un document1, elles donnent très souvent le bon résultat !

10.4.3 Vérifier les entêtes HTTP Comment peut-on vérifier les informations envoyées dans les entêtes HTTP accompagnant un document web ? Il existe plusieurs façons de vérifier les entêtes HTTP et le code source HTML/XHTML renvoyés en réponse à votre requête :

• La méthode la plus primitive, mais universelle, consiste à utiliser un programme Telnet (ou PuTTY2) et à se connecter au port du serveur (habituellement 80 pour HTTP), à envoyer une commande HEAD et une ligne Host:. Si votre 1. Une de celles-ci, développée par l’université de Montréal, a été utilisée pour établir un palmarès des langues sur Internet : . La méthode utilisait un modèle de Markov caché entraîné sur de larges corpus de documents dont la langue et le codage étaient connus. D’autres méthodes heuristiques, plutôt que probabilistes, existent également. Voir . 2. Téléchargeable ici .

10.4 Codage de caractères sur le Web

203

serveur héberge différents hôtes. La commande HEAD est similaire au GET que nous avons vu précédemment, elle ne sollicite cependant que le renvoi des entêtes et non de la page entière. Terminer le tout par une ligne vide. On voit alors apparaître les mêmes informations que celles en bas de la figure 10.4. telnet hapax.qc.ca 80 HEAD /Tableaux-4.1.htm HTTP/1.1 Host: hapax.qc.ca

• Utiliser Web Sniffer et taper l’URL dont vous désirez voir les entêtes et le début du code source. Dans le même genre, vous trouverez probablement le visualisateur HTTP de Rex Swain également très utile .

• Valider le balisage de la page grâce au valideur du W3C 1. Pour vérifier le balisage, le service de validation doit s’assurer qu’il décode correctement le document qu’il vérifie. Il fera apparaître un message d’erreur s’il ne peut trouver d’information concernant le codage, s’il trouve une information conflictuelle, ou s’il ne peut décoder le document grâce à l’information qu’il trouve. Pour savoir quel codage le valideur a trouvé, vous pouvez utiliser l’interface étendue. Dans cette interface, il est également possible de sélectionner l’option pour afficher le code source (show source), et alors vérifier visuellement que celui-ci est correctement interprété.

• Si vous possédez Firefox, téléchargez le module complémentaire « Web Developer ». Ensuite, cliquez sur le bouton « Informations » de la barre installée par ce module et enfin sélectionnez l’option « View Response Headers ». On voit alors apparaître dans un nouvel onglet les entêtes correspondants à la page que vous aviez sélectionnée. On trouvera dans la figure 10.4 les entêtes associés à l’URL .

Figure 10.4 – Entêtes de réponse

1. Voir une version en français ici : .

204

Chapitre 10. Unicode et les protocoles Internet

Il se pourrait que le paramètre charset soit absent. Comme nous le verrons, cela ne pose aucun problème si votre document indique lui-même son codage de caractères.

10.4.4 Quel codage utiliser pour mes pages web ? La réponse la plus simple consiste à dire qu’il faudrait utiliser UTF-8 partout. Bien que la prise en charge de ce codage soit de plus en plus commune, il se peut que d’autres éléments de votre chaîne d’édition ou de production de documents ne prennent pas en charge UTF-8. Dans ce cas-là, il vaut sans doute mieux se replier vers le codage naturel de votre système (ex. : ISO Latin 1 pour des systèmes Unix) si vous n’utilisez que de peu ou pas de caractères Unicode absents du codage naturel de votre machine. Notez que de nombreux caractères typographiques indispensables à une présentation soignée du français sont absents de l’ISO-8859-1 (mais ils sont présents dans Windows 1252), il s’agit, par exemple, des tirets cadratin (« — ») et demicadratin (« – »), de l’apostrophe (« ’ »), du e dans o (« œ »), etc. Si vous devez utiliser des caractères qui ne sont pas présents dans le codage « naturel » de votre système, il vous est néanmoins possible d’y accéder grâce à des appels d’entité (en HTML, par exemple é et €) ou à des appels de caractères numériques (en HTML et XML, par exemple é pour le « é »). De la sorte, n’importe qui pourra éditer vos fichiers bien que des appels d’entité comme — ou de caractère numérique comme ♘ paraîtraient bien plus opaques que l’utilisation directe des caractères Unicode correspondants (« — » et « ۛ »)si vous pouviez utiliser UTF-8 dans l’ensemble de vos outils.

10.4.5 Balise meta Il est possible que le serveur envoie systématiquement les fichiers HTML avec un entête Content-Type qui précise uniquement text/html sans aucune indication de codage. Dans ce cas, les auteurs de page HTML doivent préciser une balise HTML que l’on peut considérer comme une simulation d’entête HTTP. La balise devrait apparaître le plus près possible de la balise dont elle est une descendante. Une balise meta équivalente à l’entête Content-Type: text/html;charset=UTF-8 prend la forme suivante :

Si la version HTML que vous utilisez est une version d’XHTML, la balise doit se clore par un « /> » plutôt que par un simple « > ». Cette méthode n’est pas adéquate pour les documents de type XML, mais elle l’est pour les documents de type HTML et dans ce dernier cas, il n’existe pas de contre-indication à son utilisation, mais un avantage notable. En effet, la présence du codage dans le document permet à cette indication de suivre ce document, même

10.4 Codage de caractères sur le Web

205

lorsqu’il est lu localement comme fichier et n’est pas envoyé par un serveur. Cela ne s’applique pas uniquement aux documents statiques lus d’un disque ou d’un cédérom, mais également aux documents dynamiques produits par un serveur et sauvegardés par le client.

10.4.6 Préciser le codage dans XHTML et XML XHTML est une forme de HTML exprimée à l’aide d’une syntaxe XML. Les règles de précision du codage dans les documents XML (et donc XHTML) diffèrent de celles du HTML. Elles s’expriment de la façon suivante :

• Si l’on utilise l’entête Content-Type, celui-ci prend le pas sur les autres deux conventions mentionnées ci-dessous. Content-Type, le codage précisé à l’aide d’une déclaration XML au début du document en question : définit le codage du document.

• En l’absence d’entête

• À défaut de toute autre précision, un document XML sera considéré comme codé en UTF-8 ou UTF-16. La présence de l’indicateur d’ordre des octets (IOO ou BOM en anglais) permet de distinguer les cas, les documents en UTF-16 doivent être précédés d’un IOO. La présence d’un indicateur d’ordre des octets au début d’un fichier stocké en Unicode amènera certains navigateurs (c’est le cas de MSIE 7) à considérer votre document comme de l’Unicode quel que soit le codage mentionné dans le document (en d’autres mots, même s’il contient, par exemple, une balise avec charset=iso-8859-1). En pratique, ceci signifie pour les francophones qui ont des fichiers à caractères accentués qu’ils doivent soit opter pour UTF-8 ou UTF-16 soit déclarer explicitement le codage de leurs documents grâce à une déclaration XML ou dans un entête HTTP. Qu’en est-il de la balise qui permet en HTML de simuler l’entête Content-Type de HTTP ? Stricto sensu, elle ne sert à rien en XHTML puisqu’elle n’entre pas en ligne de compte pour déterminer le codage, comme nous l’avons vu précédemment. Elle peut toutefois se révéler utile quand vous envoyez des pages XHTML à des navigateurs comme MSIE 6 qui ne prennent pas en charge le XHMTL et qui traitent ces documents comme s’il s’agissait de document HTML et ignorent donc tout simplement la déclaration . Pour corser encore les choses, il faut préciser que lorsque MSIE 6 — ce n’est plus le cas pour MSIE 7 — rencontre une déclaration , il passe en mode « bizarreries » (quirks en anglais), un mode compatible avec le comportement de navigateurs qui ne respectaient pas les normes HTML et CSS. Nous y reviendrons au chapitre suivant.

206

Chapitre 10. Unicode et les protocoles Internet

En résumé, si vous désirez fournir des pages XHTML sur le Web, le mieux est de les coder en UTF-8, car de la sorte vous pourrez omettre la déclaration XML. Si cela n’est pas envisageable, assurez-vous que l’entête Content-Type avec le jeu de caractères correct accompagne vos pages.

Comment sauvegarder vos pages en UTF-8 Il ne suffit pas de simplement changer la balise de déclaration de vos pages pour signaler qu’elles sont désormais codées en UTF-8. Vous devez vous assurer qu’elles sont réellement codées, c’est-à-dire sauvegardées, en UTF-8. Si vous modifiez vos fichiers à la main, vous devez utiliser votre éditeur pour sauvegarder votre fichier en UTF-81 plutôt que l’ancien codage. Si vos fichiers sont construits dynamiquement par des scripts ou des bases de données, assurez-vous que les données sont bien converties et que les paramètres appropriés sont mentionnés dans votre environnement de scripts. Si une ligne blanche devait apparaître au début de la page HTML dans les navigateurs de vos clients à la suite du passage à UTF-8, il est possible qu’elle soit due à la signature UTF-8 (U+FEFF indicateur d’ordre des octets) et que vous deviez la supprimer manuellement. Il vous faut ensuite modifier la déclaration de codage de caractères de votre page ou en ajouter une si vous ne l’avez déjà fait. Selon le cas, vous le ferez à l’aide d’une balise pour les documents HTML et XHTML servis comme du text/html ou d’une déclaration pour les documents XHTML servis comme du XML (application/xhtml+xml). Enfin, assurez-vous que le serveur fasse ce qu’il faut. Bien que vos données soient désormais en UTF-8 et que vous l’ayez déclaré à l’intérieur de votre document, votre serveur pourrait continuer à envoyer la page avec un entête HTTP qui précise un autre codage, sans se soucier du codage réel des pages qu’il envoie, et c’est cet entête qui primerait.

10.4.7 Conflits des définitions de codage HTTP et HTML Selon le RFC qui définit HTTP 1.1 (RFC 2616) toutes les données de type texte sont codées par défaut en ISO-8859-1. En revanche, la spécification d’HTML 4.01 précise qu’aucun codage ne doit être considéré comme implicite ! Ceci signifie en pratique que, lorsqu’aucun codage n’est précisé, le navigateur devra faire de son mieux pour deviner le codage de la page plutôt que de supposer qu’il s’agit d’une page en Latin-1.

1. comment faire pour une longue liste d’éditeurs.

précise

10.4 Codage de caractères sur le Web

207

On comprend mieux que la solution la plus sage consiste à s’assurer que les documents HTML précisent en leur sein leur codage et à éviter que HTTP envoie systématiquement — un peu à l’aveuglette — un codage. En effet, pour un serveur qui sert des documents tirés du disque qui auraient été stockés par FTP ou un partage de disque, il vaut mieux compter sur les indications dans les documents eux-mêmes (la balise ). C’est ce que tous les éditeurs HTML font aujourd’hui et le résultat est généralement fiable, alors que ce que le serveur considère être le codage d’un document est très souvent faux. Même le site du W3C, qui s’obstine à servir un charset HTTP, regorge d’erreurs. Par contre, le charset HTTP est utile pour les pages produites par des servlets, des scripts, etc. Le script contrôle à la fois le paramètre charset et le codage réel, les deux sont donc généralement synchronisés.

Entête HTTP, balisage meta et codage de l’hyperlien d’appel En résumé, selon HTML 4.01, le codage de caractères d’un document HTML peut être précisé à l’aide des méthodes suivantes données dans leur ordre de priorité :

• Dans le paramètre charset dans un entête HTTP. • Dans le document lui-même à l’aide d’une balise meta qui correspond à l’entête HTTP.

• Dans l’attribut

charset de l’hyperlien qui faisait appel au document en

question. Les navigateurs ont ignoré la troisième option, mais, en général, ils ont bien mis en œuvre les deux premières. Ceci signifie qu’il n’y a pas moyen de « damer le pion » dans le document lui-même au codage mentionné dans un entête HTTP.

10.4.8 Configuration de serveurs web La configuration de chaque serveur diffère. Prenons, toutefois, comme exemple deux des serveurs les plus communs, Apache et IIS, pour mieux voir le genre de réglages possibles ou souhaitables.

Apache Les fichiers de configuration sur Apache qui nous intéressent sont les fichiers .htaccess1, ils permettent de définir des règles dans un répertoire et dans tous ses

sous-répertoires (qui n’ont pas un tel fichier à leur niveau). On peut les utiliser pour protéger un répertoire par un mot de passe, pour changer le nom ou l’extension de la page d’index, ou encore pour interdire l’accès au répertoire. Le fichier .htaccess est placé dans le répertoire à partir duquel il doit prendre effet. Il agit ainsi sur les permissions du répertoire qui le contient et de tous ses sous1. On peut également préciser ces mêmes réglages dans la configuration globale d’Apache (httpd. conf ou équivalent). Si vous y avez accès, on recommande de faire ces réglages à ce niveau pour des questions de performance.

208

Chapitre 10. Unicode et les protocoles Internet

répertoires. Vous pouvez placer un autre fichier .htaccess dans un sous-répertoire d’un répertoire déjà contrôlé par un fichier .htaccess. Il primera sur les fichiers .htaccess déclarés plus haut dans la hiérarchie. Par exemple, la ligne suivante permet de considérer que tous les fichiers du répertoire contenant le fichier .htaccess sont des fichiers HTML (ce qu’Apache précisera dans l’entête Content-Type) quel que soit leur suffixe : ForceType text/html

Le fichier .htaccess permet également d’associer à un suffixe de fichier donné un type de média (ou type MIME) : AddType image/x-photoshop psd AddType text/html;charset=utf-8 html

La première entrée précise donc au serveur Apache que les fichiers de ce répertoire (et ses sous-répertoires à défaut d’autres .htaccess) dont le suffixe est « psd » devront être accompagnés d’un Content-Type: image/x-photoshop. La seconde indique que les fichiers dont le nom se termine par .html dans ce répertoire doivent être envoyés avec un Content-Type qui indique qu’ils sont en UTF-8. Enfin, en ce qui nous concerne, il est également possible de définir le ContentType par défaut qui pourra s’appliquer aux fichiers auxquels ne correspond aucun Addtype ni aucun type prédéfini (dans le fichier mime.types du répertoire de configuration d’Apache). DefaultType text/html;charset=iso-8859-1

IIS 5 et 6 Le serveur Internet de Microsoft offre des fonctionnalités similaires à Apache. Pour régler ces paramètres dans IIS, dans le gestionnaire des services Internet, cliquez avec le bouton droit sur site Web par défaut (ou le site particulier que vous souhaitez configurer) puis ouvrez Propriétés, choisissez l’onglet Entêtes HTTP et cliquez sur le bouton Types de fichiers... et Nouveau type... Un à un précisez les suffixes que vous souhaitez associer à un entête Content-Type. Les utilisateurs du serveur IIS voudront sans doute que les extensions « .htm » et « .html » soient configurées. Précisez alors dans le Content-type la valeur text/html;charset=utf-8. Remplacez, le cas échéant, « utf-8 » par le codage adéquat ; ne laissez aucun espace dans la chaîne, car IIS ignore tout ce qui suit un espace.

Fichiers de plusieurs codages dans le même répertoire Mais que faire si on a dans le même répertoire des fichiers HTML en UTF-8 et dans un autre codage (le plus souvent en Latin-1 pour les francophones) ? Il existe deux options simples :

• Utiliser des suffixes différents pour les différents codages et ajouter une ligne par suffixe. Bien que les suffixes ne doivent pas avoir d’effet sur les navigateurs, ce n’est pas toujours les cas (par exemple pour l’Internet Explorer de Microsoft).

10.4 Codage de caractères sur le Web

209

Toutefois, si on choisit .html pour des pages HTML dans un codage et .htm pour l’autre ceci ne devrait jamais poser de problèmes.

• Regrouper les fichiers d’un même codage dans un même sous-répertoire et ajouter un fichier .htaccess avec une seule entrée AddType dans chaque sous-répertoire.

La sécurité prend le dessus Malheureusement, pour des raisons de sécurité, l’addition de fichiers .htaccess n’est pas toujours permise aux créateurs de page web. Ce souci des administrateurs est légitime, car ce fichier permet de contourner les paramètres (d’accès de répertoire par exemple) établis pour l’ensemble du site. Dans d’autres cas, les administrateurs configurent leur serveur afin qu’ils ignorent les .htaccess des utilisateurs ordinaires. Si un serveur empêche les auteurs de préciser les entêtes HTTP des fichiers qui se trouvent dans leur répertoire, ce serveur devrait alors s’abstenir de préciser le codage des fichiers HTML. Conjointement, les auteurs de ces pages web devront impérativement incorporer des balises dans leurs documents. Ces balises préciseront le codage des pages en question. Comme nous le signalions, le codage mentionné dans la balise n’a pas préséance sur celui mentionné dans les entêtes HTTP. Il est donc important dans ce cas que le serveur n’envoie pas de codage de caractère par défaut pour l’ensemble des fichiers qu’il sert, sinon les auteurs de pages web devront obligatoirement convertir leurs pages au codage imposé.

Langages de script de page HTML du côté du serveur Notons, enfin, qu’il existe d’autres moyens que les fichiers de configuration pour préciser les entêtes HTTP. La plupart des langages de scripts du côté des serveurs le permettent. Si vous créez des pages JSP (Java Server Pages), vous pourrez écrire :

Le processeur JSP interprétera cette directive, placera ces données parmi les entêtes HTTP et produira la sortie en ce codage. Pour PHP, avant de renvoyer du contenu, utilisez la fonction header(), par exemple : header('Content-type: text/html; charset=utf-8');

Pour les servlets Java, avant d’obtenir un objet de sortie (Stream ou Writer), utilisez la méthode setContentType() de ServletResponse, par exemple : response.setContentType ("text/html;charset=utf-8");

Si vous utilisez un objet Writer, les chaînes Java sont automatiquement converties par le processeur de servlets vers le codage mentionné (voir § 12.10, Conversion de données).

210

Chapitre 10. Unicode et les protocoles Internet

Une autre méthode peut s’avérer utile pour les servlets multilingues, il s’agit de setCharacterEncoding(). Par servlet multilingue, on entend ici une servlet qui

peut produire des pages HTML dont le codage variera. Dans ce cas-là, une partie du code sait que l’on produit du HTML (elle appelle donc setContentType() sans mentionner de charset), une autre partie du servlet sait quel codage utiliser et elle appelle setCharacterEncoding().

10.5 HTTP INTERNATIONALISÉ HTTP 1.1 permet la négociation de contenu. C’est ainsi qu’un client HTTP peut faire accompagner sa requête d’entêtes qui précisent sa langue et son format de données préférés. Il s’agit d’entêtes dont le nom commence par Accept. L’idée se résume ainsi : un même document peut exister en plusieurs variantes de langue, de format ou de codage. À l’aide de lignes d’entête Accept, le client exprime ses capacités ou ses préférences. Le serveur utilise ces préférences pour choisir parmi toutes les variantes la version la plus appropriée.

10.5.1

La négociation de langue

La négociation de langue est une des facettes de la négociation de type de contenu. La plupart des navigateurs et des serveurs permettent la négociation de contenu, et en particulier la négociation de langue. Ainsi, un des serveurs les plus populaires, le serveur Apache, peut-il être réglé pour permettre de choisir la langue d’un document selon les préférences exprimées par le navigateur. Nous examinerons sa configuration ci-après. La négociation de langue est très avantageuse pour naviguer sur les sites multilingues : le client obtient directement la version qui lui convient, sans perdre son temps à louvoyer parmi des pages qu’il comprend mal ou pas du tout, à la recherche d’un hyperlien vers la bonne langue. Le site et celui du W3C (mais de manière très parcellaire1) l’utilisent.

Configurer votre navigateur La plupart des navigateurs permettent de préciser vos préférences linguistiques. La valeur (« la langue ») doit se conformer au RFC 1766, aïeul du RFC 46462. Elle consiste, en règle générale, en un indicatif à deux ou trois lettres (« fr » pour le français) suivi de sous-indicatifs facultatifs qui indiquent des données régionales telles que le pays (exemple : « fr-CA » pour représenter le français du Canada).

1. Le site des communiqués de presse du W3C utilise cette technique, voir par exemple . 2. Pour éviter qu’une norme ne mentionne un RFC qui risque de devenir désuet (comme ce RFC 1766), l’IETF recommande aujourd’hui aux auteurs de norme de renvoyer dans le texte de ces normes à des Best Current Practice (ici le BPC 47) plutôt qu’à d’autres RFC (voir chapitre 9).

10.5 HTTP internationalisé

211

Le plus souvent, les réglages d’usine des navigateurs sont appropriés à l’utilisateur unilingue. Ainsi, si vous avez une version japonaise d’un navigateur, le navigateur fera l’hypothèse que vous préférez lire des pages en japonais et enverra cette information au serveur. Pour vérifier ou modifier les réglages dans les navigateurs mentionnés ci-après, utiliser les commandes du menu suivantes :

• Internet Explorer : Outils

> Options Internet > (onglet) Général > Langues (bouton) > Langues.

• Firefox 2 :

Outils > Options > Avancé (icône) > (onglet) Général > Langues > (bouton) Choisir.

• Safari : (configuré au niveau des préférences du système sous Mac OS X) Préférences Système > International > Langues.

Il est permis de mentionner plusieurs langues dans leur ordre de préférence. Dans l’exemple suivant, effectué sur Firefox 2, l’utilisateur a indiqué qu’il préférait recevoir ses pages en français du Canada et que si celles-ci n’étaient pas disponibles, ils les liraient, dans l’ordre, dans n’importe quelle variante du français, puis, si cela n’était pas possible, en anglais, en allemand, en espagnol et enfin en néerlandais. Il faut toujours commencer à préciser les langues du plus particulier (« fr-CA ») au plus général (« fr »). Enfin, le mécanisme de sélection de versions linguistiques du côté du serveur impose une correspondance exacte (si on exclut la casse) entre l’indicatif envoyé par le client et leur propre utilisation de cet indicatif. Ainsi ces serveurs refuseront-ils de renvoyer un document étiqueté sur le serveur comme étant du « fr » (français) si la requête demande un document en « fr-CA » (français du Canada). Pour éviter ce genre de pièges, il faut configurer son navigateur pour qu’il demande à la fois du « fr-CA » et du « fr » et dans cet ordre.

Figure 10.5 – Sélection des préférences linguistiques

212

Chapitre 10. Unicode et les protocoles Internet

Que se passe-t-il au niveau HTTP ? Au niveau du protocole, le navigateur envoie les préférences configurées comme paramètres d’un entête HTTP appelé Accept-Language qui énumère les langues acceptables et leur relatif taux d’acceptabilité. Pour être précis, il énumère les langues en question et un facteur « q » de qualité optionnel exprimé sous la forme d’un nombre décimal allant de « 0 » (très peu souhaitable) à « 1 » (hautement souhaité). L’entête suivant précise une préférence pour le français par rapport à l’anglais, mais une version anglaise est acceptable si aucune version française du document n’existe : Accept-language: fr;q=0.8, en;q=0.6

Remarquer que la notation n’est guère intuitive puisque le point-virgule sépare la langue de son caractère souhaitable, mais que ces couples ne sont séparés entre eux que par des virgules. L’entête suivant, créé par Firefox, correspond aux préférences exprimées à la figure 10.5 : Accept-Language: fr-ca,fr;q=0.8,en;q=0.7,de;q=0.5,es;q=0.3,nl;q=0.2

Il existe plus d’une manière de déterminer la langue d’un visiteur. L’entête HTTP Accept-Language est sans doute la façon la plus fiable. Tous les navigateurs envoient aussi également un entête User-Agent, celui-ci indique le type de navigateur utilisé

comme client, sa version et souvent la langue de l’interface-utilisateur. On peut s’en servir, en l’absence d’entête Accept-Language, pour découvrir la langue du visiteur. Cette méthode est, bien entendu, moins fiable et moins puissante (elle ne permet de préciser qu’une seule langue) que l’utilisation de l’entête Accept-Language. La négociation de langue n’est qu’un des aspects de la négociation de contenu HTTP. Parmi les autres aspects : la négociation du type de média (HTML, PDF ou texte brut par exemple), du codage des caractères et du surcodage de transfert (chiffré, compressé, etc.). La négociation de langue est la plus utile et la plus utilisée. La requête typique reproduite ici illustre plusieurs de ces autres entêtes de négociation : GET / HTTP/1.1 Host: hapax.qc.ca Accept-Encoding: gzip Accept: text/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8 Accept-Language:fr-ca,fr;q=0.8,en;q=0.7,de;q=0.5,es;q=0.3,nl;q=0.2 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7

L’entête Accept-Encoding précise que le document peut-être surcodé en le zippant. Accept définit le type de documents (Content-Type) acceptés. AcceptCharset énumère les codages préférés.

Configuration du serveur Chaque serveur gère à sa façon la manière d’associer les différentes versions linguistiques d’une même page. Nous ne discuterons ci-dessous que des méthodes adoptées par le serveur le plus commun, Apache, pour gérer cette association.

10.5 HTTP internationalisé

213

Sous Apache, il existe deux méthodes à la négociation de ressources. La première implique l’utilisation d’un fichier de correspondance de types qui énumère explicitement, pour chaque URL, la liste des fichiers correspondants dans les langues disponibles. La seconde s’effectue à l’aide d’une recherche « Multivues » (MultiViews) où les versions linguistiques sont nommées d’une façon systématique et le serveur effectue une recherche des fichiers linguistiques candidats à l’aide d’un patron (d’un motif) syntaxique puis choisit le meilleur candidat. L’option Multivues peut être configurée pour chaque répertoire, si l’administrateur du serveur le permet.

Utilisation de la correspondance de types (type-map) Prenons un exemple pour décrire cette méthode. Imaginons que dans un répertoire de notre serveur (http://hapax.qc.ca) nous ayons trois fichiers l’un en français canadien (patente.html), l’un en français régional belge (brol.html) et un troisième en anglais (widget.html). Supposons ensuite que l’utilisateur puisse changer certaines instructions dans les fichiers .htaccess. Pour ce faire la commande AllowOverride doit avoir été configurée correctement dans le fichier de configuration (httpd.conf) par l’administrateur du système. Dans le fichier de configuration .htaccess (de notre répertoire ou d’un ancêtre de celui-ci), ajoutons la ligne suivante : AddHandler type-map .var

Ceci signale au serveur qu’il doit traiter les fichiers dont le nom se termine en .var comme des ressources à variantes. Cette ligne est précédée d’un # de commentaire dans la version par défaut du .htaccess racine. Ensuite, créons un fichier machin.var dans notre répertoire avec le contenu suivant : URI: patente.html Content-Type: text/html;charset=iso-8859-15 Content-Language:fr-CA URI: widget.html Content-Type: text/html Content-Language:en URI: brol.html Content-Type: text/html;charset=utf-8 Content-Language:fr-BE

Il s’agit d’un fichier de correspondance de type qui définit la ressource machin. var. Ses entrées sont constituées de groupes de lignes au format d’entêtes HTTP. Les entrées de deux variantes distinctes sont séparées par une ou plusieurs lignes vides. Notez qu’Apache utilise en priorité les fichiers de correspondance de types avant d’utiliser l’extension du nom du fichier, et ce, même si l’option Multiviews est activée. Grâce à ce fichier, l’URL est désormais accessible et fournira la version correspondant le mieux aux préférences linguistiques du client : une version belge aux agents qui envoient « fr-BE » comme première

214

Chapitre 10. Unicode et les protocoles Internet

option, une version québécoise aux clients qui expédient « fr-CA » et en anglais à ceux qui préfèrent l’anglais « en ». Le nom sous-jacent de la ressource n’apparaît pas dans le navigateur : il ne voit que le nom machin.var et tous les hyperliens devraient idéalement faire référence aux URL en *.var si votre serveur utilise le mécanisme des correspondances de type.

Utilisation de Multivues (Multiviews) Une autre option consiste à utiliser la méthode Multiviews. Pour cela, il faut que l’option Multiviews soit activée dans httpd.conf pour notre site : Options MultiViews

On associe ensuite les codes de langue envoyés dans l’Accept-Language à des suffixes de fichier. Ceci peut se faire à plusieurs endroits : dans le fichier de configuration global du serveur httpd.conf (privilège réservé à l’administrateur) ou dans les fichiers .htaccess dans la hiérarchie des répertoires. Supposons que l’utilisateur puisse changer certaines instructions dans les fichiers .htaccess (voir votre administrateur de système) et qu’il y écrive : AddLanguage fr .fr AddLanguage en .en AddLanguage fr-be .be

On nomme ensuite les documents dans le répertoire en question res.html.be (pour la version « fr-BE »), res.html.fr (pour la version « fr ») et enfin res.html. en pour la version « en ». Il n’est pas nécessaire de créer un fichier res.html. Ceci fonctionne également pour les fichiers en texte brut, la négociation ne dépend pas du type de fichier. On accède ensuite à cette ressource en mentionnant l’URL . Il vous est également possible de nommer vos fichiers en utilisant la langue comme infixe et html comme suffixe (ici res.en.html, res.be.html, res.fr.html) ce qui peut faciliter l’édition des fichiers qui ne sont pas servis par un serveur Apache. Dans ce cas, les URL doivent toujours être mentionnées sans les extensions (infixe et suffixe) dans la barre d’adresse et dans les hyperliens (c’est-à-dire … ). Cette absence de suffixe est, en fait, une très bonne chose, même en dehors du contexte de négociation HTTP. En effet, cette absence permet de changer le type de contenu du fichier (en jargon « de la ressource ») sans que personne n’ait à modifier une seule URL (dans ses signets, ses pages, les moteurs de recherche, etc.) À consommer sans modération. En outre, cette absence de suffixe empêche MSIE d’être trop malin quand il essaie de découvrir le type de document à l’aide de l’extension du suffixe et se trompe donc trop souvent. Idéalement, on ne devrait jamais voir d’extension dans les URL.

10.5 HTTP internationalisé

215

Quand la négociation ne trouve pas de page adéquate Si le navigateur envoie des préférences linguistiques qui ne correspondent à aucune des versions disponibles, le serveur Apache renvoie un message HTTP d’erreur « 406 Not acceptable ». Par défaut, le texte « Not acceptable » apparaîtra en anglais avec une liste de lien vers le nom des fichiers correspondants aux versions existantes. On ne peut pas dire qu’il s’agisse là d’une solution très conviviale. Il existe plusieurs solutions plus ergonomiques : 1. Créer une page d’erreur 406 plus judicieusement traduite et personnalisée pour votre site en ajoutant, par exemple, une entrée dans httpd.conf du type : ErrorDocument 406 http://hapax.qc.ca/manqueversionlinguistique.html

Cette page pourra par exemple énumérer les langues que votre site prend en charge et avertir dans plusieurs autres langues pourquoi cette page d’erreur est apparue. Vous pourriez aussi y indiquer à vos clients comment régler leurs préférences linguistiques dans leur navigateur. 2. Vous pouvez aussi créer dans votre répertoire un fichier « générique » qui ne précise aucun Content-Language et qui sera choisi en dernier recours (dans notre exemple un res.html) si aucune version linguistique ne satisfait les préférences du client. Ce fichier énumérera à nouveau la liste des versions disponibles. 3. La dernière option est de fournir une version linguistique (ou une liste de versions linguistiques) par défaut. À l’aide des deux lignes ci-dessous on pourra ainsi préciser que, si aucune version ne satisfait aux préférences linguistiques du client, on affichera d’abord une version franco-belge, si elle existe, ensuite la version française et enfin, si les deux précédentes n’existent pas, la version anglaise : LanguagePriority fr-be fr en ForceLanguagePriority Fallback

Si un client dont le Accept-Language ne comprend que « de » (l’allemand) demandait le document res.html, c’est la version res.html.be qui lui serait renvoyée. On verra par la suite qu’il vaut mieux compléter ce comportement par ce que nous appellerons des commandes manuelles de langue.

La négociation de langue n’est pas toujours appropriée La négociation de langue est clairement une chose utile. Toutefois, avant de la mettre en œuvre, il convient de bien en comprendre les limites. Pour les illustrer, prenons l’exemple du site qui offre du contenu en allemand, en français, en italien et en romanche et qui utilise la négociation de langue. Le site sert par défaut les pages en allemand. Un visiteur, appelons-le José, parle espagnol et se débrouille en français. Que peut-il se produire ?

• José n’est pas très versé en informatique, il n’a jamais entendu parler de la négociation de langue et n’a jamais ressenti le besoin de préciser ses préférences

216

Chapitre 10. Unicode et les protocoles Internet

linguistiques. Son navigateur est donc implicitement réglé pour exprimer une préférence pour l’espagnol, ce qui est bien naturel. En arrivant sur , l’espagnol n’est pas disponible et une page en allemand (langue par défaut du site) s’affiche, même si une page en français est disponible. Perplexité de José.

• José a bien réglé son navigateur en exprimant ses préférences pour l’espagnol suivi du français. Aucune page en espagnol n’est disponible sur , les pages apparaissent en français, José est plutôt content, il comprend les pages fournies. Après tout, c’est à cela que servent les préférences linguistiques.

• José n’utilise pas son propre navigateur, il navigue depuis une université aux États-Unis. Le navigateur est configuré pour demander des pages en anglais uniquement. José voit à nouveau de l’allemand. Étonnement réitéré de José. Il existe encore d’autres cas où un utilisateur pourrait vouloir afficher une version linguistique autre que celle que lui fournit automatiquement la négociation de langue :

• Il voudrait comparer des versions différentes du même texte pour mieux le comprendre.

• Il préfère lire la version originale d’un texte même si celle-ci n’est pas dans sa langue généralement préférée.

• On peut lui avoir envoyé un hyperlien vers la mauvaise version linguistique du document (nous verrons plus tard comment cela peut se produire). Le mécanisme de préférence linguistique ne fournit donc pas toujours le résultat escompté ou désiré. En outre, il existe également des cas où la négociation de langue n’est pas pertinente, car les différentes versions linguistiques existantes ne sont pas équivalentes entre elles, c’est-à-dire identiques à quelques éléments « localisés » près comme les formats de date, les montants dans la devise locale si le montant converti est identique, les unités de longueur, etc. Prenons l’exemple classique d’une page qui reprend les conditions de vente d’un site commercial. Soit un site, disons de Toronto, qui vend d’abord en anglais en Amérique du Nord. Un jour, la société décide de s’attaquer à l’Europe et traduit le site en français, en allemand, etc. J’habite au Québec et je vais automatiquement sur le site en français grâce à la négociation de langue, je remplis mon panier et consulte les conditions de vente : les prix sont en euros, on y parle de TVA, de longs délais de livraison outre-mer, de frais de douanes, etc. La page est manifestement destinée à la France, il ne s’agit pas d’une traduction de la page en anglais de Toronto. Cette page n’est pas l’équivalent en français de la page originale, elle dit tout autre chose, la négociation de langue ne devrait pas s’y appliquer.

Pallier les imperfections – les commandes manuelles de langue Malgré ses limites, la négociation de langue est une fonction utile et il est souhaitable de la mettre en œuvre dans les sites multilingues. Mais il faut en pallier les imperfections. En bref, il faut permettre au choix exprimé par le visiteur de l’emporter sur le choix

10.5 HTTP internationalisé

217

automatique de langue fait par le serveur, lorsque ce dernier est erroné. Pour ce faire, on inclura dans la page des éléments de navigation (qu’on appellera commandes de langue ici) menant aux autres langues. Ces commandes graphiques doivent être bien visibles et de plus compréhensibles par un visiteur qui ne connaît pas la langue de la page présentement affichée. On décrira donc toujours le lien vers une page en français par le terme « français » (ou l’indicatif « fr ») et non « French » dans une page en anglais ou « ᴺ⺆ » dans une page en chinois traditionnel. Mais faut-il mettre en œuvre la négociation automatique et fournir des commandes manuelles de langue dans toutes les pages ou suffit-il de le faire sur la seule page d’accueil ? La meilleure solution est de le faire pour toutes les pages sauf celles qui ne sont pas suffisamment équivalentes entre elles (leur contenu étant trop différent). La négociation de langue est utile parce que, si Uwe envoie un lien vers une page du site à Pierre, Pierre sera bien content de voir la page en français, même si Uwe lisait la version en allemand et a copié l’hyperlien vers cette page en allemand. Les commandes manuelles de langues doivent quant à elles aussi être disponibles, même si la négociation de langue ne l’est pas. Sans négociation, Pierre aura besoin d’une commande pour atteindre la version française à partir du lien fourni par Uwe. Et même avec la négociation, José devra passer manuellement au français dans plusieurs des cas illustrés dans la section précédente.

Rémanence du choix linguistique Reprenons notre exemple. José visite et obtient de l’allemand. Il clique alors sur la commande manuelle « français », obtient une page en français et continue de lire. Tout va bien. Il veut poursuivre sa lecture et clique sur un des hyperliens de cette page. Et là, malheur ! à la page suivante, il retombe encore sur de l’allemand. Il peut évidemment à nouveau appuyer sur la commande « français », mais tout cela est peu commode. L’idéal serait que le serveur se souvienne du choix manuel du client. Le serveur dispose de plusieurs manières pour fournir cette rémanence. La meilleure solution dépendra des techniques disponibles sur le serveur et de l’effort que l’on est prêt à consacrer à cette solution :

• Si le serveur met en œuvre le mécanisme de session (dont le numéro peut être inclus dans l’URL), il est assez facile de s’assurer que le choix manuel de langue fasse partie de l’état de session.

• Le serveur peut également utiliser des témoins1 conservés d’une visite à l’autre sur la machine du client : José verra alors directement du français lors de ses prochaines visites.

• Autre option encore : le serveur indique dans l’URL le choix manuel linguistique effectué en ajoutant par exemple ?lang=fr.

1. Ces « témoins » sont ce qu’on appelle en jargon les « cookies ».

218

Chapitre 10. Unicode et les protocoles Internet

• Les sites qui obligent les utilisateurs à s’inscrire et à s’identifier peuvent également stocker les préférences linguistiques dans le profil de chaque utilisateur et présenter les pages en conséquence. La négociation de langue n’est alors utilisée que pour les visiteurs qui ne sont pas encore identifiés.

• Un autre moyen d’éviter de préciser à chaque nouvelle page sa langue préférée est de rendre tous les hyperliens du serveur spécifiques à une langue. C’est le cas du serveur du Parlement helvétique où appuyer sur une commande manuelle de langue modifie le répertoire de base des liens (à savoir le contenu de la balise HTML ) tout en laissant les autres liens intacts. On trouve donc les mêmes liens dans les pages françaises, italiennes et allemandes. Par exemple, dans la version allemande : Büros

et dans la version française : domaines politiques.

Seule la balise (la base des chemins relatifs) change, elle est, pour la version allemande, égale à :

et dans sa version française :

Cette solution est sans doute préférable1 à la modification de tous liens en leur ajoutant l’indicatif de langue à chaque page pour obtenir par exemple href="raraete/bueros.de.htm" (au lieu de la forme générique href="ra-raete/ bueros.htm")2. En ajoutant le « de » dans l’URL, on aurait restreint la navigation à l’allemand tant que l’utilisateur n’aurait pas choisi pas manuellement une autre langue. La modification de la balise a toutefois un désavantage : elle doit être modifiée lors de la traduction. Quant à la modification des URL pour y mentionner la langue, elle implique que tous les liens internes soient désormais modifiés lors de la traduction des pages qui les contiennent, ce qui augmente le coût de la traduction et les risques d’erreur. D’autre part, si Uwe envoie à Pierre un hyperlien qui n’est pas générique, il pointera vers une page dans la langue d’Uwe, c’est-à-dire en allemand. Pierre devra alors manuellement changer la langue grâce aux commandes manuelles. L’utilisation des hyperliens spécifiques est donc une solution moins optimale à celles que nous avions énumérées auparavant et on ne l’utilisera que dans les cas où la rémanence ne peut être mise en œuvre à l’aide d’un mécanisme de session ou grâce à un profil qui intègre les préférences linguistiques de l’utilisateur.

1. Cette solution empêche toutefois la négociation linguistique à la Apache de fonctionner, puisque les fichiers sont maintenant dans des répertoires distincts. 2. Comme nous l’avons vu, avec Multiviews dans Apache, les liens spécifiques pourraient également être du type bueros.de (sans le HTML final) ou bueros.html.de.

10.5 HTTP internationalisé

219

Des noms de domaine différents par langue Il existe encore d’autres techniques pour accueillir directement vos clients dans leur langue et les servir correctement. L’une consiste par exemple à enregistrer plusieurs noms de domaine, chacun dans la langue de vos principaux clients. C’est ainsi que le parlement helvétique a quatre noms de domaine : pour ses utilisateurs francophones (on tombe d’office sur la page d’accueil du parlement en français), pour les utilisateurs italophones et ou son équivalent de racine latine pour les germanophones. À défaut de quoi, si votre clientèle se divise en quelques groupes linguistiques bien identifiés, il serait sans doute opportun d’opter pour des noms de domaine qui ne privilégient aucun de ces groupes (et ceci ne veut pas dire opter automatiquement pour l’anglais). Ainsi, au Canada, les sites gouvernementaux ont-ils tendance à avoir des noms de domaine qui sont « bilingues » : peut s’analyser aussi bien en français comme étant parlement (parl) du gouvernement canadien (gc) ou, en anglais, comme parliament (parl) of the Government of Canada (gc). Idem pour le site du Premier ministre () ou du Prime Minister. Ces sites à nom de domaine bilingue s’ouvrent ensuite souvent sur une page d’accueil bilingue qui demande en grand quelle est votre préférence linguistique, bien que cette page soit superflue si on a identifié celle-ci à l’aide de l’entête HTTP Accept-Language.

Préférence automatique par pays plutôt que par langue ? Les auteurs de pages essaient souvent de mettre en œuvre la préférence linguistique en utilisant l’adresse Internet du client pour en déterminer le pays. C’est une méthode vouée à l’échec la plupart du temps pour plusieurs raisons : toutes les personnes dans un pays donné ne parlent pas la même langue, c’est bien évidemment le cas de pays multilingues (Belgique, Canada, Suisse), mais c’est également le cas dans les pays officiellement unilingues. Si vous décidez toutefois d’utiliser cette méthode, gardez à l’esprit que ce processus ne correspondra souvent pas aux préférences linguistiques de vos clients et qu’il faut donc inclure sur les pages affichées un hyperlien qui permette de choisir manuellement la version linguistique de la page à afficher.

10.5.2 Les entêtes reliés aux caractères Nous avons déjà vu en ordre dispersé les entêtes les plus importants reliés aux caractères. Nous les résumons dans le tableau 10.4, plusieurs ne sont pas reliés directement au codage de caractères, mais plutôt à la langue ou à un entête qui doit pouvoir accepter du contenu multilingue comme l’objet (Subject:) ou simplement s’il a un nom similaire à un entête qui concerne les caractères (Transfer-Encoding:).

220

Chapitre 10. Unicode et les protocoles Internet

Tableau 10.4 – Principaux entêtes reliés aux caractères Nom de l’entête

Signification

Accept-Charset

Énumère les codages de caractères acceptés (en HTTP).

Accept-Encoding

Énumère les codages de transfert acceptés (en HTTP).

Accept-Language

Énumère les l’utilisateur.

Content-Encoding

Stipule le codage de transfert d’origine des données, par exemple la compression.

Content-Transfer-Encoding

Stipule le codage de transfert utilisé lors de l’envoi pour faire passer des octets là où du « 8 bits » brut pourrait poser des problèmes (7bit, 8bit, base64, quoted-printable).

Content-Language

Précise la langue du message reçu, rarement utilisé.

Content-Type

Précise le type de média et le codage de caractères.

MIME-Version

Indique l’utilisation de MIME et sa version (la seule définie est la version « 1.0 »).

Subject

L’objet (le titre) du message. Les caractères non ASCII sont codés en « mots-codés », voir ci-dessus.

Transfer-Encoding

Précise le codage de transfert du corps du message. Pour HTTP, permet d’indiquer la longueur du message, s’il est découpé en morceaux (« chunked »), s’il est chiffré.

préférences

linguistiques

de

10.6 ADRESSES INTERNATIONALISÉES 10.6.1

Noms de domaine et DNS

Les ordinateurs reliés à Internet ont tous une adresse IP de type 213.91.4.193 qui sert à aiguiller directement les paquets de données sur le réseau. Pour simplifier l’identification de ces ordinateurs par les utilisateurs, on préfère donner à chaque ordinateur un nom mnémotechnique. L’association entre ce nom et son adresse IP est gérée par un service de noms nommé DNS (Domain Name System). On appelle résolution de noms de domaine (ou résolution d’adresses) la corrélation entre les adresses IP et le nom de domaine associé. Le système DNS s’appuie sur une structure arborescente dans laquelle sont définis des domaines de niveau supérieur (appelés domaines de tête ou TLD, Top-level domain), rattachés à un nœud racine représenté par convention dans l’arbre par un point (figure 10.6).

10.6 Adresses internationalisées

221

On appelle nom de domaine ou de sous-domaine chaque nœud de l’arbre. Chaque nœud possède une étiquette d’une longueur maximale de 63 caractères. Le nom de domaine complet exprimé sous la forme d’une chaîne de caractères correspond ainsi à un arbre inversé où chaque nœud est séparé du suivant par un point (« . »). Le standard qui précise les valeurs d’étiquette admises, le RFC 1123, n’autorise qu’un sous-ensemble de caractères ASCII : « A » à « Z », « a » à « z », « 0 » à « 9 » ainsi que le trait d’union « - ». Le point est admis dans les noms de domaine, mais il ne sert qu’à départager les étiquettes et à marquer le nombre de nœuds. L’extrémité d’une branche est appelée hôte, et correspond à une machine ou une entité du réseau. Le nom d’hôte qui lui est attribué doit être unique dans le domaine considéré. À titre d’exemple le serveur web d’un domaine porte ainsi généralement le nom www. Les domaines sont structurés de façon hiérarchique. L’élément à l’extrême droite dans le nom du domaine, le ca dans hapax.qc.ca, se nomme le domaine de tête. Il désigne le type d’organisme de haut niveau ou le pays d’origine. Les domaines de tête génériques (gTLD) se composent habituellement d’un suffixe de trois lettres, par exemple .com, .net, .org, .edu. Les domaines de tête de code de pays (ccTLD) sont normalement composés du suffixe de deux lettres — comme .ca, .be, .fr, etc. — qui est attribué à chaque pays par les Nations Unies (voir § 9.2, ISO 3166 – Indicatifs de pays).

Figure 10.6 – Hiérarchie de noms de domaine

Dans l’exemple de la figure 10.6, .ca est le domaine de tête de code de pays (ccTLD) identifiant le Canada, tandis que .com est le domaine de tête générique (gTLD) désignant le secteur commercial. Les politiques et l’administration du domaine .ca sont établies par une agence canadienne (l’ACEI) et régies par les lois canadiennes. Les domaines de tête génériques sont administrés aux États-Unis en vertu des lois américaines. À l’intérieur de ces grands domaines, on trouve des sous-domaines qui correspondent à des provinces (au Canada), à de grandes entreprises ou à d’importantes institutions. On peut encore subdiviser ces sous-domaines en de plus petits sousdomaines de niveau inférieur.

222

Chapitre 10. Unicode et les protocoles Internet

Les serveurs de noms du DNS sont hiérarchiques. Chaque domaine et sous-domaine est associé à un ensemble de serveurs qui font autorité dans la recherche de nom : un serveur de noms de domaine appelé « serveur de noms primaire » ainsi qu’un ou plusieurs serveurs de noms secondaires qui peuvent en assurer la relève en cas de défaillance. Les serveurs DNS connaissent l’adresse physique (IP) des serveurs DNS de niveau immédiatement inférieur. La hiérarchie des serveurs DNS qui font autorité épouse la hiérarchie des domaines. Lorsque l’on veut trouver l’adresse physique d’une machine cible, les serveurs qui gèrent le DNS s’envoient des requêtes de façon à remonter suffisamment dans la hiérarchie pour trouver l’adresse physique du correspondant.

10.6.2 Internationaliser les URI Alors qu’il est désormais relativement facile d’écrire des pages Internet dans les langues du monde entier, les adresses de ces pages sont encore généralement exprimées sous la forme d’URI (identificateurs de ressource uniforme). La syntaxe des URI est précisée par le RFC 3986 STD 66 qui en pratique limite les adresses Internet à un jeu de caractères restreint aux seules lettres latines de base, à savoir sans diacritique, aux chiffres européens et à quelques symboles. Mais chaque jour qui passe voit de nouveaux sites Internet naître, la plupart aujourd’hui dans des pays non anglophones. Ceci rend de plus en plus criant le besoin en termes d’internationalisation qui existe dans le domaine de l’adressage des pages Internet. Une adresse internet écrite dans sa propre langue et dans son écriture habituelle — plutôt qu’une transcription en caractères latins — est plus facile à créer, à mémoriser, à transcrire, à deviner, il est aussi plus aisé de se l’approprier. Ainsi l’adresse http://ਛᄢ.tw/ est-elle nettement plus mnémotechnique pour un Chinois que http://ncu.edu.tw/ (la même université). Mais ce problème existe également en français où le site http://biscuits-salés.com/ est nettement plus appétissant que sa version ASCII http://biscuits-sales.com/. On nomme IRI (identificateur de ressource internationalisée) les adresses Internet qui permettent l’utilisation de caractères provenant d’un large éventail d’écritures. Prenons comme exemple d’IRI l’adresse fictive présentée figure 10.7. http:// protocole

www.biscuits-salés.com

Noël.html

domaine Figure 10.7 – Parties d’un IRI

chemin

10.6 Adresses internationalisées

223

Cet IRI se compose de trois parties (figure 10.7) :

• Le «

http:// » indique le protocole utilisé. Tous les noms de protocoles définis actuellement n’utilisent que des caractères ASCII.

• La partie suivante « www.biscuits-salés.com » précise le nom de domaine. • Enfin, le reste de l’adresse est un chemin qui indique la position de la ressource à partir de la racine du serveur. À l’origine, il s’agissait habituellement du nom d’un fichier sur le serveur. Mais de plus en plus de sites sont sous gestion d’un logiciel gestionnaire de contenu (blogues, wiki, sites de grandes et même moyennes entreprises, site de presse ou des sites « Web 2.0 » comme Facebook, MySpace ou Flickr. Sur ces sites le reste de l’adresse (par exemple Noël.html) n’est pas nécessairement le nom d’un fichier sur le système qui l’héberge.

Figure 10.8 – Acteurs dans la résolution d’un IRI

Quatre conditions existent pour que les IRI fonctionnent (figure 10.8) :

• La syntaxe du document qui comprendra les IRI, par exemple, HTML ᆰ, XML, SVG, doit permettre l’utilisation de caractères non ASCII dans les adresses Internet.

• Les programmes qui liront ces IRI (les navigateurs ᆱ, les analyseurs, etc.) doivent permettre la saisie et l’utilisation de caractères non ASCII dans les adresses Internet.

• Il doit être possible de transmettre ces IRI par le protocole Internet nécessaire (HTTP ᆲ, FTP, IMAP, etc.).

• Il faut que l’on puisse comparer avec succès la chaîne de caractère précisée dans votre adresse Internet et les noms des ressources ainsi désignées sur le système de fichiers ཱི ou le registre DNS ཱི qui les héberge. Les deux premières conditions sont aujourd’hui remplies par de nombreux logiciels modernes. C’est ainsi que HTML 4.0, les identificateurs système d’XML 1.0,

224

Chapitre 10. Unicode et les protocoles Internet

l’attribut href de XLink et le type de données anyURI des Schéma XML prennent tous en charge les IRI. Il en va de même, comme nous le verrons dans les paragraphes suivants, pour les navigateurs les plus importants. Malheureusement, peu de protocoles permettent la transmission d’IRI inchangés. La plupart exigent que les adresses soient précisées uniquement à l’aide de caractères ASCII comme c’est le cas pour les URI. Il y a cependant moyen de contourner ces problèmes de manière bien précise. Nous passerons en revue cette stratégie dans les paragraphes suivants. Quant à la quatrième condition qui impose que les chaînes de caractères envoyées puissent être décryptées et interprétées sur le système cible, on utilise l’UTF-8 comme lingua franca. Mais voyons ceci dans plus de détails.

10.6.3 Noms de domaine internationalisés (NDI) Un nom de domaine internationalisé est un nom de domaine Internet qui contient (potentiellement) des caractères non ASCII. De tels noms de domaine peuvent contenir des signes diacritiques contenus dans beaucoup de langues européennes, ou des caractères non latins comme l’alphabet arabe. Si le DNS permet d’associer un nom « transparent aux 8-bits » à un numéro d’adresse IP, il n’en va pas de même du standard qui définit les noms de machines (RFC 1123) qui lui n’autorise que les lettres ASCII, les chiffres et le trait d’union. C’est pour combler cette lacune que l’IETF a établi une méthode normalisée en mars 2003 qui permet l’utilisation de noms de domaine internationalisés. Cette méthode est précisée par les RFC 3490, 3491, 3492 et 3454, son jeu de caractères est Unicode 3.2. L’IETF a décidé de ne pas modifier le protocole DNS, mais de faire porter l’effort sur les applications, qui doivent donc transformer les NDI en ASCII. RFC 3490 définit le protocole général. Tout le travail doit être effectué par les applications (navigateur Internet, logiciel de courriel, etc.). Sur le fil, dans les fichiers DNS de zone, on ne trouve que de l’ASCII, les caractères admis par le RFC 1123. RFC 3454 décrit le protocole stringprep et RFC 3491 nameprep. Nameprep est une version particulière de stringprep destinée spécifiquement aux NDI, elle précise les étapes que doit suivre une application quand elle traite un NDI. Ces étapes comprennent la normalisation de la chaîne d’entrée en forme KC (voir § 4.3, Formes normalisées), le passage en minuscules et l’élimination de codets habituellement invisibles. Le but de cette transformation est de s’assurer que des chaînes équivalentes en tant que noms de domaine soient codées de la même manière. Ainsi, « maße » et « masse » aboutiront-ils à une seule représentation1, après réduction à la forme canonique par nameprep. Il en sera de même pour « CAFÉ » et « café », car les noms de domaine ne sont pas sensibles à la casse. Enfin, le RFC 3492 définit Punycode qui transforme les chaînes canoniques préparées par nameprep en ASCII ou plus précisément dans le sous-ensemble ASCII 1. Ces deux graphies sont possibles en allemand, car en Suisse alémanique on remplace systématiquement le « ß » par deux « s », même si « maße » et « masse » ont des sens différents.

10.6 Adresses internationalisées

225

admis par le RFC 1123. Ces noms Punycode ASCII commencent tous par le préfixe « xn-- » (les lettres « x » et « n » et deux traits d’union). On a choisi ce préfixe, car il n’y a pas de raison qu’un domaine actuel utilise deux traits d’union successifs dans son nom. La chaîne « Biscuits-salés » est ainsi transformée en « xn--biscuits-sals-mhb ». Le « x-- » initial et le trait d’union « - » final sont des délimiteurs, ils entourent la version ASCII de Biscuits-salés (sans le « é » non admis). La partie « mhb » est la manière dont Punycode représente le « é » et sa position dans la chaîne originale.

Exemples de noms de domaine complets Prenons deux noms de domaine internationalisés, www.Biscuits-salés.com et notre université formosane http://ਛᄢ.tw/, et passons en revue le processus au complet :

• Diviser le nom en composants séparés par des « . » et traiter chaque partie séparément. Dans nos exemples, les composants « www », « com » et « tw » ne posent pas de problèmes et ne nécessitent pas de traitement particulier. Il reste « Biscuits-salés » et « ਛᄢ ».

• Utiliser l’algorithme Nameprep. Dans notre cas, « Biscuits-salés » devient « biscuits-salés », quant à « ਛᄢ » il demeure intact. Dans certains cas anormaux, la transformation du nom pourrait être conséquente.

• Appliquer l’algorithme punycode au résultat. Pour « biscuits-salés », on

obtient « xn--biscuits-sals-mhb » et pour « ਛᄢ » on obtient « xn--fiq80y ». On remarquera qu’il n’existe pas de partie ASCII pour ce nom, ce qui est normal tout compte fait, mais uniquement une représentation cryptique des caractères exotiques et de leur position dans la chaîne source.

On assemble ensuite les différentes parties et obtient les domaines NDI complets suivants : www.xn--biscuits-sals-mhb.com et xn--fiq80y.tw. L’idée n’est pas de faire apparaître ces noms à l’utilisateur, mais uniquement de créer des noms de domaine Internet valables compatibles avec l’infrastructure existante.

Enregistrement des noms de domaine internationalisés Chaque registraire des noms de domaine1 de tête — qu’il s’agisse d’un ccTLD ou d’un gTLD — décide de la liste des caractères que leurs clients peuvent utiliser dans les noms de domaine qu’ils sollicitent. Si un client désire obtenir un nom de domaine avec des caractères non ASCII, mais permis par ce domaine de tête, le registraire lui attribue en réalité le nom de domaine équivalent sous sa représentation Punycode. À l’heure actuelle, tous les registraires nationaux ne permettent pas l’utilisation de caractères non ASCII. En fait, parmi les domaines nationaux francophones, seul le domaine .ch le permet. En revanche, il est permis de créer un domaine accentué comme « viagénie.com » dans le domaine .com (un gTLD). De nombreux pays d’Extrême-Orient permettent désormais l’utilisation de NDI : http://www.䞲⁖.kr/, http://บἨᄢቑ.tw/, etc. 1. Également appelés autorités de gestion des noms des domaines.

226

Chapitre 10. Unicode et les protocoles Internet

Les noms de domaine de tête comme le « tw » et le « kr » doivent encore être écrits en caractères latins pour l’instant.

Résolution de l’adresse NDI Voyons ce qu’il se passe lorsqu’un utilisateur clique sur un hyperlien ou saisit un IRI dans la barre d’adresse d’un navigateur. Par exemple, (nous reviendrons sur le cas de Noël.html par la suite). Rappelons que le navigateur décomposera d’abord l’IRI en ses composantes : le protocole (http://), le nom de domaine (www.biscuits-salés) et le chemin. Le navigateur traite ensuite le nom de domaine internationalisé (ici puisqu’il comprend un accent). Comme nous l’avons vu auparavant, l’agent utilisateur (le navigateur) convertit alors le nom de domaine en punycode (dans notre cas www.xn--biscuits-sals-mhb.com). Ensuite, on résout de la façon habituelle cette adresse punycode en une adresse décimale IP pointée (ex. : 128.27.96.12). Grâce à celle-ci, l’agent utilisateur se connecte au bon serveur et lui demande la page souhaitée grâce à une requête HTTP de ce type : GET /index.htm HTTP/1.1 Host: www.xn-biscuits-sals-mhb.com

(Le paramètre Host sert au multi-hébergement quand un seul serveur dessert plusieurs noms de domaine). ou, si la requête passe par un mandataire (« proxy »), de ce type : GET http://www.xn-biscuits-sals-mhb.com/index.hm HTTP/1.1

Comme tous les noms de domaine sont passés en punycode et ne contiennent aucun caractère inhabituel pour les protocoles comme HTTP, ces requêtes ne posent donc aucun problème particulier.

10.6.4 Menaces informatiques : hameçonnage et parodie La parodie est une des techniques d’escroquerie les plus anciennes en informatique : il s’agit d’arriver à faire croire à l’utilisateur qu’il dialogue bien avec le serveur qu’il désire contacter alors qu’il communique avec un serveur qui ne lui veut pas que du bien… La version Internet de ce phénomène se nomme l’hameçonnage (le phishing en anglais). Parmi les cas les plus connus d’hameçonnage, on peut citer celui du courriel-leurre qui indique à un internaute qu’il doit se connecter à sa banque ou au site de paiement en ligne paypal.com pour y effectuer une opération. Mais voilà l’URI, mentionné dans le message ne pointe pas vers paypal.com, mais vers paypa1. com (hé oui, avec le chiffre « 1 » et non la lettre « 1 »). Le site imite parfaitement l’apparence du site légitime. À partir de là, une fois pris à l’hameçon, l’utilisateur fournira en toute confiance, pour accéder à son compte, son nom d’utilisateur et son mot de passe qui pourront être utilisés par les arnaqueurs. Une fois ces informations confidentielles divulguées, le site mystificateur pourra tout simplement rediriger l’utilisateur vers le site authentique, et l’utilisateur n’y verra que du feu.

10.6 Adresses internationalisées

227

Comme on le voit, il n’est pas besoin d’Unicode pour produire des adresses Internet contrefaites. La nouveauté avec Unicode et les NDI est le répertoire singulièrement plus important de lettres similaires désormais à la disposition des mystificateurs. Un o (comme dans http://dunod.com) pourrait non plus simplement être parodié par un 0 (un zéro) un peu maladroit, mais aussi un « о » cyrillique et un « o » grec disponibles dans la plupart des polices système et qui ont souvent exactement le même œil, mais bien sûr pas le même numéro de caractère (U+03BF pour le o grec, U+043E pour le o cyrillique) !

Stratégie des DNS face à l’hameçonnage Les règles d’enregistrement de noms de domaine internationalisés peuvent, dans une certaine mesure, éviter l’usurpation de noms de domaine internationalisés. Plusieurs stratégies sont envisageables :

• Restreindre les caractères admis dans les NDI à ceux qui sont utilisés par un petit ensemble de langues : habituellement la ou les langues locales, et parfois les langues de pays voisins. C’est la méthode adoptée par l’autorité d’enregistrement allemande (DENIC) qui ne permet dans les noms de ses domaines que les 26 lettres latines de base, le trait d’union et 92 lettres latines diacritées supplémentaires utilisées en allemand (ä, ö, ü) mais également dans de nombreuses langues d’Europe (å, ã, ą, æ, ć, č, etc.)

• Réserver en même temps que le nom demandé des noms de domaine considérés comme équivalents. Ces noms supplémentaires peuvent être attribués au demandeur originel ou assurés de ne pas être attribués à d’autres demandeurs. Ainsi, un registraire peut permettre l’enregistrement de café.dd et réserver en même temps le nom cafè.dd pour qu’il ne puisse pas être enregistré par un tiers ou qu’il soit attribué automatiquement au demandeur de café.dd. Dans le même ordre d’idée, on pourra vouloir considérer comme équivalentes les formes simplifiées et traditionnelles des idéogrammes chinois et les concéder en même temps au même demandeur.

• Ne pas permettre l’utilisation de plusieurs écritures différentes dans un même nom, tout en permettant la prise en charge de nombreuses écritures différentes. Ceci permet d’éviter, dans un registre qui admet les écritures cyrillique et latine, la ruse utilisée dans la parodie de paypal.com qui consistait à remplacer le a latin (U+0061) par le a cyrillique (U+0430). Il en va de même pour le tamoul et le malayalam, deux écritures de l’Inde qui peuvent apparaître dans les noms d’un même registre, où la lettre tamoule ka ࠎ(U+0B95) est fort semblable à la lettre malayalam ka ࣷ (U+0D15). On appelle ces lettres identiques ou fort semblables des homoglyphes.

Stratégie des navigateurs face à l’hameçonnage Les navigateurs Internet adoptent des stratégies variées quant au risque d’hameçonnage. Dès qu’ils soupçonnent une parodie par homoglyphes interposés, ils

228

Chapitre 10. Unicode et les protocoles Internet

affichent généralement l’URI sous sa forme punycode plutôt que sa forme naturelle en Unicode. Toutefois, les différents navigateurs n’utilisent pas tous les mêmes critères pour décider quand ils affichent l’adresse en punycode. Il ne faut pas non plus conclure que, parce qu’une adresse apparaît sous sa forme punycode, il s’agit d’une adresse contrefaite. Il revient à l’utilisateur de déterminer, en dernière analyse, si l’adresse est correcte ou devrait plutôt être évitée. Internet Explorer 7 affiche une adresse en punycode si une des conditions suivantes est vérifiée :

• Si le nom de domaine contient un caractère qui appartient à une écriture qui n’est pas utilisée par une des langues mentionnées dans les préférences linguistiques de l’utilisateur (voir § 10.5.1, La négociation de langue). L’affichage de la page http:// ουτοπία.δπθ.gr/, quand les préférences linguistiques ne comprennent pas le grec, suscitera l’apparition du nom sous forme punycode http://xn--kxae4bafwg. xn--pxaix.gr/ ainsi que d’un message dans la barre d’information.

• Si une des étiquettes du nom de domaine (une série de caractères séparés par des points) contient des caractères de différentes écritures qui ne font pas partie du répertoire d’une même langue. Ainsi le nom βασιλεύςкороль.org (avec un seul point) apparaîtra-t-il en punycode, car on ne peut mêler des caractères grecs et cyrilliques dans une même étiquette. Par contre, βασιλεύς. король.org (avec deux points) n’est pas suspect. De même, il est parfaitement légitime de mêler dans une même étiquette des kanas et des kanjis japonais comme dans ᧲ർ᷷ᴰࠟࠗ࠼.jp.

• Si le nom de domaine contient des caractères qui ne font partie d’aucune écriture : J♥Mtl.museum.

• En revanche, IE7 affichera un NDI en Unicode même s’il mélange de l’ASCII et une seule écriture tirée d’une liste restreinte. C’est le cas du coréen qui mélange parfois l’ASCII et les hangûl, par exemple dans les noms d’entreprises : http://lg㩚㧦.kr/. Mais le cyrillique ne fait pas partie de cette liste d’écritures permises, car il est suspect (trop proche du latin) comme on l’a vu dans le cas de l’hameçonnage de paypal.com. Firefox 2.x adopte une autre méthode. Il n’affiche les noms de domaine sous forme Unicode que pour certains domaines de tête (TLD) de confiance qui permettent explicitement l’enregistrement de nom de domaine internationalisé après avoir adopté et publié une politique antihameçonnage. À partir de là Firefox fait confiance à ces domaines de tête. Une liste des domaines de tête de confiance est disponible1. Le domaine de tête « biz » est repris dans la liste des TLD de confiance, une adresse comme lechasseurfrançais.biz sera donc affichée en Unicode, alors que, puisque le domaine de tête « com » n’est pas dans cette liste, l’adresse viagénie.com (qui existe) apparaîtra en punycode sous Firefox2 (en revanche, IE7 l’affichera sous sa 1. Voir . 2. Il est possible de modifier ce comportement implicite de Firefox, voir .

10.6 Adresses internationalisées

229

forme accentuée). Notons, en outre, que les NDI qui contiennent certains caractères dangereux (comme U+2044 barre de fraction) 1, même parmi les domaines de tête de confiance, sont considérés comme suspects et seront affichés en punycode.

10.6.5 Caractères non ASCII dans les chemins des IRI Alors que le codage des noms de domaine se limite à de l’ASCII (ou du punycode), il en va tout autrement pour les noms de ressources (les chemins) sur les serveurs. Le RFC qui définit la syntaxe des URI habituels permet déjà de transmettre des caractères non ASCII à l’aide de chaînes qui commencent par un « % » et suivie de deux chiffres hexadécimaux (%20 représente ainsi l’espace)2. Par malheur, ce RFC ne précise pas quel devrait être le codage de ces caractères hexadécimaux ni comment le client peut informer le serveur du codage adopté. Penchons-nous sur l’IRI introduit précédemment http://www.biscuitssalés.com/Noël.html, le chemin peut être codé par un navigateur qui décide d’opérer en Latin-1 parce que, par exemple, la page d’origine est codée en Latin-13, de la façon suivante : No%EBl.html

Mais si le navigateur décide de coder le « ë » en UTF-8, parce que la page d’origine est en UTF-8, la chaîne transmise sera : No%C3%ABl.html

Dans Firefox 2, si on tape « Noël.html » dans la boîte d’adresse, l’adresse est codée

par défaut en Latin-1 : No%EBl.html

On peut cependant modifier ce comportement comme nous l’avons vu en modifiant la variable appropriée dans about:config. Ceci ne poserait pas trop de problèmes s’il existait une manière de préciser le codage utilisé pour les chaînes URI. Malheureusement, il n’en existe pas. Et, même si cette information était transmise, le nombre total de codages que les serveurs devraient prendre en charge serait très important. Notons enfin que le système d’exploitation qui

1. Parmi les autres caractères dangereux : U+2215 barre oblique de division, u+2000 demicadratin, U+2006 sixième de cadratin, U+2007 espace tabulaire, U+06D4 point arabe, etc. La plupart peuvent servir à parodier les séparateurs d’URL. 2. Pour être plus précis le %HH code en fait des octets et non des caractères, le %20 ne code l’espace que si le codage est (basé sur) l’ASCII, ce qui est essentiellement toujours le cas. 3. C’est le comportement implicite sous Firefox 2.x; il est toutefois possible de le changer en mettant network.standard-url.encode-utf8 à true dans about:config (y accéder en tapant « about:config » dans la barre d’adresse). Internet Explorer 7 adopte la convention inverse et code les %hh en UTF-8 par défaut. Ce comportement peut être inhibé en désactivant l’option « Toujours envoyer les URL en tant que UTF-8 » dans Outils > Options Internet > Onglet Avancés, sous-section International.

230

Chapitre 10. Unicode et les protocoles Internet

héberge la ressource visée peut coder les noms de fichiers dans un codage totalement différent de ceux que le client utilise : EBCDIC, UTF-16, EUC-JP au Japon, etc.

RFC 3987 et les IRI Le RFC 3987 propose une solution à cette confusion : l’utilisation d’Unicode comme codage pivot. Ce standard précise que toutes les chaînes doivent être codées en UTF-8 avant sa transformation en notation %hh. Un transcodage pourrait s’avérer nécessaire si la page où se trouve ce chemin n’est pas en UTF-8. Le serveur pour sa part doit comprendre les URL en UTF-8 qui lui sont transmises et les convertir vers le codage réellement utilisé par la machine locale pour accéder à ces ressources. Voyons maintenant à quoi ressemblent les entêtes HTTP de notre requête initiale (http://www.biscuits-salés.com/Noël.html) : GET / No%C3%ABl.html HTTP/1.1 Host: xn--biscuits-sals-mhb.com

Schématiquement, on obtient la vue d’ensemble du processus présentée figure 10.9.

Figure 10.9 – Traitement des IRI

Rappelons que tout ce processus devrait idéalement se faire sans que l’utilisateur se rende compte de toutes les transformations sous-jacentes. Le navigateur devrait idéalement présenter les IRI sous leur forme naturelle dans l’écriture de l’utilisateur (pas de nom de domaine en punycode, pas de ressource et nom de chemin en notation en %).

10.6 Adresses internationalisées

231

Notons à ce stade qu’il peut exister des complications liées à l’utilisation de majuscules dans le nom de la ressource, c’est le cas souvent sous Unix/Linux, bien que des serveurs permettent de préciser que les URL/IRI doivent être considérés comme unicaméraux1 en ce qui a trait aux lettres latines de base (« Recettes », « recettes » et « RECETTES » représentent la même chose). Cette option ne s’applique probablement pas aux autres lettres. Il faudra alors prévoir des traitements spéciaux tels que la réécriture des URL/IRI pour rendre ces lettres équivalentes.

En attendant que le RFC 3987 soit mis en œuvre partout… Bien que, comme on l’a vu, il existe désormais un mécanisme qui permet de créer des URL qui emploient des caractères non ASCII, il n’est pas encore généralisé. En outre, il n’est pas certain que tous les utilisateurs de votre site parviendront à saisir les caractères exotiques nécessaires pour atteindre votre page à l’adresse non ASCII. Il est donc sans doute préférable de faire preuve de prudence sur ce plan et de coder votre ressource sous plusieurs noms : 1. Configurer votre serveur pour qu’il traite la forme UTF-8 correctement : http:// hapax.qc.ca/No%C3%ABl.html). 2. Accepter également sa forme dans le codage le plus commun (Latin-1 en français) http://hapax.qc.ca/No%EBl.html, à nouveau un alias peut faire l’affaire sinon, sous Apache, Martin Dürst a développé un module particulier (mod_fileiri2) qui effectue cette réécriture automatique des URL codées à l’aide de codages « historiques », comme le Latin-1, vers leur forme équivalente en UTF-8. 3. Accepter la même URL sous sa forme simplifiée http://hapax.qc.ca/Noel.html si

des utilisateurs étrangers qui n’ont pas accès à un clavier avec accent devaient pouvoir y accéder. Ceci peut se faire sous la forme d’un alias ou d’une réécriture d’URL vers la même ressource que ci-dessus. Apache 2.0 sur Windows NT, 2000 et XP utilise à présent l’UTF-8 pour tous les noms de fichiers. Ces noms de fichiers sont directement traduits vers le codage « naturel » du système de fichiers. La situation est quelque peu différente sur les systèmes de fichiers Unix où il n’y a pas de codage naturel, les noms de fichiers n’y sont que des suites d’octets. Ce sont les applications (comme ls et cd) qui interprètent ces noms et leur interprétation dépend du profil linguistique, de la locale active comme on dit en jargon. Cette locale peut varier d’un processus à l’autre. Dans le cas d’Apache, les noms de fichiers UTF-8 seront donc convertis vers le jeu de caractères mentionné dans la locale du processus qui exécute Apache.

1. Sans distinction de casse, les majuscules et les minuscules sont équivalentes. 2. Voir .

232

Chapitre 10. Unicode et les protocoles Internet

10.7 LA LOCALE POSIX Ceci nous amène tout naturellement au concept de locale, de profil linguistique, utilisée sur les serveurs et plus particulièrement sur les systèmes de la famille Unix. La locale permet de définir les conventions culturelles et linguistiques que doivent respecter les bibliothèques UNIX (ainsi que les utilitaires et programmes) quand celles-ci ont un impact sur le fonctionnement de ces bibliothèques. Le plus souvent, il s’agit de définir la langue des messages affichés par le système et par les programmes ainsi que le jeu de caractères codés à utiliser. Sur Unix, Linux et les autres plateformes de type POSIX, ces locales sont définies sous une forme qui rappelle le RFC 3066. Toutefois, la variante est précisée autrement et la locale peut préciser le jeu de caractères codés ce qui n’est pas le cas dans les étiquettes que nous avons vues au chapitre 9. La syntaxe de cette locale est définie de la façon suivante : [[-][.][@]]





< langue > est un indicatif ISO 639 sur deux lettres minuscules (ex. : « fr »

pour le français, « de » pour l’allemand, « en » pour l’anglais) ;



< région > est un indicatif ISO 3166 constitué de deux lettres majuscules

représentant un territoire, exemples : « JP » pour le Japon, « FR » pour la France, « NL » pour les Pays-Bas, « ES » pour l’Espagne ;

• •

< jeudecar > représente un codage comme « ISO-8859-1 » ou « UTF-8 » ; < variante > permet de préciser qu’il s’agit d’une version particulière de la locale, c’est ainsi que no_NO.ISO8859-1@bokmal représente la variante bokmål du

norvégien (il en existe une autre variante appelée nynorsk) de Norvège codée à l’aide du Latin-1, alors que zh_CN.UTF-8@stroke représente le chinois de Chine codé en UTF-8 et trié grâce à la méthode du nombre de traits. On notera que tous les champs précédents sont optionnels. En règle générale, les valeurs par défaut globales correspondent à la locale « C » (encore appelée « POSIX ») qui correspond au résultat que produirait un système américain non internationalisé. Pour sélectionner une locale, il faut affecter une valeur de locale à une ou plusieurs variables d’environnement. Le plus simple est d’affecter une valeur à la variable LANG. Cette variable décrit l’ensemble des aspects d’une locale. Voici comme préciser que la locale est désormais du français de France avec comme codage l’UTF-8 : > LANG= fr_FR.UTF-8; export LANG # pour les shells Bourne, ksh, bash,… > export LANG=fr_FR.UTF-8 # syntaxe ramassée pour bash ou ksh > setenv LANG fr_FR.UTF-8 # pour le shell C (csh), tcsh et ses dérivés

Comment on le voit la manière d’affecter une valeur à une variable d’environnement varie selon le shell Unix utilisé. Voyons l’effet de la modification de la variable LANG :

10.7 La locale POSIX

233

> man truc No manual entry for truc > export LANG=de > man truc Kein Manual-Eintrag für truc vorhanden

Le premier man truc utilise la valeur implicite (C, POSIX) de LANG, un message d’erreur en anglais apparaît puisqu’il n’existe pas de commande « truc ». Après avoir précisé comme valeur pour LANG l’allemand, le message d’erreur apparaît désormais en allemand. Notez qu’il s’agit ici d’une situation un peu idéale, le répertoire des locales traduites est en général restreint et beaucoup de commandes ne sont pas « internationalisées » sur de nombreux systèmes Unix. Nous verrons dans le chapitre 12 des infrastructures nettement plus complètes en matière d’internationalisation (ICU, .NET) et de ressources localisées (CLDR). Affecter une valeur à la variable LANG est la manière la plus simple de préciser une locale. Toutefois, cette opération agit sur toutes les opérations où peut intervenir un aspect linguistique ou culturel : que ce soit l’affichage des messages, le tri, le formatage des dates ou des montants. C’est ainsi que si on affecte d’abord à LANG la valeur « ja » et qu’on lance un programme de tri les données seront triées selon les règles japonaises. Si l’on change ensuite la valeur LANG pour y mettre « fr » et qu’on relance le programme, les mêmes données seront triées à la française. Il est souvent souhaitable de pouvoir régler de manière plus fine ce genre de comportement et permettre l’affichage des messages dans une langue comme l’anglais tout en triant les données à l’espagnole (le tri est fonction des données à trier, plus que de la langue préférée d’interface de l’utilisateur). Pour obtenir cette granularité plus fine, on utilise les catégories de locale dont la liste est dressée dans le tableau 10.5. Tableau 10.5 – Catégories de locale Catégorie

Rôle

LC_COLLATE

Règles d’ordonnancement (de tri).

LC_CTYPE

Classement des caractères et conversion de casse.

LC_MESSAGES

Format des réponses (oui/non) et des messages d’information.

LC_MONETARY

Format des montants.

LC_NUMERIC

Format des nombres (autres que les montants).

LC_TIME

Format des dates et heures.

De la sorte, on peut préciser qu’en général l’interface, les montants, les dates doivent être en néerlandais, mais que le tri doit se faire en utilisant l’algorithme de collationnement allemand appelé « tri de l’annuaire », lequel considère les lettres à umlaut comme la lettre de base correspondante suivie d’un « e » (ex. : ö = oe) : > setenv LANG nl_BE > setenv LC_COLLATE de_DE.ISO8859-1@phone

234

Chapitre 10. Unicode et les protocoles Internet

Il faut remarquer que la valeur de LC_COLLATE (et de toutes les autres catégories) prend le dessus sur la valeur précisée par LANG. Il reste finalement une dernière variable d’environnement qui nous intéresse : LC_ALL. Celle-ci ressemble à LANG en ce qu’elle affecte toutes les catégories, mais, contrairement à LANG, LC_ALL prime sur toutes les autres catégories. Le tableau 10.6 illustre cette relation. La définition de la variable LC_ALL force donc la valeur de la locale et contrecarre l’affectation de valeurs aux autres variables LC_*, c’est pourquoi il vaut mieux ne pas la définir sauf dans le cadre de tests. Tableau 10.6 – Catégories de locale par ordre de priorité Catégorie

.

Ordre de préséance

LC_ALL

En premier

LC_COLLATE LC_CTYPE LC_MESSAGES LC_MONETARY LC_NUMERIC LC_TIME

D’égale priorité

LANG

En dernier

10.7 La locale POSIX

235

Résumé Les premiers protocoles de l’Internet qui permettaient de transférer du texte ne prévoyaient habituellement pas l’utilisation d’autres caractères que les caractères ASCII et n’avaient donc pas ressenti le besoin de permettre l’identification du codage utilisé dans la transmission des textes. Avec l’avènement de la messagerie, on a éprouvé la nécessité de permettre l’adjonction de pièces jointes de différents types et codées de différentes manières. C’est ce qui a justifié la définition d’un standard appelé MIME qui définit plusieurs entêtes. Un de ceux-ci, Content-Type, définit le type de message envoyé. Tous les messages dont le Content-Type précise que le document est du « texte » — plutôt qu’une image ou une application par exemple — devraient être accompagnés d’un paramètre, appelé charset, qui précise le codage de caractères adopté : Content-Type: text/plain;charset=UTF-8

La même série d’entêtes a été reprise par HTTP pour préciser le type des documents transmis et la manière dont les textes ont été codés. Il importe que le codage des caractères d’un document XML ou (X)HTML soit précisé afin que celui-ci puisse être traité correctement. On peut préciser le codage de trois manières différentes : 1. Envoyer le paramètre charset dans un entête HTTP Content-Type. Pour ce faire, il faut avoir accès au paramétrage du serveur ou servir le document à l’aide d’un script (comme JSP). Malheureusement, le jeu de caractères imposé par un serveur n’est pas fiable, car il ne connaît pas le contenu du fichier qui peut changer (le cas est différent avec un script). Le jeu de caractères mentionné dans l’entête Content-Type prime malheureusement sur les autres méthodes. Il est donc plus sage de désactiver l’envoi du charset dans l’entête Content-Type. 2. Pour du XML (y compris du XHTML), il faut se servir du pseudo-attribut encoding dans la déclaration XML au début du document, ou de la déclaration de texte au début d’une entité :

Si vous fournissez des pages XHTML sur le Web, le mieux est de les coder en UTF-8 (ou en UTF-16 avec un IOO pour indiquer l’ordre des octets), car il est alors permis d’omettre la déclaration XML qui peut occasionner des difficultés avec d’anciens navigateurs. 3. Pour du HTML ou du XHTML servi comme du HTML, il faut toujours utiliser une balise au sein de l’entête du document :

Le protocole HTTP permet également la négociation de langue : l’utilisateur précise dans les préférences de son navigateur quelle version linguistique d’un document linguistique il désire lire et le navigateur envoie cette information au

236

Chapitre 10. Unicode et les protocoles Internet

serveur dans l’entête HTTP Accept-Language. Le serveur détermine alors quelle est la meilleure version linguistique d’un document à renvoyer. La manière dont ce choix s’effectue dépend du serveur, nous avons brièvement présenté la manière de configurer un des serveurs les plus populaires : Apache. La négociation de langue peut s’avérer bien pratique, mais elle n’est pas une panacée : – Tous les usagers ne configureront pas correctement leur navigateur. – Certains usagers préfèrent lire la V.O. d’un document plutôt que sa traduction. – Il existe des cas où les différentes versions linguistiques d’un document ne sont pas équivalentes et la négociation linguistique fournira un résultat incorrect. C’est pourquoi il est important de prévoir un mécanisme qui permette à l’utilisateur d’exprimer son choix et de s’assurer que ce choix prime alors sur la négociation linguistique HTTP. Le plus simple est d’afficher, bien en vue, sur toutes les pages équivalentes des hyperliens qui permettent de passer manuellement d’une version linguistique de la page à une autre. On appelle rémanence linguistique le fait que le serveur se souvienne du choix linguistique effectué par l’utilisateur. La meilleure mise en œuvre dépendra des techniques disponibles sur le serveur choisi et l’effort que l’on est prêt à consentir. Pour mémoire, citons ici les principales techniques utilisées : – le choix linguistique fait partie de la session ; – le serveur utilise des témoins (cookies) ; – le serveur indique la langue choisie dans les URL (ex. : ?lang=fr) ; – les utilisateurs doivent s’inscrire auprès du serveur et précisent dans leur profil leur langue ; – l’utilisation d’hyperliens relatifs, en utilisant la balise . Il est désormais permis d’avoir des adresses internationalisées du type . Tous les domaines de tête n’acceptent pas ces adresses. Ainsi, alors que des domaines comme « .de », « .jp » et « .com » prennent en charge les noms de domaine internationalisés (NDI), le domaine « .fr » ne le permet toujours pas. Si vous décidez d’utiliser un NDI qui contient des caractères d’une écriture « exotique » — ce qui est sans doute plus naturel et plus parlant pour vos clients — il est plus prudent d’également réserver une adresse composée uniquement de caractères ASCII pour ceux qui ne connaissent pas cette écriture ou qui ne sont pas capables de la saisir (dans un cybercafé à l’étranger par exemple). Les navigateurs modernes transformeront de manière transparente les adresses de domaine comme biscuits-salés en des adresses de domaine compatibles avec l’infrastructure actuelle prévue pour des adresses ASCII. L’utilisateur ne se rendra habituellement pas compte des transformations effectuées en coulisse par le protocole appelé punycode. Dans notre cas, celui-ci transforme biscuits-salés en xn-biscuits-sals-mhb). Pour le codage du chemin de la ressource sur le serveur (/Noël.html), le mieux est d’adopter le RFC 3987 qui préconise l’utilisation

10.7 La locale POSIX

237

d’UTF-8 comme codage des chemins avant leur transformation en notation %hh et leur transmission sur le réseau : Noël.html devient donc No%C3%ABl.html. La prise en charge des NDI peut singulièrement augmenter le risque de parodie ou d’hameçonnage (phishing) par l’entremise de caractères similaires à ceux auxquels s’attend l’utilisateur, mais dans un autre système d’écriture, à savoir, par exemple, utiliser un « o » cyrillique à la place d’un « o » latin ! La plupart des navigateurs et des agences d’enregistrement de noms de domaine ont mis au point des parades pour identifier ces adresses contrefaites : elles consistent le plus souvent à restreindre le répertoire des caractères permis dans un nom de domaine lors de son enregistrement (pour les DNS) et à ne pas permettre le mélange d’écritures dans une même partie du nom de domaine délimitée par des points (pour les DNS et les navigateurs). Quand un navigateur détecte une adresse suspecte, il affiche habituellement l’adresse du domaine dans sa forme punycode et alerte ainsi l’utilisateur d’une tentative de parodie.

11 Unicode et (X)HTML, XML, CSS

Objectif Si le chapitre précédent se concentrait sur les protocoles Internet, dans ce chapitre nous nous pencherons principalement sur deux formats de documents très communs : HTML et XML. Nous reviendrons d’abord brièvement sur un aspect commun aux protocoles Internet et à ces formats : l’indication du codage du document. En effet, la manière de préciser ce codage peut avoir des effets inattendus sur certains navigateurs Internet. Ensuite, nous passerons en revue comment préciser la langue dans un document ou un passage, comment indiquer la directionalité (et plus généralement comment maîtriser l’algorithme bidirectionnel) avant de passer en revue les caractères Unicode qui font double emploi avec le balisage HTML et XML. Enfin, nous conclurons ce chapitre par un problème commun : le codage des données des formulaires HTML.

11.1 PRÉCISER LE CODAGE EN (X)HTML Comme nous l’avons vu dans le chapitre précédent, préciser le codage d’un document HTML et XHTML dans l’entête HTTP n’est, en règle générale, pas une bonne idée, car le serveur n’est pas toujours au courant du codage des fichiers qu’il transmet. Il vaut mieux indiquer le codage des fichiers au sein de ceux-ci. Nous allons brièvement rappeler dans les paragraphes qui suivent comment préciser le codage à l’intérieur d’un document XHTML ou HTML.

240

11.1.1

Chapitre 11. Unicode et (X)HTML, XML, CSS

HTML La situation est relativement simple pour les fichiers HTML : on indique le codage à l’aide d’une balise de la façon suivante :



Si vos fichiers HTML sont produits par des scripts (PHP, ASP, servlet, JSP…), il est possible de vous assurer que la valeur de l’entête HTTP correspond à celle de la balise . Ces deux valeurs étant égales, l’envoi de l’entête HTTP ne soulève pas de difficultés.

11.1.2

XHTML – le prologue XML XHTML est la forme de HTML qui respecte la syntaxe XML. Mais elle fait bien plus : elle insiste sur la séparation entre la présentation du document et sa structure. Cette sépararation est de plus en plus cruciale alors qu’on assiste à l’éclosion de dispositifs de plus en plus nombreux et variés de lecture de pages (X)HTML : téléphones cellulaires, assistants personnels, livres électroniques, etc. Un autre avantage majeur d’XHTML : il permet d’y inclure d’autres types de document basés sur XML comme MathML ou SVG. XHTML respecte donc la syntaxe XML. C’est pourquoi on ajoute souvent un prologue XML au début du balisage, même si le serveur envoie le document XHTML en indiquant dans les entêtes HTTP qu’il s’agit d’un document HTML. Le prologue peut comprendre deux parties :

• Une déclaration XML optionnelle (elle commence par ) ;

• Une déclaration du type de document (elle commence par ). La déclaration de type de document est obligatoire pour les documents qui se conforment strictement à XHTML. Quant à la déclaration XML, si elle est bien en règle générale optionnelle, elle est fortement recommandée et devient obligatoire pour les documents qui ne sont codés ni en UTF-8 ni en UTF-16. La déclaration de type de document (DTD) est obligatoire, car elle permet aux navigateurs de savoir de quelle façon ils doivent interpréter le document HTML. Si la DTD n’est pas présente, ils ne pourront pas afficher de manière optimale le document.

11.1 Préciser le codage en (X)HTML

241

Voici à quoi ressemble le haut d’un fichier XHTML typique (la déclaration XML est en gras et en italique) :



...

Le code précédent fait référence à la DTD « transitionnelle » de XHTML 1.0, une forme qui admet, afin de faciliter sa transition vers la DTD « stricte », quelques éléments que l’on considère pourtant comme faisant partie de la couche de présentation, ce qu’on nomme aussi du « stylage » et qui, aujourd’hui, est habituellement précisé par des feuilles de style comme celles de CSS. Si dans XHTML 1.0, on peut choisir entre les DTD strict, transitional et frameset1, en XHTML 1.1, on ne peut mentionner qu’une seule DTD :

La plupart des navigateurs — comme Mozilla, Nescape, Opera et Internet Explorer 7 — affichent sans difficulté les pages XHTML munies de prologues XML. Il en va tout autrement avec Internet Explorer 6 qui commande encore une grande part de marché aujourd’hui. Dans ce cas-ci, la moindre ligne de texte qui apparaît avant le déclenche le mode appelé « caprices » ou « bizarreries » (quirks mode en anglais). Ce mode — qui peut habituellement aussi être déclenché dans tous les navigateurs en omettant le ou en mentionnant un incomplet — permet de signaler au navigateur qu’il doit passer dans un mode de compatibilité qui permet d’afficher des pages HTML plus ou moins fautives ou conçues pour d’anciens navigateurs plutôt que de se conformer de manière stricte aux standards du W3C. L’interprétation stricte s’appelle, pour sa part, le mode « standard ».

Mode « bizarreries » Passons en revue quelques différences entre le mode « standard » et le mode « bizarreries » à l’aide d’un même code XHTML/CSS reproduit ci-après dont on supprimera le pour en révéler l’aspect en mode « bizarreries ».

1. La DTD « transitional » permet l’utilisation de balises de présentation comme , , et qui seraient mieux mises en œuvre par une feuille de style alors que la DTD « strict » est destinée aux documents sans balises et attributs de présentation vestigiaux et où la présentation est précisée par une feuille de style CSS. Enfin, la DTD « frameset » est équivalente à la DTD « transitional » où la balise body est remplacée par la balise frameset.

242

Chapitre 11. Unicode et (X)HTML, XML, CSS



Document XHTML

Ce texte hérite le corps de sa police de , il est donc à 20 pt.

Ce texte est contenu dans un

contenu dans une et donc à 12 pt.



Texte dans une balise

et donc à 12 pt.

Texte dans une balise

et donc à 12 pt.

Aucune balise

, le corps de la police est hérité de (ou non).

Aucune balise

, le corps de la police est hérité de (ou non).



Ce code XHTML produit le résultat illustré par la figure 11.1. Si on élimine la déclaration du type de document (), on passe en mode « bizarreries » dont l’effet est illustré par la figure 11.2. Quelles sont les principales différences entre le mode « standard » et le mode « bizarreries » ? La plus importante est liée au fait qu’Internet Explorer — avant sa version 6 — ne calculait pas la largeur des boîtes CSS conformément à la méthode préconisée dans les spécifications CSS. En mode « standard », la valeur de l’attribut CSS width ne prend pas en compte les valeurs de padding et de border, contrairement au mode « bizarreries » — c’est pourquoi la grande boîte est plus étroite dans la figure 11.2. Depuis la version 6, Internet Explorer calcule désormais les largeurs de boîtes conformément aux spécifications CSS en mode « standard » et n’utilise plus son ancien algorithme non conforme qu’en mode « bizarreries ».

11.1 Préciser le codage en (X)HTML

Figure 11.1 – Affichage en mode « standard »

243

Figure 11.2 – Affichage en mode « bizarreries »

En outre, beaucoup de vieux navigateurs — comme MSIE 6 — n’avaient pas mis en œuvre l’héritage des styles de police au sein des tableaux. Il fallait donc préciser les styles de police pour l’ensemble du document et puis pour chaque tableau, bien que les spécifications CSS imposent que les attributs liés aux polices soient hérités partout. Le code XHTML et la feuille de style CSS utilisés ci-dessus attribuent une taille de 20 pt aux polices au niveau de la balise (et, par héritage, à tous les autres éléments) et une taille réduite de 12 pt pour les éléments

. En mode « bizarreries », la table n’hérite pas de la taille de police définie pour l’élément et le texte de ce tableau apparaît donc plus petit que le même texte en mode « standard ». Remarquez que le texte de la grande boîte qui précède le tableau a la même taille dans les deux modes, puisqu’il n’est pas inclus dans un élément

, mais dans un élément

. Pour plus d’information sur ce sujet, veuillez consulter le site : .

244

11.1.3

Chapitre 11. Unicode et (X)HTML, XML, CSS

Préciser le codage en CSS CSS permet de déclarer le codage adopté dans une feuille de styles à l’aide de la règle @charset. Sa syntaxe est la suivante : @charset "";

Il ne faut pas utiliser de @charset pour les feuilles de styles CSS incorporées dans des documents HTML ou XHTML. Une seule règle @charset peut figurer dans une feuille de styles externe, elle doit apparaître au tout début du document. Elle ne doit être précédée d’aucun caractère, pas même des commentaires. Le nom de codage doit être enregistré auprès de l’IANA1. Pour déclarer qu’un fichier CSS est codé en UTF-8, on écrira (à la casse près) : @charset "UTF-8";

Conseils Pour résumer, nous conseillons : – Dans le cas de documents HTML, d’indiquer le codage à l’aide d’une balise . – Dans le cas de documents XHTML servis comme des documents « xml »2, de les envoyer avec une déclaration XML qui indiquera le jeu de caractères () accompagné d’un . Le cas de documents XHTML servis comme des documents « text/html »3 est un peu plus délicat : – Si la déclaration XML ne cause pas de difficulté à l’affichage (cela dépend des navigateurs de vos clients), il vaut mieux l’inclure et dans ce cas-là de toujours mentionner le codage. – Si la déclaration XML risque de poser des problèmes (vos clients comprennent des navigateurs comme MSIE 6 qui passeront alors en mode « bizarreries »), omettez-la et transmettez le fichier en UTF-8 ou en UTF-16. Rappelons que la déclaration XML est optionnelle pour les documents XML pour autant que leur codage soit UTF-8 ou UTF-16. – Définissez le codage des feuilles de styles CSS externes à l’aide de la règle @charset.

1. Pour la liste des codages : . 2. C’est la solution préconisée quand le navigateur cible comprend le XHTML. XHTML peut inclure du SVG ou du MathML par exemple, ce qu’HTML ne peut faire. La version 1.1 d’XHTML prend en charge la notation Ruby. MSIE 7 ne comprend pas le XHTML servi de la sorte, Firefox 2 oui. 3. À utiliser avec des navigateurs comme MSIE 7 qui ne comprennent pas vraiment le XHTML : si le document est servi comme du « text/html », le navigateur l’affichera comme du HTML.

11.2 Préciser la langue

245

11.2 PRÉCISER LA LANGUE Nous l’avons déjà indiqué au chapitre 9, préciser la langue d’un document permet de mieux le traiter, qu’il s’agisse de l’affichage ou de traitements linguistiques comme la vérification orthographique ou la traduction. Nous allons brièvement voir comment préciser la langue d’un document ou d’une partie de document en HTML ou XML.

11.2.1

HTML et XML

On recommande d’ajouter, dans les documents HTML, un attribut lang à la balise html. On préfère le mettre sur la balise html plutôt que le body, car il existe au moins un autre passage de texte qui ne serait pas balisé en choisissant body : le titre (title). L’exemple suivant déclare un document écrit en français de Belgique :

En XML, et donc en XTHML, on utilisera l’attribut xml:lang pour préciser la langue :

Ces attributs peuvent s’utiliser sur la quasi-totalité des balises où il est raisonnable de préciser la langue. La valeur de ces attributs correspond à un codet défini par le BCP 47 (voir chapitre 9). Nous avons mentionné XHTML précédemment dans le cas de XML, mais il est également possible de mentionner l’attribut xml:lang dans d’autres langages balisés utilisant la syntaxe XML comme SVG, XSL, DocBook, NewsML ou SMIL. Lorsque vous servez un document XHTML 1.0 comme du « text/html », utilisez à la fois les attributs lang (seul attribut que le navigateur comprendra) et xml:lang (le plus utile sans doute quand vous éditerez le document). L’attribut lang n’est toutefois pas permis dans les documents XHTML 1.1.

11.2.2

Passages dans une autre langue

Après avoir déclaré la langue globale du document, il est facile de mentionner qu’un passage est dans une autre langue par l’adjonction d’un attribut lang, xml:lang ou les deux sur la balise qui comprend le texte dans la langue étrangère :

Triple-patte s’exclama alors :Timeo Danaos et dona ferentes.

...

246

Chapitre 11. Unicode et (X)HTML, XML, CSS

Si les passages dans une autre langue sont longs et comprennent de nombreuses balises, indiquez la langue en question le plus haut possible dans la hiérarchie des balises (par exemple à l’aide d’un span ou d’une div), il est alors inutile de préciser la langue sur chacune des balises-filles qui héritera la langue de cette balise mère.

11.2.3

Documents bilingues

Il existe un cas où il peut s’avérer utile de ne pas mentionner de langue sur la balise html : les documents bilingues comme l’extrait de document écrit en français et en néerlandais qui suit.



Waarborgregeling voor kleine en middelgrote ondernemingen — Garantie aux petites et moyennes entreprises

CHAPITRE Ier — Dispositions générales ...

Article 1er. Dans le présent arrêté on entend par Décret sur la Garantie : le décret du...



HOOFDSTUK I. — Algemene bepalingen

Artikel 1. In dit besluit wordt verstaan onder Waarborgdecreet : het decreet...





On aurait également pu déclarer une des deux langues comme la langue principale du document au niveau de la racine html et n’adjoindre explicitement l’attribut lang qu’à la div contenant le texte écrit dans l’autre langue. Dernière remarque : en HTML 4.01, il est impossible de préciser quelle partie du titre est en français et quelle autre partie est en néerlandais, puisque le seul contenu admis par title est une suite de caractères (pas de balises). Cette restriction devrait disparaître avec XHTML 2.0.

11.2 Préciser la langue

11.2.4

247

La langue dans l’entête HTTP ou l’attribut lang ?

On se rappellera — comme nous l’avons indiqué au chapitre précédent — qu’il est également possible de mentionner la langue dans l’entête HTTP qui accompagne le document que votre serveur envoie. On peut légitiment se demander s’il vaut donc mieux déclarer la langue du document dans l’entête HTTP Content-Language ou à l’aide de la balise , son pendant interne au document. Les trois cas potentiels en présence sont donc :

Ou

Ou encore HTTP/1.1 200 OK Date: Mon, 02 Sep Nov 2007 10:46:04 EST Content-Type: text/html; charset=iso-8859-1 Content-Language: fr, la …

On remarquera que l’entête HTTP et la balise permettent tous les deux de préciser plusieurs langues, ce que les attributs lang et xml:lang ne permettent pas de faire. Préciser ces langues de la sorte signifie que le document est bilingue et qu’il comprend autant de français que de latin (une édition bilingue des Catilinaires de Cicéron, un missel). Une première leçon de latin écrite à l’intention de francophones n’aura pas un Content-Language: fr, la, mais bien Content-Language: fr sans le « la », car la langue qui permet de comprendre le texte est le français. La balise et l’entête HTTP Content-Language identifient le type de lecteur humain qui pourrait être intéressé par la page en question. Le lectorat potentiel. On peut dire, grosso modo, que ce paramètre pourrait permettre au serveur de choisir une bonne version linguistique lors de la négociation linguistique (Accept-Language). En effet, le serveur HTTP effectue à la fois la négociation de langue (Accept-Language) et remplit le champ Content-Language du document renvoyé ; on peut supposer que le serveur le fera à partir des mêmes informations à sa disposition dans les deux sens, mais ceci est laissé aux concepteurs et n’est pas précisé dans les normes et standards. À nouveau, on préférera généralement la balise interne à l’entête HTTP Content-Language, puisque la balise interne accompagne le document alors que l’entête HTTP peut être perdu lors d’une sauvegarde locale et mal deviné par le serveur qui y affectera une valeur. Quant aux attributs lang et xml:lang, ils désignent la langue des différents passages et sont destinés aux processus de traitement linguistique de ces passages (y compris l’affichage des polices). Il est donc normal que ces attributs ne permettent la mention que d’une seule langue.

248

Chapitre 11. Unicode et (X)HTML, XML, CSS

11.3 PRÉCISER LA DIRECTIONALITÉ Dans un même ordre d’idées, il est essentiel de préciser la directionalité de tout document droite-à-gauche (arabe ou hébreu, par exemple) et il est préférable de le faire sur la balise html grâce à l’attribut dir auquel on affecte la valeur rtl :

Grâce à cette déclaration, tous les éléments de type bloc et les colonnes de tableaux commenceront à afficher leur texte à partir de la droite et l’écriront vers la gauche. Seuls les éléments de type bloc dont la directionalité aura été explicitement déclarée comme étant de gauche à droite (grâce à l’attribut dir="ltr") s’afficheront alors de gauche à droite. Il n’est pas nécessaire de préciser un attribut dir sur l’élément html quand la direction globale du document est gauche-à-droite. Certains navigateurs modifient le placement de la barre de défilement vertical et des options de la barre de menu (toute la symétrie de la fenêtre est inversée) quand la directionalité globale du document est droite-à-gauche (c’est-à-dire ). Certains utilisateurs trouvent cela déroutant. Pour éviter ce désagrément, on peut ajouter une balise juste après la balise et préciser la directionalité globale sur la balise . De la sorte, tous les éléments de type bloc du document hériteront de la directionalité précisée par cette balise sans modifier la directionalité globale du navigateur dont la fenêtre gardera son apparence « européenne » avec la barre de défilement à gauche et les options de la barre de menu qui s’écrivent de gauche à droite. Notons, enfin, qu’après avoir défini la directionalité globale du document, il ne faut plus utiliser d’attribut dir à moins de vouloir changer la directionalité d’un élément et de ses descendants. Nous reviendrons plus loin sur les difficultés liées à la production de pages bidirectionnelles (voir § 11.8, Réglage de l’algorithme bidi).

Éviter les valeurs « right » et « left » dans le balisage Afin de faciliter la traduction des pages HTML, il faut éviter, dans la mesure du possible, d’utiliser les valeurs « right » et « left » dans les attributs HTML. Il vaut mieux affecter ces valeurs à l’aide d’une feuille de style CSS séparée à laquelle vous ferez mention à l’aide d’un élément . Si l’on désire que les paragraphes soient justifiés au fer à gauche, on écrira : p {text-align: left;}

En XHTML 4.01, deux attributs peuvent prendre les valeurs « right » et « left », il s’agit d’align et de clear. Clear ne se rencontre que sur l’élément
, alors qu’align se retrouve sur de nombreux éléments comme , , , ,

,

, etc.

11.4 Stylage sensible à la langue

249

Les valeurs « right » et « left » devront être adaptées lorsque le document sera traduit dans une langue qui utilise une écriture bidirectionnelle. La chose est également possible quand le document est écrit dans une langue qui emploie les idéogrammes CJC. On simplifie et facilite singulièrement le processus d’adaptation culturelle en regroupant, dans une feuille de styles CSS séparée, ces attributs de justification et d’alignement. On modifiera cette feuille de style lors du processus de traduction.

11.4 STYLAGE SENSIBLE À LA LANGUE 11.4.1

Les sélecteurs CSS

Une règle CSS1 est composée d’un sélecteur et d’une série de déclarations de propriétés entourées d’accolades : Sélecteur

Bloc de déclarations Déclaration propriété

th

{

color

valeur : red;

Déclaration propriété

valeur

margin : 1em 12px; }

Le sélecteur CSS (en grisé dans l’exemple ci-dessous) détermine à quelles portions du document une règle s’appliquera. p { font-family : Courier, font-style : italic; font-weight : bold; } p em {color : blue; font-size : 16pt; } p > em {color : red; font-size :24pt; }

La première ligne signifie que les paragraphes

devraient être affichés en Courier italique gras, alors que la seconde précise que les éléments dont

est un ascendant quelconque devraient s’afficher en vert avec un corps de 16 pt. La troisième règle ne s’applique qu’aux éléments qui descendent directement d’un

, ils seront affichés en rouge et en un corps de 24 pt. Il existe un sélecteur universel; il permet de sélectionner indifféremment tous les éléments. On le note à l’aide d’un astérisque « * ». C’est ainsi que la règle * { ... } s’applique à tous les éléments du document. Tout élément, y compris l’élément universel, peut être suivi d’un prédicat, écrits entre crochets, qui vérifie la valeur des attributs liés à cet élément, et uniquement à cet élément (pas ses ancêtres). On nomme ce type de sélecteur les sélecteurs d’attribut.

1. Un bon ouvrage sur ces feuilles de styles : CSS : La référence par Eric Meyer, 2e édition, O’Reilly, Paris, 2005.

250

Chapitre 11. Unicode et (X)HTML, XML, CSS

th[attr="val"]

Sélectionne tout élément

, ,
dont l’attribut attr vaut exactement val, [alt="Image"] ne sélectionnera donc pas . Il existe une autre manière de tester les attributs qui peut se révéler intéressante dans le contexte de l’internationalisation : p[attr|="val"]

Sélectionne tout élément

dont l’attribut correspond à une liste de valeurs séparées par un trait d’union et dont le premier élément vaut val. C’est ainsi que div[lang|= "fr"] s’appliquera à , mais pas à . CSS connaît un dernier type de sélecteur d’intérêt : la pseudoclasse. La pseudoclasse est un sélecteur spécial qui définit une condition difficilement exprimable par les sélecteurs standard ou qui n’est pas liée à la structure du document. Une pseudoclasse nous intéresse particulièrement, il s’agit de :lang(l). Exemples : * :lang(fr) { font-weight :bold; } div :lang(en) { background : red; }

La pseudoclasse :lang(l) est proche du sélecteur d’attribut [lang|=l], mais elle s’en distingue par le fait que l’élément mentionné dans le sélecteur (div dans l’exemple précédent) ne doit pas nécessairement avoir un attribut lang, à la différence des sélecteurs d’attribut, il suffit que la langue courante soit celle mentionnée entre les parenthèses de lang(). La langue courante peut avoir été définie sur un ancêtre de l’élément en question, précisé sur la balise ou même dans l’entête HTTP.

11.4.2

Utilisation des sélecteurs de langue

Le stylage lié à la langue permet de régler avec précision la présentation d’une page ou d’un passage dans cette page selon la langue en question. On peut de la sorte choisir une police particulière pour des caractères qui s’utilisent dans plusieurs langues à la tradition typographique différente. Pour fixer les idées, considérons ces cinq règles CSS : *:lang(el) {font-family : "SBL Greek", serif} *:lang(fr) {font-family : "Fournier MT ", serif} *:lang(zh-tw) {font-family: "Li Sung", serif} *:lang(zh-Hans) {font-family: SimSum-18030,SimHei, serif;} *:lang(ja) {font-family : "MS Mincho", serif}

La première règle indique que les éléments dont la langue est le grec doivent utiliser la police SBL Greek ou à défaut la police à empattements générique. Cette police permet d’afficher les caractères grecs (anciens et modernes) ainsi qu’un grand nombre de caractères latins de manière harmonieuse.

11.5 Schémas XML internationalisés

251

Ensuite, on associe aux textes français une police typiquement française produite par Monotype et imitée de la police « Saint Augustin ordinaire » conçue par Pierre Simon Fournier vers 1742. La règle :lang(fr) sélectionnera les éléments dont la langue est « fr », mais également ceux qui auraient été identifiés de manière plus précise comme « fr-CA » ou « fr-be » (la casse est sans importance). Les deux règles suivantes portent sur le chinois. La première (« zh-tw ») associera aux textes en chinois de Taïwan une police chinoise traditionnelle. La seconde (« zh-Hans ») associe des polices chinoises simplifiées aux éléments dont la langue est égale à « zh-hans », à la casse près. Aucune de ces deux règles n’attribue un style particulier aux éléments dont la langue n’est précisée que sous la forme de « zh ». La dernière règle associe une police typiquement japonaise aux textes identifiés comme étant du japonais. Cette technique permet, en quelque sorte, de contrer les effets de l’unification CJC en choisissant une police idéographique typique à la tradition typographique qui correspond aux textes affichés. La pseudoclasse lang n’est pas encore prise en compte par tous les navigateurs, il est possible de vérifier si les navigateurs qui vous intéressent la prennent en charge grâce à cette page de tests : .

11.5 SCHÉMAS XML INTERNATIONALISÉS 11.5.1

Texte dans les attributs XML

Lors de l’élaboration d’une DTD ou d’un schéma XML on évitera de créer des attributs qui pourraient comprendre du texte traduisible. On leur préférera des éléments. En effet, il n’existe pas de moyen de préciser la langue du texte des attributs (on ne peut affecter des attributs XML aux attributs XML). On ne peut pas plus indiquer la directionalité des attributs ce qui pourrait poser des problèmes d’affichage pour des textes bidirectionnels. Évitez de décrire une DTD ou un schéma qui définit une image de la sorte : // MAUVAIS

Définissez-le plutôt pour qu’une image soit définie ainsi : vue du Rocher percé en Gaspésie // BON vue du Rocher percé en Gaspésie // BON

Il n’aura pas échappé au lecteur averti que la syntaxe d’HTML (ainsi que celle d’XHTML 1.0 et 1.1) ne respecte pas ce principe. Écart corrigé dans la préversion d’XHTML 2.0.

252

Chapitre 11. Unicode et (X)HTML, XML, CSS

11.5.2

Les éléments qui ne contiennent qu’une chaîne

Dans le même ordre d’idées, il faut faire attention aux éléments du schéma1 que vous pourriez déclarer comme ne pouvant contenir qu’une chaîne.



En effet, il se pourrait que cet élément soit appelé à contenir du balisage (on parle alors en jargon XML d’un type complexe au contenu mixte2) dans certaines langues comme les langues droite-à-gauche pour maîtriser l’affichage ou les langues idéographiques et permettre l’inclusion de la notation Ruby3. En réalité, le problème se pose même dans les textes latins si l’élément peut contenir des lettres en indice, en exposant ou des fractions arbitraires. HTML donne un mauvais exemple ici en ne permettant que du texte dans l’élément qui n’admet qu’une chaîne de caractères sans sous-éléments.

11.5.3

Prévoir l’attribut xml:lang

Votre schéma devrait utiliser l’attribut xml:lang. Ce n’est pas la peine de créer votre propre attribut lang. Cet attribut xml:lang devrait être prévu sur la quasi-totalité des éléments : la racine du document, les grandes divisions, les différents blocs et les éléments en ligne.

11.5.4

Prévoir un élément de type span

Afin de pouvoir orner toute suite arbitraire de caractères d’attributs comme xml:lang ou dir, votre schéma XML devrait définir un élément analogue au span de HTML.

11.5.5

Ne pas créer d’éléments de présentation

Se rappeler que votre schéma XML doit refléter la structure, la sémantique de vos documents et ne devrait pas contenir d’éléments de présentation (contrairement à HTML par exemple avec ses , et ). Plutôt qu’un définissez un ou un (comme en HTML). Pourquoi ? Parce que la manière de faire ressortir un texte dépend des écritures et qu’imposer un système comme un supplément de graisse va à l’encontre des principes d’internationalisation. Les idéogrammes de petit corps, par exemple, sont illisibles en gras. C’est ainsi que ੰ donne ੰ en gras 8 pt. À la place du gras, les écritures idéographiques utilisent

1. Un bon ouvrage sur les schémas : XML Schéma d’Éric van der Vlist, O’Reilly, Paris, 2002. 2. Dont la définition commence alors par . 3. Pour la notation Ruby, voir § 8.3.1, Délimiteurs d’annotation interlinéaire.

11.6 Notation des caractères

253

souvent un point suscrit1, appelé   wakiten en japonais, sur chaque caractère pour marquer l’accentuation : ᣣ ᧄ     ⺆ . Le tibétain pour sa part utilise un U+0F35 ༵ signe tibétain mise en exergue honorifique ou U+0F37 ༷ signe tibétain mise en exergue pour souligner une « syllabe ». Une fois l’élément sémantique défini, il vous serait alors possible de modifier la présentation de celui-ci grâce à une règle CSS 3.0 de ce type : em:lang(ja) { font-emphasize: dot before; font-style: normal; }

Ce qui peut se lire comme suit : pour chaque balise , quand la langue courante est le japonais, utiliser un point suscrit et éliminer l’italique ou le gras. Nous avons écrit « serait possible » au conditionnel, car à ce stade CSS 3.0 n’est pas une recommandation officielle du W3C et font-emphasize n’est pris en charge par aucun grand navigateur.

11.5.6

Prévoir xml:id sur tous les éléments traduisibles

Associer un identifiant unique à un élément facilite grandement la vie des logiciels de traduction. En effet, si une chaîne traduite conserve le même xml:id, il est alors facile pour un outil de traduction ou de localisation de retrouver les différentes traductions d’une chaîne donnée. Cette technique est plus précise et plus rapide que les correspondances que font habituellement les mémoires de traduction. Exemple dans trois fichiers différents (l’id doit être unique au sein d’un même document) :

Un haut rocher brille.

Cacumen montis lucescit.

Der Gipfel des Berges funkelt.



Alternativement, une base de données de traductions XML pourra contenir les trois versions dans un seul élément :

Un haut rocher brille. Cacumen montis lucescit. Der Gipfel des Berges funkelt.



11.6 NOTATION DES CARACTÈRES On se rappellera qu’il existe plusieurs manières de désigner ou de saisir des caractères Unicode. Le liste suivante offre un bref récapitulatif de ces différentes méthodes dans le monde du HTML, du XML et des CSS :

1. En Chine continentale, le point d’accentuation est plutôt souscrit : ᣣ  ᧄ  ⺆ .

254

Chapitre 11. Unicode et (X)HTML, XML, CSS

• œ — Il s’agit d’un appel, écrit sous forme hexadécimale, au caractère U+0153 digramme soudé minuscule latin oe. Ce mécanisme est disponible en HTML et en XML pour désigner le « œ » quel que soit le codage du document ! En effet, il s’agit toujours du caractère Unicode U+0153 même si le document est codé dans un jeu de caractères autre qu’Unicode. Tous les documents HTML et XML peuvent ainsi faire référence à tous les caractères Unicode. Techniquement, on dira que le jeu de caractères de référence du document est toujours Unicode et que celui-ci est complètement indépendant du codage du document (par exemple Latin-1, cp1252, KOI8-R ou ShiftJIS). En utilisant un appel de caractère, vous garantissez la conservation et le transfert correct de ce caractère Unicode peu importe le codage de votre fichier. Enfin, pour peu que l’ASCII soit bien conservé et transféré.

• œ — Appel au même caractère que ci-dessus, mais sous sa forme décimale.

• 𐌗 — Représente la lettre falisque U+10317 ¢ lettre italique iks quel que soit le codage. Ceci est également vrai de l’UTF-16 même si, puisque ce caractère est affecté au plan multilingue complémentaire, on pouvait penser devoir y faire appel grâce à deux seizets d’indirection. C’est, en effet, une erreur que de vouloir accéder à cette lettre falisque à l’aide de deux appels de caractères du type : &x#D800; � même si le codage du document est UTF-16. Pourquoi ? Parce que les seizets d’indirection ne sont pas des numéros de caractères (positions de code) Unicode valables, il s’agit plutôt d’unités de stockage.

• œ — Il s’agit d’un appel d’entité. Il s’agit, grosso modo, du nom d’une macro à laquelle on associe un appel de caractère à l’aide d’une déclaration SGML de ce type : . Cette déclaration associe au nom « oelig » la valeur « œ ». Contrairement à ce que l’on pourrait penser, ces appels d’entité sont moins portables que les appels de caractère, car il faut qu’ils soient définis de la même façon par des « macros » dans le langage XML/HTML que vous utilisiez. Or, si HTML définit de nombreuses entités, XML en définit très peu par défaut1. L’entité « oelig » n’est, par exemple, pas définie par défaut dans XML. L’entité « œ » peut s’avérer utile à la saisie de documents HTML pour les utilisateurs qui ne trouvent pas le caractère « œ » sur une des touches de leur clavier (il est habituellement absent des claviers francophones).

• é — À nouveau un appel d’entité, cette fois il correspond à « é ». Dans la plupart des cas, l’utilisation de cet appel est tout à fait superflue pour les Européens puisqu’il est facile de saisir le caractère « é » sur un clavier et qu’il est présent dans la quasi-totalité des codages. Il en va sans doute autrement de 中 (ਛ) que vous ne pourrez probablement pas saisir facilement et qui est peut-être inconnu du codage (par exemple le Latin-1) dans lequel vous sauvegarderez le document. En utilisant un appel de caractère ici, vous 1. XML définit en tout et pour tout cinq entités : , &, ' et "

11.6 Notation des caractères

255

garantissez la conservation de ce caractère même si vous conservez votre document sur une machine européenne dont le codage « naturel » sur 8 bits ne comprend pas le caractère ਛ.

• \201C — Il s’agit de la suite d’échappement utilisée dans CSS pour désigner l’apostrophe de fantaisie anglaise « “ », elle peut s’avérer utile si vous ne parvenez pas à saisir cette apostrophe telle quelle. La suite d’échappement se termine par un espace (qui est « avalé »). Son emploi est plutôt rare, mais elle peut servir quand on désire, par exemple, modifier les guillemets à utiliser autour d’une citation :

...

Jonah wrote He said unto them: Take me up, and cast me forth into the sea.

Don diègue lança : Va, cours, vole, et nous venge.



Les deux règles CSS précédentes utilisent un sélecteur sensible à la langue pour modifier la propriété quotes associée aux caractères ouvrant et fermant des citations. Chaque paire de valeurs représente les suites de caractères ouvrants et fermants d’un niveau de citation. On remarquera que, dans le cas français, on a utilisé les guillemets chevrons et ajouter l’espace insécable ce qui évite de laborieusement ajouter à la main l’espace insécable qui accompagne chaque guillemet et d’en oublier. Le fragment de code précédent produit le résultat suivant : Jonah wrote “He said unto them: ‘Take me up, and cast me forth into the sea’.” Don Diègue lança : « Va, cours, vole, et nous venge. »

11.6.1

Appels d’entités HTML : souvent de peu d’utilité

La majeure partie des entités définies par HTML2 sont de peu d’utilité. En effet, la plupart des éditeurs HTML modernes sont aujourd’hui des outils qui permettent la saisie de données Unicode : vous n’avez donc qu’à saisir vos données directement en Unicode sans recours à l’artifice des entités, même dans le texte source HTML. C’est nettement plus commode que l’utilisation d’entités qui conjuguent trois défauts : elles rendent le texte peu lisible, il n’en existe qu’une liste restreinte et leur nom est souvent peu parlant. Qui sait, en effet, que ∩ représente U+2229 ∩ intersection ou que ∋ correspond à U+220B Ь contient comme élément ? Autre désavantage : les entités définies par HTML ne sont pas connues de XML.

1. On aurait pu tout aussi bien écrire : q:lang(fr) { quotes:'\AB\A0' '\A0\BB' '\201C' '\201D'} avec \AB et \BB à la place de '«' et '»'. 2. Voir la liste définie ici : < http://www.w3.org/TR/xhtml1/dtds.html#h-A2>.

256

Chapitre 11. Unicode et (X)HTML, XML, CSS

11.6.2

Appels de caractère : à n’utiliser que rarement

L’utilisation d’appels de caractère numériques rend la lecture et la modification d’un texte plus difficiles. Voyez ce texte en français et en grec : Josèphe est le témoin oculaire de la guerre des Juifs contre les Romains — « Ἐπειδὴ τὸν Ἰουδαίων πρὸς Ῥωμαίους πόλεμον συστάντα μέγιστον οὐ μόνον τῶν καθʼ ἡμᾶς, σχεδὸν δὲ καὶ ὧν ἀκοῇ... » Et le début du même texte où chaque caractère non ASCII est stocké sous la forme d’un appel de caractère numérique : Josèphe est le témoin oculaire de la guerre des Juifs contre les Romains : « Ἐπε ιδὴ τὸν Ἰ ουδαίων πρὸς Ῥω μαίους π όλ εμον σ υστάντα μέγιστο ν οὐ μόνο ν τῶν καθ ’ ἡμᾶς, σχ εδὸν δὲ κ αὶ ὧν ἀκο ῇ…  » Non seulement le texte est illisible, mais la taille du fichier qui le contient augmente très rapidement. Les appels de caractère numériques peuvent se justifier si le codage du fichier qui les contient ne permet pas de stocker ces caractères, pour le grec, un fichier Latin-1 par exemple :



Toutefois, si votre fichier contient de très nombreux caractères qui ne sont pas pris en charge par le codage de votre fichier, il vaut mieux changer de codage et en choisir un qui prend en charge directement ces caractères sous leur forme normale (passer en UTF-8 par exemple). Si le fichier est codé en UTF-8, on peut alors écrire le texte français et grec comme il apparaît au début de cette section, sans aucun appel de caractère numérique.

11.6.3

Quand les appels de caractère et d’entité sont utiles

XML ne prédéfinit que cinq appels d’entités de caractère. Aucun de ces appels n’est jamais nécessaire : on peut toujours utiliser des appels numériques (ACN), mais il est vrai que les entités peuvent être plus mnémotechniques pour ceux qui connaissent l’anglais. Certaines entités (ou les ACN correspondants) sont obligatoires dès que l’on veut par exemple mentionner un caractère qui sert de délimiteur de balise (« < »), d’appel (« & ») ou d’attribut (comme « « »). Le tableau 11.1 les énumère.

11.6 Notation des caractères

257

Tableau 11.1 – Appels d’entité définis en XML Appel d’entité

Glyphe




supérieur à

Cet appel d’entité n’est pas en général utile, on l’a inclus surtout pour faire pendant à » plutôt que d’indiquer la fin d’une section CDATA.

&

&

perluète

Le « & » marque le début d’un appel, on utilisera donc & pour la simple perluète sans signification particulière syntaxique.

'

'

apostrophe

Permet d’inclure une apostrophe dans une valeur d’attribut délimitée par des apostrophes.

"

"

guillemet anglais

Permet d’inclure un guillemet anglais dans une valeur d’attribut délimitée par des guillemets anglais.

Rappelons que les caractères à remplacer par des appels d’entité ou de caractère — parce qu’ils ne jouent pas le rôle de délimiteurs mais celui de caractères à inclure tels quels — dépendent du contexte. C’est ainsi que, dans une valeur d’attribut délimitée par des « « », seuls les caractères « « », « < » et « & » sont interdits. De même, dans une valeur d’attribut délimitée par des « ‘ », seuls les caractères « ‘ », « < » et « & » sont interdits. Enfin dans les éléments, seuls les caractères « < » et « & » ainsi que la suite « ]]> » (fin de section CDATA) sont interdits. Pour ce qui est des appels de caractère numériques (&#xhhhh;), ils sont utiles, comme nous l’avons vu, quand on fait une (rare) référence à un caractère Unicode (le hhhh est toujours la valeur hexadécimale ISO 10646/Unicode du caractère) qui n’appartient pas au codage du fichier (quand ces références deviennent nombreuses, il faut envisager de changer le codage du fichier) ou quand ce caractère n’est pas facile à saisir. Il existe d’autres circonstances où les appels de caractère sont en fait recommandés : quand ils représentent des caractères invisibles ou ambigus comme U+00A0 espace insécable, dont l’insertion devant certains signes de ponctuation français est obligatoire ou U+200F marque droite-à-gauche qui permet de clarifier la directionalité d’un texte bidirectionnel comme l’arabe ou l’hébreu. Ces caractères Unicode n’ont pas d’œil et échappent donc facilement au regard de l’auteur d’un texte (on ne distingue l’espace insécable de l’espace normal que par leur comportement respectif en fin de ligne). Utiliser respectivement   (ou   en HTML) et &x200F; (ou ‏ en HTML) permet de repérer facilement ces signes. Contrairement à ce que d’aucuns croient, les appels de caractère et les appels d’entité peuvent s’utiliser dans les attributs. Ceci signifie que l’esperluette, lorsqu’elle ne sert pas à introduire un appel d’entité ou de caractère doit être représentée à l’aide de « & » dans les valeurs d’attribut. Ainsi, si vous désirez pointer vers une

258

Chapitre 11. Unicode et (X)HTML, XML, CSS

page comme celle-ci : http://écolelibre.com/search?q=esquimaux&hl=fr à l’intérieur d’un document HTML, vous devriez écrire :

Un valideur HTML comme celui du W3 Québec () rejettera un hyperlien qui contiendrait /search?q=esquimaux&hl=fr puisqu’il contient apparemment un appel d’entité incorrect (l’appel qui commence par le « & » ne se termine pas par un « ; ») et que, bien sûr, il ne correspond à aucune entité définie. Toutefois, la plupart du temps, les navigateurs gommeront silencieusement l’erreur, récupéreront et interpréteront le « & » isolé comme s’il s’agissait d’un « & ».

11.6.4

Entités en XHTML

Nous savons qu’HTML a défini un grand nombre d’entités et qu’XML n’en a défini que cinq, mais qu’en est-il d’XHTML ? Un document XHTML 1.0 conforme doit faire référence à une des trois DTD précisées dans la spécification du W3C (strict, transitional, frameset). XHTML 1.1 n’accepte plus qu’une DTD stricte. Or ces DTD font appel aux mêmes jeux d’entités que HTML, à peu de choses près. La spécification d’XHTML 1.0 déclare : « Les ensembles d’entité XHTML sont les mêmes que pour HTML 4, mais ont été modifiés pour s’assurer qu’elles soient des déclarations d’entités XML 1.0 valides. » Notons que l’entité ' n’est pas définie en HTML, elle est donc à éviter dans les documents XHTML qu’on veut garder compatibles avec les navigateurs HTML. Les ACN ' ou ' font parfaitement l’affaire. Pour d’autres règles de compatibilité XHTML/XML, voir .

11.7 CARACTÈRE OU BALISAGE ? 11.7.1

Unicode contient trop de caractères Unicode a été conçu pour permettre l’affichage univoque de toutes les écritures du monde en une séquence linéaire de caractères, appelée communément texte brut. Un caractère suit un autre caractère, sans structure particulière. En revanche, le balisage définit une structure hiérarchique pour le texte ou les données. Dans le cas de XML, il définit une structure en arbre. Les opérations faciles à réaliser sur les arbres sont souvent difficiles à réaliser sur les séquences linéaires et inversement. En particulier, les opérations qui impliquent plusieurs caractères à la fois se font aisément à l’aide du balisage. C’est le cas, par exemple, de l’étiquetage linguistique d’un passage, de la notation Ruby (pour, entre autres, indiquer au-dessus de certains mots leur prononciation, voir § 8.3.1, Délimiteurs d’annotation interlinéaire) ou de l’indication de la directionalité d’un texte. Effectuer

11.7 Caractère ou balisage ?

259

les mêmes opérations sur des suites de caractères linéaires, à l’aide de caractères de commande, demande beaucoup plus d’effort et constitue une source d’erreurs — plus particulièrement lors d’un copier-coller. En outre, le balisage offre un autre avantage par rapport aux caractères de commande : on peut facilement l’étendre, y ajouter de nouveaux attributs, ce qui est difficilement concevable pour des caractères Unicode. Pour éviter toute ambiguïté, le W3C et Unicode ont établi des lignes directrices pour établir quels caractères sont permis dans un texte balisé et quand il est préférable d’utiliser du balisage à la place de caractères Unicode.

11.7.2

Caractères de commande en HTML et XHTML

Les standards HTML 4.01 et XHTML 1.0 imposent certaines restrictions quant aux caractères de commande qui peuvent apparaître dans un document HTML 4.01 ou XHTML 1.0. Les caractères de commande sont le plus souvent inutiles en HTML, et quand ils auraient pu servir, nous verrons par la suite que les standards (X)HTML préconisent plutôt l’emploi du balisage. Les restrictions imposées par XHTML sont héritées de XML 1.0. Dans l’esprit des concepteurs de XML 1.0, les caractères de commandes, sauf les passages à la ligne et la tabulation, n’avaient pas leur place dans un texte balisé. Toutefois XML 1.0 permet l’utilisation de caractères de commande C1. Lors de l’élaboration de XML 1.1, de nombreuses personnes ont fait valoir qu’elles voulaient pouvoir stocker en XML tous les caractères tels quels sans avoir à chipoter pour en exclure les commandes C0 ou C1. C’est pourquoi, XML 1.1 permet l’utilisation des caractères C0 par appel de caractère ( à ). Toutefois, pour des raisons de robustesse afin, par exemple, de ne pas affecter la détection de codages erronés, les caractères C0 interdits en XML 1.0 ne peuvent toujours pas être utilisés directement dans les documents XML 1.1. Dans le même ordre d’idées, afin d’améliorer la détection des erreurs de codages de caractères, les caractères de commande C1, qui pouvaient être insérés tels quels en XML 1.0, ne peuvent plus apparaître en XML 1.1 que sous la forme d’ACN ( à Ÿ). La seule exception est … qui représente du blanc (un retour à la ligne dans EBCDIC). Ce caractère peut être inclus directement dans les documents XML 1.1 sans recours à un ACN, car depuis XML 1.1 il fait partie des caractères de fin de ligne. Ceci signifie que de tous les caractères de commande interdits par XML 1.0, il ne reste plus que le caractère U+0000, pour éviter les difficultés qui pourraient survenir avec les applications qui traitent ce caractère comme un terminateur de chaîne de caractères.

260

Chapitre 11. Unicode et (X)HTML, XML, CSS

Tableau 11.2 – Caractères de commande interdits dans XML et HTML Caractères

Sens

HTML 4.01

XHTML 1.0

XML 1.0

XML 1.1

U+0000

Nul

Interdit

U+0001.. U+0008

Partie des commandes C0

U+0009

Tabulation

U+000A

Passage à la ligne

U+000B

Tabulation verticale

Interdit

ACN

U+000C

Saut de page

Interdit

ACN

U+000D

Retour de chariot

U+000E.. U+007E

Partie des commandes C0

U+007F

Suppression

Interdit

Permis

ACN

U+0080.. U+0084

Partie des commandes C1

Interdits

Permis

ACN

U+0085

À la ligne

Interdit

Permis1

Permis

U+0086.. U+009F

Partie des commandes C1

Interdits

Permis

ACN

Interdits

ACN

Permis

Permis Interdits

ACN

Certains auteurs de pages HTML pourraient être tentés de coder l’euro sous la forme d’un € puisque c’est le numéro de caractère dans le codage Windows Latin-1 (Windows 1252). Stricto sensu, ce € est interdit en HTML 4.01 (car c’est en fait un caractère de commande Unicode), bien que de nombreux navigateurs interpréteront ce caractère comme un caractère Windows 1252 et afficheront donc un « € ». Pour insérer le symbole euro de manière conforme et sûre, il faut soit saisir directement € (si vous avez un clavier qui le permet par exemple) ou faire appel au caractère Unicode équivalent grâce à l’appel de caractère numérique € ou, en HTML, à l’aide de l’appel d’entité €.

11.7.3

Autres caractères permis et interdits en XML

Nous avons vu ci-dessus comment les versions XML 1.0 (et donc XHTML) et XML 1.1 classifient les caractères de commande. Ces deux versions XML déconseillent ou interdisent également l’utilisation d’autres caractères. Les caractères déconseillés

1. U+0085 est permis en XML 1.0 au même titre que tous les autres C1. Il n’est pas interprété en XML 1.0 comme une fin de ligne contrairement à XML 1.1.

11.7 Caractère ou balisage ?

261

sont, stricto sensu, permis mais il est vivement conseillé de s’abstenir de les utiliser. Les caractères suivants sont déconseillés par XML :

• Les caractères de compatibilité définis par le standard Unicode (ils ne sont pas repris dans le tableau 11.3).

• Les caractères qui sont désignés comme « déconseillés » dans la troisième colonne du tableau 11.3. Tableau 11.3 – Caractères interdits, déconseillés et permis dans XML Points de code

Sens

Qualité dans XML

U+00A0..U+D7FF

Caractères du PMB

Valables

U+D800..U+DFFF

Seizets d’indirection

Interdits

U+E000..U+FDCF

Caractères du PMB

Valables

U+FDD0..U+FDEF

Non-caractères

Déconseillés

U+FDF0..U+FFFD

Caractères du PMB

Valables

U+FFFE..U+FFFF

Non-caractères

Interdits

U+xFFFE..U+xFFFF

Non-caractères (où x va de 116 à F16).

Déconseillés

U+10000..U+10FFFF

Caractères des plans complémentaires

Valables sauf les noncaractères mentionnés ci-dessus.

11.7.4

Caractères incompatibles avec le balisage

Un nombre croissant de documents est échangé sous la forme de textes balisés comme HTML ou XML. Il arrive souvent que le balisage de ces langages permette d’exprimer des fonctionnalités similaires à celles que possèdent des caractères Unicode dans un texte brut. Il suffit de penser, par exemple, à U+000A passage à la ligne et
en XHTML. Les raisons pour lesquelles on décourage l’utilisation de plusieurs caractères Unicode dans un contexte balisé comme XML/XHTML peuvent être nombreuses :

• Ces caractères sont déconseillés par Unicode. • Ils sont difficiles à mettre en œuvre parce que, par exemple, ils nécessitent la tenue à jour d’une pile ou d’une variable à états.

• On les gère mieux au niveau du balisage parce que celui-ci permet plus d’options. • Ils rentrent en conflit avec le balisage équivalent. Le tableau 11.4 énumère les caractères Unicode qu’il ne faut pas utiliser dans un contexte balisé, ils doivent être remplacés par du balisage.

262

Chapitre 11. Unicode et (X)HTML, XML, CSS

Tableau 11.4 – Caractères incompatibles avec le balisage Numéro de caractère

Description

Commentaire

U+0340, U+0341

Clones de l’accent grave et de l’accent aigu.

Déconseillés par Unicode.

U+17A3, U+17D3

Caractères khmers erronés.

Déconseillés par Unicode.

U+2028, U+2029

Séparateurs de lignes et de paragraphes.

Utiliser , …, ou un équivalent.

U+202A...U+202E

Commandes d’incorporation bidi (LRE, RLE, LRO, RLO, PDF).

Fortement découragés dans HTML 4.01. Nous reviendrons ci-dessous sur la façon de les remplacer en HTML. Voir § 11.8, Réglage de l’algorithme bidi.

U+206A, U+206B

Actionne/inhibe l’échange symétrique bidi.

Déconseillé par le standard Unicode.

U+206C, U+206D

Actionne/inhibe le façonnage Déconseillé par le standard Unicode. de l’arabe.

U+206E, U+206F

Actionne/inhibe les formes numérales nationales

Déconseillé par le standard Unicode.

U+FFF9...U+FFFB

Caractères d’annotation interlinéaire.

Utiliser le balisage Ruby (voir § 8.3.1, Délimiteurs d’annotation interlinéaire).

En tant qu’espace insécable sans chasse.

Utiliser U+2060 gluon de mots.

U+FEFF En tant qu’indicateur d’ordre À n’utiliser qu’au début d’un fichier. des octets. U+FFFC

caractère de remplacement d'objet.

Utiliser du balisage, par exemple les éléments ou de HTML.

U+1D173...U+1D17A

Liaisons dans la notation musicale (coulés, phrasés, etc.).

Utiliser un langage de balisage musical adéquat.

U+E0000...U+E007F

Codets des étiquettes linguistiques.

Utiliser xhtml:lang ou xml:lang.

Si on exclut les séparateurs de lignes et de paragraphes et l’indicateur d’ordre des octets, les navigateurs et autres agents utilisateur peuvent ignorer la présence de caractères incompatibles avec le balisage dans HTML ou XML. Pour plus de détails, voir 1.

1. Il en existe une version française qui date un peu ici : .

11.8 Réglage de l’algorithme bidi

11.7.5

263

Caractères de compatibilité Unicode

Unicode comprend un grand nombre de caractères de compatibilité. Il fournit également des correspondances entre ces caractères de compatibilité et d’autres caractères. Toutefois, la nature exacte de cette correspondance varie. Parfois, la correspondance signifie « s’inspire de », d’autres fois, elle indique une propriété. Il peut être judicieux de remplacer ces caractères de compatibilité par le caractère équivalent « classique » et du balisage. Il ne faut pas effectuer ce passage sans bien comprendre la nature des caractères en jeu. Le tableau 11.5 fournit un aperçu des divers types de caractères de compatibilité et précise s’ils devraient plutôt être remplacés par du balisage ou non. Tableau 11.5 – Caractères de compatibilité Unicode dans XML Description Lettres et nombres cerclés

Exemples

ķ ĸ ծ կࢺ࣢༼

Verdict À conserver.

Lettres et nombres entre parenthèses ou à point

Հ Ց Ւ Ԭԭ՝՞

Utiliser un style d’élément de liste.

Formes de présentation arabes

‫ﻉﻊﻋﮓﭗ‬

Normaliser à la forme non contextualisée1. Voir § 4.3, Formes normalisées.

Fractions

Caractères de demie et pleine chasse Caractères en exposant (suscrit ou en chef) Caractères en indice (souscrit).

ΘΛ

㨰 㨱 㩚 㧣㨍 㨎 㨏 ¹²³ ʰʴ ₁₂₃ᵦₑₒₓₔ

Normaliser pour autant que la U+2044 barre de fraction soit prise en charge à l’affichage (présente dans la police du navigateur). Conserver. Utiliser le balisage . Utiliser la balise .

11.8 RÉGLAGE DE L’ALGORITHME BIDI Nous avons vu plus tôt que certaines commandes d’incorporation bidirectionnelle (LRE, RLE, LRO, RLO, PDF) étaient déconseillées dans les textes balisés. Dans cette section, nous allons voir comment les remplacer et comment régler l’algorithme bidirectionnel dans les situations les plus délicates. 1. La contextualisation de l’arabe modifie l’apparence des lettres arabes selon leur position dans un mot. Une même lettre peut prendre jusqu’à 4 aspects, dites formes de présentation. La lettre arabe ghaïn U+063A s’écrit ‫ غ‬dans sa forme isolée (canonique), ‫ ﻏ‬dans sa forme initiale (en règle générale en début de mot), ‫ ﻐ‬dans sa forme médiale et dans sa forme finale ‫( ﻎ‬généralement en fin de mot).

264

Chapitre 11. Unicode et (X)HTML, XML, CSS

Les textes bidirectionnels sont courants dans les écritures droite-à-gauche comme l’arabe, l’hébraïque, le syriaque, le n’ko et le thâna. De nombreuses langues s’écrivent à l’aide de ces écritures. On croit souvent qu’on peut déterminer la directionalité (le sens) dans lequel s’écrit un texte d’après sa langue. En toute généralité, c’est faux : l’azéri peut s’écrire de droite à gauche ou de gauche à droite selon l’écriture choisie (latin ou cyrillique dans un cas et l’arabe dans l’autre cas). On connaît également des textes indonésiens et afrikaans (par les Malais du Cap) écrits de droite à gauche à l’aide de l’écriture arabe, alors que ces langues s’écrivent habituellement aujourd’hui de gauche à droite à l’aide de l’écriture latine. C’est donc le système d’écriture1 et non la langue qui détermine le sens dans lequel s’écrit un texte.

11.8.1

Bref rappel de l’algorithme bidi

Nous allons maintenant introduire quelques concepts de base importants. Ceci peut sembler fastidieux, mais il faut y consacrer quelque temps et de l’effort car, sans une bonne compréhension de ces concepts, vous serez perdu quand il vous faudra écrire ou déboguer des textes bidirectionnels balisés. L’algorithme bidirectionnel opère sur du texte stocké en ordre logique. Les caractères d’un mot arabe comme ‫( ﺳﻼم‬salâm, la paix) seront donc placés en mémoire dans l’ordre suivant : 0

1

2

3

‫س‬

‫ل‬

‫ا‬

‫م‬

U+0633

U+0644

U+0627

U+0645

SÎN

LAM

ALIF

MÎM

On notera que le sîn ‫ س‬est stocké en premier en mémoire alors qu’il s’affiche à l’extrême droite du mot salâm (sous sa forme initiale ‫ ﺳ‬sans queue) puisque les mots arabes s’écrivent de droite à gauche. Rappelons2 comment on passe de la forme en mémoire au mot arabe affiché à l’écran. On se souviendra qu’il existe une ligature obligatoire en arabe, celle qui joint le lam (‫ )ل‬à l’alif (‫ )ا‬pour former ici ‫ﻼ‬.

1. À l’exception d’écritures qui peuvent s’écrire aussi bien de gauche à droite que de droite à gauche, comme le tifinagh touareg, l’étrusque, l’osque ou le falisque. 2. Pour une description complète de l’algorithme bidirectionnel, voir et .

11.8 Réglage de l’algorithme bidi

265

Sens de la lecture

Å

Å

Å

Å

Forme isolée (canonique)

‫م‬

‫ا‬

‫ل‬

‫س‬

U+0645

U+0627

U+0644

U+0633

MÎM

ALIF

LAM

SÎN

Forme contextualisée

‫م‬

‫ﺎ‬

‫ﻠ‬

‫ﺳ‬

Forme ligaturée

‫م‬

Numéro de caractère Nom

‫ﻼ‬

‫ﺳ‬

‫ﺳﻼم‬

Mot lié

Propriété directionnelle des caractères Rappelons qu’Unicode associe à chaque caractère une propriété directionnelle. La plupart des lettres ont un type directionnel gauche-à-droite (GàD) fort, c’est le cas des lettres latines, grecques ou cyrilliques par exemple. Les lettres arabes1, par contre, ont un type droite-à-gauche (DàG) fort. Pour plus détails sur cette propriété directionnelle voir § 4.2.5, Directionalité. Quand du texte au sein d’un élément bloc (comme un paragraphe) mélange plusieurs directionalités, l’algorithme bidi affiche chaque suite contiguë de caractères de même directionalité sous la forme d’un passage directionnel distinct. L’exemple suivant comprend trois passages directionnels : Algérie

‫ﻟﺒﻨﺎن‬

Maroc

Æ

Å

Æ

1

2

3

L’ordre d’affichage des passages directionnels dépend du contexte général. Pour l’exemple ci-dessus, dont le contexte général est GàD puisqu’il s’inscrit dans un texte en français, on lira d’abord « Algérie » puis « ‫( » ﻟﺒﻨﺎن‬DàG) et enfin « Maroc ». Aucun balisage ou stylage (comme les feuilles de styles CSS) n’est nécessaire pour obtenir ce résultat.

Contexte directionnel Le résultat de l’algorithme bidirectionnel dépend du contexte directionnel global du paragraphe, du bloc ou de la page auquel il s’applique. En XHTML, si on ne précise aucun attribut dir, le contexte directionnel implicite est GàD. En revanche, en ajoutant dir="rtl" à la balise html, tous les éléments du document héritent d’un contexte DàG. L’utilisation de l’attribut dir

1. Ainsi que les lettres hébraïques, syriaques, thâna, kharochthies et n’ko et les syllabes chypriotes.

266

Chapitre 11. Unicode et (X)HTML, XML, CSS

sur un élément de type bloc particulier (comme

,

ou ) permet de modifier le contexte directionnel en vigueur pour cet élément et ses descendants.

Caractères neutres Rappelons que les espaces et les signes de ponctuation n’ont pas de formes distinctes GàD ou DàG dans Unicode, car ils peuvent être utilisés avec n’importe quelle écriture. C’est pourquoi on les appelle des caractères neutres. Comme nous l’avons vu au § 4.2.6, Réflexion bidi, certains de ces caractères peuvent d’ailleurs changer de forme dans un passage DàG, c’est le cas des crochets, des parenthèses et des symboles mathématiques de comparaison comme le « < » qui apparaîtra automatiquement sous la forme d’un « > » dans un contexte arabe pour conserver la signification du symbole. Ces caractères ont la propriété booléenne réflexion bidi à vrai. En effet, si b < c en latin, alors la forme équivalente en arabe est ‫ ب > ح‬à l’affichage (où b est représenté par ‫ب‬, et c par ‫)ح‬. Voyons cela de plus près. Nous avons donc en mémoire :

En mémoire

0

1

2

‫ب‬


"دوﻟﻪ‬،‫ اﻟﻤﻐﺮب‬ne forme donc qu’un passage directionnel arabe qui s’affichera comme ‫ ﻟﺒﻨﺎن‬،‫ دوﻟﻪ" PAYS 1 , PAYS 2 < / p > N 㩳 N 㩳 㩳 㩳 㩳 㩳 NN 㩳 㩳 㩳 㩳 㩳 㩳 㩳 㩳 NN 㩳 㩳 㩳 㩳 㩳 NN 㩱 㩱 㩱 㩱 㩱 NN 㩱 㩱 㩱 㩱 㩱 㩱 N 㩱 㩱 㩱 㩱 㩱 N F 㩳 N

11.8 Réglage de l’algorithme bidi

271

La deuxième ligne ci-dessus indique les catégories bidirectionnelles : N représente les neutres, F le caractère de type faible et les flèches la directionalité forte des lettres correspondantes. Après résolution des caractères faibles (F) et neutres (N) dans un contexte global GàD (᪸ , on obtient : PAYS 1 , Å

PAYS 2 < / p > Æ

Ce qui donnera à l’affichage après inversion du passage DàG (᪶ 

On remarquera que le « > » a été inversé car sa propriété « Réflexion bidi ? » est à vrai (voir § 4.2.7, Réflexion bidi). Il faut souligner que le problème de Notepad n’en est un que d’affichage : en mémoire les caractères arabes sont dans le bon ordre et ils s’afficheront correctement dans un navigateur qui prend en charge l’algorithme bidirectionnel. Évidemment, ces difficultés rendent l’édition de textes bidi balisés très fastidieuse — voire impossible — dans un éditeur comme Notepad.

11.8.5

Emboîtement des passages bidi

Reprenons notre convention où les minuscules représentent des caractères latins et les majuscules des caractères arabes. Imaginons maintenant que nous ayons en mémoire la suite de caractères suivante : a

b

c

D

E

F

g

h

i

J

K

L

m

n

o

On peut a priori interpréter cette suite des deux façons suivantes :

• Cinq passages directionnels séparés qui s’afficheront ainsi : abc FED ghi LKJ mno

• Deux passages imbriqués (on parle aussi de deux paliers) qui s’afficheront comme suit : abc LKJ ghi FED mno.

Sans caractère de commande supplémentaire, l’algorithme bidi Unicode analysera la chaîne comme cinq passages directionnels distincts. Pour permettre la seconde interprétation, Unicode prévoit trois caractères de commande1, mais ils créent des régions aux frontières invisibles et ne sont donc pas recommandés dans un contexte 1. Il s’agit des caractères suivants : U+202A enchâssement gauche-à-droite (LRE), U+202B enchâssement droite-à-gauche (RLE) et U+202C dépilement de formatage directionnel (PDF).

272

Chapitre 11. Unicode et (X)HTML, XML, CSS

balisé d’autant plus que la structure des documents balisés épouse habituellement de près l’imbrication bidirectionnelle (il s’agit, par exemple, souvent de citations qui devraient de toute façon être balisées). La solution est simple : il suffit d’ajouter l’attribut de directionalité (dir) au balisage qui entoure le passage de deuxième niveau. Prenons un exemple avec une citation arabe emboîtée dans le texte français1 : Il murmura « ! ‫ﻏﺪا‬ 1

4

L’Oasis

‫ﺳﺄﻛﻮن ﻓﻲ ﻓﻨﺪق‬

» avant de disparaître.

3

2

5

Les numéros directement sous les extraits de texte indiquent la position relative de ces extraits en mémoire. Les lignes suivantes représentent le sens des passages imbriqués, d’abord le sens du passage latin englobant, puis le sens du palier arabe de second niveau. Si on écrit ce texte en HTML, dans un éditeur qui traite correctement le bidi balisé comme XMLSpy, de la façon suivante :

Il murmura « ! ‫ ﻏﺪا‬L’Oasis ‫ » ﺳﺄﻛﻮن ﻓﻲ ﻓﻨﺪق‬avant de disparaître.



On obtient un texte mal ordonné (l’algorithme bidi pense avoir affaire à cinq passages distincts) : Il murmura « ‫ ﺳﺄﻛﻮن ﻓﻲ ﻓﻨﺪق‬L’Oasis ‫ » ! ﻏﺪا‬avant de disparaître.

Pour obtenir le bon résultat, il faut ouvrir un nouveau palier directionnel. Pour ce faire, en XHTML, on encadre la citation à l’aide de balises et on lui affecte une directionalité DàG grâce à l’attributdir, comme ci-dessous :

Il murmura « ! ‫ ﻏﺪا‬L’Oasis ‫ » avant de disparaître.



Pour des langages de balisages autres que XHTML/HTML, il se peut qu’un attribut similaire à dir existe. Vous pourrez alors lui associer une mise en forme particulière pour obtenir l’imbrication souhaitée (voir § 11.8.7, Les feuilles de styles CSS et le bidi). Si un tel attribut n’existe pas, il faudra probablement vous résoudre, faute de mieux, à utiliser les caractères d’enchâssement bidi Unicode mentionnés plus tôt (U+202A LRE, U+202B RLE, U+202C PDF), même s’ils sont déconseillés.

1. C’est-à-dire il murmura « JE SERAI À L’HÔTEL l’oasis DEMAIN ! » avant de disparaître.

11.8 Réglage de l’algorithme bidi

11.8.6

273

Caractères de commande bidi et balisage

Concluons en présentant à nouveau les caractères Unicode déconseillés que nous mentionnions au début du § 11.8 et rappelons comment ils peuvent être remplacés par du balisage HTML. Nom abrégé

Numéro

Nom

Balisage équivalent

LRE

U+202A

enchâssement gauche-à-droite

dir="ltr"

RLE

U+202B

enchâssement droite-à-gauche

dir="rtl"

LRO

U+202D

forçage gauche-à-droite

RLO

U+202E

forçage droite-à-gauche

PDF

U+202C

dépilement de formatage directionnel

Rien

Les caractères Unicode sont, en règle générale, déconseillés et il est spécifiquement déconseillé de mélanger le balisage et les caractères Unicode de même type. Il existe, toutefois, des cas où il n’est pas possible d’utiliser le balisage proposé en XHTML 1.0 : les éléments comme title et les attributs. Ceux-ci ne peuvent en effet que contenir des caractères et aucun sous-élément. Dans ce cas de figure, les caractères de commande bidi Unicode peuvent légitimement s’utiliser pour indiquer la directionalité du texte ou d’une partie du texte. Rappelons, pour être complet, qu’il existe deux caractères de commande bidi parfaitement légitimes : U+200E marque gauche-à-droite (‎) et U+200F marque droite-à-gauche (‏) qui permettent de forcer la directionalité des caractères de type faible ou neutre qui les jouxtent directement. Ils ne permettent donc pas, contrairement à de modifier la directionalité de caractères de type fort comme ABC ou ‫اﺑﺖ‬.

11.8.7

Les feuilles de styles CSS et le bidi

Il existe trois manières de forcer la directionalité d’un texte : • Insérer des caractères de commande bidi comme nous l’avons vu précédemment ; ceci est déconseillé sauf en ce qui a trait aux marques droite-à-gauche (‏) et gauche-à-droite (‎). • Utiliser du balisage grâce à l’attribut dir ou l’élément bdo. • Avoir recours à du stylage, plus particulièrement des feuilles de styles CSS, en utilisant les propriétés direction et unicode-bidi au besoin sur des balises supplémentaires, comme span et div, introduites à cet effet dans le document. Ainsi pour écrire le mot « TROP » de droite à gauche (c’est-à-dire « PORT »), on pourrait a priori penser écrire en (X)HTML/CSS :

274

Chapitre 11. Unicode et (X)HTML, XML, CSS

‮TROP‬

ou1 TROP

ou PORT

ou encore forcerBidi[dir="dag"] {unicode-bidi: bidi-override; direction:rtl;} … TROP

Nous avons vu que la première méthode (l’utilisation des caractères de commande bidi) est déconseillée et qu’on lui préfère la deuxième. Mais qu’en est-il des deux dernières options qui utilisent des propriétés CSS ? La solution qui consiste à ajouter un attribut style à un élément HTML est très fortement déconseillée. En effet, en HTML le comportement par défaut de tous les éléments est prédéfini et les navigateurs sont censés le connaître. On n’ajoute du CSS que pour modifier ce comportement. Il est tout à fait inutile de modifier span, autant utiliser bdo. En outre, comme nous le verrons ci-dessous les navigateurs HTML peuvent légitimement ignorer les feuilles de styles ce qui signifie que le style du span pourrait être tout simplement ignoré ! Pour ce qui est de la dernière option qui utilise une feuille de styles séparée, il faut ici distinguer deux cas :

• Document (X)HTML servi comme du texte — Pour les documents HTML et XHTML servis comme du « text/html » et considérés comme du HTML par le navigateur, il n’est pas conseillé d’utiliser les propriétés bidirectionnelles puisque, d’une part, la spécification HTML précise très clairement le comportement de l’attribut dir et que, d’autre part, la spécification CSS 2.0 recommande d’utiliser du balisage pour les textes bidirectionnels plutôt que ses propres propriétés, car les navigateurs HTML peuvent ignorer les propriétés bidi de CSS 2.0. Ceci signifie que, si vous comptez sur les propriétés CSS pour que le texte HTML s’affiche correctement, vous pourriez bien parfois être déçu et ne pas obtenir le résultat escompté. Toutefois, les dernières versions des grands navigateurs, comme Firefox et MSIE, prennent en charge correctement les propriétés bidirectionnelles de CSS 2.0.

• Document XHTML servi comme du XML — Si le document est accompagné d’un type MIME que l’application cliente interprétera comme un document XML (à savoir application/xhtml+xml, application/xml ou text/xml), il y a fort à parier que cette application ne saura pas comment interpréter l’élément bdo et l’attribut dir. En théorie, dans le monde XML, la

1. U+202E correspond au : forçage droite-à-gauche.

11.9 Formulaire « universel »

275

présentation de toutes les balises est inconnue et il faut tout préciser : dire par exemple que le

est un bloc et que a tel effet bidi. C’est pourquoi, dans ce cas-ci, il est recommandé de préciser le comportement bidi à l’aide de propriétés CSS prévues spécifiquement à cet effet. On conseille de regrouper dans une feuille de styles CSS (appelons-la bidi.css) les propriétés CSS qui permettent d’interpréter correctement la balise bdo et l’attribut dir : *[dir="ltr"] {direction:ltr; unicode-bidi:embed; } *[dir="rtl"] {direction:rtl; unicode-bidi:embed; } bdo[dir="ltr"] {direction:ltr; unicode-bidi:bidi-override;} bdo[dir="rtl"] {direction:rtl; unicode-bidi:bidi-override;}

On fait ensuite appel à ce fichier dans les documents bidirectionnels XHTML de la façon suivante :

...



L’utilisation d’un fichier séparé regroupant ces propriétés bidi permet leur réutilisation dans de nombreuses pages XHTML. Séparer ces fonctionnalités permet également d’éviter que celles-ci soient modifiées par mégarde. Cette séparation permet, enfin, la désactivation sélective de cette feuille de style quand l’application cliente le permet.

11.9 FORMULAIRE « UNIVERSEL » 11.9.1

Créer un formulaire

Les formulaires web permettent la saisie d’informations. Habituellement, l’utilisateur saisit des données dans des champs prévus à cet effet (nom, adresse, numéro de téléphone) ou choisit une option prédéfinie. L’envoi du formulaire se fait en appuyant sur un bouton. Les formulaires sont délimités par la balise . Elle permet de regrouper plusieurs éléments de formulaire (boutons, champs de saisie...). On retrouve habituellement les éléments suivants au sein de la balise :

• L’élément

qui représente différents types de boutons et de champs

de saisie.

• La balise correspond à une zone de saisie de texte. • L’élément , une liste à choix multiples. La balise comprend également différents attributs qui précisent comment et à qui sera envoyé le formulaire. Nous nous intéresserons ici aux attributs « action » et « method » :

276

Chapitre 11. Unicode et (X)HTML, XML, CSS



action indique l’adresse d’envoi, un URI HTTP. Cette adresse correspond à

celle d’un agent qui traitera les formulaires (un script CGI par exemple) et qui analysera les résultats envoyés.



method indique sous quelle forme sera envoyée la requête au serveur, il existe

deux méthodes : 1. « post » précise que les données qui constituent la requête seront envoyées dans le corps de la transmission au serveur ; 2. « get » indique que les données seront ajoutées à la fin de l’URI mentionnée dans action et séparées de cette adresse par un point d’interrogation.

Précisons encore la syntaxe de l’élément , car il est crucial :

Les types de champ input qui nous intéressent dans cette discussion sont :



submit : il s’agit d’un bouton d’envoi de formulaire. Le texte qui apparaîtra sur le bouton peut être précisé grâce à l’attribut value.



text : il s’agit d’un champ de saisie d’une ligne de texte. La taille du champ à l’écran peut être définie à l’aide de l’attribut size et la taille maximale du texte saisi peut l’être grâce à l’attribut maxlength.

Chaque champ du formulaire est envoyé au serveur sous la forme d’une paire name=value, les champs sont concaténés entre eux à l’aide d’une esperluette (&). Exemple de formulaire :

Enregistrement d’un utilisateur

Nom
Prénom
Commentaires Saisir ici vos commentaires


11.9 Formulaire « universel »

277

Que se passe-t-il lors de l’envoi ? Prenons le cas du formulaire ci-dessus et supposons que l’utilisateur a inscrit comme nom « Reimer » et prénom « Tina », n’a pas modifié la boîte de commentaires et qu’il vient d’appuyer sur le bouton « envoyer ». Comme le formulaire doit être envoyé à l’aide de la méthode « GET », le navigateur rassemble les paires « nom=valeur » reliées entre elles par un « & » et les ajoute après l’URI mentionné dans l’attribut « action » et un « ? ». On obtient donc cette requête que le navigateur renvoie au serveur http://hapax.qc.ca GET /form1?nom=Reimer&prenom=Tina& \ commentaires=Saisir+ici+vos+commentaires&soumettre=envoyer HTTP/1.0

Les contraintes d’impression nous obligent à représenter cette requête sur deux lignes (ce qu’indique le \) alors qu’en réalité, le navigateur envoie la requête GET sous la forme d’une seule ligne. On remarquera également que les espaces ont été remplacés par des « + ». Si l’on choisit de préciser que la méthode devrait être POST, le navigateur envoie alors : POST /form1 HTTP/1.0 Accept: text/html Content-type: application/x-www-form-urlencoded Content-length: 82 nom=Reimer \ &prenom=Tina \ &commentaires=Saisir+ici+vos+commentaires \ &soumettre=envoyer

La ligne blanche après Content-Length sépare les entêtes HTTP du corps de la requête POST. Alors que la longueur de l’URL est limitée à, grosso modo, 2 kilo-octets, la taille des données qui peuvent être envoyées au sein d’une requête POST n’est pas limitée par la taille de l’URL pour l’envoi de paires nom/valeur puisque ces paires sont transférées dans le corps du message et non dans l’URL. En théorie, il n’existe pas de limite à la taille des données qui peuvent être transférées par la méthode POST, bien que certains serveurs puissent décider de limiter cette taille. Le codage des données transmises par URL (« GET ») est limité à l’ASCII, il s’agit aussi du codage par défaut des données transmises par la méthode « POST ». Ce mécanisme est inadéquat même pour du texte ISO-8859-1. La section 2.2 du RFC 1738 précise que des octets peuvent être codés selon la notation %hh, mais le texte d’un formulaire est composé de caractères, et non d’octets. Sans définition du codage de caractères, la notation %hh n’a aucun sens. Malheureusement, dans le cas des données envoyées par URL (« GET ») le serveur ne reçoit pas d’information qui précise le codage. Dans le cas de la méthode « POST »,

278

Chapitre 11. Unicode et (X)HTML, XML, CSS

par contre, il existe un entête HTTP qui se nomme Content-Type et celui-ci peut préciser le codage adopté : Content-type: application/x-www-form-urlencoded; charset=utf-8

Par malheur, l’expérience montre que de nombreux scripts du côté des serveurs sont mal écrits et qu’ils sont déroutés par ce type d’entête. En conséquence, la plupart des navigateurs n’envoient pas l’attribut charset quand il est identique à celui de la page HTML qui contenait le formulaire. Avant d’aller plus loin et afin de bien fixer les idées, regardons ce qui se passe quand on remplit le formulaire ci-dessus, mais cette fois-ci avec des caractères accentués. Voici ce que produit le formulaire quand on choisit comme nom « Noël » et comme prénom « François ». GET /form1?nom=No%EBl&prenom=Fran%E7ois& \ commentaires=Saisir+ici+vos+commentaires&soumettre=envoyer HTTP/1.0

On devine qu’il s’agit d’un codage ISO-8859-1. Mais, en pratique, il pourrait aussi bien s’agir de l’ISO-8859-15 ou de Windows 1252. Et si généralement un navigateur renvoie les données d’un formulaire dans le même codage que celui précisé dans la page HTML qui définissait ce formulaire, on n’en est pas assuré. Prenons l’exemple d’un formulaire codé en ISO-8859-15, mais transformé en ISO-8859-1 ou Windows-1252 par le navigateur. Si l’utilisateur insère un caractère qui est codé différemment en ISO-8859-15 et le codage adopté par le navigateur, le serveur qui recevra les données du formulaire pensera les trouver codées en ISO-8859-15, et interprètera mal ces caractères.

11.9.2 Accept-charset sur la balise form Il existe en théorie une manière d’éviter ce problème. En effet, le serveur peut préciser quels codages il est prêt à accepter grâce à l’attribut accept-charset de l’élément form.

Dans la ligne ci-dessus, le serveur déclare qu’il accepte des données de formulaires en Latin-1 ou en UTF-8. Il existe donc en principe une solution simple à l’absence d’indication de codage : ne mentionner et n’accepter qu’un seul codage dans accept-charset. Malheureusement, si Firefox 2 prend en compte accept-charset, MSIE 7 ne s’en préoccupe pas et il envoie habituellement les données du formulaire dans le codage de la page HTML qui contenait le formulaire. Mais ce n’est pas toujours le cas. En effet, si vous insérez un caractère comme « œ » dans le champ « nom » du formulaire ci-dessus (exemple : « Lebœuf »), MSIE 7 modifie le codage pour permettre la transmission de ce digramme et choisit silencieusement Windows-1252

11.9 Formulaire « universel »

279

même si l’accept-charset ne permet pas ce codage ! Voir ci-dessous le « œ » codé sous la forme de %9C : GET /form1?nom=Leb%9Cuf&prenom=Fran%E7ois& \ commentaires=Saisir+ici+vos+commentaires&soumettre=envoyer HTTP/1.0

11.9.3

Inclusion de caractères étrangers au charset

Ceci pose la question plus générale de ce que le navigateur doit faire quand l’utilisateur saisit ou copie des caractères qui sont étrangers au codage du formulaire. Imaginons ainsi que vous vouliez mentionner le premier nombre transfini ℵ (U+2135) dans le champ commentaires alors que le formulaire est codé en Latin-1. Plusieurs navigateurs convertissent cet aleph d’une manière peu conforme : il transforme le caractère ℵ en un appel de caractère numérique sous sa forme décimale, à savoir ℵ. Ensuite, cet appel de caractère est transformé dans la notation %hh, ce qui donne un étrange %26%238501%3B. Ce n’est guère logique ni conforme, mais il y a pire : l’utilisateur ne se rend pas compte que le caractère qu’il croit légitime sera mutilé de la sorte.

11.9.4

Solution : n’envoyer et n’accepter que de l’UTF-8

Cet obstacle nous mène à la conclusion logique : il suffit de choisir pour la page qui définit le formulaire un codage qui permet de représenter tous les caractères. Et c’est là qu’intervient à nouveau Unicode. La solution la plus simple aujourd’hui est de définir ses formulaires en UTF-8 et de préciser un accept-charset="utf-8" sur l’élément form pour les navigateurs qui respectent cet attribut. De la sorte, tous les caractères sont représentables dans le formulaire — plus de surprise de codage du type aleph ℵ — et les données seront toujours renvoyées en UTF-8 puisque les navigateurs utiliseront le codage d’origine et n’auront plus besoin de changer subrepticement de codage avant d’envoyer les données. Depuis quelques années c’est ce que font de grands sites comme Google dans leurs formulaires et ceci fonctionne avec tous les navigateurs modernes (compatibles avec HTML 4). Ceci implique évidemment que les scripts et programmes du côté du serveur puissent aussi traiter correctement les données Unicode, heureusement ceci ne représente plus aujourd’hui un obstacle important.

280

Chapitre 11. Unicode et (X)HTML, XML, CSS

Résumé Voici quelques conseils lorsque vous désirez construire un site web dûment internationalisé. Rappelons qu’internationaliser ne signifie pas que votre site doit être traduit en de nombreuses langues, mais uniquement qu’il est conçu de manière à pouvoir héberger des textes en plusieurs langues. Toujours déclarer le codage associé à vos données, le lieu où l’indiquer dépend du type de document et comment il est servi. Un « non » dans le tableau suivant signifie qu’il ne faut pas préciser le codage de la sorte. Ainsi ne faut-il pas déclarer le codage des fichiers HTML à l’aide d’une déclaration . Les cases « toujours » signifient qu’il faut indiquer le codage de cette façon : un fichier HTML doit indiquer le codage à l’aide de la balise . Quant à « possible », elle indique une possibilité technique qui n’est pas toujours recommandée dans les faits : un script peut préciser le codage dans un entête HTTP, mais il est déconseillé de laisser un serveur préciser le codage de la sorte. Où déclarer le codage Servi comme du

HTTP



HTML

possible

non

toujours

XHTML (text/html)

possible

option

toujours

XHTML (xml)

possible

toujours

non

Utiliser Unicode autant que se peut pour le stockage de vos données : pages HTML, base de données, scripts, etc. N’utiliser les entités de caractères ( ) et les appels aux caractères numériques (de type &#xxxxx;) qu’avec parcimonie et judicieusement. Ils sont utiles pour représenter des caractères invisibles, ambigus et empêcher des problèmes de syntaxe (p. ex. = 16 bits */ typedef unsigned long UChar32; /* >= 32 bits */

Vous pourrez alors utiliser ces typedef pour définir vos variables : UChar string[4]={0x0061,0xdbd0,0xdf21,0 }; UChar32 codePoints[3]={0x00000061,0x00104321,0};

Malheureusement, cette solution, si elle est plus portable, comporte aussi de graves limites, la moindre n’étant pas que nombreuses fonctions standards sur les caractères larges comme celles définies dans (wcslen,

1. Téléchargeable ici .

12.2 Les langages de programmation

289

wcscmp,...) ne sont pas utilisables avec les caractères définis avec les typedef

mentionnés ci-dessus.

12.2.2 Les caractères dans Java Dès sa conception, Java a utilisé Unicode comme seule représentation interne des caractères. Avant la version 1.5 de Java, les caractères étaient codés dans des variables de type char sous la forme de valeurs UCS-2, à savoir des seizets ne donnant accès qu’au plan multilingue de base (PMB). Java 1.5 est la première version à permettre l’accès aux plans complémentaires grâce à deux char qui représentent une paire de seizets d’indirection. Les char Java sont donc désormais des unités de stockage UTF-16. Il est possible d’utiliser n’importe quel caractère Unicode du plan multilingue de base sous la forme d’un caractère littéral ou sous la forme d’une suite d’échappement introduite par \u. Le tableau 12.2 reprend les principales conventions d’échappement de Java pour représenter les caractères. Tableau 12.2 – Conventions d’échappement de caractère en Java Suite d’échappement

Signification

\b

U+0008 espace arrière

\t

U+0009 tabulation horizontale

\n

U+000A passage à la ligne

\r

U+000D retour de chariot

\"

U+0022 guillemet anglais

\' \\

U+0027 apostrophe

\xxx

Caractères du répertoire « Latin-1 » (mais il s’agit toujours de caractères codés Unicode) dont le numéro est exprimé sous la forme d’un nombre octal compris entre 000 et 377.

\uxxxx

Caractères Unicode dont le numéro Unicode est exprimé sous la forme d’un nombre hexadécimal de quatre chiffres. Les échappements Unicode peuvent apparaître partout dans un programme Java, pas uniquement dans les littéraux. On peut ainsi les utiliser dans les noms de variable ou de méthode.

U+005C barre oblique inversée (contre-oblique)

Contrairement à C et C++, les chaînes en Java (String) ne sont pas des tableaux de caractères (char[]), bien que les tableaux de char existent en Java (mais il est difficile de les manipuler comme chaînes) et qu’il soit facile de passer d’un type à l’autre. Un littéral de type char est entouré de guillemets simples (‘a’) alors qu’un littéral de type String l’est d’apostrophes anglaises droites («Une chaîne»). Java permet l’utilisation des caractères Unicode partout, même dans les noms de variables ou de méthodes. C’est le cas dans le code suivant où l’on voit apparaître non seulement des caractères français, mais également, à titre d’illustration, des caractères de l’alphabet phonétique international :

290

Chapitre 12. Internationalisation des logiciels

public static void main(String[] args) { String nȈʰdȍvarjablȍ = "Comment ça va ? Quel № \u2116 !"; System.out.println(nȈʰdȍvarjablȍ); javax.swing.JOptionPane.showMessageDialog(null, nȈʰdȍvarjablȍ); }

Le System.out.println ne parvient souvent pas à afficher les « № » et affiche plutôt des « ? », nous verrons par la suite comment remédier à ce désagrément. Le compilateur Java (javac) considère, sauf option –encoding à l’effet contraire, que les fichiers qui lui sont soumis sont codés dans le codage « naturel » de votre machine. Sur une plateforme MS Windows en français, il s’agit de Windows Latin-1 (Windows 1252), sur une plateforme Linux ou Unix probablement de l’ISO 8859-1. C’est pourquoi votre éditeur de code (JBuilder, Eclipse, etc.) pourra convertir les caractères qui ne font pas partie de ce codage naturel en une série de suites d’échappement comme ceci : String n\u0254\u0303d\u0259varjabl\u0259 = "Comment ça va ? Quel \u2116 \u2116 !";

Remarquez que le fait que votre fichier ne contienne que des caractères appartenant au jeu de caractères « naturel » de votre plateforme ne vous empêche pas de faire référence à des caractères Unicode grâce à des suites d’échappement du type « \uxxxx » passe-partout, puisque codées en ASCII. Il n’est pas important de savoir si votre plateforme prend en charge ces caractères Unicode pour autant qu’ils soient conservés intacts sous la forme de suites d’échappement, car c’est Java qui les interprétera et non votre plateforme. Votre éditeur pourra également vous forcer à éliminer ces caractères ou, encore, à choisir un autre codage pour vos fichiers, mais il faudra alors, lors de la compilation, préciser celui-ci au compilateur à l’aide de l’option –encoding. Utiliser des noms de caractères non ASCII dans les noms de classes peut poser un problème de portabilité pour les machines qui gèrent mal ou différemment les noms de fichiers qui ne sont pas en ASCII (car en Java, à quelques exceptions près le nom d’une classe correspond au nom du fichier qui le contient). Même si la plupart des systèmes de fichiers modernes peuvent, en principe, prendre en charge les noms de fichier Unicode, il existe encore de nombreux cas où ceci n’est pas le cas dans les faits. Java 1.5 a introduit la possibilité de manipuler directement des unités de stockage sur 32 bits, appelés « points de code » dans la terminologie Java, sous la forme d’entiers (int).

12.2 Les langages de programmation

291

Configuration d’Eclipse pour afficher de l’Unicode Eclipse est un outil de développement gratuit Java très poussé. Voici comment configurer sa console pour y afficher des textes Unicode : – Choisir dans la barre de menu Fenêtre > Préférences > Général > Apparence > Couleurs et polices > Déboguer > Police de la console. – Choisir une police Unicode suffisamment riche pour vos besoins (Arial Unicode

MS, Code 2000, etc.). Pour chaque configuration d’exécution (il faut, malheureusement, répéter ceci pour chacune d’entre elles) : – sous l’onglet (x)=Arguments, dans la boîte Arguments VM, ajouter -Dfile.encoding=UTF-8. – sous l’onglet Commun, à droite sous l’entête Codage de la console, sélectionner Autre, puis UTF-8 dans la liste déroulante. Si on ressaye maintenant d’exécuter le code suivant : String nȈʰdȍvarjablȍ = "Comment ça va ? Quel № \u2116 !"; System.out.println(nȈʰdȍvarjablȍ);

On voit bien apparaître sur la console le texte sans aucun « ? », même si les caractères ne sont pas codés en Latin-1, le codage « naturel » de la machine : Comment ça va ? Quel № № !

12.2.3 Les caractères dans C# et la plateforme .NET Les chaînes de caractères en C# (prononcé « c dièse » ou « c sharp ») sont toujours codées en Unicode. Pour être plus exact, chaque caractère en C# prend 16 bits et est codé sous la forme de stockage UTF-16. Les caractères C# adoptent donc la même forme stockée que les caractères Java postérieurs à la version 1.4 : UTF-16. Ceci signifie qu’un seul char (System.Char) ne permet pas d’accéder directement à tous les caractères Unicode. Il faut employer deux seizets d’indirection (appelés « substituts » dans la documentation de Microsoft) pour accéder aux plans complémentaires (audelà du PMB). Chaque seizet sera également stocké dans un char. Rappelons que pour Unicode un seizet d’indirection n’est pas un caractère. L’extrait de code suivant illustre le cas où l’on désire représenter U+18000 syllabe chypriote a. char[] chypriote = new char[] { '\uD802', '\uDC00' };

Contrairement à C ou C++, les chaînes en .NET et donc en C# peuvent contenir des caractères nuls sans soulever de difficultés : les méthodes qui opèrent sur les chaînes ne traitent pas ce caractère comme une fin de chaîne. Toutefois, d’autres classes, notamment de nombreuses classes de Windows.Forms, considèrent que la chaîne se termine au premier caractère nul. Si jamais votre chaîne semble tronquée de manière inexpliquée, ce caractère nul pourrait en être la cause.

292

Chapitre 12. Internationalisation des logiciels

Dans le code suivant, la fenêtre n’affichera que « Ah ! ». Il faut supprimer le caractère nul (‘\u0000’) pour voir apparaître « François Yergeau ! ». namespace using using using

EssaiDeTroncature { System; System.Drawing; System.Windows.Forms;

public class BonjourToutLeMonde : System.Windows.Forms.Form { public BonjourToutLeMonde() { System.Windows.Forms.Label libellé = new Label(); libellé.Location = new Point(8, 8); libellé.Text = "Ah !\u0000 François Yergeau !"; libellé.Size = new Size(408, 48); libellé.Font = new Font("Arial", 24f); this.ClientSize = new Size(426, 55); this.Controls.Add(libellé); } public static void Main(string[] args) { Application.Run(new BonjourToutLeMonde()); } } } // fin de l’espace de nom

C#, notamment par sa classe System.Char, offre un grand nombre de méthodes qui permettent de manipuler des caractères Unicode ou d’obtenir leurs propriétés. Ces propriétés, comme c’est également le cas pour Java, sont tirées directement des fichiers fournis par le consortium Unicode et que BabelMap permet de visualiser de manière conviviale. En ce sens, C# ressemble grandement à Java et à ICU. À titre d’exemple, le code suivant, vérifie si deux caractères constituent une paire de seizets d’indirection valable : Console.WriteLine("Paire d’indirection légale - {0}", Char.IsSurrogatePair(chypriote[0], chypriote[1]));

12.2.4 Bibliothèques d’internationalisation, le cas ICU Nous allons voir dans les pages qui suivent quelques aspects de Java qui facilitent grandement l’internationalisation des logiciels. Les langages de la plateforme .NET comme C# et J# ont sensiblement les mêmes fonctionnalités que Java et les présentent sous une interface similaire. Il existe également une bibliothèque d’internationalisation qui prend son origine dans un effort de développement d’IBM : l’ICU (International Components for Unicode). D’abord développé en C/C++, selon les termes d’IBM, « afin de combler les lacunes et de corriger les défauts en termes d’internationalisation » de ces langages, l’ICU est désormais également disponible pour les programmes Java.

12.2 Les langages de programmation

293

L’ICU sert souvent de terrain d’essai pour Java, ICU pousse plus loin les fonctionnalités d’i18n de Java. C’est ainsi qu’une grande portion des paquets java.text et java.util sont directement hérités de l’ICU. C’est une nouvelle fois le cas pour Java 1.6 qui hérite de plusieurs classes d’intérêts. Nous y reviendrons.

12.2.5 Propriétés de caractères en Java/ICU Il est exclu avec Unicode de vérifier si un caractère est une lettre à l’aide d’un test comme celui-ci : char c ; ... if ((c >= 'a' && c = 'A' && c 10 324,34 0.23 => 0,23

On notera avec intérêt que les délimiteurs décimaux (« . ») et de tranches (« , ») du DecimalFormat, d’inspiration américaine, se sont adaptés lors du formatage aux conventions françaises (de France). Le tableau 12.9 énumère la liste des métacaractères de formatage. Tableau 12.9 – Métacaractères de formatage des chiffres et des montants Métacaractère

Signification

#

Un chiffre, les zéros initiaux seront supprimés.

0

Un chiffre, les zéros s’affichent toujours.

.

Le séparateur décimal (sera remplacé selon la Locale).

,

Le séparateur de milliers (sera remplacé selon la Locale).

-

Le préfixe négatif (sera remplacé selon la Locale).

;

Sépare les motifs positifs et négatifs. Le format « ###,##0.00;(###,##0.00) » affichera la valeur -255 comme ceci : « (255,00) », alors que 255 sera affiché « 255,00 ».

¤

Représente la devise monétaire, ce signe sera remplacé par la devise locale.

E

Sépare l’exposant de la mantisse.

%

Affiche les valeurs sous la forme de pourcentages.



Affiche les valeurs sous la forme de pour mille.

' (autre)

Caractère d’échappement, '#' représente un croisillon (« dièse »), '' (deux apostrophes) représente une apostrophe. Apparaît tel quel dans le résultat.

12.5 Formater les messages

317

L’exemple précédent créait un objet DecimalFormat pour la Locale implicite. Si vous voulez préciser la Locale, vous devez instancier un NumberFormat et le transtyper (« cast ») en DecimalFormat. DecimalFormat f = (DecimalFormat) NumberFormat.getInstance(laLocale);

De la même manière, on peut obtenir de NumberFormat un formateur de montants pourvu de la logique nécessaire pour présenter des montants monétaires (y compris le symbole de devise) dans de nombreuses locales. Ces NumberFormat utilisent des motifs DecimalFormat prédéfinis pour chaque Locale. L’exemple suivant affiche le même montant en euros pour la France et la Belgique, en francs suisses en Suisse et en « piastres » pour le Canada français. Locale Locale Locale Locale

ch fr ca be

= = = =

new new new new

Locale("fr", Locale("fr", Locale("fr", Locale("fr",

NumberFormat fCh NumberFormat fFr NumberFormat fCa NumberFormat fBe double montant =

"CH"); "FR"); "CA"); "BE");

= NumberFormat.getCurrencyInstance(ch); = NumberFormat.getCurrencyInstance(fr); = NumberFormat.getCurrencyInstance(ca); = NumberFormat.getCurrencyInstance(be); 1234.56;

System.out.println(fCh.format(montant)); System.out.println(fFr.format(montant)); System.out.println(fCa.format(montant)); System.out.println(fBe.format(montant));

On obtient, de la sorte, après utilisation des séparateurs et du symbole monétaire locaux, quatre formes différentes du montant (la classe NumberFormat n’effectue bien évidemment pas de conversion de devises) : SFr. 1'234.56 1 234,56 € 1 234,56 $ 1.234,56 €

Il est également possible d’utiliser NumberFormat pour analyser des nombres. Il ne faut pas utiliser des méthodes du type Integer.parseInt() ou Double. parseDouble(), car elles ne prennent pas en compte les différentes conventions culturelles.

318

Chapitre 12. Internationalisation des logiciels

NumberFormat fFr = NumberFormat.getInstance(new Locale("fr", "FR")); NumberFormat fAr = NumberFormat.getNumberInstance(new Locale("ar")); String nombreArabe = "١،٢٣٤،٥٦٧٫٨٩"; try { Number résultat = fAr.parse(nombreArabe); System.out.println(" Nombre arabe converti : " + fFr.format(résultat)); } catch(ParseException e) { // traiter l’exception }

On obtient ainsi les chiffres utilisés en arabe (dits arabo-hindis) convertis en nos chiffres (dits arabes) : Nombre arabe converti : 1 234 567,89

12.5.4 Variabilité de l’ordre des mots dans les langues Les messages composés contiennent des données variables. Imaginons le message « Le chat a mangé le poisson » où « le poisson » est une variable. Vous pourriez être tenté d’écrire le code suivant en Java : String dîner = "le poisson"; System.out.println("Le chat a mangé " + dîner);

Vous avez bien lu les pages qui précèdent et vous avez donc décidé d’extraire les deux chaînes de caractères et de les mettre dans une Ressource : chasseur=Le chat a mangé proie=le poisson

Ce qui donne le code suivant : ResourceBundle chasseurEtProie = ResourceBundle.getBundle("faisceaux.ChasseurEtProie", new Locale("fr")); String dîner = chasseurEtProie.getString("proie"); System.out.println(chasseurEtProie.getString("chasseur") + dîner);

12.5 Formater les messages

319

Vous pourriez vous dire que votre code est maintenant internationalisé et prêt à la localisation. Il existe malheureusement plusieurs problèmes avec le code ci-dessus. Le plus grand est lié à l’ordre des mots qui diffère grandement dans les langues du monde. Prenons la même phrase et comparons l’ordre des mots équivalents dans quatre langues : Le chat 1 Felis 1 ₀ߪ 1 Die Katze 1

a mangé 2 piscem 3 㝼ࠍ 3 hat den Fisch 2 3

le poisson. 3 edit. 2

㘩ߴߚ‫ޕ‬ 2 gegessen 2

français latin japonais allemand

Rappelons que le traducteur de chaque langue ne voit que les chaînes dans les ressources. Imaginons le traducteur allemand confronté à « Le chat a mangé ». Il sera probablement obligé de le traduire par « Die Katze hat gegessen ». À l’assemblage des deux parties, on obtiendra un message en mauvais allemand : Die Katze hat gegessen den Fisch

Cette phrase n’est pas grammaticalement correcte en allemand. Comment éviter ce type de problèmes ? La solution consiste à éviter la composition de messages faits à partir de fragments de phrase ou, quand vos messages contiennent des variables, à utiliser les techniques présentées ci-dessous.

12.5.5 Messages variables et internationalisés Pour éviter les difficultés liées à la composition dynamique de messages identifiées ci-dessus, on utilisera la classe MessageFormat à laquelle on passera le gabarit de la phrase pour une Locale donnée ainsi que les paramètres nécessaires à sa composition. Dans notre cas, le gabarit est relativement simple puisque nous n’avons qu’une variable associée au message : le plat dégusté par le chat représenté par {0} dans le gabarit. Dans la syntaxe de MessageFormat, ceci peut s’écrire de la façon suivante dans les quatre langues qui nous intéressent : # dans fichier pour locale « fr » gabarit=Le chat a mangé {0}. # dans fichier pour locale « la » gabarit=Felis {0} edit. # dans fichier pour locale « ja » gabarit=₀ߪ{0}㘩ߴߚᇭ # dans fichier pour locale « de » gabarit=Die Katze hat {0} gegessen.

320

Chapitre 12. Internationalisation des logiciels

Chaque ressource contiendra donc deux valeurs : le gabarit et la proie. Voici un exemple complet de la ressource (comme une ListResourceBundle pour l’allemand) : public class ChasseurEtProie_de extends ChasseurEtProie { static final Object[][] contenu = { {"proie", "den Fisch"}, {"gabarit", "Die Katze hat {0} gegessen."} }; protected Object[][] getContents() { return contenu; } }

On obtient le gabarit comme n’importe quelle autre ressource : Locale laLocale = new Locale("de") ; chasseurEtProie = ResourceBundle.getBundle("faisceaux.ChasseurEtProie", laLocale) ; String gabarit chasseurEtProie.getString("gabarit") ;

Restent deux choses à faire : créer un MessageFormat en précisant le gabarit à utiliser et la locale visée (si celle-ci n’est pas précisée, le message sera formaté pour la locale par défaut), puis passer à ce MessageFormat les arguments du gabarit (ici il n’y en a qu’un) pour qu’il puisse formater le tout. MessageFormat formateur = new MessageFormat(gabarit, laLocale); Object[] argumentsDuGabarit = { chasseurEtProie.getString("proie") }; String résultat = formateur.format(argumentsDuGabarit);

Voilà le tour est joué : la « proie » sera insérée au bon endroit dans le gabarit et le tout sera affecté à résultat. Il s’agissait d’un exemple très simple, prenons-en un quelque peu plus compliqué. Imaginons que nous voulions internationaliser cette chaîne : À 13 h 15 le 5 août 2007, le dollar valait 0,726 €. Chaque champ variable est souligné. Remarquons, d’une part, que nous n’avons plus affaire qu’à des chaînes de caractères, mais aussi à des montants et des heures et, d’autre part, que nous avons souligné l’article de la devise car en français celuici peut varier (« la lire, la roupie »). On obtient donc un gabarit quelque peu plus complexe cette fois-ci : gabarit=À {0,time,HH' h 'mm} le {0,date,long}, {1} valait \ {2, number,#.###} {3}.

Ce gabarit se lit de la manière suivante : la première variable {0} est une heure exprimée sous la forme française avec un « h » comme séparateur (pour la syntaxe, voir SimpleDateFormat) et non le « : » par défaut dans Java, puis la même variable (rappelons qu’une Date en Java contient à la fois la date et l’heure) est exprimée comme une date de format DateFormat.LONG, c’est-à-dire avec le nom du mois au complet). Ensuite, on insère simplement le 2e argument {1}, puis vient le 3e {2}

12.5 Formater les messages

321

exprimé sous la forme d’un flottant avec trois chiffres après la virgule et enfin le 4e argument {3}, le symbole de la devise. On utilise ce gabarit de la façon suivante : ResourceBundle cours = ResourceBundle.getBundle("faisceaux.coursDevises", laLocale); MessageFormat formateur = new MessageFormat(cours.getString("gabarit"), laLocale); // gabarit contient une date, une chaîne, un nombre, une chaîne Object[] argumentsDuGabarit = { new Date(), "le dollar", 0.726, "€"}; String résultat = formateur.format(argumentsDuGabarit); System.out.println(résultat);

Il faut noter le fait que nous avons ici mentionné la locale lors de la création du MessageFormat, cette mention est obligatoire, car le gabarit contient des dates, des montants, etc. qui devront être formatés en fonction de cette locale. L’application de ce code produit le résultat suivant : À 13 h 15 le 5 août 2008, le dollar valait 0,726 €.

Pour produire le même texte en chinois, on créera un gabarit de ce type : gabarit={0,date,long}{0,time,short}㧘{1}ଖ{2,number,#.###}{3}‫"ޕ‬

On instancie la ResourceBundle chinoise correspondante et on initialise les arguments du gabarit. Par souci de concision, ici, ces arguments sont des chaînes codées en dur, normalement il faudra bien sûr aller les chercher dans une ressource localisée. Locale laLocale = new Locale("zh"); ResourceBundle coursCh = ResourceBundle.getBundle("faisceaux.coursDevises", laLocale); MessageFormat formatChine = new MessageFormat(coursCh.getString("gabarit"), laLocale); Object[] argumentsChinois = {new Date(),"৻⟤ర", 0.65353,"᰷ర"}; String résultat = formatChine.format(argumentsChinois);

Ce qui produit1 : 2008ᐕ8᦬5ᣣਅඦ13:18㧘৻⟤రଖ0.654᰷ర‫ޕ‬

Notez que le gabarit français aurait pu s’écrire (en reportant la date et l’heure à la fin) : gabarit= {1} valait {2, number,#.###} {3} à \ {0,time,HH' h 'mm} le {0,date,long}.

si on avait voulu produire avec les mêmes arguments fournis dans le même ordre : le dollar valait 0,654 € à 13 h 18 le 5 août 2008.

1. Les Chinois, comme les anglophones, n’ont pas vraiment l’habitude française de dire « 13 heures » (sauf pour des raisons militaires, scientifiques, etc.), mais ils comprendront cette notation. Écrire l’heure comme le feraient les Chinois est plus compliqué que ce que produit Java, car il faut respecter plusieurs distinctions. On dira traditionnellement, par exemple, « ਅඦ3ὐ » soit 3 heures de l’après-midi pour 15 h 00, mais « ඡ਄7ὐ » 7 heures de la soirée pour 19 h 00. Malheureusement, Java fait en sorte que « ਅඦ » servent de « PM » américain, et certains programmes se voient obligés de mettre quelque chose pour « AM » et « PM » bien qu’en chinois ça ne se fasse pas...

322

Chapitre 12. Internationalisation des logiciels

12.5.6 Gestion de l’accord en nombre Un autre problème lié à l’affichage de messages composés qui contiennent des variables est l’accord en nombre des différentes composantes du message. Prenons le cas, où nous aimerions indiquer le nombre d’erreurs découvertes dans un document. On pourra un peu vite écrire un gabarit du genre : Il y a {0} erreurs dans le fichier {1}.

Si {0} vaut 0 ou 1, on affichera respectivement : Il y a 0 erreurs dans le fichier {1}.

et Il y a 1 erreurs dans le fichier {1}.

Ce qui n’est guère satisfaisant dans une application de qualité où l’on voudra plutôt produire les formats suivants : Il n’y a pas d’erreur dans le fichier {1}. Il y a une erreur dans le fichier {1}.

C’est possible grâce à la classe ChoiceFormat. Il faut d’abord identifier le groupe nominal qui varie. Ici, il s’agit de tout ce qui se trouve entre « Il » et « dans », on obtient dès lors le gabarit suivant : Il {0} dans le fichier {1}.

Le nom représentant le fichier {1} est une simple chaîne, facile à traiter comme nous l’avons vu précédemment. Le paramètre {0} est une autre paire de manches. On va l’isoler et utiliser la classe ChoiceFormat pour permettre d’en choisir la bonne version. Cette classe est une sous-classe de Format. Un ChoiceFormat convertit un nombre en objet String d’une façon analogue à l’instruction switch. Chaque ChoiceFormat est formée d’un tableau de valeurs double qui représentent des limites d’intervalle et d’un tableau de chaînes de caractères représentant des formats. Lorsqu’on appelle la méthode format de ChoiceFormat avec comme paramètre un nombre y, l’objet ChoiceFormat utilisera le format[i] avec i tel que : limites[i] " : " == ")) + chaîne2);

Le programme affiche comme prévu le résultat erroné : poète > poule

Dans cette section, nous allons voir comment utiliser Java et plus particulièrement ICU pour mettre en œuvre le tri et sa contrepartie, la comparaison. Pourquoi particulièrement l’ICU ? Parce qu’à nouveau Java hérite son tri d’ICU et que la version du tri de Java traîne souvent de plusieurs années par rapport à la version d’ICU, elle est habituellement moins rapide et moins puissante1 que la dernière version d’ICU que vous pourrez télécharger bien avant que Java ne mette à jour ses classes de tri. L’interface d’ICU (en Java) est quasi identique à celle de Java et il suffit souvent pour passer de la bibliothèque standard de Java à celle d’ICU de modifier les import en tête de classe.

12.6.1

Tri en Java ou ICU pour Java

Il ne faut pas utiliser String.equals() ou String.compare() pour comparer des chaînes qui seraient internationalisées — cela vaut donc pour le français — puisque ces méthodes effectuent des comparaisons binaires. La solution la plus simple est d’utiliser la classe abstraite java.text.Collator. À nouveau, il faut instancier cette classe en mentionnant la locale en vigueur. On utilisera alors la méthode compare() de ce Collator qui rend une valeur négative, égale à zéro, ou positive selon, respectivement, que la première chaîne se trie avant la seconde, est de même rang que la seconde ou se trie après la seconde. Si on reprend l’exemple de tri « intuitif » erroné ci-dessus et qu’on y ajoute l’utilisation d’un Collator, on obtient :

1. Notez que, malgré ces couronnes tressées, la dernière version d’ICU à ce jour (ICU 3.8) ne trie toujours pas correctement le français selon la norme canadienne CAN/CSA Z243.4.1-98 ou selon le standard SGQRI 004 du gouvernement du Québec (les spécifications les plus précises en la matière). Un rapport d’anomalie existe dans la base des bogues d’ICU à ce sujet. Voir pour les curieux, la précision de la description de la norme mentionnée dans ce rapport d’anomalie est instructive.

326

Chapitre 12. Internationalisation des logiciels

Collator c = Collator.getInstance(Locale.FRENCH); String chaîne1 = "poète"; String chaîne2 = "poule"; int comp = c.compare(chaîne1, chaîne2); System.out.println(chaîne1 + (comp < 0 ? " < " : (comp > 0 ? " > " : " == ")) + chaîne2);

Et cette fois le résultat affiché est bien correct : poète < poule

Trier une liste de mots n’est guère plus difficile : Collator c = Collator.getInstance(Locale.FRENCH); TreeSet liste = new TreeSet(c); // arbre trié selon c liste.add("poème"); liste.add("poule"); liste.add("podagre"); for (String chaîne : liste) { System.out.println(chaîne); }

Le résultat produit : podagre poème poule

On se rappellera que le tri à quatre niveaux ne considère pas toutes les différences entre les lettres comme étant d’égales forces (voir § 4.4.4, La solution — Un tri à quatre niveaux). L’objet Collator permet de préciser comment ce « trieur » devrait considérer les différences entre deux caractères. Ces différences dépendent de la locale, le tableau 12.10 résume le sens typique de ces forces. Tableau 12.10 – Description des cinq forces de comparaison Force

Description

Exemple

PRIMARY

Les lettres de bases sont différentes.

« a » par rapport à « b »

SECONDARY

Les lettres de base sont identiques, mais « a » par rapport à « à » elles diffèrent par leurs accents.

TERTIARY

Les lettres de base sont identiques, mais « A » par rapport à « a » elles diffèrent par leur casse.

QUATERNARY

Les lettres sont identiques si ce n’est par « coop » par rapport à « co-op » la ponctuation.

IDENTICAL

Les lettres sont identiques, si ce n’est par U+212B Å par rapport à U+00C5 Å leur numéro de caractères Unicode sous la forme D de normalisation.

12.6 Comparaison et tri

327

La force primaire est la plus forte. La force Collator.IDENTICAL est la force de moindre de force qui sert à départager les chaînes qui sont par ailleurs rigoureusement identiques. La force implicite est Collator.TERTIARY, on peut la modifier grâce à la méthode setStrength() de la classe Collator. Dans les bibliothèques de tri d’ICU et de Java, quand la force du tri est de niveau trois, les signes de ponctuation sont considérés comme des caractères comme les autres et interviennent donc au premier niveau.

12.6.2 Comparer des chaînes en ignorant les accents Dans certaines langues, comme l’anglais, certains mots peuvent être écrits avec ou sans diacritiques (rôle, café, façade, etc.). Si vous utilisez un collateur anglais avec sa force implicite (tertiaire), ce trieur vous dira qu’un mot comme « rôle » est différent de « role » alors que ce n’est pas le cas pour la plupart des applications en anglais. Pour s’assurer que de tels mots sont traités comme des mots identiques, on modifie la force du collateur de cette manière : String chaîne1 = "rôle"; String chaîne2 = "role"; Collator trieurAnglais = Collator.getInstance(Locale.US); trieurAnglais.setStrength(Collator.PRIMARY); if (trieurAnglais.equals(chaîne1, chaîne2)) System.out.println(chaîne1 + " est égal à " + chaîne2); else System.out.println(chaîne1 + " N’est PAS égal à " + chaîne2);

Le résultat produit : rôle est égal à role

Si vous supprimez la ligne qui modifie la force implicite le résultat sera : rôle N’est PAS égal à role

12.6.3 Personnaliser le tri La personnalisation des règles de tri se fait à l’aide de la classe RuleBasedCollator à laquelle on fournit une chaîne de personnalisation qui peut comprendre plusieurs règles dont la syntaxe de base1 est fournie par le tableau 12.11.

1. Pour la syntaxe complète, voir .

328

Chapitre 12. Internationalisation des logiciels

Tableau 12.11 – Syntaxe de base des règles de tri Symbole Exemple

Description