Intermédiaire 7 min de lecture 25 janvier 2025

ZWNJ (Zero Width Non-Joiner) : problèmes courants et solutions

Tout semble normal, mais une comparaison échoue, un slug casse, une recherche ne trouve rien. ZWNJ (Zero Width Non‑Joiner) est invisible à l'œil nu, pourtant il change la façon dont les caractères se lient. Voici ce que c'est, pourquoi il se glisse dans vos données et comment l'attraper avant qu'il ne cause des bugs.

Qu'est-ce que ZWNJ ?

ZWNJ est un caractère Unicode de format (U+200C) qui empêche la jonction typographique entre deux lettres, sans afficher de symbole.

Les points essentiels à connaître pour travailler avec ZWNJ :

1 Définition et encodage

Empêche une ligature/jonction sans introduire d'espace visible.

ZWNJ — U+200C — UTF-8: E2 80 8C — Catégorie: Cf (Format)

2 Rôle dans les écritures liées

Utilisé notamment en persan, ourdou, arabe ou devanagari pour casser une ligature.

Empêche la liaison typographique entre lettres adjacentes

3 Cousins à ne pas confondre

Plusieurs caractères zero-width se ressemblent mais n'ont pas le même effet :

ZWJ (U+200D) - Zero Width Joiner
ZWSP (U+200B) - Zero Width Space
BOM/ZWNBSP (U+FEFF) - Byte Order Mark
NBSP (U+00A0) - Espace insécable

4 Sources d'introduction fréquentes

Copier-coller, claviers multilingues, normalisation ou éditeurs :

Claviers mobiles pour langues liées
Collage depuis pages multilingues
Nettoyage incomplet et conversions

Problèmes classiques

Copier-coller depuis le web ou Word

Insère des ZWNJ invisibles dans des identifiants, des slugs ou du code.

Tests unitaires qui échouent

Une chaîne contient un U+200C invisible, la comparaison stricte échoue.

Trim() ou strip() inefficace

ZWNJ n'est pas un espace ; il reste après les nettoyages basiques.

Regex \s ou \w incomplètes

ZWNJ est un caractère de format : ni \s ni \w ne le couvrent toujours selon les moteurs.

Exemple de problème courant :

# Données qui semblent identiques mais ne le sont pas
string1 = "email@domain.com"
string2 = "email@domain.com‌" # Contient U+200C (ZWNJ) à la fin
assert string1 == string2 # ❌ Échec

Symptômes qui doivent vous alerter

🚨 Signaux d'alarme

!
Un diff git montre des changements invisibles après un simple copier-coller
!
Des split() ou un parser JSON/CSV se comportent de manière incohérente
!
Une clé .env, un login ou un slug ne correspond pas malgré un visuel identique
!
Le curseur se déplace de façon étrange au milieu d'un mot sans raison apparente
!
Une commande collée dans un terminal n'est pas reconnue à cause d'un ZWNJ caché

Comment les détecter

Solution recommandée : Clean ASCII

Clean ASCII repère instantanément ZWNJ et les autres caractères zéro largeur. Il met en évidence U+200C, indique l'emplacement précis et propose des remplacements adaptés.

✅ Détection automatique

ZWNJ, ZWJ, ZWSP, NBSP, BOM, caractères de contrôle

📊 Analyse complète

Code Unicode, positions exactes, impact sur la jonction/ligature

🧹 Nettoyage automatique

Suppression de ZWNJ indésirables, conversions sûres

💾 Export propre

Téléchargement du texte corrigé prêt à intégrer

Autres méthodes de détection

Affichage dans l'éditeur

Activez "show invisibles" / "render whitespace & zero-width" dans VS Code, JetBrains, Sublime
Installez une extension qui surligne ZWNJ (U+200C) et ZWJ

En ligne de commande (Unix)

# Repérer explicitement ZWNJ (U+200C)
grep -P "\x{200C}" fichier.txt
# Voir les fins de ligne et tabulations
sed -n l fichier.txt
# Afficher les caractères de contrôle/format
cat -A fichier.txt
# Inspecter les octets (ZWNJ = E2 80 8C)
hexdump -C fichier.txt

En code

JavaScript

const cleaned = str.replace(/\u200C/g, "")

Python

cleaned = s.replace("\u200C", "")

Excel / Google Sheets

SUBSTITUE(A1;CAR(8204);"")

Nettoyer et prévenir

🚀 Solution rapide avec Clean ASCII

Avant d'écrire des scripts, utilisez Clean ASCII pour supprimer immédiatement les ZWNJ indésirables.

Détection ZWNJ ciblée
Nettoyage sécurisé
Export immédiat

Méthodes techniques avancées

🔧 Normaliser

Appliquez NFC/NFKC pour homogénéiser, puis gérez ZWNJ explicitement
Supprimez ZWNJ hors contextes typographiques légitimes
Uniformisez les fins de ligne (dos2unix, gitattributes)

🧹 Filtrer

Écrivez une fonction remove_cf() qui retire les caractères de format (dont U+200C)
Remplacez ZWNJ par rien ou par un espace selon le besoin métier
Bloquez les caractères zero-width à l'entrée utilisateur

⚙️ Automatiser

Hooks pre-commit qui refusent les fichiers contenant U+200C
Tests d'assainissement sur les entrées et formulaires
Linting Unicode dans la CI pour détecter les caractères zero-width

Checklist rapide

Fichiers en UTF-8 sans BOM et sans ZWNJ caché
Fins de ligne uniformes via gitattributes
Affichage des caractères zéro largeur dans l'éditeur
Fonction de suppression des caractères de format (U+200C, U+200D, etc.)
Tests garantissant l'absence de ZWNJ indésirables dans les clés/IDs
Documentation pour l'équipe sur ZWNJ et les caractères zero-width

Conclusion

ZWNJ est minuscule mais impactant. Une simple présence peut changer un rendu, casser un tri ou briser une égalité.

Mettez en place une détection systématique, retirez ZWNJ lorsqu'il n'est pas intentionnel et réduisez drastiquement les bugs invisibles.

Détectez ZWNJ (U+200C) maintenant

Utilisez notre outil pour repérer et nettoyer les ZWNJ dans vos textes et vos données.

Analyser mon texte