@valueerror/ltjs-lang-fr 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/LICENSE +232 -0
  2. package/NOTICE +9 -0
  3. package/README.md +25 -2
  4. package/index.js +24 -0
  5. package/licenses/LGPL-2.1.txt +504 -0
  6. package/licenses/french-pos-dict.pom.xml +115 -0
  7. package/licenses/resource_fr_README_lexique.txt +30 -0
  8. package/licenses/resource_fr_hunspell_README_fr.txt +73 -0
  9. package/package.json +60 -4
  10. package/resource-root.js +4 -0
  11. package/resources/META-INF/org/languagetool/language-module.properties +1 -0
  12. package/resources/org/languagetool/resource/fr/README_lexique.txt +30 -0
  13. package/resources/org/languagetool/resource/fr/added.txt +477 -0
  14. package/resources/org/languagetool/resource/fr/added_custom.txt +4 -0
  15. package/resources/org/languagetool/resource/fr/compounds.txt +1443 -0
  16. package/resources/org/languagetool/resource/fr/confusion_sets.txt +76 -0
  17. package/resources/org/languagetool/resource/fr/disambiguation.xml +11391 -0
  18. package/resources/org/languagetool/resource/fr/fr.sor +162 -0
  19. package/resources/org/languagetool/resource/fr/french.dict +0 -0
  20. package/resources/org/languagetool/resource/fr/french.info +20 -0
  21. package/resources/org/languagetool/resource/fr/french_synth.dict +0 -0
  22. package/resources/org/languagetool/resource/fr/french_synth.info +4 -0
  23. package/resources/org/languagetool/resource/fr/french_tags.txt +268 -0
  24. package/resources/org/languagetool/resource/fr/hunspell/README_fr.txt +73 -0
  25. package/resources/org/languagetool/resource/fr/hunspell/ignore.txt +1551 -0
  26. package/resources/org/languagetool/resource/fr/hunspell/prohibit.txt +3 -0
  27. package/resources/org/languagetool/resource/fr/hunspell/spelling.txt +34735 -0
  28. package/resources/org/languagetool/resource/fr/hunspell/spelling_custom.txt +1 -0
  29. package/resources/org/languagetool/resource/fr/hyphenated_words.txt +12864 -0
  30. package/resources/org/languagetool/resource/fr/multiwords.txt +4886 -0
  31. package/resources/org/languagetool/resource/fr/removed.txt +5 -0
  32. package/resources/org/languagetool/resource/fr/removed_custom.txt +4 -0
  33. package/resources/org/languagetool/rules/fr/grammar.xml +151570 -0
  34. package/resources/org/languagetool/rules/fr/remote-rule-filters.xml +820 -0
  35. package/resources/org/languagetool/rules/fr/replace.txt +39 -0
  36. package/resources/org/languagetool/rules/fr/replace_custom.txt +7 -0
  37. package/resources/org/languagetool/rules/fr/style.xml +22790 -0
  38. package/resources/org/languagetool/rules/fr/synonyms.txt +203 -0
  39. package/src/lang/fr/language/BelgianFrench.js +38 -0
  40. package/src/lang/fr/language/CanadianFrench.js +38 -0
  41. package/src/lang/fr/language/French.js +478 -0
  42. package/src/lang/fr/language/SwissFrench.js +38 -0
  43. package/src/lang/fr/language/id2prioFrench.js +102 -0
  44. package/src/lang/fr/rules/AdvancedSynthesizerFilter.js +12 -0
  45. package/src/lang/fr/rules/CompoundRule.js +47 -0
  46. package/src/lang/fr/rules/DMYDateCheckFilter.js +31 -0
  47. package/src/lang/fr/rules/DateCheckFilter.js +35 -0
  48. package/src/lang/fr/rules/DateFilterHelper.js +55 -0
  49. package/src/lang/fr/rules/FindSuggestionsFilter.js +80 -0
  50. package/src/lang/fr/rules/FrenchLazy.js +9 -0
  51. package/src/lang/fr/rules/FrenchMultitokenSpeller.js +15 -0
  52. package/src/lang/fr/rules/FrenchNumberInWordFilter.js +29 -0
  53. package/src/lang/fr/rules/FrenchPartialPosTagFilter.js +29 -0
  54. package/src/lang/fr/rules/FrenchRepeatedWordsRule.js +76 -0
  55. package/src/lang/fr/rules/FrenchSuppressMisspelledSuggestionsFilter.js +12 -0
  56. package/src/lang/fr/rules/InterrogativeVerbFilter.js +159 -0
  57. package/src/lang/fr/rules/MakeContractionsFilter.js +32 -0
  58. package/src/lang/fr/rules/MorfologikFrenchSpellerRule.js +262 -0
  59. package/src/lang/fr/rules/NewYearDateFilter.js +30 -0
  60. package/src/lang/fr/rules/PostponedAdjectiveConcordanceFilter.js +512 -0
  61. package/src/lang/fr/rules/QuestionWhitespaceRule.js +171 -0
  62. package/src/lang/fr/rules/QuestionWhitespaceStrictRule.js +38 -0
  63. package/src/lang/fr/rules/SimpleReplaceRule.js +63 -0
  64. package/src/lang/fr/rules/SuggestionsFilter.js +29 -0
  65. package/src/lang/fr/rules/WordWithDeterminerFilter.js +168 -0
  66. package/src/lang/fr/synthesis/FrenchSynthesizer.js +36 -0
  67. package/src/lang/fr/tagging/FrenchHybridDisambiguator.js +28 -0
  68. package/src/lang/fr/tagging/FrenchTagger.js +176 -0
  69. package/src/lang/fr/tokenizers/FrenchWordTokenizer.js +164 -0
@@ -0,0 +1,31 @@
1
+ // org.languagetool.rules.fr.DMYDateCheckFilter
2
+ import { registerClass } from '@valueerror/ltjs-core/src/core/resources/ClassBroker.js';
3
+ import { RuntimeException } from '@valueerror/ltjs-core/src/lib/java/errors.js';
4
+ import { javaSplit } from '@valueerror/ltjs-core/src/lib/java/strings.js';
5
+ import { DateCheckFilter } from './DateCheckFilter.js';
6
+
7
+ // Java: DMYDateCheckFilter
8
+ export class DMYDateCheckFilter extends DateCheckFilter {
9
+ static FQCN = 'org.languagetool.rules.fr.DMYDateCheckFilter';
10
+ static JAVA_ABSTRACT = false;
11
+ static JAVA_CONSTRUCTORS = [{ params: [], text: 'public org.languagetool.rules.fr.DMYDateCheckFilter()' }];
12
+
13
+ // Java: DMYDateCheckFilter#acceptRuleMatch(RuleMatch,Map,int,AnalyzedTokenReadings[],List)
14
+ acceptRuleMatch(match, args, patternTokenPos, patternTokens, tokenPositions) {
15
+ if (args.containsKey('year') || args.containsKey('month') || args.containsKey('day')) {
16
+ throw new RuntimeException("Set only 'weekDay' and 'date' for " + 'DMYDateCheckFilter');
17
+ }
18
+ const dateString = this.getRequired('date', args);
19
+ const parts = javaSplit(dateString, '-');
20
+ if (parts.length !== 3) {
21
+ throw new RuntimeException("Expected date in format 'dd-mm-yyyy': '" + dateString + "'");
22
+ }
23
+ args.put('day', parts[0]);
24
+ args.put('month', parts[1]);
25
+ args.put('year', parts[2]);
26
+ // DEV-017: parent expects token indexes; the wrapper's text values are checked as weekday vs. date text
27
+ return this.acceptRuleMatchFromText(match, args);
28
+ }
29
+ }
30
+
31
+ registerClass(DMYDateCheckFilter.FQCN, DMYDateCheckFilter);
@@ -0,0 +1,35 @@
1
+ // org.languagetool.rules.fr.DateCheckFilter
2
+ import { registerClass } from '@valueerror/ltjs-core/src/core/resources/ClassBroker.js';
3
+ import { AbstractDateCheckWithSuggestionsFilter } from '@valueerror/ltjs-core/src/core/rules/AbstractDateCheckWithSuggestionsFilter.js';
4
+ import { DateFilterHelper } from './DateFilterHelper.js';
5
+
6
+ // Java: DateCheckFilter
7
+ export class DateCheckFilter extends AbstractDateCheckWithSuggestionsFilter {
8
+ static FQCN = 'org.languagetool.rules.fr.DateCheckFilter';
9
+ static JAVA_ABSTRACT = false;
10
+ static JAVA_CONSTRUCTORS = [{ params: [], text: 'public org.languagetool.rules.fr.DateCheckFilter()' }];
11
+
12
+ dateFilterHelper = new DateFilterHelper();
13
+
14
+ // Java: DateCheckFilter#getMonth(String)
15
+ getMonth(localizedMonth) {
16
+ return this.dateFilterHelper.getMonth(localizedMonth);
17
+ }
18
+
19
+ // Java: DateCheckFilter#getCalendar()
20
+ getCalendar() {
21
+ return this.dateFilterHelper.getCalendar();
22
+ }
23
+
24
+ // Java: DateCheckFilter#getDayOfWeek(String) and #getDayOfWeek(Calendar) (overloads, one JS method dispatching on the argument type)
25
+ getDayOfWeek(arg) {
26
+ return this.dateFilterHelper.getDayOfWeek(arg);
27
+ }
28
+
29
+ // Java: DateCheckFilter#getErrorMessageWrongYear()
30
+ getErrorMessageWrongYear() {
31
+ return 'Cette date est incorrecte. Faites-vous référence à l\'année "{currentYear}" ?';
32
+ }
33
+ }
34
+
35
+ registerClass(DateCheckFilter.FQCN, DateCheckFilter);
@@ -0,0 +1,55 @@
1
+ // org.languagetool.rules.fr.DateFilterHelper (package-private)
2
+ import { Calendar } from '@valueerror/ltjs-core/src/lib/java/Calendar.js';
3
+ import { Locale } from '@valueerror/ltjs-core/src/lib/java/Locale.js';
4
+ import { RuntimeException } from '@valueerror/ltjs-core/src/lib/java/errors.js';
5
+ import { toLowerCase } from '@valueerror/ltjs-core/src/lib/java/strings.js';
6
+
7
+ // Java: DateFilterHelper
8
+ export class DateFilterHelper {
9
+ static FQCN = 'org.languagetool.rules.fr.DateFilterHelper';
10
+
11
+ // Java: DateFilterHelper#getCalendar()
12
+ getCalendar() {
13
+ return Calendar.getInstance(Locale.FRENCH);
14
+ }
15
+
16
+ // Java: DateFilterHelper#getDayOfWeek(String) and #getDayOfWeek(Calendar) (overloads, one JS method dispatching on the argument type)
17
+ getDayOfWeek(arg) {
18
+ if (arg instanceof Calendar) {
19
+ return arg.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, Locale.FRENCH);
20
+ }
21
+ const dayStr = arg;
22
+ const day = toLowerCase(dayStr);
23
+ if (day.startsWith('dim')) return Calendar.SUNDAY;
24
+ if (day.startsWith('lun')) return Calendar.MONDAY;
25
+ if (day.startsWith('mar')) return Calendar.TUESDAY;
26
+ if (day.startsWith('mer')) return Calendar.WEDNESDAY;
27
+ if (day.startsWith('jeu')) return Calendar.THURSDAY;
28
+ if (day.startsWith('ven')) return Calendar.FRIDAY;
29
+ if (day.startsWith('sam')) return Calendar.SATURDAY;
30
+ throw new RuntimeException("Could not find day of week for '" + dayStr + "'");
31
+ }
32
+
33
+ // Java: DateFilterHelper#getMonth(String)
34
+ getMonth(monthStr) {
35
+ const mon = toLowerCase(monthStr);
36
+ if (mon.startsWith('jan')) return 1;
37
+ if (mon.startsWith('fév')) return 2;
38
+ if (mon.startsWith('fev')) return 2;
39
+ if (mon.startsWith('mar')) return 3;
40
+ if (mon.startsWith('avr')) return 4;
41
+ if (mon.startsWith('mai')) return 5;
42
+ // "juin" and "juillet" are never abbreviated with 3 letters
43
+ // since it would be ambiguous (both start with "jui").
44
+ if (mon.startsWith('juin')) return 6;
45
+ if (mon.startsWith('juil')) return 7;
46
+ if (mon.startsWith('aou') ||
47
+ mon.startsWith('aoû')) return 8;
48
+ if (mon.startsWith('sep')) return 9;
49
+ if (mon.startsWith('oct')) return 10;
50
+ if (mon.startsWith('nov')) return 11;
51
+ if (mon.startsWith('déc')) return 12;
52
+ if (mon.startsWith('dec')) return 12;
53
+ throw new RuntimeException("Could not find month '" + monthStr + "'");
54
+ }
55
+ }
@@ -0,0 +1,80 @@
1
+ // org.languagetool.rules.fr.FindSuggestionsFilter
2
+ import { registerClass } from '@valueerror/ltjs-core/src/core/resources/ClassBroker.js';
3
+ import { Pattern } from '@valueerror/ltjs-core/src/lib/java/regex/index.js';
4
+ import { arrayGet } from '@valueerror/ltjs-core/src/lib/java/arrays.js';
5
+ import { javaSplit, substring } from '@valueerror/ltjs-core/src/lib/java/strings.js';
6
+ import { AnalyzedSentence } from '@valueerror/ltjs-core/src/core/AnalyzedSentence.js';
7
+ import { AnalyzedToken } from '@valueerror/ltjs-core/src/core/AnalyzedToken.js';
8
+ import { AnalyzedTokenReadings } from '@valueerror/ltjs-core/src/core/AnalyzedTokenReadings.js';
9
+ import { AbstractFindSuggestionsFilter } from '@valueerror/ltjs-core/src/core/rules/AbstractFindSuggestionsFilter.js';
10
+ import { makeWrong } from '@valueerror/ltjs-core/src/core/text/StringTools.js';
11
+ import { FrenchSynthesizer } from '../synthesis/FrenchSynthesizer.js';
12
+ import { FrenchTagger } from '../tagging/FrenchTagger.js';
13
+ import { French } from './FrenchLazy.js';
14
+
15
+ const ENDS_IN_VOWEL = Pattern.compile('[aeioué]$'); // Java: FindSuggestionsFilter#ENDS_IN_VOWEL
16
+ const PATTERN = Pattern.compile("^[smntl]'|^(nous|vous|le|la|les|me|te|se|leur|en|y) "); // Java: FindSuggestionsFilter#PATTERN
17
+
18
+ // Java: FindSuggestionsFilter
19
+ export class FindSuggestionsFilter extends AbstractFindSuggestionsFilter {
20
+ static FQCN = 'org.languagetool.rules.fr.FindSuggestionsFilter';
21
+ static JAVA_ABSTRACT = false;
22
+ static JAVA_CONSTRUCTORS = [{ params: [], text: 'public org.languagetool.rules.fr.FindSuggestionsFilter() throws java.io.IOException' }];
23
+
24
+ // Java: FindSuggestionsFilter#FindSuggestionsFilter()
25
+ constructor() {
26
+ super();
27
+ this.morfologikRule = French.getInstance().getDefaultSpellingRule();
28
+ }
29
+
30
+ // Java: FindSuggestionsFilter#getTagger()
31
+ getTagger() {
32
+ return FrenchTagger.INSTANCE;
33
+ }
34
+
35
+ // Java: FindSuggestionsFilter#getSynthesizer()
36
+ getSynthesizer() {
37
+ return FrenchSynthesizer.INSTANCE;
38
+ }
39
+
40
+ // Java: FindSuggestionsFilter#getSpellingSuggestions(AnalyzedTokenReadings)
41
+ getSpellingSuggestions(atr) {
42
+ let w;
43
+ if (atr.isTagged()) {
44
+ w = makeWrong(atr.getToken());
45
+ } else {
46
+ w = atr.getToken();
47
+ }
48
+ const suggestions = [];
49
+ const wordsToCheck = [];
50
+ wordsToCheck.push(w);
51
+ if (w.endsWith('s')) {
52
+ wordsToCheck.push(substring(w, 0, w.length - 1));
53
+ }
54
+ if (ENDS_IN_VOWEL.matcher(w).matches()) {
55
+ wordsToCheck.push(w + 's');
56
+ }
57
+ for (const word of wordsToCheck) {
58
+ const atk = new Array(1);
59
+ const token = new AnalyzedToken(word, null, null);
60
+ atk[0] = new AnalyzedTokenReadings(token);
61
+ const sentence = new AnalyzedSentence(atk);
62
+ const matches = this.morfologikRule.match(sentence);
63
+ if (matches.length > 0) {
64
+ suggestions.push(...matches[0].getSuggestedReplacements());
65
+ }
66
+ }
67
+ return suggestions;
68
+ }
69
+
70
+ // Java: FindSuggestionsFilter#cleanSuggestion(String)
71
+ cleanSuggestion(s) {
72
+ // remove pronouns before verbs
73
+ let output = PATTERN.matcher(s).replaceAll('');
74
+ // check only first element
75
+ output = arrayGet(javaSplit(output, ' '), 0);
76
+ return output;
77
+ }
78
+ }
79
+
80
+ registerClass(FindSuggestionsFilter.FQCN, FindSuggestionsFilter);
@@ -0,0 +1,9 @@
1
+ // Lazy access to French (import cycle French -> rules -> French); same class as the Java static import
2
+ import { getClassBroker } from '@valueerror/ltjs-core/src/core/resources/LtStatics.js';
3
+
4
+ export const French = {
5
+ // Java: French#getInstance()
6
+ getInstance() {
7
+ return getClassBroker().forName('org.languagetool.language.French').getInstance();
8
+ },
9
+ };
@@ -0,0 +1,15 @@
1
+ // org.languagetool.rules.fr.FrenchMultitokenSpeller
2
+ import { MultitokenSpeller } from '@valueerror/ltjs-core/src/core/rules/spelling/multitoken/MultitokenSpeller.js';
3
+ import { Languages } from '@valueerror/ltjs-core/src/core/Languages.js';
4
+ import { registerComponent } from '@valueerror/ltjs-core/src/core/language/components.js';
5
+
6
+ // Java: FrenchMultitokenSpeller (INSTANCE is the shared component 'org.languagetool.rules.fr.FrenchMultitokenSpeller')
7
+ export class FrenchMultitokenSpeller extends MultitokenSpeller {
8
+ static FQCN = 'org.languagetool.rules.fr.FrenchMultitokenSpeller';
9
+
10
+ // Java: FrenchMultitokenSpeller()
11
+ constructor() {
12
+ super(Languages.getLanguageForShortCode('fr'), ['/fr/multiwords.txt', '/spelling_global.txt', '/fr/hyphenated_words.txt']);
13
+ }
14
+ }
15
+ registerComponent(FrenchMultitokenSpeller.FQCN, () => new FrenchMultitokenSpeller());
@@ -0,0 +1,29 @@
1
+ // org.languagetool.rules.fr.FrenchNumberInWordFilter
2
+ import { registerClass } from '@valueerror/ltjs-core/src/core/resources/ClassBroker.js';
3
+ import { AbstractNumberInWordFilter } from '@valueerror/ltjs-core/src/core/rules/AbstractNumberInWordFilter.js';
4
+ import { French } from './FrenchLazy.js';
5
+
6
+ // Java: FrenchNumberInWordFilter
7
+ export class FrenchNumberInWordFilter extends AbstractNumberInWordFilter {
8
+ static FQCN = 'org.languagetool.rules.fr.FrenchNumberInWordFilter';
9
+ static JAVA_ABSTRACT = false;
10
+ static JAVA_CONSTRUCTORS = [{ params: [], text: 'public org.languagetool.rules.fr.FrenchNumberInWordFilter() throws java.io.IOException' }];
11
+
12
+ // Java: FrenchNumberInWordFilter#FrenchNumberInWordFilter()
13
+ constructor() {
14
+ super(French.getInstance());
15
+ this.frenchSpellerRule = French.getInstance().getDefaultSpellingRule();
16
+ }
17
+
18
+ // Java: FrenchNumberInWordFilter#isMisspelled(String)
19
+ isMisspelled(word) {
20
+ return this.frenchSpellerRule.isMisspelled(word);
21
+ }
22
+
23
+ // Java: FrenchNumberInWordFilter#getSuggestions(String)
24
+ getSuggestions(word) {
25
+ return this.frenchSpellerRule.getSpellingSuggestions(word);
26
+ }
27
+ }
28
+
29
+ registerClass(FrenchNumberInWordFilter.FQCN, FrenchNumberInWordFilter);
@@ -0,0 +1,29 @@
1
+ // org.languagetool.rules.fr.FrenchPartialPosTagFilter
2
+ import { registerClass } from '@valueerror/ltjs-core/src/core/resources/ClassBroker.js';
3
+ import { AnalyzedSentence } from '@valueerror/ltjs-core/src/core/AnalyzedSentence.js';
4
+ import { IOException, RuntimeException } from '@valueerror/ltjs-core/src/lib/java/errors.js';
5
+ import { PartialPosTagFilter } from '@valueerror/ltjs-core/src/core/rules/PartialPosTagFilter.js';
6
+ import { French } from './FrenchLazy.js';
7
+
8
+ // Java: FrenchPartialPosTagFilter
9
+ export class FrenchPartialPosTagFilter extends PartialPosTagFilter {
10
+ static FQCN = 'org.languagetool.rules.fr.FrenchPartialPosTagFilter';
11
+ static JAVA_ABSTRACT = false;
12
+ static JAVA_CONSTRUCTORS = [{ params: [], text: 'public org.languagetool.rules.fr.FrenchPartialPosTagFilter()' }];
13
+
14
+ // Java: FrenchPartialPosTagFilter#tag(String)
15
+ tag(token) {
16
+ try {
17
+ const frenchLanguage = French.getInstance();
18
+ const tags = frenchLanguage.getTagger().tag([token]);
19
+ const atr = [...tags];
20
+ const disambiguated = frenchLanguage.getDisambiguator().disambiguate(new AnalyzedSentence(atr));
21
+ return [...disambiguated.getTokens()];
22
+ } catch (e) {
23
+ if (e instanceof IOException) throw new RuntimeException("Could not tag and disambiguate '" + token + "'", e);
24
+ throw e;
25
+ }
26
+ }
27
+ }
28
+
29
+ registerClass(FrenchPartialPosTagFilter.FQCN, FrenchPartialPosTagFilter);
@@ -0,0 +1,76 @@
1
+ // org.languagetool.rules.fr.FrenchRepeatedWordsRule
2
+ import { AbstractRepeatedWordsRule } from '@valueerror/ltjs-core/src/core/rules/AbstractRepeatedWordsRule.js';
3
+ import { replaceOnce } from '@valueerror/ltjs-core/src/lib/java/StringUtils.js';
4
+ import { getClassBroker } from '@valueerror/ltjs-core/src/core/resources/LtStatics.js';
5
+ import { FrenchSynthesizer } from '../synthesis/FrenchSynthesizer.js';
6
+
7
+ let wordsToCheck = null; // Java: static wordsToCheck = loadWords("/fr/synonyms.txt")
8
+
9
+ // Java: FrenchRepeatedWordsRule
10
+ export class FrenchRepeatedWordsRule extends AbstractRepeatedWordsRule {
11
+ static FQCN = 'org.languagetool.rules.fr.FrenchRepeatedWordsRule';
12
+
13
+ // Java: FrenchRepeatedWordsRule(ResourceBundle)
14
+ constructor(messages) {
15
+ super(messages, getClassBroker().forName('org.languagetool.language.French').getInstance());
16
+ if (wordsToCheck === null) wordsToCheck = AbstractRepeatedWordsRule.loadWords('/fr/synonyms.txt');
17
+ // super.setDefaultTempOff();
18
+ }
19
+
20
+ // Java: FrenchRepeatedWordsRule#getMessage()
21
+ getMessage() {
22
+ return "Ce mot apparaît déjà dans l'une des phrases précédant immédiatement celle-ci. Utilisez un synonyme pour apporter plus de variété à votre texte, excepté si la répétition est intentionnelle.";
23
+ }
24
+
25
+ // Java: FrenchRepeatedWordsRule#getDescription()
26
+ getDescription() {
27
+ return ('Synonymes de mots répétés.');
28
+ }
29
+
30
+ // Java: FrenchRepeatedWordsRule#getWordsToCheck()
31
+ getWordsToCheck() {
32
+ return wordsToCheck;
33
+ }
34
+
35
+ // Java: FrenchRepeatedWordsRule#getShortMessage()
36
+ getShortMessage() {
37
+ return 'Style : Mot répété';
38
+ }
39
+
40
+ // Java: FrenchRepeatedWordsRule#getSynthesizer()
41
+ getSynthesizer() {
42
+ return FrenchSynthesizer.INSTANCE;
43
+ }
44
+
45
+ // Java: FrenchRepeatedWordsRule#adjustPostag(String)
46
+ adjustPostag(postag) {
47
+ if (postag.endsWith('e sp')) {
48
+ return replaceOnce(postag, 'e sp', '. .*');
49
+ } else if (postag.endsWith('m s')) {
50
+ return replaceOnce(postag, 'm s', '[me] sp?');
51
+ } else if (postag.endsWith('f s')) {
52
+ return replaceOnce(postag, 'f s', '[fe] sp?');
53
+ } else if (postag.endsWith('m p')) {
54
+ return replaceOnce(postag, 'm p', '[me] s?p');
55
+ } else if (postag.endsWith('f p')) {
56
+ return replaceOnce(postag, 'f p', '[fe] s?p');
57
+ } else if (postag.endsWith('e s')) {
58
+ return replaceOnce(postag, 'e s', '[me] sp?'); // also F ?
59
+ } else if (postag.endsWith('e p')) {
60
+ return replaceOnce(postag, 'e p', '[me] s?p'); // also F ?
61
+ } else if (postag.endsWith('m sp')) {
62
+ return replaceOnce(postag, 'm sp', '[me] s?p?');
63
+ } else if (postag.endsWith('f sp')) {
64
+ return replaceOnce(postag, 'f sp', '[fe] s?p?');
65
+ }
66
+ return postag;
67
+ }
68
+
69
+ // Java: FrenchRepeatedWordsRule#isException(AnalyzedTokenReadings[],int,boolean,boolean,boolean)
70
+ isException(tokens, i, sentStart, isCapitalized, isAllUppercase) {
71
+ if (isAllUppercase || (isCapitalized && !sentStart)) {
72
+ return true;
73
+ }
74
+ return tokens[i].hasPosTagStartingWith('Z');
75
+ }
76
+ }
@@ -0,0 +1,12 @@
1
+ // org.languagetool.rules.fr.FrenchSuppressMisspelledSuggestionsFilter
2
+ import { registerClass } from '@valueerror/ltjs-core/src/core/resources/ClassBroker.js';
3
+ import { AbstractSuppressMisspelledSuggestionsFilter } from '@valueerror/ltjs-core/src/core/rules/AbstractSuppressMisspelledSuggestionsFilter.js';
4
+
5
+ // Java: FrenchSuppressMisspelledSuggestionsFilter
6
+ export class FrenchSuppressMisspelledSuggestionsFilter extends AbstractSuppressMisspelledSuggestionsFilter {
7
+ static FQCN = 'org.languagetool.rules.fr.FrenchSuppressMisspelledSuggestionsFilter';
8
+ static JAVA_ABSTRACT = false;
9
+ static JAVA_CONSTRUCTORS = [{ params: [], text: 'public org.languagetool.rules.fr.FrenchSuppressMisspelledSuggestionsFilter() throws java.io.IOException' }];
10
+ }
11
+
12
+ registerClass(FrenchSuppressMisspelledSuggestionsFilter.FQCN, FrenchSuppressMisspelledSuggestionsFilter);
@@ -0,0 +1,159 @@
1
+ // org.languagetool.rules.fr.InterrogativeVerbFilter
2
+ import { registerClass } from '@valueerror/ltjs-core/src/core/resources/ClassBroker.js';
3
+ import { IllegalArgumentException } from '@valueerror/ltjs-core/src/lib/java/errors.js';
4
+ import { Integer } from '@valueerror/ltjs-core/src/lib/java/int.js';
5
+ import { equalsIgnoreCase, javaReplace, substring } from '@valueerror/ltjs-core/src/lib/java/strings.js';
6
+ import { AnalyzedSentence } from '@valueerror/ltjs-core/src/core/AnalyzedSentence.js';
7
+ import { AnalyzedToken } from '@valueerror/ltjs-core/src/core/AnalyzedToken.js';
8
+ import { AnalyzedTokenReadings } from '@valueerror/ltjs-core/src/core/AnalyzedTokenReadings.js';
9
+ import { RuleMatch } from '@valueerror/ltjs-core/src/core/rules/model/RuleMatch.js';
10
+ import { RuleFilter } from '@valueerror/ltjs-core/src/core/patterns/RuleFilter.js';
11
+ import { preserveCase } from '@valueerror/ltjs-core/src/core/text/StringTools.js';
12
+ import { FrenchSynthesizer } from '../synthesis/FrenchSynthesizer.js';
13
+ import { FrenchTagger } from '../tagging/FrenchTagger.js';
14
+ import { French } from './FrenchLazy.js';
15
+
16
+ // Java: InterrogativeVerbFilter
17
+ export class InterrogativeVerbFilter extends RuleFilter {
18
+ static FQCN = 'org.languagetool.rules.fr.InterrogativeVerbFilter';
19
+ static JAVA_ABSTRACT = false;
20
+ static JAVA_CONSTRUCTORS = [{ params: [], text: 'public org.languagetool.rules.fr.InterrogativeVerbFilter() throws java.io.IOException' }];
21
+
22
+ // Java: InterrogativeVerbFilter#InterrogativeVerbFilter()
23
+ constructor() {
24
+ super();
25
+ this.morfologikRule = French.getInstance().getDefaultSpellingRule();
26
+ }
27
+
28
+ // Java: InterrogativeVerbFilter#acceptRuleMatch(RuleMatch,Map,int,AnalyzedTokenReadings[],List)
29
+ acceptRuleMatch(match, arguments_, patternTokenPos, patternTokens) {
30
+ const replacements = [];
31
+ const pronounFrom = this.getRequired('PronounFrom', arguments_);
32
+ const verbFrom = this.getRequired('VerbFrom', arguments_);
33
+ let desiredPostag = null;
34
+ const extraSuggestions = [];
35
+ if (pronounFrom !== null && verbFrom !== null) {
36
+ const posPronoun = Integer.parseInt(pronounFrom);
37
+ if (posPronoun < 1 || posPronoun > patternTokens.length) {
38
+ throw new IllegalArgumentException('ConfusionCheckFilter: Index out of bounds in ' + match.getRule().getFullId()
39
+ + ', PronounFrom: ' + posPronoun);
40
+ }
41
+ const posVerb = Integer.parseInt(verbFrom);
42
+ if (posVerb < 1 || posVerb > patternTokens.length) {
43
+ throw new IllegalArgumentException(
44
+ 'ConfusionCheckFilter: Index out of bounds in ' + match.getRule().getFullId() + ', VerbFrom: ' + posVerb);
45
+ }
46
+ const atrPronoun = patternTokens[posPronoun - 1];
47
+
48
+ // vous
49
+ if (atrPronoun.matchesPosTagRegex('R pers obj 2 p')) {
50
+ desiredPostag = 'V.* (imp) [23] [sp]|V .*(ind|cond).* 2 p';
51
+ } else if (atrPronoun.matchesPosTagRegex('R pers obj 1 p')) { // nous
52
+ desiredPostag = 'V.* (imp) .*|V .*(ind|cond).* 1 p';
53
+ } else if (atrPronoun.matchesPosTagRegex('R pers obj.*')) { // moi, toi, le, la, lui, nous, vous, les, leur
54
+ desiredPostag = 'V.* (imp) .*';
55
+ } else if (atrPronoun.matchesPosTagRegex('.* 1 s')) {
56
+ desiredPostag = 'V .*(ind|cond).* 1 s';
57
+ const atrVerb = patternTokens[posVerb - 1];
58
+ const reading = atrVerb.readingWithTagRegex('V .*');
59
+ if (reading !== null) {
60
+ const participles = FrenchSynthesizer.INSTANCE.synthesize(reading, 'V ppa [me] sp?', true);
61
+ if (participles.length > 0) {
62
+ if (participles[0].endsWith('é')) {
63
+ extraSuggestions.push(participles[0]);
64
+ extraSuggestions.push(substring(participles[0], 0, participles[0].length - 1) + 'è');
65
+ }
66
+ }
67
+ }
68
+ } else if (atrPronoun.matchesPosTagRegex('.* 2 s')) {
69
+ desiredPostag = 'V .*(ind|cond).* 2 s';
70
+ } else if (atrPronoun.matchesPosTagRegex('.* 3( [mfe])? s')) {
71
+ desiredPostag = 'V .*(ind|cond).* 3 s';
72
+ } else if (atrPronoun.matchesPosTagRegex('.* 1 p')) {
73
+ desiredPostag = 'V .*(ind|cond).* 1 p';
74
+ } else if (atrPronoun.matchesPosTagRegex('.* 2 p')) {
75
+ desiredPostag = 'V .*(ind|cond).* 2 p';
76
+ } else if (atrPronoun.matchesPosTagRegex('.* 3( [mf])? p')) {
77
+ desiredPostag = 'V .*(ind|cond).* 3 p';
78
+ }
79
+
80
+ // add: trompè-je and trompé-je for original sentence "trompe-je"
81
+ if (extraSuggestions.length > 0) {
82
+ for (const extraSuggestion of extraSuggestions) {
83
+ const separator = (atrPronoun.getToken().startsWith('-') ? '' : '-');
84
+ const completeSuggestion = extraSuggestion + separator + atrPronoun.getToken();
85
+ if (!replacements.includes(completeSuggestion)
86
+ && !completeSuggestion.endsWith('e-je')) { // exclude trompe-je
87
+ replacements.push(completeSuggestion);
88
+ }
89
+ }
90
+ } else if (desiredPostag !== null) {
91
+ const auxPatternTokens = new Array(1);
92
+ if (patternTokens[posVerb - 1].isTagged()) {
93
+ auxPatternTokens[0] = new AnalyzedTokenReadings(
94
+ new AnalyzedToken(this.makeWrong(patternTokens[posVerb - 1].getToken()), null, null));
95
+ } else {
96
+ auxPatternTokens[0] = patternTokens[posVerb - 1];
97
+ }
98
+ const sentence = new AnalyzedSentence(auxPatternTokens);
99
+ const matches = this.morfologikRule.match(sentence);
100
+ if (matches.length > 0) {
101
+ const suggestions = matches[0].getSuggestedReplacements();
102
+ const analyzedSuggestions = FrenchTagger.INSTANCE.tag(suggestions);
103
+ for (const analyzedSuggestion of analyzedSuggestions) {
104
+ if (analyzedSuggestion.matchesPosTagRegex(desiredPostag)) {
105
+ const separator = (atrPronoun.getToken().startsWith('-') ? '' : '-');
106
+ let completeSuggestion = analyzedSuggestion.getToken() + separator + atrPronoun.getToken();
107
+ if (equalsIgnoreCase(completeSuggestion, 'peux-je')) {
108
+ completeSuggestion = preserveCase('puis-je', completeSuggestion);
109
+ }
110
+ if (completeSuggestion.endsWith('e-je')) { // exclude trompe-je -> trompé-je, trompè-je
111
+ completeSuggestion = substring(completeSuggestion, 0, completeSuggestion.length - 4) + 'é-je';
112
+ if (!replacements.includes(completeSuggestion)) {
113
+ replacements.push(completeSuggestion);
114
+ }
115
+ completeSuggestion = substring(completeSuggestion, 0, completeSuggestion.length - 4) + 'è-je';
116
+ if (!replacements.includes(completeSuggestion)) {
117
+ replacements.push(completeSuggestion);
118
+ }
119
+ } else if (!replacements.includes(completeSuggestion)) {
120
+ replacements.push(completeSuggestion);
121
+ }
122
+ }
123
+ }
124
+ }
125
+ }
126
+ }
127
+
128
+ const message = match.getMessage();
129
+ const ruleMatch = new RuleMatch(match.getRule(), match.getSentence(), match.getFromPos(), match.getToPos(),
130
+ message, match.getShortMessage());
131
+ ruleMatch.setType(match.getType());
132
+ if (replacements.length > 0) {
133
+ ruleMatch.setSuggestedReplacements(replacements);
134
+ }
135
+ return ruleMatch;
136
+ }
137
+
138
+ // Java: InterrogativeVerbFilter#makeWrong(String)
139
+ makeWrong(s) {
140
+ /* this doesn't work for some cases: ex. tarta / trata */
141
+ if (s.includes('a')) { return javaReplace(s, 'a', 'ä'); }
142
+ if (s.includes('e')) { return javaReplace(s, 'e', 'ë'); }
143
+ if (s.includes('i')) { return javaReplace(s, 'i', 'í'); }
144
+ if (s.includes('o')) { return javaReplace(s, 'o', 'ö'); }
145
+ if (s.includes('u')) { return javaReplace(s, 'u', 'ü'); }
146
+ if (s.includes('é')) { return javaReplace(s, 'é', 'ë'); }
147
+ if (s.includes('à')) { return javaReplace(s, 'à', 'ä'); }
148
+ if (s.includes('è')) { return javaReplace(s, 'è', 'ë'); }
149
+ if (s.includes('ù')) { return javaReplace(s, 'ù', 'ü'); }
150
+ if (s.includes('â')) { return javaReplace(s, 'â', 'ä'); }
151
+ if (s.includes('ê')) { return javaReplace(s, 'ê', 'ë'); }
152
+ if (s.includes('î')) { return javaReplace(s, 'î', 'ï'); }
153
+ if (s.includes('ô')) { return javaReplace(s, 'ô', 'ö'); }
154
+ if (s.includes('û')) { return javaReplace(s, 'û', 'ü'); }
155
+ return s + '-';
156
+ }
157
+ }
158
+
159
+ registerClass(InterrogativeVerbFilter.FQCN, InterrogativeVerbFilter);
@@ -0,0 +1,32 @@
1
+ // org.languagetool.rules.fr.MakeContractionsFilter
2
+ import { registerClass } from '@valueerror/ltjs-core/src/core/resources/ClassBroker.js';
3
+ import { Pattern } from '@valueerror/ltjs-core/src/lib/java/regex/index.js';
4
+ import { AbstractMakeContractionsFilter } from '@valueerror/ltjs-core/src/core/rules/AbstractMakeContractionsFilter.js';
5
+
6
+ const FLAGS = Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE | Pattern.UNICODE_CHARACTER_CLASS;
7
+ const DE_LE = Pattern.compile('\\bde le\\b', FLAGS); // Java: MakeContractionsFilter#DE_LE
8
+ const A_LE = Pattern.compile('\\bà le\\b', FLAGS); // Java: MakeContractionsFilter#A_LE
9
+ const DE_LES = Pattern.compile('\\bde les\\b', FLAGS); // Java: MakeContractionsFilter#DE_LES
10
+ const A_LES = Pattern.compile('\\bà les\\b', FLAGS); // Java: MakeContractionsFilter#A_LES
11
+
12
+ // Java: MakeContractionsFilter
13
+ export class MakeContractionsFilter extends AbstractMakeContractionsFilter {
14
+ static FQCN = 'org.languagetool.rules.fr.MakeContractionsFilter';
15
+ static JAVA_ABSTRACT = false;
16
+ static JAVA_CONSTRUCTORS = [{ params: [], text: 'public org.languagetool.rules.fr.MakeContractionsFilter()' }];
17
+
18
+ // Java: MakeContractionsFilter#fixContractions(String)
19
+ fixContractions(suggestion) {
20
+ let matcher = DE_LE.matcher(suggestion);
21
+ suggestion = matcher.replaceAll('du');
22
+ matcher = A_LE.matcher(suggestion);
23
+ suggestion = matcher.replaceAll('au');
24
+ matcher = DE_LES.matcher(suggestion);
25
+ suggestion = matcher.replaceAll('des');
26
+ matcher = A_LES.matcher(suggestion);
27
+ suggestion = matcher.replaceAll('aux');
28
+ return suggestion;
29
+ }
30
+ }
31
+
32
+ registerClass(MakeContractionsFilter.FQCN, MakeContractionsFilter);