QR code et accents : UTF-8, ECI et caractères non latins — featured illustration
Technologie

QR code et accents : UTF-8, ECI et caractères non latins

5 min de lecture
Créer un QR code

Un café commande des cartons de table avec un menu en turc encodé directement dans le code. Sur l'ordinateur de la graphiste, l'aperçu est impeccable. Sur le téléphone d'un client, le même code affiche « Kahvaltı Menüsü ». Le code n'est pas cassé : le téléphone a simplement lu les octets avec la mauvaise table de caractères.

L'impression est nette. La correction d'erreurs ne s'est jamais déclenchée. Les octets sont arrivés exactement tels qu'encodés, puis ont été lus avec le mauvais dictionnaire.

Un QR code stocke des octets, pas des lettres

La symbologie définit quatre façons de tasser les données dans la grille, et elles sont choisies pour la densité, pas pour la langue.

  • Le mode numérique tasse trois chiffres dans dix bits.
  • Le mode alphanumérique tasse deux caractères dans onze bits, avec un jeu restreint de chiffres, de majuscules et d'une poignée de symboles.
  • Le mode octet stocke des valeurs brutes de huit bits, un octet à la fois.
  • Le mode kanji stocke les caractères japonais à double octet en environ treize bits chacun, contre les seize que le même caractère consommerait en mode octet.

Tout ce qui sort des jeux numérique et alphanumérique atterrit en mode octet, et c'est là que finit toute écriture non latine. Le mode octet est honnête sur ce qu'il est : un conteneur d'octets. Il ne porte aucune déclaration native indiquant que ces octets sont du turc, du grec ou autre chose. Les écarts de densité entre modes expliquent pourquoi la capacité varie tant selon le type de contenu, comme détaillé dans combien de données contient un QR code.

L'hypothèse par défaut que personne n'a déclarée

La spécification définit pour le mode octet une interprétation par défaut bâtie autour d'un jeu de caractères latin sur un octet. La plupart des encodeurs modernes écrivent quand même de l'UTF-8, parce que c'est ce qui fait tourner le reste du web, et la plupart des décodeurs modernes détectent l'UTF-8 quand le motif d'octets ressemble à de l'UTF-8 valide. Cette détection marche en général, et « en général » est tout le problème.

Le charabia apparaît quand des séquences UTF-8 multi-octets sont lues octet par octet à travers une table sur un octet. Un i sans point turc ou un tréma devient deux caractères visibles au lieu d'un. Les paires ı et ü du menu ci-dessus sont exactement la signature de ce décalage. Le cyrillique se dégrade plutôt en chaînes de caractères Ð et Ñ, ce qui est le même défaut sous un autre costume.

Ce qu'apporte l'ECI

L'Extended Channel Interpretation est le mécanisme que la norme fournit pour supprimer la devinette. Un désignateur ECI est écrit dans le flux de données avant la charge utile, et porte un numéro d'attribution identifiant le jeu de caractères auquel appartiennent les octets suivants. L'UTF-8 a son propre numéro dans ce registre, le 26. Un décodeur qui comprend le désignateur cesse de deviner et applique le jeu déclaré.

Le support varie. Certains lecteurs honorent le désignateur, d'autres l'ignorent et retombent sur leur propre détection, et le comportement des encodeurs diffère aussi, puisque tous les générateurs n'émettent pas de désignateur. Vous ne pouvez pas contrôler quel lecteur tourne sur le téléphone d'un inconnu : considérez donc l'ECI comme améliorant les chances, pas comme une garantie.

Les URL contournent tout le problème

La syntaxe des URL restreint ce qui peut figurer dans une adresse à un sous-ensemble d'ASCII. Tout le reste est encodé en pourcentage, c'est-à-dire que chaque octet non ASCII devient un signe pourcentage et deux chiffres hexadécimaux. Les noms de domaine non latins passent par un encodage compatible ASCII distinct qui les transforme en une forme préfixée par xn--.

Le résultat est une charge utile faite entièrement de caractères qui survivent à n'importe quelle hypothèse de jeu de caractères d'un décodeur. C'est l'argument pratique le plus fort en faveur de l'URL plutôt que du texte brut dans un code imprimé, et il vaut tout autant pour les astuces de routage décrites dans les expériences QR multilingues.

Une mise en garde : copiez la forme encodée, pas la jolie. Les barres d'adresse affichent souvent la version lisible d'un chemin tout en conservant la version encodée dessous, et coller ce que l'on voit plutôt que ce qui est stocké réintroduit des octets bruts dans la charge utile.

Le texte brut et les cartes de contact, c'est là que ça casse

Deux types de charge utile concentrent l'essentiel des plaintes réelles.

Une charge utile texte est faite d'octets sans enveloppe de protocole autour, donc rien ne déclare d'encodage et rien ne corrige une mauvaise hypothèse. Ce que le scanner décide est ce que l'utilisateur lit.

Une carte de contact ajoute une seconde couche de risque. Le décodeur QR interprète les octets, puis l'importateur de contacts du téléphone analyse les champs vCard et les transmet au carnet d'adresses. La gestion des jeux de caractères par le format vCard a bougé d'une version à l'autre, si bien qu'une application peut décoder correctement les octets et écrire malgré tout un nom déformé dans la fiche. Les noms portent le risque le plus élevé, car c'est là que vivent les caractères propres à chaque écriture : i turc pointé et sans point, schwa azerbaïdjanais, textes arabe et hébreu qui dépendent en plus de l'application réceptrice pour l'affichage de droite à gauche.

Deux téléphones, avant le passage en presse

Les fautes d'encodage coûtent peu à détecter et cher à réimprimer : testez plutôt que de raisonner.

  • Scannez avec l'appareil photo natif d'un iPhone et d'un appareil Android. Ces deux chemins couvrent la majorité des scans réels.
  • Ajoutez au moins une application de scan tierce, plus tout scanner intégré à une application que votre public risque d'utiliser.
  • Testez la plus longue chaîne que vous comptez encoder, pas un échantillon court. Troncatures et fautes d'encodage se manifestent toutes deux plutôt en fin de chaîne.
  • Lisez le résultat entier, y compris le dernier caractère. Une corruption partielle au milieu d'une chaîne se survole facilement.

Et en France ?

Le français a un caractère piège que beaucoup d'outils oublient : le « œ », comme dans cœur, œuvre ou sœur. Il n'existe pas dans l'ancienne norme ISO 8859-1 (Latin-1), que certains lecteurs appliquent encore par défaut quand un code ne précise rien. Un « œuf » peut alors devenir un point d'interrogation ou un couple de symboles étranges.

La parade : encodez le texte en UTF-8 et vérifiez-le sur plusieurs téléphones avant d'imprimer, surtout pour une vCard avec des noms comme Hélène, François ou Cœurdevey. Pour un menu ou un long texte, la solution la plus sûre reste une page web vers laquelle pointe le code.

Le repli qu'il vaut mieux adopter par défaut

Si un lecteur abîme votre texte non latin, ne cherchez pas le bon réglage : arrêtez de lui confier le texte. Publiez-le sur une page web et encodez seulement l'adresse de cette page ; le navigateur, lui, sait afficher toutes les langues.

La page déclare son encodage dans les en-têtes de réponse et dans le document lui-même, le navigateur est un moteur de rendu de texte bien plus capable que l'écran de résultat d'un scanner, et la mise en page de droite à gauche devient du CSS au lieu d'une supposition. Rendez le code dynamique et une coquille devient une modification au lieu d'une réimpression, et le même symbole peut servir une langue différente selon qui a scanné.

Le coût, c'est un aller-retour réseau et une dépendance à un hébergement que vous contrôlez. Pour tout ce qui est imprimé en volume dans une écriture autre que le latin simple, c'est en général le bon prix.

Partager cet article