Unicode et encodage des caractères : pourquoi votre application casse dans d'autres langues
Unicode dans les applications métier : comment « José » devient « José », pourquoi cela arrive et ce qu'exige l'UTF-8 en production.


Unicode est la norme qui attribue à chaque caractère, qu’il s’agisse de « A », de « あ » ou de « 🚀 », un identifiant unique. Ce standard associe ainsi un numéro, appelé point de code, aux caractères d’un répertoire, tandis que l’encodage définit la manière de représenter ces valeurs sous forme d’octets (W3C). L’encodage des caractères est l’étape distincte qui convertit ces numéros en octets exploitables par un ordinateur. La plupart des logiciels qui « plantent dans d’autres langues » ne butent pas sur la traduction, mais sur cette couche invisible en amont. Leur échec porte un nom : le *mojibake*, ce texte illisible obtenu lorsque des octets sont interprétés avec le mauvais encodage.
Nous avions annoncé une analyse détaillée de ces échecs dans le développement de logiciels multilingues et dans l’internationalisation (i18n), expliquée ici, où un client nommé José se transforme en « José » sur une étiquette ou une facture. Voici l’explication concrète de ce phénomène, les situations où ces bugs d’encodage coûtent réellement de l’argent à une entreprise, et ce que signifie vraiment « UTF-8 partout » dans un système opérationnel.
Unicode et UTF-8 : deux notions distinctes
Ces deux termes sont souvent employés l’un pour l’autre, et c’est là que réside l’essentiel de la confusion.
Unicode est une table de correspondance. Il attribue à chaque caractère un point de code, un numéro noté U+XXXX. La lettre « A » correspond à U+0041, le sinogramme « 中 » à U+4E2D. Mais cette table ne précise pas comment stocker ce numéro sur un disque ni comment le transmettre via un réseau.
UTF-8 est un encodage qui traduit ces points de code en octets. C’est l’encodage dominant sur le Web : selon W3Techs, il équipe 99,0 % des sites dont l’encodage est déclaré, d’après un relevé quotidien actualisé au 20 août 2026. Cette mesure concerne le Web et ne reflète pas nécessairement les applications métier, les bases de données ou les logiciels hors ligne. UTF-8 représente chaque point de code sur 1 à 4 octets : les lettres et chiffres non accentués tiennent sur 1 octet (identique à l’ancien ASCII, d’où sa rétrocompatibilité), les caractères latins accentués, l’essentiel d’un texte en français, en occupent généralement 2, la plupart des sinogrammes, kanjis et hanguls en nécessitent 3, et les emojis 4.
Les encodages plus anciens associent les mêmes valeurs d’octets à des caractères radicalement différents. Windows-1252 et Latin-1 (ISO-8859-1), fréquents sur les anciens systèmes Windows et les bases de données héritées, utilisent un seul octet par caractère et se limitent aux écritures d’Europe occidentale. Si l’on soumet des octets UTF-8 à un logiciel attendant du Windows-1252, ou inversement, le résultat semble valide… mais est en réalité faux. Ce décalage, c’est le *mojibake* : rien n’est « corrompu » au sens de données perdues, les mêmes octets sont simplement lus avec le mauvais jeu de règles.
Le *mojibake* décrypté : comment « José » devient « José »
Décortiquons les octets pour dissiper le mystère.
En UTF-8, le caractère « é » s’écrit sur deux octets : 0xC3 0xA9. « José » en UTF-8 correspond donc à la séquence d’octets pour J, o, s, puis 0xC3 0xA9, suivis du caractère de fin.
Imaginons maintenant que cette séquence soit lue comme du Windows-1252 au lieu d’UTF-8, un cas fréquent lorsque des données transitent entre des composants configurés différemment, notamment avec des systèmes anciens. Windows-1252 ignore que ces deux octets forment un seul caractère : il les interprète comme deux caractères distincts : 0xC3 donne « à » et 0xA9 donne « © ». Le « é » unique se transforme ainsi en « é », et « José » devient « José » à l’écran, sur une étiquette ou une facture. Ce résultat illustre un mauvais décodage : les mêmes octets sont interprétés selon une autre table, ce qui peut rendre le texte illisible ou erroné (W3C).
Le même mécanisme explique tous les autres *mojibake* que vous avez pu rencontrer : des guillemets typographiques qui se muent en chaînes comme “ ou â€\x9d, ou un tiret long qui devient â€". Chaque cas résulte de la lecture d’octets d’un encodage à travers le filtre d’un autre. Une fois les deux encodages en cause identifiés, la correction peut parfois se limiter à une simple reconfiguration, mais elle peut aussi exiger une conversion des données, une migration ou une modification du code, selon l’endroit où le décalage s’est produit.
Où les bugs d’encodage coûtent vraiment cher à une entreprise
Le *mojibake* à l’écran n’est que la partie visible de l’iceberg, et le français, riche en accents, le révèle plus rapidement que d’autres langues. Les échecs les plus coûteux se nichent ailleurs.
- Des noms déformés sur des documents clients. Étiquettes d’expédition, factures ou contrats où le nom d’un client apparaît sous la forme « José » au lieu de « José » donnent une impression de négligence, au mieux. Au pire, ils compliquent le contrôle ou le traitement des adresses, notamment dans les documents douaniers et données transporteurs de la logistique, où un nom ou une adresse doit correspondre exactement à un registre officiel.
- Des recherches et requêtes inopérantes. Si un nom est stocké dans un encodage et recherché dans un autre, les séquences d’octets ne coïncident pas, et une fiche client pourtant existante ne renvoie aucun résultat. Les équipes de support contournent souvent le problème manuellement bien avant qu’un diagnostic d’encodage ne soit posé.
- Des données tronquées en silence. Une colonne de base de données dimensionnée en octets plutôt qu’en caractères peut couper un caractère multi-octets en deux lors de l’insertion, corrompant le dernier caractère d’un nom ou laissant une séquence d’octets invalide, qui échouera plus tard à la validation, souvent dans une autre partie du système.
- Des emojis et caractères CJK qui disparaissent purement et simplement. Le jeu de caractères historiquement nommé
utf8dans MySQL ne stockait que 3 octets par caractère au maximum, suffisant pour la plupart des caractères latins, cyrilliques et CJK courants, mais pas pour les emojis ni certains caractères CJK étendus, qui en nécessitent 4. Depuis MySQL 8.0,utf8est un alias déprécié deutf8mb3, limité à trois octets ;utf8mb4, lui, gère jusqu’à quatre octets et les caractères supplémentaires (Oracle MySQL). Selon la version de MySQL, le mode SQL et la gestion des erreurs par l’application, le texte concerné peut être rejeté, remplacé ou perdre des informations, tant que l’option complète UTF-8 de MySQL,utf8mb4, n’est pas utilisée. - Des exports hérités qui contaminent les systèmes modernes. Un fichier CSV ou un flux EDI provenant d’un ancien ERP ou d’un partenaire, encore configuré par défaut en Windows-1252, peut sembler s’importer correctement au premier abord, l’ampleur des dégâts dépendant de l’outil d’import et de ses paramètres, avant de révéler des caractères accentués mal interprétés dès qu’il est ouvert dans un outil natif UTF-8.
Le piège spécifique aux équipes francophones est plus subtil qu’il n’y paraît. Le français, lui, passe : Latin-1 et Windows-1252 couvrent é, è, à, ç et consorts, si bien qu’une application franco-française peut tourner des années sur un encodage hérité sans que personne ne s’en aperçoive. La facture arrive au premier client nommé Wojciech, Öztürk ou 田中, au premier fournisseur envoyant un flux en cyrillique, ou au premier emoji dans un champ de commentaire. Ces bugs d’encodage surgissent souvent tardivement, une fois que les données de production intègrent plus de langues, de caractères ou de flux partenaires que les jeux de test.
Les encodages hérités qui posent encore problème
ASCII pur, Latin-1/ISO-8859-1 et Windows-1252 figurent parmi les encodages hérités les plus fréquents dans les systèmes métier, sans pour autant couvrir tous les cas de figure : ASCII pur (lettres anglaises, chiffres et ponctuation de base uniquement, sans accents ni caractères non latins), Latin-1/ISO-8859-1 (un octet par caractère, accents d’Europe occidentale uniquement) et Windows-1252 (le quasi-sur-ensemble de Latin-1 de Microsoft, par défaut sur les anciens logiciels Windows et responsable du *mojibake* des guillemets typographiques évoqué plus haut).
Latin-1 mérite une mention particulière pour le français, car il ne le couvre pas entièrement. Il lui manque la ligature « œ » et le symbole « € », deux caractères difficiles à éviter sur un devis ou un catalogue. C’est précisément pour cela qu’a été créé Latin-9 (ISO-8859-15), une révision qui les intègre. Un système hérité qui transforme le « œ » d’« œuvre » en un caractère fantôme ou remplace « € » par « EUR » ne fait pas une faute de frappe : il trahit son encodage.
Ces encodages persistent dans des recoins prévisibles : des bases de données créées il y a des années avec un jeu de caractères par défaut jamais revu, des exports CSV issus de vieux systèmes comptables ou d’ERP, des messages EDI de partenaires logistiques ou de fret fonctionnant sur des formats vieux de plusieurs décennies, et des bibliothèques de génération de PDF supposant un jeu de caractères restreint en l’absence de consigne contraire. Chacun de ces points est une frontière où les données passent d’un système à un autre, et c’est précisément là que les hypothèses d’encodage, souvent implicites, entrent en conflit.
Ce que signifie vraiment « UTF-8 partout »
« Utilisez UTF-8, un point c’est tout » est un conseil pertinent, mais qui minimise l’effort nécessaire. Un support UTF-8 complet exige de le déclarer explicitement à chaque couche, sans supposer qu’il se propagera de lui-même. La déclaration seule ne suffit pas : le texte doit aussi être enregistré dans l’encodage annoncé, et les différents composants du système doivent pouvoir communiquer sans ambiguïté (W3C).
- Jeu de caractères et collation de la base de données. UTF-8 doit être déclaré au niveau de la base, de chaque table et de chaque colonne, et pas seulement sur la connexion. Sur MySQL, cela signifie
utf8mb4, et non l’alias héritéutf8. - En-têtes HTTP et fichiers. Chaque réponse d’API et chaque export de fichier doit annoncer son encodage explicitement (
Content-Type: text/html; charset=utf-8), plutôt que de laisser les clients deviner. - Des exports CSV avec BOM quand Excel est la cible. Excel interprète souvent un CSV UTF-8 sans indicateur d’ordre des octets (BOM) comme du Windows-1252, un problème récurrent lors de l’ouverture de fichiers UTF-8 dans certaines versions d’Excel si l’encodage n’est pas détecté correctement.
- Couverture des glyphes par la police. Un caractère cyrillique ou CJK correctement encodé peut malgré tout s’afficher sous forme de carré vide (« tofu ») si la police utilisée ne contient pas le glyphe correspondant. Un encodage correct ne garantit donc pas un affichage parfait : si la police manque de glyphes, l’utilisateur verra un carré ou un caractère de remplacement (W3C). Il s’agit d’un problème de design, pas d’encodage, mais pour l’utilisateur, le résultat est le même.
- Validation à chaque frontière. Les téléversements, les entrées d’API et les flux de données partenaires doivent voir leur encodage vérifié et normalisé en UTF-8 à l’entrée, pour éviter que des octets mal interprétés ne contaminent le stockage.
Prendre en compte ces cinq points au niveau de l’architecture réduit considérablement les risques de problèmes d’encodage, sans pour autant dispenser de tests de bout en bout, de la surveillance des flux et de la gestion des cas particuliers. En négliger un seul, et il resurgira sous forme de ticket de support à chaque fois qu’un nom accentué, un emoji ou un caractère non latin franchira cette frontière.
Questions fréquentes sur Unicode et l’encodage des caractères
Qu’est-ce qu’Unicode ?
Unicode est un standard qui attribue un numéro unique, appelé point de code, à chaque caractère des principaux systèmes d’écriture. C’est une table de correspondance entre caractères et numéros, mais il ne définit pas comment ces numéros sont stockés en octets.
Quelle est la différence entre Unicode et UTF-8 ?
Unicode est la table des caractères ; UTF-8 est un encodage qui convertit les points de code Unicode en octets, sur 1 à 4 octets par caractère. UTF-8 est l’encodage dominant sur le Web : selon W3Techs, il équipe 99,0 % des sites dont l’encodage est connu, une mesure qui concerne le Web et ne s’étend pas nécessairement aux applications métier.
Qu’est-ce que le *mojibake* ?
Le *mojibake* est le texte illisible obtenu lorsque des octets encodés dans un jeu de caractères sont interprétés avec un autre. Ce n’est pas un phénomène aléatoire : le même décalage d’encodage produit toujours le même motif brouillé, comme « José » transformé en « José ».
Pourquoi mon logiciel affiche-t-il des caractères bizarres comme « é » à la place des lettres accentuées ?
Un composant du système, souvent une base de données, un outil d’export ou un flux partenaire ancien, interprète des octets UTF-8 comme du Windows-1252 ou du Latin-1. La correction consiste à identifier où se produit le décalage : parfois, il suffit de configurer ce composant explicitement en UTF-8, mais une conversion ou une migration des données peut aussi s’avérer nécessaire.
Comment corriger les problèmes d’encodage dans un logiciel existant ?
Auditez chaque frontière : jeu de caractères et collation de la base de données, exports de fichiers, en-têtes d’API et flux de données partenaires, et configurez chacun explicitement en UTF-8 (utf8mb4 si la base est MySQL). Nous réalisons cet audit lors de la phase de cadrage de chaque projet multilingue : demandez un devis à prix fixe, il est inclus.
Un logiciel qui gère correctement tous les caractères
Dites-nous quels noms, écritures et flux de données votre logiciel doit prendre en charge sans erreur. Nous vous proposerons un périmètre précis, un prix fixe et une date de livraison.

À lire ensuite
Besoin d’un logiciel qui parle tous vos marchés dès le premier jour ?
Dites-nous ce que vous voulez faire construire. Nous répondons avec un périmètre fixe, un prix fixe et une date de livraison en semaines.
