Gestion des abréviations et d’un glossaire avec SPIP

Comme vous aurez compris que je suis fortement sensibilisé à l’accessibilité web, je me suis efforcé de suivre les recommandations nationales et internationales dans ce domaine pour la conception de ce site. Les abréviations, acronymes, et le glossaire ont été traités suite à des recherches personnelles sur les bonnes pratiques à adopter, et les plugins SPIP qui me permettraient de les mettre en œuvre. Je détaille ici la mise en place de la solution retenue, la meilleure que j’ai pu trouver à ce jour, qui produit un bon niveau d’accessibilité…

Remerciements

Je tiens tout particulièrement à adresser mes remerciements appuyés aux personnes qui m’ont aidé dans ce travail, en particulier à Patrice Vanneufville, développeur de lame glossaire du couteau Suisse pour SPIP, qui a notamment modifié le code de ce plugin, en fonction de nos discussions, afin que toute la communauté puisse en profiter.

Tests

Les tests fonctionnels ont été faits manuellement pour la vérification du code produit, mais également avec un lecteur d’écran (JAWS 10) sous différents paramétrages :

  • développement ou non des abréviations et acronymes ;
  • lecture de l’intitulé des liens ou bien du titre des liens ;
  • les 2 points précédents avec leurs associations possibles, par exemple un paramétrage où les abréviations sont développées et les titres des liens sont lus, un paramétrage où les abréviations sont développées et les intitulés des liens sont lus, etc.

Rappel des recommandations WCAG et RGAA

Pour ne pas alourdir les éléments listés ci-après, je ne mets pas les références vers les critères de succès ou les tests unitaires de conformité à chaque fois : on pourra les retrouver sur rgaa.net.

Afin de respecter les principes « Perceptible » et « Compréhensible » de ces référentiels, il faut fournir :

  • des liens ou définitions donnant accès aux informations nécessaires à la compréhension des contenus ;
  • un balisage correct des listes de définitions ;
  • un balisage correct des abréviations et acronymes ;
  • une version non abrégée des abréviations et acronymes pertinente.

Mais également, compte-tenu du fait que certaines abréviations sont d’origine étrangère il faut indiquer :

  • la présence des changements de langue dans le texte ;
  • la présence des changements de langue dans les valeurs d’attributs HTML ;

Solution adoptée pour ce site

Tout d’abord, du point de vue du balisage, il ne sera fait aucune distinction entre un acronyme et une abréviation qui seront toutes les deux codées avec la seule balise abbr, conformément au référentiel HTML5 actuel. Cela permet d’ailleurs de simplifier la tâche du rédacteur d’une part au niveau de la saisie, puisqu’il n’a pas à réfléchir si le terme est bien une abréviation ou un acronyme. D’autre part, cela n’a aucune incidence sur la restitution de la version non abrégée (sauf traitement CSS différent pour les balises abbr et acronym pour les voyants, les lecteurs d’écran pour non-voyants restituant l’information de la même manière si leur paramétrage est le même pour le traitement des 2 balises).

Ensuite, pour éviter au rédacteur de saisir directement les balises abbr et leurs attributs title et éventuellement lang (les rédacteurs des sites SPIP ne sont pas touts des codeurs loin s’en faut…), j’ai cherché un moyen d’automatiser la chose tout en évitant de devoir rédiger le code des balises utilisées, et bien sûr de centraliser les définitions et les expansions afin de ne pas les saisir dans les articles à rédiger. J’ai pu trouver mon bonheur sur spip-contrib.

La solution retenue utilise 2 plugins SPIP qui se complètent assez bien :

  • le plugin « acronymes » ;
  • la lame « glossaire » du Couteau Suisse.

Pourquoi 2 plugins ? C’est simple :

  • les termes à définir ne sont pas forcément des abréviations (il faut donc la lame « glossaire » pour donner accès à leur définition) ;
  • les expansions (ou versions non-abrégées) des abréviations ont souvent besoin d’être complétées par une définition plus précise ou apporter des éléments de nature à faciliter la compréhension de celles-ci (là encore, il faut donc la lame « glossaire »). D’ailleurs la spécification W3C de l’attribut title de la balise abbr précise bien que la valeur de l’attribut ne doit contenir rien d’autre que l’expansion seule, ce qui impose que si des informations complémentaires sont indispensables à la compréhension, elles doivent être fournies par un autre moyen (ici la lame « glossaire ») ;
  • Il est inutile d’utiliser le glossaire si c’est pour exprimer seulement l’expansion de l’abréviation ; Sur le plan structurel et sémantique, il est préférable d’encadrer toutes les abréviations par la balise abbr qui permettra un accès direct à l’expansion sans avoir besoin d’activer un lien (d’où la nécessité de disposer du plugin « acronymes »).

Installation du plugin « acronymes »

Il faut d’abord installer puis d’activer le plugin Forms & Tables par la méthode habituelle d’installation d’un plugin. Faire la même chose avec le plugin « acronymes ».

Faire ensuite un test en ajoutant dans la table des « sigles/acronymes » votre première abréviation (suivre les indications de la section « Faire un sigle » sur spip-contrib).

Le problème c’est que la dernière version du plugin « acronymes » en date au moment de la rédaction de cet article, la version 0.13.0, ne prend pas en compte le paramètre langue indiqué dans le formulaire de saisie. D’autre part, concernant le problème des abréviations d’origine étrangère, la solution préconisée ne peut pas être mise en oeuvre en l’état du plugin.

Il m’a fallu donc modifier celui-ci, mais je précise qu’avec avoir contacté son auteur, que le développement du plugin « acronymes » est désormais figé, donc les modifications ne devraient pas être écrasées car il n’y aura plus de mise à jour. Je fournis donc le script php contenant les modifications, qui remplace le script original du plugin et qui permet de résoudre les problèmes évoqués précédemment :

acronymes_filtres.php -  Zip - 3.2 ko
acronymes_filtres.php

Enfin, j’ai également ajouté des langues supplémentaires (seules le français et l’anglais sont proposées par défaut) pour la prononciation de l’expansion. Malheureusement, il a fallu ajouter des enregistrements dans une table spip_forms_champs_choix avec phpmyadmin. Il faut d’abord connaître l’identifiant du formulaire sigles :

SELECT *  FROM `spip_forms` WHERE `titre` LIKE 'Sigles'

Repérer l’id_form (pour moi, id_form=1) et l’insérer en première valeur de chaque parenthèse après « VALUES » dans la requête suivante :

INSERT INTO `iew_site`.`spip_forms_champs_choix` (`id_form`, `champ`, `choix`, `titre`, `rang`) VALUES ('1', 'select_2', 'select_2_3', 'de', '3'), ('1', 'select_2', 'select_2_4', 'es', '4'), ('1', 'select_2', 'select_2_5', 'it', '5');

On dispose alors en plus des langues proposées par défaut, de l’allemand, de l’espagnol, et de l’italien.

Installation de la lame « glossaire » du couteau Suisse

Cette lame est fournie avec le Couteau Suisse qu’il faudra installer.
Ensuite, il faut activer l’outil « Glossaire interne » en se rendant sur la page d’administration du plugin en espace privé (Bouton « Configuration », et onglet « Le Couteau Suisse », choisir ensuite d’activer l’outil « Glossaire interne »).
Pour la configuration de cette lame, laisser les valeurs par défaut sauf :

  • Nombre de liens maximum : remplacer « 0 » par « 1 » ;
  • Technique utilisée : cocher CSS (fonctionnera même si javascript est désactivé) ;
  • décocher la case « Ignorer les balises <abbr> et <acronym> » afin que la lame « glossaire interne » puisse prendre en compte les abréviations déjà définies également dans le plugin « acronymes »

Pour éviter la pollution autant visuelle (pour les voyants) que sonore (pour les non-voyants), seule la première occurrence du terme dans la page est associée avec un lien vers sa définition, ce qui garantit la conformité aux référentiels d’accessibilité utilisés, même si évidemment les modes d’accès à la page avec notamment les lecteurs d’écran peuvent se faire sur des sections « postérieures » à cette occurrence (au sens de lecture conventionnelle d’un document papier), ce qui peut rendre plus difficile la compréhension.
Les tests que j’ai pratiqué sur ce site ont montré qu’il était plus pénible à l’usage de traiter toutes les occurrences, plutôt que de devoir de temps en temps accéder à la définition du terme par un accès direct à la page du glossaire (ou bien indirectement par une recherche avec le moteur de recherche du site).

C’est pourquoi ici, j’utilise un paramétrage égal à « 1 » pour le nombre maximal de liens créés dans l’interface de configuration de la lame « glossaire interne » du Couteau Suisse.

Enfin, pour réaliser une bonne accessibilité, il est nécessaire d’ajouter un attribut title sur les balises <a> ajoutées par la lame « glossaire interne ». Cela consiste en une surcharge de la fonction glossaire_attributs_lien_dist() de la lame glossaire (dans glossaire_fonctions.php) sous forme d’une fonction glossaire_attributs_lien() qu’on placera dans mes_fonctions.php :

function glossaire_attributs_lien($id_mot, $lien, $titre, $les_titres) {
        return recuperer_fond('glossaire_attributs_a', array(
                'mot'=>$les_titres[0],
                'lien'=>$lien."#debut_def",
        ));

Cette fonction fait appel à un squelette glossaire_attributs_a.html (à placer dans votre dossier squelettes) et contenant les lignes suivantes :

[(#REM) génère les attributs title et lang de la balise <a> pour un mot du glossaire
       
- si la langue n'est pas définie dans le titre du mot (français par défaut), alors title contiendra la chaîne "MOT, Définition dans le glossaire" et lang contiendra "fr" (car un attribut lang vide ne serait pas valide)
- si c'est une langue définie par un <multi>, alors title contiendra la chaîne "MOT" (même si cela n'apporte rien de plus que l'intitulé, un attribut vide ne serait pas valide) et lang contiendra la langue définie pour le mot pour une prononciation correcte

Le mot est recherché par une expression régulière, ce qui permet de trouver le mot qu'il soit titré avec un <multi> ou pas
]

[(#SET{mot,[(#ENV**{mot}|textebrut)]})]
[(#SET{motif_mot,^#GET{mot}$|\]#GET{mot}<})]
[href="(#ENV**{lien})"] title="<B_Glossaire_title><BOUCLE_Glossaire_title(MOTS){titre == #GET{motif_mot}}{0,1}>[(#TITRE*|trouve_attribut_lang|=={#LANG}|?{[(#TITRE|contenu_balises_acronym_abbr_span), <:def_glossaire:>],[(#TITRE|contenu_balises_acronym_abbr_span)]})]</BOUCLE_Glossaire_title></B_Glossaire_title>#GET{mot}<//B_Glossaire_title>" lang="<B_Glossaire_lang><BOUCLE_Glossaire_lang(MOTS){titre == #GET{motif_mot}}{0,1}>[(#TITRE|extraire_balise{abbr}|?{[(#TITRE|extraire_balise{abbr}|extraire_balise{span}|extraire_attribut{lang}|sinon{#LANG})],[(#TITRE|extraire_attribut{lang}|sinon{#LANG})]})]</BOUCLE_Glossaire_lang></B_Glossaire_lang>#LANG<//B_Glossaire_lang>"

Attention, ce code ne doit pas contenir de saut de ligne ou d’espace supplémentaire par rapport à ce qui est présenté ici, sinon le code généré pour les attributs title et lang ne sera pas bien formé. Je fournis donc le fichier glossaire_attributs_a.html ci-dessous :

glossaire_attributs_a.html -  HTML - 1.4 ko
glossaire_attributs_a.html

L’attribut title de la future balise <a> est construit à partir du titre du mot dans le glossaire avant les traitements automatiques (#TITRE*), et l’attribut lang de la future balise <a> est recherché après les traitements automatiques dont le filtre acronymes (donc sur #TITRE, dans une éventuelle balise abbr ou span).

Ainsi, on est assuré de la correspondance parfaite (title et lang) avec ce qui est saisi dans le glossaire (ce qui paraît plus cohérent pour une balise <a> dont le href pointe sur la définition correspondante du glossaire, que ce soit une abréviation ou non).

Ces attributs sont ensuite transmis à la fonction glossaire_attributs_lien() (dans mes_fonctions.php) qui se chargera de les retransmettre à la fonction cs_rempl_glossaire() de la lame glossaire (glossaire_fonctions.php) afin de construire correctement la balise <a> avec les bons attributs. L’attribut href du lien contient une référence #debut_def qui sera utilisée pour pointer directement vers la définition du mot (ancre nommée correspondante dans le squelette mot.html, voir la section Mise en place d’un squelette glossaire et modification d’autres squelettes)

Mise en place d’un squelette glossaire et modification d’autres squelettes

Avec le dispositif actuellement mis en place, on a la reconnaissance des mots du glossaire et des abréviations dans tous les articles, mais on peut aussi générer des pages spéciales contenant les entrées du glossaire, avec une barre de navigation alphabétique, c’est ce qui est fait sur ce site. Pour cela, j’utilise les fonctions suivantes (dans mes_fonctions.php), tirées de la page sur la lame glossaire interne sur spip-contrib :

/***********************************************************************************
 Filtres pour le glossaire avec barre de navigation alphabétique
 (d'après http://www.spip-contrib.net/Un-glossaire-interne-pour-vos-sites#bonus)
************************************************************************************/

// fonction pour array_walk : renvoie la premiere lettre majuscule translitteree du mot
// (ex. : &eacute; => E, &oelig; => O, etc.)
function premiere_lettre_tab(&$item) {
       $item = translitteration_complexe($item);
       $item = strtoupper($item{0});
}
// fonction pour array_walk : renvoie un lien, sauf si le contexte est la lettre en question
function lien_1ere_lettre_tab(&$item, $key, $arg) {
       $item = $arg[0]==$item
               ?"<span class='lettre_contexte'>$item</span>"
               :'<a href="'.parametre_url($arg[1],"lettre",$item).'">'.$item.'</a>';
}
// renvoie la premiere lettre majuscule translitteree du mot
// (ex. : &eacute; => E, &oelig; => O, etc.)
function premiere_lettre($titre) {
       premiere_lettre_tab($titre);
       return $titre;
}
// renvoie les premieres lettres majuscules translitterees de tous les mots du titre
// formes du titre du glossaire : "Mot" ou "Mot1/Mot2/Mot3" ou "<multi>[fr]Mots1[en]Mots2</multi>"
function premieres_lettres($titre) {
       $arr = explode(_GLOSSAIRE_TITRE_BASE_SEP, extraire_multi($titre));
       array_walk($arr, 'premiere_lettre_tab');
       return join('', $arr);
}
// renvoie une barre de navigation alphabetique a partir d'une chaine (ex : "AABBBFGG")
function alphabet_cliquable($texte, $lettre, $nomboucle='') {
       $arr =  array_unique(preg_split('//', " $texte", -1, PREG_SPLIT_NO_EMPTY));
       sort($arr);
       unset($arr[0]);
       // retrait de la pagination
       $self = parametre_url(self(),'debut_'.$nomboucle,'');
       array_walk($arr, 'lien_1ere_lettre_tab', array($lettre, $self));
       return join(' | ',$arr);
}
// renvoie true si le mot peut etre affiche (sa premiere lettre correspond au contexte)
function mot_affichable($titre, $lettre) {
       $arr = explode(_GLOSSAIRE_TITRE_BASE_SEP, extraire_multi($titre));
       array_walk($arr, 'premiere_lettre_tab');
       return in_array($lettre, $arr);
}

Puis la fonction :

/********************************************************************
        Sylvain Godmé <sylvain point godme at gmail.com>       
        Filtre personnalisé pour empêcher l'affichage des balises
        fermantes </span> et </abbr> ou </acronym> dans les titres
        des mots du glossaire (glossaire.html) induite par l'activation
        du plugin "Acronymes"
********************************************************************/

/*
En effet, le plugin "Acronymes" aura pour effet d'ajouter des balises <abbr> aux abréviations qu'il reconnaîtra y compris dans les mots-clés (donc le glossaire est concerné)
Ceci va alors perturber le fonctionnement de la lame glossaire du couteau suisse :
- pour la construction de la barre de navigation alphabétique : le caractère "<" va apparaître dans cette barre (à cause de la présence de <abbr> dans le titre du mot-clé => Ce problème est traité par la fonction contenu_balises_acronym_abbr_span() qui est ensuite utilisée comme filtre dans glossaire.html pour générer la barre de navigation alphabétique
- pour l'affichage des listes de définition des mots-clés où les titres des mots clés contiennent des balises fermantes visibles "</abbr>" et/ou "</span>" (si langue spécifiée) */


function contenu_balises_acronym_abbr_span($chaine) {

        /* Cette fonction retourne le contenu des balises acronym ou abbr ou span */
       
        // reperage des balises acronym abbr (viennent du plugin acronymes)
        // ou span (viennent des balises spip [multi][en]titre[/multi] dans le titre d'un mot du glossaire, traité par le plugin glossaire)

        $pattern="{<(?:acronym|abbr|span)[^>]*>([^<]*)</(?:acronym|abbr|span)>}";
        preg_match_all ($pattern, $chaine, $tagMatches, PREG_SET_ORDER);

        // On retourne le contenu sans les balises afin que les filtres de glossaire.html agissant sur le titre du mot (#TITRE)
        // ne détectent pas "<" comme première lettre du mot pour la construction de la barre de navigation alphabétique
        // et que les balises fermantes ne soient pas affichées

        /* $tagMatches contient toutes les occurrences des balises recherchées sous forme de tableau à 2 dimensions
           $tagMatches[0] est la première occurrence, $tagMatches[1] la 2ème etc...
           $tagMatches[0][0] contient la portion de chaîne contenant la balise complète de la première occurrence, $tagMatches[0][1] contient uniquement le contenu de cette balise
           (par ex : ce qui se trouve ENTRE <abbr> et </abbr>)
        */

        //var_dump(htmlspecialchars($chaine));

        if (count($tagMatches) !=0) // Il y a au moins occurrence trouvée
                return $tagMatches[0][1]; // Attention : ceci ne renvoie que le contenu de la première occurrence de balise trouvée (c'est correct si on utilise ce filtre pour la construction de la barre de                                                         navigation alphabétique dans glossaire.html car la première lettre du mot-clé est recherchée)
        else // la chaine ne contient aucune balise recherchée, on la renvois telle quelle
                return $chaine;
}

Et enfin, le squelette glossaire.html :

<div id="article" role="article">
                <div class="cartouche">
                    <h1>[(#ENV{lettre}|?{"Glossaire, lettre "#ENV{lettre},"Glossaire"})]</h1>
                </div>
               [(#REM) Construction d'une chaine comportant toutes les premieres lettres de tous les mots du glossaire  (ex : "AABBBFGG") et stockage en tableau des mots valides]
                #SET{arr,#ARRAY}
                <BOUCLE_listalpha(MOTS){type=Glossaire}>
                  [(#SET{lettres,[(#GET{lettres}|concat{[(#TITRE|contenu_balises_acronym_abbr_span|premieres_lettres)]})]})]
                  [(#TITRE|contenu_balises_acronym_abbr_span|mot_affichable{#ENV{lettre,A}}|oui)#SET{arr,#GET{arr}|push{#ID_MOT}}]
                </BOUCLE_listalpha>
                [(#REM) Affichage de la barre de navigation ]
<span class="hidden"><a href="#debut_liste_def">Éviter la barre de navigation alphabétique</a></span>
                <div class="barre_alphabetique" aria-labelledby="labelalpha" role="navigation">
                  <span id="labelalpha" class="hidden">Index alphab&eacute;tique&nbsp;:</span> [(#GET{lettres}|alphabet_cliquable{#ENV{lettre,A},Glossaire2})]
                </div><hr/>
                [(#REM) Affichage de la liste des mots retenus dans le tableau "arr" ]
<a id="debut_liste_def" name="debut_liste_def"></a>
                <div class="liste_glossaire">
                  <B_Glossaire2>
                  <dl>
                  <BOUCLE_Glossaire2(MOTS){type=Glossaire}{id_mot IN #GET{arr}}{par multi titre}{pagination}>

                            [(#REM) l'étoile sur le titre qui suit évite l'application des filtres automatiques dont celui du plugin acronymes faisant appraître les balises abbr avec leur expansion. Ici,                                         l'expansion ne doit pas s'afficher car est indiquée en clair dans la définition complète du mot. Par contre, si le titre du mot est en langue étrangère, il faut que la balise                                         <multi> en soit transformée en        <span lang="en">, ce qui est fait grâce au filtre extraire_multi]
                   
                    <dt class="#EDIT{titre}">[(#TITRE*|extraire_multi)][ ((#DESCRIPTIF))]</dt>
                       
                        [(#REM) le filtre suivant permet d'éviter l'application du glossaire (activation d'un cadre affichant la définition) car on est déjà dans le glossaire, sinon c'est pénible de se
                        retrouver avec des définitions redondantes]

                    <dd class="#EDIT{texte}">[(#TEXTE*|cs_traitements{TEXTE,articles,cs_glossaire})]</dd>

                  </BOUCLE_Glossaire2>
                  </dl>
                  #PAGINATION
                  </B_Glossaire2>
        </div>
        </div><!--#article-->

Dans le squelette précédent, le filtre glossaire est désactivé pour éviter une redondance de la définition exposée, ce qui a un effet de bord lorsque la définition contient une occurrence d’un autre mot du glossaire : dans ce cas, le lien vers la définition de cet autre mot n’est pas automatique, c’est au rédacteur d’indiquer manuellement ce lien.
Les lignes <span class="hidden"><a href="#debut_liste_def">Éviter la barre de navigation alphabétique</a></span> et <a id="debut_liste_def" name="debut_liste_def"></a> permettent à un lecteur d’écran d’annoncer un lien d’accès rapide au contenu principal de la page sans devoir tabuler sur toutes les liens-lettres de la barre de navigation alphabétique. La classe "hidden" de la balise <span> est définie avec les propriétés CSS suivantes dans la feuille de style utilisée sur ce site :

.hidden {
height: 0.1em;
left: -10000px;
overflow: hidden;
position: absolute;
top: auto;
width: 0.1em;
}

, ce qui permet de mettre le contenu hors écran afin qu’il ne soit perceptible que par les lecteurs d’écran.

De plus, dans le squelette recherche.html, on peut filtrer la balise #INTRODUCTION de façon à ce que les effets acronymes et glossaires apparaissent sur le texte correspondant : pour cela il suffit d’ajouter (#INTRODUCTION*|typo|cs_glossaire) (cela devrait être valable dans tout squelette utilisant la balise #INTRODUCTION).

Pour les résultats de recherche sur les mots-clés on peut mettre :

[(#REM) Mots-cles trouves ]
                <B_mots>
                <div>
                        #ANCRE_PAGINATION
                        <h2 class="spip">#GRAND_TOTAL mot(s)-clé(s)</h2>
                        <ul class="spip_plan">
                                <BOUCLE_mots(MOTS) {recherche} {par points}{inverse} {pagination 5}>
                                <li><a href="#URL_MOT#debut_def" title="[(#TITRE|contenu_balises_acronym_abbr_span)], Définition dans le glossaire">#TITRE</a></li>
                                </BOUCLE_mots>
                        </ul>
                        [<p class="pagination">(#PAGINATION)</p>]
                </div>
                </B_mots>

Finalement, dans le squelette mot.html :

<div id="article" role="article">
       <div class="cartouche">
           [(#LOGO_MOT|image_reduire{200,200})]
           <h1 class="#EDIT{titre}">[(#TITRE*|extraire_multi)]</h1>
       </div>

       [<a id="debut_def" name="debut_def"></a><div class="#EDIT{texte}">(#TEXTE)</div>]
        <p><a href="#URL_SITE_SPIP/?page=glossaire">Glossaire alphabétique</a></p>
        </div><!--#article-->

Utilisation concrète pour le rédacteur

En tant que rédacteur, il suffit d’abord en mode « édition » sur un article, de cliquer sur l’onglet « Voir » du porte-plume, ce qui permettra de vérifier si le terme à définir ou l’expansion d’une abréviation à indiquer n’est pas déjà dans les tables SPIP : si c’est le cas, au survol de la souris, vous devez voir l’« effet glossaire » (apparition d’une fenêtre en surimpression contenant la définition du mot dans le glossaire) et/ou l’« effet acronymes » (info-bulle contenant l’expansion de l’abréviation). Sinon, suivre les cas indiqués dans la liste ci-dessous :

  • L’expression à définir n’est pas une abréviation : dans ce cas, la saisie dans l’interface privée se fait uniquement en tant que mot-clé dans le groupe de mots « glossaire ». Si l’expression est à prononcer dans une langue étrangère, ne pas oublier d’encadrer le titre du mot par une balise <multi>[code langue]expression</multi>, mais il faudra aussi le faire dans la zone de saisie d’un article qui utiliserait cette expression : sinon le mot ne sera pas reconnu par le filtre glossaire d’une part, et d’autre part il ne sera pas prononcé dans la bonne langue…
  • L’expression à définir est une abréviation : dans tous les cas, il faudra saisir l’abréviation (champ SIGLE), ainsi que son expansion (champ DESCRIPTIF) dans le formulaire de saisie du plugin « sigles/acronymes ».
    • Si l’abréviation est d’origine étrangère, alors il faut réfléchir à la prononciation dans la langue qui facilite sa compréhension. Si c’est la langue d’origine, alors le champ SIGLE correspondant doit être encadré par une balise <multi> adéquate. Si c’est le français, il n’y a rien de spécial à faire (aucune balise <multi> à mettre). Concernant la langue de prononciation de l’expansion de l’abréviation, cette dernière doit toujours se faire dans la langue d’origine (donc renseigner le champ LANGUE).
    • Si l’expansion de l’abréviation ne suffit pas à sa compréhension ou si l’on tient à apporter des informations complémentaires qui pourraient en favoriser la compréhension, il faudra à nouveau saisir l’abréviation en tant que mot-clé dans le groupe de mots « glossaire » (par contre, ne jamais mettre de <multi> dans le champ titre d’un mot du glossaire si ce mot est aussi dans la table sigles/acronymes, sinon le filtre glossaire ne reconnaîtra pas ce mot).
  • Lorsqu’il est fait référence dans une définition à une autre entrée du glossaire proche du mot et qui partage la même définition, il suffit de mettre les variantes dans le titre du mot avec un séparateur "/" comme indiqué dans la documentation de la lame glossaire du couteau suisse (exemple : ARIA / WAI-ARIA)
  • Si dans le texte de définition il est fait référence directement à un autre mot du glossaire (dont la définition n’a rien à voir avec celle en cours), par convention on en fera un lien sous la forme : [MOT|MOT, Définition dans le glossaire->motID_MOT#debut_def] ou encore sous la forme [MOT|MOT, Définition dans le glossaire->?page=glossaire&lettre=1ERE_LETTRE_MOT#MOT]. Dans le premier cas, on est redirigé vers le squelette mot.html affichant une page concernant le mot seul et un lien de retour au glossaire ; dans le second cas, on est redirigé vers l’entrée correspondant au mot en restant dans le glossaire (mais SPIP interprête ce type de lien comme lien externe alors qu’il en est rien)…
    Une exception à la convention indiquée précédemment : lorsque le mot concerné (XML dans l’exemple qui suit) se trouve dans une expression du type « Abréviation de Asynchronous Javascript and XML » où il s’agit de donner la clarification d’une abréviation, un lecteur d’écran marque une pause en lisant « Abréviation de : Asynchronous Javascript and » ; puis après appui sur la touche « flèche basse » du clavier, on entend « lien : XML, definition dans le glossaire ». Cette pause nuit à la compréhension de la « clarification » de l’abréviation. Donc, dans ce cas, on indiquera pas de lien vers la définition du mot dans le glossaire.

Il faut penser à vérifier les entrées du glossaire pour voir si au moins la première occurrence d’un mot déjà présent dans le glossaire est traité comme indiqué dans la convention ci-dessus. Ceci n’est à faire que dans les pages du glossaire où la fenêtre de définition n’apparaît pas lors du survol souris.

L’entrée d’une abréviation dans le formulaire de saisie du plugin « acronymes » peut se faire :

  • au moment de la rédaction d’un article : l’abréviation est saisie en lettres capitales sans point séparateur directement dans le corps de l’article, mais sa clarification n’est pas précisée. Ne pas oublier de passer par le formulaire de saisie du plugin « acronymes » et de renseigner l’abréviation comme mot-clé du groupe de mots « glossaire ». Il n’est pas nécessaire d’associer à une abréviation définie dans le formulaire de saisie du plugin « acronymes », la création d’un mot-clé correspondant dans le groupe de mots « glossaire », si la définition dans le glossaire ne contient que l’expansion de l’abréviation sans information complémentaire ;
  • avant la rédaction d’un article. Suivre la même procédure que celle qui vient d’être décrite. La seule différence est qu’après la rédaction d’un article et le click sur l’onglet « Voir » du porte-plume, l’abréviation est immédiatement traitée comme telle au niveau du code ;
  • après la rédaction d’un article. Même procédure que ci-dessus.

L’entrée d’une expression (qui n’est pas une abréviation) dans le glossaire peut se faire selon les 3 mêmes modes que décrits précédemment, la seule différence étant que seule est renseignée la définition d’un mot-clé du groupe « glossaire » (aucun passage par le formulaire de saisie d’un sigle/acronyme).

Effets sur le site

En présence d’un mot du glossaire ou d’une abréviation, le comportement des pages est le suivant :

  1. Si le terme est une abréviation dont l’expansion n’est pas complétée par une définition approfondie dans le glossaire, le simple survol de la souris ou la lecture de l’attribut title de la balise par un lecteur d’écran donne accès à la clarification (c’est-à-dire l’expansion) de l’abréviation ;
  2. Si le terme n’est pas une abréviation et a une définition associée dans le glossaire, alors cette définition est accessible au survol de la souris par une petite fenêtre en surimpression sur le texte (obtenue par CSS, pour les utilisateurs voyants) et à travers l’activation d’un lien vers la page contenant la définition pour les utilisateurs de lecteurs d’écran (l’attribut title de la balise <a> contient outre le terme à définir, la précision sur la destination du lien « Définition dans le glossaire ») ;
  3. Si le terme est une abréviation dont l’expansion est complétée par une définition approfondie dans le glossaire, l’expansion et la définition complète sont accessibles tous les 2 par une combinaison des moyens précédents.

Recherche des abréviations potentielles dans les articles

Il est possible, pour des articles déjà rédigés (par forcément publiés) de rechercher d’éventuelles abréviations qui n’ont pas d’entrée dans la table sigles/acronymes, afin de détecter les abréviations manquantes. Le plugin « acronymes » fournit un squelette acronymes_voir.html qui recherche, dans tous les articles, tous les mots écrits en majuscule : parmi eux, les abréviations déjà définies, et des abréviations potentielles.

Afin de distinguer celles qui sont déjà définies (elles sont encadrées par des balises <abbr></abbr>) de celles qui ne le sont pas, il faut modifier le code du squelette acronymes_voir.html en y ajoutant un style CSS local entre les balises <head></head> :

[ (#REM) Définition d'un style particulier pour les abréviations déjà reconnues, mises en surbrillance]
<style type="text/css">
        abbr {background: #9F3603;color: #fff;padding: 0 0.5em 0.2em;}
</style>

Puis dans la section <body> le code suivant :

<h1>Recherche des abréviations potentielles dans les articles</h1>
                [(#REM) Articles trouves ]
                <BOUCLE_recherche(ARTICLES){tout}{!par date}>               
                        <h2 class="spip"><a name="art#ID_ARTICLE"></a><a href='#URL_ARTICLE'>#TITRE</a></h2>
                        <ul class="spip">
                        <li>[Dans le titre : (#TITRE|acronymes_voir|acronymes_ajouter)]</li>
                        <li>[Dans le sous-titre : (#SOUSTITRE|acronymes_voir|acronymes_ajouter)]</li>
                        <li>[Dans le descriptif : (#DESCRIPTIF|acronymes_voir|acronymes_ajouter)]</li>
                        <li>[Dans le chapo : (#CHAPO|acronymes_voir|acronymes_ajouter)]</li>
                        <li>[Dans le texte : (#TEXTE|acronymes_voir|acronymes_ajouter)]</li>
                        </ul>
                </BOUCLE_recherche>
                <p><a href="ecrire/?exec=sigles_tous">Gérer les acronymes</a></p>

Vous pouvez voir le résultat sur ce site : les abréviations déjà renseignées dans la table sigles/acronymes sont mises en surbrillance ; parmi les mots en majuscule, c’est au rédacteur de vérifier si ceux-ci sont susceptibles d’être renseignés dans la table sigles/acronymes, et de le faire le cas échéant.

Ce squelette boucle sur les articles publiés dans toutes les rubriques. Il est possible de chercher dans tous les articles publiés ou non, sauf ceux à la poubelle en écrivant :

<BOUCLE_recherche(ARTICLES){tout}{statut!=poubelle}{!par date}>

Les inconvénients de l’automatisation des traitements

Les problèmes qui peuvent rester posés sont ceux de la gestion des changements de langue (voir Le codage des abréviations appartenant à une langue étrangère). Il est en effet difficile d’automatiser le fait qu’une abréviation étrangère puisse être prononcée en français (son expansion étant elle prononcée en anglais) selon qu’elle se trouve dans un segment de texte anglais ou français : l’automatisation ne peut pas tenir compte de ce type de contexte, mais ces cas sont très rares.

Certaines abréviations sont orthographiées de la même façon qu’un mot ayant une signification complètement différente : les filtres acronymes et glossaire ne font aucune distinction bien entendu (sauf le filtre acronymes qui ne reconnaît ces mots que s’ils sont en majuscule), ce qui peut poser problème. Par exemple, l’abréviation CAS (Central Authentication Service) peut être reconnue par le filtre glossaire (car celui-ci est insensible à la casse) dans des expressions françaises n’ayant rien à voir : « dans ce cas », « dans tous les cas »…

Pour éviter cet inconvénient, il faudrait une intervention humaine en permettant au rédacteur de positionner une balise particulière qui désactive ou empêche la reconnaissance du terme par les filtres acronymes et glossaire. Mais il y a une façon plus simple de gérer le problème :

L’exemple concernant l’abréviation CAS peut se corriger a posteriori de la constatation du problème en modifiant le titre du mot dans le glossaire en ajoutant un point entre chaque lettre (C.A.S) : ainsi dans les expressions « dans ce cas », « dans tous les cas », etc. le filtre glossaire ne reconnaît plus le mot. Quant au filtre acronyme, celui-ci ne reconnaît que les abréviations en majuscule, donc pas de souci.

Le seul inconvénient à cette méthode est qu’ensuite le terme CAS est reconnu uniquement par le filtre acronymes (que ce terme soit saisi avec ou sans [1] point dans la table des sigles/acronymes), ce qui prive l’utilisateur de l’accès à une définition plus complète que la seule expansion de l’abréviation, mais le minimum est là.

Problèmes résiduels non solutionnés

fenêtre de définition

La fenêtre de définition d’un mot du glossaire apparaissant au survol de ce mot par la souris n’affiche pas les liens contenus dans la définition, ce qui peut affecter la bonne compréhension de celle-ci (seuls les voyants ont ce problème, car les lecteurs d’écran n’ont pas accès à cette fenêtre, la définition est de toutes façon accessible par l’activation du lien vers l’entrée du glossaire : à cet endroit, tout utilisateur a accès à la définition complète, les liens éventuels qu’elle contient étant affichés). Ce comportement est certainement dû au fait que le filtre glossaire échappe les balises <a> au cours de son traitement…

Codage direct des abréviations dans le texte d’un article

Il est possible de coder directement les abréviations dans le texte d’un article avec la balise <abbr> : dans ce cas, le filtre acronymes n’intervient pas, ce qui a pour conséquence que c’est l’attribut title de cette balise qui sera affiché (et non pas celui d’une entrée dans la table sigles/acronymes). Ceci présente l’intérêt de ne pas avoir à retoucher le texte d’un article si les abréviations ont été introduites comme indiquées et que le plugin « acronymes » a été installé plus tard SAUF si le texte de l’article contient des balises <abbr> contenant une balise <span lang="fr">.

Par exemple, si le texte suivant est le le corps de l’article :

<abbr lang="en" title="Central Authentication Service">
 <span lang="fr">CAS</span>
</abbr>

Alors l’abréviation située entre les balises <span lang="fr"></span> sera reconnue par le filtre acronymes, ce qui provoquera l’insertion d’une balise <abbr> lors du traitement ; on se retrouvera alors avec le code suivant :

<abbr lang="en" title="Central Authentication Service">
 <span lang="fr">
    <abbr lang="en" title="Central Authentication Service">CAS</abbr>
 </span>
</abbr>

En conséquence, si on a installé le plugin « acronyme » après avoir saisi directement dans le texte une balise <abbr>, il faudrait rechercher les articles qui ont ce type de balise, et vérifier que la balise <abbr> ne contient pas elle-même une balise <span> : si c’est le cas, alors il faut supprimer ce code dans le texte de l’article et définir l’abréviation dans la table sigles/acronymes pour que le filtre acronyme se charge de coder correctement les choses.

Attributs de la balise <a> encadrant un mot du glossaire

L’attribut lang de cette balise <a> devrait être prise dans la table des sigles/acronymes plutôt que dans la table glossaire dans la mesure où on ne peut pas mettre de <multi> dans le titre du mot d’un glossaire si c’est en même temps une abréviation renseignée dans la table sigles/acronymes avec un <multi>. Par exemple, avec JAWS, L’attribut lang de la balise <a> correspondante vaut « fr ». Cependant, la recherche dans la table sigles/acronymes du fait de sa structure morcelée, est rendu très difficile depuis un squelette comme glossaire_attributs_a.html du fait qu’il ne semble pas possible de faire une recherche autrement qu’avec le filtre recherche_donnee qui effectue une requête LIKE%% de l’abréviation dans tous les champs du formulaire sigles/acronymes au lieu de le cibler sur le champ ligne_1. De guerre lasse pour trouver la solution, j’ai laissé les choses en l’état.

Mise à jour des plugins

Si le plugin Couteau Suisse est compatible avec la version 3 de SPIP (donc sa lame glossaire avec), ce ne sera pas le cas de Forms&Tables, nécessaire au plugin acronymes. D’après son auteur, il n’y a pas de portage prévu vers la version 3, le développement est donc figé.

Cela signifie qu’avec SPIP 3, on ne pourra pas utiliser le plugin « acronymes » qui permet l’insertion dans le code de balises <abbr>, contrairement à la lame glossaire, qui ne distingue pas sémantiquement les abréviations du reste des termes à définir.

Il semble qu’il y ait un plugin « dictionnaires » en cours de développement qui pourrait remplacer l’association plugin acronymes + lame glossaire, mais je n’ai pas eu le temps de tester, il faut voir si c’est correct sur les plans sémantique et accessibilité.

Prononciation des abréviations

Certaines abréviations, malgré l’indication de la langue sont mal prononcées par les synthèses vocales : par exemple EPLE qui devraît être prononcé « èple ». Il s’agit là à la fois d’un problème de phonétique et de convention, et le code XHTML ne permet pas d’apporter cette information aux lecteurs d’écran, je ne vois pas de solution. J’avais pensé un temps à l’utilisation d’un attribut ARIA comme aria-describedby qui référencerait un <span> caché à l’écran par CSS dont le contenu donnerait la bonne prononciation du terme, mais je n’ai pas testé pour savoir comment réagirait un lecteur d’écran, et je ne suis pas sûr que cette utilisation serait valide.

Problème avec certaines abréviations

Par exemple « Monsieur », abrégé très souvent en « M. ». Comme le filtre acronyme ne tient pas compte des points entre les lettres de l’abréviation un « M » dans le texte sera filtré de la même façon q’un « M. ». En conséquence, si « M. » est renseigné dans la table sigles/acronymes, les phrases commençant (ou contenant) un M majuscule se verront codées avec une balise <abbr title="Monsieur"> encadrant ce M !

Du coup, on peut pas se servir de cette abréviation, il faudra toujours écrire l’expansion correspondante.

Notes

[1] Dans la table des sigles/acronymes, l’abréviation peut-être saisie avec ou sans point séparateur entre les lettres, la reconnaissance par le filtre acronymes y est indifférente