WikiNi

MotWikiAccentue

PagePrincipale :: DerniersChangements :: DerniersCommentaires :: ParametresUtilisateur :: Vous êtes 38.107.191.105
Les Wikis francophones évolués semblent généralement adopter la possibilité de MotWiki accentués comme WebSémantique. Cela paraît être de bon sens puisque les accents sont des marques orthographiques qui affectent le sens : comment sinon faire la différence entre UnHommeTue et UnHommeTué ?
Les MotWiki contenant des caractères accentués donnent des URL partiellement codées ; par exemple WebSémantique donne :
Pourquoi ces différences ?
Hors la lisibilité dégradée, quels sont les incidences de l'emploi de telles URL ?
Comment sont-elles implémentées dans les différents moteurs de Wiki ?
Je n'ai pas encore de réponse très claire à toutes ces questions. -- CharlesNepote



2007-08-19 : DidierLoiseau a annulé (SvnCommit:837 (interwiki)) le commit que j'ai fait dans le dépôt SVN car il générait un avertissement. Quelques petits changements que j'ai exposés hier sur la MailingList devraient permettre de les résoudre. Je vous les laisse ici :

[...] il manque presque rien pour que ça marche. Il suffirait de
changer 'wiki_word_strict_ascii' (positionné à 'true') par
'wiki_word_extended_latin1' (positionné à 'false'). Ca permettrait de mieux
gérer la transition : si cette clé n'existe pas, la valeur conservatrice 'false'
est utilisée. (Et il faut ajouter un '@' dans /includes/constants.php pour ne
pas générer d'avertissement au moment du test.) [...]


-- BenjE

2007-08-12 : J'ai fait un commit dans le dépôt SVN (branche 0.5, SvnCommit:836 (interwiki)) des modifications pour gérer les accents dans les MotsWiki. Le support du charset Latin-1 dans les MotsWiki est contrôlé par une option dans wakka.config.php. Je me suis inspiré sur toutes vos contributions, et en particulier de celle d'Olivier Mengué, qui avant bien avancé dans l'analyse du problème. Olivier, tu pourras créer ta page quand on aura basculé le SVN sur WikiNi.net ;-) Merci à tous -- BenjE



Pour détecter un MotWiki, WikiNi utilise l'expression rationnelle suivante :
/^[A-Z][a-z]+[A-Z,0-9][A-Z,a-z,0-9]*$/
ce qui veut dire tous les mots :
Au passage je crois que la virgule doit être supprimée de l'expression rationnelle.

Pour gérer les MotWikiAccentue, l'expression rationnelle deviendrait :
/^[A-Z\xc0-\xdd][a-z\xe0-\xff]+[A-Z0-9\xc0-\xdd][A-Za-z0-9\xc0-\xdd\xe0-\xff]*$/
ce qui veut dire tous les mots :

Pour réaliser ce changement dans WikiNi on peut envisager d'utiliser des constantes définissant chaque groupe de lettre :

Nous aurions donc par exemple pour /formatters/wakka.php :

A priori les modifications portent sur les fichiers :

La modification ajoute quelques octets de code mais on devrait gagner légèrement en performance du fait de l'emploi des constantes.
La modification est cependant d'importance et je ne voudrais pas tout casser... Si cela vous intéresse, je propose donc de publier une version CVS que l'on teste à plusieurs chez nous avant de la passer en production.
-- CharlesNepote (CharlesNepoteASuivreEnPriorite)

Oui, je suis intérressé par cette fonctionnalité, d'accord pour une mise à jour du CVS .... -- DavidDelon

La modification proposée est très spécifique à l'ISO-8859-1 (Latin-1). On pourrait préférer utiliser ereg (les expressions régulières standard POSIX, pas celles de Perl) de la manière suivante : ereg("^[[:upper:]][[:lower:]]+[[:upper:]][[:alnum:]]*$", $thing). -- ProgFou



Pour la virgule, il suffit d'essayer un MotWiki avec une virgule (comme Abc,Def) pour se rendre compte qu'elle est effectivement de trop. -- ProgFou

Quant à l'optimisation, l'idéal aurait été d'avoir accès à la fonction regcomp (standard POSIX, compilation d'une expression régulière en vue d'utilisations multiples), mais elle n'est apparement pas présente dans PHP (au moins juqu'en PHP 4.3.0). Je ne suis pas certain du gain obtenu en découpant l'expression en constantes, hormis niveau lisibilité bien sûr. -- ProgFou

Dans tous les cas, je ne vois pas ici la conversion des accents depuis l'URL reçue et au moment de la génération des pages Wiki ; est-ce déjà implémenté (avec des urldecode/urlencode bien placés) ? -- ProgFou.


Quoi qu'on décide, je propose dans un premier temps de construire les expressions rationnelles uniquement à partir de constantes. Cela permettra :
Nous aurions donc :
Dès lors, il devient facile pour un développeur de personnaliser ces chaines. S'il veut ajouter la possibilité du souligné-bas, il lui suffira de modifier comme suit :
[En ce qui me concerne ça me va. :) -- ProgFou] [C'est mis dans le CVS. -- ProgFou 20040720]

A priori les modifications portent sur les fichiers :
-- CharlesNepote

En faisant un grep -ri '.*\[[^-+"$<].*\-.*\]' wikini (version CVS) j'obtiens aussi :
- actions/mychanges.php : !preg_match("/[A-Z,a-z]/", $firstChar)
- actions/mypages.php : !preg_match("/[A-Z,a-z]/", $firstChar)
- actions/pageindex.php : !preg_match("/[A-Z,a-z]/", $firstChar)
- actions/trail.php : preg_replace("/^([A-Za-z0-9]+\)|-)/",'',$line) et preg_replace("/^(\[\[.*\]\]|[A-Za-z0-9]+)\s*(.*)$/","$1",$line)
- handlers/page/addcomment.php : preg_match("/^Comment([0-9]+)$/", $latestComment["tag"], $matches)
Ce qui veut dire que ces constantes seront même utiles globalement.
-- ProgFou

Bon, je viens de l'implémanter dans mon Wiki, et ça a fait ressortir pas mal de problèmes... Tout d'abord il faut faire bien attention à la détection des MotWiki et certains tests actuels ont du être modifiés (dans le test lui même, je ne parle pas des remplacement de constantes). Ensuite, il a fallu ajouter des urlencode à quelques endroits (je n'ai pas encore tout vérifié, mais ça a l'air d'aller). Et pour finir, mais pas le moindre des soucis, MySQL semble faire toutes ses recherches dans le jeu de charactère dans lequel il a été lancé, en reconnaissant les caractères accentués comme étant identiques à leur version sans accent ! Du coup les pages UnHommeTue et UnHommeTué ne sont pas différenciables !! Grmph... -- ProgFou

Bon. On peu commencer par les urlencode (tu peux publier ton code ? il y a peu d'endroits je suppose ?). Le problème de MySQL me semble mineur et n'altère pas véritablement le fonctionnement.
Peux-tu nous en dire plus sur les modifications des tests actuels (code ?). Je veux bien recetter à fond tout ça. -- CharlesNepote



J'ai modifié mon propre WikiNi (privé, désolé) dès ma première installation de WikiNi, afin de créer mon utilisateur : OlivierMengu?é.
C'était avant de découvrir cette page.
Voici ce que j'ai modifié pour que toutes les lettres accentuées de ISO-8859-1 soient supportées :
wakka.php:
- else if (preg_match("/[^[:alnum:]]/", $tag))
+ // OM Majuscules : À-ÖØ-Þ Minuscules : ß-öø-ÿ Tout : À-ÖØ-öø-ÿ
+ else if (preg_match("/[^[:alnum:]À-ÖØ-öø-ÿ]/", $tag))

- function IsWikiName($text) { return preg_match("/^[A-Z][a-z]+[A-Z,0-9][A-Z,a-z,0-9]*$/", $text); }
+ function IsWikiName($text) { return preg_match("/^[A-ZÀ-ÖØ-Þ][a-zß-öø-ÿ]+[A-Z0-9À-ÖØ-Þ][A-Za-z0-9À-ÖØ-öø-ÿ]*$/", $text); }


formatter/wakka.php:
- else if (preg_match("/^[A-Z][a-z]+[A-Z,0-9][A-Z,a-z,0-9]*$/s", $thing))
+ else if (preg_match("/^[A-ZÀ-ÖØ-Þ][a-zß-öø-ÿ]+[A-Z0-9À-ÖØ-Þ][A-Za-z0-9À-ÖØ-öø-ÿ]*$/s", $thing))

- "\b([A-Z][a-z]+[A-Z,0-9][A-Z,a-z,0-9]*)\b|".
+ "(?![^A-Za-z0-9À-ÖØ-öø-ÿ_])([A-ZÀ-ÖØ-Þ][a-zß-öø-ÿ]+[A-Z0-9À-ÖØ-Þ][A-Za-z0-9À-ÖØ-öø-ÿ]*)(?=[^A-Za-z0-9À-ÖØ-öø-ÿ_])|".


Notez sur la dernière ligne le remplacement de \b par des expressions un peu plus complexes, mais qui donnent la même fonctionnalité en ajoutant le support des accents. '\b' est une condition indiquant une frontière de mot : on veut que le mot Wiki ne soit pas à l'intérieur d'un mot. Les conditions (?![...]) (condition "pas un caractère alphanum qui précède") et (?=[...]) (condition "pas un caractère alphanum qui suit"). Avec l'ancienne regexp, MotWikiAccentue doit matcher (notez ce qui se passe dans éMotWikiAccentueÉ ou ÉMotWikiAccentueÉ), mais pas aMotWikiAccentue, ni AMotWikiAccentue, ni _MotWikiAccentue, ni MotWikiAccentue_. Avec la nouvelle : OlivierMengu?é matchera, mais pas éOlivierMengu?é, ni ÉOlivierMengu?é, ni _OlivierMengué ou OlivierMengu?é_.
En lisant cette page je découvre le problème de MySQL rapporté par ProgFou. Il va falloir que je teste cela.
-- OlivierMengu?é (qui espère bien pouvoir bientôt créer sa micro-page perso sur WikiNi.net avec le mot wiki qui va bien).

Pour compléter : j'ai appliqué mon patch sur la version 0.4.1rc.
Je n'ai par rencontré de problème concernant les URLs : elle ne sont pas encodées, mais comme le jeu de caractères iso-8859-1 est spécifié, cela ne pose pas de problème.
Mais pour une vraie internationalisation il faudrait envisager un jeu de caractères plus large, ce que MySQL ne semble pas supporter.
-- OlivierMengu?é

Bonjour Olivier, content de voir que tu travailles aussi sur ce sujet ! Charles et moi avions déjà discuté implémentation, comme tu peux le voir plus haut dans cette page, et j'avais déjà fait une implémentation sur WikiTeki en suivant ces idées. Je vais publier ici mon .diff (d'ici quelques jours) afin que nous puissions continuer les discussions et intégrer une version commune au tronc actuel. -- ProgFou



Pour ma part, j'ai opté pour une solution plus simple: j'affiche un lien comprenant des lettres accentuées, mais la cible du lien l'est vers une page ne contenant aucun caractère accentué (Script de remplacement des caractères accentués trouvé sur: http://fr.php.net/manual/fr/function.str-replace.php#68480 )

J'ai donc d'une part modifié: ~/formatters/wakka.php pour qu'il reconnaisse les liens contenant des caractères accentués (plus d'info sur la wikipédia: http://en.wikipedia.org/wiki/ISO_8859-1 )

Liens interwiki:
- else if (preg_match("/^[A-Z][A-Za-z]+[:]([A-Za-z0-9]*)$/s", $thing))
+ else if (preg_match("/^[A-Z\xc0-\xdd][A-Z\xc0-\xdd,a-z\xe0-\xff]+[:]([A-Z\xc0-\xdd,a-z\xe0-\xff,0-9]*)$/s", $thing))

Liens wiki:
- else if (preg_match("/^[A-Z][a-z]+[A-Z0-9][A-Za-z0-9]*$/s", $thing))
+ else if (preg_match("/^[A-Z\xc0-\xdd][a-z\xe0-\xff]+[A-Z0-9\xc0-\xdd][A-Za-z0-9\xc0-\xdd\xe0-\xff]*$/", $thing))

D'autre part, j'ai modifié dans ~/wakka.php la fonction Link, et rajouté après l'instruction if (!$text) $text = $tag; le script permettant de remplacer la cible du lien (la variable $tag) sans toucher au titre du lien (variable $text qui vient d'être affectée à la valeur de $tag).

// Remplacement des lettres accentuées par des lettres non accentuées dans la cible du lien
$tag = htmlentities($tag);
$tag = preg_replace('/&([a-zA-Z])(uml|acute|grave|circ|tilde);/','$1',$tag);
$tag = html_entity_decode($tag);

NB: je ne sais pas dans quelles circonstances la fonction Link est appelée avec une valeur pour le paramètre $text ... Il y a peut être là sujet à bug!

--SoubourouPierre


J'ai téléchargé la version CVS et tenté de mettre en oeuvre ce beau système de constantes, mais je suis tombé sur un os ! Le responsable étant else if (preg_match("/[^[:alnum:]]/", $tag)) dans la fonction link. Avec lui, pas moyen d'avoir des caractères accentués sans que link() ne les interprètes comme liens externes !

Après plusieurs tentatives infructueuses pour parvenir à lui faire reconnaître WN_CHAR ou WN_CHAR2 sans pour autant que les véritables liens externes ne deviennent interprétés comme des liens internes, je suis arrivé à la conclusion que la logique même de cette fonction est erronée. En effet, elle fonctionne ainsi :

On voit tout de suite le problème : il faudrait logiquement vérifier s'il s'agit d'un lien Wiki avant d'assumer que c'est n'importe quoi. Aussi, voilà ma fonction link(), telle que modifiée par rapport au CVS d'aujourd'hui.
function Link($tag, $method = "", $text = "")
    {
        $tag  = htmlspecialchars($tag); //avoid xss
        $text = htmlspecialchars($text); //paranoiac again
        $text = preg_replace('/&amp;(\\#[xX][a-fA-F0-9]+|\\#[0-9]+|[WN_CHAR]+);/', '&$1;', $text);
        if (!$text) $text = $tag;

        // is this an interwiki link?
        if (preg_match('/^' . WN_INTERWIKI_CAPTURE . '$/s', $tag, $matches))
        {
            if ($tagInterWiki = $this->GetInterWikiUrl($matches[1], $matches[2])) {
                return "<a href=\"$tagInterWiki\">$text (interwiki)</a>";
            }
            else return "<a href=\"$tag\">$text (interwiki inconnu)</a>";
        }
        else if (preg_match('/^' . WN_CAMEL_CASE . '$/s', $tag)) // it's a Wiki link!
        {
            if ($this->PageExists($tag)) {
                // if ($text == $tag) $text = $this->GetExistingPageName($tag);    // Modification inutile pour le cas qui nous occupe, GetExistingPageName 
                                                            // n'existant pas dans Wikini "normal". Elle me sert pour les _ dans les MotsWiki...
                $tag = $this->GetExistingPageTag($tag);
                return "<a href=\"".$this->href($method, $tag)."\">$text</a>";
            }
            else {
                return "<a href=\"".$this->href("edit", $tag)."\" class=\"missingpage\" title=\"Cr&eacute;er cette page\">$text</a>";
            }
        }
        else // it must be some sort of full link...
        {
            // check for email addresses
            if (preg_match("/^[\w.-]+\@[\w.-]+$/", $tag))
            {
                $tag = "mailto:".$tag;
            }
            // check for protocol-less URLs
            else if (!preg_match("/:\/\//", $tag))
            {
                $tag = "http://".$tag;    //Very important for xss (avoid javascript:() hacking)
            }
            // is this an inline image (text!=tag and url ends png,gif,jpeg)
            if ($text!=$tag and preg_match("/\.(gif|jpeg|png|jpg)$/i",$tag))
            {
                return "<img src=\"$tag\" alt=\"$text\"/>";
            }
            else
            {
                return "<a href=\"$tag\">$text</a>";
            }
        }
    }

--GeZ

En effet GeZ, et j'ai moi aussi fait cette constatation la semaine dernière pour produire mon SvnCommit:836 (interwiki). J'y ai choisi de changer le else if (preg_match("/[^[:alnum:]]/", $tag)) par un else if (!preg_match('/^'.WN_PAGE_TAG.'$/', $tag)) qui est plus logique. Note que dans ta proposition, il est essentiel d'encoder le contenu des variables avec HtmlSpecialChars() sans quoi tu ne peux pas être certain de produire du HTML. De manière générale, ta proposition semble basée sur une version de Link() buggée dont j'ai récemment exposé les limites dans le BugTracker et sur la MailingList, et que j'ai ensuite modifiée. Pour les MotsWiki accentués, base-toi plutôt sur la révision SvnCommit:836 (interwiki). -- BenjE

Je vois. J'avais téléchargé le SVN de Wikini/Trunk, pas celui de Wikini/Branches/Wikini-0.5/... -- GeZ
Il n'y a pas de commentaire sur cette page. [Afficher commentaires/formulaire]