@surea11y/core 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/README.md +382 -81
- package/docs/ENGINE_OPTIONS.md +97 -4
- package/docs/I18N.md +3 -3
- package/docs/OUTPUT_SCHEMA.md +5 -5
- package/docs/RULE_TAXONOMY.md +9 -8
- package/docs/TROUBLESHOOTING.md +3 -3
- package/docs/WCAG_CONFORMANCE.md +1 -1
- package/package.json +3 -2
- package/src/checks/automatic/aria-allowed-attr.js +47 -24
- package/src/core/dom-helpers.js +48 -16
- package/src/core/dom-runner.js +17 -0
- package/src/core.js +1173 -87
- package/src/i18n/fr.js +314 -1
package/src/core.js
CHANGED
|
@@ -7932,7 +7932,320 @@ const I18N = {
|
|
|
7932
7932
|
"labelInName_title": "Intitulé dans le nom : le nom accessible contient le texte visible",
|
|
7933
7933
|
"labelInName_description": "Vérifie que lorsqu’un composant possède un libellé textuel visible, le nom accessible contient ce libellé visible (WCAG 2.5.3).",
|
|
7934
7934
|
"labelInName_summary_fail": "{{element}} : le libellé visible « {{visibleLabel}} » (source : {{labelSource}}) n’est pas inclus dans le nom accessible (source : {{nameMechanism}}).",
|
|
7935
|
-
"labelInName_hint_fail": "Modifiez aria-label ou aria-labelledby (ou le texte du libellé visible) afin que le nom accessible inclue le libellé visible."
|
|
7935
|
+
"labelInName_hint_fail": "Modifiez aria-label ou aria-labelledby (ou le texte du libellé visible) afin que le nom accessible inclue le libellé visible.",
|
|
7936
|
+
"ariaRolesValid_title": "L’attribut role doit être un rôle ARIA valide et non abstrait",
|
|
7937
|
+
"ariaRolesValid_description": "Vérifie qu’un attribut role=\"\" explicite correspond à un rôle WAI-ARIA réel et non abstrait.",
|
|
7938
|
+
"ariaRolesValid_summary_invalid": "role=\"{{role}}\" n’est pas un rôle ARIA reconnu.",
|
|
7939
|
+
"ariaRolesValid_hint_invalid": "Utilisez un rôle ARIA valide, ou retirez l’attribut role si aucun ne s’applique.",
|
|
7940
|
+
"ariaRolesValid_summary_abstract": "role=\"{{role}}\" est un rôle ARIA abstrait, qui ne doit pas être utilisé directement.",
|
|
7941
|
+
"ariaRolesValid_hint_abstract": "Remplacez ce rôle abstrait par un rôle concret adapté au composant/à la structure.",
|
|
7942
|
+
"ariaDeprecatedRole_title": "L’attribut role ne doit pas utiliser un rôle ARIA obsolète ou interdit aux auteurs",
|
|
7943
|
+
"ariaDeprecatedRole_description": "Vérifie qu’un attribut role=\"\" explicite n’utilise pas un rôle rendu obsolète par la spécification WAI-ARIA, ni un rôle réservé à un usage interne à l’agent utilisateur (ex. role=\"generic\").",
|
|
7944
|
+
"ariaDeprecatedRole_summary_fail": "Cet élément utilise role=\"{{role}}\", que les auteurs ne doivent pas déclarer explicitement.",
|
|
7945
|
+
"ariaDeprecatedRole_hint_fail": "{{guidance}}",
|
|
7946
|
+
"ariaValidAttr_title": "Les attributs aria-* doivent être des attributs ARIA réels et définis",
|
|
7947
|
+
"ariaValidAttr_description": "Vérifie que chaque nom d’attribut aria-* présent dans le DOM est un attribut réel défini par la spécification WAI-ARIA.",
|
|
7948
|
+
"ariaValidAttr_summary_fail": "{{attr}} n’est pas un attribut ARIA reconnu.",
|
|
7949
|
+
"ariaValidAttr_hint_fail": "Corrigez le nom de l’attribut (vérifiez les fautes de frappe), ou retirez-le s’il n’est pas nécessaire.",
|
|
7950
|
+
"ariaValidAttrValue_title": "Les valeurs des attributs aria-* doivent correspondre à leur type déclaré",
|
|
7951
|
+
"ariaValidAttrValue_description": "Vérifie que chaque attribut aria-* reconnu a une valeur conforme à son type déclaré par WAI-ARIA (booléen, tri-état, jeton, entier, nombre ou référence d’ID).",
|
|
7952
|
+
"ariaValidAttrValue_summary_fail": "{{attr}}=\"{{value}}\" n’est pas une valeur valide pour cet attribut.",
|
|
7953
|
+
"ariaValidAttrValue_hint_fail": "Utilisez une valeur correspondant au type attendu de l’attribut (consultez la spécification WAI-ARIA pour cet attribut).",
|
|
7954
|
+
"ariaAllowedAttr_title": "Les attributs aria-* doivent être autorisés pour le rôle de l’élément",
|
|
7955
|
+
"ariaAllowedAttr_description": "Vérifie que chaque attribut aria-* reconnu présent sur un élément ayant un rôle explicite est soit globalement pris en charge, soit pris en charge par ce rôle.",
|
|
7956
|
+
"ariaAllowedAttr_summary_fail": "{{attr}} n’est pas autorisé sur role=\"{{role}}\".",
|
|
7957
|
+
"ariaAllowedAttr_hint_fail": "Retirez cet attribut, ou utilisez un rôle qui le prend en charge.",
|
|
7958
|
+
"ariaProhibitedAttr_title": "Les attributs de nommage ARIA ne doivent pas être utilisés sur des rôles qui les interdisent",
|
|
7959
|
+
"ariaProhibitedAttr_description": "Vérifie que aria-label/aria-labelledby ne sont pas présents sur des rôles WAI-ARIA dont la spécification interdit explicitement le nommage ARIA (ex. generic, emphasis, strong, paragraph).",
|
|
7960
|
+
"ariaProhibitedAttr_summary_fail": "{{attr}} est interdit sur role=\"{{role}}\".",
|
|
7961
|
+
"ariaProhibitedAttr_hint_fail": "Retirez cet attribut ; ce rôle ne doit pas porter de nom accessible.",
|
|
7962
|
+
"ariaRequiredAttr_title": "Les rôles avec un état/une propriété ARIA requis doivent le porter",
|
|
7963
|
+
"ariaRequiredAttr_description": "Vérifie que les éléments ayant un rôle explicite portent chaque état/propriété aria-* requis, non ambigu et indépendant du contexte, pour ce rôle (ex. role=\"checkbox\" doit avoir aria-checked).",
|
|
7964
|
+
"ariaRequiredAttr_summary_fail": "{{attr}} est requis pour role=\"{{role}}\", mais est absent.",
|
|
7965
|
+
"ariaRequiredAttr_hint_fail": "Ajoutez cet attribut avec une valeur valide pour ce rôle.",
|
|
7966
|
+
"ariaAllowedRole_title": "Le rôle explicite doit être autorisé pour son élément hôte",
|
|
7967
|
+
"ariaAllowedRole_description": "Vérifie qu’un attribut role=\"\" explicite fait partie des rôles que la spécification ARIA-in-HTML autorise pour l’élément hôte (ex. role=\"tab\" n’est pas autorisé sur <nav>).",
|
|
7968
|
+
"ariaAllowedRole_summary_fail": "role=\"{{role}}\" n’est pas autorisé sur <{{element}}>.",
|
|
7969
|
+
"ariaAllowedRole_hint_fail": "Utilisez un rôle autorisé pour cet élément, ou changez l’élément hôte.",
|
|
7970
|
+
"ariaRequiredChildren_title": "Les rôles conteneurs doivent posséder au moins un rôle enfant requis",
|
|
7971
|
+
"ariaRequiredChildren_description": "Vérifie que les rôles conteneurs disposant d’une entrée documentée « éléments possédés requis » (list, listbox, menu, radiogroup, table, grid, tablist, tree, row, ...) contiennent au moins un descendant, ou un élément référencé par aria-owns, ayant un rôle possédé acceptable.",
|
|
7972
|
+
"ariaRequiredChildren_summary_fail": "role=\"{{role}}\" ne possède aucun enfant ayant l’un des rôles requis : {{requiredRoles}}.",
|
|
7973
|
+
"ariaRequiredChildren_hint_fail": "Ajoutez un descendant (ou un élément référencé par aria-owns) ayant l’un des rôles possédés requis.",
|
|
7974
|
+
"ariaProhibitedChildren_title": "Les rôles conteneurs ne doivent pas posséder d’enfant ayant un rôle interdit",
|
|
7975
|
+
"ariaProhibitedChildren_description": "Vérifie que chaque enfant possédé (dans l’arbre d’accessibilité) d’un rôle conteneur (list, listbox, menu, menubar, radiogroup, rowgroup, table, grid, treegrid, tablist, tree, row) a l’un des rôles possédés autorisés par ce rôle.",
|
|
7976
|
+
"ariaProhibitedChildren_summary_fail": "Cet élément a le rôle role=\"{{childRole}}\", qui n’est pas un rôle enfant possédé autorisé par le conteneur englobant role=\"{{containerRole}}\".",
|
|
7977
|
+
"ariaProhibitedChildren_hint_fail": "Retirez ou modifiez ce rôle afin qu’il corresponde à l’un des rôles possédés autorisés du conteneur ({{allowedRoles}}), ou déplacez cet élément hors du conteneur {{containerRole}}.",
|
|
7978
|
+
"ariaProhibitedChildren_summary_fail_roleless": "Cet élément n’a pas de rôle explicite mais porte {{attr}}, ce qui en fait un véritable nœud de l’arbre d’accessibilité qui n’est pas un enfant possédé autorisé du conteneur englobant role=\"{{containerRole}}\".",
|
|
7979
|
+
"ariaProhibitedChildren_hint_fail_roleless": "Retirez {{attr}} (ou la relation de possession avec le conteneur role=\"{{containerRole}}\"), ou attribuez à cet élément role=\"presentation\"/\"none\" s’il n’est pas censé constituer son propre nœud dans l’arbre d’accessibilité.",
|
|
7980
|
+
"ariaRequiredParent_title": "Les rôles exigeant un rôle de contexte spécifique doivent se trouver dans ce contexte",
|
|
7981
|
+
"ariaRequiredParent_description": "Vérifie que les rôles disposant d’une entrée documentée « rôle de contexte requis » (listitem, option, tab, treeitem, row, cell, ...) ont un ancêtre, ou un propriétaire aria-owns, ayant un rôle de contexte acceptable.",
|
|
7982
|
+
"ariaRequiredParent_summary_fail": "role=\"{{role}}\" exige un rôle de contexte parmi : {{requiredRoles}}, qui n’a pas été trouvé.",
|
|
7983
|
+
"ariaRequiredParent_hint_fail": "Placez cet élément à l’intérieur d’un élément ayant un rôle de contexte acceptable (ou référencez-le depuis celui-ci via aria-owns).",
|
|
7984
|
+
"deprecatedElements_title": "Les éléments obsolètes non interruptibles (<blink>, <marquee>) ne doivent pas être utilisés",
|
|
7985
|
+
"deprecatedElements_description": "Vérifie que les éléments HTML obsolètes et non standards dont le contenu clignotant/défilant ne peut pas être mis en pause, arrêté ou masqué par l’utilisateur (<blink>, <marquee>) ne sont pas présents.",
|
|
7986
|
+
"deprecatedElements_summary_fail": "Le contenu de <{{element}}> ne peut pas être mis en pause, arrêté ou masqué par l’utilisateur.",
|
|
7987
|
+
"deprecatedElements_hint_fail": "Retirez cet élément ; utilisez à la place un contenu statique, ou une animation dotée d’un contrôle de pause/arrêt accessible à l’utilisateur.",
|
|
7988
|
+
"iframeNamePresent_title": "Les cadres ont un nom accessible",
|
|
7989
|
+
"iframeNamePresent_description": "Vérifie que les éléments <iframe>/<frame> exposent un nom accessible non vide via aria-label, aria-labelledby, ou l’attribut title.",
|
|
7990
|
+
"iframeNamePresent_summary_fail": "Ce <{{element}}> n’a pas de nom accessible.",
|
|
7991
|
+
"iframeNamePresent_hint_fail": "Ajoutez un attribut title (ou aria-label/aria-labelledby) décrivant le contenu ou l’objet du cadre.",
|
|
7992
|
+
"iframeTitleUnique_title": "Les titres de cadres doivent être uniques",
|
|
7993
|
+
"iframeTitleUnique_description": "Vérifie qu’aucun <iframe>/<frame> dans le périmètre analysé ne partage la même valeur d’attribut title qu’un autre.",
|
|
7994
|
+
"iframeTitleUnique_summary_fail": "Le titre « {{title}} » de ce <{{element}}> n’est pas unique parmi les cadres de cette page.",
|
|
7995
|
+
"iframeTitleUnique_hint_fail": "Donnez à chaque cadre un titre distinct décrivant son contenu ou son objet spécifique.",
|
|
7996
|
+
"iframeFocusableContent_title": "Les cadres avec tabindex=\"-1\" ne doivent pas contenir de contenu focalisable",
|
|
7997
|
+
"iframeFocusableContent_description": "Vérifie que les éléments <iframe>/<frame> de même origine avec tabindex=\"-1\" ne contiennent pas de contenu focalisable, car les navigateurs ne propagent pas cette restriction au document intégré du cadre.",
|
|
7998
|
+
"iframeFocusableContent_summary_fail": "Ce <{{element}}> a tabindex=\"-1\" mais son contenu contient des éléments focalisables, qui restent accessibles au clavier.",
|
|
7999
|
+
"iframeFocusableContent_hint_fail": "Retirez le contenu focalisable du cadre, ou retirez tabindex=\"-1\" si le cadre est censé être accessible.",
|
|
8000
|
+
"tableHeadersAttrValid_title": "L’attribut headers d’une cellule de tableau doit référencer des cellules d’en-tête valides",
|
|
8001
|
+
"tableHeadersAttrValid_description": "Vérifie que chaque id de l’attribut headers d’un <td>/<th> correspond à un élément <th> du même tableau (ni absent, ni un élément autre que th, ni lui-même).",
|
|
8002
|
+
"tableHeadersAttrValid_summary_fail": "L’attribut headers de ce <{{element}}> référence des cellules d’en-tête invalides : {{invalidIds}}.",
|
|
8003
|
+
"tableHeadersAttrValid_hint_fail": "Mettez à jour l’attribut headers afin que chaque id désigne un élément <th> du même tableau.",
|
|
8004
|
+
"tableThHasDataCells_title": "Les éléments <th> doivent décrire au moins une cellule de données",
|
|
8005
|
+
"tableThHasDataCells_description": "Vérifie qu’un tableau contenant des éléments <th> contient aussi au moins une cellule de données <td> que ces en-têtes décrivent.",
|
|
8006
|
+
"tableThHasDataCells_summary_fail": "Ce tableau a des cellules d’en-tête mais aucune cellule de données à décrire.",
|
|
8007
|
+
"tableThHasDataCells_hint_fail": "Ajoutez des cellules de données (<td>) au tableau, ou retirez les cellules d’en-tête si le tableau n’a pas de données.",
|
|
8008
|
+
"ariaHiddenBody_title": "Le <body> du document ne doit pas être aria-hidden",
|
|
8009
|
+
"ariaHiddenBody_description": "Vérifie que <body> n’a pas aria-hidden=\"true\", ce qui retirerait toute la page de l’arbre d’accessibilité.",
|
|
8010
|
+
"ariaHiddenBody_summary_fail": "Le corps du document a aria-hidden=\"true\", ce qui masque toute la page aux technologies d’assistance.",
|
|
8011
|
+
"ariaHiddenBody_hint_fail": "Retirez aria-hidden de <body>. Masquez des éléments spécifiques à la place, si c’était l’intention.",
|
|
8012
|
+
"listChildrenValid_title": "Les listes ne doivent contenir directement que des éléments de liste",
|
|
8013
|
+
"listChildrenValid_description": "Vérifie que les éléments <ul>/<ol> n’ont comme enfants directs que <li>, <script> ou <template>.",
|
|
8014
|
+
"listChildrenValid_summary_fail": "Ce <{{element}}> contient un enfant direct qui n’est pas un élément de liste : {{invalidChildren}}.",
|
|
8015
|
+
"listChildrenValid_hint_fail": "N’utilisez que <li> (ou <script>/<template>) comme enfants directs de <ul>/<ol> ; déplacez tout autre balisage à l’intérieur d’un <li>.",
|
|
8016
|
+
"listitemParentValid_title": "Les éléments de liste doivent se trouver à l’intérieur d’un conteneur de liste",
|
|
8017
|
+
"listitemParentValid_description": "Vérifie que les éléments <li> sont contenus par <ul>, <ol>, ou un élément ayant role=\"list\".",
|
|
8018
|
+
"listitemParentValid_summary_fail": "Le parent de cet élément de liste (<{{parentElement}}>) n’est pas un conteneur de liste.",
|
|
8019
|
+
"listitemParentValid_hint_fail": "Placez ce <li> à l’intérieur d’un <ul>/<ol>, ou donnez à son parent role=\"list\".",
|
|
8020
|
+
"definitionListChildrenValid_title": "Les listes de définitions doivent être structurées correctement",
|
|
8021
|
+
"definitionListChildrenValid_description": "Vérifie que les éléments <dl> ne contiennent directement que des groupes <dt>/<dd> (éventuellement enveloppés dans un seul <div>), <script>, <template>, ou <style>.",
|
|
8022
|
+
"definitionListChildrenValid_summary_fail_invalidChild": "Cette liste de définitions contient un enfant direct ou enveloppé qui ne fait pas partie d’un groupe dt/dd : {{invalidChildren}}.",
|
|
8023
|
+
"definitionListChildrenValid_hint_fail_invalidChild": "N’utilisez que <dt>/<dd> (éventuellement enveloppés dans un seul <div>), <script>, <template>, ou <style> à l’intérieur de <dl>.",
|
|
8024
|
+
"definitionListChildrenValid_summary_fail_noDtDd": "Cette liste de définitions n’a aucun groupe terme/définition <dt>/<dd>.",
|
|
8025
|
+
"definitionListChildrenValid_hint_fail_noDtDd": "Ajoutez au moins une paire <dt>/<dd> à l’intérieur de ce <dl>.",
|
|
8026
|
+
"dlitemParentValid_title": "Les éléments d’une liste de définitions doivent se trouver à l’intérieur d’une liste de définitions",
|
|
8027
|
+
"dlitemParentValid_description": "Vérifie que les éléments <dt>/<dd> sont contenus par un <dl>, directement ou via un <div> englobant.",
|
|
8028
|
+
"dlitemParentValid_summary_fail": "Le parent (<{{parentElement}}>) de ce <{{element}}> n’est pas une liste de définitions.",
|
|
8029
|
+
"dlitemParentValid_hint_fail": "Placez ce <dt>/<dd> à l’intérieur d’un <dl>, directement ou enveloppé dans un seul <div>.",
|
|
8030
|
+
"duplicateIdAria_title": "Les ID référencés par ARIA doivent être uniques",
|
|
8031
|
+
"duplicateIdAria_description": "Vérifie que toute valeur id référencée par un attribut de référence d’ID ARIA (aria-labelledby, aria-describedby, aria-owns, aria-controls, aria-activedescendant, aria-flowto, aria-errormessage, aria-details) est unique dans le document.",
|
|
8032
|
+
"duplicateIdAria_summary_fail": "L’id « {{id}} » est référencé par un attribut ARIA mais est utilisé par {{duplicateCount}} éléments.",
|
|
8033
|
+
"duplicateIdAria_hint_fail": "Rendez uniques dans le document les id référencés par des attributs ARIA.",
|
|
8034
|
+
"summaryNamePresent_title": "Les éléments summary ont un nom accessible",
|
|
8035
|
+
"summaryNamePresent_description": "Vérifie que les éléments <summary> exposent un nom accessible non vide.",
|
|
8036
|
+
"summaryNamePresent_summary_fail": "Ce summary n’a pas de nom accessible.",
|
|
8037
|
+
"summaryNamePresent_hint_fail": "Fournissez un texte de summary qui ne soit pas masqué aux technologies d’assistance, ou fournissez aria-label ou aria-labelledby.",
|
|
8038
|
+
"metaViewportZoomEnabled_title": "La balise meta viewport ne doit pas désactiver le zoom",
|
|
8039
|
+
"metaViewportZoomEnabled_description": "Vérifie que <meta name=\"viewport\"> ne définit pas user-scalable=no ni maximum-scale en dessous de 2 (200 %).",
|
|
8040
|
+
"metaViewportZoomEnabled_summary_fail": "Cette balise meta viewport restreint la capacité de l’utilisateur à zoomer ({{reasons}}).",
|
|
8041
|
+
"metaViewportZoomEnabled_hint_fail": "Retirez user-scalable=no et tout maximum-scale inférieur à 2 du contenu de la balise meta viewport.",
|
|
8042
|
+
"metaRefreshTimingAbsent_title": "La page ne doit pas utiliser un rafraîchissement meta minuté",
|
|
8043
|
+
"metaRefreshTimingAbsent_description": "Vérifie que <meta http-equiv=\"refresh\"> n’impose pas un délai positif de 20 heures ou moins.",
|
|
8044
|
+
"metaRefreshTimingAbsent_summary_fail": "Cette page se rafraîchit automatiquement après {{delay}} secondes.",
|
|
8045
|
+
"metaRefreshTimingAbsent_hint_fail": "Retirez le rafraîchissement meta minuté, ou proposez un moyen pour les utilisateurs de le désactiver, de le prolonger ou de le mettre en pause avant qu’il ne se déclenche.",
|
|
8046
|
+
"meterNamePresent_title": "Les éléments meter ont un nom accessible",
|
|
8047
|
+
"meterNamePresent_description": "Vérifie que les éléments avec role=\"meter\" exposent un nom accessible non vide.",
|
|
8048
|
+
"meterNamePresent_summary_fail": "Ce meter n’a pas de nom accessible.",
|
|
8049
|
+
"meterNamePresent_hint_fail": "Fournissez un texte pour le meter qui ne soit pas masqué aux technologies d’assistance, ou fournissez aria-label ou aria-labelledby.",
|
|
8050
|
+
"progressbarNamePresent_title": "Les barres de progression ont un nom accessible",
|
|
8051
|
+
"progressbarNamePresent_description": "Vérifie que les éléments avec role=\"progressbar\" exposent un nom accessible non vide.",
|
|
8052
|
+
"progressbarNamePresent_summary_fail": "Cette barre de progression n’a pas de nom accessible.",
|
|
8053
|
+
"progressbarNamePresent_hint_fail": "Fournissez un texte pour la barre de progression qui ne soit pas masqué aux technologies d’assistance, ou fournissez aria-label ou aria-labelledby.",
|
|
8054
|
+
"tooltipNamePresent_title": "Les infobulles ont un nom accessible",
|
|
8055
|
+
"tooltipNamePresent_description": "Vérifie que les éléments avec role=\"tooltip\" exposent un nom accessible non vide.",
|
|
8056
|
+
"tooltipNamePresent_summary_fail": "Cette infobulle n’a pas de nom accessible.",
|
|
8057
|
+
"tooltipNamePresent_hint_fail": "Fournissez un texte pour l’infobulle qui ne soit pas masqué aux technologies d’assistance, ou fournissez aria-label ou aria-labelledby.",
|
|
8058
|
+
"serverSideImageMapAbsent_title": "Les images ne doivent pas utiliser une carte d’image côté serveur",
|
|
8059
|
+
"serverSideImageMapAbsent_description": "Vérifie que les éléments <img> ne portent pas l’attribut ismap (les cartes d’image côté serveur n’ont pas d’équivalent utilisable au clavier).",
|
|
8060
|
+
"serverSideImageMapAbsent_summary_fail": "Cette image utilise une carte d’image côté serveur, qui n’a pas d’équivalent utilisable au clavier.",
|
|
8061
|
+
"serverSideImageMapAbsent_hint_fail": "Remplacez la carte d’image côté serveur (ismap) par une carte d’image côté client (<map>/<area>) ou par des liens/boutons accessibles distincts.",
|
|
8062
|
+
"formControlSingleLabel_title": "Les contrôles de formulaire ne doivent pas avoir plusieurs étiquettes",
|
|
8063
|
+
"formControlSingleLabel_description": "Vérifie qu’un contrôle de formulaire est associé à au plus un <label> (par imbrication ou par label[for]).",
|
|
8064
|
+
"formControlSingleLabel_summary_fail": "Ce <{{element}}> est associé à {{labelCount}} étiquettes.",
|
|
8065
|
+
"formControlSingleLabel_hint_fail": "Conservez une seule <label> par contrôle de formulaire (soit en l’enveloppant, soit en la référençant via for/id).",
|
|
8066
|
+
"nestedInteractiveControlsAbsent_title": "Les contrôles interactifs ne doivent pas être imbriqués",
|
|
8067
|
+
"nestedInteractiveControlsAbsent_description": "Vérifie qu’un contrôle interactif (lien, bouton, contrôle de formulaire, ou rôle de widget ARIA) ne contient pas un autre contrôle interactif.",
|
|
8068
|
+
"nestedInteractiveControlsAbsent_summary_fail": "Ce <{{element}}> contient un ou plusieurs contrôles interactifs imbriqués : {{nestedElements}}.",
|
|
8069
|
+
"nestedInteractiveControlsAbsent_hint_fail": "Déplacez le(s) contrôle(s) interactif(s) imbriqué(s) hors de cet élément ; les contrôles interactifs imbriqués ne sont pas utilisables de façon fiable via les technologies d’assistance.",
|
|
8070
|
+
"bypassBlocksPresent_title": "La page doit proposer un moyen de contourner les blocs répétés",
|
|
8071
|
+
"bypassBlocksPresent_description": "Vérifie que la page dispose d’au moins un mécanisme reconnu de contournement des blocs répétés (WCAG 2.4.1) : un point de repère main, un lien d’ancrage fonctionnel vers la même page, ou un titre.",
|
|
8072
|
+
"bypassBlocksPresent_summary_fail": "Cette page n’a aucun moyen reconnu de contourner les blocs de contenu répétés.",
|
|
8073
|
+
"bypassBlocksPresent_hint_fail": "Ajoutez un point de repère main (<main> ou role=\"main\"), un lien « aller au contenu » fonctionnel, ou des éléments de titre que les technologies d’assistance peuvent utiliser pour passer le contenu répété.",
|
|
8074
|
+
"landmarkBannerIsTopLevel_title": "Le point de repère banner doit être de premier niveau",
|
|
8075
|
+
"landmarkBannerIsTopLevel_description": "Vérifie que le point de repère banner (role=\"banner\" ou un <header> non imbriqué) n’est pas imbriqué dans un autre point de repère.",
|
|
8076
|
+
"landmarkBannerIsTopLevel_summary_cantTell": "Ce point de repère banner est imbriqué dans un autre point de repère.",
|
|
8077
|
+
"landmarkBannerIsTopLevel_hint_cantTell": "Déplacez le point de repère banner (header/role=\"banner\") afin qu’il ne soit contenu par aucun autre point de repère ; un banner doit être une région de premier niveau de la page.",
|
|
8078
|
+
"landmarkContentinfoIsTopLevel_title": "Le point de repère contentinfo doit être de premier niveau",
|
|
8079
|
+
"landmarkContentinfoIsTopLevel_description": "Vérifie que le point de repère contentinfo (role=\"contentinfo\" ou un <footer> non imbriqué) n’est pas imbriqué dans un autre point de repère.",
|
|
8080
|
+
"landmarkContentinfoIsTopLevel_summary_cantTell": "Ce point de repère contentinfo est imbriqué dans un autre point de repère.",
|
|
8081
|
+
"landmarkContentinfoIsTopLevel_hint_cantTell": "Déplacez le point de repère contentinfo (footer/role=\"contentinfo\") afin qu’il ne soit contenu par aucun autre point de repère ; contentinfo doit être une région de premier niveau de la page.",
|
|
8082
|
+
"landmarkMainIsTopLevel_title": "Le point de repère main doit être de premier niveau",
|
|
8083
|
+
"landmarkMainIsTopLevel_description": "Vérifie que le point de repère main (role=\"main\" ou <main>) n’est pas imbriqué dans un autre point de repère.",
|
|
8084
|
+
"landmarkMainIsTopLevel_summary_cantTell": "Ce point de repère main est imbriqué dans un autre point de repère.",
|
|
8085
|
+
"landmarkMainIsTopLevel_hint_cantTell": "Déplacez le point de repère main (<main>/role=\"main\") afin qu’il ne soit contenu par aucun autre point de repère ; main doit être une région de premier niveau de la page.",
|
|
8086
|
+
"landmarkNoDuplicateBanner_title": "La page ne doit pas avoir plus d’un point de repère banner",
|
|
8087
|
+
"landmarkNoDuplicateBanner_description": "Vérifie qu’au plus un point de repère banner (role=\"banner\" ou un <header> non imbriqué) existe sur la page.",
|
|
8088
|
+
"landmarkNoDuplicateBanner_summary_cantTell": "Cette page a plus d’un point de repère banner.",
|
|
8089
|
+
"landmarkNoDuplicateBanner_hint_cantTell": "Ne conservez qu’un seul point de repère banner (header/role=\"banner\") par page.",
|
|
8090
|
+
"landmarkNoDuplicateContentinfo_title": "La page ne doit pas avoir plus d’un point de repère contentinfo",
|
|
8091
|
+
"landmarkNoDuplicateContentinfo_description": "Vérifie qu’au plus un point de repère contentinfo (role=\"contentinfo\" ou un <footer> non imbriqué) existe sur la page.",
|
|
8092
|
+
"landmarkNoDuplicateContentinfo_summary_cantTell": "Cette page a plus d’un point de repère contentinfo.",
|
|
8093
|
+
"landmarkNoDuplicateContentinfo_hint_cantTell": "Ne conservez qu’un seul point de repère contentinfo (footer/role=\"contentinfo\") par page.",
|
|
8094
|
+
"landmarkNoDuplicateMain_title": "La page ne doit pas avoir plus d’un point de repère main",
|
|
8095
|
+
"landmarkNoDuplicateMain_description": "Vérifie qu’au plus un point de repère main (role=\"main\" ou <main>) existe sur la page.",
|
|
8096
|
+
"landmarkNoDuplicateMain_summary_cantTell": "Cette page a plus d’un point de repère main.",
|
|
8097
|
+
"landmarkNoDuplicateMain_hint_cantTell": "Ne conservez qu’un seul point de repère main (<main>/role=\"main\") par page.",
|
|
8098
|
+
"landmarkOneMain_title": "La page devrait avoir un point de repère main",
|
|
8099
|
+
"landmarkOneMain_description": "Vérifie que la page a au moins un point de repère main (role=\"main\" ou <main>).",
|
|
8100
|
+
"landmarkOneMain_summary_cantTell_missing": "Cette page n’a aucun point de repère main.",
|
|
8101
|
+
"landmarkOneMain_hint_cantTell_missing": "Ajoutez un point de repère main (<main> ou role=\"main\") autour du contenu principal de la page.",
|
|
8102
|
+
"landmarkUnique_title": "Les points de repère partageant le même rôle doivent avoir des noms uniques",
|
|
8103
|
+
"landmarkUnique_description": "Vérifie que lorsque deux points de repère ou plus partagent le même rôle, chacun a un nom accessible distinct.",
|
|
8104
|
+
"landmarkUnique_summary_cantTell_duplicateName": "Ce point de repère {{role}} partage son nom accessible avec un autre point de repère {{role}}.",
|
|
8105
|
+
"landmarkUnique_summary_cantTell_bothUnnamed": "Ce point de repère {{role}} n’a pas de nom accessible, et plus d’un point de repère {{role}} sans nom existe sur cette page.",
|
|
8106
|
+
"landmarkUnique_hint_cantTell": "Donnez à chaque point de repère {{role}} un nom distinct via aria-label ou aria-labelledby.",
|
|
8107
|
+
"emptyHeading_title": "Les titres ne doivent pas être vides",
|
|
8108
|
+
"emptyHeading_description": "Vérifie que les éléments de titre (<h1>-<h6> ou role=\"heading\") ont un nom accessible non vide.",
|
|
8109
|
+
"emptyHeading_summary_cantTell": "Ce titre n’a pas de nom accessible.",
|
|
8110
|
+
"emptyHeading_hint_cantTell": "Ajoutez du contenu textuel (ou aria-label/aria-labelledby) à ce titre, ou retirez-le s’il n’est pas nécessaire.",
|
|
8111
|
+
"headingOrder_title": "Les niveaux de titre ne doivent pas sauter un niveau",
|
|
8112
|
+
"headingOrder_description": "Vérifie que les niveaux de titre n’augmentent que d’un niveau à la fois, dans l’ordre du document.",
|
|
8113
|
+
"headingOrder_summary_cantTell": "Ce titre passe du niveau {{fromLevel}} au niveau {{toLevel}}, en sautant un niveau.",
|
|
8114
|
+
"headingOrder_hint_cantTell": "Utilisez des niveaux de titre consécutifs (ne sautez pas de niveau en descendant dans la hiérarchie) afin que le plan du document reste prévisible.",
|
|
8115
|
+
"pageHasHeadingOne_title": "La page devrait avoir un titre de niveau un",
|
|
8116
|
+
"pageHasHeadingOne_description": "Vérifie que la page a au moins un titre de niveau un (<h1> ou role=\"heading\" avec aria-level=\"1\").",
|
|
8117
|
+
"pageHasHeadingOne_summary_cantTell": "Cette page n’a aucun titre de niveau un.",
|
|
8118
|
+
"pageHasHeadingOne_hint_cantTell": "Ajoutez un titre de niveau un (<h1> ou role=\"heading\" aria-level=\"1\") identifiant le contenu principal de la page.",
|
|
8119
|
+
"accesskeys_title": "Les valeurs accesskey doivent être uniques",
|
|
8120
|
+
"accesskeys_description": "Vérifie qu’aucun élément de la page ne partage la même valeur d’attribut accesskey qu’un autre.",
|
|
8121
|
+
"accesskeys_summary_cantTell": "L’accesskey de cet élément est partagée avec un autre élément de la page.",
|
|
8122
|
+
"accesskeys_hint_cantTell": "Rendez chaque valeur accesskey unique sur l’ensemble de la page.",
|
|
8123
|
+
"scopeAttrValid_title": "L’attribut scope doit avoir une valeur valide",
|
|
8124
|
+
"scopeAttrValid_description": "Vérifie que scope=\"...\" vaut row, col, rowgroup, ou colgroup.",
|
|
8125
|
+
"scopeAttrValid_summary_cantTell": "Cette valeur d’attribut scope n’est pas reconnue.",
|
|
8126
|
+
"scopeAttrValid_hint_cantTell": "Utilisez row, col, rowgroup, ou colgroup pour l’attribut scope.",
|
|
8127
|
+
"tabindex_title": "tabindex ne devrait pas être supérieur à 0",
|
|
8128
|
+
"tabindex_description": "Vérifie que les valeurs de tabindex sont égales à 0 ou négatives, jamais un nombre positif.",
|
|
8129
|
+
"tabindex_summary_cantTell": "Cet élément a un tabindex positif, ce qui modifie l’ordre naturel de tabulation.",
|
|
8130
|
+
"tabindex_hint_cantTell": "Utilisez tabindex=\"0\" (ou une valeur négative pour le retirer de l’ordre de tabulation) plutôt qu’un nombre positif ; corrigez l’ordre dans le DOM si un ordre de tabulation différent est nécessaire.",
|
|
8131
|
+
"emptyTableHeader_title": "Les cellules d’en-tête de tableau ne doivent pas être vides",
|
|
8132
|
+
"emptyTableHeader_description": "Vérifie que les éléments <th> ont un contenu textuel visible — un en-tête nommé uniquement via aria-label/aria-labelledby est aussi signalé, car la prise en charge réelle par les lecteurs d’écran/navigateurs est incohérente.",
|
|
8133
|
+
"emptyTableHeader_summary_cantTell": "Cette cellule d’en-tête de tableau n’a pas de nom accessible.",
|
|
8134
|
+
"emptyTableHeader_hint_cantTell": "Ajoutez du contenu textuel (ou aria-label/aria-labelledby) à cette cellule d’en-tête, ou retirez-la si elle n’est pas nécessaire.",
|
|
8135
|
+
"emptyTableHeader_summary_cantTell_ariaOnly": "Cette cellule d’en-tête de tableau n’a pas de texte visible — son seul nom accessible provient de aria-label/aria-labelledby, que des combinaisons réelles de lecteur d’écran/navigateur (ex. NVDA+Firefox, iOS VoiceOver+Safari) sont connues pour ignorer sur les éléments <th>.",
|
|
8136
|
+
"emptyTableHeader_hint_cantTell_ariaOnly": "Ajoutez du contenu textuel visible à cette cellule d’en-tête (en plus de, ou à la place de, aria-label/aria-labelledby) — le texte visible est le seul mécanisme de nommage confirmé comme fonctionnel sur les lecteurs d’écran testés.",
|
|
8137
|
+
"labelTitleOnly_title": "Les contrôles de formulaire ne devraient pas utiliser title comme seule étiquette",
|
|
8138
|
+
"labelTitleOnly_description": "Vérifie qu’un contrôle de formulaire ayant un attribut title possède aussi une véritable étiquette (élément label, aria-label, ou aria-labelledby).",
|
|
8139
|
+
"labelTitleOnly_summary_cantTell": "Ce contrôle de formulaire repose sur l’attribut title comme seule étiquette.",
|
|
8140
|
+
"labelTitleOnly_hint_cantTell": "Ajoutez une <label> visible (ou aria-label/aria-labelledby) en plus de, ou à la place de, l’attribut title.",
|
|
8141
|
+
"imageRedundantAlt_title": "Le texte alt d’une image ne doit pas dupliquer le texte visible adjacent",
|
|
8142
|
+
"imageRedundantAlt_description": "Vérifie que le texte alt d’un <img> n’est pas identique à un autre texte visible déjà présent dans son élément parent immédiat.",
|
|
8143
|
+
"imageRedundantAlt_summary_cantTell": "Le texte alt de cette image duplique un autre texte visible juste à côté.",
|
|
8144
|
+
"imageRedundantAlt_hint_cantTell": "Videz le texte alt (alt=\"\") si l’image est purement décorative à côté du texte, ou supprimez la duplication redondante.",
|
|
8145
|
+
"tableDuplicateName_title": "La légende d’un tableau ne doit pas dupliquer son attribut summary",
|
|
8146
|
+
"tableDuplicateName_description": "Vérifie que le texte de la <caption> d’un <table> n’est pas identique à son attribut summary (obsolète).",
|
|
8147
|
+
"tableDuplicateName_summary_cantTell": "La légende de ce tableau duplique son attribut summary.",
|
|
8148
|
+
"tableDuplicateName_hint_cantTell": "Retirez l’attribut summary redondant, ou faites en sorte qu’il apporte une information différente de la légende.",
|
|
8149
|
+
"metaViewportLarge_title": "La balise meta viewport devrait permettre un zoom jusqu’à 500 %",
|
|
8150
|
+
"metaViewportLarge_description": "Vérifie que <meta name=\"viewport\"> ne définit pas user-scalable=no ni maximum-scale en dessous de 5 (500 %).",
|
|
8151
|
+
"metaViewportLarge_summary_cantTell": "Cette balise meta viewport restreint le zoom en dessous de l’objectif de bonne pratique de 500 %.",
|
|
8152
|
+
"metaViewportLarge_hint_cantTell": "Retirez user-scalable=no et augmentez maximum-scale à au moins 5 (500 %) si possible.",
|
|
8153
|
+
"presentationRoleConflict_title": "Un rôle de présentation ne doit pas entrer en conflit avec un attribut ARIA global ou la focalisabilité",
|
|
8154
|
+
"presentationRoleConflict_description": "Vérifie que role=\"presentation\"/\"none\" (y compris le rôle presentation implicite d’un <img alt=\"\">) n’est pas combiné avec un attribut ARIA global (aria-label, aria-hidden, aria-describedby, ...) ou avec la focalisabilité (tabindex/native).",
|
|
8155
|
+
"presentationRoleConflict_summary_cantTell": "Cet élément role=\"{{role}}\" a aussi une condition conflictuelle ({{attrs}}), qui restaure son rôle implicite et annule l’intention présentationnelle.",
|
|
8156
|
+
"presentationRoleConflict_hint_cantTell": "Retirez le(s) attribut(s) de nommage conflictuel(s) et/ou la focalisabilité (tabindex/native) si l’élément doit rester présentationnel, ou retirez role=\"presentation\"/\"none\" s’il doit être exposé aux technologies d’assistance.",
|
|
8157
|
+
"region_title": "Le contenu de la page devrait se trouver à l’intérieur d’un point de repère",
|
|
8158
|
+
"region_description": "Vérifie que les enfants directs de <body> ayant un contenu textuel visible sont contenus dans un point de repère.",
|
|
8159
|
+
"region_summary_cantTell": "Ce contenu n’est contenu dans aucun point de repère.",
|
|
8160
|
+
"region_hint_cantTell": "Déplacez ce contenu à l’intérieur d’un point de repère (main, nav, aside, une section nommée, etc.).",
|
|
8161
|
+
"skipLink_title": "Un lien d’évitement doit avoir une cible qui se résout",
|
|
8162
|
+
"skipLink_description": "Vérifie que le fragment href d’un lien « aller au... » se résout vers un élément réel du document.",
|
|
8163
|
+
"skipLink_summary_cantTell": "La cible de ce lien d’évitement n’existe pas.",
|
|
8164
|
+
"skipLink_hint_cantTell": "Faites pointer le href du lien d’évitement vers un id qui existe dans le document, ou ajoutez l’élément cible manquant.",
|
|
8165
|
+
"autocompleteValid_title": "L’attribut autocomplete doit être une valeur d’auto-remplissage valide",
|
|
8166
|
+
"autocompleteValid_description": "Vérifie qu’un attribut autocomplete non vide vaut « on »/« off » ou une liste de jetons d’auto-remplissage bien formée.",
|
|
8167
|
+
"autocompleteValid_summary_fail": "Cette valeur d’attribut autocomplete n’est pas une valeur d’auto-remplissage valide.",
|
|
8168
|
+
"autocompleteValid_hint_fail": "Utilisez « on »/« off », ou une liste de jetons d’auto-remplissage valide (ex. « shipping street-address », « cc-number »).",
|
|
8169
|
+
"htmlXmlLangMismatch_title": "lang et xml:lang ne doivent pas se contredire",
|
|
8170
|
+
"htmlXmlLangMismatch_description": "Vérifie que les attributs lang et xml:lang de l’élément <html> déclarent la même langue principale, lorsque les deux sont présents.",
|
|
8171
|
+
"htmlXmlLangMismatch_summary_fail": "Les attributs lang (« {{lang}} ») et xml:lang (« {{xmlLang}} ») déclarent des langues différentes.",
|
|
8172
|
+
"htmlXmlLangMismatch_hint_fail": "Faites en sorte que lang et xml:lang déclarent la même langue principale, ou retirez l’attribut obsolète xml:lang.",
|
|
8173
|
+
"avoidInlineSpacing_title": "Un style en ligne ne doit pas forcer l’espacement du texte avec !important",
|
|
8174
|
+
"avoidInlineSpacing_description": "Vérifie qu’un style en ligne ne définit pas line-height, letter-spacing, ou word-spacing avec !important, ce qui bloque les surcharges d’espacement de texte par l’utilisateur.",
|
|
8175
|
+
"avoidInlineSpacing_summary_fail": "Le style en ligne de cet élément force {{properties}} avec !important, bloquant les surcharges d’espacement de texte par l’utilisateur.",
|
|
8176
|
+
"avoidInlineSpacing_hint_fail": "Retirez !important de line-height/letter-spacing/word-spacing dans les styles en ligne afin que les utilisateurs puissent surcharger l’espacement du texte.",
|
|
8177
|
+
"metaRefreshNoExceptions_title": "La page ne doit utiliser aucun rafraîchissement meta (AAA)",
|
|
8178
|
+
"metaRefreshNoExceptions_description": "Vérifie que <meta http-equiv=\"refresh\"> n’est présent en aucun cas, quel que soit le délai — la variante plus stricte, de niveau AAA, de la vérification de niveau A qui ne porte que sur les délais positifs.",
|
|
8179
|
+
"metaRefreshNoExceptions_summary_fail": "Cette page utilise un rafraîchissement meta, un changement de contexte automatique non initié par l’utilisateur.",
|
|
8180
|
+
"metaRefreshNoExceptions_hint_fail": "Retirez le rafraîchissement meta ; déclenchez la redirection/le rafraîchissement uniquement en réponse à une action de l’utilisateur.",
|
|
8181
|
+
"validLang_title": "L’attribut lang d’un élément doit être syntaxiquement valide",
|
|
8182
|
+
"validLang_description": "Vérifie que tout élément (autre que la racine <html>) ayant un attribut lang non vide utilise une étiquette de langue syntaxiquement valide.",
|
|
8183
|
+
"validLang_summary_fail": "Cette valeur d’attribut lang (« {{value}} ») n’est pas une étiquette de langue syntaxiquement valide.",
|
|
8184
|
+
"validLang_hint_fail": "Utilisez une étiquette de langue BCP47 valide (ex. « fr », « es-MX »).",
|
|
8185
|
+
"linkInTextBlock_title": "Les liens dans des blocs de texte doivent être distinguables du texte environnant sans se fier uniquement à la couleur",
|
|
8186
|
+
"linkInTextBlock_description": "Vérifie qu’un lien à l’intérieur d’un bloc de texte est visuellement distinguable du texte environnant par un soulignement, une différence de graisse/style de police, ou un contraste de couleur suffisant (>= 3:1) — pas seulement par la couleur.",
|
|
8187
|
+
"linkInTextBlock_summary_fail": "Ce lien dans un bloc de texte se distingue du texte environnant uniquement par la couleur.",
|
|
8188
|
+
"linkInTextBlock_hint_fail": "Ajoutez un soulignement, une différence de graisse/style de police, ou augmentez le contraste de couleur entre le lien et le texte environnant à au moins 3:1.",
|
|
8189
|
+
"noAutoplayAudio_title": "Un audio en lecture automatique devrait proposer un mécanisme de pause/arrêt ou de contrôle du volume",
|
|
8190
|
+
"noAutoplayAudio_description": "Signale les éléments <audio>/<video> qui se lancent automatiquement sans être coupés et sans attribut controls natif, pour une revue manuelle par rapport à l’exemption de 3 secondes de la WCAG 1.4.2.",
|
|
8191
|
+
"noAutoplayAudio_summary_cantTell": "Cet élément lit un audio automatiquement sans mécanisme natif de pause/arrêt ou de contrôle du volume.",
|
|
8192
|
+
"noAutoplayAudio_hint_cantTell": "Si ce clip dure plus de 3 secondes, ajoutez un attribut controls (ou un mécanisme personnalisé équivalent) afin que les utilisateurs puissent le mettre en pause/l’arrêter ou contrôler son volume indépendamment du volume du système.",
|
|
8193
|
+
"videoCaption_title": "Une vidéo préenregistrée devrait proposer une piste de sous-titres",
|
|
8194
|
+
"videoCaption_description": "Signale les éléments <video> sans enfant <track kind=\"captions\"|\"subtitles\">, pour une revue manuelle visant à déterminer si la vidéo a une piste audio nécessitant des sous-titres.",
|
|
8195
|
+
"videoCaption_summary_cantTell": "Cette vidéo n’a aucune piste de sous-titres (captions ou subtitles).",
|
|
8196
|
+
"videoCaption_hint_cantTell": "Si cette vidéo a une piste audio porteuse d’information, ajoutez un <track kind=\"captions\" src=\"...\"> avec le contenu sous-titré.",
|
|
8197
|
+
"scrollableRegionFocusable_title": "Les régions défilantes sans contenu focalisable devraient être focalisables au clavier",
|
|
8198
|
+
"scrollableRegionFocusable_description": "Signale les éléments dont le CSS déclare overflow:auto/scroll, qui ne contiennent aucun descendant focalisable, et qui ne sont pas eux-mêmes focalisables au clavier, pour une revue manuelle visant à déterminer si leur contenu déborde réellement et nécessite un accès au défilement au clavier.",
|
|
8199
|
+
"scrollableRegionFocusable_summary_cantTell": "Cet élément déclare overflow:auto/scroll, n’a aucun descendant focalisable, et n’est pas lui-même focalisable au clavier.",
|
|
8200
|
+
"scrollableRegionFocusable_hint_cantTell": "Si le contenu de cette région déborde réellement, ajoutez tabindex=\"0\" (et une étiquette adaptée) afin que les utilisateurs du clavier puissent la focaliser et faire défiler avec les flèches.",
|
|
8201
|
+
"identicalLinksSamePurpose_title": "Les liens partageant le même nom accessible devraient mener à la même destination",
|
|
8202
|
+
"identicalLinksSamePurpose_description": "Signale les groupes de liens qui partagent le même nom accessible mais mènent à plus d’une destination distincte, pour une revue manuelle visant à déterminer s’ils servent le même objectif.",
|
|
8203
|
+
"identicalLinksSamePurpose_summary_cantTell": "Ce lien partage un nom accessible avec d’autres liens de la page qui mènent à une destination différente.",
|
|
8204
|
+
"identicalLinksSamePurpose_hint_cantTell": "Assurez-vous que les liens ayant le même texte servent le même objectif, ou rendez le texte du lien suffisamment distinct pour décrire chaque destination.",
|
|
8205
|
+
"ariaBrailleEquivalent_title": "aria-braillelabel/aria-brailleroledescription doivent avoir un équivalent non braille",
|
|
8206
|
+
"ariaBrailleEquivalent_description": "Vérifie que les éléments utilisant aria-braillelabel ont aussi un nom accessible ordinaire, et que ceux utilisant aria-brailleroledescription ont aussi aria-roledescription.",
|
|
8207
|
+
"ariaBrailleEquivalent_summary_fail": "Cet élément a {{attr}} mais pas {{requires}}, son équivalent non braille.",
|
|
8208
|
+
"ariaBrailleEquivalent_hint_fail": "{{attr}} est un complément spécifique au braille, pas un remplacement — fournissez aussi {{requires}}.",
|
|
8209
|
+
"ariaConditionalAttr_title": "aria-errormessage exige que aria-invalid soit défini à une valeur autre que false",
|
|
8210
|
+
"ariaConditionalAttr_description": "Vérifie que les éléments ayant aria-errormessage ont aussi aria-invalid défini à « true », « grammar », ou « spelling » — sinon le message d’erreur est retiré de l’arbre d’accessibilité.",
|
|
8211
|
+
"ariaConditionalAttr_summary_fail": "Cet élément a aria-errormessage mais aria-invalid est absent ou « false », donc le message d’erreur n’est pas exposé.",
|
|
8212
|
+
"ariaConditionalAttr_hint_fail": "Définissez aria-invalid à « true » (ou « grammar »/« spelling ») chaque fois que aria-errormessage doit être exposé aux technologies d’assistance.",
|
|
8213
|
+
"ariaCheckedStateMismatch_title": "L’aria-checked d’une case à cocher/d’un bouton radio natif devrait correspondre à son état réel",
|
|
8214
|
+
"ariaCheckedStateMismatch_description": "Signale un <input type=\"checkbox\">/<input type=\"radio\"> natif dont la valeur explicite d’aria-checked ne correspond pas à son état réel (coché/indéterminé), pour une revue manuelle.",
|
|
8215
|
+
"ariaCheckedStateMismatch_summary_cantTell": "La valeur d’aria-checked de cet élément ne correspond pas à son état réel (coché/indéterminé).",
|
|
8216
|
+
"ariaCheckedStateMismatch_hint_cantTell": "Définissez aria-checked pour qu’il corresponde à l’état réel de l’élément, ou retirez-le — une case à cocher/un bouton radio natif expose déjà cet état sans lui.",
|
|
8217
|
+
"cssOrientationLock_title": "Le CSS ne doit pas verrouiller la page à une seule orientation",
|
|
8218
|
+
"cssOrientationLock_description": "Vérifie qu’aucune règle @media (orientation: portrait|landscape) ne définit un transform: rotate(...) sur la page, une technique connue pour contourner l’orientation de l’appareil.",
|
|
8219
|
+
"cssOrientationLock_summary_fail": "Une media query « {{mediaText}} » fait pivoter « {{selectorText}} », verrouillant la page à une seule orientation.",
|
|
8220
|
+
"cssOrientationLock_hint_fail": "Retirez la transformation rotate() de la media query d’orientation ; laissez la page répondre naturellement à l’orientation de l’appareil au lieu de forcer une rotation visuelle.",
|
|
8221
|
+
"ariaText_title": "Les éléments role=\"text\" ne devraient avoir aucun descendant focalisable",
|
|
8222
|
+
"ariaText_description": "Vérifie que les éléments ayant role=\"text\" ne contiennent aucun descendant focalisable (lien, bouton, contrôle de formulaire, tabindex, iframe, ou contenteditable).",
|
|
8223
|
+
"ariaText_summary_cantTell": "Cet élément role=\"text\" contient un descendant focalisable.",
|
|
8224
|
+
"ariaText_hint_cantTell": "Retirez role=\"text\" (ou retirez le descendant focalisable) — une région de « texte brut » ne devrait pas contenir de contenu focalisable.",
|
|
8225
|
+
"focusOrderSemantics_title": "Les éléments ajoutés à l’ordre de tabulation devraient avoir une sémantique interactive",
|
|
8226
|
+
"focusOrderSemantics_description": "Signale les éléments ayant tabindex >= 0 dont le rôle explicite est un rôle structurel/documentaire non interactif (ex. heading, list, region, presentation), pour une revue manuelle.",
|
|
8227
|
+
"focusOrderSemantics_summary_cantTell": "Cet élément est dans l’ordre de tabulation (tabindex=\"{{tabindex}}\") mais a un rôle non interactif (« {{role}} »).",
|
|
8228
|
+
"focusOrderSemantics_hint_cantTell": "Retirez tabindex si cet élément n’est pas censé être interactif, ou utilisez un rôle interactif correspondant à son comportement réel.",
|
|
8229
|
+
"pAsHeading_title": "Un <p> stylé pour ressembler à un titre devrait probablement être un véritable titre",
|
|
8230
|
+
"pAsHeading_description": "Signale les éléments <p> courts dont tout le texte est en gras et affiché à >= 18px, pour une revue manuelle visant à déterminer si un véritable élément de titre devrait être utilisé à la place.",
|
|
8231
|
+
"pAsHeading_summary_cantTell": "Ce paragraphe est entièrement en gras et affiché à une taille évoquant un titre.",
|
|
8232
|
+
"pAsHeading_hint_cantTell": "Si ce texte introduit une nouvelle section, utilisez un véritable élément de titre (<h1>-<h6> ou role=\"heading\") plutôt que de styler un paragraphe pour qu’il y ressemble.",
|
|
8233
|
+
"tableFakeCaption_title": "La première ligne d’un tableau ne devrait pas tenir lieu de véritable <caption>",
|
|
8234
|
+
"tableFakeCaption_description": "Signale les tableaux sans <caption> dont la première ligne a une seule cellule non vide alors que les autres lignes ont plusieurs cellules, pour une revue manuelle visant à déterminer si cette cellule fait office de légende factice.",
|
|
8235
|
+
"tableFakeCaption_summary_cantTell": "Ce tableau n’a pas de <caption>, mais sa première ligne est une cellule unique placée au-dessus de lignes à plusieurs cellules — elle fait peut-être office de légende factice.",
|
|
8236
|
+
"tableFakeCaption_hint_cantTell": "Si cette cellule est censée décrire le tableau, utilisez un véritable élément <caption> plutôt qu’une cellule isolée en première ligne.",
|
|
8237
|
+
"tdHasHeader_title": "Les cellules de données des grands tableaux doivent avoir un en-tête associé",
|
|
8238
|
+
"tdHasHeader_description": "Vérifie que chaque <td> d’un tableau grand et simple (sans colspan/rowspan) a un en-tête associé — via un attribut headers, un <th> de colonne implicite au-dessus, ou un <th> de ligne implicite à sa gauche.",
|
|
8239
|
+
"tdHasHeader_summary_fail": "Cette cellule de données n’a pas d’en-tête associé (pas d’attribut headers, pas de <th> de colonne au-dessus, pas de <th> de ligne à gauche).",
|
|
8240
|
+
"tdHasHeader_hint_fail": "Ajoutez un attribut headers référençant le(s) id du/des <th> pertinent(s), ou restructurez le tableau afin que cette cellule ait un en-tête de ligne/colonne implicite.",
|
|
8241
|
+
"mouseOnlyEventHandlers_title": "Les gestionnaires d’événements en ligne réservés au pointeur devraient avoir un équivalent accessible au clavier",
|
|
8242
|
+
"mouseOnlyEventHandlers_description": "Signale les éléments ayant un gestionnaire d’événement en ligne réservé au pointeur (onmouseover, onmouseout, onmousedown, onmouseup, ondblclick, onmousemove, onmouseenter, onmouseleave) sans équivalent accessible au clavier (onkeydown/onkeyup/onkeypress/onfocus/onblur), pour une revue manuelle.",
|
|
8243
|
+
"mouseOnlyEventHandlers_summary_cantTell": "Cet élément a {{attrs}} mais aucun gestionnaire équivalent accessible au clavier.",
|
|
8244
|
+
"mouseOnlyEventHandlers_hint_cantTell": "Ajoutez onkeydown/onkeyup/onkeypress (ou onfocus/onblur pour un comportement déclenché au survol) afin que cette fonctionnalité soit aussi accessible au clavier.",
|
|
8245
|
+
"linkNameQuality_title": "Le texte des liens devrait être descriptif, pas générique",
|
|
8246
|
+
"linkNameQuality_description": "Signale les liens dont le nom accessible complet est une formule connue comme non descriptive (ex. « cliquez ici », « en savoir plus », « plus »), pour une revue manuelle visant à déterminer si l’objet du lien est clair sans contexte supplémentaire.",
|
|
8247
|
+
"linkNameQuality_summary_cantTell": "Le nom accessible de ce lien (« {{name}} ») est une formule générique et non descriptive.",
|
|
8248
|
+
"linkNameQuality_hint_cantTell": "Faites en sorte que le texte du lien lui-même décrive sa destination/son objet (ex. « Télécharger le guide tarifaire 2026 » plutôt que « Télécharger »), ou confirmez que le contexte environnant rend déjà l’objet clair."
|
|
7936
8249
|
}
|
|
7937
8250
|
};
|
|
7938
8251
|
|
|
@@ -10656,14 +10969,35 @@ const createDomHelpers = (function createDomHelpers(opts) {
|
|
|
10656
10969
|
const includeShadowDom = !(opts && opts.includeShadowDom === false);
|
|
10657
10970
|
const excludeSelectors = Array.isArray(opts && opts.excludeSelectors) ? opts.excludeSelectors : [];
|
|
10658
10971
|
|
|
10972
|
+
// Rule-scoped excludes (engineOptions.rules[ruleId].excludeSelectors), set
|
|
10973
|
+
// by dom-runner.js immediately before invoking each rule's applicability/
|
|
10974
|
+
// run function via __setActiveRuleExcludeSelectors(). Safe as mutable
|
|
10975
|
+
// closure state because rule execution is synchronous and single-rule-
|
|
10976
|
+
// at-a-time: exactly one rule's excludes are ever "active" at once.
|
|
10977
|
+
var __activeRuleExcludeSelectors = [];
|
|
10978
|
+
|
|
10979
|
+
function __getEffectiveExcludeSelectors() {
|
|
10980
|
+
return __activeRuleExcludeSelectors.length
|
|
10981
|
+
? excludeSelectors.concat(__activeRuleExcludeSelectors)
|
|
10982
|
+
: excludeSelectors;
|
|
10983
|
+
}
|
|
10984
|
+
|
|
10985
|
+
function __setActiveRuleExcludeSelectors(list) {
|
|
10986
|
+
__activeRuleExcludeSelectors = normalizeSelectorList(list);
|
|
10987
|
+
}
|
|
10988
|
+
|
|
10659
10989
|
// Selector-related caches (selector uniqueness index, per-element built
|
|
10660
|
-
// selector strings) depend on includeShadowDom/
|
|
10661
|
-
// those change which elements are considered when checking
|
|
10662
|
-
// The underlying storage is shared across createDomHelpers()
|
|
10663
|
-
// the same window/document (see __domSharedCache below), so a
|
|
10664
|
-
//
|
|
10665
|
-
//
|
|
10666
|
-
|
|
10990
|
+
// selector strings) depend on includeShadowDom/the effective exclude
|
|
10991
|
+
// list, since those change which elements are considered when checking
|
|
10992
|
+
// uniqueness. The underlying storage is shared across createDomHelpers()
|
|
10993
|
+
// calls on the same window/document (see __domSharedCache below), so a
|
|
10994
|
+
// run -- or a rule with its own rule-scoped excludes -- must not
|
|
10995
|
+
// read/write another run/rule's cached selectors. This key partitions
|
|
10996
|
+
// those caches per effective option set; recomputed per call (not a
|
|
10997
|
+
// constant) since the effective list changes as the active rule changes.
|
|
10998
|
+
function __getSelectorOptsKey() {
|
|
10999
|
+
return (includeShadowDom ? 'sd1' : 'sd0') + '|' + __getEffectiveExcludeSelectors().slice().sort().join(',');
|
|
11000
|
+
}
|
|
10667
11001
|
|
|
10668
11002
|
// -------------------------------------------------------------------------
|
|
10669
11003
|
// Per-run shared caches (DOM helpers)
|
|
@@ -11425,9 +11759,10 @@ const createDomHelpers = (function createDomHelpers(opts) {
|
|
|
11425
11759
|
|
|
11426
11760
|
|
|
11427
11761
|
function isExcluded(el) {
|
|
11428
|
-
|
|
11762
|
+
const eff = __getEffectiveExcludeSelectors();
|
|
11763
|
+
if (!eff.length || !el || !el.closest) return false;
|
|
11429
11764
|
try {
|
|
11430
|
-
return
|
|
11765
|
+
return eff.some((sel) => !!el.closest(sel));
|
|
11431
11766
|
} catch {
|
|
11432
11767
|
return false;
|
|
11433
11768
|
}
|
|
@@ -11522,8 +11857,10 @@ const createDomHelpers = (function createDomHelpers(opts) {
|
|
|
11522
11857
|
if (!scope || !scope.querySelectorAll) return [];
|
|
11523
11858
|
|
|
11524
11859
|
// Cache shadow root discovery per root to avoid repeated querySelectorAll('*') walks.
|
|
11525
|
-
// IMPORTANT: do not cache when
|
|
11526
|
-
|
|
11860
|
+
// IMPORTANT: do not cache when the effective exclude list (global
|
|
11861
|
+
// ∪ active rule-scoped excludes) is non-empty -- different rules
|
|
11862
|
+
// may have different effective lists and must not share results.
|
|
11863
|
+
if (!__getEffectiveExcludeSelectors().length && __shadowRootsByRoot) {
|
|
11527
11864
|
try {
|
|
11528
11865
|
const cached = __shadowRootsByRoot.get(scope);
|
|
11529
11866
|
if (cached) {
|
|
@@ -11598,7 +11935,7 @@ const createDomHelpers = (function createDomHelpers(opts) {
|
|
|
11598
11935
|
|
|
11599
11936
|
function queryAllSmart(sel) {
|
|
11600
11937
|
const list = includeShadowDom ? queryAllDeep(sel) : queryAll(sel);
|
|
11601
|
-
return
|
|
11938
|
+
return __getEffectiveExcludeSelectors().length ? list.filter((el) => !isExcluded(el)) : list;
|
|
11602
11939
|
}
|
|
11603
11940
|
|
|
11604
11941
|
// -------------------------------------------------------------------------
|
|
@@ -11632,10 +11969,11 @@ const createDomHelpers = (function createDomHelpers(opts) {
|
|
|
11632
11969
|
function __getSelectorCacheForOpts() {
|
|
11633
11970
|
if (!__selectorCache) return null;
|
|
11634
11971
|
try {
|
|
11635
|
-
|
|
11972
|
+
const key = __getSelectorOptsKey();
|
|
11973
|
+
let wm = __selectorCache.get(key);
|
|
11636
11974
|
if (!(wm instanceof WeakMap)) {
|
|
11637
11975
|
wm = new WeakMap();
|
|
11638
|
-
__selectorCache.set(
|
|
11976
|
+
__selectorCache.set(key, wm);
|
|
11639
11977
|
}
|
|
11640
11978
|
return wm;
|
|
11641
11979
|
} catch {
|
|
@@ -14046,7 +14384,8 @@ const createDomHelpers = (function createDomHelpers(opts) {
|
|
|
14046
14384
|
return createSelectorUniqIndex();
|
|
14047
14385
|
}
|
|
14048
14386
|
|
|
14049
|
-
const
|
|
14387
|
+
const key = __getSelectorOptsKey();
|
|
14388
|
+
const cached = perScope.get(key);
|
|
14050
14389
|
if (cached) {
|
|
14051
14390
|
__perfInc('uniqIndex.hit');
|
|
14052
14391
|
return cached;
|
|
@@ -14055,7 +14394,7 @@ const createDomHelpers = (function createDomHelpers(opts) {
|
|
|
14055
14394
|
__perfInc('uniqIndex.miss');
|
|
14056
14395
|
const idx = createSelectorUniqIndex();
|
|
14057
14396
|
try {
|
|
14058
|
-
perScope.set(
|
|
14397
|
+
perScope.set(key, idx);
|
|
14059
14398
|
} catch { /* ignore */
|
|
14060
14399
|
}
|
|
14061
14400
|
__perfInc('uniqIndex.build');
|
|
@@ -14565,6 +14904,12 @@ const createDomHelpers = (function createDomHelpers(opts) {
|
|
|
14565
14904
|
isAccTreeEligible,
|
|
14566
14905
|
isDomVisibleEligible,
|
|
14567
14906
|
|
|
14907
|
+
// Engine-internal: sets which rule's rule-scoped excludeSelectors
|
|
14908
|
+
// (engineOptions.rules[ruleId].excludeSelectors) are currently in
|
|
14909
|
+
// effect. Called by dom-runner.js before each rule invocation, not
|
|
14910
|
+
// intended for use by rule implementations.
|
|
14911
|
+
__setActiveRuleExcludeSelectors,
|
|
14912
|
+
|
|
14568
14913
|
// Eligibility info wrapper
|
|
14569
14914
|
getEligibilityInfo,
|
|
14570
14915
|
|
|
@@ -14978,6 +15323,15 @@ const runCore = (function runCore(pageUrl, contextSelector, engineOptions, runOn
|
|
|
14978
15323
|
? engineOptionsResolved.rules[defResolved.ruleId]
|
|
14979
15324
|
: null;
|
|
14980
15325
|
|
|
15326
|
+
// Rule-scoped excludeSelectors (engineOptions.rules[ruleId].excludeSelectors)
|
|
15327
|
+
// apply on top of the global excludeSelectors for exactly this rule's
|
|
15328
|
+
// applicability check + run, then are cleared once this rule is done.
|
|
15329
|
+
// Safe because rule execution below is synchronous and one rule at a
|
|
15330
|
+
// time -- sharedHelpers is reused across all rules in this loop.
|
|
15331
|
+
if (typeof sharedHelpers.__setActiveRuleExcludeSelectors === 'function') {
|
|
15332
|
+
sharedHelpers.__setActiveRuleExcludeSelectors(ruleConfig && ruleConfig.excludeSelectors);
|
|
15333
|
+
}
|
|
15334
|
+
|
|
14981
15335
|
const ctx = {
|
|
14982
15336
|
document,
|
|
14983
15337
|
window,
|
|
@@ -15048,6 +15402,14 @@ const runCore = (function runCore(pageUrl, contextSelector, engineOptions, runOn
|
|
|
15048
15402
|
if (ruleTimings) ruleTimings[defResolved.ruleId] = (ruleTimings[defResolved.ruleId] || 0) + (nowMs() - t0);
|
|
15049
15403
|
}
|
|
15050
15404
|
|
|
15405
|
+
// Composite rollups below carry no occurrences/nodes of their own, so
|
|
15406
|
+
// they never exercise rule-scoped excludes -- but clear the "active
|
|
15407
|
+
// rule" state on sharedHelpers regardless, so nothing after this point
|
|
15408
|
+
// (composite aggregation, perf stats) can observe a stale rule's excludes.
|
|
15409
|
+
if (typeof sharedHelpers.__setActiveRuleExcludeSelectors === 'function') {
|
|
15410
|
+
sharedHelpers.__setActiveRuleExcludeSelectors(null);
|
|
15411
|
+
}
|
|
15412
|
+
|
|
15051
15413
|
// =========================
|
|
15052
15414
|
// Composite rule aggregation (data-only rollups)
|
|
15053
15415
|
// =========================
|
|
@@ -23103,39 +23465,39 @@ if (isAccTreeEligible) {
|
|
|
23103
23465
|
// role/attribute pairings from the WAI-ARIA role definitions are listed.
|
|
23104
23466
|
const SUPPORTED_ATTRS_BY_ROLE = {
|
|
23105
23467
|
alertdialog: ['aria-modal'],
|
|
23106
|
-
checkbox: ['aria-checked', 'aria-readonly', 'aria-required'],
|
|
23107
|
-
columnheader: ['aria-sort', 'aria-colindex', 'aria-colspan', 'aria-readonly', 'aria-required', 'aria-rowindex', 'aria-rowspan', 'aria-selected'],
|
|
23108
|
-
combobox: ['aria-expanded', 'aria-autocomplete', 'aria-readonly', 'aria-required'],
|
|
23468
|
+
checkbox: ['aria-checked', 'aria-readonly', 'aria-required', 'aria-expanded'],
|
|
23469
|
+
columnheader: ['aria-sort', 'aria-colindex', 'aria-colspan', 'aria-readonly', 'aria-required', 'aria-rowindex', 'aria-rowspan', 'aria-selected', 'aria-expanded'],
|
|
23470
|
+
combobox: ['aria-expanded', 'aria-autocomplete', 'aria-readonly', 'aria-required', 'aria-activedescendant'],
|
|
23109
23471
|
dialog: ['aria-modal'],
|
|
23110
|
-
grid: ['aria-multiselectable', 'aria-readonly', 'aria-colcount', 'aria-rowcount'],
|
|
23111
|
-
gridcell: ['aria-selected', 'aria-readonly', 'aria-required', 'aria-colindex', 'aria-colspan', 'aria-rowindex', 'aria-rowspan'],
|
|
23472
|
+
grid: ['aria-multiselectable', 'aria-readonly', 'aria-colcount', 'aria-rowcount', 'aria-activedescendant'],
|
|
23473
|
+
gridcell: ['aria-selected', 'aria-readonly', 'aria-required', 'aria-colindex', 'aria-colspan', 'aria-rowindex', 'aria-rowspan', 'aria-expanded'],
|
|
23112
23474
|
heading: ['aria-level'],
|
|
23113
|
-
listbox: ['aria-multiselectable', 'aria-readonly', 'aria-required', 'aria-orientation'],
|
|
23475
|
+
listbox: ['aria-multiselectable', 'aria-readonly', 'aria-required', 'aria-orientation', 'aria-expanded', 'aria-activedescendant'],
|
|
23114
23476
|
listitem: ['aria-level', 'aria-posinset', 'aria-setsize'],
|
|
23115
23477
|
menu: ['aria-activedescendant', 'aria-orientation'],
|
|
23116
23478
|
menubar: ['aria-activedescendant', 'aria-orientation'],
|
|
23117
|
-
menuitemcheckbox: ['aria-checked'],
|
|
23118
|
-
menuitemradio: ['aria-checked'],
|
|
23479
|
+
menuitemcheckbox: ['aria-checked', 'aria-expanded', 'aria-readonly', 'aria-required', 'aria-posinset', 'aria-setsize'],
|
|
23480
|
+
menuitemradio: ['aria-checked', 'aria-expanded', 'aria-readonly', 'aria-required', 'aria-posinset', 'aria-setsize'],
|
|
23119
23481
|
meter: ['aria-valuenow', 'aria-valuemin', 'aria-valuemax', 'aria-valuetext'],
|
|
23120
23482
|
option: ['aria-selected', 'aria-checked', 'aria-posinset', 'aria-setsize'],
|
|
23121
23483
|
progressbar: ['aria-valuenow', 'aria-valuemin', 'aria-valuemax', 'aria-valuetext'],
|
|
23122
|
-
radio: ['aria-checked'],
|
|
23123
|
-
radiogroup: ['aria-readonly', 'aria-required', 'aria-orientation'],
|
|
23124
|
-
row: ['aria-selected', 'aria-level', 'aria-posinset', 'aria-setsize', 'aria-colindex', 'aria-rowindex'],
|
|
23125
|
-
rowheader: ['aria-sort', 'aria-colindex', 'aria-colspan', 'aria-readonly', 'aria-required', 'aria-rowindex', 'aria-rowspan', 'aria-selected'],
|
|
23484
|
+
radio: ['aria-checked', 'aria-posinset', 'aria-setsize'],
|
|
23485
|
+
radiogroup: ['aria-readonly', 'aria-required', 'aria-orientation', 'aria-activedescendant'],
|
|
23486
|
+
row: ['aria-selected', 'aria-level', 'aria-posinset', 'aria-setsize', 'aria-colindex', 'aria-rowindex', 'aria-expanded', 'aria-activedescendant'],
|
|
23487
|
+
rowheader: ['aria-sort', 'aria-colindex', 'aria-colspan', 'aria-readonly', 'aria-required', 'aria-rowindex', 'aria-rowspan', 'aria-selected', 'aria-expanded'],
|
|
23126
23488
|
scrollbar: ['aria-valuenow', 'aria-valuemin', 'aria-valuemax', 'aria-valuetext', 'aria-orientation', 'aria-controls'],
|
|
23127
23489
|
searchbox: ['aria-activedescendant', 'aria-autocomplete', 'aria-multiline', 'aria-placeholder', 'aria-readonly', 'aria-required'],
|
|
23128
23490
|
separator: ['aria-valuenow', 'aria-valuemin', 'aria-valuemax', 'aria-valuetext', 'aria-orientation'],
|
|
23129
23491
|
slider: ['aria-valuenow', 'aria-valuemin', 'aria-valuemax', 'aria-valuetext', 'aria-orientation', 'aria-readonly'],
|
|
23130
|
-
spinbutton: ['aria-valuenow', 'aria-valuemin', 'aria-valuemax', 'aria-valuetext', 'aria-readonly', 'aria-required'],
|
|
23131
|
-
switch: ['aria-checked'],
|
|
23132
|
-
tab: ['aria-selected'],
|
|
23492
|
+
spinbutton: ['aria-valuenow', 'aria-valuemin', 'aria-valuemax', 'aria-valuetext', 'aria-readonly', 'aria-required', 'aria-activedescendant'],
|
|
23493
|
+
switch: ['aria-checked', 'aria-expanded', 'aria-readonly', 'aria-required'],
|
|
23494
|
+
tab: ['aria-selected', 'aria-expanded', 'aria-posinset', 'aria-setsize'],
|
|
23133
23495
|
table: ['aria-colcount', 'aria-rowcount'],
|
|
23134
|
-
tablist: ['aria-multiselectable', 'aria-orientation'],
|
|
23496
|
+
tablist: ['aria-multiselectable', 'aria-orientation', 'aria-level', 'aria-activedescendant'],
|
|
23135
23497
|
textbox: ['aria-activedescendant', 'aria-autocomplete', 'aria-multiline', 'aria-placeholder', 'aria-readonly', 'aria-required'],
|
|
23136
23498
|
toolbar: ['aria-activedescendant', 'aria-orientation'],
|
|
23137
|
-
tree: ['aria-multiselectable', 'aria-
|
|
23138
|
-
treegrid: ['aria-multiselectable', 'aria-readonly', 'aria-required', 'aria-orientation', 'aria-colcount', 'aria-rowcount'],
|
|
23499
|
+
tree: ['aria-multiselectable', 'aria-required', 'aria-orientation', 'aria-activedescendant'],
|
|
23500
|
+
treegrid: ['aria-multiselectable', 'aria-readonly', 'aria-required', 'aria-orientation', 'aria-colcount', 'aria-rowcount', 'aria-activedescendant'],
|
|
23139
23501
|
treeitem: ['aria-checked', 'aria-selected', 'aria-expanded', 'aria-level', 'aria-posinset', 'aria-setsize']
|
|
23140
23502
|
};
|
|
23141
23503
|
|
|
@@ -39659,7 +40021,320 @@ const I18N = {
|
|
|
39659
40021
|
"labelInName_title": "Intitulé dans le nom : le nom accessible contient le texte visible",
|
|
39660
40022
|
"labelInName_description": "Vérifie que lorsqu’un composant possède un libellé textuel visible, le nom accessible contient ce libellé visible (WCAG 2.5.3).",
|
|
39661
40023
|
"labelInName_summary_fail": "{{element}} : le libellé visible « {{visibleLabel}} » (source : {{labelSource}}) n’est pas inclus dans le nom accessible (source : {{nameMechanism}}).",
|
|
39662
|
-
"labelInName_hint_fail": "Modifiez aria-label ou aria-labelledby (ou le texte du libellé visible) afin que le nom accessible inclue le libellé visible."
|
|
40024
|
+
"labelInName_hint_fail": "Modifiez aria-label ou aria-labelledby (ou le texte du libellé visible) afin que le nom accessible inclue le libellé visible.",
|
|
40025
|
+
"ariaRolesValid_title": "L’attribut role doit être un rôle ARIA valide et non abstrait",
|
|
40026
|
+
"ariaRolesValid_description": "Vérifie qu’un attribut role=\"\" explicite correspond à un rôle WAI-ARIA réel et non abstrait.",
|
|
40027
|
+
"ariaRolesValid_summary_invalid": "role=\"{{role}}\" n’est pas un rôle ARIA reconnu.",
|
|
40028
|
+
"ariaRolesValid_hint_invalid": "Utilisez un rôle ARIA valide, ou retirez l’attribut role si aucun ne s’applique.",
|
|
40029
|
+
"ariaRolesValid_summary_abstract": "role=\"{{role}}\" est un rôle ARIA abstrait, qui ne doit pas être utilisé directement.",
|
|
40030
|
+
"ariaRolesValid_hint_abstract": "Remplacez ce rôle abstrait par un rôle concret adapté au composant/à la structure.",
|
|
40031
|
+
"ariaDeprecatedRole_title": "L’attribut role ne doit pas utiliser un rôle ARIA obsolète ou interdit aux auteurs",
|
|
40032
|
+
"ariaDeprecatedRole_description": "Vérifie qu’un attribut role=\"\" explicite n’utilise pas un rôle rendu obsolète par la spécification WAI-ARIA, ni un rôle réservé à un usage interne à l’agent utilisateur (ex. role=\"generic\").",
|
|
40033
|
+
"ariaDeprecatedRole_summary_fail": "Cet élément utilise role=\"{{role}}\", que les auteurs ne doivent pas déclarer explicitement.",
|
|
40034
|
+
"ariaDeprecatedRole_hint_fail": "{{guidance}}",
|
|
40035
|
+
"ariaValidAttr_title": "Les attributs aria-* doivent être des attributs ARIA réels et définis",
|
|
40036
|
+
"ariaValidAttr_description": "Vérifie que chaque nom d’attribut aria-* présent dans le DOM est un attribut réel défini par la spécification WAI-ARIA.",
|
|
40037
|
+
"ariaValidAttr_summary_fail": "{{attr}} n’est pas un attribut ARIA reconnu.",
|
|
40038
|
+
"ariaValidAttr_hint_fail": "Corrigez le nom de l’attribut (vérifiez les fautes de frappe), ou retirez-le s’il n’est pas nécessaire.",
|
|
40039
|
+
"ariaValidAttrValue_title": "Les valeurs des attributs aria-* doivent correspondre à leur type déclaré",
|
|
40040
|
+
"ariaValidAttrValue_description": "Vérifie que chaque attribut aria-* reconnu a une valeur conforme à son type déclaré par WAI-ARIA (booléen, tri-état, jeton, entier, nombre ou référence d’ID).",
|
|
40041
|
+
"ariaValidAttrValue_summary_fail": "{{attr}}=\"{{value}}\" n’est pas une valeur valide pour cet attribut.",
|
|
40042
|
+
"ariaValidAttrValue_hint_fail": "Utilisez une valeur correspondant au type attendu de l’attribut (consultez la spécification WAI-ARIA pour cet attribut).",
|
|
40043
|
+
"ariaAllowedAttr_title": "Les attributs aria-* doivent être autorisés pour le rôle de l’élément",
|
|
40044
|
+
"ariaAllowedAttr_description": "Vérifie que chaque attribut aria-* reconnu présent sur un élément ayant un rôle explicite est soit globalement pris en charge, soit pris en charge par ce rôle.",
|
|
40045
|
+
"ariaAllowedAttr_summary_fail": "{{attr}} n’est pas autorisé sur role=\"{{role}}\".",
|
|
40046
|
+
"ariaAllowedAttr_hint_fail": "Retirez cet attribut, ou utilisez un rôle qui le prend en charge.",
|
|
40047
|
+
"ariaProhibitedAttr_title": "Les attributs de nommage ARIA ne doivent pas être utilisés sur des rôles qui les interdisent",
|
|
40048
|
+
"ariaProhibitedAttr_description": "Vérifie que aria-label/aria-labelledby ne sont pas présents sur des rôles WAI-ARIA dont la spécification interdit explicitement le nommage ARIA (ex. generic, emphasis, strong, paragraph).",
|
|
40049
|
+
"ariaProhibitedAttr_summary_fail": "{{attr}} est interdit sur role=\"{{role}}\".",
|
|
40050
|
+
"ariaProhibitedAttr_hint_fail": "Retirez cet attribut ; ce rôle ne doit pas porter de nom accessible.",
|
|
40051
|
+
"ariaRequiredAttr_title": "Les rôles avec un état/une propriété ARIA requis doivent le porter",
|
|
40052
|
+
"ariaRequiredAttr_description": "Vérifie que les éléments ayant un rôle explicite portent chaque état/propriété aria-* requis, non ambigu et indépendant du contexte, pour ce rôle (ex. role=\"checkbox\" doit avoir aria-checked).",
|
|
40053
|
+
"ariaRequiredAttr_summary_fail": "{{attr}} est requis pour role=\"{{role}}\", mais est absent.",
|
|
40054
|
+
"ariaRequiredAttr_hint_fail": "Ajoutez cet attribut avec une valeur valide pour ce rôle.",
|
|
40055
|
+
"ariaAllowedRole_title": "Le rôle explicite doit être autorisé pour son élément hôte",
|
|
40056
|
+
"ariaAllowedRole_description": "Vérifie qu’un attribut role=\"\" explicite fait partie des rôles que la spécification ARIA-in-HTML autorise pour l’élément hôte (ex. role=\"tab\" n’est pas autorisé sur <nav>).",
|
|
40057
|
+
"ariaAllowedRole_summary_fail": "role=\"{{role}}\" n’est pas autorisé sur <{{element}}>.",
|
|
40058
|
+
"ariaAllowedRole_hint_fail": "Utilisez un rôle autorisé pour cet élément, ou changez l’élément hôte.",
|
|
40059
|
+
"ariaRequiredChildren_title": "Les rôles conteneurs doivent posséder au moins un rôle enfant requis",
|
|
40060
|
+
"ariaRequiredChildren_description": "Vérifie que les rôles conteneurs disposant d’une entrée documentée « éléments possédés requis » (list, listbox, menu, radiogroup, table, grid, tablist, tree, row, ...) contiennent au moins un descendant, ou un élément référencé par aria-owns, ayant un rôle possédé acceptable.",
|
|
40061
|
+
"ariaRequiredChildren_summary_fail": "role=\"{{role}}\" ne possède aucun enfant ayant l’un des rôles requis : {{requiredRoles}}.",
|
|
40062
|
+
"ariaRequiredChildren_hint_fail": "Ajoutez un descendant (ou un élément référencé par aria-owns) ayant l’un des rôles possédés requis.",
|
|
40063
|
+
"ariaProhibitedChildren_title": "Les rôles conteneurs ne doivent pas posséder d’enfant ayant un rôle interdit",
|
|
40064
|
+
"ariaProhibitedChildren_description": "Vérifie que chaque enfant possédé (dans l’arbre d’accessibilité) d’un rôle conteneur (list, listbox, menu, menubar, radiogroup, rowgroup, table, grid, treegrid, tablist, tree, row) a l’un des rôles possédés autorisés par ce rôle.",
|
|
40065
|
+
"ariaProhibitedChildren_summary_fail": "Cet élément a le rôle role=\"{{childRole}}\", qui n’est pas un rôle enfant possédé autorisé par le conteneur englobant role=\"{{containerRole}}\".",
|
|
40066
|
+
"ariaProhibitedChildren_hint_fail": "Retirez ou modifiez ce rôle afin qu’il corresponde à l’un des rôles possédés autorisés du conteneur ({{allowedRoles}}), ou déplacez cet élément hors du conteneur {{containerRole}}.",
|
|
40067
|
+
"ariaProhibitedChildren_summary_fail_roleless": "Cet élément n’a pas de rôle explicite mais porte {{attr}}, ce qui en fait un véritable nœud de l’arbre d’accessibilité qui n’est pas un enfant possédé autorisé du conteneur englobant role=\"{{containerRole}}\".",
|
|
40068
|
+
"ariaProhibitedChildren_hint_fail_roleless": "Retirez {{attr}} (ou la relation de possession avec le conteneur role=\"{{containerRole}}\"), ou attribuez à cet élément role=\"presentation\"/\"none\" s’il n’est pas censé constituer son propre nœud dans l’arbre d’accessibilité.",
|
|
40069
|
+
"ariaRequiredParent_title": "Les rôles exigeant un rôle de contexte spécifique doivent se trouver dans ce contexte",
|
|
40070
|
+
"ariaRequiredParent_description": "Vérifie que les rôles disposant d’une entrée documentée « rôle de contexte requis » (listitem, option, tab, treeitem, row, cell, ...) ont un ancêtre, ou un propriétaire aria-owns, ayant un rôle de contexte acceptable.",
|
|
40071
|
+
"ariaRequiredParent_summary_fail": "role=\"{{role}}\" exige un rôle de contexte parmi : {{requiredRoles}}, qui n’a pas été trouvé.",
|
|
40072
|
+
"ariaRequiredParent_hint_fail": "Placez cet élément à l’intérieur d’un élément ayant un rôle de contexte acceptable (ou référencez-le depuis celui-ci via aria-owns).",
|
|
40073
|
+
"deprecatedElements_title": "Les éléments obsolètes non interruptibles (<blink>, <marquee>) ne doivent pas être utilisés",
|
|
40074
|
+
"deprecatedElements_description": "Vérifie que les éléments HTML obsolètes et non standards dont le contenu clignotant/défilant ne peut pas être mis en pause, arrêté ou masqué par l’utilisateur (<blink>, <marquee>) ne sont pas présents.",
|
|
40075
|
+
"deprecatedElements_summary_fail": "Le contenu de <{{element}}> ne peut pas être mis en pause, arrêté ou masqué par l’utilisateur.",
|
|
40076
|
+
"deprecatedElements_hint_fail": "Retirez cet élément ; utilisez à la place un contenu statique, ou une animation dotée d’un contrôle de pause/arrêt accessible à l’utilisateur.",
|
|
40077
|
+
"iframeNamePresent_title": "Les cadres ont un nom accessible",
|
|
40078
|
+
"iframeNamePresent_description": "Vérifie que les éléments <iframe>/<frame> exposent un nom accessible non vide via aria-label, aria-labelledby, ou l’attribut title.",
|
|
40079
|
+
"iframeNamePresent_summary_fail": "Ce <{{element}}> n’a pas de nom accessible.",
|
|
40080
|
+
"iframeNamePresent_hint_fail": "Ajoutez un attribut title (ou aria-label/aria-labelledby) décrivant le contenu ou l’objet du cadre.",
|
|
40081
|
+
"iframeTitleUnique_title": "Les titres de cadres doivent être uniques",
|
|
40082
|
+
"iframeTitleUnique_description": "Vérifie qu’aucun <iframe>/<frame> dans le périmètre analysé ne partage la même valeur d’attribut title qu’un autre.",
|
|
40083
|
+
"iframeTitleUnique_summary_fail": "Le titre « {{title}} » de ce <{{element}}> n’est pas unique parmi les cadres de cette page.",
|
|
40084
|
+
"iframeTitleUnique_hint_fail": "Donnez à chaque cadre un titre distinct décrivant son contenu ou son objet spécifique.",
|
|
40085
|
+
"iframeFocusableContent_title": "Les cadres avec tabindex=\"-1\" ne doivent pas contenir de contenu focalisable",
|
|
40086
|
+
"iframeFocusableContent_description": "Vérifie que les éléments <iframe>/<frame> de même origine avec tabindex=\"-1\" ne contiennent pas de contenu focalisable, car les navigateurs ne propagent pas cette restriction au document intégré du cadre.",
|
|
40087
|
+
"iframeFocusableContent_summary_fail": "Ce <{{element}}> a tabindex=\"-1\" mais son contenu contient des éléments focalisables, qui restent accessibles au clavier.",
|
|
40088
|
+
"iframeFocusableContent_hint_fail": "Retirez le contenu focalisable du cadre, ou retirez tabindex=\"-1\" si le cadre est censé être accessible.",
|
|
40089
|
+
"tableHeadersAttrValid_title": "L’attribut headers d’une cellule de tableau doit référencer des cellules d’en-tête valides",
|
|
40090
|
+
"tableHeadersAttrValid_description": "Vérifie que chaque id de l’attribut headers d’un <td>/<th> correspond à un élément <th> du même tableau (ni absent, ni un élément autre que th, ni lui-même).",
|
|
40091
|
+
"tableHeadersAttrValid_summary_fail": "L’attribut headers de ce <{{element}}> référence des cellules d’en-tête invalides : {{invalidIds}}.",
|
|
40092
|
+
"tableHeadersAttrValid_hint_fail": "Mettez à jour l’attribut headers afin que chaque id désigne un élément <th> du même tableau.",
|
|
40093
|
+
"tableThHasDataCells_title": "Les éléments <th> doivent décrire au moins une cellule de données",
|
|
40094
|
+
"tableThHasDataCells_description": "Vérifie qu’un tableau contenant des éléments <th> contient aussi au moins une cellule de données <td> que ces en-têtes décrivent.",
|
|
40095
|
+
"tableThHasDataCells_summary_fail": "Ce tableau a des cellules d’en-tête mais aucune cellule de données à décrire.",
|
|
40096
|
+
"tableThHasDataCells_hint_fail": "Ajoutez des cellules de données (<td>) au tableau, ou retirez les cellules d’en-tête si le tableau n’a pas de données.",
|
|
40097
|
+
"ariaHiddenBody_title": "Le <body> du document ne doit pas être aria-hidden",
|
|
40098
|
+
"ariaHiddenBody_description": "Vérifie que <body> n’a pas aria-hidden=\"true\", ce qui retirerait toute la page de l’arbre d’accessibilité.",
|
|
40099
|
+
"ariaHiddenBody_summary_fail": "Le corps du document a aria-hidden=\"true\", ce qui masque toute la page aux technologies d’assistance.",
|
|
40100
|
+
"ariaHiddenBody_hint_fail": "Retirez aria-hidden de <body>. Masquez des éléments spécifiques à la place, si c’était l’intention.",
|
|
40101
|
+
"listChildrenValid_title": "Les listes ne doivent contenir directement que des éléments de liste",
|
|
40102
|
+
"listChildrenValid_description": "Vérifie que les éléments <ul>/<ol> n’ont comme enfants directs que <li>, <script> ou <template>.",
|
|
40103
|
+
"listChildrenValid_summary_fail": "Ce <{{element}}> contient un enfant direct qui n’est pas un élément de liste : {{invalidChildren}}.",
|
|
40104
|
+
"listChildrenValid_hint_fail": "N’utilisez que <li> (ou <script>/<template>) comme enfants directs de <ul>/<ol> ; déplacez tout autre balisage à l’intérieur d’un <li>.",
|
|
40105
|
+
"listitemParentValid_title": "Les éléments de liste doivent se trouver à l’intérieur d’un conteneur de liste",
|
|
40106
|
+
"listitemParentValid_description": "Vérifie que les éléments <li> sont contenus par <ul>, <ol>, ou un élément ayant role=\"list\".",
|
|
40107
|
+
"listitemParentValid_summary_fail": "Le parent de cet élément de liste (<{{parentElement}}>) n’est pas un conteneur de liste.",
|
|
40108
|
+
"listitemParentValid_hint_fail": "Placez ce <li> à l’intérieur d’un <ul>/<ol>, ou donnez à son parent role=\"list\".",
|
|
40109
|
+
"definitionListChildrenValid_title": "Les listes de définitions doivent être structurées correctement",
|
|
40110
|
+
"definitionListChildrenValid_description": "Vérifie que les éléments <dl> ne contiennent directement que des groupes <dt>/<dd> (éventuellement enveloppés dans un seul <div>), <script>, <template>, ou <style>.",
|
|
40111
|
+
"definitionListChildrenValid_summary_fail_invalidChild": "Cette liste de définitions contient un enfant direct ou enveloppé qui ne fait pas partie d’un groupe dt/dd : {{invalidChildren}}.",
|
|
40112
|
+
"definitionListChildrenValid_hint_fail_invalidChild": "N’utilisez que <dt>/<dd> (éventuellement enveloppés dans un seul <div>), <script>, <template>, ou <style> à l’intérieur de <dl>.",
|
|
40113
|
+
"definitionListChildrenValid_summary_fail_noDtDd": "Cette liste de définitions n’a aucun groupe terme/définition <dt>/<dd>.",
|
|
40114
|
+
"definitionListChildrenValid_hint_fail_noDtDd": "Ajoutez au moins une paire <dt>/<dd> à l’intérieur de ce <dl>.",
|
|
40115
|
+
"dlitemParentValid_title": "Les éléments d’une liste de définitions doivent se trouver à l’intérieur d’une liste de définitions",
|
|
40116
|
+
"dlitemParentValid_description": "Vérifie que les éléments <dt>/<dd> sont contenus par un <dl>, directement ou via un <div> englobant.",
|
|
40117
|
+
"dlitemParentValid_summary_fail": "Le parent (<{{parentElement}}>) de ce <{{element}}> n’est pas une liste de définitions.",
|
|
40118
|
+
"dlitemParentValid_hint_fail": "Placez ce <dt>/<dd> à l’intérieur d’un <dl>, directement ou enveloppé dans un seul <div>.",
|
|
40119
|
+
"duplicateIdAria_title": "Les ID référencés par ARIA doivent être uniques",
|
|
40120
|
+
"duplicateIdAria_description": "Vérifie que toute valeur id référencée par un attribut de référence d’ID ARIA (aria-labelledby, aria-describedby, aria-owns, aria-controls, aria-activedescendant, aria-flowto, aria-errormessage, aria-details) est unique dans le document.",
|
|
40121
|
+
"duplicateIdAria_summary_fail": "L’id « {{id}} » est référencé par un attribut ARIA mais est utilisé par {{duplicateCount}} éléments.",
|
|
40122
|
+
"duplicateIdAria_hint_fail": "Rendez uniques dans le document les id référencés par des attributs ARIA.",
|
|
40123
|
+
"summaryNamePresent_title": "Les éléments summary ont un nom accessible",
|
|
40124
|
+
"summaryNamePresent_description": "Vérifie que les éléments <summary> exposent un nom accessible non vide.",
|
|
40125
|
+
"summaryNamePresent_summary_fail": "Ce summary n’a pas de nom accessible.",
|
|
40126
|
+
"summaryNamePresent_hint_fail": "Fournissez un texte de summary qui ne soit pas masqué aux technologies d’assistance, ou fournissez aria-label ou aria-labelledby.",
|
|
40127
|
+
"metaViewportZoomEnabled_title": "La balise meta viewport ne doit pas désactiver le zoom",
|
|
40128
|
+
"metaViewportZoomEnabled_description": "Vérifie que <meta name=\"viewport\"> ne définit pas user-scalable=no ni maximum-scale en dessous de 2 (200 %).",
|
|
40129
|
+
"metaViewportZoomEnabled_summary_fail": "Cette balise meta viewport restreint la capacité de l’utilisateur à zoomer ({{reasons}}).",
|
|
40130
|
+
"metaViewportZoomEnabled_hint_fail": "Retirez user-scalable=no et tout maximum-scale inférieur à 2 du contenu de la balise meta viewport.",
|
|
40131
|
+
"metaRefreshTimingAbsent_title": "La page ne doit pas utiliser un rafraîchissement meta minuté",
|
|
40132
|
+
"metaRefreshTimingAbsent_description": "Vérifie que <meta http-equiv=\"refresh\"> n’impose pas un délai positif de 20 heures ou moins.",
|
|
40133
|
+
"metaRefreshTimingAbsent_summary_fail": "Cette page se rafraîchit automatiquement après {{delay}} secondes.",
|
|
40134
|
+
"metaRefreshTimingAbsent_hint_fail": "Retirez le rafraîchissement meta minuté, ou proposez un moyen pour les utilisateurs de le désactiver, de le prolonger ou de le mettre en pause avant qu’il ne se déclenche.",
|
|
40135
|
+
"meterNamePresent_title": "Les éléments meter ont un nom accessible",
|
|
40136
|
+
"meterNamePresent_description": "Vérifie que les éléments avec role=\"meter\" exposent un nom accessible non vide.",
|
|
40137
|
+
"meterNamePresent_summary_fail": "Ce meter n’a pas de nom accessible.",
|
|
40138
|
+
"meterNamePresent_hint_fail": "Fournissez un texte pour le meter qui ne soit pas masqué aux technologies d’assistance, ou fournissez aria-label ou aria-labelledby.",
|
|
40139
|
+
"progressbarNamePresent_title": "Les barres de progression ont un nom accessible",
|
|
40140
|
+
"progressbarNamePresent_description": "Vérifie que les éléments avec role=\"progressbar\" exposent un nom accessible non vide.",
|
|
40141
|
+
"progressbarNamePresent_summary_fail": "Cette barre de progression n’a pas de nom accessible.",
|
|
40142
|
+
"progressbarNamePresent_hint_fail": "Fournissez un texte pour la barre de progression qui ne soit pas masqué aux technologies d’assistance, ou fournissez aria-label ou aria-labelledby.",
|
|
40143
|
+
"tooltipNamePresent_title": "Les infobulles ont un nom accessible",
|
|
40144
|
+
"tooltipNamePresent_description": "Vérifie que les éléments avec role=\"tooltip\" exposent un nom accessible non vide.",
|
|
40145
|
+
"tooltipNamePresent_summary_fail": "Cette infobulle n’a pas de nom accessible.",
|
|
40146
|
+
"tooltipNamePresent_hint_fail": "Fournissez un texte pour l’infobulle qui ne soit pas masqué aux technologies d’assistance, ou fournissez aria-label ou aria-labelledby.",
|
|
40147
|
+
"serverSideImageMapAbsent_title": "Les images ne doivent pas utiliser une carte d’image côté serveur",
|
|
40148
|
+
"serverSideImageMapAbsent_description": "Vérifie que les éléments <img> ne portent pas l’attribut ismap (les cartes d’image côté serveur n’ont pas d’équivalent utilisable au clavier).",
|
|
40149
|
+
"serverSideImageMapAbsent_summary_fail": "Cette image utilise une carte d’image côté serveur, qui n’a pas d’équivalent utilisable au clavier.",
|
|
40150
|
+
"serverSideImageMapAbsent_hint_fail": "Remplacez la carte d’image côté serveur (ismap) par une carte d’image côté client (<map>/<area>) ou par des liens/boutons accessibles distincts.",
|
|
40151
|
+
"formControlSingleLabel_title": "Les contrôles de formulaire ne doivent pas avoir plusieurs étiquettes",
|
|
40152
|
+
"formControlSingleLabel_description": "Vérifie qu’un contrôle de formulaire est associé à au plus un <label> (par imbrication ou par label[for]).",
|
|
40153
|
+
"formControlSingleLabel_summary_fail": "Ce <{{element}}> est associé à {{labelCount}} étiquettes.",
|
|
40154
|
+
"formControlSingleLabel_hint_fail": "Conservez une seule <label> par contrôle de formulaire (soit en l’enveloppant, soit en la référençant via for/id).",
|
|
40155
|
+
"nestedInteractiveControlsAbsent_title": "Les contrôles interactifs ne doivent pas être imbriqués",
|
|
40156
|
+
"nestedInteractiveControlsAbsent_description": "Vérifie qu’un contrôle interactif (lien, bouton, contrôle de formulaire, ou rôle de widget ARIA) ne contient pas un autre contrôle interactif.",
|
|
40157
|
+
"nestedInteractiveControlsAbsent_summary_fail": "Ce <{{element}}> contient un ou plusieurs contrôles interactifs imbriqués : {{nestedElements}}.",
|
|
40158
|
+
"nestedInteractiveControlsAbsent_hint_fail": "Déplacez le(s) contrôle(s) interactif(s) imbriqué(s) hors de cet élément ; les contrôles interactifs imbriqués ne sont pas utilisables de façon fiable via les technologies d’assistance.",
|
|
40159
|
+
"bypassBlocksPresent_title": "La page doit proposer un moyen de contourner les blocs répétés",
|
|
40160
|
+
"bypassBlocksPresent_description": "Vérifie que la page dispose d’au moins un mécanisme reconnu de contournement des blocs répétés (WCAG 2.4.1) : un point de repère main, un lien d’ancrage fonctionnel vers la même page, ou un titre.",
|
|
40161
|
+
"bypassBlocksPresent_summary_fail": "Cette page n’a aucun moyen reconnu de contourner les blocs de contenu répétés.",
|
|
40162
|
+
"bypassBlocksPresent_hint_fail": "Ajoutez un point de repère main (<main> ou role=\"main\"), un lien « aller au contenu » fonctionnel, ou des éléments de titre que les technologies d’assistance peuvent utiliser pour passer le contenu répété.",
|
|
40163
|
+
"landmarkBannerIsTopLevel_title": "Le point de repère banner doit être de premier niveau",
|
|
40164
|
+
"landmarkBannerIsTopLevel_description": "Vérifie que le point de repère banner (role=\"banner\" ou un <header> non imbriqué) n’est pas imbriqué dans un autre point de repère.",
|
|
40165
|
+
"landmarkBannerIsTopLevel_summary_cantTell": "Ce point de repère banner est imbriqué dans un autre point de repère.",
|
|
40166
|
+
"landmarkBannerIsTopLevel_hint_cantTell": "Déplacez le point de repère banner (header/role=\"banner\") afin qu’il ne soit contenu par aucun autre point de repère ; un banner doit être une région de premier niveau de la page.",
|
|
40167
|
+
"landmarkContentinfoIsTopLevel_title": "Le point de repère contentinfo doit être de premier niveau",
|
|
40168
|
+
"landmarkContentinfoIsTopLevel_description": "Vérifie que le point de repère contentinfo (role=\"contentinfo\" ou un <footer> non imbriqué) n’est pas imbriqué dans un autre point de repère.",
|
|
40169
|
+
"landmarkContentinfoIsTopLevel_summary_cantTell": "Ce point de repère contentinfo est imbriqué dans un autre point de repère.",
|
|
40170
|
+
"landmarkContentinfoIsTopLevel_hint_cantTell": "Déplacez le point de repère contentinfo (footer/role=\"contentinfo\") afin qu’il ne soit contenu par aucun autre point de repère ; contentinfo doit être une région de premier niveau de la page.",
|
|
40171
|
+
"landmarkMainIsTopLevel_title": "Le point de repère main doit être de premier niveau",
|
|
40172
|
+
"landmarkMainIsTopLevel_description": "Vérifie que le point de repère main (role=\"main\" ou <main>) n’est pas imbriqué dans un autre point de repère.",
|
|
40173
|
+
"landmarkMainIsTopLevel_summary_cantTell": "Ce point de repère main est imbriqué dans un autre point de repère.",
|
|
40174
|
+
"landmarkMainIsTopLevel_hint_cantTell": "Déplacez le point de repère main (<main>/role=\"main\") afin qu’il ne soit contenu par aucun autre point de repère ; main doit être une région de premier niveau de la page.",
|
|
40175
|
+
"landmarkNoDuplicateBanner_title": "La page ne doit pas avoir plus d’un point de repère banner",
|
|
40176
|
+
"landmarkNoDuplicateBanner_description": "Vérifie qu’au plus un point de repère banner (role=\"banner\" ou un <header> non imbriqué) existe sur la page.",
|
|
40177
|
+
"landmarkNoDuplicateBanner_summary_cantTell": "Cette page a plus d’un point de repère banner.",
|
|
40178
|
+
"landmarkNoDuplicateBanner_hint_cantTell": "Ne conservez qu’un seul point de repère banner (header/role=\"banner\") par page.",
|
|
40179
|
+
"landmarkNoDuplicateContentinfo_title": "La page ne doit pas avoir plus d’un point de repère contentinfo",
|
|
40180
|
+
"landmarkNoDuplicateContentinfo_description": "Vérifie qu’au plus un point de repère contentinfo (role=\"contentinfo\" ou un <footer> non imbriqué) existe sur la page.",
|
|
40181
|
+
"landmarkNoDuplicateContentinfo_summary_cantTell": "Cette page a plus d’un point de repère contentinfo.",
|
|
40182
|
+
"landmarkNoDuplicateContentinfo_hint_cantTell": "Ne conservez qu’un seul point de repère contentinfo (footer/role=\"contentinfo\") par page.",
|
|
40183
|
+
"landmarkNoDuplicateMain_title": "La page ne doit pas avoir plus d’un point de repère main",
|
|
40184
|
+
"landmarkNoDuplicateMain_description": "Vérifie qu’au plus un point de repère main (role=\"main\" ou <main>) existe sur la page.",
|
|
40185
|
+
"landmarkNoDuplicateMain_summary_cantTell": "Cette page a plus d’un point de repère main.",
|
|
40186
|
+
"landmarkNoDuplicateMain_hint_cantTell": "Ne conservez qu’un seul point de repère main (<main>/role=\"main\") par page.",
|
|
40187
|
+
"landmarkOneMain_title": "La page devrait avoir un point de repère main",
|
|
40188
|
+
"landmarkOneMain_description": "Vérifie que la page a au moins un point de repère main (role=\"main\" ou <main>).",
|
|
40189
|
+
"landmarkOneMain_summary_cantTell_missing": "Cette page n’a aucun point de repère main.",
|
|
40190
|
+
"landmarkOneMain_hint_cantTell_missing": "Ajoutez un point de repère main (<main> ou role=\"main\") autour du contenu principal de la page.",
|
|
40191
|
+
"landmarkUnique_title": "Les points de repère partageant le même rôle doivent avoir des noms uniques",
|
|
40192
|
+
"landmarkUnique_description": "Vérifie que lorsque deux points de repère ou plus partagent le même rôle, chacun a un nom accessible distinct.",
|
|
40193
|
+
"landmarkUnique_summary_cantTell_duplicateName": "Ce point de repère {{role}} partage son nom accessible avec un autre point de repère {{role}}.",
|
|
40194
|
+
"landmarkUnique_summary_cantTell_bothUnnamed": "Ce point de repère {{role}} n’a pas de nom accessible, et plus d’un point de repère {{role}} sans nom existe sur cette page.",
|
|
40195
|
+
"landmarkUnique_hint_cantTell": "Donnez à chaque point de repère {{role}} un nom distinct via aria-label ou aria-labelledby.",
|
|
40196
|
+
"emptyHeading_title": "Les titres ne doivent pas être vides",
|
|
40197
|
+
"emptyHeading_description": "Vérifie que les éléments de titre (<h1>-<h6> ou role=\"heading\") ont un nom accessible non vide.",
|
|
40198
|
+
"emptyHeading_summary_cantTell": "Ce titre n’a pas de nom accessible.",
|
|
40199
|
+
"emptyHeading_hint_cantTell": "Ajoutez du contenu textuel (ou aria-label/aria-labelledby) à ce titre, ou retirez-le s’il n’est pas nécessaire.",
|
|
40200
|
+
"headingOrder_title": "Les niveaux de titre ne doivent pas sauter un niveau",
|
|
40201
|
+
"headingOrder_description": "Vérifie que les niveaux de titre n’augmentent que d’un niveau à la fois, dans l’ordre du document.",
|
|
40202
|
+
"headingOrder_summary_cantTell": "Ce titre passe du niveau {{fromLevel}} au niveau {{toLevel}}, en sautant un niveau.",
|
|
40203
|
+
"headingOrder_hint_cantTell": "Utilisez des niveaux de titre consécutifs (ne sautez pas de niveau en descendant dans la hiérarchie) afin que le plan du document reste prévisible.",
|
|
40204
|
+
"pageHasHeadingOne_title": "La page devrait avoir un titre de niveau un",
|
|
40205
|
+
"pageHasHeadingOne_description": "Vérifie que la page a au moins un titre de niveau un (<h1> ou role=\"heading\" avec aria-level=\"1\").",
|
|
40206
|
+
"pageHasHeadingOne_summary_cantTell": "Cette page n’a aucun titre de niveau un.",
|
|
40207
|
+
"pageHasHeadingOne_hint_cantTell": "Ajoutez un titre de niveau un (<h1> ou role=\"heading\" aria-level=\"1\") identifiant le contenu principal de la page.",
|
|
40208
|
+
"accesskeys_title": "Les valeurs accesskey doivent être uniques",
|
|
40209
|
+
"accesskeys_description": "Vérifie qu’aucun élément de la page ne partage la même valeur d’attribut accesskey qu’un autre.",
|
|
40210
|
+
"accesskeys_summary_cantTell": "L’accesskey de cet élément est partagée avec un autre élément de la page.",
|
|
40211
|
+
"accesskeys_hint_cantTell": "Rendez chaque valeur accesskey unique sur l’ensemble de la page.",
|
|
40212
|
+
"scopeAttrValid_title": "L’attribut scope doit avoir une valeur valide",
|
|
40213
|
+
"scopeAttrValid_description": "Vérifie que scope=\"...\" vaut row, col, rowgroup, ou colgroup.",
|
|
40214
|
+
"scopeAttrValid_summary_cantTell": "Cette valeur d’attribut scope n’est pas reconnue.",
|
|
40215
|
+
"scopeAttrValid_hint_cantTell": "Utilisez row, col, rowgroup, ou colgroup pour l’attribut scope.",
|
|
40216
|
+
"tabindex_title": "tabindex ne devrait pas être supérieur à 0",
|
|
40217
|
+
"tabindex_description": "Vérifie que les valeurs de tabindex sont égales à 0 ou négatives, jamais un nombre positif.",
|
|
40218
|
+
"tabindex_summary_cantTell": "Cet élément a un tabindex positif, ce qui modifie l’ordre naturel de tabulation.",
|
|
40219
|
+
"tabindex_hint_cantTell": "Utilisez tabindex=\"0\" (ou une valeur négative pour le retirer de l’ordre de tabulation) plutôt qu’un nombre positif ; corrigez l’ordre dans le DOM si un ordre de tabulation différent est nécessaire.",
|
|
40220
|
+
"emptyTableHeader_title": "Les cellules d’en-tête de tableau ne doivent pas être vides",
|
|
40221
|
+
"emptyTableHeader_description": "Vérifie que les éléments <th> ont un contenu textuel visible — un en-tête nommé uniquement via aria-label/aria-labelledby est aussi signalé, car la prise en charge réelle par les lecteurs d’écran/navigateurs est incohérente.",
|
|
40222
|
+
"emptyTableHeader_summary_cantTell": "Cette cellule d’en-tête de tableau n’a pas de nom accessible.",
|
|
40223
|
+
"emptyTableHeader_hint_cantTell": "Ajoutez du contenu textuel (ou aria-label/aria-labelledby) à cette cellule d’en-tête, ou retirez-la si elle n’est pas nécessaire.",
|
|
40224
|
+
"emptyTableHeader_summary_cantTell_ariaOnly": "Cette cellule d’en-tête de tableau n’a pas de texte visible — son seul nom accessible provient de aria-label/aria-labelledby, que des combinaisons réelles de lecteur d’écran/navigateur (ex. NVDA+Firefox, iOS VoiceOver+Safari) sont connues pour ignorer sur les éléments <th>.",
|
|
40225
|
+
"emptyTableHeader_hint_cantTell_ariaOnly": "Ajoutez du contenu textuel visible à cette cellule d’en-tête (en plus de, ou à la place de, aria-label/aria-labelledby) — le texte visible est le seul mécanisme de nommage confirmé comme fonctionnel sur les lecteurs d’écran testés.",
|
|
40226
|
+
"labelTitleOnly_title": "Les contrôles de formulaire ne devraient pas utiliser title comme seule étiquette",
|
|
40227
|
+
"labelTitleOnly_description": "Vérifie qu’un contrôle de formulaire ayant un attribut title possède aussi une véritable étiquette (élément label, aria-label, ou aria-labelledby).",
|
|
40228
|
+
"labelTitleOnly_summary_cantTell": "Ce contrôle de formulaire repose sur l’attribut title comme seule étiquette.",
|
|
40229
|
+
"labelTitleOnly_hint_cantTell": "Ajoutez une <label> visible (ou aria-label/aria-labelledby) en plus de, ou à la place de, l’attribut title.",
|
|
40230
|
+
"imageRedundantAlt_title": "Le texte alt d’une image ne doit pas dupliquer le texte visible adjacent",
|
|
40231
|
+
"imageRedundantAlt_description": "Vérifie que le texte alt d’un <img> n’est pas identique à un autre texte visible déjà présent dans son élément parent immédiat.",
|
|
40232
|
+
"imageRedundantAlt_summary_cantTell": "Le texte alt de cette image duplique un autre texte visible juste à côté.",
|
|
40233
|
+
"imageRedundantAlt_hint_cantTell": "Videz le texte alt (alt=\"\") si l’image est purement décorative à côté du texte, ou supprimez la duplication redondante.",
|
|
40234
|
+
"tableDuplicateName_title": "La légende d’un tableau ne doit pas dupliquer son attribut summary",
|
|
40235
|
+
"tableDuplicateName_description": "Vérifie que le texte de la <caption> d’un <table> n’est pas identique à son attribut summary (obsolète).",
|
|
40236
|
+
"tableDuplicateName_summary_cantTell": "La légende de ce tableau duplique son attribut summary.",
|
|
40237
|
+
"tableDuplicateName_hint_cantTell": "Retirez l’attribut summary redondant, ou faites en sorte qu’il apporte une information différente de la légende.",
|
|
40238
|
+
"metaViewportLarge_title": "La balise meta viewport devrait permettre un zoom jusqu’à 500 %",
|
|
40239
|
+
"metaViewportLarge_description": "Vérifie que <meta name=\"viewport\"> ne définit pas user-scalable=no ni maximum-scale en dessous de 5 (500 %).",
|
|
40240
|
+
"metaViewportLarge_summary_cantTell": "Cette balise meta viewport restreint le zoom en dessous de l’objectif de bonne pratique de 500 %.",
|
|
40241
|
+
"metaViewportLarge_hint_cantTell": "Retirez user-scalable=no et augmentez maximum-scale à au moins 5 (500 %) si possible.",
|
|
40242
|
+
"presentationRoleConflict_title": "Un rôle de présentation ne doit pas entrer en conflit avec un attribut ARIA global ou la focalisabilité",
|
|
40243
|
+
"presentationRoleConflict_description": "Vérifie que role=\"presentation\"/\"none\" (y compris le rôle presentation implicite d’un <img alt=\"\">) n’est pas combiné avec un attribut ARIA global (aria-label, aria-hidden, aria-describedby, ...) ou avec la focalisabilité (tabindex/native).",
|
|
40244
|
+
"presentationRoleConflict_summary_cantTell": "Cet élément role=\"{{role}}\" a aussi une condition conflictuelle ({{attrs}}), qui restaure son rôle implicite et annule l’intention présentationnelle.",
|
|
40245
|
+
"presentationRoleConflict_hint_cantTell": "Retirez le(s) attribut(s) de nommage conflictuel(s) et/ou la focalisabilité (tabindex/native) si l’élément doit rester présentationnel, ou retirez role=\"presentation\"/\"none\" s’il doit être exposé aux technologies d’assistance.",
|
|
40246
|
+
"region_title": "Le contenu de la page devrait se trouver à l’intérieur d’un point de repère",
|
|
40247
|
+
"region_description": "Vérifie que les enfants directs de <body> ayant un contenu textuel visible sont contenus dans un point de repère.",
|
|
40248
|
+
"region_summary_cantTell": "Ce contenu n’est contenu dans aucun point de repère.",
|
|
40249
|
+
"region_hint_cantTell": "Déplacez ce contenu à l’intérieur d’un point de repère (main, nav, aside, une section nommée, etc.).",
|
|
40250
|
+
"skipLink_title": "Un lien d’évitement doit avoir une cible qui se résout",
|
|
40251
|
+
"skipLink_description": "Vérifie que le fragment href d’un lien « aller au... » se résout vers un élément réel du document.",
|
|
40252
|
+
"skipLink_summary_cantTell": "La cible de ce lien d’évitement n’existe pas.",
|
|
40253
|
+
"skipLink_hint_cantTell": "Faites pointer le href du lien d’évitement vers un id qui existe dans le document, ou ajoutez l’élément cible manquant.",
|
|
40254
|
+
"autocompleteValid_title": "L’attribut autocomplete doit être une valeur d’auto-remplissage valide",
|
|
40255
|
+
"autocompleteValid_description": "Vérifie qu’un attribut autocomplete non vide vaut « on »/« off » ou une liste de jetons d’auto-remplissage bien formée.",
|
|
40256
|
+
"autocompleteValid_summary_fail": "Cette valeur d’attribut autocomplete n’est pas une valeur d’auto-remplissage valide.",
|
|
40257
|
+
"autocompleteValid_hint_fail": "Utilisez « on »/« off », ou une liste de jetons d’auto-remplissage valide (ex. « shipping street-address », « cc-number »).",
|
|
40258
|
+
"htmlXmlLangMismatch_title": "lang et xml:lang ne doivent pas se contredire",
|
|
40259
|
+
"htmlXmlLangMismatch_description": "Vérifie que les attributs lang et xml:lang de l’élément <html> déclarent la même langue principale, lorsque les deux sont présents.",
|
|
40260
|
+
"htmlXmlLangMismatch_summary_fail": "Les attributs lang (« {{lang}} ») et xml:lang (« {{xmlLang}} ») déclarent des langues différentes.",
|
|
40261
|
+
"htmlXmlLangMismatch_hint_fail": "Faites en sorte que lang et xml:lang déclarent la même langue principale, ou retirez l’attribut obsolète xml:lang.",
|
|
40262
|
+
"avoidInlineSpacing_title": "Un style en ligne ne doit pas forcer l’espacement du texte avec !important",
|
|
40263
|
+
"avoidInlineSpacing_description": "Vérifie qu’un style en ligne ne définit pas line-height, letter-spacing, ou word-spacing avec !important, ce qui bloque les surcharges d’espacement de texte par l’utilisateur.",
|
|
40264
|
+
"avoidInlineSpacing_summary_fail": "Le style en ligne de cet élément force {{properties}} avec !important, bloquant les surcharges d’espacement de texte par l’utilisateur.",
|
|
40265
|
+
"avoidInlineSpacing_hint_fail": "Retirez !important de line-height/letter-spacing/word-spacing dans les styles en ligne afin que les utilisateurs puissent surcharger l’espacement du texte.",
|
|
40266
|
+
"metaRefreshNoExceptions_title": "La page ne doit utiliser aucun rafraîchissement meta (AAA)",
|
|
40267
|
+
"metaRefreshNoExceptions_description": "Vérifie que <meta http-equiv=\"refresh\"> n’est présent en aucun cas, quel que soit le délai — la variante plus stricte, de niveau AAA, de la vérification de niveau A qui ne porte que sur les délais positifs.",
|
|
40268
|
+
"metaRefreshNoExceptions_summary_fail": "Cette page utilise un rafraîchissement meta, un changement de contexte automatique non initié par l’utilisateur.",
|
|
40269
|
+
"metaRefreshNoExceptions_hint_fail": "Retirez le rafraîchissement meta ; déclenchez la redirection/le rafraîchissement uniquement en réponse à une action de l’utilisateur.",
|
|
40270
|
+
"validLang_title": "L’attribut lang d’un élément doit être syntaxiquement valide",
|
|
40271
|
+
"validLang_description": "Vérifie que tout élément (autre que la racine <html>) ayant un attribut lang non vide utilise une étiquette de langue syntaxiquement valide.",
|
|
40272
|
+
"validLang_summary_fail": "Cette valeur d’attribut lang (« {{value}} ») n’est pas une étiquette de langue syntaxiquement valide.",
|
|
40273
|
+
"validLang_hint_fail": "Utilisez une étiquette de langue BCP47 valide (ex. « fr », « es-MX »).",
|
|
40274
|
+
"linkInTextBlock_title": "Les liens dans des blocs de texte doivent être distinguables du texte environnant sans se fier uniquement à la couleur",
|
|
40275
|
+
"linkInTextBlock_description": "Vérifie qu’un lien à l’intérieur d’un bloc de texte est visuellement distinguable du texte environnant par un soulignement, une différence de graisse/style de police, ou un contraste de couleur suffisant (>= 3:1) — pas seulement par la couleur.",
|
|
40276
|
+
"linkInTextBlock_summary_fail": "Ce lien dans un bloc de texte se distingue du texte environnant uniquement par la couleur.",
|
|
40277
|
+
"linkInTextBlock_hint_fail": "Ajoutez un soulignement, une différence de graisse/style de police, ou augmentez le contraste de couleur entre le lien et le texte environnant à au moins 3:1.",
|
|
40278
|
+
"noAutoplayAudio_title": "Un audio en lecture automatique devrait proposer un mécanisme de pause/arrêt ou de contrôle du volume",
|
|
40279
|
+
"noAutoplayAudio_description": "Signale les éléments <audio>/<video> qui se lancent automatiquement sans être coupés et sans attribut controls natif, pour une revue manuelle par rapport à l’exemption de 3 secondes de la WCAG 1.4.2.",
|
|
40280
|
+
"noAutoplayAudio_summary_cantTell": "Cet élément lit un audio automatiquement sans mécanisme natif de pause/arrêt ou de contrôle du volume.",
|
|
40281
|
+
"noAutoplayAudio_hint_cantTell": "Si ce clip dure plus de 3 secondes, ajoutez un attribut controls (ou un mécanisme personnalisé équivalent) afin que les utilisateurs puissent le mettre en pause/l’arrêter ou contrôler son volume indépendamment du volume du système.",
|
|
40282
|
+
"videoCaption_title": "Une vidéo préenregistrée devrait proposer une piste de sous-titres",
|
|
40283
|
+
"videoCaption_description": "Signale les éléments <video> sans enfant <track kind=\"captions\"|\"subtitles\">, pour une revue manuelle visant à déterminer si la vidéo a une piste audio nécessitant des sous-titres.",
|
|
40284
|
+
"videoCaption_summary_cantTell": "Cette vidéo n’a aucune piste de sous-titres (captions ou subtitles).",
|
|
40285
|
+
"videoCaption_hint_cantTell": "Si cette vidéo a une piste audio porteuse d’information, ajoutez un <track kind=\"captions\" src=\"...\"> avec le contenu sous-titré.",
|
|
40286
|
+
"scrollableRegionFocusable_title": "Les régions défilantes sans contenu focalisable devraient être focalisables au clavier",
|
|
40287
|
+
"scrollableRegionFocusable_description": "Signale les éléments dont le CSS déclare overflow:auto/scroll, qui ne contiennent aucun descendant focalisable, et qui ne sont pas eux-mêmes focalisables au clavier, pour une revue manuelle visant à déterminer si leur contenu déborde réellement et nécessite un accès au défilement au clavier.",
|
|
40288
|
+
"scrollableRegionFocusable_summary_cantTell": "Cet élément déclare overflow:auto/scroll, n’a aucun descendant focalisable, et n’est pas lui-même focalisable au clavier.",
|
|
40289
|
+
"scrollableRegionFocusable_hint_cantTell": "Si le contenu de cette région déborde réellement, ajoutez tabindex=\"0\" (et une étiquette adaptée) afin que les utilisateurs du clavier puissent la focaliser et faire défiler avec les flèches.",
|
|
40290
|
+
"identicalLinksSamePurpose_title": "Les liens partageant le même nom accessible devraient mener à la même destination",
|
|
40291
|
+
"identicalLinksSamePurpose_description": "Signale les groupes de liens qui partagent le même nom accessible mais mènent à plus d’une destination distincte, pour une revue manuelle visant à déterminer s’ils servent le même objectif.",
|
|
40292
|
+
"identicalLinksSamePurpose_summary_cantTell": "Ce lien partage un nom accessible avec d’autres liens de la page qui mènent à une destination différente.",
|
|
40293
|
+
"identicalLinksSamePurpose_hint_cantTell": "Assurez-vous que les liens ayant le même texte servent le même objectif, ou rendez le texte du lien suffisamment distinct pour décrire chaque destination.",
|
|
40294
|
+
"ariaBrailleEquivalent_title": "aria-braillelabel/aria-brailleroledescription doivent avoir un équivalent non braille",
|
|
40295
|
+
"ariaBrailleEquivalent_description": "Vérifie que les éléments utilisant aria-braillelabel ont aussi un nom accessible ordinaire, et que ceux utilisant aria-brailleroledescription ont aussi aria-roledescription.",
|
|
40296
|
+
"ariaBrailleEquivalent_summary_fail": "Cet élément a {{attr}} mais pas {{requires}}, son équivalent non braille.",
|
|
40297
|
+
"ariaBrailleEquivalent_hint_fail": "{{attr}} est un complément spécifique au braille, pas un remplacement — fournissez aussi {{requires}}.",
|
|
40298
|
+
"ariaConditionalAttr_title": "aria-errormessage exige que aria-invalid soit défini à une valeur autre que false",
|
|
40299
|
+
"ariaConditionalAttr_description": "Vérifie que les éléments ayant aria-errormessage ont aussi aria-invalid défini à « true », « grammar », ou « spelling » — sinon le message d’erreur est retiré de l’arbre d’accessibilité.",
|
|
40300
|
+
"ariaConditionalAttr_summary_fail": "Cet élément a aria-errormessage mais aria-invalid est absent ou « false », donc le message d’erreur n’est pas exposé.",
|
|
40301
|
+
"ariaConditionalAttr_hint_fail": "Définissez aria-invalid à « true » (ou « grammar »/« spelling ») chaque fois que aria-errormessage doit être exposé aux technologies d’assistance.",
|
|
40302
|
+
"ariaCheckedStateMismatch_title": "L’aria-checked d’une case à cocher/d’un bouton radio natif devrait correspondre à son état réel",
|
|
40303
|
+
"ariaCheckedStateMismatch_description": "Signale un <input type=\"checkbox\">/<input type=\"radio\"> natif dont la valeur explicite d’aria-checked ne correspond pas à son état réel (coché/indéterminé), pour une revue manuelle.",
|
|
40304
|
+
"ariaCheckedStateMismatch_summary_cantTell": "La valeur d’aria-checked de cet élément ne correspond pas à son état réel (coché/indéterminé).",
|
|
40305
|
+
"ariaCheckedStateMismatch_hint_cantTell": "Définissez aria-checked pour qu’il corresponde à l’état réel de l’élément, ou retirez-le — une case à cocher/un bouton radio natif expose déjà cet état sans lui.",
|
|
40306
|
+
"cssOrientationLock_title": "Le CSS ne doit pas verrouiller la page à une seule orientation",
|
|
40307
|
+
"cssOrientationLock_description": "Vérifie qu’aucune règle @media (orientation: portrait|landscape) ne définit un transform: rotate(...) sur la page, une technique connue pour contourner l’orientation de l’appareil.",
|
|
40308
|
+
"cssOrientationLock_summary_fail": "Une media query « {{mediaText}} » fait pivoter « {{selectorText}} », verrouillant la page à une seule orientation.",
|
|
40309
|
+
"cssOrientationLock_hint_fail": "Retirez la transformation rotate() de la media query d’orientation ; laissez la page répondre naturellement à l’orientation de l’appareil au lieu de forcer une rotation visuelle.",
|
|
40310
|
+
"ariaText_title": "Les éléments role=\"text\" ne devraient avoir aucun descendant focalisable",
|
|
40311
|
+
"ariaText_description": "Vérifie que les éléments ayant role=\"text\" ne contiennent aucun descendant focalisable (lien, bouton, contrôle de formulaire, tabindex, iframe, ou contenteditable).",
|
|
40312
|
+
"ariaText_summary_cantTell": "Cet élément role=\"text\" contient un descendant focalisable.",
|
|
40313
|
+
"ariaText_hint_cantTell": "Retirez role=\"text\" (ou retirez le descendant focalisable) — une région de « texte brut » ne devrait pas contenir de contenu focalisable.",
|
|
40314
|
+
"focusOrderSemantics_title": "Les éléments ajoutés à l’ordre de tabulation devraient avoir une sémantique interactive",
|
|
40315
|
+
"focusOrderSemantics_description": "Signale les éléments ayant tabindex >= 0 dont le rôle explicite est un rôle structurel/documentaire non interactif (ex. heading, list, region, presentation), pour une revue manuelle.",
|
|
40316
|
+
"focusOrderSemantics_summary_cantTell": "Cet élément est dans l’ordre de tabulation (tabindex=\"{{tabindex}}\") mais a un rôle non interactif (« {{role}} »).",
|
|
40317
|
+
"focusOrderSemantics_hint_cantTell": "Retirez tabindex si cet élément n’est pas censé être interactif, ou utilisez un rôle interactif correspondant à son comportement réel.",
|
|
40318
|
+
"pAsHeading_title": "Un <p> stylé pour ressembler à un titre devrait probablement être un véritable titre",
|
|
40319
|
+
"pAsHeading_description": "Signale les éléments <p> courts dont tout le texte est en gras et affiché à >= 18px, pour une revue manuelle visant à déterminer si un véritable élément de titre devrait être utilisé à la place.",
|
|
40320
|
+
"pAsHeading_summary_cantTell": "Ce paragraphe est entièrement en gras et affiché à une taille évoquant un titre.",
|
|
40321
|
+
"pAsHeading_hint_cantTell": "Si ce texte introduit une nouvelle section, utilisez un véritable élément de titre (<h1>-<h6> ou role=\"heading\") plutôt que de styler un paragraphe pour qu’il y ressemble.",
|
|
40322
|
+
"tableFakeCaption_title": "La première ligne d’un tableau ne devrait pas tenir lieu de véritable <caption>",
|
|
40323
|
+
"tableFakeCaption_description": "Signale les tableaux sans <caption> dont la première ligne a une seule cellule non vide alors que les autres lignes ont plusieurs cellules, pour une revue manuelle visant à déterminer si cette cellule fait office de légende factice.",
|
|
40324
|
+
"tableFakeCaption_summary_cantTell": "Ce tableau n’a pas de <caption>, mais sa première ligne est une cellule unique placée au-dessus de lignes à plusieurs cellules — elle fait peut-être office de légende factice.",
|
|
40325
|
+
"tableFakeCaption_hint_cantTell": "Si cette cellule est censée décrire le tableau, utilisez un véritable élément <caption> plutôt qu’une cellule isolée en première ligne.",
|
|
40326
|
+
"tdHasHeader_title": "Les cellules de données des grands tableaux doivent avoir un en-tête associé",
|
|
40327
|
+
"tdHasHeader_description": "Vérifie que chaque <td> d’un tableau grand et simple (sans colspan/rowspan) a un en-tête associé — via un attribut headers, un <th> de colonne implicite au-dessus, ou un <th> de ligne implicite à sa gauche.",
|
|
40328
|
+
"tdHasHeader_summary_fail": "Cette cellule de données n’a pas d’en-tête associé (pas d’attribut headers, pas de <th> de colonne au-dessus, pas de <th> de ligne à gauche).",
|
|
40329
|
+
"tdHasHeader_hint_fail": "Ajoutez un attribut headers référençant le(s) id du/des <th> pertinent(s), ou restructurez le tableau afin que cette cellule ait un en-tête de ligne/colonne implicite.",
|
|
40330
|
+
"mouseOnlyEventHandlers_title": "Les gestionnaires d’événements en ligne réservés au pointeur devraient avoir un équivalent accessible au clavier",
|
|
40331
|
+
"mouseOnlyEventHandlers_description": "Signale les éléments ayant un gestionnaire d’événement en ligne réservé au pointeur (onmouseover, onmouseout, onmousedown, onmouseup, ondblclick, onmousemove, onmouseenter, onmouseleave) sans équivalent accessible au clavier (onkeydown/onkeyup/onkeypress/onfocus/onblur), pour une revue manuelle.",
|
|
40332
|
+
"mouseOnlyEventHandlers_summary_cantTell": "Cet élément a {{attrs}} mais aucun gestionnaire équivalent accessible au clavier.",
|
|
40333
|
+
"mouseOnlyEventHandlers_hint_cantTell": "Ajoutez onkeydown/onkeyup/onkeypress (ou onfocus/onblur pour un comportement déclenché au survol) afin que cette fonctionnalité soit aussi accessible au clavier.",
|
|
40334
|
+
"linkNameQuality_title": "Le texte des liens devrait être descriptif, pas générique",
|
|
40335
|
+
"linkNameQuality_description": "Signale les liens dont le nom accessible complet est une formule connue comme non descriptive (ex. « cliquez ici », « en savoir plus », « plus »), pour une revue manuelle visant à déterminer si l’objet du lien est clair sans contexte supplémentaire.",
|
|
40336
|
+
"linkNameQuality_summary_cantTell": "Le nom accessible de ce lien (« {{name}} ») est une formule générique et non descriptive.",
|
|
40337
|
+
"linkNameQuality_hint_cantTell": "Faites en sorte que le texte du lien lui-même décrive sa destination/son objet (ex. « Télécharger le guide tarifaire 2026 » plutôt que « Télécharger »), ou confirmez que le contexte environnant rend déjà l’objet clair."
|
|
39663
40338
|
}
|
|
39664
40339
|
};
|
|
39665
40340
|
|
|
@@ -42383,14 +43058,35 @@ const createDomHelpers = (function createDomHelpers(opts) {
|
|
|
42383
43058
|
const includeShadowDom = !(opts && opts.includeShadowDom === false);
|
|
42384
43059
|
const excludeSelectors = Array.isArray(opts && opts.excludeSelectors) ? opts.excludeSelectors : [];
|
|
42385
43060
|
|
|
43061
|
+
// Rule-scoped excludes (engineOptions.rules[ruleId].excludeSelectors), set
|
|
43062
|
+
// by dom-runner.js immediately before invoking each rule's applicability/
|
|
43063
|
+
// run function via __setActiveRuleExcludeSelectors(). Safe as mutable
|
|
43064
|
+
// closure state because rule execution is synchronous and single-rule-
|
|
43065
|
+
// at-a-time: exactly one rule's excludes are ever "active" at once.
|
|
43066
|
+
var __activeRuleExcludeSelectors = [];
|
|
43067
|
+
|
|
43068
|
+
function __getEffectiveExcludeSelectors() {
|
|
43069
|
+
return __activeRuleExcludeSelectors.length
|
|
43070
|
+
? excludeSelectors.concat(__activeRuleExcludeSelectors)
|
|
43071
|
+
: excludeSelectors;
|
|
43072
|
+
}
|
|
43073
|
+
|
|
43074
|
+
function __setActiveRuleExcludeSelectors(list) {
|
|
43075
|
+
__activeRuleExcludeSelectors = normalizeSelectorList(list);
|
|
43076
|
+
}
|
|
43077
|
+
|
|
42386
43078
|
// Selector-related caches (selector uniqueness index, per-element built
|
|
42387
|
-
// selector strings) depend on includeShadowDom/
|
|
42388
|
-
// those change which elements are considered when checking
|
|
42389
|
-
// The underlying storage is shared across createDomHelpers()
|
|
42390
|
-
// the same window/document (see __domSharedCache below), so a
|
|
42391
|
-
//
|
|
42392
|
-
//
|
|
42393
|
-
|
|
43079
|
+
// selector strings) depend on includeShadowDom/the effective exclude
|
|
43080
|
+
// list, since those change which elements are considered when checking
|
|
43081
|
+
// uniqueness. The underlying storage is shared across createDomHelpers()
|
|
43082
|
+
// calls on the same window/document (see __domSharedCache below), so a
|
|
43083
|
+
// run -- or a rule with its own rule-scoped excludes -- must not
|
|
43084
|
+
// read/write another run/rule's cached selectors. This key partitions
|
|
43085
|
+
// those caches per effective option set; recomputed per call (not a
|
|
43086
|
+
// constant) since the effective list changes as the active rule changes.
|
|
43087
|
+
function __getSelectorOptsKey() {
|
|
43088
|
+
return (includeShadowDom ? 'sd1' : 'sd0') + '|' + __getEffectiveExcludeSelectors().slice().sort().join(',');
|
|
43089
|
+
}
|
|
42394
43090
|
|
|
42395
43091
|
// -------------------------------------------------------------------------
|
|
42396
43092
|
// Per-run shared caches (DOM helpers)
|
|
@@ -43152,9 +43848,10 @@ const createDomHelpers = (function createDomHelpers(opts) {
|
|
|
43152
43848
|
|
|
43153
43849
|
|
|
43154
43850
|
function isExcluded(el) {
|
|
43155
|
-
|
|
43851
|
+
const eff = __getEffectiveExcludeSelectors();
|
|
43852
|
+
if (!eff.length || !el || !el.closest) return false;
|
|
43156
43853
|
try {
|
|
43157
|
-
return
|
|
43854
|
+
return eff.some((sel) => !!el.closest(sel));
|
|
43158
43855
|
} catch {
|
|
43159
43856
|
return false;
|
|
43160
43857
|
}
|
|
@@ -43249,8 +43946,10 @@ const createDomHelpers = (function createDomHelpers(opts) {
|
|
|
43249
43946
|
if (!scope || !scope.querySelectorAll) return [];
|
|
43250
43947
|
|
|
43251
43948
|
// Cache shadow root discovery per root to avoid repeated querySelectorAll('*') walks.
|
|
43252
|
-
// IMPORTANT: do not cache when
|
|
43253
|
-
|
|
43949
|
+
// IMPORTANT: do not cache when the effective exclude list (global
|
|
43950
|
+
// ∪ active rule-scoped excludes) is non-empty -- different rules
|
|
43951
|
+
// may have different effective lists and must not share results.
|
|
43952
|
+
if (!__getEffectiveExcludeSelectors().length && __shadowRootsByRoot) {
|
|
43254
43953
|
try {
|
|
43255
43954
|
const cached = __shadowRootsByRoot.get(scope);
|
|
43256
43955
|
if (cached) {
|
|
@@ -43325,7 +44024,7 @@ const createDomHelpers = (function createDomHelpers(opts) {
|
|
|
43325
44024
|
|
|
43326
44025
|
function queryAllSmart(sel) {
|
|
43327
44026
|
const list = includeShadowDom ? queryAllDeep(sel) : queryAll(sel);
|
|
43328
|
-
return
|
|
44027
|
+
return __getEffectiveExcludeSelectors().length ? list.filter((el) => !isExcluded(el)) : list;
|
|
43329
44028
|
}
|
|
43330
44029
|
|
|
43331
44030
|
// -------------------------------------------------------------------------
|
|
@@ -43359,10 +44058,11 @@ const createDomHelpers = (function createDomHelpers(opts) {
|
|
|
43359
44058
|
function __getSelectorCacheForOpts() {
|
|
43360
44059
|
if (!__selectorCache) return null;
|
|
43361
44060
|
try {
|
|
43362
|
-
|
|
44061
|
+
const key = __getSelectorOptsKey();
|
|
44062
|
+
let wm = __selectorCache.get(key);
|
|
43363
44063
|
if (!(wm instanceof WeakMap)) {
|
|
43364
44064
|
wm = new WeakMap();
|
|
43365
|
-
__selectorCache.set(
|
|
44065
|
+
__selectorCache.set(key, wm);
|
|
43366
44066
|
}
|
|
43367
44067
|
return wm;
|
|
43368
44068
|
} catch {
|
|
@@ -45773,7 +46473,8 @@ const createDomHelpers = (function createDomHelpers(opts) {
|
|
|
45773
46473
|
return createSelectorUniqIndex();
|
|
45774
46474
|
}
|
|
45775
46475
|
|
|
45776
|
-
const
|
|
46476
|
+
const key = __getSelectorOptsKey();
|
|
46477
|
+
const cached = perScope.get(key);
|
|
45777
46478
|
if (cached) {
|
|
45778
46479
|
__perfInc('uniqIndex.hit');
|
|
45779
46480
|
return cached;
|
|
@@ -45782,7 +46483,7 @@ const createDomHelpers = (function createDomHelpers(opts) {
|
|
|
45782
46483
|
__perfInc('uniqIndex.miss');
|
|
45783
46484
|
const idx = createSelectorUniqIndex();
|
|
45784
46485
|
try {
|
|
45785
|
-
perScope.set(
|
|
46486
|
+
perScope.set(key, idx);
|
|
45786
46487
|
} catch { /* ignore */
|
|
45787
46488
|
}
|
|
45788
46489
|
__perfInc('uniqIndex.build');
|
|
@@ -46292,6 +46993,12 @@ const createDomHelpers = (function createDomHelpers(opts) {
|
|
|
46292
46993
|
isAccTreeEligible,
|
|
46293
46994
|
isDomVisibleEligible,
|
|
46294
46995
|
|
|
46996
|
+
// Engine-internal: sets which rule's rule-scoped excludeSelectors
|
|
46997
|
+
// (engineOptions.rules[ruleId].excludeSelectors) are currently in
|
|
46998
|
+
// effect. Called by dom-runner.js before each rule invocation, not
|
|
46999
|
+
// intended for use by rule implementations.
|
|
47000
|
+
__setActiveRuleExcludeSelectors,
|
|
47001
|
+
|
|
46295
47002
|
// Eligibility info wrapper
|
|
46296
47003
|
getEligibilityInfo,
|
|
46297
47004
|
|
|
@@ -46705,6 +47412,15 @@ const runCore = (function runCore(pageUrl, contextSelector, engineOptions, runOn
|
|
|
46705
47412
|
? engineOptionsResolved.rules[defResolved.ruleId]
|
|
46706
47413
|
: null;
|
|
46707
47414
|
|
|
47415
|
+
// Rule-scoped excludeSelectors (engineOptions.rules[ruleId].excludeSelectors)
|
|
47416
|
+
// apply on top of the global excludeSelectors for exactly this rule's
|
|
47417
|
+
// applicability check + run, then are cleared once this rule is done.
|
|
47418
|
+
// Safe because rule execution below is synchronous and one rule at a
|
|
47419
|
+
// time -- sharedHelpers is reused across all rules in this loop.
|
|
47420
|
+
if (typeof sharedHelpers.__setActiveRuleExcludeSelectors === 'function') {
|
|
47421
|
+
sharedHelpers.__setActiveRuleExcludeSelectors(ruleConfig && ruleConfig.excludeSelectors);
|
|
47422
|
+
}
|
|
47423
|
+
|
|
46708
47424
|
const ctx = {
|
|
46709
47425
|
document,
|
|
46710
47426
|
window,
|
|
@@ -46775,6 +47491,14 @@ const runCore = (function runCore(pageUrl, contextSelector, engineOptions, runOn
|
|
|
46775
47491
|
if (ruleTimings) ruleTimings[defResolved.ruleId] = (ruleTimings[defResolved.ruleId] || 0) + (nowMs() - t0);
|
|
46776
47492
|
}
|
|
46777
47493
|
|
|
47494
|
+
// Composite rollups below carry no occurrences/nodes of their own, so
|
|
47495
|
+
// they never exercise rule-scoped excludes -- but clear the "active
|
|
47496
|
+
// rule" state on sharedHelpers regardless, so nothing after this point
|
|
47497
|
+
// (composite aggregation, perf stats) can observe a stale rule's excludes.
|
|
47498
|
+
if (typeof sharedHelpers.__setActiveRuleExcludeSelectors === 'function') {
|
|
47499
|
+
sharedHelpers.__setActiveRuleExcludeSelectors(null);
|
|
47500
|
+
}
|
|
47501
|
+
|
|
46778
47502
|
// =========================
|
|
46779
47503
|
// Composite rule aggregation (data-only rollups)
|
|
46780
47504
|
// =========================
|
|
@@ -54785,39 +55509,39 @@ if (isAccTreeEligible) {
|
|
|
54785
55509
|
// role/attribute pairings from the WAI-ARIA role definitions are listed.
|
|
54786
55510
|
const SUPPORTED_ATTRS_BY_ROLE = {
|
|
54787
55511
|
alertdialog: ['aria-modal'],
|
|
54788
|
-
checkbox: ['aria-checked', 'aria-readonly', 'aria-required'],
|
|
54789
|
-
columnheader: ['aria-sort', 'aria-colindex', 'aria-colspan', 'aria-readonly', 'aria-required', 'aria-rowindex', 'aria-rowspan', 'aria-selected'],
|
|
54790
|
-
combobox: ['aria-expanded', 'aria-autocomplete', 'aria-readonly', 'aria-required'],
|
|
55512
|
+
checkbox: ['aria-checked', 'aria-readonly', 'aria-required', 'aria-expanded'],
|
|
55513
|
+
columnheader: ['aria-sort', 'aria-colindex', 'aria-colspan', 'aria-readonly', 'aria-required', 'aria-rowindex', 'aria-rowspan', 'aria-selected', 'aria-expanded'],
|
|
55514
|
+
combobox: ['aria-expanded', 'aria-autocomplete', 'aria-readonly', 'aria-required', 'aria-activedescendant'],
|
|
54791
55515
|
dialog: ['aria-modal'],
|
|
54792
|
-
grid: ['aria-multiselectable', 'aria-readonly', 'aria-colcount', 'aria-rowcount'],
|
|
54793
|
-
gridcell: ['aria-selected', 'aria-readonly', 'aria-required', 'aria-colindex', 'aria-colspan', 'aria-rowindex', 'aria-rowspan'],
|
|
55516
|
+
grid: ['aria-multiselectable', 'aria-readonly', 'aria-colcount', 'aria-rowcount', 'aria-activedescendant'],
|
|
55517
|
+
gridcell: ['aria-selected', 'aria-readonly', 'aria-required', 'aria-colindex', 'aria-colspan', 'aria-rowindex', 'aria-rowspan', 'aria-expanded'],
|
|
54794
55518
|
heading: ['aria-level'],
|
|
54795
|
-
listbox: ['aria-multiselectable', 'aria-readonly', 'aria-required', 'aria-orientation'],
|
|
55519
|
+
listbox: ['aria-multiselectable', 'aria-readonly', 'aria-required', 'aria-orientation', 'aria-expanded', 'aria-activedescendant'],
|
|
54796
55520
|
listitem: ['aria-level', 'aria-posinset', 'aria-setsize'],
|
|
54797
55521
|
menu: ['aria-activedescendant', 'aria-orientation'],
|
|
54798
55522
|
menubar: ['aria-activedescendant', 'aria-orientation'],
|
|
54799
|
-
menuitemcheckbox: ['aria-checked'],
|
|
54800
|
-
menuitemradio: ['aria-checked'],
|
|
55523
|
+
menuitemcheckbox: ['aria-checked', 'aria-expanded', 'aria-readonly', 'aria-required', 'aria-posinset', 'aria-setsize'],
|
|
55524
|
+
menuitemradio: ['aria-checked', 'aria-expanded', 'aria-readonly', 'aria-required', 'aria-posinset', 'aria-setsize'],
|
|
54801
55525
|
meter: ['aria-valuenow', 'aria-valuemin', 'aria-valuemax', 'aria-valuetext'],
|
|
54802
55526
|
option: ['aria-selected', 'aria-checked', 'aria-posinset', 'aria-setsize'],
|
|
54803
55527
|
progressbar: ['aria-valuenow', 'aria-valuemin', 'aria-valuemax', 'aria-valuetext'],
|
|
54804
|
-
radio: ['aria-checked'],
|
|
54805
|
-
radiogroup: ['aria-readonly', 'aria-required', 'aria-orientation'],
|
|
54806
|
-
row: ['aria-selected', 'aria-level', 'aria-posinset', 'aria-setsize', 'aria-colindex', 'aria-rowindex'],
|
|
54807
|
-
rowheader: ['aria-sort', 'aria-colindex', 'aria-colspan', 'aria-readonly', 'aria-required', 'aria-rowindex', 'aria-rowspan', 'aria-selected'],
|
|
55528
|
+
radio: ['aria-checked', 'aria-posinset', 'aria-setsize'],
|
|
55529
|
+
radiogroup: ['aria-readonly', 'aria-required', 'aria-orientation', 'aria-activedescendant'],
|
|
55530
|
+
row: ['aria-selected', 'aria-level', 'aria-posinset', 'aria-setsize', 'aria-colindex', 'aria-rowindex', 'aria-expanded', 'aria-activedescendant'],
|
|
55531
|
+
rowheader: ['aria-sort', 'aria-colindex', 'aria-colspan', 'aria-readonly', 'aria-required', 'aria-rowindex', 'aria-rowspan', 'aria-selected', 'aria-expanded'],
|
|
54808
55532
|
scrollbar: ['aria-valuenow', 'aria-valuemin', 'aria-valuemax', 'aria-valuetext', 'aria-orientation', 'aria-controls'],
|
|
54809
55533
|
searchbox: ['aria-activedescendant', 'aria-autocomplete', 'aria-multiline', 'aria-placeholder', 'aria-readonly', 'aria-required'],
|
|
54810
55534
|
separator: ['aria-valuenow', 'aria-valuemin', 'aria-valuemax', 'aria-valuetext', 'aria-orientation'],
|
|
54811
55535
|
slider: ['aria-valuenow', 'aria-valuemin', 'aria-valuemax', 'aria-valuetext', 'aria-orientation', 'aria-readonly'],
|
|
54812
|
-
spinbutton: ['aria-valuenow', 'aria-valuemin', 'aria-valuemax', 'aria-valuetext', 'aria-readonly', 'aria-required'],
|
|
54813
|
-
switch: ['aria-checked'],
|
|
54814
|
-
tab: ['aria-selected'],
|
|
55536
|
+
spinbutton: ['aria-valuenow', 'aria-valuemin', 'aria-valuemax', 'aria-valuetext', 'aria-readonly', 'aria-required', 'aria-activedescendant'],
|
|
55537
|
+
switch: ['aria-checked', 'aria-expanded', 'aria-readonly', 'aria-required'],
|
|
55538
|
+
tab: ['aria-selected', 'aria-expanded', 'aria-posinset', 'aria-setsize'],
|
|
54815
55539
|
table: ['aria-colcount', 'aria-rowcount'],
|
|
54816
|
-
tablist: ['aria-multiselectable', 'aria-orientation'],
|
|
55540
|
+
tablist: ['aria-multiselectable', 'aria-orientation', 'aria-level', 'aria-activedescendant'],
|
|
54817
55541
|
textbox: ['aria-activedescendant', 'aria-autocomplete', 'aria-multiline', 'aria-placeholder', 'aria-readonly', 'aria-required'],
|
|
54818
55542
|
toolbar: ['aria-activedescendant', 'aria-orientation'],
|
|
54819
|
-
tree: ['aria-multiselectable', 'aria-
|
|
54820
|
-
treegrid: ['aria-multiselectable', 'aria-readonly', 'aria-required', 'aria-orientation', 'aria-colcount', 'aria-rowcount'],
|
|
55543
|
+
tree: ['aria-multiselectable', 'aria-required', 'aria-orientation', 'aria-activedescendant'],
|
|
55544
|
+
treegrid: ['aria-multiselectable', 'aria-readonly', 'aria-required', 'aria-orientation', 'aria-colcount', 'aria-rowcount', 'aria-activedescendant'],
|
|
54821
55545
|
treeitem: ['aria-checked', 'aria-selected', 'aria-expanded', 'aria-level', 'aria-posinset', 'aria-setsize']
|
|
54822
55546
|
};
|
|
54823
55547
|
|
|
@@ -71341,7 +72065,320 @@ const I18N = {
|
|
|
71341
72065
|
"labelInName_title": "Intitulé dans le nom : le nom accessible contient le texte visible",
|
|
71342
72066
|
"labelInName_description": "Vérifie que lorsqu’un composant possède un libellé textuel visible, le nom accessible contient ce libellé visible (WCAG 2.5.3).",
|
|
71343
72067
|
"labelInName_summary_fail": "{{element}} : le libellé visible « {{visibleLabel}} » (source : {{labelSource}}) n’est pas inclus dans le nom accessible (source : {{nameMechanism}}).",
|
|
71344
|
-
"labelInName_hint_fail": "Modifiez aria-label ou aria-labelledby (ou le texte du libellé visible) afin que le nom accessible inclue le libellé visible."
|
|
72068
|
+
"labelInName_hint_fail": "Modifiez aria-label ou aria-labelledby (ou le texte du libellé visible) afin que le nom accessible inclue le libellé visible.",
|
|
72069
|
+
"ariaRolesValid_title": "L’attribut role doit être un rôle ARIA valide et non abstrait",
|
|
72070
|
+
"ariaRolesValid_description": "Vérifie qu’un attribut role=\"\" explicite correspond à un rôle WAI-ARIA réel et non abstrait.",
|
|
72071
|
+
"ariaRolesValid_summary_invalid": "role=\"{{role}}\" n’est pas un rôle ARIA reconnu.",
|
|
72072
|
+
"ariaRolesValid_hint_invalid": "Utilisez un rôle ARIA valide, ou retirez l’attribut role si aucun ne s’applique.",
|
|
72073
|
+
"ariaRolesValid_summary_abstract": "role=\"{{role}}\" est un rôle ARIA abstrait, qui ne doit pas être utilisé directement.",
|
|
72074
|
+
"ariaRolesValid_hint_abstract": "Remplacez ce rôle abstrait par un rôle concret adapté au composant/à la structure.",
|
|
72075
|
+
"ariaDeprecatedRole_title": "L’attribut role ne doit pas utiliser un rôle ARIA obsolète ou interdit aux auteurs",
|
|
72076
|
+
"ariaDeprecatedRole_description": "Vérifie qu’un attribut role=\"\" explicite n’utilise pas un rôle rendu obsolète par la spécification WAI-ARIA, ni un rôle réservé à un usage interne à l’agent utilisateur (ex. role=\"generic\").",
|
|
72077
|
+
"ariaDeprecatedRole_summary_fail": "Cet élément utilise role=\"{{role}}\", que les auteurs ne doivent pas déclarer explicitement.",
|
|
72078
|
+
"ariaDeprecatedRole_hint_fail": "{{guidance}}",
|
|
72079
|
+
"ariaValidAttr_title": "Les attributs aria-* doivent être des attributs ARIA réels et définis",
|
|
72080
|
+
"ariaValidAttr_description": "Vérifie que chaque nom d’attribut aria-* présent dans le DOM est un attribut réel défini par la spécification WAI-ARIA.",
|
|
72081
|
+
"ariaValidAttr_summary_fail": "{{attr}} n’est pas un attribut ARIA reconnu.",
|
|
72082
|
+
"ariaValidAttr_hint_fail": "Corrigez le nom de l’attribut (vérifiez les fautes de frappe), ou retirez-le s’il n’est pas nécessaire.",
|
|
72083
|
+
"ariaValidAttrValue_title": "Les valeurs des attributs aria-* doivent correspondre à leur type déclaré",
|
|
72084
|
+
"ariaValidAttrValue_description": "Vérifie que chaque attribut aria-* reconnu a une valeur conforme à son type déclaré par WAI-ARIA (booléen, tri-état, jeton, entier, nombre ou référence d’ID).",
|
|
72085
|
+
"ariaValidAttrValue_summary_fail": "{{attr}}=\"{{value}}\" n’est pas une valeur valide pour cet attribut.",
|
|
72086
|
+
"ariaValidAttrValue_hint_fail": "Utilisez une valeur correspondant au type attendu de l’attribut (consultez la spécification WAI-ARIA pour cet attribut).",
|
|
72087
|
+
"ariaAllowedAttr_title": "Les attributs aria-* doivent être autorisés pour le rôle de l’élément",
|
|
72088
|
+
"ariaAllowedAttr_description": "Vérifie que chaque attribut aria-* reconnu présent sur un élément ayant un rôle explicite est soit globalement pris en charge, soit pris en charge par ce rôle.",
|
|
72089
|
+
"ariaAllowedAttr_summary_fail": "{{attr}} n’est pas autorisé sur role=\"{{role}}\".",
|
|
72090
|
+
"ariaAllowedAttr_hint_fail": "Retirez cet attribut, ou utilisez un rôle qui le prend en charge.",
|
|
72091
|
+
"ariaProhibitedAttr_title": "Les attributs de nommage ARIA ne doivent pas être utilisés sur des rôles qui les interdisent",
|
|
72092
|
+
"ariaProhibitedAttr_description": "Vérifie que aria-label/aria-labelledby ne sont pas présents sur des rôles WAI-ARIA dont la spécification interdit explicitement le nommage ARIA (ex. generic, emphasis, strong, paragraph).",
|
|
72093
|
+
"ariaProhibitedAttr_summary_fail": "{{attr}} est interdit sur role=\"{{role}}\".",
|
|
72094
|
+
"ariaProhibitedAttr_hint_fail": "Retirez cet attribut ; ce rôle ne doit pas porter de nom accessible.",
|
|
72095
|
+
"ariaRequiredAttr_title": "Les rôles avec un état/une propriété ARIA requis doivent le porter",
|
|
72096
|
+
"ariaRequiredAttr_description": "Vérifie que les éléments ayant un rôle explicite portent chaque état/propriété aria-* requis, non ambigu et indépendant du contexte, pour ce rôle (ex. role=\"checkbox\" doit avoir aria-checked).",
|
|
72097
|
+
"ariaRequiredAttr_summary_fail": "{{attr}} est requis pour role=\"{{role}}\", mais est absent.",
|
|
72098
|
+
"ariaRequiredAttr_hint_fail": "Ajoutez cet attribut avec une valeur valide pour ce rôle.",
|
|
72099
|
+
"ariaAllowedRole_title": "Le rôle explicite doit être autorisé pour son élément hôte",
|
|
72100
|
+
"ariaAllowedRole_description": "Vérifie qu’un attribut role=\"\" explicite fait partie des rôles que la spécification ARIA-in-HTML autorise pour l’élément hôte (ex. role=\"tab\" n’est pas autorisé sur <nav>).",
|
|
72101
|
+
"ariaAllowedRole_summary_fail": "role=\"{{role}}\" n’est pas autorisé sur <{{element}}>.",
|
|
72102
|
+
"ariaAllowedRole_hint_fail": "Utilisez un rôle autorisé pour cet élément, ou changez l’élément hôte.",
|
|
72103
|
+
"ariaRequiredChildren_title": "Les rôles conteneurs doivent posséder au moins un rôle enfant requis",
|
|
72104
|
+
"ariaRequiredChildren_description": "Vérifie que les rôles conteneurs disposant d’une entrée documentée « éléments possédés requis » (list, listbox, menu, radiogroup, table, grid, tablist, tree, row, ...) contiennent au moins un descendant, ou un élément référencé par aria-owns, ayant un rôle possédé acceptable.",
|
|
72105
|
+
"ariaRequiredChildren_summary_fail": "role=\"{{role}}\" ne possède aucun enfant ayant l’un des rôles requis : {{requiredRoles}}.",
|
|
72106
|
+
"ariaRequiredChildren_hint_fail": "Ajoutez un descendant (ou un élément référencé par aria-owns) ayant l’un des rôles possédés requis.",
|
|
72107
|
+
"ariaProhibitedChildren_title": "Les rôles conteneurs ne doivent pas posséder d’enfant ayant un rôle interdit",
|
|
72108
|
+
"ariaProhibitedChildren_description": "Vérifie que chaque enfant possédé (dans l’arbre d’accessibilité) d’un rôle conteneur (list, listbox, menu, menubar, radiogroup, rowgroup, table, grid, treegrid, tablist, tree, row) a l’un des rôles possédés autorisés par ce rôle.",
|
|
72109
|
+
"ariaProhibitedChildren_summary_fail": "Cet élément a le rôle role=\"{{childRole}}\", qui n’est pas un rôle enfant possédé autorisé par le conteneur englobant role=\"{{containerRole}}\".",
|
|
72110
|
+
"ariaProhibitedChildren_hint_fail": "Retirez ou modifiez ce rôle afin qu’il corresponde à l’un des rôles possédés autorisés du conteneur ({{allowedRoles}}), ou déplacez cet élément hors du conteneur {{containerRole}}.",
|
|
72111
|
+
"ariaProhibitedChildren_summary_fail_roleless": "Cet élément n’a pas de rôle explicite mais porte {{attr}}, ce qui en fait un véritable nœud de l’arbre d’accessibilité qui n’est pas un enfant possédé autorisé du conteneur englobant role=\"{{containerRole}}\".",
|
|
72112
|
+
"ariaProhibitedChildren_hint_fail_roleless": "Retirez {{attr}} (ou la relation de possession avec le conteneur role=\"{{containerRole}}\"), ou attribuez à cet élément role=\"presentation\"/\"none\" s’il n’est pas censé constituer son propre nœud dans l’arbre d’accessibilité.",
|
|
72113
|
+
"ariaRequiredParent_title": "Les rôles exigeant un rôle de contexte spécifique doivent se trouver dans ce contexte",
|
|
72114
|
+
"ariaRequiredParent_description": "Vérifie que les rôles disposant d’une entrée documentée « rôle de contexte requis » (listitem, option, tab, treeitem, row, cell, ...) ont un ancêtre, ou un propriétaire aria-owns, ayant un rôle de contexte acceptable.",
|
|
72115
|
+
"ariaRequiredParent_summary_fail": "role=\"{{role}}\" exige un rôle de contexte parmi : {{requiredRoles}}, qui n’a pas été trouvé.",
|
|
72116
|
+
"ariaRequiredParent_hint_fail": "Placez cet élément à l’intérieur d’un élément ayant un rôle de contexte acceptable (ou référencez-le depuis celui-ci via aria-owns).",
|
|
72117
|
+
"deprecatedElements_title": "Les éléments obsolètes non interruptibles (<blink>, <marquee>) ne doivent pas être utilisés",
|
|
72118
|
+
"deprecatedElements_description": "Vérifie que les éléments HTML obsolètes et non standards dont le contenu clignotant/défilant ne peut pas être mis en pause, arrêté ou masqué par l’utilisateur (<blink>, <marquee>) ne sont pas présents.",
|
|
72119
|
+
"deprecatedElements_summary_fail": "Le contenu de <{{element}}> ne peut pas être mis en pause, arrêté ou masqué par l’utilisateur.",
|
|
72120
|
+
"deprecatedElements_hint_fail": "Retirez cet élément ; utilisez à la place un contenu statique, ou une animation dotée d’un contrôle de pause/arrêt accessible à l’utilisateur.",
|
|
72121
|
+
"iframeNamePresent_title": "Les cadres ont un nom accessible",
|
|
72122
|
+
"iframeNamePresent_description": "Vérifie que les éléments <iframe>/<frame> exposent un nom accessible non vide via aria-label, aria-labelledby, ou l’attribut title.",
|
|
72123
|
+
"iframeNamePresent_summary_fail": "Ce <{{element}}> n’a pas de nom accessible.",
|
|
72124
|
+
"iframeNamePresent_hint_fail": "Ajoutez un attribut title (ou aria-label/aria-labelledby) décrivant le contenu ou l’objet du cadre.",
|
|
72125
|
+
"iframeTitleUnique_title": "Les titres de cadres doivent être uniques",
|
|
72126
|
+
"iframeTitleUnique_description": "Vérifie qu’aucun <iframe>/<frame> dans le périmètre analysé ne partage la même valeur d’attribut title qu’un autre.",
|
|
72127
|
+
"iframeTitleUnique_summary_fail": "Le titre « {{title}} » de ce <{{element}}> n’est pas unique parmi les cadres de cette page.",
|
|
72128
|
+
"iframeTitleUnique_hint_fail": "Donnez à chaque cadre un titre distinct décrivant son contenu ou son objet spécifique.",
|
|
72129
|
+
"iframeFocusableContent_title": "Les cadres avec tabindex=\"-1\" ne doivent pas contenir de contenu focalisable",
|
|
72130
|
+
"iframeFocusableContent_description": "Vérifie que les éléments <iframe>/<frame> de même origine avec tabindex=\"-1\" ne contiennent pas de contenu focalisable, car les navigateurs ne propagent pas cette restriction au document intégré du cadre.",
|
|
72131
|
+
"iframeFocusableContent_summary_fail": "Ce <{{element}}> a tabindex=\"-1\" mais son contenu contient des éléments focalisables, qui restent accessibles au clavier.",
|
|
72132
|
+
"iframeFocusableContent_hint_fail": "Retirez le contenu focalisable du cadre, ou retirez tabindex=\"-1\" si le cadre est censé être accessible.",
|
|
72133
|
+
"tableHeadersAttrValid_title": "L’attribut headers d’une cellule de tableau doit référencer des cellules d’en-tête valides",
|
|
72134
|
+
"tableHeadersAttrValid_description": "Vérifie que chaque id de l’attribut headers d’un <td>/<th> correspond à un élément <th> du même tableau (ni absent, ni un élément autre que th, ni lui-même).",
|
|
72135
|
+
"tableHeadersAttrValid_summary_fail": "L’attribut headers de ce <{{element}}> référence des cellules d’en-tête invalides : {{invalidIds}}.",
|
|
72136
|
+
"tableHeadersAttrValid_hint_fail": "Mettez à jour l’attribut headers afin que chaque id désigne un élément <th> du même tableau.",
|
|
72137
|
+
"tableThHasDataCells_title": "Les éléments <th> doivent décrire au moins une cellule de données",
|
|
72138
|
+
"tableThHasDataCells_description": "Vérifie qu’un tableau contenant des éléments <th> contient aussi au moins une cellule de données <td> que ces en-têtes décrivent.",
|
|
72139
|
+
"tableThHasDataCells_summary_fail": "Ce tableau a des cellules d’en-tête mais aucune cellule de données à décrire.",
|
|
72140
|
+
"tableThHasDataCells_hint_fail": "Ajoutez des cellules de données (<td>) au tableau, ou retirez les cellules d’en-tête si le tableau n’a pas de données.",
|
|
72141
|
+
"ariaHiddenBody_title": "Le <body> du document ne doit pas être aria-hidden",
|
|
72142
|
+
"ariaHiddenBody_description": "Vérifie que <body> n’a pas aria-hidden=\"true\", ce qui retirerait toute la page de l’arbre d’accessibilité.",
|
|
72143
|
+
"ariaHiddenBody_summary_fail": "Le corps du document a aria-hidden=\"true\", ce qui masque toute la page aux technologies d’assistance.",
|
|
72144
|
+
"ariaHiddenBody_hint_fail": "Retirez aria-hidden de <body>. Masquez des éléments spécifiques à la place, si c’était l’intention.",
|
|
72145
|
+
"listChildrenValid_title": "Les listes ne doivent contenir directement que des éléments de liste",
|
|
72146
|
+
"listChildrenValid_description": "Vérifie que les éléments <ul>/<ol> n’ont comme enfants directs que <li>, <script> ou <template>.",
|
|
72147
|
+
"listChildrenValid_summary_fail": "Ce <{{element}}> contient un enfant direct qui n’est pas un élément de liste : {{invalidChildren}}.",
|
|
72148
|
+
"listChildrenValid_hint_fail": "N’utilisez que <li> (ou <script>/<template>) comme enfants directs de <ul>/<ol> ; déplacez tout autre balisage à l’intérieur d’un <li>.",
|
|
72149
|
+
"listitemParentValid_title": "Les éléments de liste doivent se trouver à l’intérieur d’un conteneur de liste",
|
|
72150
|
+
"listitemParentValid_description": "Vérifie que les éléments <li> sont contenus par <ul>, <ol>, ou un élément ayant role=\"list\".",
|
|
72151
|
+
"listitemParentValid_summary_fail": "Le parent de cet élément de liste (<{{parentElement}}>) n’est pas un conteneur de liste.",
|
|
72152
|
+
"listitemParentValid_hint_fail": "Placez ce <li> à l’intérieur d’un <ul>/<ol>, ou donnez à son parent role=\"list\".",
|
|
72153
|
+
"definitionListChildrenValid_title": "Les listes de définitions doivent être structurées correctement",
|
|
72154
|
+
"definitionListChildrenValid_description": "Vérifie que les éléments <dl> ne contiennent directement que des groupes <dt>/<dd> (éventuellement enveloppés dans un seul <div>), <script>, <template>, ou <style>.",
|
|
72155
|
+
"definitionListChildrenValid_summary_fail_invalidChild": "Cette liste de définitions contient un enfant direct ou enveloppé qui ne fait pas partie d’un groupe dt/dd : {{invalidChildren}}.",
|
|
72156
|
+
"definitionListChildrenValid_hint_fail_invalidChild": "N’utilisez que <dt>/<dd> (éventuellement enveloppés dans un seul <div>), <script>, <template>, ou <style> à l’intérieur de <dl>.",
|
|
72157
|
+
"definitionListChildrenValid_summary_fail_noDtDd": "Cette liste de définitions n’a aucun groupe terme/définition <dt>/<dd>.",
|
|
72158
|
+
"definitionListChildrenValid_hint_fail_noDtDd": "Ajoutez au moins une paire <dt>/<dd> à l’intérieur de ce <dl>.",
|
|
72159
|
+
"dlitemParentValid_title": "Les éléments d’une liste de définitions doivent se trouver à l’intérieur d’une liste de définitions",
|
|
72160
|
+
"dlitemParentValid_description": "Vérifie que les éléments <dt>/<dd> sont contenus par un <dl>, directement ou via un <div> englobant.",
|
|
72161
|
+
"dlitemParentValid_summary_fail": "Le parent (<{{parentElement}}>) de ce <{{element}}> n’est pas une liste de définitions.",
|
|
72162
|
+
"dlitemParentValid_hint_fail": "Placez ce <dt>/<dd> à l’intérieur d’un <dl>, directement ou enveloppé dans un seul <div>.",
|
|
72163
|
+
"duplicateIdAria_title": "Les ID référencés par ARIA doivent être uniques",
|
|
72164
|
+
"duplicateIdAria_description": "Vérifie que toute valeur id référencée par un attribut de référence d’ID ARIA (aria-labelledby, aria-describedby, aria-owns, aria-controls, aria-activedescendant, aria-flowto, aria-errormessage, aria-details) est unique dans le document.",
|
|
72165
|
+
"duplicateIdAria_summary_fail": "L’id « {{id}} » est référencé par un attribut ARIA mais est utilisé par {{duplicateCount}} éléments.",
|
|
72166
|
+
"duplicateIdAria_hint_fail": "Rendez uniques dans le document les id référencés par des attributs ARIA.",
|
|
72167
|
+
"summaryNamePresent_title": "Les éléments summary ont un nom accessible",
|
|
72168
|
+
"summaryNamePresent_description": "Vérifie que les éléments <summary> exposent un nom accessible non vide.",
|
|
72169
|
+
"summaryNamePresent_summary_fail": "Ce summary n’a pas de nom accessible.",
|
|
72170
|
+
"summaryNamePresent_hint_fail": "Fournissez un texte de summary qui ne soit pas masqué aux technologies d’assistance, ou fournissez aria-label ou aria-labelledby.",
|
|
72171
|
+
"metaViewportZoomEnabled_title": "La balise meta viewport ne doit pas désactiver le zoom",
|
|
72172
|
+
"metaViewportZoomEnabled_description": "Vérifie que <meta name=\"viewport\"> ne définit pas user-scalable=no ni maximum-scale en dessous de 2 (200 %).",
|
|
72173
|
+
"metaViewportZoomEnabled_summary_fail": "Cette balise meta viewport restreint la capacité de l’utilisateur à zoomer ({{reasons}}).",
|
|
72174
|
+
"metaViewportZoomEnabled_hint_fail": "Retirez user-scalable=no et tout maximum-scale inférieur à 2 du contenu de la balise meta viewport.",
|
|
72175
|
+
"metaRefreshTimingAbsent_title": "La page ne doit pas utiliser un rafraîchissement meta minuté",
|
|
72176
|
+
"metaRefreshTimingAbsent_description": "Vérifie que <meta http-equiv=\"refresh\"> n’impose pas un délai positif de 20 heures ou moins.",
|
|
72177
|
+
"metaRefreshTimingAbsent_summary_fail": "Cette page se rafraîchit automatiquement après {{delay}} secondes.",
|
|
72178
|
+
"metaRefreshTimingAbsent_hint_fail": "Retirez le rafraîchissement meta minuté, ou proposez un moyen pour les utilisateurs de le désactiver, de le prolonger ou de le mettre en pause avant qu’il ne se déclenche.",
|
|
72179
|
+
"meterNamePresent_title": "Les éléments meter ont un nom accessible",
|
|
72180
|
+
"meterNamePresent_description": "Vérifie que les éléments avec role=\"meter\" exposent un nom accessible non vide.",
|
|
72181
|
+
"meterNamePresent_summary_fail": "Ce meter n’a pas de nom accessible.",
|
|
72182
|
+
"meterNamePresent_hint_fail": "Fournissez un texte pour le meter qui ne soit pas masqué aux technologies d’assistance, ou fournissez aria-label ou aria-labelledby.",
|
|
72183
|
+
"progressbarNamePresent_title": "Les barres de progression ont un nom accessible",
|
|
72184
|
+
"progressbarNamePresent_description": "Vérifie que les éléments avec role=\"progressbar\" exposent un nom accessible non vide.",
|
|
72185
|
+
"progressbarNamePresent_summary_fail": "Cette barre de progression n’a pas de nom accessible.",
|
|
72186
|
+
"progressbarNamePresent_hint_fail": "Fournissez un texte pour la barre de progression qui ne soit pas masqué aux technologies d’assistance, ou fournissez aria-label ou aria-labelledby.",
|
|
72187
|
+
"tooltipNamePresent_title": "Les infobulles ont un nom accessible",
|
|
72188
|
+
"tooltipNamePresent_description": "Vérifie que les éléments avec role=\"tooltip\" exposent un nom accessible non vide.",
|
|
72189
|
+
"tooltipNamePresent_summary_fail": "Cette infobulle n’a pas de nom accessible.",
|
|
72190
|
+
"tooltipNamePresent_hint_fail": "Fournissez un texte pour l’infobulle qui ne soit pas masqué aux technologies d’assistance, ou fournissez aria-label ou aria-labelledby.",
|
|
72191
|
+
"serverSideImageMapAbsent_title": "Les images ne doivent pas utiliser une carte d’image côté serveur",
|
|
72192
|
+
"serverSideImageMapAbsent_description": "Vérifie que les éléments <img> ne portent pas l’attribut ismap (les cartes d’image côté serveur n’ont pas d’équivalent utilisable au clavier).",
|
|
72193
|
+
"serverSideImageMapAbsent_summary_fail": "Cette image utilise une carte d’image côté serveur, qui n’a pas d’équivalent utilisable au clavier.",
|
|
72194
|
+
"serverSideImageMapAbsent_hint_fail": "Remplacez la carte d’image côté serveur (ismap) par une carte d’image côté client (<map>/<area>) ou par des liens/boutons accessibles distincts.",
|
|
72195
|
+
"formControlSingleLabel_title": "Les contrôles de formulaire ne doivent pas avoir plusieurs étiquettes",
|
|
72196
|
+
"formControlSingleLabel_description": "Vérifie qu’un contrôle de formulaire est associé à au plus un <label> (par imbrication ou par label[for]).",
|
|
72197
|
+
"formControlSingleLabel_summary_fail": "Ce <{{element}}> est associé à {{labelCount}} étiquettes.",
|
|
72198
|
+
"formControlSingleLabel_hint_fail": "Conservez une seule <label> par contrôle de formulaire (soit en l’enveloppant, soit en la référençant via for/id).",
|
|
72199
|
+
"nestedInteractiveControlsAbsent_title": "Les contrôles interactifs ne doivent pas être imbriqués",
|
|
72200
|
+
"nestedInteractiveControlsAbsent_description": "Vérifie qu’un contrôle interactif (lien, bouton, contrôle de formulaire, ou rôle de widget ARIA) ne contient pas un autre contrôle interactif.",
|
|
72201
|
+
"nestedInteractiveControlsAbsent_summary_fail": "Ce <{{element}}> contient un ou plusieurs contrôles interactifs imbriqués : {{nestedElements}}.",
|
|
72202
|
+
"nestedInteractiveControlsAbsent_hint_fail": "Déplacez le(s) contrôle(s) interactif(s) imbriqué(s) hors de cet élément ; les contrôles interactifs imbriqués ne sont pas utilisables de façon fiable via les technologies d’assistance.",
|
|
72203
|
+
"bypassBlocksPresent_title": "La page doit proposer un moyen de contourner les blocs répétés",
|
|
72204
|
+
"bypassBlocksPresent_description": "Vérifie que la page dispose d’au moins un mécanisme reconnu de contournement des blocs répétés (WCAG 2.4.1) : un point de repère main, un lien d’ancrage fonctionnel vers la même page, ou un titre.",
|
|
72205
|
+
"bypassBlocksPresent_summary_fail": "Cette page n’a aucun moyen reconnu de contourner les blocs de contenu répétés.",
|
|
72206
|
+
"bypassBlocksPresent_hint_fail": "Ajoutez un point de repère main (<main> ou role=\"main\"), un lien « aller au contenu » fonctionnel, ou des éléments de titre que les technologies d’assistance peuvent utiliser pour passer le contenu répété.",
|
|
72207
|
+
"landmarkBannerIsTopLevel_title": "Le point de repère banner doit être de premier niveau",
|
|
72208
|
+
"landmarkBannerIsTopLevel_description": "Vérifie que le point de repère banner (role=\"banner\" ou un <header> non imbriqué) n’est pas imbriqué dans un autre point de repère.",
|
|
72209
|
+
"landmarkBannerIsTopLevel_summary_cantTell": "Ce point de repère banner est imbriqué dans un autre point de repère.",
|
|
72210
|
+
"landmarkBannerIsTopLevel_hint_cantTell": "Déplacez le point de repère banner (header/role=\"banner\") afin qu’il ne soit contenu par aucun autre point de repère ; un banner doit être une région de premier niveau de la page.",
|
|
72211
|
+
"landmarkContentinfoIsTopLevel_title": "Le point de repère contentinfo doit être de premier niveau",
|
|
72212
|
+
"landmarkContentinfoIsTopLevel_description": "Vérifie que le point de repère contentinfo (role=\"contentinfo\" ou un <footer> non imbriqué) n’est pas imbriqué dans un autre point de repère.",
|
|
72213
|
+
"landmarkContentinfoIsTopLevel_summary_cantTell": "Ce point de repère contentinfo est imbriqué dans un autre point de repère.",
|
|
72214
|
+
"landmarkContentinfoIsTopLevel_hint_cantTell": "Déplacez le point de repère contentinfo (footer/role=\"contentinfo\") afin qu’il ne soit contenu par aucun autre point de repère ; contentinfo doit être une région de premier niveau de la page.",
|
|
72215
|
+
"landmarkMainIsTopLevel_title": "Le point de repère main doit être de premier niveau",
|
|
72216
|
+
"landmarkMainIsTopLevel_description": "Vérifie que le point de repère main (role=\"main\" ou <main>) n’est pas imbriqué dans un autre point de repère.",
|
|
72217
|
+
"landmarkMainIsTopLevel_summary_cantTell": "Ce point de repère main est imbriqué dans un autre point de repère.",
|
|
72218
|
+
"landmarkMainIsTopLevel_hint_cantTell": "Déplacez le point de repère main (<main>/role=\"main\") afin qu’il ne soit contenu par aucun autre point de repère ; main doit être une région de premier niveau de la page.",
|
|
72219
|
+
"landmarkNoDuplicateBanner_title": "La page ne doit pas avoir plus d’un point de repère banner",
|
|
72220
|
+
"landmarkNoDuplicateBanner_description": "Vérifie qu’au plus un point de repère banner (role=\"banner\" ou un <header> non imbriqué) existe sur la page.",
|
|
72221
|
+
"landmarkNoDuplicateBanner_summary_cantTell": "Cette page a plus d’un point de repère banner.",
|
|
72222
|
+
"landmarkNoDuplicateBanner_hint_cantTell": "Ne conservez qu’un seul point de repère banner (header/role=\"banner\") par page.",
|
|
72223
|
+
"landmarkNoDuplicateContentinfo_title": "La page ne doit pas avoir plus d’un point de repère contentinfo",
|
|
72224
|
+
"landmarkNoDuplicateContentinfo_description": "Vérifie qu’au plus un point de repère contentinfo (role=\"contentinfo\" ou un <footer> non imbriqué) existe sur la page.",
|
|
72225
|
+
"landmarkNoDuplicateContentinfo_summary_cantTell": "Cette page a plus d’un point de repère contentinfo.",
|
|
72226
|
+
"landmarkNoDuplicateContentinfo_hint_cantTell": "Ne conservez qu’un seul point de repère contentinfo (footer/role=\"contentinfo\") par page.",
|
|
72227
|
+
"landmarkNoDuplicateMain_title": "La page ne doit pas avoir plus d’un point de repère main",
|
|
72228
|
+
"landmarkNoDuplicateMain_description": "Vérifie qu’au plus un point de repère main (role=\"main\" ou <main>) existe sur la page.",
|
|
72229
|
+
"landmarkNoDuplicateMain_summary_cantTell": "Cette page a plus d’un point de repère main.",
|
|
72230
|
+
"landmarkNoDuplicateMain_hint_cantTell": "Ne conservez qu’un seul point de repère main (<main>/role=\"main\") par page.",
|
|
72231
|
+
"landmarkOneMain_title": "La page devrait avoir un point de repère main",
|
|
72232
|
+
"landmarkOneMain_description": "Vérifie que la page a au moins un point de repère main (role=\"main\" ou <main>).",
|
|
72233
|
+
"landmarkOneMain_summary_cantTell_missing": "Cette page n’a aucun point de repère main.",
|
|
72234
|
+
"landmarkOneMain_hint_cantTell_missing": "Ajoutez un point de repère main (<main> ou role=\"main\") autour du contenu principal de la page.",
|
|
72235
|
+
"landmarkUnique_title": "Les points de repère partageant le même rôle doivent avoir des noms uniques",
|
|
72236
|
+
"landmarkUnique_description": "Vérifie que lorsque deux points de repère ou plus partagent le même rôle, chacun a un nom accessible distinct.",
|
|
72237
|
+
"landmarkUnique_summary_cantTell_duplicateName": "Ce point de repère {{role}} partage son nom accessible avec un autre point de repère {{role}}.",
|
|
72238
|
+
"landmarkUnique_summary_cantTell_bothUnnamed": "Ce point de repère {{role}} n’a pas de nom accessible, et plus d’un point de repère {{role}} sans nom existe sur cette page.",
|
|
72239
|
+
"landmarkUnique_hint_cantTell": "Donnez à chaque point de repère {{role}} un nom distinct via aria-label ou aria-labelledby.",
|
|
72240
|
+
"emptyHeading_title": "Les titres ne doivent pas être vides",
|
|
72241
|
+
"emptyHeading_description": "Vérifie que les éléments de titre (<h1>-<h6> ou role=\"heading\") ont un nom accessible non vide.",
|
|
72242
|
+
"emptyHeading_summary_cantTell": "Ce titre n’a pas de nom accessible.",
|
|
72243
|
+
"emptyHeading_hint_cantTell": "Ajoutez du contenu textuel (ou aria-label/aria-labelledby) à ce titre, ou retirez-le s’il n’est pas nécessaire.",
|
|
72244
|
+
"headingOrder_title": "Les niveaux de titre ne doivent pas sauter un niveau",
|
|
72245
|
+
"headingOrder_description": "Vérifie que les niveaux de titre n’augmentent que d’un niveau à la fois, dans l’ordre du document.",
|
|
72246
|
+
"headingOrder_summary_cantTell": "Ce titre passe du niveau {{fromLevel}} au niveau {{toLevel}}, en sautant un niveau.",
|
|
72247
|
+
"headingOrder_hint_cantTell": "Utilisez des niveaux de titre consécutifs (ne sautez pas de niveau en descendant dans la hiérarchie) afin que le plan du document reste prévisible.",
|
|
72248
|
+
"pageHasHeadingOne_title": "La page devrait avoir un titre de niveau un",
|
|
72249
|
+
"pageHasHeadingOne_description": "Vérifie que la page a au moins un titre de niveau un (<h1> ou role=\"heading\" avec aria-level=\"1\").",
|
|
72250
|
+
"pageHasHeadingOne_summary_cantTell": "Cette page n’a aucun titre de niveau un.",
|
|
72251
|
+
"pageHasHeadingOne_hint_cantTell": "Ajoutez un titre de niveau un (<h1> ou role=\"heading\" aria-level=\"1\") identifiant le contenu principal de la page.",
|
|
72252
|
+
"accesskeys_title": "Les valeurs accesskey doivent être uniques",
|
|
72253
|
+
"accesskeys_description": "Vérifie qu’aucun élément de la page ne partage la même valeur d’attribut accesskey qu’un autre.",
|
|
72254
|
+
"accesskeys_summary_cantTell": "L’accesskey de cet élément est partagée avec un autre élément de la page.",
|
|
72255
|
+
"accesskeys_hint_cantTell": "Rendez chaque valeur accesskey unique sur l’ensemble de la page.",
|
|
72256
|
+
"scopeAttrValid_title": "L’attribut scope doit avoir une valeur valide",
|
|
72257
|
+
"scopeAttrValid_description": "Vérifie que scope=\"...\" vaut row, col, rowgroup, ou colgroup.",
|
|
72258
|
+
"scopeAttrValid_summary_cantTell": "Cette valeur d’attribut scope n’est pas reconnue.",
|
|
72259
|
+
"scopeAttrValid_hint_cantTell": "Utilisez row, col, rowgroup, ou colgroup pour l’attribut scope.",
|
|
72260
|
+
"tabindex_title": "tabindex ne devrait pas être supérieur à 0",
|
|
72261
|
+
"tabindex_description": "Vérifie que les valeurs de tabindex sont égales à 0 ou négatives, jamais un nombre positif.",
|
|
72262
|
+
"tabindex_summary_cantTell": "Cet élément a un tabindex positif, ce qui modifie l’ordre naturel de tabulation.",
|
|
72263
|
+
"tabindex_hint_cantTell": "Utilisez tabindex=\"0\" (ou une valeur négative pour le retirer de l’ordre de tabulation) plutôt qu’un nombre positif ; corrigez l’ordre dans le DOM si un ordre de tabulation différent est nécessaire.",
|
|
72264
|
+
"emptyTableHeader_title": "Les cellules d’en-tête de tableau ne doivent pas être vides",
|
|
72265
|
+
"emptyTableHeader_description": "Vérifie que les éléments <th> ont un contenu textuel visible — un en-tête nommé uniquement via aria-label/aria-labelledby est aussi signalé, car la prise en charge réelle par les lecteurs d’écran/navigateurs est incohérente.",
|
|
72266
|
+
"emptyTableHeader_summary_cantTell": "Cette cellule d’en-tête de tableau n’a pas de nom accessible.",
|
|
72267
|
+
"emptyTableHeader_hint_cantTell": "Ajoutez du contenu textuel (ou aria-label/aria-labelledby) à cette cellule d’en-tête, ou retirez-la si elle n’est pas nécessaire.",
|
|
72268
|
+
"emptyTableHeader_summary_cantTell_ariaOnly": "Cette cellule d’en-tête de tableau n’a pas de texte visible — son seul nom accessible provient de aria-label/aria-labelledby, que des combinaisons réelles de lecteur d’écran/navigateur (ex. NVDA+Firefox, iOS VoiceOver+Safari) sont connues pour ignorer sur les éléments <th>.",
|
|
72269
|
+
"emptyTableHeader_hint_cantTell_ariaOnly": "Ajoutez du contenu textuel visible à cette cellule d’en-tête (en plus de, ou à la place de, aria-label/aria-labelledby) — le texte visible est le seul mécanisme de nommage confirmé comme fonctionnel sur les lecteurs d’écran testés.",
|
|
72270
|
+
"labelTitleOnly_title": "Les contrôles de formulaire ne devraient pas utiliser title comme seule étiquette",
|
|
72271
|
+
"labelTitleOnly_description": "Vérifie qu’un contrôle de formulaire ayant un attribut title possède aussi une véritable étiquette (élément label, aria-label, ou aria-labelledby).",
|
|
72272
|
+
"labelTitleOnly_summary_cantTell": "Ce contrôle de formulaire repose sur l’attribut title comme seule étiquette.",
|
|
72273
|
+
"labelTitleOnly_hint_cantTell": "Ajoutez une <label> visible (ou aria-label/aria-labelledby) en plus de, ou à la place de, l’attribut title.",
|
|
72274
|
+
"imageRedundantAlt_title": "Le texte alt d’une image ne doit pas dupliquer le texte visible adjacent",
|
|
72275
|
+
"imageRedundantAlt_description": "Vérifie que le texte alt d’un <img> n’est pas identique à un autre texte visible déjà présent dans son élément parent immédiat.",
|
|
72276
|
+
"imageRedundantAlt_summary_cantTell": "Le texte alt de cette image duplique un autre texte visible juste à côté.",
|
|
72277
|
+
"imageRedundantAlt_hint_cantTell": "Videz le texte alt (alt=\"\") si l’image est purement décorative à côté du texte, ou supprimez la duplication redondante.",
|
|
72278
|
+
"tableDuplicateName_title": "La légende d’un tableau ne doit pas dupliquer son attribut summary",
|
|
72279
|
+
"tableDuplicateName_description": "Vérifie que le texte de la <caption> d’un <table> n’est pas identique à son attribut summary (obsolète).",
|
|
72280
|
+
"tableDuplicateName_summary_cantTell": "La légende de ce tableau duplique son attribut summary.",
|
|
72281
|
+
"tableDuplicateName_hint_cantTell": "Retirez l’attribut summary redondant, ou faites en sorte qu’il apporte une information différente de la légende.",
|
|
72282
|
+
"metaViewportLarge_title": "La balise meta viewport devrait permettre un zoom jusqu’à 500 %",
|
|
72283
|
+
"metaViewportLarge_description": "Vérifie que <meta name=\"viewport\"> ne définit pas user-scalable=no ni maximum-scale en dessous de 5 (500 %).",
|
|
72284
|
+
"metaViewportLarge_summary_cantTell": "Cette balise meta viewport restreint le zoom en dessous de l’objectif de bonne pratique de 500 %.",
|
|
72285
|
+
"metaViewportLarge_hint_cantTell": "Retirez user-scalable=no et augmentez maximum-scale à au moins 5 (500 %) si possible.",
|
|
72286
|
+
"presentationRoleConflict_title": "Un rôle de présentation ne doit pas entrer en conflit avec un attribut ARIA global ou la focalisabilité",
|
|
72287
|
+
"presentationRoleConflict_description": "Vérifie que role=\"presentation\"/\"none\" (y compris le rôle presentation implicite d’un <img alt=\"\">) n’est pas combiné avec un attribut ARIA global (aria-label, aria-hidden, aria-describedby, ...) ou avec la focalisabilité (tabindex/native).",
|
|
72288
|
+
"presentationRoleConflict_summary_cantTell": "Cet élément role=\"{{role}}\" a aussi une condition conflictuelle ({{attrs}}), qui restaure son rôle implicite et annule l’intention présentationnelle.",
|
|
72289
|
+
"presentationRoleConflict_hint_cantTell": "Retirez le(s) attribut(s) de nommage conflictuel(s) et/ou la focalisabilité (tabindex/native) si l’élément doit rester présentationnel, ou retirez role=\"presentation\"/\"none\" s’il doit être exposé aux technologies d’assistance.",
|
|
72290
|
+
"region_title": "Le contenu de la page devrait se trouver à l’intérieur d’un point de repère",
|
|
72291
|
+
"region_description": "Vérifie que les enfants directs de <body> ayant un contenu textuel visible sont contenus dans un point de repère.",
|
|
72292
|
+
"region_summary_cantTell": "Ce contenu n’est contenu dans aucun point de repère.",
|
|
72293
|
+
"region_hint_cantTell": "Déplacez ce contenu à l’intérieur d’un point de repère (main, nav, aside, une section nommée, etc.).",
|
|
72294
|
+
"skipLink_title": "Un lien d’évitement doit avoir une cible qui se résout",
|
|
72295
|
+
"skipLink_description": "Vérifie que le fragment href d’un lien « aller au... » se résout vers un élément réel du document.",
|
|
72296
|
+
"skipLink_summary_cantTell": "La cible de ce lien d’évitement n’existe pas.",
|
|
72297
|
+
"skipLink_hint_cantTell": "Faites pointer le href du lien d’évitement vers un id qui existe dans le document, ou ajoutez l’élément cible manquant.",
|
|
72298
|
+
"autocompleteValid_title": "L’attribut autocomplete doit être une valeur d’auto-remplissage valide",
|
|
72299
|
+
"autocompleteValid_description": "Vérifie qu’un attribut autocomplete non vide vaut « on »/« off » ou une liste de jetons d’auto-remplissage bien formée.",
|
|
72300
|
+
"autocompleteValid_summary_fail": "Cette valeur d’attribut autocomplete n’est pas une valeur d’auto-remplissage valide.",
|
|
72301
|
+
"autocompleteValid_hint_fail": "Utilisez « on »/« off », ou une liste de jetons d’auto-remplissage valide (ex. « shipping street-address », « cc-number »).",
|
|
72302
|
+
"htmlXmlLangMismatch_title": "lang et xml:lang ne doivent pas se contredire",
|
|
72303
|
+
"htmlXmlLangMismatch_description": "Vérifie que les attributs lang et xml:lang de l’élément <html> déclarent la même langue principale, lorsque les deux sont présents.",
|
|
72304
|
+
"htmlXmlLangMismatch_summary_fail": "Les attributs lang (« {{lang}} ») et xml:lang (« {{xmlLang}} ») déclarent des langues différentes.",
|
|
72305
|
+
"htmlXmlLangMismatch_hint_fail": "Faites en sorte que lang et xml:lang déclarent la même langue principale, ou retirez l’attribut obsolète xml:lang.",
|
|
72306
|
+
"avoidInlineSpacing_title": "Un style en ligne ne doit pas forcer l’espacement du texte avec !important",
|
|
72307
|
+
"avoidInlineSpacing_description": "Vérifie qu’un style en ligne ne définit pas line-height, letter-spacing, ou word-spacing avec !important, ce qui bloque les surcharges d’espacement de texte par l’utilisateur.",
|
|
72308
|
+
"avoidInlineSpacing_summary_fail": "Le style en ligne de cet élément force {{properties}} avec !important, bloquant les surcharges d’espacement de texte par l’utilisateur.",
|
|
72309
|
+
"avoidInlineSpacing_hint_fail": "Retirez !important de line-height/letter-spacing/word-spacing dans les styles en ligne afin que les utilisateurs puissent surcharger l’espacement du texte.",
|
|
72310
|
+
"metaRefreshNoExceptions_title": "La page ne doit utiliser aucun rafraîchissement meta (AAA)",
|
|
72311
|
+
"metaRefreshNoExceptions_description": "Vérifie que <meta http-equiv=\"refresh\"> n’est présent en aucun cas, quel que soit le délai — la variante plus stricte, de niveau AAA, de la vérification de niveau A qui ne porte que sur les délais positifs.",
|
|
72312
|
+
"metaRefreshNoExceptions_summary_fail": "Cette page utilise un rafraîchissement meta, un changement de contexte automatique non initié par l’utilisateur.",
|
|
72313
|
+
"metaRefreshNoExceptions_hint_fail": "Retirez le rafraîchissement meta ; déclenchez la redirection/le rafraîchissement uniquement en réponse à une action de l’utilisateur.",
|
|
72314
|
+
"validLang_title": "L’attribut lang d’un élément doit être syntaxiquement valide",
|
|
72315
|
+
"validLang_description": "Vérifie que tout élément (autre que la racine <html>) ayant un attribut lang non vide utilise une étiquette de langue syntaxiquement valide.",
|
|
72316
|
+
"validLang_summary_fail": "Cette valeur d’attribut lang (« {{value}} ») n’est pas une étiquette de langue syntaxiquement valide.",
|
|
72317
|
+
"validLang_hint_fail": "Utilisez une étiquette de langue BCP47 valide (ex. « fr », « es-MX »).",
|
|
72318
|
+
"linkInTextBlock_title": "Les liens dans des blocs de texte doivent être distinguables du texte environnant sans se fier uniquement à la couleur",
|
|
72319
|
+
"linkInTextBlock_description": "Vérifie qu’un lien à l’intérieur d’un bloc de texte est visuellement distinguable du texte environnant par un soulignement, une différence de graisse/style de police, ou un contraste de couleur suffisant (>= 3:1) — pas seulement par la couleur.",
|
|
72320
|
+
"linkInTextBlock_summary_fail": "Ce lien dans un bloc de texte se distingue du texte environnant uniquement par la couleur.",
|
|
72321
|
+
"linkInTextBlock_hint_fail": "Ajoutez un soulignement, une différence de graisse/style de police, ou augmentez le contraste de couleur entre le lien et le texte environnant à au moins 3:1.",
|
|
72322
|
+
"noAutoplayAudio_title": "Un audio en lecture automatique devrait proposer un mécanisme de pause/arrêt ou de contrôle du volume",
|
|
72323
|
+
"noAutoplayAudio_description": "Signale les éléments <audio>/<video> qui se lancent automatiquement sans être coupés et sans attribut controls natif, pour une revue manuelle par rapport à l’exemption de 3 secondes de la WCAG 1.4.2.",
|
|
72324
|
+
"noAutoplayAudio_summary_cantTell": "Cet élément lit un audio automatiquement sans mécanisme natif de pause/arrêt ou de contrôle du volume.",
|
|
72325
|
+
"noAutoplayAudio_hint_cantTell": "Si ce clip dure plus de 3 secondes, ajoutez un attribut controls (ou un mécanisme personnalisé équivalent) afin que les utilisateurs puissent le mettre en pause/l’arrêter ou contrôler son volume indépendamment du volume du système.",
|
|
72326
|
+
"videoCaption_title": "Une vidéo préenregistrée devrait proposer une piste de sous-titres",
|
|
72327
|
+
"videoCaption_description": "Signale les éléments <video> sans enfant <track kind=\"captions\"|\"subtitles\">, pour une revue manuelle visant à déterminer si la vidéo a une piste audio nécessitant des sous-titres.",
|
|
72328
|
+
"videoCaption_summary_cantTell": "Cette vidéo n’a aucune piste de sous-titres (captions ou subtitles).",
|
|
72329
|
+
"videoCaption_hint_cantTell": "Si cette vidéo a une piste audio porteuse d’information, ajoutez un <track kind=\"captions\" src=\"...\"> avec le contenu sous-titré.",
|
|
72330
|
+
"scrollableRegionFocusable_title": "Les régions défilantes sans contenu focalisable devraient être focalisables au clavier",
|
|
72331
|
+
"scrollableRegionFocusable_description": "Signale les éléments dont le CSS déclare overflow:auto/scroll, qui ne contiennent aucun descendant focalisable, et qui ne sont pas eux-mêmes focalisables au clavier, pour une revue manuelle visant à déterminer si leur contenu déborde réellement et nécessite un accès au défilement au clavier.",
|
|
72332
|
+
"scrollableRegionFocusable_summary_cantTell": "Cet élément déclare overflow:auto/scroll, n’a aucun descendant focalisable, et n’est pas lui-même focalisable au clavier.",
|
|
72333
|
+
"scrollableRegionFocusable_hint_cantTell": "Si le contenu de cette région déborde réellement, ajoutez tabindex=\"0\" (et une étiquette adaptée) afin que les utilisateurs du clavier puissent la focaliser et faire défiler avec les flèches.",
|
|
72334
|
+
"identicalLinksSamePurpose_title": "Les liens partageant le même nom accessible devraient mener à la même destination",
|
|
72335
|
+
"identicalLinksSamePurpose_description": "Signale les groupes de liens qui partagent le même nom accessible mais mènent à plus d’une destination distincte, pour une revue manuelle visant à déterminer s’ils servent le même objectif.",
|
|
72336
|
+
"identicalLinksSamePurpose_summary_cantTell": "Ce lien partage un nom accessible avec d’autres liens de la page qui mènent à une destination différente.",
|
|
72337
|
+
"identicalLinksSamePurpose_hint_cantTell": "Assurez-vous que les liens ayant le même texte servent le même objectif, ou rendez le texte du lien suffisamment distinct pour décrire chaque destination.",
|
|
72338
|
+
"ariaBrailleEquivalent_title": "aria-braillelabel/aria-brailleroledescription doivent avoir un équivalent non braille",
|
|
72339
|
+
"ariaBrailleEquivalent_description": "Vérifie que les éléments utilisant aria-braillelabel ont aussi un nom accessible ordinaire, et que ceux utilisant aria-brailleroledescription ont aussi aria-roledescription.",
|
|
72340
|
+
"ariaBrailleEquivalent_summary_fail": "Cet élément a {{attr}} mais pas {{requires}}, son équivalent non braille.",
|
|
72341
|
+
"ariaBrailleEquivalent_hint_fail": "{{attr}} est un complément spécifique au braille, pas un remplacement — fournissez aussi {{requires}}.",
|
|
72342
|
+
"ariaConditionalAttr_title": "aria-errormessage exige que aria-invalid soit défini à une valeur autre que false",
|
|
72343
|
+
"ariaConditionalAttr_description": "Vérifie que les éléments ayant aria-errormessage ont aussi aria-invalid défini à « true », « grammar », ou « spelling » — sinon le message d’erreur est retiré de l’arbre d’accessibilité.",
|
|
72344
|
+
"ariaConditionalAttr_summary_fail": "Cet élément a aria-errormessage mais aria-invalid est absent ou « false », donc le message d’erreur n’est pas exposé.",
|
|
72345
|
+
"ariaConditionalAttr_hint_fail": "Définissez aria-invalid à « true » (ou « grammar »/« spelling ») chaque fois que aria-errormessage doit être exposé aux technologies d’assistance.",
|
|
72346
|
+
"ariaCheckedStateMismatch_title": "L’aria-checked d’une case à cocher/d’un bouton radio natif devrait correspondre à son état réel",
|
|
72347
|
+
"ariaCheckedStateMismatch_description": "Signale un <input type=\"checkbox\">/<input type=\"radio\"> natif dont la valeur explicite d’aria-checked ne correspond pas à son état réel (coché/indéterminé), pour une revue manuelle.",
|
|
72348
|
+
"ariaCheckedStateMismatch_summary_cantTell": "La valeur d’aria-checked de cet élément ne correspond pas à son état réel (coché/indéterminé).",
|
|
72349
|
+
"ariaCheckedStateMismatch_hint_cantTell": "Définissez aria-checked pour qu’il corresponde à l’état réel de l’élément, ou retirez-le — une case à cocher/un bouton radio natif expose déjà cet état sans lui.",
|
|
72350
|
+
"cssOrientationLock_title": "Le CSS ne doit pas verrouiller la page à une seule orientation",
|
|
72351
|
+
"cssOrientationLock_description": "Vérifie qu’aucune règle @media (orientation: portrait|landscape) ne définit un transform: rotate(...) sur la page, une technique connue pour contourner l’orientation de l’appareil.",
|
|
72352
|
+
"cssOrientationLock_summary_fail": "Une media query « {{mediaText}} » fait pivoter « {{selectorText}} », verrouillant la page à une seule orientation.",
|
|
72353
|
+
"cssOrientationLock_hint_fail": "Retirez la transformation rotate() de la media query d’orientation ; laissez la page répondre naturellement à l’orientation de l’appareil au lieu de forcer une rotation visuelle.",
|
|
72354
|
+
"ariaText_title": "Les éléments role=\"text\" ne devraient avoir aucun descendant focalisable",
|
|
72355
|
+
"ariaText_description": "Vérifie que les éléments ayant role=\"text\" ne contiennent aucun descendant focalisable (lien, bouton, contrôle de formulaire, tabindex, iframe, ou contenteditable).",
|
|
72356
|
+
"ariaText_summary_cantTell": "Cet élément role=\"text\" contient un descendant focalisable.",
|
|
72357
|
+
"ariaText_hint_cantTell": "Retirez role=\"text\" (ou retirez le descendant focalisable) — une région de « texte brut » ne devrait pas contenir de contenu focalisable.",
|
|
72358
|
+
"focusOrderSemantics_title": "Les éléments ajoutés à l’ordre de tabulation devraient avoir une sémantique interactive",
|
|
72359
|
+
"focusOrderSemantics_description": "Signale les éléments ayant tabindex >= 0 dont le rôle explicite est un rôle structurel/documentaire non interactif (ex. heading, list, region, presentation), pour une revue manuelle.",
|
|
72360
|
+
"focusOrderSemantics_summary_cantTell": "Cet élément est dans l’ordre de tabulation (tabindex=\"{{tabindex}}\") mais a un rôle non interactif (« {{role}} »).",
|
|
72361
|
+
"focusOrderSemantics_hint_cantTell": "Retirez tabindex si cet élément n’est pas censé être interactif, ou utilisez un rôle interactif correspondant à son comportement réel.",
|
|
72362
|
+
"pAsHeading_title": "Un <p> stylé pour ressembler à un titre devrait probablement être un véritable titre",
|
|
72363
|
+
"pAsHeading_description": "Signale les éléments <p> courts dont tout le texte est en gras et affiché à >= 18px, pour une revue manuelle visant à déterminer si un véritable élément de titre devrait être utilisé à la place.",
|
|
72364
|
+
"pAsHeading_summary_cantTell": "Ce paragraphe est entièrement en gras et affiché à une taille évoquant un titre.",
|
|
72365
|
+
"pAsHeading_hint_cantTell": "Si ce texte introduit une nouvelle section, utilisez un véritable élément de titre (<h1>-<h6> ou role=\"heading\") plutôt que de styler un paragraphe pour qu’il y ressemble.",
|
|
72366
|
+
"tableFakeCaption_title": "La première ligne d’un tableau ne devrait pas tenir lieu de véritable <caption>",
|
|
72367
|
+
"tableFakeCaption_description": "Signale les tableaux sans <caption> dont la première ligne a une seule cellule non vide alors que les autres lignes ont plusieurs cellules, pour une revue manuelle visant à déterminer si cette cellule fait office de légende factice.",
|
|
72368
|
+
"tableFakeCaption_summary_cantTell": "Ce tableau n’a pas de <caption>, mais sa première ligne est une cellule unique placée au-dessus de lignes à plusieurs cellules — elle fait peut-être office de légende factice.",
|
|
72369
|
+
"tableFakeCaption_hint_cantTell": "Si cette cellule est censée décrire le tableau, utilisez un véritable élément <caption> plutôt qu’une cellule isolée en première ligne.",
|
|
72370
|
+
"tdHasHeader_title": "Les cellules de données des grands tableaux doivent avoir un en-tête associé",
|
|
72371
|
+
"tdHasHeader_description": "Vérifie que chaque <td> d’un tableau grand et simple (sans colspan/rowspan) a un en-tête associé — via un attribut headers, un <th> de colonne implicite au-dessus, ou un <th> de ligne implicite à sa gauche.",
|
|
72372
|
+
"tdHasHeader_summary_fail": "Cette cellule de données n’a pas d’en-tête associé (pas d’attribut headers, pas de <th> de colonne au-dessus, pas de <th> de ligne à gauche).",
|
|
72373
|
+
"tdHasHeader_hint_fail": "Ajoutez un attribut headers référençant le(s) id du/des <th> pertinent(s), ou restructurez le tableau afin que cette cellule ait un en-tête de ligne/colonne implicite.",
|
|
72374
|
+
"mouseOnlyEventHandlers_title": "Les gestionnaires d’événements en ligne réservés au pointeur devraient avoir un équivalent accessible au clavier",
|
|
72375
|
+
"mouseOnlyEventHandlers_description": "Signale les éléments ayant un gestionnaire d’événement en ligne réservé au pointeur (onmouseover, onmouseout, onmousedown, onmouseup, ondblclick, onmousemove, onmouseenter, onmouseleave) sans équivalent accessible au clavier (onkeydown/onkeyup/onkeypress/onfocus/onblur), pour une revue manuelle.",
|
|
72376
|
+
"mouseOnlyEventHandlers_summary_cantTell": "Cet élément a {{attrs}} mais aucun gestionnaire équivalent accessible au clavier.",
|
|
72377
|
+
"mouseOnlyEventHandlers_hint_cantTell": "Ajoutez onkeydown/onkeyup/onkeypress (ou onfocus/onblur pour un comportement déclenché au survol) afin que cette fonctionnalité soit aussi accessible au clavier.",
|
|
72378
|
+
"linkNameQuality_title": "Le texte des liens devrait être descriptif, pas générique",
|
|
72379
|
+
"linkNameQuality_description": "Signale les liens dont le nom accessible complet est une formule connue comme non descriptive (ex. « cliquez ici », « en savoir plus », « plus »), pour une revue manuelle visant à déterminer si l’objet du lien est clair sans contexte supplémentaire.",
|
|
72380
|
+
"linkNameQuality_summary_cantTell": "Le nom accessible de ce lien (« {{name}} ») est une formule générique et non descriptive.",
|
|
72381
|
+
"linkNameQuality_hint_cantTell": "Faites en sorte que le texte du lien lui-même décrive sa destination/son objet (ex. « Télécharger le guide tarifaire 2026 » plutôt que « Télécharger »), ou confirmez que le contexte environnant rend déjà l’objet clair."
|
|
71345
72382
|
}
|
|
71346
72383
|
};
|
|
71347
72384
|
|
|
@@ -74065,14 +75102,35 @@ const createDomHelpers = (function createDomHelpers(opts) {
|
|
|
74065
75102
|
const includeShadowDom = !(opts && opts.includeShadowDom === false);
|
|
74066
75103
|
const excludeSelectors = Array.isArray(opts && opts.excludeSelectors) ? opts.excludeSelectors : [];
|
|
74067
75104
|
|
|
75105
|
+
// Rule-scoped excludes (engineOptions.rules[ruleId].excludeSelectors), set
|
|
75106
|
+
// by dom-runner.js immediately before invoking each rule's applicability/
|
|
75107
|
+
// run function via __setActiveRuleExcludeSelectors(). Safe as mutable
|
|
75108
|
+
// closure state because rule execution is synchronous and single-rule-
|
|
75109
|
+
// at-a-time: exactly one rule's excludes are ever "active" at once.
|
|
75110
|
+
var __activeRuleExcludeSelectors = [];
|
|
75111
|
+
|
|
75112
|
+
function __getEffectiveExcludeSelectors() {
|
|
75113
|
+
return __activeRuleExcludeSelectors.length
|
|
75114
|
+
? excludeSelectors.concat(__activeRuleExcludeSelectors)
|
|
75115
|
+
: excludeSelectors;
|
|
75116
|
+
}
|
|
75117
|
+
|
|
75118
|
+
function __setActiveRuleExcludeSelectors(list) {
|
|
75119
|
+
__activeRuleExcludeSelectors = normalizeSelectorList(list);
|
|
75120
|
+
}
|
|
75121
|
+
|
|
74068
75122
|
// Selector-related caches (selector uniqueness index, per-element built
|
|
74069
|
-
// selector strings) depend on includeShadowDom/
|
|
74070
|
-
// those change which elements are considered when checking
|
|
74071
|
-
// The underlying storage is shared across createDomHelpers()
|
|
74072
|
-
// the same window/document (see __domSharedCache below), so a
|
|
74073
|
-
//
|
|
74074
|
-
//
|
|
74075
|
-
|
|
75123
|
+
// selector strings) depend on includeShadowDom/the effective exclude
|
|
75124
|
+
// list, since those change which elements are considered when checking
|
|
75125
|
+
// uniqueness. The underlying storage is shared across createDomHelpers()
|
|
75126
|
+
// calls on the same window/document (see __domSharedCache below), so a
|
|
75127
|
+
// run -- or a rule with its own rule-scoped excludes -- must not
|
|
75128
|
+
// read/write another run/rule's cached selectors. This key partitions
|
|
75129
|
+
// those caches per effective option set; recomputed per call (not a
|
|
75130
|
+
// constant) since the effective list changes as the active rule changes.
|
|
75131
|
+
function __getSelectorOptsKey() {
|
|
75132
|
+
return (includeShadowDom ? 'sd1' : 'sd0') + '|' + __getEffectiveExcludeSelectors().slice().sort().join(',');
|
|
75133
|
+
}
|
|
74076
75134
|
|
|
74077
75135
|
// -------------------------------------------------------------------------
|
|
74078
75136
|
// Per-run shared caches (DOM helpers)
|
|
@@ -74834,9 +75892,10 @@ const createDomHelpers = (function createDomHelpers(opts) {
|
|
|
74834
75892
|
|
|
74835
75893
|
|
|
74836
75894
|
function isExcluded(el) {
|
|
74837
|
-
|
|
75895
|
+
const eff = __getEffectiveExcludeSelectors();
|
|
75896
|
+
if (!eff.length || !el || !el.closest) return false;
|
|
74838
75897
|
try {
|
|
74839
|
-
return
|
|
75898
|
+
return eff.some((sel) => !!el.closest(sel));
|
|
74840
75899
|
} catch {
|
|
74841
75900
|
return false;
|
|
74842
75901
|
}
|
|
@@ -74931,8 +75990,10 @@ const createDomHelpers = (function createDomHelpers(opts) {
|
|
|
74931
75990
|
if (!scope || !scope.querySelectorAll) return [];
|
|
74932
75991
|
|
|
74933
75992
|
// Cache shadow root discovery per root to avoid repeated querySelectorAll('*') walks.
|
|
74934
|
-
// IMPORTANT: do not cache when
|
|
74935
|
-
|
|
75993
|
+
// IMPORTANT: do not cache when the effective exclude list (global
|
|
75994
|
+
// ∪ active rule-scoped excludes) is non-empty -- different rules
|
|
75995
|
+
// may have different effective lists and must not share results.
|
|
75996
|
+
if (!__getEffectiveExcludeSelectors().length && __shadowRootsByRoot) {
|
|
74936
75997
|
try {
|
|
74937
75998
|
const cached = __shadowRootsByRoot.get(scope);
|
|
74938
75999
|
if (cached) {
|
|
@@ -75007,7 +76068,7 @@ const createDomHelpers = (function createDomHelpers(opts) {
|
|
|
75007
76068
|
|
|
75008
76069
|
function queryAllSmart(sel) {
|
|
75009
76070
|
const list = includeShadowDom ? queryAllDeep(sel) : queryAll(sel);
|
|
75010
|
-
return
|
|
76071
|
+
return __getEffectiveExcludeSelectors().length ? list.filter((el) => !isExcluded(el)) : list;
|
|
75011
76072
|
}
|
|
75012
76073
|
|
|
75013
76074
|
// -------------------------------------------------------------------------
|
|
@@ -75041,10 +76102,11 @@ const createDomHelpers = (function createDomHelpers(opts) {
|
|
|
75041
76102
|
function __getSelectorCacheForOpts() {
|
|
75042
76103
|
if (!__selectorCache) return null;
|
|
75043
76104
|
try {
|
|
75044
|
-
|
|
76105
|
+
const key = __getSelectorOptsKey();
|
|
76106
|
+
let wm = __selectorCache.get(key);
|
|
75045
76107
|
if (!(wm instanceof WeakMap)) {
|
|
75046
76108
|
wm = new WeakMap();
|
|
75047
|
-
__selectorCache.set(
|
|
76109
|
+
__selectorCache.set(key, wm);
|
|
75048
76110
|
}
|
|
75049
76111
|
return wm;
|
|
75050
76112
|
} catch {
|
|
@@ -77455,7 +78517,8 @@ const createDomHelpers = (function createDomHelpers(opts) {
|
|
|
77455
78517
|
return createSelectorUniqIndex();
|
|
77456
78518
|
}
|
|
77457
78519
|
|
|
77458
|
-
const
|
|
78520
|
+
const key = __getSelectorOptsKey();
|
|
78521
|
+
const cached = perScope.get(key);
|
|
77459
78522
|
if (cached) {
|
|
77460
78523
|
__perfInc('uniqIndex.hit');
|
|
77461
78524
|
return cached;
|
|
@@ -77464,7 +78527,7 @@ const createDomHelpers = (function createDomHelpers(opts) {
|
|
|
77464
78527
|
__perfInc('uniqIndex.miss');
|
|
77465
78528
|
const idx = createSelectorUniqIndex();
|
|
77466
78529
|
try {
|
|
77467
|
-
perScope.set(
|
|
78530
|
+
perScope.set(key, idx);
|
|
77468
78531
|
} catch { /* ignore */
|
|
77469
78532
|
}
|
|
77470
78533
|
__perfInc('uniqIndex.build');
|
|
@@ -77974,6 +79037,12 @@ const createDomHelpers = (function createDomHelpers(opts) {
|
|
|
77974
79037
|
isAccTreeEligible,
|
|
77975
79038
|
isDomVisibleEligible,
|
|
77976
79039
|
|
|
79040
|
+
// Engine-internal: sets which rule's rule-scoped excludeSelectors
|
|
79041
|
+
// (engineOptions.rules[ruleId].excludeSelectors) are currently in
|
|
79042
|
+
// effect. Called by dom-runner.js before each rule invocation, not
|
|
79043
|
+
// intended for use by rule implementations.
|
|
79044
|
+
__setActiveRuleExcludeSelectors,
|
|
79045
|
+
|
|
77977
79046
|
// Eligibility info wrapper
|
|
77978
79047
|
getEligibilityInfo,
|
|
77979
79048
|
|
|
@@ -78387,6 +79456,15 @@ const runCore = (function runCore(pageUrl, contextSelector, engineOptions, runOn
|
|
|
78387
79456
|
? engineOptionsResolved.rules[defResolved.ruleId]
|
|
78388
79457
|
: null;
|
|
78389
79458
|
|
|
79459
|
+
// Rule-scoped excludeSelectors (engineOptions.rules[ruleId].excludeSelectors)
|
|
79460
|
+
// apply on top of the global excludeSelectors for exactly this rule's
|
|
79461
|
+
// applicability check + run, then are cleared once this rule is done.
|
|
79462
|
+
// Safe because rule execution below is synchronous and one rule at a
|
|
79463
|
+
// time -- sharedHelpers is reused across all rules in this loop.
|
|
79464
|
+
if (typeof sharedHelpers.__setActiveRuleExcludeSelectors === 'function') {
|
|
79465
|
+
sharedHelpers.__setActiveRuleExcludeSelectors(ruleConfig && ruleConfig.excludeSelectors);
|
|
79466
|
+
}
|
|
79467
|
+
|
|
78390
79468
|
const ctx = {
|
|
78391
79469
|
document,
|
|
78392
79470
|
window,
|
|
@@ -78457,6 +79535,14 @@ const runCore = (function runCore(pageUrl, contextSelector, engineOptions, runOn
|
|
|
78457
79535
|
if (ruleTimings) ruleTimings[defResolved.ruleId] = (ruleTimings[defResolved.ruleId] || 0) + (nowMs() - t0);
|
|
78458
79536
|
}
|
|
78459
79537
|
|
|
79538
|
+
// Composite rollups below carry no occurrences/nodes of their own, so
|
|
79539
|
+
// they never exercise rule-scoped excludes -- but clear the "active
|
|
79540
|
+
// rule" state on sharedHelpers regardless, so nothing after this point
|
|
79541
|
+
// (composite aggregation, perf stats) can observe a stale rule's excludes.
|
|
79542
|
+
if (typeof sharedHelpers.__setActiveRuleExcludeSelectors === 'function') {
|
|
79543
|
+
sharedHelpers.__setActiveRuleExcludeSelectors(null);
|
|
79544
|
+
}
|
|
79545
|
+
|
|
78460
79546
|
// =========================
|
|
78461
79547
|
// Composite rule aggregation (data-only rollups)
|
|
78462
79548
|
// =========================
|