Slug d’une chaîne de caractères non ASCII avec Django et unidecode


Une slug est une chaîne de caractère ASCII en minuscule, sans espace, ponctuation, ni caractères spéciaux, qu’on utilise souvent dans les URLs ou les noms de ficher pour en simplifier l’analyse informatique.

Par exemple, le titre de cet article est Slug d’une chaîne de caractères non ASCII avec Django et unidecode, mais si vous regardez dans la barre d’adresse de votre navigateur, vous remarquerez qu’on le retrouve sous la forme slug-dune-chaine-de-caracteres-non-ascii-avec-django-et-unidecode. C’est le slug du titre de l’article.

Django possède un filter slugify et un SlugField qui sont censés nous faciliter la vie quand on a besoin de générer un slug :

>>> slugify(u"Slug d'une chaîne de caractères non ASCII avec Django et unidecode")
>>> u'slug-dune-chaine-de-caracteres-non-ascii-avec-django-et-unidecode'

Sous le capot, ça utilise le module standard unicodedata :

>>> import unicodedata
>>> unicodedata.normalize('NFKD', u"éêèçàùï").encode('ascii', 'ignore')
>>> 'eeecaui'

Problème, unicodedata ne fonctionne qu’avec des caractères dérivés de l’alphabet latin. Essayez avec du chinois ou de l’arabe, ça ne marche pas. Petit exemple avec du Hongrois et son alphabet cyrillique :

>>> unicodedata.normalize('NFKD', u"Сайн уу").encode('ascii', 'ignore')
>>> ' '

Il existe deux solutions. La première est proposée par Mozilla : elle retourne un slug unicode, et présuppose que vous voulez créer des urls unicodes.

La seconde, qui nous intéresse, est une tout petite library pip installable : unidecode.

>>> unidecode.unidecode(u"北亰")
>>> 'Bei Jing '
>>> unidecode.unidecode(u"Сайн уу")
>>> 'Sain uu'
>>> unidecode.unidecode(u"éùïàô")
>>> 'euiao'

Du coup, pour le slugify :

In [52]: slugify(unidecode.unidecode(u"Сайн уу"))
Out[52]: u'sain-uu'

3 thoughts on “Slug d’une chaîne de caractères non ASCII avec Django et unidecode

  • mac

    unidecode.unidecode(u”للمقبولين لاجتياز”)
    sa donne ça llmqbwlyn ljtyz au lieu de ça للمقبولين لاجتياز

  • Sam Post author

    Il y a une limite a ce qu’il est possible de faire.

    Le but est de transformer un text unicode en une représentation ASCII proche dans la phonétique ou l’intention.

    Dans le cas d’un bout de phrase en arabe, il n’y a pas le context suffisant pour permettre une conversion. Ca n’aurait pas de sens.

    Je ne vois vraiment pas comment on pourrait faire un slug ASCII sur la langue arabe sans avoir un traducteur humain ou une base de données d’équivalence phonétique (ce qui alors n’aurait aucune valeur sémantique). Heureusement, les URLs peuvent maintenant contenir des caractères non ASCII, et dans quelques années le support sera suffisant pour que tout le monde arabe puisse utiliser leur langue dans les URLs.

Comments are closed.

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.