Intermédiaire 8 min de lecture 25 janvier 2025

zero width non joiner (ZWNJ) : comprendre et éviter les pièges

Tout a l’air normal, mais une comparaison échoue, un slug casse, un texte arabe ne forme plus ses ligatures. Derrière ces comportements, le zero width non joiner se cache souvent. Invisible à l’écran, il change pourtant la logique du texte. Voici comment il intervient, pourquoi il complique vos traitements et comment le repérer.

Qu'est-ce que le zero width non joiner (ZWNJ) ?

C’est un caractère Unicode de largeur nulle (U+200C) qui empêche la jonction typographique entre deux lettres adjacentes.

L’essentiel à connaître autour du zero width non joiner et des caractères voisins :

1 ZWNJ en bref

Empêche la ligature ou la jonction sans afficher d’espace.

ZWNJ (U+200C) - Zero Width Non-Joiner

2 ZWNJ vs ZWJ

Le ZWJ (U+200D) force la jonction, le ZWNJ (U+200C) la bloque.

ZWJ (U+200D) ↔ ZWNJ (U+200C) : effets opposés

3 Caractères proches du ZWNJ

Souvent confondus ou rencontrés ensemble :

ZWSP (U+200B) - Zero Width Space
ZWJ (U+200D) - Zero Width Joiner
SHY (U+00AD) - Soft Hyphen
NBSP (U+00A0) - Espace insécable

4 Contextes d’apparition

Là où le ZWNJ se glisse facilement :

Claviers persan/ourdou/arabes qui insèrent U+200C
Copier-coller depuis le web ou des PDFs
Normalisations/exports qui conservent U+200C
Éditeurs affichant mal les caractères zéro largeur

Problèmes classiques

Copier-coller depuis le web ou Word

Introduit un ZWNJ invisible dans des identifiants, slugs ou champs texte.

Tests unitaires qui échouent

Une chaîne contient un U+200C imperceptible qui casse les égalités strictes.

Trim() ou strip() inefficace

ZWNJ n’est pas un espace : les trims classiques ne l’enlèvent pas.

Regex \s ou \w incomplètes

Le ZWNJ n’est ni mot ni espace : segmentation, slugs et \b se comportent différemment.

Exemple de problème courant :

# Deux chaînes visuellement identiques diffèrent
string1 = "username"
string2 = "user‌name" # Contient U+200C entre r et n
assert string1 == string2 # ❌ Échec

Symptômes qui doivent vous alerter

🚨 Signaux d'alarme

!
Un diff git montre des changements invisibles au milieu d’un mot (U+200C)
!
Un slug/URL diffère entre environnements sans raison apparente
!
Un système de connexion refuse un identifiant copié-collé mais accepte une saisie manuelle
!
Les ligatures en arabe/persan ne se forment pas là où elles devraient
!
Un copier-coller dans un terminal produit une commande invalide sans caractère visible

Comment les détecter

Solution recommandée : Clean ASCII

Clean ASCII identifie précisément le zero width non joiner (U+200C) et les autres caractères zéro largeur. L’analyse se fait en temps réel avec les positions et libellés utiles pour corriger rapidement vos données.

✅ Détection automatique

ZWNJ, ZWJ, ZWSP, soft hyphens, caractères de contrôle

📊 Analyse complète

Codes Unicode, positions exactes, explications d’usage

🧹 Nettoyage automatique

Suppression ou remplacement intelligent des U+200C hors contexte

💾 Export propre

Téléchargement du texte corrigé prêt pour la prod

Autres méthodes de détection

Affichage dans l'éditeur

Activez l’affichage des espaces invisibles et des caractères zéro largeur
Installez un linter qui signale explicitement U+200C

En ligne de commande (Unix)

# Rechercher explicitement U+200C (ZWNJ)
grep -nP "\x{200C}" fichier.txt
# Visualiser les fins de ligne et caractères spéciaux
sed -n l fichier.txt
# Afficher les caractères de contrôle et zéro largeur
cat -A fichier.txt
# Vérifier les octets hexadécimaux (200c)
hexdump -C fichier.txt

En code

JavaScript

Array.from(str).reduce((a,c,i)=>c==='\u200C'?[...a,i]:a,[])

Python

[i for i, c in enumerate(s) if ord(c) == 0x200C]

Excel / Google Sheets

CODE(MID(cellule;position;1)) = 8204

Nettoyer et prévenir

🚀 Solution rapide avec Clean ASCII

Avant de coder des filtres, passez votre texte dans Clean ASCII pour supprimer ou marquer le ZWNJ en un clic :

Détection du ZWNJ
Nettoyage ciblé
Export immédiat

Méthodes techniques avancées

🔧 Normaliser

Uniformisez en NFC/NFKC puis gérez explicitement U+200C
Retirez le ZWNJ quand il n’a pas de rôle typographique attendu
Harmonisez les fins de ligne (dos2unix, gitattributes)

🧹 Filtrer

Écrivez des fonctions trim_zwnj() qui retirent U+200C en bordure ou en plein texte
Remplacez U+200C par un espace simple uniquement si le contexte l’exige
Bloquez les caractères zéro largeur dans les formulaires sauf besoin explicite

⚙️ Automatiser

Hooks pre-commit pour refuser des fichiers contenant U+200C non attendu
Tests qui valident l’absence de ZWNJ dans les identifiants/URLs
Linting en CI avec recherche de \x{200C}

Checklist rapide

Fichiers en UTF-8 sans BOM et sans U+200C parasite
Fins de ligne uniformes via gitattributes
Outil affichant les caractères zéro largeur dans l’éditeur
Fonction de suppression ZWNJ dans vos libs de sanitation
Tests vérifiant l’absence d’U+200C dans slugs/identifiants
Documentation devs sur ZWNJ, ZWJ et saisies multi-langues

Conclusion

Le zero width non joiner est discret mais déterminant. En contrôle qualité comme en production, le traiter réduit nettement les erreurs sournoises.

Mettez en place une détection systématique d’U+200C, normalisez vos flux et éliminez-le hors contexte typographique. Vous éviterez une grande partie des surprises liées au texte.

Détectez le zero width non joiner maintenant

Utilisez notre outil pour repérer et nettoyer U+200C dans vos textes, fichiers et copies collées.

Analyser mon texte