Grammalecte  Check-in [a56f46447a]

Overview
Comment:[build][core][lo][fx][fr] change data structure for conjugation tool
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk | fr | core | build | major_change | fx | lo
Files: files | file ages | folders
SHA3-256: a56f46447a36260199b02a46075211c69979e97a57c21dcf3d074530fff8344c
User & Date: olr on 2021-02-05 21:07:08
Other Links: manifest | tags
Context
2021-02-06
01:52
[fr] ajustements check-in: 111afef718 user: olr tags: trunk, fr
2021-02-05
21:07
[build][core][lo][fx][fr] change data structure for conjugation tool check-in: a56f46447a user: olr tags: trunk, fr, core, build, major_change, fx, lo
19:41
[core][fr] fix previous commit check-in: 47944f336f user: olr tags: trunk, fr, core
Changes

Modified doc/API.txt from [d7c5950527] to [8e533ff8ba].

45
46
47
48
49
50
51

52

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67




68
69

70
71
72
73
74
75
76
45
46
47
48
49
50
51
52

53
54
55
56
57
58
59
60
61
62
63
64




65
66
67
68
69

70
71
72
73
74
75
76
77







+
-
+











-
-
-
-
+
+
+
+

-
+







    .isVerb(word)
        Returns True is word exists in the list of verb (infinite form)

    .getConj(verb, tense, who)
        Returns conjugation of verb with subject who at tense (can be an empty string)
            tense has to be:
                :Y      infinitif
                :P      participe présent
                :PQ     participes passés et présent
                :Q      participes passés
                :Ip     indicatif présent
                :Iq     imparfait
                :Is     passé simple
                :If     futur
                :K      conditionnel
                :Sp     subjonctif présent
                :Sq     subjonctif imparfait
                :E      impératif

            who has to be:
                :P      participe présent
                :Q1     participe passé masculin singulier ou invariable
                :Q2     participe passé masculin pluriel
                :Q3     participe passé féminin singulier
                :Q4     participe passé féminin pluriel
                :m:s    participe passé masculin singulier ou invariable
                :m:p    participe passé masculin pluriel
                :f:s    participe passé féminin singulier
                :f:p    participe passé féminin pluriel

                :1s     première personne au singulier 
                :1s     première personne au singulier
                        (1ś pour une éventuelle forme interrogative spécifique)
                :2s     deuxième personne au singulier
                :3s     troisième personne au singulier
                :1p     première personne au pluriel
                :2p     deuxième personne au pluriel
                :3p     troisième personne au pluriel

Modified gc_lang/fr/build_data.py from [3eb0f89147] to [94a1ff7b31].

1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19


20
21
22
23
24
25
26












+






-
-







#!python3

# FRENCH DATA BUILDER
#
# by Olivier R.
# License: MPL 2

import json
import os
import itertools
import traceback
import platform
import importlib

import graphspell.ibdawg as ibdawg
from graphspell.echo import echo
from graphspell.str_transform import defineSuffixCode
import graphspell.tokenizer as tkz

import gc_lang.fr.modules.conj as conj


oDict = None


class cd:
    """Context manager for changing the current working directory"""
    def __init__ (self, newPath):
70
71
72
73
74
75
76
77

78
79
80

81
82
83
84
85

86
87
88
89
90
91
92
93
94
95
96
97


98
99
100
101
102
103
104
69
70
71
72
73
74
75

76
77
78

79
80
81
82
83

84
85
86
87
88
89
90
91
92
93
94
95

96
97
98
99
100
101
102
103
104







-
+


-
+




-
+











-
+
+







    print("(Python et JavaScript)"  if bJS  else "(Python seulement)")
    dVerb = {}
    lVinfo = []; dVinfo = {}; nVinfo = 0
    lTags = []; dTags = {}; nTags = 0
    dVerbNames = {}

    dPatternList = {
        ":PQ": [], ":Ip": [], ":Iq": [], ":Is": [], ":If": [], ":K": [], ":Sp": [], ":Sq": [], ":E": []
        ":P": [], ":Q": [], ":Ip": [], ":Iq": [], ":Is": [], ":If": [], ":K": [], ":Sp": [], ":Sq": [], ":E": []
    }
    dTrad = {
        "infi": ":Y", "ppre": ":PQ", "ppas": ":PQ",
        "infi": ":Y", "ppre": ":P", "ppas": ":Q",
        "ipre": ":Ip", "iimp": ":Iq", "ipsi": ":Is", "ifut": ":If",
        "spre": ":Sp", "simp": ":Sq",
        "cond": ":K", "impe": ":E",
        "1sg": ":1s", "2sg": ":2s", "3sg": ":3s", "1pl": ":1p", "2pl": ":2p", "3pl": ":3p", "1isg": ":1ś",
        "mas sg": ":Q1", "mas pl": ":Q2", "mas inv": ":Q1", "fem sg": ":Q3", "fem pl": ":Q4", "epi inv": ":Q1"
        "mas sg": ":m:s", "mas pl": ":m:p", "mas inv": ":m:s", "fem sg": ":f:s", "fem pl": ":f:p", "epi inv": ":m:s"
    }

    loadDictionary()

    # read lexicon
    nStop = 0
    for n, sLine in enumerate(readFile(sp+"/data/dictConj.txt")):
        nTab = sLine.count("\t")
        if nTab == 1:
            # new entry
            sLemma, sVinfo = sLine.split("\t")
            dConj = {   ":PQ": { ":P": "", ":Q1": "", ":Q2": "", ":Q3": "", ":Q4": ""},
            dConj = {   ":P": { ":P": "" },
                        ":Q": { ":m:s": "", ":f:s": "", ":m:p": "", ":f:p": "" },
                        ":Ip": { ":1s": "", ":2s": "", ":3s": "", ":1p": "", ":2p": "", ":3p": "", ":1ś": "" },
                        ":Iq": { ":1s": "", ":2s": "", ":3s": "", ":1p": "", ":2p": "", ":3p": "" },
                        ":Is": { ":1s": "", ":2s": "", ":3s": "", ":1p": "", ":2p": "", ":3p": "" },
                        ":If": { ":1s": "", ":2s": "", ":3s": "", ":1p": "", ":2p": "", ":3p": "" },
                        ":K":  { ":1s": "", ":2s": "", ":3s": "", ":1p": "", ":2p": "", ":3p": "" },
                        ":Sp": { ":1s": "", ":2s": "", ":3s": "", ":1p": "", ":2p": "", ":3p": "", ":1ś": "" },
                        ":Sq": { ":1s": "", ":2s": "", ":3s": "", ":1p": "", ":2p": "", ":3p": "", ":1ś": "" },
114
115
116
117
118
119
120
121

122
123
124
125
126
127
128
114
115
116
117
118
119
120

121
122
123
124
125
126
127
128







-
+







                    dVerbNames[sLemma] = { sLemma }
                    break
        elif nTab == 2:
            # flexion
            _, sTag, sFlex = sLine.split("\t")
            if sTag.count(" ") == 0:
                if sTag == "ppre":
                    dConj[":PQ"][":P"] = defineSuffixCode(sLemma, sFlex)
                    dConj[":P"][":P"] = defineSuffixCode(sLemma, sFlex)
            else:
                try:
                    mode, g = sTag.split(maxsplit=1)
                    mode = dTrad[mode]
                    g = dTrad[g]
                    if dConj[mode][g] == "":
                        dConj[mode][g] = defineSuffixCode(sLemma, sFlex)
142
143
144
145
146
147
148
149

150
151
152
153
154
155
156
142
143
144
145
146
147
148

149
150
151
152
153
154
155
156







-
+







        elif sLine == "$":
            # we store the dictionary of rules for this lemma
            if dConj[":Ip"][":1ś"] == "2è":
                dConj[":Ip"][":1ś"] = "2é"
            elif sLemma == "pouvoir":
                dConj[":Ip"][":1ś"] = "6uis"
            lConjTags = []
            for sTense in [":PQ", ":Ip", ":Iq", ":Is", ":If", ":K", ":Sp", ":Sq", ":E"]:
            for sTense in [":P", ":Q", ":Ip", ":Iq", ":Is", ":If", ":K", ":Sp", ":Sq", ":E"]:
                bFound = False
                for i, d in enumerate(dPatternList[sTense]):
                    if dConj[sTense] == d:
                        bFound = True
                        lConjTags.append(i)
                        break
                if not bFound:
285
286
287
288
289
290
291


292
293
294
295
296
297
298
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300







+
+








def makePhonetTable (sp, bJS=False):
    print("> Correspondances phonétiques ", end="")
    print("(Python et JavaScript)"  if bJS  else "(Python seulement)")

    loadDictionary()

    conj = importlib.import_module("gc_lang.fr.modules.conj")

    # set of homophonic words
    lSet = []
    for sLine in readFile(sp+"/data/phonet_simil.txt"):
        lWord = sLine.split()
        for sWord in lWord:
            if sWord.endswith("er") and conj.isVerb(sWord):
                lWord.extend(conj.getConjSimilInfiV1(sWord))
376
377
378
379
380
381
382
383
384


385
378
379
380
381
382
383
384


385
386
387







-
-
+
+

    print("========== Build Hunspell dictionaries ==========")
    makeDictionaries(spLaunch, dVars['oxt_version'])


def after (spLaunch, dVars, bJS=False):
    print("========== Build French data ==========")
    makeMfsp(spLaunch, bJS)
    makePhonetTable(spLaunch, bJS)
    makeConj(spLaunch, bJS)
    makeConj(spLaunch, bJS)
    makePhonetTable(spLaunch, bJS)
    #makeLocutions(spLaunch, bJS)

Modified gc_lang/fr/modules-js/conj.js from [fd6082c64b] to [0c226f31fc].

48
49
50
51
52
53
54
55

56
57
58
59
60
61
62
48
49
50
51
52
53
54

55
56
57
58
59
60
61
62







-
+







    _dImpePro: new Map ([ [":2s", "-toi"], [":1p", "-nous"], [":2p", "-vous"] ]),
    _dImpeProNeg: new Map ([ [":2s", "ne te "], [":1p", "ne nous "], [":2p", "ne vous "] ]),
    _dImpeProEn: new Map ([ [":2s", "-t’en"], [":1p", "-nous-en"], [":2p", "-vous-en"] ]),
    _dImpeProNegEn: new Map ([ [":2s", "ne t’en "], [":1p", "ne nous en "], [":2p", "ne vous en "] ]),

    _dGroup: new Map ([ ["0", "auxiliaire"], ["1", "1ᵉʳ groupe"], ["2", "2ᵉ groupe"], ["3", "3ᵉ groupe"] ]),

    _dTenseIdx: new Map ([ [":PQ", 0], [":Ip", 1], [":Iq", 2], [":Is", 3], [":If", 4], [":K", 5], [":Sp", 6], [":Sq", 7], [":E", 8] ]),
    _dTenseIdx: new Map ([ [":P", 0], [":Q", 1], [":Ip", 2], [":Iq", 3], [":Is", 4], [":If", 5], [":K", 6], [":Sp", 7], [":Sq", 8], [":E", 9] ]),

    isVerb: function (sVerb) {
        return this._dVerb.hasOwnProperty(sVerb);
    },

    getConj: function (sVerb, sTense, sWho) {
        // returns conjugation (can be an empty string)
100
101
102
103
104
105
106
107
108
109



110
111
112


113
114
115


116
117
118
119
120
121
122
100
101
102
103
104
105
106



107
108
109
110


111
112
113


114
115
116
117
118
119
120
121
122







-
-
-
+
+
+

-
-
+
+

-
-
+
+







        if (this._dVerbNames.hasOwnProperty(sVerb)) {
            // there are names derivated from the verb
            return this._dVerbNames[sVerb];
        } else {
            // we suggest past participles
            let tTags = this._getTags(sVerb);
            if (tTags) {
                let aSugg = [ this._getConjWithTags(sVerb, tTags, ":PQ", ":Q1") ];
                if (this._hasConjWithTags(tTags, ":PQ", ":Q2")) {
                    aSugg.push(this._getConjWithTags(sVerb, tTags, ":PQ", ":Q2"));
                let aSugg = [ this._getConjWithTags(sVerb, tTags, ":Q", ":m:s") ];
                if (this._hasConjWithTags(tTags, ":Q", ":f:s")) {
                    aSugg.push(this._getConjWithTags(sVerb, tTags, ":Q", ":f:s"));
                }
                if (this._hasConjWithTags(tTags, ":PQ", ":Q3")) {
                    aSugg.push(this._getConjWithTags(sVerb, tTags, ":PQ", ":Q3"));
                if (this._hasConjWithTags(tTags, ":Q", ":m:p")) {
                    aSugg.push(this._getConjWithTags(sVerb, tTags, ":Q", ":m:p"));
                }
                if (this._hasConjWithTags(tTags, ":PQ", ":Q4")) {
                    aSugg.push(this._getConjWithTags(sVerb, tTags, ":PQ", ":Q4"));
                if (this._hasConjWithTags(tTags, ":Q", ":f:p")) {
                    aSugg.push(this._getConjWithTags(sVerb, tTags, ":Q", ":f:p"));
                }
                // if there is only one past participle (epi inv), unreliable.
                return (aSugg.length > 1) ? aSugg : [];
            }
            return [];
        }
    },
210
211
212
213
214
215
216
217

218
219
220
221

222
223
224
225
226
227
228




229
230
231
232
233
234
235
210
211
212
213
214
215
216

217
218
219
220

221
222
223
224




225
226
227
228
229
230
231
232
233
234
235







-
+



-
+



-
-
-
-
+
+
+
+







        } else {
            this.sProLabel = "# erreur #";
            this.nPronominable = -1;
        }
        this.dConj = new Map ([
            [":Y", new Map ([
                ["label", "Infinitif"],
                [":", sVerb]
                [":Y", sVerb]
            ])],
            [":P", new Map ([
                ["label", "Participe présent"],
                [":", conj._getConjWithTags(sVerb, this._tTags, ":PQ", ":P")]
                [":P", conj._getConjWithTags(sVerb, this._tTags, ":P", ":P")]
            ])],
            [":Q", new Map ([
                ["label", "Participes passés"],
                [":Q1", conj._getConjWithTags(sVerb, this._tTags, ":PQ", ":Q1")],
                [":Q2", conj._getConjWithTags(sVerb, this._tTags, ":PQ", ":Q2")],
                [":Q3", conj._getConjWithTags(sVerb, this._tTags, ":PQ", ":Q3")],
                [":Q4", conj._getConjWithTags(sVerb, this._tTags, ":PQ", ":Q4")],
                [":m:s", conj._getConjWithTags(sVerb, this._tTags, ":Q", ":m:s")],
                [":f:s", conj._getConjWithTags(sVerb, this._tTags, ":Q", ":f:s")],
                [":m:p", conj._getConjWithTags(sVerb, this._tTags, ":Q", ":m:p")],
                [":f:p", conj._getConjWithTags(sVerb, this._tTags, ":Q", ":f:p")],
            ])],
            [":Ip", new Map ([
                ["label", "Présent"],
                [":1s", conj._getConjWithTags(sVerb, this._tTags, ":Ip", ":1s")],
                [":1ś", conj._getConjWithTags(sVerb, this._tTags, ":Ip", ":1ś")],
                [":2s", conj._getConjWithTags(sVerb, this._tTags, ":Ip", ":2s")],
                [":3s", conj._getConjWithTags(sVerb, this._tTags, ":Ip", ":3s")],
357
358
359
360
361
362
363
364

365
366
367
368
369

370
371

372
373
374
375
376
377
378
357
358
359
360
361
362
363

364
365
366
367
368

369
370

371
372
373
374
375
376
377
378







-
+




-
+

-
+







    }

    participePasse (sWho) {
        return this.dConj.get(":Q").get(sWho);
    }

    participePresent (bPro, bNeg, bTpsCo, bInt, bFem) {
        if (!this.dConj.get(":P").get(":")) {
        if (!this.dConj.get(":P").get(":P")) {
            return "";
        }
        let sPartPre;
        if (bTpsCo) {
            sPartPre = (!bPro) ? conj._getConjWithTags(this.sVerbAux, this._tTagsAux, ":PQ", ":P") : conj.getConj("être", ":PQ", ":P");
            sPartPre = (!bPro) ? conj._getConjWithTags(this.sVerbAux, this._tTagsAux, ":P", ":P") : conj.getConj("être", ":P", ":P");
        } else {
            sPartPre = this.dConj.get(":P").get(":");
            sPartPre = this.dConj.get(":P").get(":P");
        }
        if (sPartPre === "") {
            return "";
        }
        let bEli = conj._zStartVoy.test(sPartPre);
        if (bPro) {
            if (this.bProWithEn) {
488
489
490
491
492
493
494
495

496
497
498

499
500
501

502
503

504
505
506
507
508
509
510
511
512
513
514
515
516




517
518
519
520
521
522
523
488
489
490
491
492
493
494

495
496
497

498
499
500

501
502

503
504
505
506
507
508
509
510
511
512




513
514
515
516
517
518
519
520
521
522
523







-
+


-
+


-
+

-
+









-
-
-
-
+
+
+
+







            return sImpe + " " + this._seekPpas(bPro, bFem, sWho.endsWith("p") || this._sRawInfo[5] == "r");
        }
        return sImpe;
    }

    _seekPpas (bPro, bFem, bPlur) {
        if (!bPro && this.sVerbAux == "avoir") {
            return this.dConj.get(":Q").get(":Q1");
            return this.dConj.get(":Q").get(":m:s");
        }
        if (!bFem) {
            return (bPlur && this.dConj.get(":Q").get(":Q2")) ? this.dConj.get(":Q").get(":Q2") : this.dConj.get(":Q").get(":Q1");
            return (bPlur && this.dConj.get(":Q").get(":f:s")) ? this.dConj.get(":Q").get(":f:s") : this.dConj.get(":Q").get(":m:s");
        }
        if (!bPlur) {
            return (this.dConj.get(":Q").get(":Q3")) ? this.dConj.get(":Q").get(":Q3") : this.dConj.get(":Q").get(":Q1");
            return (this.dConj.get(":Q").get(":m:p")) ? this.dConj.get(":Q").get(":m:p") : this.dConj.get(":Q").get(":m:s");
        }
        return (this.dConj.get(":Q").get(":Q4")) ? this.dConj.get(":Q").get(":Q4") : this.dConj.get(":Q").get(":Q1");
        return (this.dConj.get(":Q").get(":f:p")) ? this.dConj.get(":Q").get(":f:p") : this.dConj.get(":Q").get(":m:s");
    }

    createConjTable (bPro=false, bNeg=false, bTpsCo=false, bInt=false, bFem=false) {
        let oConjTable = {
            "t_infi":   "Infinitif",
            "infi":     this.infinitif(bPro, bNeg, bTpsCo, bInt, bFem),
            "t_ppre":   "Participe présent",
            "ppre":     this.participePresent(bPro, bNeg, bTpsCo, bInt, bFem),
            "t_ppas":   "Participes passés",
            "ppas1":    this.participePasse(":Q1"),
            "ppas2":    this.participePasse(":Q2"),
            "ppas3":    this.participePasse(":Q3"),
            "ppas4":    this.participePasse(":Q4"),
            "ppas1":    this.participePasse(":m:s"),
            "ppas2":    this.participePasse(":f:s"),
            "ppas3":    this.participePasse(":m:p"),
            "ppas4":    this.participePasse(":f:p"),
            "t_imp":    "Impératif",
            "t_impe":   (bInt) ? "" : ((!bTpsCo) ? "Présent" : "Passé"),
            "impe1":    (!bInt) ? this.imperatif(":2s", bPro, bNeg, bTpsCo, bFem) : "",
            "impe2":    (!bInt) ? this.imperatif(":1p", bPro, bNeg, bTpsCo, bFem) : "",
            "impe3":    (!bInt) ? this.imperatif(":2p", bPro, bNeg, bTpsCo, bFem) : "",
            "t_indi":   "Indicatif",
            "t_ipre":   (!bTpsCo) ? "Présent"      : "Passé composé",

Modified gc_lang/fr/modules-js/conj_data.json from [47ac86593a] to [d7e47e8b98].

cannot compute difference between binary files

Modified gc_lang/fr/modules-js/gce_suggestions.js from [e713e67341] to [dddc903a64].

97
98
99
100
101
102
103
104
105
106
107




108
109
110

111
112
113


114
115

116
117
118
119


120
121

122
123
124
125


126
127

128
129
130
131


132
133
134
135


136
137
138

139
140
141
142
143
144
145
97
98
99
100
101
102
103




104
105
106
107
108
109

110
111


112
113
114

115
116
117


118
119
120

121
122
123


124
125
126

127
128
129


130
131
132
133


134
135
136
137

138
139
140
141
142
143
144
145







-
-
-
-
+
+
+
+


-
+

-
-
+
+

-
+


-
-
+
+

-
+


-
-
+
+

-
+


-
-
+
+


-
-
+
+


-
+








function suggVerbPpas (sFlex, sWhat=null) {
    let aSugg = new Set();
    for (let sStem of gc_engine.oSpellChecker.getLemma(sFlex)) {
        let tTags = conj._getTags(sStem);
        if (tTags) {
            if (!sWhat) {
                aSugg.add(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1"));
                aSugg.add(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q2"));
                aSugg.add(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q3"));
                aSugg.add(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q4"));
                aSugg.add(conj._getConjWithTags(sStem, tTags, ":Q", ":m:s"));
                aSugg.add(conj._getConjWithTags(sStem, tTags, ":Q", ":m:p"));
                aSugg.add(conj._getConjWithTags(sStem, tTags, ":Q", ":f:s"));
                aSugg.add(conj._getConjWithTags(sStem, tTags, ":Q", ":f:p"));
                aSugg.delete("");
            } else if (sWhat === ":m:s") {
                aSugg.add(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1"));
                aSugg.add(conj._getConjWithTags(sStem, tTags, ":Q", ":m:s"));
            } else if (sWhat === ":m:p") {
                if (conj._hasConjWithTags(tTags, ":PQ", ":Q2")) {
                    aSugg.add(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q2"));
                if (conj._hasConjWithTags(tTags, ":Q", ":m:p")) {
                    aSugg.add(conj._getConjWithTags(sStem, tTags, ":Q", ":m:p"));
                } else {
                    aSugg.add(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1"));
                    aSugg.add(conj._getConjWithTags(sStem, tTags, ":Q", ":m:s"));
                }
            } else if (sWhat === ":f:s") {
                if (conj._hasConjWithTags(tTags, ":PQ", ":Q3")) {
                    aSugg.add(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q3"));
                if (conj._hasConjWithTags(tTags, ":Q", ":f:s")) {
                    aSugg.add(conj._getConjWithTags(sStem, tTags, ":Q", ":f:s"));
                } else {
                    aSugg.add(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1"));
                    aSugg.add(conj._getConjWithTags(sStem, tTags, ":Q", ":m:s"));
                }
            } else if (sWhat === ":f:p") {
                if (conj._hasConjWithTags(tTags, ":PQ", ":Q4")) {
                    aSugg.add(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q4"));
                if (conj._hasConjWithTags(tTags, ":Q", ":f:p")) {
                    aSugg.add(conj._getConjWithTags(sStem, tTags, ":Q", ":f:p"));
                } else {
                    aSugg.add(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1"));
                    aSugg.add(conj._getConjWithTags(sStem, tTags, ":Q", ":m:s"));
                }
            } else if (sWhat === ":s") {
                aSugg.add(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1"));
                aSugg.add(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q3"));
                aSugg.add(conj._getConjWithTags(sStem, tTags, ":Q", ":m:s"));
                aSugg.add(conj._getConjWithTags(sStem, tTags, ":Q", ":f:s"));
                aSugg.delete("");
            } else if (sWhat === ":p") {
                aSugg.add(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q2"));
                aSugg.add(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q4"));
                aSugg.add(conj._getConjWithTags(sStem, tTags, ":Q", ":m:p"));
                aSugg.add(conj._getConjWithTags(sStem, tTags, ":Q", ":f:p"));
                aSugg.delete("");
            } else {
                aSugg.add(conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1"));
                aSugg.add(conj._getConjWithTags(sStem, tTags, ":Q", ":m:s"));
            }
        }
    }
    if (aSugg.size > 0) {
        return Array.from(aSugg).join("|");
    }
    return "";
168
169
170
171
172
173
174
175

176
177
178
179
180
181
182
168
169
170
171
172
173
174

175
176
177
178
179
180
181
182







-
+







                if (conj.hasConj(sStem, sTense, sWho)) {
                    aSugg.add(conj.getConj(sStem, sTense, sWho));
                }
            }
        }
        else {
            for (let [sTense, ] of lTenses) {
                for (let [sWho, ] of [ ...sMorph.matchAll(/:[123][sp]/g) ]) {
                for (let [sWho, ] of [ ...sMorph.matchAll(/:(?:[123][sp]|P|Y)/g) ]) {
                    if (conj.hasConj(sStem, sTense, sWho)) {
                        aSugg.add(conj.getConj(sStem, sTense, sWho));
                    }
                }
            }
        }
    }
354
355
356
357
358
359
360
361

362
363
364

365
366
367
368
369
370
371
354
355
356
357
358
359
360

361
362
363

364
365
366
367
368
369
370
371







-
+


-
+







                if (mfsp.isMasForm(sStem)) {
                    aSugg.add(sStem);
                }
            }
        } else {
            // a verb
            let sVerb = cregex.getLemmaOfMorph(sMorph);
            if (conj.hasConj(sVerb, ":PQ", ":Q1") && conj.hasConj(sVerb, ":PQ", ":Q3")) {
            if (conj.hasConj(sVerb, ":Q", ":m:s") && conj.hasConj(sVerb, ":Q", ":f:s")) {
                // We also check if the verb has a feminine form.
                // If not, we consider it’s better to not suggest the masculine one, as it can be considered invariable.
                aSugg.add(conj.getConj(sVerb, ":PQ", ":Q1"));
                aSugg.add(conj.getConj(sVerb, ":Q", ":m:s"));
            }
        }
    }
    if (bSuggSimil) {
        for (let e of phonet.selectSimil(sFlex, ":m:[si]")) {
            aSugg.add(e);
        }
390
391
392
393
394
395
396
397
398
399
400




401
402
403
404
405
406
407
390
391
392
393
394
395
396




397
398
399
400
401
402
403
404
405
406
407







-
-
-
-
+
+
+
+







                if (mfsp.isMasForm(sStem)) {
                    aSugg.add(suggPlur(sStem, true));
                }
            }
        } else {
            // a verb
            let sVerb = cregex.getLemmaOfMorph(sMorph);
            if (conj.hasConj(sVerb, ":PQ", ":Q2")) {
                aSugg.add(conj.getConj(sVerb, ":PQ", ":Q2"));
            } else if (conj.hasConj(sVerb, ":PQ", ":Q1")) {
                let sSugg = conj.getConj(sVerb, ":PQ", ":Q1");
            if (conj.hasConj(sVerb, ":Q", ":m:p")) {
                aSugg.add(conj.getConj(sVerb, ":Q", ":m:p"));
            } else if (conj.hasConj(sVerb, ":Q", ":m:s")) {
                let sSugg = conj.getConj(sVerb, ":Q", ":m:s");
                // it is necessary to filter these flexions, like “succédé” or “agi” that are not masculine plural
                if (sSugg.endsWith("s")) {
                    aSugg.add(sSugg);
                }
            }
        }
    }
431
432
433
434
435
436
437
438
439


440
441
442
443
444
445
446
431
432
433
434
435
436
437


438
439
440
441
442
443
444
445
446







-
-
+
+







                if (mfsp.isMasForm(sStem)) {
                    mfsp.getFemForm(sStem, false).forEach(function(x) { aSugg.add(x); });
                }
            }
        } else {
            // a verb
            let sVerb = cregex.getLemmaOfMorph(sMorph);
            if (conj.hasConj(sVerb, ":PQ", ":Q3")) {
                aSugg.add(conj.getConj(sVerb, ":PQ", ":Q3"));
            if (conj.hasConj(sVerb, ":Q", ":f:s")) {
                aSugg.add(conj.getConj(sVerb, ":Q", ":f:s"));
            }
        }
    }
    if (bSuggSimil) {
        for (let e of phonet.selectSimil(sFlex, ":f:[si]")) {
            aSugg.add(e);
        }
465
466
467
468
469
470
471
472
473


474
475
476
477
478
479
480
465
466
467
468
469
470
471


472
473
474
475
476
477
478
479
480







-
-
+
+







                if (mfsp.isMasForm(sStem)) {
                    mfsp.getFemForm(sStem, true).forEach(function(x) { aSugg.add(x); });
                }
            }
        } else {
            // a verb
            let sVerb = cregex.getLemmaOfMorph(sMorph);
            if (conj.hasConj(sVerb, ":PQ", ":Q4")) {
                aSugg.add(conj.getConj(sVerb, ":PQ", ":Q4"));
            if (conj.hasConj(sVerb, ":Q", ":f:p")) {
                aSugg.add(conj.getConj(sVerb, ":Q", ":f:p"));
            }
        }
    }
    if (bSuggSimil) {
        for (let e of phonet.selectSimil(sFlex, ":f:[pi]")) {
            aSugg.add(e);
        }
558
559
560
561
562
563
564
565

566
567
568
569
570
571
572
573
574
575
576
577

578
579
580
581
582
583
584
558
559
560
561
562
563
564

565
566
567
568
569
570
571
572
573
574
575
576

577
578
579
580
581
582
583
584







-
+











-
+







        return oTokenDst["sValue"];
    }
    return "";
}

function hasFemForm (sFlex) {
    for (let sStem of gc_engine.oSpellChecker.getLemma(sFlex)) {
        if (mfsp.isMasForm(sStem) || conj.hasConj(sStem, ":PQ", ":Q3")) {
        if (mfsp.isMasForm(sStem) || conj.hasConj(sStem, ":Q", ":f:s")) {
            return true;
        }
    }
    if (phonet.hasSimil(sFlex, ":f")) {
        return true;
    }
    return false;
}

function hasMasForm (sFlex) {
    for (let sStem of gc_engine.oSpellChecker.getLemma(sFlex)) {
        if (mfsp.isMasForm(sStem) || conj.hasConj(sStem, ":PQ", ":Q1")) {
        if (mfsp.isMasForm(sStem) || conj.hasConj(sStem, ":Q", ":m:s")) {
            // what has a feminine form also has a masculine form
            return true;
        }
    }
    if (phonet.hasSimil(sFlex, ":m")) {
        return true;
    }

Modified gc_lang/fr/modules-js/phonet_data.json from [670718f9b4] to [b360af44eb].

cannot compute difference between binary files

Modified gc_lang/fr/modules/conj.py from [af72bab83b] to [bb0326be30].

24
25
26
27
28
29
30
31

32
33
34
35
36
37
38
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38







-
+







_dImpePro = { ":2s": "-toi", ":1p": "-nous", ":2p": "-vous" }
_dImpeProNeg = { ":2s": "ne te ", ":1p": "ne nous ", ":2p": "ne vous " }
_dImpeProEn = { ":2s": "-t’en", ":1p": "-nous-en", ":2p": "-vous-en" }
_dImpeProNegEn = { ":2s": "ne t’en ", ":1p": "ne nous en ", ":2p": "ne vous en " }

_dGroup = { "0": "auxiliaire", "1": "1ᵉʳ groupe", "2": "2ᵉ groupe", "3": "3ᵉ groupe" }

_dTenseIdx = { ":PQ": 0, ":Ip": 1, ":Iq": 2, ":Is": 3, ":If": 4, ":K": 5, ":Sp": 6, ":Sq": 7, ":E": 8 }
_dTenseIdx = { ":P": 0, ":Q": 1, ":Ip": 2, ":Iq": 3, ":Is": 4, ":If": 5, ":K": 6, ":Sp": 7, ":Sq": 8, ":E": 9 }



def isVerb (sVerb):
    "return True if it’s a existing verb"
    return sVerb in _dVerb

67
68
69
70
71
72
73
74
75
76
77
78
79
80







81
82
83
84
85
86
87
67
68
69
70
71
72
73







74
75
76
77
78
79
80
81
82
83
84
85
86
87







-
-
-
-
-
-
-
+
+
+
+
+
+
+







    if sVerb in _dVerbNames:
        # there are names derivated from the verb
        return list(_dVerbNames[sVerb])
    else:
        # we suggest past participles
        tTags = _getTags(sVerb)
        if tTags:
            aSugg = [ _getConjWithTags(sVerb, tTags, ":PQ", ":Q1") ]
            if _hasConjWithTags(tTags, ":PQ", ":Q2"):
                aSugg.append(_getConjWithTags(sVerb, tTags, ":PQ", ":Q2"))
            if _hasConjWithTags(tTags, ":PQ", ":Q3"):
                aSugg.append(_getConjWithTags(sVerb, tTags, ":PQ", ":Q3"))
            if _hasConjWithTags(tTags, ":PQ", ":Q4"):
                aSugg.append(_getConjWithTags(sVerb, tTags, ":PQ", ":Q4"))
            aSugg = [ _getConjWithTags(sVerb, tTags, ":Q", ":m:s") ]
            if _hasConjWithTags(tTags, ":Q", ":f:s"):
                aSugg.append(_getConjWithTags(sVerb, tTags, ":Q", ":f:s"))
            if _hasConjWithTags(tTags, ":Q", ":m:p"):
                aSugg.append(_getConjWithTags(sVerb, tTags, ":Q", ":m:p"))
            if _hasConjWithTags(tTags, ":Q", ":f:p"):
                aSugg.append(_getConjWithTags(sVerb, tTags, ":Q", ":f:p"))
            # if there is only one past participle (epi inv), unreliable.
            return aSugg  if len(aSugg) > 1  else []
        return []


def getConjSimilInfiV1 (sInfi):
    "returns verbal forms phonetically similar to infinitive form (for verb in group 1)"
176
177
178
179
180
181
182
183

184
185
186
187

188
189
190
191
192
193
194




195
196
197
198
199
200
201
176
177
178
179
180
181
182

183
184
185
186

187
188
189
190




191
192
193
194
195
196
197
198
199
200
201







-
+



-
+



-
-
-
-
+
+
+
+







            self.nPronominable = 2
        else:
            self.sProLabel = "# erreur #"
            self.nPronominable = -1
        self.dConj = {
            ":Y": {
                "label": "Infinitif",
                ":": sVerb,
                ":Y": sVerb,
            },
            ":P": {
                "label": "Participe présent",
                ":": _getConjWithTags(sVerb, self._tTags, ":PQ", ":P"),
                ":P": _getConjWithTags(sVerb, self._tTags, ":P", ":P"),
            },
            ":Q": {
                "label": "Participes passés",
                ":Q1": _getConjWithTags(sVerb, self._tTags, ":PQ", ":Q1"),
                ":Q2": _getConjWithTags(sVerb, self._tTags, ":PQ", ":Q2"),
                ":Q3": _getConjWithTags(sVerb, self._tTags, ":PQ", ":Q3"),
                ":Q4": _getConjWithTags(sVerb, self._tTags, ":PQ", ":Q4"),
                ":m:s": _getConjWithTags(sVerb, self._tTags, ":Q", ":m:s"),
                ":f:s": _getConjWithTags(sVerb, self._tTags, ":Q", ":f:s"),
                ":m:p": _getConjWithTags(sVerb, self._tTags, ":Q", ":m:p"),
                ":f:p": _getConjWithTags(sVerb, self._tTags, ":Q", ":f:p"),
            },
            ":Ip": {
                "label": "Présent",
                ":1s": _getConjWithTags(sVerb, self._tTags, ":Ip", ":1s"),
                ":1ś": _getConjWithTags(sVerb, self._tTags, ":Ip", ":1ś"),
                ":2s": _getConjWithTags(sVerb, self._tTags, ":Ip", ":2s"),
                ":3s": _getConjWithTags(sVerb, self._tTags, ":Ip", ":3s"),
329
330
331
332
333
334
335
336

337
338
339

340
341

342
343
344
345
346
347
348
329
330
331
332
333
334
335

336
337
338

339
340

341
342
343
344
345
346
347
348







-
+


-
+

-
+







        except KeyError:
            traceback.print_exc()
            return "# erreur"

    def participePresent (self, bPro, bNeg, bTpsCo, bInt, bFem):
        "returns string (conjugaison du participe présent)"
        try:
            if not self.dConj[":P"][":"]:
            if not self.dConj[":P"][":P"]:
                return ""
            if bTpsCo:
                sPartPre = _getConjWithTags(self.sVerbAux, self._tTagsAux, ":PQ", ":P")  if not bPro  else  getConj("être", ":PQ", ":P")
                sPartPre = _getConjWithTags(self.sVerbAux, self._tTagsAux, ":P", ":P")  if not bPro  else  getConj("être", ":P", ":P")
            else:
                sPartPre = self.dConj[":P"][":"]
                sPartPre = self.dConj[":P"][":P"]
            if not sPartPre:
                return ""
            bEli = bool(_zStartVoy.search(sPartPre))
            if bPro:
                if self.bProWithEn:
                    sPartPre = "s’en " + sPartPre
                else:
447
448
449
450
451
452
453
454

455
456

457
458
459


460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475




476
477
478
479
480
481
482
447
448
449
450
451
452
453

454
455

456
457


458
459
460
461
462
463
464
465
466
467
468
469
470
471




472
473
474
475
476
477
478
479
480
481
482







-
+

-
+

-
-
+
+












-
-
-
-
+
+
+
+







        except (KeyError, TypeError, IndexError):
            traceback.print_exc()
            return "# erreur"

    def _seekPpas (self, bPro, bFem, bPlur):
        try:
            if not bPro and self.sVerbAux == "avoir":
                return self.dConj[":Q"][":Q1"]
                return self.dConj[":Q"][":m:s"]
            if not bFem:
                return self.dConj[":Q"][":Q2"]  if bPlur and self.dConj[":Q"][":Q2"]  else  self.dConj[":Q"][":Q1"]
                return self.dConj[":Q"][":f:s"]  if bPlur and self.dConj[":Q"][":f:s"]  else  self.dConj[":Q"][":m:s"]
            if not bPlur:
                return self.dConj[":Q"][":Q3"]  if self.dConj[":Q"][":Q3"]  else  self.dConj[":Q"][":Q1"]
            return self.dConj[":Q"][":Q4"]  if self.dConj[":Q"][":Q4"]  else  self.dConj[":Q"][":Q1"]
                return self.dConj[":Q"][":m:p"]  if self.dConj[":Q"][":m:p"]  else  self.dConj[":Q"][":m:s"]
            return self.dConj[":Q"][":f:p"]  if self.dConj[":Q"][":f:p"]  else  self.dConj[":Q"][":m:s"]
        except KeyError:
            traceback.print_exc()
            return "# erreur"

    def createConjTable (self, bPro=False, bNeg=False, bTpsCo=False, bInt=False, bFem=False):
        "return a dictionary of all conjugations with titles, according to options (used to be displayed as is)"
        dConjTable = {
            "t_infi":   "Infinitif",
            "infi":     self.infinitif(bPro, bNeg, bTpsCo, bInt, bFem),
            "t_ppre":   "Participe présent",
            "ppre":     self.participePresent(bPro, bNeg, bTpsCo, bInt, bFem),
            "t_ppas":   "Participes passés",
            "ppas1":    self.participePasse(":Q1"),
            "ppas2":    self.participePasse(":Q2"),
            "ppas3":    self.participePasse(":Q3"),
            "ppas4":    self.participePasse(":Q4"),
            "ppas1":    self.participePasse(":m:s"),
            "ppas2":    self.participePasse(":f:s"),
            "ppas3":    self.participePasse(":m:p"),
            "ppas4":    self.participePasse(":f:p"),
            "t_imp":    "Impératif",
            "t_impe":   ""  if bInt  else "Présent"  if not bTpsCo  else "Passé",
            "impe1":    self.imperatif(":2s", bPro, bNeg, bTpsCo, bFem)  if not bInt  else "",
            "impe2":    self.imperatif(":1p", bPro, bNeg, bTpsCo, bFem)  if not bInt  else "",
            "impe3":    self.imperatif(":2p", bPro, bNeg, bTpsCo, bFem)  if not bInt  else "",
            "t_indi":   "Indicatif",
            "t_ipre":   "Présent"      if not bTpsCo  else "Passé composé",

Modified gc_lang/fr/modules/conj_data.py from [f52d7dbb37] to [f86856f4a3].

cannot compute difference between binary files

Modified gc_lang/fr/modules/gce_suggestions.py from [26290c5dd1] to [fdf32f5da9].

71
72
73
74
75
76
77
78
79
80
81




82
83

84
85
86


87
88

89
90
91


92
93

94
95
96


97
98

99
100
101


102
103
104


105
106
107


108
109

110
111
112
113
114
115
116
71
72
73
74
75
76
77




78
79
80
81
82

83
84


85
86
87

88
89


90
91
92

93
94


95
96
97

98
99


100
101
102


103
104
105


106
107
108

109
110
111
112
113
114
115
116







-
-
-
-
+
+
+
+

-
+

-
-
+
+

-
+

-
-
+
+

-
+

-
-
+
+

-
+

-
-
+
+

-
-
+
+

-
-
+
+

-
+







def suggVerbPpas (sFlex, sPattern=None):
    "suggest past participles for <sFlex>"
    dSugg = {}
    for sStem in _oSpellChecker.getLemma(sFlex):
        tTags = conj._getTags(sStem)
        if tTags:
            if not sPattern:
                dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1")] = ""
                dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q2")] = ""
                dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q3")] = ""
                dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q4")] = ""
                dSugg[conj._getConjWithTags(sStem, tTags, ":Q", ":m:s")] = ""
                dSugg[conj._getConjWithTags(sStem, tTags, ":Q", ":m:p")] = ""
                dSugg[conj._getConjWithTags(sStem, tTags, ":Q", ":f:s")] = ""
                dSugg[conj._getConjWithTags(sStem, tTags, ":Q", ":f:p")] = ""
            elif sPattern == ":m:s":
                dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1")] = ""
                dSugg[conj._getConjWithTags(sStem, tTags, ":Q", ":m:s")] = ""
            elif sPattern == ":m:p":
                if conj._hasConjWithTags(tTags, ":PQ", ":Q2"):
                    dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q2")] = ""
                if conj._hasConjWithTags(tTags, ":Q", ":m:p"):
                    dSugg[conj._getConjWithTags(sStem, tTags, ":Q", ":m:p")] = ""
                else:
                    dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1")] = ""
                    dSugg[conj._getConjWithTags(sStem, tTags, ":Q", ":m:s")] = ""
            elif sPattern == ":f:s":
                if conj._hasConjWithTags(tTags, ":PQ", ":Q3"):
                    dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q3")] = ""
                if conj._hasConjWithTags(tTags, ":Q", ":f:s"):
                    dSugg[conj._getConjWithTags(sStem, tTags, ":Q", ":f:s")] = ""
                else:
                    dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1")] = ""
                    dSugg[conj._getConjWithTags(sStem, tTags, ":Q", ":m:s")] = ""
            elif sPattern == ":f:p":
                if conj._hasConjWithTags(tTags, ":PQ", ":Q4"):
                    dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q4")] = ""
                if conj._hasConjWithTags(tTags, ":Q", ":f:p"):
                    dSugg[conj._getConjWithTags(sStem, tTags, ":Q", ":f:p")] = ""
                else:
                    dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1")] = ""
                    dSugg[conj._getConjWithTags(sStem, tTags, ":Q", ":m:s")] = ""
            elif sPattern == ":s":
                dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1")] = ""
                dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q3")] = ""
                dSugg[conj._getConjWithTags(sStem, tTags, ":Q", ":m:s")] = ""
                dSugg[conj._getConjWithTags(sStem, tTags, ":Q", ":f:s")] = ""
            elif sPattern == ":p":
                if conj._hasConjWithTags(tTags, ":PQ", ":Q2"):
                    dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q2")] = ""
                if conj._hasConjWithTags(tTags, ":Q", ":m:p"):
                    dSugg[conj._getConjWithTags(sStem, tTags, ":Q", ":m:p")] = ""
                else:
                    dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1")] = ""
                dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q4")] = ""
                    dSugg[conj._getConjWithTags(sStem, tTags, ":Q", ":m:s")] = ""
                dSugg[conj._getConjWithTags(sStem, tTags, ":Q", ":f:p")] = ""
            else:
                dSugg[conj._getConjWithTags(sStem, tTags, ":PQ", ":Q1")] = ""
                dSugg[conj._getConjWithTags(sStem, tTags, ":Q", ":m:s")] = ""
    if "" in dSugg:
        del dSugg[""]
    if dSugg:
        return "|".join(dSugg.keys())
    return ""


132
133
134
135
136
137
138
139

140
141
142
143
144
145
146
132
133
134
135
136
137
138

139
140
141
142
143
144
145
146







-
+







        lTenses = [ m.group(0)  for m in re.finditer(":(?:Y|I[pqsf]|S[pq]|K|P)", sMorph) ]
        if sWho:
            for sTense in lTenses:
                if conj.hasConj(sStem, sTense, sWho):
                    dSugg[conj.getConj(sStem, sTense, sWho)] = ""
        else:
            for sTense in lTenses:
                for sWho in [ m.group(0)  for m in re.finditer(":[123][sp]", sMorph) ]:
                for sWho in [ m.group(0)  for m in re.finditer(":(?:[123][sp]|P|Y)", sMorph) ]:
                    if conj.hasConj(sStem, sTense, sWho):
                        dSugg[conj.getConj(sStem, sTense, sWho)] = ""
    if dSugg:
        return "|".join(dSugg.keys())
    return ""


267
268
269
270
271
272
273
274

275
276
277

278
279
280
281
282
283
284
267
268
269
270
271
272
273

274
275
276

277
278
279
280
281
282
283
284







-
+


-
+







            else:
                sStem = cr.getLemmaOfMorph(sMorph)
                if mfsp.isMasForm(sStem):
                    dSugg[sStem] = ""
        else:
            # a verb
            sVerb = cr.getLemmaOfMorph(sMorph)
            if conj.hasConj(sVerb, ":PQ", ":Q1") and conj.hasConj(sVerb, ":PQ", ":Q3"):
            if conj.hasConj(sVerb, ":Q", ":m:s") and conj.hasConj(sVerb, ":Q", ":f:s"):
                # We also check if the verb has a feminine form.
                # If not, we consider it’s better to not suggest the masculine one, as it can be considered invariable.
                dSugg[conj.getConj(sVerb, ":PQ", ":Q1")] = ""
                dSugg[conj.getConj(sVerb, ":Q", ":m:s")] = ""
    if bSuggSimil:
        for e in phonet.selectSimil(sFlex, ":m:[si]"):
            dSugg[e] = ""
    if dSugg:
        return "|".join(dSugg.keys())
    return ""

294
295
296
297
298
299
300
301
302
303
304




305
306
307
308
309
310
311
294
295
296
297
298
299
300




301
302
303
304
305
306
307
308
309
310
311







-
-
-
-
+
+
+
+







            else:
                sStem = cr.getLemmaOfMorph(sMorph)
                if mfsp.isMasForm(sStem):
                    dSugg[suggPlur(sStem, True)] = ""
        else:
            # a verb
            sVerb = cr.getLemmaOfMorph(sMorph)
            if conj.hasConj(sVerb, ":PQ", ":Q2"):
                dSugg[conj.getConj(sVerb, ":PQ", ":Q2")] = ""
            elif conj.hasConj(sVerb, ":PQ", ":Q1"):
                sSugg = conj.getConj(sVerb, ":PQ", ":Q1")
            if conj.hasConj(sVerb, ":Q", ":m:p"):
                dSugg[conj.getConj(sVerb, ":Q", ":m:p")] = ""
            elif conj.hasConj(sVerb, ":Q", ":m:s"):
                sSugg = conj.getConj(sVerb, ":Q", ":m:s")
                # it is necessary to filter these flexions, like “succédé” or “agi” that are not masculine plural.
                if sSugg.endswith("s"):
                    dSugg[sSugg] = ""
    if bSuggSimil:
        for e in phonet.selectSimil(sFlex, ":m:[pi]"):
            dSugg[e] = ""
    if dSugg:
324
325
326
327
328
329
330
331
332


333
334
335
336
337
338
339
324
325
326
327
328
329
330


331
332
333
334
335
336
337
338
339







-
-
+
+







            else:
                sStem = cr.getLemmaOfMorph(sMorph)
                if mfsp.isMasForm(sStem):
                    dSugg.update(dict.fromkeys(mfsp.getFemForm(sStem, False), ""))
        else:
            # a verb
            sVerb = cr.getLemmaOfMorph(sMorph)
            if conj.hasConj(sVerb, ":PQ", ":Q3"):
                dSugg[conj.getConj(sVerb, ":PQ", ":Q3")] = ""
            if conj.hasConj(sVerb, ":Q", ":f:s"):
                dSugg[conj.getConj(sVerb, ":Q", ":f:s")] = ""
    if bSuggSimil:
        for e in phonet.selectSimil(sFlex, ":f:[si]"):
            dSugg[e] = ""
    if dSugg:
        return "|".join(dSugg.keys())
    return ""

349
350
351
352
353
354
355
356
357


358
359
360
361
362
363
364
349
350
351
352
353
354
355


356
357
358
359
360
361
362
363
364







-
-
+
+







            else:
                sStem = cr.getLemmaOfMorph(sMorph)
                if mfsp.isMasForm(sStem):
                    dSugg.update(dict.fromkeys(mfsp.getFemForm(sStem, True)))
        else:
            # a verb
            sVerb = cr.getLemmaOfMorph(sMorph)
            if conj.hasConj(sVerb, ":PQ", ":Q4"):
                dSugg[conj.getConj(sVerb, ":PQ", ":Q4")] = ""
            if conj.hasConj(sVerb, ":Q", ":f:p"):
                dSugg[conj.getConj(sVerb, ":Q", ":f:p")] = ""
    if bSuggSimil:
        for e in phonet.selectSimil(sFlex, ":f:[pi]"):
            dSugg[e] = ""
    if dSugg:
        return "|".join(dSugg)
    return ""

416
417
418
419
420
421
422
423

424
425
426
427
428
429
430
431
432
433

434
435
436
437
438
439
440
416
417
418
419
420
421
422

423
424
425
426
427
428
429
430
431
432

433
434
435
436
437
438
439
440







-
+









-
+







        return dTokenDst["sValue"]
    return ""


def hasFemForm (sFlex):
    "return True if there is a feminine form of <sFlex>"
    for sStem in _oSpellChecker.getLemma(sFlex):
        if mfsp.isMasForm(sStem) or conj.hasConj(sStem, ":PQ", ":Q3"):
        if mfsp.isMasForm(sStem) or conj.hasConj(sStem, ":Q", ":f:s"):
            return True
    if phonet.hasSimil(sFlex, ":f"):
        return True
    return False


def hasMasForm (sFlex):
    "return True if there is a masculine form of <sFlex>"
    for sStem in _oSpellChecker.getLemma(sFlex):
        if mfsp.isMasForm(sStem) or conj.hasConj(sStem, ":PQ", ":Q1"):
        if mfsp.isMasForm(sStem) or conj.hasConj(sStem, ":Q", ":m:s"):
            # what has a feminine form also has a masculine form
            return True
    if phonet.hasSimil(sFlex, ":m"):
        return True
    return False


Modified gc_lang/fr/modules/phonet_data.py from [5f1637f274] to [0784da10ed].

cannot compute difference between binary files

Modified gc_lang/fr/oxt/DictOptions/LexiconEditor.py from [28c9952b1e] to [eb9da137a5].

556
557
558
559
560
561
562
563
564
565
566




567
568
569
570



571
572

573
574
575
576
577
578
579
556
557
558
559
560
561
562




563
564
565
566
567



568
569
570
571

572
573
574
575
576
577
578
579







-
-
-
-
+
+
+
+

-
-
-
+
+
+

-
+







                                for sTag1, dFlex in oVerb.dConj.items():
                                    if sTag1 != ":Q":
                                        for sTag2, sConj in dFlex.items():
                                            if sTag2.startswith(":") and sConj:
                                                self.lGeneratedFlex.append((sConj, ":V" + oVerb.cGroup + "_" + sVerbTag + sTag1 + sTag2))
                                    else:
                                        # participes passés
                                        if dFlex[":Q3"]:
                                            if dFlex[":Q2"]:
                                                self.lGeneratedFlex.append((dFlex[":Q1"], ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:m:s/*"))
                                                self.lGeneratedFlex.append((dFlex[":Q2"], ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:m:p/*"))
                                        if dFlex[":f:s"]:
                                            if dFlex[":m:p"]:
                                                self.lGeneratedFlex.append((dFlex[":m:s"], ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:m:s/*"))
                                                self.lGeneratedFlex.append((dFlex[":m:p"], ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:m:p/*"))
                                            else:
                                                self.lGeneratedFlex.append((dFlex[":Q1"], ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:m:i/*"))
                                            self.lGeneratedFlex.append((dFlex[":Q3"], ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:f:s/*"))
                                            self.lGeneratedFlex.append((dFlex[":Q4"], ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:f:p/*"))
                                                self.lGeneratedFlex.append((dFlex[":m:s"], ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:m:i/*"))
                                            self.lGeneratedFlex.append((dFlex[":f:s"], ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:f:s/*"))
                                            self.lGeneratedFlex.append((dFlex[":f:p"], ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:f:p/*"))
                                        else:
                                            self.lGeneratedFlex.append((dFlex[":Q1"], ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:e:i/*"))
                                            self.lGeneratedFlex.append((dFlex[":m:s"], ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:e:i/*"))
            elif self.xW.State:
                # Adverbe
                self.sLemma = self.sLemma.lower();
                self.lGeneratedFlex.append((self.sLemma, ":W/*"))
            elif self.xX.State:
                # Autre
                sFlexion = self.xFlexion.Text.strip()

Modified gc_lang/fr/oxt/Dictionnaires/dictionaries/README_dict_fr.txt from [9b7087f211] to [a680cb95fb].

1
2
3
4

5
6
7
8
9
10
11
1
2
3

4
5
6
7
8
9
10
11



-
+







_______________________________________________________________________________

   DICTIONNAIRES ORTHOGRAPHIQUES FRANÇAIS
   version 7.4
   version 7.5

   Olivier R.
   https://grammalecte.net/

   Licence :
     MPL : Mozilla Public License
     version 2.0  --  http://www.mozilla.org/MPL/2.0/

Modified gc_lang/fr/oxt/Dictionnaires/dictionaries/fr-classique.aff from [cfa2723c07] to [660ccbc5b3].

1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







# This Source Code Form is subject to the terms of the Mozilla Public
# 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.4
# AFFIXES DU DICTIONNAIRE ORTHOGRAPHIQUE FRANÇAIS “CLASSIQUE” v7.5
# par Olivier R. -- licence MPL 2.0
# Pour améliorer le dictionnaire, allez sur https://grammalecte.net/



SET UTF-8

Modified gc_lang/fr/oxt/Dictionnaires/dictionaries/fr-reforme1990.aff from [520df6672c] to [4b9d5873a2].

1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







# This Source Code Form is subject to the terms of the Mozilla Public
# 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.4
# AFFIXES DU DICTIONNAIRE ORTHOGRAPHIQUE FRANÇAIS “RÉFORME 1990” v7.5
# par Olivier R. -- licence MPL 2.0
# Pour améliorer le dictionnaire, allez sur https://grammalecte.net/



SET UTF-8

Modified gc_lang/fr/oxt/Dictionnaires/dictionaries/fr-toutesvariantes.aff from [6ec4d6396a] to [6e3a94ad8b].

1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







# This Source Code Form is subject to the terms of the Mozilla Public
# 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.4
# AFFIXES DU DICTIONNAIRE ORTHOGRAPHIQUE FRANÇAIS “TOUTES VARIANTES” v7.5
# par Olivier R. -- licence MPL 2.0
# Pour améliorer le dictionnaire, allez sur https://grammalecte.net/



SET UTF-8

Modified gc_lang/fr/rules.grx from [c8824c64d1] to [70dea3980f].

7119
7120
7121
7122
7123
7124
7125
7126

7127
7128
7129
7130
7131
7132
7133
7119
7120
7121
7122
7123
7124
7125

7126
7127
7128
7129
7130
7131
7132
7133







-
+







TEST: {{acculé au pied du mur}}                                 ->> acculé
TEST: {{ajouter en plus}}                                       ->> ajouter
TEST: s’avérer {{vrai}}                                         ->> exact
TEST: {{contraint malgré lui}}                                  ->> contraint
TEST: {{contraindre malgré eux}}                                ->> contraindre
TEST: {{applaudir des deux mains}}                              ->> applaudir
TEST: {{Avancer en avant}}, pas le choix                        ->> Avancer
TEST: vas-y, {{choisis}} un choix                               ->> fais
TEST: vas-y, {{choisis}} un choix                               ->> fais|fis
TEST: {{dessiner un dessin}}                                    ->> dessiner
TEST: nous {{joignons ensemble}}                                ->> joignons
TEST: {{collaborer ensemble}}                                   ->> collaborer
TEST: {{comparer entre eux}}                                    ->> comparer
TEST: {{monter en haut}}                                        ->> monter
TEST: {{descendre en bas}}                                      ->> descendre
TEST: {{enchevêtrer les uns dans les autres}}                   ->> enchevêtrer
8405
8406
8407
8408
8409
8410
8411
8412

8413
8414
8415
8416
8417
8418

8419
8420
8421
8422
8423

8424
8425
8426
8427
8428
8429
8430
8405
8406
8407
8408
8409
8410
8411

8412
8413
8414
8415
8416
8417

8418
8419
8420
8421
8422

8423
8424
8425
8426
8427
8428
8429
8430







-
+





-
+




-
+







TEST: comme des nuages ou des coteaux se reflétant dans l’eau (ligature fl)
TEST: ces hommes qui avaient abusé de lui enfant.


__conf_en_participes_présents__
    en   [ne|me|m’|te|t’|s’]  @:[123][sp]¬:[PY]
        <<- /conf/ not \1.isupper() >>>
        <<- /conf/ morph(\3, ":3p") -3>> =suggVerbTense(\3, ":PQ", ":P")                            && Incohérence : « en \1 \2 »… Vouliez-vous écrire le verbe au participe présent ?
        <<- /conf/ morph(\3, ":3p") -3>> =suggVerbTense(\3, ":P", ":P")                             && Incohérence : « en \1 \2 »… Vouliez-vous écrire le verbe au participe présent ?
        <<- /conf/ value(\2, "|m’|t’|s’|") -1:2>> "\2en "                                           && Incohérence : vouliez-vous écrire « \2en » ?
        <<- /conf/ __else__ -1:2>> =\2[0:1] + "’en"                                                 && Incohérence.

    en   se  @:[123][sp]¬:[PY]
        <<- /conf/ not \1.isupper() >>>
        <<- /conf/ morph(\3, ":3p") -3>> =suggVerbTense(\3, ":PQ", ":P")                            && Incohérence : « en \1 \2 »… Vouliez-vous écrire le verbe au participe présent ?
        <<- /conf/ morph(\3, ":3p") -3>> =suggVerbTense(\3, ":P", ":P")                             && Incohérence : « en \1 \2 »… Vouliez-vous écrire le verbe au participe présent ?
        <<- /conf/ not morph(\3, ":[NA]") -1:2>> "s’en"                                             && Incohérence : vouliez-vous écrire « s’en » ?

    en   n’  @:[123][sp]¬:[PY]
        <<- /conf/ not \1.isupper() and not value(\3, "|importe|") >>>
        <<- /conf/ morph(\3, ":3p") -3>> =suggVerbTense(\3, ":PQ", ":P")                            && Incohérence : « en \1 \2 »… Vouliez-vous écrire le verbe au participe présent ?
        <<- /conf/ morph(\3, ":3p") -3>> =suggVerbTense(\3, ":P", ":P")                             && Incohérence : « en \1 \2 »… Vouliez-vous écrire le verbe au participe présent ?
        <<- /conf/ not value(<1, "|n’|") -1:2>> "n’en "                                             && Incohérence : vouliez-vous écrire « n’en » ?
        <<- /conf/ __else__ -1:2>> "en "                                                            && Double négation : “n’” est une graphie élidée de “ne”. Il est inutile de la mettre deux fois. L’accord euphonique se fait en prononçant le “n” de “en” avec la première voyelle de “\3”.

TEST: {{en t’}}ait donné tant.                                              ->> "t’en "
TEST: il {{en me}} donne beaucoup.                                          ->> m’en
TEST: elle n’{{en n’}}avait plus pour longtemps.                            ->> "en "
TEST: {{en m’}}{{apportent}} des gâteaux                                    ->> m’en |||apportant

Modified gc_lang/fr/webext/panel/lex_editor.js from [ffa654539b] to [a73ece9f08].

429
430
431
432
433
434
435
436
437
438
439




440
441

442
443
444


445
446

447
448
449
450
451
452
453
429
430
431
432
433
434
435




436
437
438
439
440

441
442


443
444
445

446
447
448
449
450
451
452
453







-
-
-
-
+
+
+
+

-
+

-
-
+
+

-
+







                                            for (let [sTag2, sConj] of dFlex.entries()) {
                                                if (sTag2.startsWith(":") && sConj !== "") {
                                                    this.lFlexion.push([sConj, ":V" + oVerb.cGroup + "_" + sVerbTag + sTag1 + sTag2]);
                                                }
                                            }
                                        } else {
                                            // participes passés
                                            if (dFlex.get(":Q3") !== "") {
                                                if (dFlex.get(":Q2") !== "") {
                                                    this.lFlexion.push([dFlex.get(":Q1"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:m:s/*"]);
                                                    this.lFlexion.push([dFlex.get(":Q2"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:m:p/*"]);
                                            if (dFlex.get(":f:s") !== "") {
                                                if (dFlex.get(":m:p") !== "") {
                                                    this.lFlexion.push([dFlex.get(":m:s"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:m:s/*"]);
                                                    this.lFlexion.push([dFlex.get(":m:p"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:m:p/*"]);
                                                } else {
                                                    this.lFlexion.push([dFlex.get(":Q1"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:m:i/*"]);
                                                    this.lFlexion.push([dFlex.get(":m:s"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:m:i/*"]);
                                                }
                                                this.lFlexion.push([dFlex.get(":Q3"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:f:s/*"]);
                                                this.lFlexion.push([dFlex.get(":Q4"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:f:p/*"]);
                                                this.lFlexion.push([dFlex.get(":f:s"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:f:s/*"]);
                                                this.lFlexion.push([dFlex.get(":f:p"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:f:p/*"]);
                                            } else {
                                                this.lFlexion.push([dFlex.get(":Q1"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:e:i/*"]);
                                                this.lFlexion.push([dFlex.get(":m:s"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:e:i/*"]);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        break;

Modified lexicons/French.lex from [c776de0a50] to [044ca17631].

1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







# This Source Code Form is subject to the terms of the Mozilla Public
# 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/.

# Lexique simplifié pour Grammalecte v7.4
# Lexique simplifié pour Grammalecte v7.5
# Licence : MPL v2.0

# :POS ;LEX ~SEM =FQ /DIC
de	de	:G:D:e:i/*
de	de	:G:R:Rv/*
et	et	:G:Cc/*
à	à	:G:R:Rv/*