Index: gc_lang/fr/config.ini ================================================================== --- gc_lang/fr/config.ini +++ gc_lang/fr/config.ini @@ -15,26 +15,30 @@ logo = logo.png # main dictionary lexicon_src = lexicons/French.lex dic_filenames = fr-allvars,fr-classic,fr-reform -dic_name = Français,Français (Classique/Moderne),Français (Réforme 1990) +dic_name = fr-allvars,fr-classic,fr-reform +dic_description = Français (Toutes variantes),Français (Classique),Français (Réforme 1990) dic_filter = ,[*CMPX]$,[*RPX]$ dic_default_filename_py = fr-allvars dic_default_filename_js = fr-allvars # extended dictionary lexicon_extended_src = lexicons/French.extended.lex dic_extended_filename = fr.extended -dic_extended_name = Français - dictionnaire étendu +dic_extended_name = fr.extended +dic_extended_description = Français - dictionnaire étendu # community dictionary lexicon_community_src = lexicons/French.community.lex dic_community_filename = fr.community -dic_community_name = Français - dictionnaire communautaire +dic_community_name = fr.community +dic_community_description = Français - dictionnaire communautaire # personal dictionary lexicon_personal_src = lexicons/French.personal.lex dic_personal_filename = fr.personal -dic_personal_name = Français - dictionnaire personnel +dic_personal_name = fr.personal +dic_personal_description = Français - dictionnaire personnel # Finite state automaton compression: 1, 2 (experimental) or 3 (experimental) fsa_method = 1 # stemming method: S for suffixes only, A for prefixes and suffixes stemming_method = S @@ -46,11 +50,11 @@ # Firefox fx_identifier = French-GC@grammalecte.net fx_name = Grammalecte [fr] win_fx_dev_path = C:\Program Files\Firefox Developer Edition\firefox.exe -win_fx_nightly_path = C:\Program Files\Nightly\firefox.exe +win_fx_nightly_path = C:\Program Files\Firefox Nightly\firefox.exe linux_fx_dev_path = /usr/bin/firefox linux_fx_nightly_path = /usr/bin/firefox # Thunderbird tb_identifier = French-GC-TB@grammalecte.net Index: gc_lang/fr/dictionnaire/genfrdic.py ================================================================== --- gc_lang/fr/dictionnaire/genfrdic.py +++ gc_lang/fr/dictionnaire/genfrdic.py @@ -524,15 +524,10 @@ def writeGrammarCheckerLexicon (self, spfDst, version): echo(' * Lexique simplifié >> [ {} ] '.format(spfDst)) with open(spfDst[:-4]+".lex", 'w', encoding='utf-8', newline="\n") as hDst: hDst.write(MPLHEADER) hDst.write("# Lexique simplifié pour Grammalecte v{}\n# Licence : MPL v2.0\n\n".format(version)) - hDst.write("## LangCode: fr\n") - hDst.write("## LangName: Français\n") - hDst.write("## DicName: fr.commun\n") - hDst.write("## Description: Français commun (toutes variantes)\n") - hDst.write("## Author: Olivier R.\n\n") hDst.write(Flexion.simpleHeader()) for oFlex in self.lFlexions: hDst.write(oFlex.getGrammarCheckerRepr()) def createFiles (self, spDst, lDictVars, nMode, bSimplified): Index: gc_lang/fr/oxt/DictOptions/LexiconEditor.py ================================================================== --- gc_lang/fr/oxt/DictOptions/LexiconEditor.py +++ gc_lang/fr/oxt/DictOptions/LexiconEditor.py @@ -409,11 +409,11 @@ xGridDataModel = self.xGridModelLex.GridDataModel lEntry = [] for i in range(xGridDataModel.RowCount): lEntry.append(xGridDataModel.getRowData(i)) if lEntry: - oDAWG = dawg.DAWG(lEntry, "S", "fr", "Français", "fr.personal") + oDAWG = dawg.DAWG(lEntry, "S", "fr", "Français", "fr.personal", "Dictionnaire personnel") self.oPersonalDicJSON = oDAWG.getBinaryAsJSON() self.xOptionNode.setPropertyValue("personal_dic", json.dumps(self.oPersonalDicJSON, ensure_ascii=False)) self.xSettingNode.commitChanges() self.xNumDic.Label = str(self.oPersonalDicJSON["nEntry"]) self.xDateDic.Label = self.oPersonalDicJSON["sDate"] Index: gc_lang/fr/oxt/Dictionnaires/dictionaries/fr-classique.aff ================================================================== --- gc_lang/fr/oxt/Dictionnaires/dictionaries/fr-classique.aff +++ gc_lang/fr/oxt/Dictionnaires/dictionaries/fr-classique.aff @@ -2,11 +2,11 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # AFFIXES DU DICTIONNAIRE ORTHOGRAPHIQUE FRANÇAIS “CLASSIQUE” v7.0 # par Olivier R. -- licence MPL 2.0 -# Généré le 09-01-2019 à 18:08 +# Généré le 11-01-2019 à 17:14 # Pour améliorer le dictionnaire, allez sur https://grammalecte.net/ SET UTF-8 Index: gc_lang/fr/oxt/Dictionnaires/dictionaries/fr-moderne.aff ================================================================== --- gc_lang/fr/oxt/Dictionnaires/dictionaries/fr-moderne.aff +++ gc_lang/fr/oxt/Dictionnaires/dictionaries/fr-moderne.aff @@ -2,11 +2,11 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # AFFIXES DU DICTIONNAIRE ORTHOGRAPHIQUE FRANÇAIS “MODERNE” v7.0 # par Olivier R. -- licence MPL 2.0 -# Généré le 09-01-2019 à 18:08 +# Généré le 11-01-2019 à 17:14 # Pour améliorer le dictionnaire, allez sur https://grammalecte.net/ SET UTF-8 Index: gc_lang/fr/oxt/Dictionnaires/dictionaries/fr-reforme1990.aff ================================================================== --- gc_lang/fr/oxt/Dictionnaires/dictionaries/fr-reforme1990.aff +++ gc_lang/fr/oxt/Dictionnaires/dictionaries/fr-reforme1990.aff @@ -2,11 +2,11 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # AFFIXES DU DICTIONNAIRE ORTHOGRAPHIQUE FRANÇAIS “RÉFORME 1990” v7.0 # par Olivier R. -- licence MPL 2.0 -# Généré le 09-01-2019 à 18:08 +# Généré le 11-01-2019 à 17:14 # Pour améliorer le dictionnaire, allez sur https://grammalecte.net/ SET UTF-8 Index: gc_lang/fr/oxt/Dictionnaires/dictionaries/fr-toutesvariantes.aff ================================================================== --- gc_lang/fr/oxt/Dictionnaires/dictionaries/fr-toutesvariantes.aff +++ gc_lang/fr/oxt/Dictionnaires/dictionaries/fr-toutesvariantes.aff @@ -2,11 +2,11 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # AFFIXES DU DICTIONNAIRE ORTHOGRAPHIQUE FRANÇAIS “TOUTES VARIANTES” v7.0 # par Olivier R. -- licence MPL 2.0 -# Généré le 09-01-2019 à 18:08 +# Généré le 11-01-2019 à 17:14 # Pour améliorer le dictionnaire, allez sur https://grammalecte.net/ SET UTF-8 Index: gc_lang/fr/tb/content/lex_editor.js ================================================================== --- gc_lang/fr/tb/content/lex_editor.js +++ gc_lang/fr/tb/content/lex_editor.js @@ -476,11 +476,11 @@ build: function () { let xProgressNode = document.getElementById("wait_progress"); let lEntry = oLexiconTable.getEntries(); if (lEntry.length > 0) { - let oDAWG = new DAWG(lEntry, "S", "fr", "Français", "fr.personal", xProgressNode); + let oDAWG = new DAWG(lEntry, "S", "fr", "Français", "fr.personal", "Dictionnaire personnel", xProgressNode); let oJSON = oDAWG.createBinaryJSON(1); oFileHandler.saveFile("fr.personal.json", JSON.stringify(oJSON)); this.oIBDAWG = new IBDAWG(oJSON); this.setDictData(this.oIBDAWG.nEntry, this.oIBDAWG.sDate); //browser.runtime.sendMessage({ sCommand: "setDictionary", dParam: {sType: "personal", oDict: oJSON}, dInfo: {} }); Index: gc_lang/fr/webext/background.js ================================================================== --- gc_lang/fr/webext/background.js +++ gc_lang/fr/webext/background.js @@ -117,25 +117,22 @@ dParam: { sDictionary: sDictionary, bActivate: bActivate }, dInfo: {} }); } -function initSCOptions (dSavedOptions) { - if (!dSavedOptions.hasOwnProperty("sc_options")) { +function initSCOptions (oData) { + if (!oData.hasOwnProperty("sc_options")) { browser.storage.local.set({"sc_options": { extended: true, community: true, personal: true }}); - setDictionaryOnOff("extended", true); setDictionaryOnOff("community", true); setDictionaryOnOff("personal", true); } else { - let dOptions = dSavedOptions.sc_options; - setDictionaryOnOff("extended", dOptions["extended"]); - setDictionaryOnOff("community", dOptions["community"]); - setDictionaryOnOff("personal", dOptions["personal"]); + setDictionaryOnOff("community", oData.sc_options["community"]); + setDictionaryOnOff("personal", oData.sc_options["personal"]); } } function setDictionary (sDictionary, oDictionary) { xGCEWorker.postMessage({ @@ -143,37 +140,41 @@ dParam: { sDictionary: sDictionary, oDict: oDictionary }, dInfo: {} }); } -function setSpellingDictionary (dSavedDictionary) { - if (dSavedDictionary.hasOwnProperty("oExtendedDictionary")) { - setDictionary("extended", dSavedDictionary["oExtendedDictionary"]); - } - if (dSavedDictionary.hasOwnProperty("oCommunityDictionary")) { - setDictionary("community", dSavedDictionary["oCommunityDictionary"]); - } - if (dSavedDictionary.hasOwnProperty("oPersonalDictionary")) { - setDictionary("personal", dSavedDictionary["oPersonalDictionary"]); +function setSpellingDictionaries (oData) { + if (oData.hasOwnProperty("oPersonalDictionary")) { + // deprecated (to be removed in 2020) + console.log("personal dictionary migration"); + browser.storage.local.set({ "personal_dictionary": oData["oPersonalDictionary"] }); + setDictionary("personal", oData["oPersonalDictionary"]); + browser.storage.local.remove("oPersonalDictionary"); + } + if (oData.hasOwnProperty("personal_dictionary")) { + setDictionary("personal", oData["personal_dictionary"]); + } + if (oData.hasOwnProperty("community_dictionary")) { + setDictionary("community", oData["community_dictionary"]); } } function init () { if (bChrome) { browser.storage.local.get("gc_options", initGrammarChecker); browser.storage.local.get("ui_options", initUIOptions); - browser.storage.local.get("oExtendedDictionary", setSpellingDictionary); - browser.storage.local.get("oCommunityDictionary", setSpellingDictionary); - browser.storage.local.get("oPersonalDictionary", setSpellingDictionary); + browser.storage.local.get("personal_dictionary", setSpellingDictionaries); + browser.storage.local.get("community_dictionary", setSpellingDictionaries); + browser.storage.local.get("oPersonalDictionary", setSpellingDictionaries); // deprecated browser.storage.local.get("sc_options", initSCOptions); return; } browser.storage.local.get("gc_options").then(initGrammarChecker, showError); browser.storage.local.get("ui_options").then(initUIOptions, showError); - browser.storage.local.get("oExtendedDictionary").then(setSpellingDictionary, showError); - browser.storage.local.get("oCommunityDictionary").then(setSpellingDictionary, showError); - browser.storage.local.get("oPersonalDictionary").then(setSpellingDictionary, showError); + browser.storage.local.get("personal_dictionary").then(setSpellingDictionaries, showError); + browser.storage.local.get("community_dictionary").then(setSpellingDictionaries, showError); + browser.storage.local.get("oPersonalDictionary").then(setSpellingDictionaries, showError); // deprecated browser.storage.local.get("sc_options").then(initSCOptions, showError); } init(); @@ -215,10 +216,19 @@ xGCEWorker.postMessage(oRequest); break; case "openURL": browser.tabs.create({url: dParam.sURL}); break; + case "openConjugueurTab": + openConjugueurTab(); + break; + case "openLexiconEditor": + openLexiconEditor(dParam["dictionary"]); + break; + case "openDictionaries": + openDictionaries(); + break; default: console.log("[background] Unknown command: " + sCommand); console.log(oRequest); } //sendResponse({response: "response from background script"}); @@ -226,10 +236,11 @@ browser.runtime.onMessage.addListener(handleMessage); function handleConnexion (xPort) { + // Messages from tabs let iPortId = xPort.sender.tab.id; // identifier for the port: each port can be found at dConnx[iPortId] dConnx.set(iPortId, xPort); xPort.onMessage.addListener(function (oRequest) { let {sCommand, dParam, dInfo} = oRequest; switch (sCommand) { @@ -277,13 +288,15 @@ browser.contextMenus.create({ id: "separator_editable", type: "separator", contexts: ["editable"] }); // Page browser.contextMenus.create({ id: "rightClickLxgPage", title: "Lexicographe (page)", contexts: ["all"] }); // on all parts, due to unwanted selection browser.contextMenus.create({ id: "rightClickGCPage", title: "Correction grammaticale (page)", contexts: ["all"] }); browser.contextMenus.create({ id: "separator_page", type: "separator", contexts: ["all"] }); -// Conjugueur +// Tools browser.contextMenus.create({ id: "conjugueur_window", title: "Conjugueur [fenêtre]", contexts: ["all"] }); browser.contextMenus.create({ id: "conjugueur_tab", title: "Conjugueur [onglet]", contexts: ["all"] }); +browser.contextMenus.create({ id: "dictionaries", title: "Dictionnaires", contexts: ["all"] }); +browser.contextMenus.create({ id: "lexicon_editor", title: "Éditeur lexical", contexts: ["all"] }); // Rescan page browser.contextMenus.create({ id: "separator_rescan", type: "separator", contexts: ["editable"] }); browser.contextMenus.create({ id: "rescanPage", title: "Rechercher à nouveau les zones de texte", contexts: ["editable"] }); @@ -323,10 +336,16 @@ openConjugueurWindow(); break; case "conjugueur_tab": openConjugueurTab(); break; + case "lexicon_editor": + openLexiconEditor(); + break; + case "dictionaries": + openDictionaries(); + break; // rescan page case "rescanPage": let xPort = dConnx.get(xTab.id); xPort.postMessage({sActionDone: "rescanPage"}); break; @@ -347,16 +366,35 @@ openConjugueurTab(); break; case "conjugueur_window": openConjugueurWindow(); break; - case "lex_editor": - openLexEditor(); + case "lexicon_editor": + openLexiconEditor(); + break; + case "dictionaries": + openDictionaries(); break; } }); + +/* + Tabs +*/ +let nTabLexiconEditor = null; +let nTabDictionaries = null; +let nTabConjugueur = null; + +browser.tabs.onRemoved.addListener(function (nTabId, xRemoveInfo) { + switch (nTabId) { + case nTabLexiconEditor: nTabLexiconEditor = null; break; + case nTabDictionaries: nTabDictionaries = null; break; + case nTabConjugueur: nTabConjugueur = null; break; + } +}); + /* Actions */ @@ -370,34 +408,74 @@ function sendCommandToTab (sCommand, iTab) { let xTabPort = dConnx.get(iTab); xTabPort.postMessage({sActionDone: sCommand, result: null, dInfo: null, bEnd: false, bError: false}); } -function openLexEditor () { - if (bChrome) { - browser.tabs.create({ +function openLexiconEditor (sName="__personal__") { + if (nTabLexiconEditor === null) { + if (bChrome) { + browser.tabs.create({ + url: browser.extension.getURL("panel/lex_editor.html") + }, onLexiconEditorOpened); + return; + } + let xLexEditor = browser.tabs.create({ url: browser.extension.getURL("panel/lex_editor.html") }); - return; + xLexEditor.then(onLexiconEditorOpened, onError); + } + else { + browser.tabs.update(nTabLexiconEditor, {active: true}); + } +} + +function onLexiconEditorOpened (xTab) { + nTabLexiconEditor = xTab.id; +} + +function openDictionaries () { + if (nTabDictionaries === null) { + if (bChrome) { + browser.tabs.create({ + url: browser.extension.getURL("panel/dictionaries.html") + }, onDictionariesOpened); + return; + } + let xLexEditor = browser.tabs.create({ + url: browser.extension.getURL("panel/dictionaries.html") + }); + xLexEditor.then(onDictionariesOpened, onError); + } + else { + browser.tabs.update(nTabDictionaries, {active: true}); } - let xLexEditor = browser.tabs.create({ - url: browser.extension.getURL("panel/lex_editor.html") - }); - xLexEditor.then(onCreated, onError); +} + +function onDictionariesOpened (xTab) { + nTabDictionaries = xTab.id; } function openConjugueurTab () { - if (bChrome) { - browser.tabs.create({ + if (nTabDictionaries === null) { + if (bChrome) { + browser.tabs.create({ + url: browser.extension.getURL("panel/conjugueur.html") + }, onConjugueurOpened); + return; + } + let xConjTab = browser.tabs.create({ url: browser.extension.getURL("panel/conjugueur.html") }); - return; + xConjTab.then(onConjugueurOpened, onError); + } + else { + browser.tabs.update(nTabConjugueur, {active: true}); } - let xConjTab = browser.tabs.create({ - url: browser.extension.getURL("panel/conjugueur.html") - }); - xConjTab.then(onCreated, onError); +} + +function onConjugueurOpened (xTab) { + nTabConjugueur = xTab.id; } function openConjugueurWindow () { if (bChrome) { browser.windows.create({ @@ -412,16 +490,11 @@ url: browser.extension.getURL("panel/conjugueur.html"), type: "popup", width: 710, height: 980 }); - xConjWindow.then(onCreated, onError); } -function onCreated (xWindowInfo) { - //console.log(`Created window: ${xWindowInfo.id}`); -} - -function onError (error) { - console.log(`Error: ${error}`); +function onError (e) { + console.error(e); } Index: gc_lang/fr/webext/gce_worker.js ================================================================== --- gc_lang/fr/webext/gce_worker.js +++ gc_lang/fr/webext/gce_worker.js @@ -318,13 +318,10 @@ //console.log("setDictionary", sDictionary); switch (sDictionary) { case "main": oSpellChecker.setMainDictionary(oDict); break; - case "extended": - oSpellChecker.setExtendedDictionary(oDict); - break; case "community": oSpellChecker.setCommunityDictionary(oDict); break; case "personal": oSpellChecker.setPersonalDictionary(oDict); @@ -340,17 +337,10 @@ postMessage(createResponse("setDictionary", "# Error. SpellChecker not loaded.", dInfo, true)); return; } //console.log("setDictionaryOnOff", sDictionary, bActivate); switch (sDictionary) { - case "extended": - if (bActivate) { - oSpellChecker.activateExtendedDictionary(); - } else { - oSpellChecker.deactivateExtendedDictionary(); - } - break; case "community": if (bActivate) { oSpellChecker.activateCommunityDictionary(); } else { oSpellChecker.deactivateCommunityDictionary(); Index: gc_lang/fr/webext/manifest.json ================================================================== --- gc_lang/fr/webext/manifest.json +++ gc_lang/fr/webext/manifest.json @@ -79,26 +79,24 @@ } ], "commands": { "conjugueur_tab": { - "suggested_key": { - "default": "Ctrl+Shift+6" - }, + "suggested_key": { "default": "Ctrl+Shift+6" }, "description": "Ouvre le conjugueur dans un onglet" }, "conjugueur_window": { - "suggested_key": { - "default": "Ctrl+Shift+7" - }, + "suggested_key": { "default": "Ctrl+Shift+7" }, "description": "Ouvre le conjugueur dans une fenêtre" }, - "lex_editor": { - "suggested_key": { - "default": "Ctrl+Shift+8" - }, + "lexicon_editor": { + "suggested_key": { "default": "Ctrl+Shift+8" }, "description": "Ouvre l’éditeur lexical" + }, + "dictionaries": { + "suggested_key": { "default": "Ctrl+Shift+9" }, + "description": "Ouvre le gestionnaire de dictionnaires communautaires" } }, "web_accessible_resources": [ "content_scripts/panel.css", @@ -116,10 +114,12 @@ "grammalecte/fr/tests_data.json", "img/logo-16.png" ], "permissions": [ + "*://localhost/*", + "*://dic.grammalecte.net/*", "activeTab", "contextMenus", "downloads", "storage" ], ADDED gc_lang/fr/webext/panel/dictionaries.css Index: gc_lang/fr/webext/panel/dictionaries.css ================================================================== --- /dev/null +++ gc_lang/fr/webext/panel/dictionaries.css @@ -0,0 +1,156 @@ +/* + CSS Document + White + Design par Olivier R. +*/ + +* { margin: 0; padding: 0; } +img { border: none; } + + +/* Generic classes */ + +.fleft { float: left; } +.fright { float: right; } +.center { text-align: center; } +.right { text-align: right; } +.left { text-align: left; } +.justify { text-align: justify; } +.hidden { display: none; } +.clearer { clear: both; font-size: 0; height: 0; } + +body { + background: hsl(0, 0%, 100%) url(../img/lines.png); + font: normal 16px "Trebuchet MS", "Fira Sans", "Liberation Sans", sans-serif; + color: #505050; +} + +.inbox { + width: 800px; + margin: 20px auto 10px auto; + padding: 10px 30px 30px 30px; + background: hsl(0, 0%, 100%); + border: 2px solid hsl(210, 0%, 90%); + border-radius: 20px; +} + +h1 { + margin: 5px 0 5px 0; + color: hsl(210, 50%, 50%); + font: bold 30px "Trebuchet MS", "Fira Sans", "Liberation Sans", sans-serif; + text-align: center; +} +h2 { + margin: 10px 0 2px 0; + color: hsl(0, 50%, 50%); + font: bold 20px "Trebuchet MS", "Fira Sans", "Liberation Sans", sans-serif; +} + + +/* + Main buttons +*/ + +ul { + margin-left: 30px; +} + +input[type=text].large { + display: inline-block; + width: 250px; + padding: 5px 10px; + border: 2px solid hsl(0, 0%, 80%); + border-radius: 3px; + height: 24px; + background: transparent; + font: normal 20px Tahoma, "Ubuntu Condensed"; + color: hsl(0, 0%, 20%); +} + +input[type=text].medium { + display: inline-block; + width: 175px; + padding: 2px 5px; + border: 2px solid hsl(0, 0%, 80%); + border-radius: 3px; + height: 20px; + background: transparent; + font: normal 18px Tahoma, "Ubuntu Condensed"; + color: hsl(0, 0%, 20%); +} + +input[placeholder] { + color: hsl(0, 0%, 50%); +} + + +.dic_button { + margin: 2px; + display: inline-block; +} +.dic_button_close { + display: inline-block; + padding: 1px 5px; + background-color: hsl(0, 50%, 50%); + color: hsl(0, 90%, 90%); + border-style: solid; + border-width: 1px 0 1px 1px; + border-color: hsl(0, 50%, 45%); + border-radius: 3px 0 0 3px; + cursor: pointer; +} +.dic_button_label { + display: inline-block; + padding: 1px 10px; + background-color: hsl(210, 50%, 94%); + border-style: solid; + border-width: 1px 1px 1px 0; + border-color: hsl(210, 50%, 70%); + border-radius: 0 3px 3px 0; +} + +.apply { + display: none; + float: right; + padding: 2px 10px; + background: hsl(120, 50%, 30%); + color: hsl(120, 50%, 96%); + cursor: pointer; + border-radius: 3px; +} + + +/* + Table +*/ +#wait_progress { + width: 100%; + height: 4px; +} + +table { + border: 1px solid hsl(210, 10%, 50%); + width: 100%; + font-size: 14px; +} +th { + padding: 5px 10px; + border-left: 1px solid hsl(210, 10%, 90%); + text-align: left; +} +td { + padding: 0 10px; + vertical-align: top; +} +.delete_entry { + cursor: pointer; + font-weight: bold; + color: hsl(0, 100%, 50%); +} +.select_entry { + cursor: pointer; + background-color: hsl(210, 50%, 30%); + color: hsl(210, 50%, 100%); + border-radius: 3px; + text-align: center; +} ADDED gc_lang/fr/webext/panel/dictionaries.html Index: gc_lang/fr/webext/panel/dictionaries.html ================================================================== --- /dev/null +++ gc_lang/fr/webext/panel/dictionaries.html @@ -0,0 +1,38 @@ + + +
+ +[Aucun]
+ + +
Nombre d’entrées : 0.
-Il est déconseillé d’utiliser la catégorie ‹Autre› pour générer autre chose que des noms, des adjectifs, des noms propres, des verbes et des adverbes. Il n’y a aucune garantie que les étiquettes pour les autres catégories, notamment les mots grammaticaux, ne changeront pas.