diff --git a/addon/globalPlugins/webAccess/gui/__init__.py b/addon/globalPlugins/webAccess/gui/__init__.py index 2a67a897..2a844ec5 100644 --- a/addon/globalPlugins/webAccess/gui/__init__.py +++ b/addon/globalPlugins/webAccess/gui/__init__.py @@ -385,7 +385,7 @@ class KbNavMultiCategorySettingsDialog(FillableMultiCategorySettingsDialog): def onCharHook(self, evt): keycode = evt.GetKeyCode() mods = evt.GetModifiers() - if keycode == wx.WXK_F6 and mods == wx.MOD_NONE: + if keycode == wx.WXK_F6 and mods | wx.MOD_SHIFT == wx.MOD_SHIFT: if self.catListCtrl.HasFocus(): self.container.SetFocus() else: diff --git a/addon/globalPlugins/webAccess/gui/rule/criteriaEditor.py b/addon/globalPlugins/webAccess/gui/rule/criteriaEditor.py index 1dc870dc..a1160f34 100644 --- a/addon/globalPlugins/webAccess/gui/rule/criteriaEditor.py +++ b/addon/globalPlugins/webAccess/gui/rule/criteriaEditor.py @@ -891,6 +891,73 @@ def updateData_others(self): value = InvalidValue(value) updateOrDrop(data, "index", value) + def copySelector(self): + self.updateData() + data = {"webAccess.selector" : self.getData()} + import json + data = json.dumps(data, indent=4) + import api + if api.copyToClip(data): + # Translators: A message from the Rule Editor dialog + ui.message(_("Criteria data copied to clipboard")) + return + wx.Bell() + + def pasteSelector(self): + self.updateData() + import api + data = api.getClipData() + if not data: + wx.Bell() + return + import json + try: + data = json.loads(data) + except Exception: + wx.Bell() + return + if not isinstance(data, dict) and len(data) == 1: + wx.Bell() + return + key, data = data.popitem() + try: + if key == "webAccess.rule": + if len(data) != 1: + wx.Bell() + return + data = data[0]["criteria"]["selector"] + elif key == "webAccess.criteria": + data = data["selector"] + elif key == "webAccess.rule": + data = data["criteria"] + if len(data) != 1: + wx.Bell() + return + data = data[0] + elif key == "webAccess.selector": + pass + else: + wx.Bell() + return + except (AttributeError, TypeError): + wx.Bell() + return + if not data or set(data.keys()) == {"start", "end"}: + wx.Bell() + return + if self.getData(): + if gui.messageBox( + # Translators: A prompt for confirmation on the Criteria Editor + message=_("Replace editor content with data from the clipboard?"), + # Translators: The title of a prompt for confirmation on the Criteria Editor + caption=_("Paste"), + style=wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION, + parent=self + ) != wx.YES: + return + self.getData().clear() + self.getData().update(data) + def refreshContextMacroChoices(self, initial=False): context = self.context dropDown = self.contextMacroDropDown @@ -1251,9 +1318,9 @@ def makeSettings(self, settingsSizer): def onCharHook(self, evt): # Bound by MultiCategorySettingsDialog.makeSettings - keycode = evt.GetKeyCode() + keyCode = evt.GetKeyCode() mods = evt.GetModifiers() - if keycode == wx.WXK_F5 and mods in (wx.MOD_NONE, wx.MOD_CONTROL): + if keyCode == wx.WXK_F5 and mods in (wx.MOD_NONE, wx.MOD_CONTROL): currCat = self.currentCategory restrictDualNodeTo = None if mods == wx.MOD_NONE: @@ -1263,7 +1330,7 @@ def onCharHook(self, evt): restrictDualNodeTo = "end" currCat.updateData() testCriteria(self.context, restrictDualNodeTo=restrictDualNodeTo) - elif keycode == wx.WXK_F8 and mods == wx.MOD_NONE: + elif keyCode == wx.WXK_F8 and mods == wx.MOD_NONE: from ..inspector import show try: node = self.context["webModule"].ruleManager.nodeManager.getCaretNode().parent @@ -1272,9 +1339,24 @@ def onCharHook(self, evt): return show(parent=self, node=node) return - elif keycode == wx.WXK_F12 and mods == wx.MOD_NONE: + elif keyCode == wx.WXK_F12 and mods == wx.MOD_NONE: self.switchToFullEditor() return + elif self.catListCtrl.HasFocus(): + cat = self.currentCategory + if isinstance(cat, CriteriaPanel): + if ( + keyCode in (ord("C"), wx.WXK_INSERT, wx.WXK_NUMPAD_INSERT) + and mods == wx.MOD_CONTROL + ): + cat.copySelector() + return + elif ( + keyCode == ord("V") and mods == wx.MOD_CONTROL + or keyCode in (wx.WXK_INSERT, wx.WXK_NUMPAD_INSERT) and mods == wx.MOD_SHIFT + ): + cat.pasteSelector() + return super().onCharHook(evt) def onConvertToDualNode(self, evt): diff --git a/addon/globalPlugins/webAccess/gui/rule/editor.py b/addon/globalPlugins/webAccess/gui/rule/editor.py index bb42d5c4..5e869b4c 100644 --- a/addon/globalPlugins/webAccess/gui/rule/editor.py +++ b/addon/globalPlugins/webAccess/gui/rule/editor.py @@ -427,6 +427,7 @@ def makeSettings(self, settingsSizer): listEndCol = 2 item = self.criteriaList = wx.ListBox(self) item.Bind(wx.EVT_LISTBOX, self.onCriteriaSelected) + item.Bind(wx.EVT_CHAR_HOOK, self.onCriteriaListCharHook) gbSizer.Add(item, pos=(row, 0), span=(6, 3), flag=wx.EXPAND) row += 6 @@ -530,20 +531,112 @@ def isValid(self): return False return True - + @guarded + def copyAlternative(self): + index = self.getIndex() + if index == wx.NOT_FOUND: + wx.Bell() + return + data = {"webAccess.criteria" : self.getData()[index]} + import json + data = json.dumps(data, indent=4) + import api + if api.copyToClip(data): + # Translators: A message from the Rule Editor dialog + ui.message(_("Criteria data copied to clipboard")) + return + wx.Bell() + + def pasteAlternative(self): + import api + data = api.getClipData() + if not data: + wx.Bell() + return + import json + try: + data = json.loads(data) + except Exception: + wx.Bell() + return + if not isinstance(data, dict) and len(data) == 1: + wx.Bell() + return + key, data = data.popitem() + if key == "webAccess.rule": + try: + data = data["criteria"] + if len(data) != 1: + wx.Bell() + return + data = data[0] + except (AttributeError, TypeError): + wx.Bell() + return + elif key == "webAccess.criteria": + pass + elif key == "webAccess.selector": + data = {"selector": data} + else: + wx.Bell() + return + if criteriaEditor.isDualNode(data) and self.getRuleType() != ruleTypes.ZONE: + wx.Bell() + return + self.onNewCriteria(pastedData=data) + def onCriteriaChange(self, change: Change, index: int): self.updateCriteriaList(index) self.refreshParent(self.categoryParams.treeNode) @guarded - def onNewCriteria(self, evt): - prm = self.categoryParams + def onCriteriaListCharHook(self, evt): + keyCode = evt.KeyCode + mods = evt.GetModifiers() + if keyCode == wx.WXK_DELETE and mods == wx.MOD_NONE: + self.onDeleteCriteria() + return + elif ( + keyCode in (ord("C"), wx.WXK_INSERT, wx.WXK_NUMPAD_INSERT) + and mods == wx.MOD_CONTROL + ): + self.copyAlternative() + return + elif ( + keyCode == ord("V") and mods == wx.MOD_CONTROL + or keyCode in (wx.WXK_INSERT, wx.WXK_NUMPAD_INSERT) and mods == wx.MOD_SHIFT + ): + self.pasteAlternative() + return + evt.Skip() + + @guarded + def onNewCriteria(self, evt=None, pastedData=None): listData = self.getData() + index = self.getIndex() + if index != wx.NOT_FOUND: + itemData = listData[index] + if not itemData.get("name"): + with wx.TextEntryDialog( + self, + # Translators: A prompt on the Rule editor + _("You may first provide a name for the current criteria set:"), + # Translators: The title of an input dialog in the Rule Editor dialog + _("Add alternatives"), + ) as dlg: + if dlg.ShowModal() != wx.ID_OK: + return + name = dlg.Value + if name: + itemData["name"] = name + self.onCriteriaChange(Change.UPDATE, index) context = self.context.copy() context["new"] = True itemData = context["data"]["criteria"] = OrderedDict({ "criteriaIndex": len(self.getData()) }) + if pastedData: + itemData.update(pastedData) if criteriaEditor.show(context, parent=self): index = itemData.pop("criteriaIndex") listData.insert(index, itemData) @@ -566,9 +659,11 @@ def onEditCriteria(self, evt, convertToDualNode=False): self.onCriteriaChange(Change.UPDATE, index) @guarded - def onDeleteCriteria(self, evt): - prm = self.categoryParams + def onDeleteCriteria(self, evt=None): index = self.getIndex() + if index == wx.NOT_FOUND: + wx.Bell() + return if gui.messageBox( # Translator: A confirmation prompt on the Rule editor _("Are you sure you want to delete this alternative?"), @@ -742,10 +837,7 @@ def makeSettings_buttons(self, gbSizer, row, col, full=True): row = startRow # Translators: New criteria button label item = self.newButton = wx.Button(self, label=_("&New...")) - item.Bind( - wx.EVT_BUTTON, - self.onNewCriteria if full else self.Parent.onAddAlternative, - ) + item.Bind(wx.EVT_BUTTON, self.onNewCriteria) gbSizer.Add(item, pos=(row, col)) row += 1 @@ -967,9 +1059,9 @@ def initData(self, context): self.Thaw() def onCharHook(self, evt): - keycode = evt.GetKeyCode() + keyCode = evt.GetKeyCode() mods = evt.GetModifiers() - if keycode == wx.WXK_F5 and mods == wx.MOD_NONE: + if keyCode == wx.WXK_F5 and mods == wx.MOD_NONE: self.testCriteria() return evt.Skip() @@ -1002,6 +1094,7 @@ def onCriteriaChange(self, change: Change, index: int): dlg = parent.Parent.Parent if change is Change.CREATION: dlg.switchToFullEditor() + return parent.switchToAppropriatePanel() parent.shownPanel.initData(self.context) @@ -1035,20 +1128,6 @@ def updateData(self): self.shownPanel.updateData() def onAddAlternative(self, evt): - data = self.getData() - if not data.get("name"): - with wx.TextEntryDialog( - self, - # Translators: A prompt on the Rule editor - _("You may first provide a name for the current criteria set:"), - # Translators: The title of an input dialog in the Rule Editor dialog - _("Add alternatives"), - ) as dlg: - if dlg.ShowModal() != wx.ID_OK: - return - name = dlg.Value - if name: - data["name"] = name self.summaryPanel.onNewCriteria(evt) def onConvertToDualNode(self, evt): @@ -1064,6 +1143,9 @@ def isValid(self): def delete(self): wx.Bell() + def pasteAlternative(self): + self.summaryPanel.pasteAlternative() + def spaceIsPressedOnTreeNode(self): self.shownPanel.spaceIsPressedOnTreeNode() @@ -1296,9 +1378,9 @@ def focusContainerControl(self, index: int): def onCharHook(self, evt): # Bound by TreeMultiCategorySettingsDialog.makeSettings - keycode = evt.GetKeyCode() + keyCode = evt.KeyCode mods = evt.GetModifiers() - if keycode == wx.WXK_F8 and mods == wx.MOD_NONE: + if keyCode == wx.WXK_F8 and mods == wx.MOD_NONE: from ..inspector import show try: node = self.context["webModule"].ruleManager.nodeManager.getCaretNode().parent @@ -1307,9 +1389,33 @@ def onCharHook(self, evt): return show(parent=self, node=node) return - elif keycode == wx.WXK_F12 and mods == wx.MOD_NONE: + elif keyCode == wx.WXK_F12 and mods == wx.MOD_NONE: self.switchToFullEditor() return + elif self.catListCtrl.HasFocus(): + cat = self.currentCategory + if ( + isinstance(cat, SimpleCriteriaPanel) + and keyCode in (ord("C"), wx.WXK_INSERT, wx.WXK_NUMPAD_INSERT) + and mods == wx.MOD_CONTROL + ): + cat.updateData() + cat.summaryPanel.copyAlternative() + return + elif ( + isinstance(cat, (AlternativesPanel, SimpleCriteriaPanel)) + and ( + keyCode == ord("V") and mods == wx.MOD_CONTROL + or keyCode in (wx.WXK_INSERT, wx.WXK_NUMPAD_INSERT) and mods == wx.MOD_SHIFT + ) + ): + if ( + isinstance(cat, SimpleCriteriaPanel) + and isinstance(cat.shownPanel, SimpleSingleNodeCriteriaPanel) + ): + cat.updateData() + cat.pasteAlternative() + return super().onCharHook(evt) def switchToFullEditor(self): diff --git a/addon/globalPlugins/webAccess/gui/rule/manager.py b/addon/globalPlugins/webAccess/gui/rule/manager.py index 35b249cf..8a293922 100644 --- a/addon/globalPlugins/webAccess/gui/rule/manager.py +++ b/addon/globalPlugins/webAccess/gui/rule/manager.py @@ -579,6 +579,27 @@ def cycleGroupBy(self, previous: bool = False, report: bool = True): ) self.onGroupByRadio(None) + @guarded + def copyRule(self): + obj = self.getSelectedObject() + if obj is None: + wx.Bell() + return + rule = None + if isinstance(obj, Result): + rule = obj.rule + elif isinstance(obj, Rule): + rule = obj + data = {"webAccess.rule" : rule.dump()} + import json + data = json.dumps(data, indent=4) + import api + if api.copyToClip(data): + # Translators: A message from the Rules Manager dialog + ui.message(_("Rule data copied to clipboard")) + return + wx.Bell() + def disableGroupByPosition(self) -> bool: """Returns `True` if the tree was refreshed as of this call. """ @@ -591,6 +612,33 @@ def disableGroupByPosition(self) -> bool: return True return False + def pasteRule(self): + import api + data = api.getClipData() + if not data: + wx.Bell() + return + import json + try: + data = json.loads(data) + except Exception: + wx.Bell() + return + if not (isinstance(data, dict) and len(data) == 1): + wx.Bell() + return + key, data = data.popitem() + if key == "webAccess.rule": + pass + elif key == "webAccess.criteria": + data = {"type": ruleTypes.MARKER, "criteria": [data]} + elif key == "webAccess.selector": + data = {"type": ruleTypes.MARKER, "criteria": [{"selector": data}]} + else: + wx.Bell() + return + self.onRuleNew(pastedData=data) + def refreshRuleList(self): context = self.context result = context.pop("initialSelectedResult", None) @@ -707,13 +755,24 @@ def onCharHook(self, evt: wx.KeyEvent): elif self.tree.HasFocus(): # Collapse/Expand all instead of current node as there are only two levels. char = getCharFromKeyEvent(evt) - #char = evt.GetUnicodeKey() if char == "*": self.tree.ExpandAll() return elif char == "/": self.tree.CollapseAll() return + elif ( + keyCode in (ord("C"), wx.WXK_INSERT, wx.WXK_NUMPAD_INSERT) + and mods == wx.MOD_CONTROL + ): + self.copyRule() + return + elif( + keyCode == ord("V") and mods == wx.MOD_CONTROL + or keyCode in (wx.WXK_INSERT, wx.WXK_NUMPAD_INSERT) and mods == wx.MOD_SHIFT + ): + self.pasteRule() + return evt.Skip() @guarded @@ -809,11 +868,18 @@ def onRuleEdit(self, evt): wx.CallAfter(self.tree.SetFocus) @guarded - def onRuleNew(self, evt): + def onRuleNew(self, evt=None, pastedData=None): context = self.context.copy() context["new"] = True context.get("data", {}).pop("rule", None) - from .wizard import show + if pastedData: + context.setdefault("data", {})["rule"] = pastedData + from . import editor + if not pastedData or editor.supportsSimpleMode(context): + from . import wizard + show = wizard.show + else: + show = editor.show if show(context, parent=self): rule = self.context["rule"] = context["rule"] # As a new rule was created, all results are to be considered obsolete diff --git a/addon/globalPlugins/webAccess/gui/rule/wizard.py b/addon/globalPlugins/webAccess/gui/rule/wizard.py index 0cb5b649..fe3b5fa6 100644 --- a/addon/globalPlugins/webAccess/gui/rule/wizard.py +++ b/addon/globalPlugins/webAccess/gui/rule/wizard.py @@ -279,7 +279,8 @@ def initData(self, context): if context.get("new"): # Translators: The title for the Rule Creation Wizard dialog title = _("Rule Creation Wizard") - data["rule"] = {"type": ruleTypes.MARKER} + # There might be existing data pasted from the clipboard + data.setdefault("rule", {"type": ruleTypes.MARKER}) else: # Translators: The title for the Rule Creation Wizard dialog title = _("Rule Edit Wizard") diff --git a/addon/locale/fr/LC_MESSAGES/nvda.po b/addon/locale/fr/LC_MESSAGES/nvda.po index 72f4049c..552a460c 100644 --- a/addon/locale/fr/LC_MESSAGES/nvda.po +++ b/addon/locale/fr/LC_MESSAGES/nvda.po @@ -21,8 +21,8 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: 'nvda-translations@groups.io'\n" -"POT-Creation-Date: 2025-04-22 17:29+0200\n" -"PO-Revision-Date: 2025-04-22 17:35+0200\n" +"POT-Creation-Date: 2025-04-24 09:56+0200\n" +"PO-Revision-Date: 2025-04-24 10:02+0200\n" "Last-Translator: Julien Cochuyt \n" "Language-Team: \n" "Language: fr_FR\n" @@ -648,7 +648,7 @@ msgstr "Ordre de &séquence :" #. Translators: The label for a field on the Rule editor #: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:414 #: addon\globalPlugins\webAccess\gui\rule\editor.py:240 -#: addon\globalPlugins\webAccess\gui\rule\editor.py:437 +#: addon\globalPlugins\webAccess\gui\rule\editor.py:438 msgid "Summar&y:" msgstr "&Résumé :" @@ -656,14 +656,14 @@ msgstr "&Résumé :" #. Translators: The label for a field on the Rule editor #: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:426 #: addon\globalPlugins\webAccess\gui\rule\editor.py:252 -#: addon\globalPlugins\webAccess\gui\rule\editor.py:449 +#: addon\globalPlugins\webAccess\gui\rule\editor.py:450 msgid "Technical n&otes:" msgstr "N&otes techniques :" #. Translators: The label for a button in the Criteria Editor dialog #. Translators: The label for a button in the Rule Editor dialog #: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:440 -#: addon\globalPlugins\webAccess\gui\rule\editor.py:938 +#: addon\globalPlugins\webAccess\gui\rule\editor.py:1030 msgid "Convert to free &zone (two sets of criteria)" msgstr "Convertir en &zone libre (deux jeux de critères)" @@ -676,7 +676,7 @@ msgstr "Convertir en &zone simple (un seul jeu de critères)" #. Translators: The label for a category in the rule editor #: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:528 #: addon\globalPlugins\webAccess\gui\rule\editor.py:405 -#: addon\globalPlugins\webAccess\gui\rule\editor.py:1012 +#: addon\globalPlugins\webAccess\gui\rule\editor.py:1105 msgid "Criteria" msgstr "Critères" @@ -789,81 +789,99 @@ msgstr "Avancé" msgid "Test these criteria (F5)" msgstr "Tester ces critères (F5)" +#. Translators: A message from the Rule Editor dialog +#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:902 +#: addon\globalPlugins\webAccess\gui\rule\editor.py:546 +msgid "Criteria data copied to clipboard" +msgstr "Données des critères copiées dans le presse-papier" + +#. Translators: A prompt for confirmation on the Criteria Editor +#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:951 +msgid "Replace editor content with data from the clipboard?" +msgstr "" +"Voulez-vous remplacer le contenu de l'éditeur avec les données présentes " +"dans le presse-papier ?" + +#. Translators: The title of a prompt for confirmation on the Criteria Editor +#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:953 +msgid "Paste" +msgstr "Coller" + #. Translators: An error message on the Criteria Editor #. Translators: An error message on the Rule Editor -#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:969 -#: addon\globalPlugins\webAccess\gui\rule\editor.py:525 +#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1036 +#: addon\globalPlugins\webAccess\gui\rule\editor.py:526 msgid "You must choose at least one criteria." msgstr "Vous devez choisir au moins un critère." #. Translators: The title of a message dialog #. Translators: The title of an error message dialog -#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:970 -#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:985 -#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:999 -#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1014 -#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1028 -#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1045 +#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1037 +#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1052 +#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1066 +#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1081 +#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1095 +#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1112 #: addon\globalPlugins\webAccess\gui\rule\editor.py:354 #: addon\globalPlugins\webAccess\gui\rule\editor.py:366 #: addon\globalPlugins\webAccess\gui\rule\editor.py:395 -#: addon\globalPlugins\webAccess\gui\rule\editor.py:526 +#: addon\globalPlugins\webAccess\gui\rule\editor.py:527 #: addon\globalPlugins\webAccess\gui\webModule\editor.py:275 #: addon\globalPlugins\webAccess\gui\webModule\editor.py:289 -#: addon\globalPlugins\webAccess\webModuleHandler\__init__.py:357 +#: addon\globalPlugins\webAccess\webModuleHandler\__init__.py:361 msgid "Error" msgstr "Erreur" #. Translators: Error message when the field doesn't meet the required syntax -#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:983 -#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1012 +#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1050 +#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1079 #, python-brace-format msgid "Syntax error in the field \"{field}\"" msgstr "Erreur de syntaxe dans le champ \"{field}\"" #. Translators: Error message when the field doesn't match any known identifier -#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:997 -#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1026 +#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1064 +#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1093 #, python-brace-format msgid "Unknown identifier in the field \"{field}\"" msgstr "Identifiant inconnu dans le champ \"{field}\"" #. Translators: Error message when the index is not positive -#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1044 +#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1111 msgid "Index, if set, must be a positive integer." msgstr "Index, si renseigné, doit être un nombre entier strictement positif." #. Translators: The label for a Criteria editor category. -#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1057 +#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1124 msgid "Start Criteria" msgstr "Critères de début" #. Translators: The label for a Criteria editor category. -#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1069 +#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1136 msgid "End Criteria" msgstr "Critères de fin" -#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1088 +#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1155 msgid "Select a property to override" msgstr "Sélectionnez une propriété à surcharger" #. Translators: The label for a list on the Criteria Editor dialog -#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1101 +#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1168 msgid "Properties specific to this criteria set" msgstr "Propriétés spécifiques à cet ensemble de critères" #. Translators: A hint stating a list is empty and how to populate it on the Criteria Editor dialog -#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1104 +#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1171 msgid "None. Press alt+n to override a property." msgstr "Aucune. Appuyez sur alt+n pour remplacer une propriété." #. Translators: A column header in the Criteria Editor dialog -#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1106 +#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1173 msgid "Rule value" msgstr "Valeur de la règle" #. Translators: The label for a button on the Criteria Editor dialog -#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1114 +#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1181 msgid "&New" msgstr "&Nouveau" @@ -875,10 +893,10 @@ msgstr "&Nouveau" #. Translator: The label for a button on the RulesManager dialog. #. Translators: The label for a button in the #. Web Modules Manager dialog -#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1124 -#: addon\globalPlugins\webAccess\gui\rule\editor.py:480 -#: addon\globalPlugins\webAccess\gui\rule\editor.py:737 -#: addon\globalPlugins\webAccess\gui\rule\editor.py:831 +#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1191 +#: addon\globalPlugins\webAccess\gui\rule\editor.py:481 +#: addon\globalPlugins\webAccess\gui\rule\editor.py:832 +#: addon\globalPlugins\webAccess\gui\rule\editor.py:923 #: addon\globalPlugins\webAccess\gui\rule\gestures.py:144 #: addon\globalPlugins\webAccess\gui\rule\manager.py:519 #: addon\globalPlugins\webAccess\gui\webModule\manager.py:126 @@ -887,20 +905,20 @@ msgstr "&Supprimer" #. Avoid announcing the whole eventual control refresh #. Translators: Announced when resetting a property to its default value in the editor -#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1200 +#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1267 #: addon\globalPlugins\webAccess\gui\rule\properties.py:312 #, python-brace-format msgid "Reset to {value}" msgstr "Réinitialiser à {value}" #. Translators: The title of the Criteria Editor dialog. -#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1205 +#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1272 msgid "WebAccess Criteria Set editor" msgstr "Éditeur de jeux de critères WebAccess" #. Translators: A prompt for confirmation on the Criteria Set editor #. Translators: A prompt for confirmation on the Rule editor -#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1288 +#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1370 #: addon\globalPlugins\webAccess\gui\rule\editor.py:179 msgid "" "This will delete your End Criteria choices.\n" @@ -912,11 +930,11 @@ msgstr "" "Voulez-vous continuer ?" #. Translators: The title of prompt for confirmation on the Criteria Set editor -#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1293 +#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1375 msgid "Convert to simple zone (one set of criteria)" msgstr "Convertir en zone simple (un seul jeu de critères)" -#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1336 +#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1418 #: addon\globalPlugins\webAccess\gui\rule\__init__.py:112 msgid "" "The \"Transform\" property is not supported with free zones (two sets of " @@ -930,7 +948,7 @@ msgstr "" "Voulez-vous poursuivre néanmoins ?\n" #. Translators: The title of a message dialog -#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1342 +#: addon\globalPlugins\webAccess\gui\rule\criteriaEditor.py:1424 #: addon\globalPlugins\webAccess\gui\rule\__init__.py:118 #: addon\globalPlugins\webAccess\gui\webModule\__init__.py:86 msgid "Warning" @@ -1008,9 +1026,9 @@ msgstr "&Alternatives" #. Translators: New criteria button label #. Translators: The label for a button on the Rule Editor dialog #. Translators: The label for a button in the Rule Editor dialog -#: addon\globalPlugins\webAccess\gui\rule\editor.py:462 -#: addon\globalPlugins\webAccess\gui\rule\editor.py:744 -#: addon\globalPlugins\webAccess\gui\rule\editor.py:838 +#: addon\globalPlugins\webAccess\gui\rule\editor.py:463 +#: addon\globalPlugins\webAccess\gui\rule\editor.py:839 +#: addon\globalPlugins\webAccess\gui\rule\editor.py:930 #: addon\globalPlugins\webAccess\gui\rule\gestures.py:122 msgid "&New..." msgstr "&Nouveau..." @@ -1020,79 +1038,79 @@ msgstr "&Nouveau..." #. Translators: The label for a button in the Rule Editor dialog #. Translator: The label for a button on the RulesManager dialog. #. Translators: The label for a button in the Web Modules Manager dialog -#: addon\globalPlugins\webAccess\gui\rule\editor.py:471 -#: addon\globalPlugins\webAccess\gui\rule\editor.py:727 +#: addon\globalPlugins\webAccess\gui\rule\editor.py:472 +#: addon\globalPlugins\webAccess\gui\rule\editor.py:822 #: addon\globalPlugins\webAccess\gui\rule\gestures.py:133 #: addon\globalPlugins\webAccess\gui\rule\manager.py:511 #: addon\globalPlugins\webAccess\gui\webModule\manager.py:103 msgid "&Edit..." msgstr "&Modifier..." +#. Translators: A prompt on the Rule editor +#: addon\globalPlugins\webAccess\gui\rule\editor.py:623 +msgid "You may first provide a name for the current criteria set:" +msgstr "Vous pouvez d'abord attribuer un nom au jeu de critères existant :" + +#. Translators: The title of an input dialog in the Rule Editor dialog +#: addon\globalPlugins\webAccess\gui\rule\editor.py:625 +msgid "Add alternatives" +msgstr "Ajouter des alternatives" + #. Translator: A confirmation prompt on the Rule editor -#: addon\globalPlugins\webAccess\gui\rule\editor.py:574 +#: addon\globalPlugins\webAccess\gui\rule\editor.py:669 msgid "Are you sure you want to delete this alternative?" msgstr "Êtes-vous sûr de vouloir supprimer cette alternative ?" #. Translator: The title for a confirmation prompt on the Rule editor #. Translator: The title for a confirmation prompt on the #. RulesManager dialog. -#: addon\globalPlugins\webAccess\gui\rule\editor.py:576 -#: addon\globalPlugins\webAccess\gui\rule\manager.py:770 +#: addon\globalPlugins\webAccess\gui\rule\editor.py:671 +#: addon\globalPlugins\webAccess\gui\rule\manager.py:829 msgid "Confirm Deletion" msgstr "Confirmation d'effacement" #. Translators: The label for a field on the Rule editor -#: addon\globalPlugins\webAccess\gui\rule\editor.py:686 +#: addon\globalPlugins\webAccess\gui\rule\editor.py:781 msgid "Summar&y" msgstr "&Résumé" #. Translators: The label for a field on the Rule editor -#: addon\globalPlugins\webAccess\gui\rule\editor.py:703 +#: addon\globalPlugins\webAccess\gui\rule\editor.py:798 msgid "Technical n&otes" msgstr "N&otes techniques" #. Translators: The label for a button in the Rule Editor dialog -#: addon\globalPlugins\webAccess\gui\rule\editor.py:946 +#: addon\globalPlugins\webAccess\gui\rule\editor.py:1038 msgid "Add alternati&ves" msgstr "Ajouter des alternati&ves" -#. Translators: A prompt on the Rule editor -#: addon\globalPlugins\webAccess\gui\rule\editor.py:1043 -msgid "You may first provide a name for the current criteria set:" -msgstr "Vous pouvez d'abord attribuer un nom au jeu de critères existant :" - -#. Translators: The title of an input dialog in the Rule Editor dialog -#: addon\globalPlugins\webAccess\gui\rule\editor.py:1045 -msgid "Add alternatives" -msgstr "Ajouter des alternatives" - #. Translators: A title of the rule editor -#: addon\globalPlugins\webAccess\gui\rule\editor.py:1217 +#: addon\globalPlugins\webAccess\gui\rule\editor.py:1299 msgid "Sub Module {} - New Rule" msgstr "Sous-module {} - Nouvelle règle" #. Translators: A title of the rule editor -#: addon\globalPlugins\webAccess\gui\rule\editor.py:1220 +#: addon\globalPlugins\webAccess\gui\rule\editor.py:1302 msgid "Root Module {} - New Rule" msgstr "Module racine {} - Nouvelle règle" #. Translators: A title of the rule editor -#: addon\globalPlugins\webAccess\gui\rule\editor.py:1223 +#: addon\globalPlugins\webAccess\gui\rule\editor.py:1305 msgid "Web Module {} - New Rule" msgstr "Module web {} - Nouvelle règle" #. Translators: A title of the rule editor -#: addon\globalPlugins\webAccess\gui\rule\editor.py:1235 +#: addon\globalPlugins\webAccess\gui\rule\editor.py:1317 msgid "Sub Module {} - Edit Rule {}" msgstr "Sous-module {} - Modifier la règle {}" #. Translators: A title of the rule editor -#: addon\globalPlugins\webAccess\gui\rule\editor.py:1238 +#: addon\globalPlugins\webAccess\gui\rule\editor.py:1320 msgid "Root Module {} - Edit Rule {}" msgstr "Module racine - Modifier la règle {}" #. Translators: A title of the rule editor -#: addon\globalPlugins\webAccess\gui\rule\editor.py:1241 +#: addon\globalPlugins\webAccess\gui\rule\editor.py:1323 msgid "Web Module {} - Edit Rule {}" msgstr "Module web {} - Modifier la règle {}" @@ -1289,8 +1307,13 @@ msgstr "Aller à" msgid "Group by: {}" msgstr "Regrouper par : {}" +#. Translators: A message from the Rules Manager dialog +#: addon\globalPlugins\webAccess\gui\rule\manager.py:599 +msgid "Rule data copied to clipboard" +msgstr "Données de la règle copiées dans le presse-papier" + #. Translator: A confirmation prompt on the RulesManager dialog. -#: addon\globalPlugins\webAccess\gui\rule\manager.py:764 +#: addon\globalPlugins\webAccess\gui\rule\manager.py:823 msgid "Are you sure you want to delete this rule?" msgstr "Êtes-vous sûr de vouloir supprimer cette règle ?" @@ -1321,7 +1344,7 @@ msgctxt "webAccess.ruleEditor" msgid "Value" msgstr "Valeur" -#: addon\globalPlugins\webAccess\gui\rule\wizard.py:120 +#: addon\globalPlugins\webAccess\gui\rule\wizard.py:121 msgid "" "First, choose a type and name for the Rule.\n" "At any time, press F12 to leave this wizard and open the full fledged editor." @@ -1330,7 +1353,7 @@ msgstr "" "À tout moment, appuyez sur F12 pour quitter cet assistant et ouvrir " "l'éditeur complet." -#: addon\globalPlugins\webAccess\gui\rule\wizard.py:140 +#: addon\globalPlugins\webAccess\gui\rule\wizard.py:141 msgid "" "Choose the criteria evaluation context.\n" "\n" @@ -1346,7 +1369,7 @@ msgstr "" "\n" "En cas de doute, conservez le choix par défaut \"Général\"." -#: addon\globalPlugins\webAccess\gui\rule\wizard.py:164 +#: addon\globalPlugins\webAccess\gui\rule\wizard.py:165 msgid "" "Choose search criteria.\n" "\n" @@ -1367,7 +1390,7 @@ msgstr "" "Appuyez sur F5 pour tester ces critères. Une fois satisfait du résultat, " "appuyez sur Entrée ou cliquez sur Suivant." -#: addon\globalPlugins\webAccess\gui\rule\wizard.py:200 +#: addon\globalPlugins\webAccess\gui\rule\wizard.py:201 msgid "" "You may associate an input gesture with an action on the result found.\n" "\n" @@ -1380,12 +1403,12 @@ msgstr "" "l'emplacement souhaité." #. Translators: The title for the Rule Creation Wizard dialog -#: addon\globalPlugins\webAccess\gui\rule\wizard.py:280 +#: addon\globalPlugins\webAccess\gui\rule\wizard.py:281 msgid "Rule Creation Wizard" msgstr "Assistant nouvelle règle" #. Translators: The title for the Rule Creation Wizard dialog -#: addon\globalPlugins\webAccess\gui\rule\wizard.py:284 +#: addon\globalPlugins\webAccess\gui\rule\wizard.py:286 msgid "Rule Edit Wizard" msgstr "Assistant modification de règle" @@ -1805,49 +1828,49 @@ msgid "Current web module is: {name}" msgstr "Le module web actuel est : {name}" #. Translators: Confirmation message after web module creation. -#: addon\globalPlugins\webAccess\webModuleHandler\__init__.py:255 +#: addon\globalPlugins\webAccess\webModuleHandler\__init__.py:259 #, python-brace-format msgid "Your new web module {name} has been created." msgstr "Votre nouveau module web {name} a été créé." -#: addon\globalPlugins\webAccess\webModuleHandler\__init__.py:269 +#: addon\globalPlugins\webAccess\webModuleHandler\__init__.py:273 msgid "The web module name should be a valid file name." msgstr "Le nom d'un web module doit être un nom de fichier valide." -#: addon\globalPlugins\webAccess\webModuleHandler\__init__.py:271 +#: addon\globalPlugins\webAccess\webModuleHandler\__init__.py:275 msgid "It should not contain any of the following:" msgstr "Il ne doit contenir aucun des caractères suivants :" #. Translators: An error message upon attempting to save a modification -#: addon\globalPlugins\webAccess\webModuleHandler\__init__.py:326 +#: addon\globalPlugins\webAccess\webModuleHandler\__init__.py:330 msgid "This modification cannot be saved under the current configuration." msgstr "" "Cette modification ne peut pas être enregistrée de par la configuration " "actuelle." #. Translators: A hint on how to allow to save a modification -#: addon\globalPlugins\webAccess\webModuleHandler\__init__.py:330 +#: addon\globalPlugins\webAccess\webModuleHandler\__init__.py:334 msgid "• In the WebAccess category, enable User WebModules." msgstr "• Dans la catégorie WebAccess, activer les WebModules utilisateur." #. Translators: A hint on how to allow to save a modification -#: addon\globalPlugins\webAccess\webModuleHandler\__init__.py:336 +#: addon\globalPlugins\webAccess\webModuleHandler\__init__.py:340 msgid "• In the WebAccess category, enable Developper Mode." msgstr "• Dans la catégorie WebAccess, activer le mode développeur." #. Translators: A hint on how to allow to save a modification -#: addon\globalPlugins\webAccess\webModuleHandler\__init__.py:345 +#: addon\globalPlugins\webAccess\webModuleHandler\__init__.py:349 msgid "• In the Advanced category, enable loading of the Scratchpad directory" msgstr "" "• Dans la catégorie Avancé, activer le chargement de code personnalisé " "depuis le répertoire Bloc-notes du Développeur" -#: addon\globalPlugins\webAccess\webModuleHandler\__init__.py:348 +#: addon\globalPlugins\webAccess\webModuleHandler\__init__.py:352 msgid "or" msgstr "ou" #. Translators: An introduction to hints on how to allow to save a modification -#: addon\globalPlugins\webAccess\webModuleHandler\__init__.py:351 +#: addon\globalPlugins\webAccess\webModuleHandler\__init__.py:355 msgid "You may, in NVDA Preferences:" msgstr "Vous pouvez, dans les paramètres de NVDA :"