Bonjour,
Dans le tutoriel de Spacefox sur l’internationalisation, on trouve ce passage (Tout ce qui vient avec une langue mais qui n’était pas prévu):
On ne supprime jamais les diacritiques. Il n’y a plus de raison de faire ça
Si votre crainte (légitime) est qu’un utilisateur abuse de votre largesse en employant des caractères différents, mais visuellement identiques (comme les Α grec, А cyrillique et A latins), ce n’est pas un problème de diacritique, mais d’homoglyphes et Unicode fournit les outils pour les résoudre.
Ce que le tutoriel ne dit pas, c’est comment on fait concrètement ?
Je réfléchis éventuellement à autoriser des pseudos avec des caractères non ASCII, non latins, mais je ne trouve pas comment faire concrètement pour éviter que plusieurs utilisateurs choisissent des noms trop ressemblants.
Le principe de base est, lors de l’inscription d’un nouveau pseudo, de comparer avec des versions normalisées des pseudos existants. Comment construit-on cette forme normalisée ? C’est là toute la question, c’est là que j’ai du mal à trouver comment faire, même en demandant gentiment à mon moteur de recherche favori. J’ai quelque pistes partielles, mais rien de complet…
En premier lieu, j’aimerais fixer quelques règles de base:
- J’accepte donc des pseudos en lettres latines, cyrillique, grec, arabe, etc. Mais pas de mélange d’alphabet dans un même pseudo. Ainsi "ABC", "ΑΒΓ" et "АБВ" sont acceptables, mais pas "ΑΒC". Je pense que ça limitera pas mal d’abus.
- Je suis d’accord d’accepter des lettres et des chiffres, mais pas non plus n’importe quel caractère Unicode. Par exemple je ne veux pas d’émojis parce que les gens font vraiment n’importe quoi avec, ni de symboles de maths, de chiffres entourés et autres qui n’ont, de mon point de vue, rien à faire dans un pseudo. Un pseudo est un nom, pas une oeuvre artistique; et c’est aussi probablement une potentielle possibilité d’attaque.
Première bonne nouvelle, la méthode toLowerCase a l’air de fonctionner correctement:
jshell> "AΑА" .toLowerCase()
"aαа"
Du côté de la suppression des accents, parce qu’il va quand même falloir le faire, j’ai trouvé une méthode qui est censée être générique:
public static String unaccent (String s) {
s = Normalizer.normalize(s, Normalizer.Form.NFD);
StringBuilder sb = new StringBuilder();
s.codePoints() //
.filter(c -> {
int t = Character.getType(c);
return t!=Character.NON_SPACING_MARK && t!=Character.ENCLOSING_MARK && t!=Character.COMBINING_SPACING_MARK;
})
.forEach(sb::appendCodePoint);
return sb.toString();
}
jshell> unaccent("Ça a marché !")
"Ca a marche !"
Par contre cette méthode n’est pas complète:
jshell> unaccent("œ")
"œ"
Dans ce cas, je m’attends à ce que "œ" devienne "oe". Ca ne change rien si je choisis le mode NFKD au lieu de NFD (d’ailleurs c’est quoi la différence entre les deux ?)
JE voudrais aussi autoriser le tiret et le point, mais là par contre le Normalizer ne m’est visiblement d’aucun secours. IL faudrait que tous les tirets de plus ou moins grande longueur se normalisent en point de code 45. et pareil avec les différents points (p.ex. point médian).
Pour distinguer les différents alphabets, je suis aussi perdu. Comment les distinguer ?
jshell> Character.getType('A')
1
jshell> Character.getType('\u0410') // Le A en cyrillique
1
Bref, c’est bien beau tout ça, mais ça parait hyper compliqué.
J’aimerais tant que possible éviter une méthode qui fait des replace à l’ancienne, parce qu’on ne peut pas faire quelque chose de fiable, et parce que je suis sûr qu’il existe mieux. La bibliothèque standard de Java me donne quelques outils mais ils ne sont pas complets, ou alors je ne sais pas comment les utiliser correctement.
Merci pour votre aide !
Et un petit troll pour finir: Est-ce qu’il existe quelque chose du côté de PHP 7 ?