@valueerror/ltjs-lang-en 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +232 -0
- package/NOTICE +10 -0
- package/README.md +25 -2
- package/index.js +34 -0
- package/licenses/LGPL-2.1.txt +504 -0
- package/licenses/english-pos-dict.pom.xml +135 -0
- package/licenses/resource_en_12dicts-readme.html +738 -0
- package/licenses/resource_en_agid-readme.txt +340 -0
- package/licenses/resource_en_pos-readme.txt +115 -0
- package/package.json +60 -4
- package/resource-root.js +4 -0
- package/resources/META-INF/org/languagetool/language-module.properties +1 -0
- package/resources/en-chunker.bin +0 -0
- package/resources/en-pos-maxent.bin +0 -0
- package/resources/en-token.bin +0 -0
- package/resources/org/languagetool/resource/en/12dicts-readme.html +738 -0
- package/resources/org/languagetool/resource/en/added.txt +446 -0
- package/resources/org/languagetool/resource/en/added_custom.txt +4 -0
- package/resources/org/languagetool/resource/en/agid-readme.txt +340 -0
- package/resources/org/languagetool/resource/en/compounds.txt +9059 -0
- package/resources/org/languagetool/resource/en/confusion_sets.txt +871 -0
- package/resources/org/languagetool/resource/en/disambiguation.xml +17238 -0
- package/resources/org/languagetool/resource/en/do-not-synthesize.txt +13 -0
- package/resources/org/languagetool/resource/en/en-US-GB.txt +4804 -0
- package/resources/org/languagetool/resource/en/en.sor +211 -0
- package/resources/org/languagetool/resource/en/english.dict +0 -0
- package/resources/org/languagetool/resource/en/english.info +8 -0
- package/resources/org/languagetool/resource/en/english_synth.dict +0 -0
- package/resources/org/languagetool/resource/en/english_synth.info +7 -0
- package/resources/org/languagetool/resource/en/english_tags.txt +88 -0
- package/resources/org/languagetool/resource/en/hunspell/en_AU.dict +0 -0
- package/resources/org/languagetool/resource/en/hunspell/en_AU.info +16 -0
- package/resources/org/languagetool/resource/en/hunspell/en_CA.dict +0 -0
- package/resources/org/languagetool/resource/en/hunspell/en_CA.info +13 -0
- package/resources/org/languagetool/resource/en/hunspell/en_GB.dict +0 -0
- package/resources/org/languagetool/resource/en/hunspell/en_GB.info +15 -0
- package/resources/org/languagetool/resource/en/hunspell/en_NZ.dict +0 -0
- package/resources/org/languagetool/resource/en/hunspell/en_NZ.info +18 -0
- package/resources/org/languagetool/resource/en/hunspell/en_US.dict +0 -0
- package/resources/org/languagetool/resource/en/hunspell/en_US.info +15 -0
- package/resources/org/languagetool/resource/en/hunspell/en_ZA.dict +0 -0
- package/resources/org/languagetool/resource/en/hunspell/en_ZA.info +16 -0
- package/resources/org/languagetool/resource/en/hunspell/ignore.txt +11070 -0
- package/resources/org/languagetool/resource/en/hunspell/prohibit.txt +383 -0
- package/resources/org/languagetool/resource/en/hunspell/prohibit_custom.txt +1 -0
- package/resources/org/languagetool/resource/en/hunspell/spelling.txt +477 -0
- package/resources/org/languagetool/resource/en/hunspell/spelling_custom.txt +1 -0
- package/resources/org/languagetool/resource/en/hunspell/spelling_en-AU.txt +34 -0
- package/resources/org/languagetool/resource/en/hunspell/spelling_en-CA.txt +28 -0
- package/resources/org/languagetool/resource/en/hunspell/spelling_en-GB.txt +44 -0
- package/resources/org/languagetool/resource/en/hunspell/spelling_en-NZ.txt +31 -0
- package/resources/org/languagetool/resource/en/hunspell/spelling_en-US.txt +41 -0
- package/resources/org/languagetool/resource/en/hunspell/spelling_en-ZA.txt +32 -0
- package/resources/org/languagetool/resource/en/hunspell/spelling_merged.txt +0 -0
- package/resources/org/languagetool/resource/en/multiwords.txt +8210 -0
- package/resources/org/languagetool/resource/en/pos-readme.txt +115 -0
- package/resources/org/languagetool/resource/en/removed.txt +31 -0
- package/resources/org/languagetool/resource/en/removed_custom.txt +4 -0
- package/resources/org/languagetool/resource/en/specific_case.txt +5621 -0
- package/resources/org/languagetool/resource/en/word_definitions.txt +1510 -0
- package/resources/org/languagetool/rules/en/coherency.txt +2501 -0
- package/resources/org/languagetool/rules/en/contractions.txt +198 -0
- package/resources/org/languagetool/rules/en/det_a.txt +959 -0
- package/resources/org/languagetool/rules/en/det_an.txt +4080 -0
- package/resources/org/languagetool/rules/en/diacritics.txt +1415 -0
- package/resources/org/languagetool/rules/en/en-AU/grammar.xml +171 -0
- package/resources/org/languagetool/rules/en/en-CA/grammar.xml +197 -0
- package/resources/org/languagetool/rules/en/en-GB/grammar.xml +555 -0
- package/resources/org/languagetool/rules/en/en-GB/replace.txt +104 -0
- package/resources/org/languagetool/rules/en/en-GB/style.xml +302 -0
- package/resources/org/languagetool/rules/en/en-NZ/grammar.xml +171 -0
- package/resources/org/languagetool/rules/en/en-NZ/replace.txt +5 -0
- package/resources/org/languagetool/rules/en/en-US/grammar.xml +913 -0
- package/resources/org/languagetool/rules/en/en-US/replace.txt +74 -0
- package/resources/org/languagetool/rules/en/en-US/style.xml +524 -0
- package/resources/org/languagetool/rules/en/grammar-l2-de.xml +227 -0
- package/resources/org/languagetool/rules/en/grammar-l2-fr.xml +39 -0
- package/resources/org/languagetool/rules/en/grammar.xml +142537 -0
- package/resources/org/languagetool/rules/en/redundancies.txt +866 -0
- package/resources/org/languagetool/rules/en/remote-rule-filters.xml +3622 -0
- package/resources/org/languagetool/rules/en/replace.txt +221 -0
- package/resources/org/languagetool/rules/en/replace_custom.txt +7 -0
- package/resources/org/languagetool/rules/en/replace_profanity.txt +540 -0
- package/resources/org/languagetool/rules/en/style.xml +12556 -0
- package/resources/org/languagetool/rules/en/synonyms.txt +42 -0
- package/resources/org/languagetool/rules/en/wordiness.txt +1061 -0
- package/resources/org/languagetool/rules/en/wrongWordInContext.txt +14 -0
- package/src/lang/en/chunking/EnglishChunkFilter.js +108 -0
- package/src/lang/en/chunking/EnglishChunker.js +135 -0
- package/src/lang/en/language/AmericanEnglish.js +73 -0
- package/src/lang/en/language/AustralianEnglish.js +42 -0
- package/src/lang/en/language/BritishEnglish.js +91 -0
- package/src/lang/en/language/CanadianEnglish.js +70 -0
- package/src/lang/en/language/English.js +398 -0
- package/src/lang/en/language/NewZealandEnglish.js +44 -0
- package/src/lang/en/language/SouthAfricanEnglish.js +40 -0
- package/src/lang/en/language/id2prioBritishEnglish.js +6 -0
- package/src/lang/en/language/id2prioEnglish.js +333 -0
- package/src/lang/en/rules/AbstractEnglishSpellerRule.js +677 -0
- package/src/lang/en/rules/AbstractEnglishSpellerRuleData.js +778 -0
- package/src/lang/en/rules/AdvancedSynthesizerFilter.js +12 -0
- package/src/lang/en/rules/AdverbFilter.js +538 -0
- package/src/lang/en/rules/AmericanReplaceRule.js +57 -0
- package/src/lang/en/rules/AvsAnData.js +37 -0
- package/src/lang/en/rules/AvsAnRule.js +182 -0
- package/src/lang/en/rules/BritishReplaceRule.js +57 -0
- package/src/lang/en/rules/CompoundRule.js +150 -0
- package/src/lang/en/rules/ConsistentApostrophesRule.js +87 -0
- package/src/lang/en/rules/ContractionSpellingRule.js +64 -0
- package/src/lang/en/rules/DateCheckFilter.js +58 -0
- package/src/lang/en/rules/DateFilterHelper.js +51 -0
- package/src/lang/en/rules/EnglishConvertToSentenceCaseFilter.js +17 -0
- package/src/lang/en/rules/EnglishDashRule.js +42 -0
- package/src/lang/en/rules/EnglishDiacriticsRule.js +67 -0
- package/src/lang/en/rules/EnglishMultitokenSpeller.js +15 -0
- package/src/lang/en/rules/EnglishNumberInWordFilter.js +38 -0
- package/src/lang/en/rules/EnglishPartialPosTagFilter.js +29 -0
- package/src/lang/en/rules/EnglishPlainEnglishRule.js +67 -0
- package/src/lang/en/rules/EnglishRedundancyRule.js +67 -0
- package/src/lang/en/rules/EnglishRepeatedWordsRule.js +212 -0
- package/src/lang/en/rules/EnglishSpecificCaseRule.js +47 -0
- package/src/lang/en/rules/EnglishSuppressMisspelledSuggestionsFilter.js +12 -0
- package/src/lang/en/rules/EnglishUnpairedBracketsRule.js +25 -0
- package/src/lang/en/rules/EnglishUnpairedQuotesRule.js +41 -0
- package/src/lang/en/rules/EnglishWordRepeatBeginningRule.js +107 -0
- package/src/lang/en/rules/EnglishWordRepeatRule.js +126 -0
- package/src/lang/en/rules/EnglishWrongWordInContextRule.js +50 -0
- package/src/lang/en/rules/FindSuggestionsFilter.js +41 -0
- package/src/lang/en/rules/FutureDateFilter.js +25 -0
- package/src/lang/en/rules/LongSentenceRule.js +19 -0
- package/src/lang/en/rules/MorfologikAmericanSpellerRule.js +69 -0
- package/src/lang/en/rules/MorfologikAustralianSpellerRule.js +45 -0
- package/src/lang/en/rules/MorfologikBritishSpellerRule.js +47 -0
- package/src/lang/en/rules/MorfologikCanadianSpellerRule.js +45 -0
- package/src/lang/en/rules/MorfologikNewZealandSpellerRule.js +45 -0
- package/src/lang/en/rules/MorfologikSouthAfricanSpellerRule.js +45 -0
- package/src/lang/en/rules/NewYearDateFilter.js +25 -0
- package/src/lang/en/rules/NewZealandReplaceRule.js +56 -0
- package/src/lang/en/rules/NoDisambiguationEnglishPartialPosTagFilter.js +24 -0
- package/src/lang/en/rules/OrdinalSuffixFilter.js +33 -0
- package/src/lang/en/rules/SimpleReplaceProfanityRule.js +55 -0
- package/src/lang/en/rules/SimpleReplaceRule.js +46 -0
- package/src/lang/en/rules/StyleTooOftenUsedAdjectiveRule.js +58 -0
- package/src/lang/en/rules/StyleTooOftenUsedNounRule.js +58 -0
- package/src/lang/en/rules/StyleTooOftenUsedVerbRule.js +58 -0
- package/src/lang/en/rules/UnitConversionRule.js +47 -0
- package/src/lang/en/rules/UnitConversionRuleImperial.js +57 -0
- package/src/lang/en/rules/UnitConversionRuleUS.js +62 -0
- package/src/lang/en/rules/VariantInfo.js +23 -0
- package/src/lang/en/rules/WordCoherencyRule.js +40 -0
- package/src/lang/en/rules/YMDDateCheckFilter.js +25 -0
- package/src/lang/en/rules/YMDNewYearDateFilter.js +25 -0
- package/src/lang/en/rules/translation/BeoLingusTranslator.js +357 -0
- package/src/lang/en/rules/translation/Inflector.js +72 -0
- package/src/lang/en/synthesis/EnglishSynthesizer.js +109 -0
- package/src/lang/en/tagging/EnglishHybridDisambiguator.js +28 -0
- package/src/lang/en/tagging/EnglishTagger.js +78 -0
- package/src/lang/en/tokenizers/EnglishWordTokenizer.js +113 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// org.languagetool.rules.en.WordCoherencyRule
|
|
2
|
+
import { AbstractWordCoherencyRule } from '@valueerror/ltjs-core/src/core/rules/AbstractWordCoherencyRule.js';
|
|
3
|
+
import { WordCoherencyDataLoader } from '@valueerror/ltjs-core/src/core/rules/WordCoherencyDataLoader.js';
|
|
4
|
+
import { Example } from '@valueerror/ltjs-core/src/core/rules/model/Examples.js';
|
|
5
|
+
|
|
6
|
+
let wordMap = null; // Java: static wordMap = new WordCoherencyDataLoader().loadWords("/en/coherency.txt")
|
|
7
|
+
|
|
8
|
+
// Java: WordCoherencyRule (en)
|
|
9
|
+
export class WordCoherencyRule extends AbstractWordCoherencyRule {
|
|
10
|
+
static FQCN = 'org.languagetool.rules.en.WordCoherencyRule';
|
|
11
|
+
|
|
12
|
+
// Java: WordCoherencyRule(ResourceBundle)
|
|
13
|
+
constructor(messages) {
|
|
14
|
+
super(messages);
|
|
15
|
+
this.getWordMap(); // Java: static initializer runs at class load
|
|
16
|
+
this.addExamplePair(Example.wrong('He likes archaeology. Really? She likes <marker>archeology</marker>, too.'),
|
|
17
|
+
Example.fixed('He likes archaeology. Really? She likes <marker>archaeology</marker>, too.'));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Java: WordCoherencyRule#getWordMap()
|
|
21
|
+
getWordMap() {
|
|
22
|
+
if (wordMap === null) wordMap = new WordCoherencyDataLoader().loadWords('/en/coherency.txt');
|
|
23
|
+
return wordMap;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Java: WordCoherencyRule#getMessage(String,String)
|
|
27
|
+
getMessage(word1, word2) {
|
|
28
|
+
return "Do not mix variants of the same word ('" + word1 + "' and '" + word2 + "') within a single text.";
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Java: WordCoherencyRule#getId()
|
|
32
|
+
getId() {
|
|
33
|
+
return 'EN_WORD_COHERENCY';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Java: WordCoherencyRule#getDescription()
|
|
37
|
+
getDescription() {
|
|
38
|
+
return 'Coherent spelling of words with two admitted variants.';
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// org.languagetool.rules.en.YMDDateCheckFilter
|
|
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 { YMDDateHelper } from '@valueerror/ltjs-core/src/core/rules/YMDDateHelper.js';
|
|
5
|
+
import { DateCheckFilter } from './DateCheckFilter.js';
|
|
6
|
+
|
|
7
|
+
// Java: YMDDateCheckFilter
|
|
8
|
+
export class YMDDateCheckFilter extends DateCheckFilter {
|
|
9
|
+
static FQCN = 'org.languagetool.rules.en.YMDDateCheckFilter';
|
|
10
|
+
static JAVA_ABSTRACT = false;
|
|
11
|
+
static JAVA_CONSTRUCTORS = [{ params: [], text: 'public org.languagetool.rules.en.YMDDateCheckFilter()' }];
|
|
12
|
+
|
|
13
|
+
ymdDateHelper = new YMDDateHelper();
|
|
14
|
+
|
|
15
|
+
// Java: YMDDateCheckFilter#acceptRuleMatch(RuleMatch,Map,int,AnalyzedTokenReadings[],List)
|
|
16
|
+
acceptRuleMatch(match, args, patternTokenPos, patternTokens, tokenPositions) {
|
|
17
|
+
if (args.containsKey('year') || args.containsKey('month') || args.containsKey('day')) {
|
|
18
|
+
throw new RuntimeException("Set only 'weekDay' and 'date' for " + 'YMDDateCheckFilter');
|
|
19
|
+
}
|
|
20
|
+
// DEV-017: parent expects token indexes; the wrapper's text values are checked as weekday vs. date text
|
|
21
|
+
return this.acceptRuleMatchFromText(match, this.ymdDateHelper.parseDate(args));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
registerClass(YMDDateCheckFilter.FQCN, YMDDateCheckFilter);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// org.languagetool.rules.en.YMDNewYearDateFilter
|
|
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 { YMDDateHelper } from '@valueerror/ltjs-core/src/core/rules/YMDDateHelper.js';
|
|
5
|
+
import { NewYearDateFilter } from './NewYearDateFilter.js';
|
|
6
|
+
|
|
7
|
+
// Java: YMDNewYearDateFilter
|
|
8
|
+
export class YMDNewYearDateFilter extends NewYearDateFilter {
|
|
9
|
+
static FQCN = 'org.languagetool.rules.en.YMDNewYearDateFilter';
|
|
10
|
+
static JAVA_ABSTRACT = false;
|
|
11
|
+
static JAVA_CONSTRUCTORS = [{ params: [], text: 'public org.languagetool.rules.en.YMDNewYearDateFilter()' }];
|
|
12
|
+
|
|
13
|
+
ymdDateHelper = new YMDDateHelper();
|
|
14
|
+
|
|
15
|
+
// Java: YMDNewYearDateFilter#acceptRuleMatch(RuleMatch,Map,int,AnalyzedTokenReadings[],List)
|
|
16
|
+
acceptRuleMatch(match, args, patternTokenPos, patternTokens, tokenPositions) {
|
|
17
|
+
if (args.containsKey('year') || args.containsKey('month') || args.containsKey('day')) {
|
|
18
|
+
throw new RuntimeException("Set only 'weekDay' and 'date' for " + 'YMDDateCheckFilter');
|
|
19
|
+
}
|
|
20
|
+
args = this.ymdDateHelper.parseDate(args);
|
|
21
|
+
return super.acceptRuleMatch(this.ymdDateHelper.correctDate(match, args), args, patternTokenPos, patternTokens, tokenPositions);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
registerClass(YMDNewYearDateFilter.FQCN, YMDNewYearDateFilter);
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
// org.languagetool.rules.en.translation.BeoLingusTranslator (German / English translator, D-019)
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { Languages } from '@valueerror/ltjs-core/src/core/Languages.js';
|
|
4
|
+
import { GlobalConfig } from '@valueerror/ltjs-core/src/core/rules/model/GlobalConfig.js';
|
|
5
|
+
import { DataSource } from '@valueerror/ltjs-core/src/core/rules/translation/DataSource.js';
|
|
6
|
+
import { TranslationEntry } from '@valueerror/ltjs-core/src/core/rules/translation/TranslationEntry.js';
|
|
7
|
+
import { uppercaseFirstChar } from '@valueerror/ltjs-core/src/core/text/StringTools.js';
|
|
8
|
+
import { IOException, MalformedInputException, NoSuchFileException, RuntimeException } from '@valueerror/ltjs-core/src/lib/java/errors.js';
|
|
9
|
+
import { ArrayIndexOutOfBoundsException } from '@valueerror/ltjs-core/src/lib/java/errors.js';
|
|
10
|
+
import { JavaHashSet } from '@valueerror/ltjs-core/src/lib/java/collections/JavaHashSet.js';
|
|
11
|
+
import { readerLines } from '@valueerror/ltjs-core/src/lib/java/io.js';
|
|
12
|
+
import { Pattern, javaReplaceAll, javaReplaceFirst, javaSplit } from '@valueerror/ltjs-core/src/lib/java/regex/index.js';
|
|
13
|
+
import { javaReplace, javaTrim, toLowerCase } from '@valueerror/ltjs-core/src/lib/java/strings.js';
|
|
14
|
+
import { Inflector } from './Inflector.js';
|
|
15
|
+
import { LoggerFactory } from '@valueerror/ltjs-core/src/lib/slf4j/Logger.js';
|
|
16
|
+
import { currentTimeMillis } from '@valueerror/ltjs-core/src/lib/java/clock.js';
|
|
17
|
+
|
|
18
|
+
const logger = LoggerFactory.getLogger('org.languagetool.rules.en.translation.BeoLingusTranslator');
|
|
19
|
+
|
|
20
|
+
const enUsPattern = Pattern.compile('.*?\\w+ \\[(Br|Am)\\.\\] ?/ ?\\w+ \\[(Br|Am)\\.\\].*');
|
|
21
|
+
|
|
22
|
+
let instance = null;
|
|
23
|
+
|
|
24
|
+
// Source: https://www.cafe-lingua.de/englische-grammatik/verben-mit-to-infinitiv.php
|
|
25
|
+
const verbsWithTo = new Set(['afford', 'agree', 'aim', 'appear', 'arrange',
|
|
26
|
+
'attempt', 'beg', 'care', 'choose', 'claim', 'condescend', 'consent', 'dare', 'decide', 'demand', 'deserve',
|
|
27
|
+
'determine', 'endeavour', 'expect', 'fail', 'forget', 'guarantee', 'happen', 'have', 'help', 'hesitate', 'hope',
|
|
28
|
+
'learn', 'long', 'manage', 'mean', 'need', 'neglect', 'offer', 'plan', 'prepare', 'pretend', 'proceed', 'promise',
|
|
29
|
+
'refuse', 'resolve', 'seem', 'stop', 'swear', 'tend', 'threaten', 'trouble', 'undertake', 'volunteer', 'vow', 'want', 'wish']);
|
|
30
|
+
|
|
31
|
+
// Java: Files.readAllLines(Path) (UTF-8, strict)
|
|
32
|
+
function readAllLines(file) {
|
|
33
|
+
let buf;
|
|
34
|
+
try {
|
|
35
|
+
buf = readFileSync(file.getAbsolutePath());
|
|
36
|
+
} catch (e) {
|
|
37
|
+
if (e.code === 'ENOENT' || e.code === 'ENOTDIR') throw new NoSuchFileException(file.getPath());
|
|
38
|
+
if (e.code === 'EISDIR') throw new IOException('Is a directory');
|
|
39
|
+
throw new IOException(`${file.getPath()}: ${e.message}`);
|
|
40
|
+
}
|
|
41
|
+
let text;
|
|
42
|
+
try {
|
|
43
|
+
text = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(buf);
|
|
44
|
+
} catch (e) {
|
|
45
|
+
if (e instanceof TypeError) throw new MalformedInputException('Input length = 1');
|
|
46
|
+
throw e;
|
|
47
|
+
}
|
|
48
|
+
return readerLines(text);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Java: BeoLingusTranslator (implements Translator)
|
|
52
|
+
export class BeoLingusTranslator {
|
|
53
|
+
static FQCN = 'org.languagetool.rules.en.translation.BeoLingusTranslator';
|
|
54
|
+
|
|
55
|
+
// Java: BeoLingusTranslator#getInstance(File) / getInstance(GlobalConfig)
|
|
56
|
+
static getInstance(arg) {
|
|
57
|
+
if (arg instanceof GlobalConfig || arg === null || arg === undefined) return BeoLingusTranslator.getInstanceFromConfig(arg);
|
|
58
|
+
const config = new GlobalConfig();
|
|
59
|
+
config.setBeolingusFile(arg);
|
|
60
|
+
return BeoLingusTranslator.getInstanceFromConfig(config);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Java: BeoLingusTranslator#getInstance(GlobalConfig)
|
|
64
|
+
static getInstanceFromConfig(globalConfig) {
|
|
65
|
+
if (instance === null && globalConfig !== null && globalConfig !== undefined && globalConfig.getBeolingusFile() !== null) {
|
|
66
|
+
const t1 = currentTimeMillis();
|
|
67
|
+
logger.info(`Init dict from ${globalConfig.getBeolingusFile()}...`);
|
|
68
|
+
instance = new BeoLingusTranslator(globalConfig.getBeolingusFile());
|
|
69
|
+
const t2 = currentTimeMillis();
|
|
70
|
+
logger.info(`Init dict done (${t2 - t1}ms) - loaded ${instance.getDeEnSize()} de -> en items.`);
|
|
71
|
+
}
|
|
72
|
+
return instance;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Java: BeoLingusTranslator#BeoLingusTranslator(File)
|
|
76
|
+
constructor(file) {
|
|
77
|
+
this.de2en = new Map();
|
|
78
|
+
this.en2de = new Map();
|
|
79
|
+
this.inflector = new Inflector();
|
|
80
|
+
this.tagger = Languages.getLanguageForShortCode('de').getTagger();
|
|
81
|
+
const lines = readAllLines(file);
|
|
82
|
+
for (const line of lines) {
|
|
83
|
+
if (javaTrim(line).length === 0 || line.startsWith('#')) {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const parts = javaSplit(line, ' :: ');
|
|
87
|
+
if (parts.length < 1) throw new ArrayIndexOutOfBoundsException('Index 0 out of bounds for length 0');
|
|
88
|
+
const german = parts[0];
|
|
89
|
+
if (parts.length < 2) throw new ArrayIndexOutOfBoundsException(`Index 1 out of bounds for length ${parts.length}`);
|
|
90
|
+
const english = parts[1];
|
|
91
|
+
const germanParts = javaSplit(german, '\\|');
|
|
92
|
+
const englishParts = javaSplit(english, '\\|');
|
|
93
|
+
if (germanParts.length !== englishParts.length) {
|
|
94
|
+
throw new IOException(`Invalid line format (DE item count != EN item count): ${line}`);
|
|
95
|
+
}
|
|
96
|
+
let i = 0;
|
|
97
|
+
for (const germanPart of germanParts) {
|
|
98
|
+
this.handleItem(this.de2en, germanParts, englishParts, i, germanPart);
|
|
99
|
+
// handleItem(en2de, englishParts, germanParts, i, englishParts[i]); -- direction not supported yet
|
|
100
|
+
i++;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Java: BeoLingusTranslator#handleItem(Map,String[],String[],int,String)
|
|
106
|
+
handleItem(map, germanParts, englishParts, i, germanPart) {
|
|
107
|
+
germanPart = javaReplaceAll(germanPart, '/.*?/', ''); // e.g. "oder {conj} /o.; od./"
|
|
108
|
+
const germanSubParts = this.split(germanPart);
|
|
109
|
+
for (const germanSubPart of germanSubParts) {
|
|
110
|
+
const key = this.cleanForLookup(germanSubPart);
|
|
111
|
+
const oldEntries = map.get(key);
|
|
112
|
+
if (oldEntries !== undefined) {
|
|
113
|
+
if (javaTrim(englishParts[i]).length !== 0) {
|
|
114
|
+
oldEntries.push(new TranslationEntry(this.split(germanPart), this.split(javaTrim(englishParts[i])), germanParts.length));
|
|
115
|
+
map.set(key, oldEntries);
|
|
116
|
+
}
|
|
117
|
+
} else {
|
|
118
|
+
const l = [];
|
|
119
|
+
if (javaTrim(englishParts[i]).length !== 0) {
|
|
120
|
+
l.push(new TranslationEntry(this.split(germanPart), this.split(englishParts[i]), germanParts.length));
|
|
121
|
+
map.set(key, l);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// "tyre [Br.]/tire [Am.] pump" -> "tyre pump [Br.]" + "tire pump [Am.]"
|
|
128
|
+
// Java: BeoLingusTranslator#split(String)
|
|
129
|
+
split(s) {
|
|
130
|
+
const parts = this.splitAtSemicolon(s);
|
|
131
|
+
const newParts = [];
|
|
132
|
+
for (const part of parts) {
|
|
133
|
+
if (enUsPattern.matcher(part).matches()) {
|
|
134
|
+
const variant1 = javaReplaceFirst(part, '^(.*?)(\\w+) (\\[(?:Br|Am)\\.\\]) ?/ ?\\w+ \\[(?:Br|Am)\\.\\](.*)', '$1$2$4 $3');
|
|
135
|
+
const variant2 = javaReplaceFirst(part, '^(.*?)(\\w+) (\\[(?:Br|Am)\\.\\]) ?/ ?(\\w+) (\\[(?:Br|Am)\\.\\])(.*)', '$1$4$6 $5');
|
|
136
|
+
newParts.push(variant1);
|
|
137
|
+
newParts.push(variant2);
|
|
138
|
+
} else {
|
|
139
|
+
newParts.push(part);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return newParts;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Java: BeoLingusTranslator#getDeEnSize()
|
|
146
|
+
getDeEnSize() {
|
|
147
|
+
return this.de2en.size;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// split input like "family doctors; family physicians" at ";", unless it's in "{...}":
|
|
151
|
+
// Java: BeoLingusTranslator#splitAtSemicolon(String)
|
|
152
|
+
splitAtSemicolon(s) {
|
|
153
|
+
const list = javaSplit(s, ';\\s+').map((k) => javaTrim(k));
|
|
154
|
+
const mergedList = [];
|
|
155
|
+
let mergeListPos = 0;
|
|
156
|
+
let merging = false;
|
|
157
|
+
for (const item of list) {
|
|
158
|
+
const openPos = item.indexOf('{');
|
|
159
|
+
const closePos = item.indexOf('}');
|
|
160
|
+
if (merging) {
|
|
161
|
+
mergedList[mergeListPos - 1] = `${mergedList[mergeListPos - 1]}; ${item}`;
|
|
162
|
+
mergeListPos--;
|
|
163
|
+
if (closePos >= 0) {
|
|
164
|
+
merging = false;
|
|
165
|
+
}
|
|
166
|
+
} else if (openPos > closePos) {
|
|
167
|
+
// ";" inside "{...}" - merge those again
|
|
168
|
+
mergedList.push(item);
|
|
169
|
+
merging = true;
|
|
170
|
+
} else {
|
|
171
|
+
mergedList.push(item);
|
|
172
|
+
}
|
|
173
|
+
mergeListPos++;
|
|
174
|
+
}
|
|
175
|
+
return mergedList;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Java: BeoLingusTranslator#translate(String,String,String)
|
|
179
|
+
translate(term, fromLang, toLang) {
|
|
180
|
+
let map;
|
|
181
|
+
if (fromLang === 'de' && toLang === 'en') {
|
|
182
|
+
map = this.de2en;
|
|
183
|
+
} else if (fromLang === 'en' && toLang === 'de') {
|
|
184
|
+
map = this.en2de;
|
|
185
|
+
} else {
|
|
186
|
+
throw new RuntimeException(`Not supported: ${fromLang} -> ${toLang}`);
|
|
187
|
+
}
|
|
188
|
+
const entries = map.get(toLowerCase(term));
|
|
189
|
+
const entriesSet = new JavaHashSet();
|
|
190
|
+
if (entries !== undefined) {
|
|
191
|
+
entriesSet.addAll(entries);
|
|
192
|
+
}
|
|
193
|
+
const translationsForBaseforms = this.getTranslationsForBaseforms(term, map);
|
|
194
|
+
for (const trans of translationsForBaseforms) {
|
|
195
|
+
if (entries !== undefined) {
|
|
196
|
+
const first = entries.find((k) => listEquals(k.getL1(), trans.getL1()));
|
|
197
|
+
if (first !== undefined && listEquals(first.getL1(), trans.getL1())) {
|
|
198
|
+
// skip duplicates
|
|
199
|
+
} else {
|
|
200
|
+
entriesSet.add(trans);
|
|
201
|
+
}
|
|
202
|
+
} else {
|
|
203
|
+
entriesSet.add(trans);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
const sortedList = [...entriesSet];
|
|
207
|
+
sortedList.sort((t1, t2) => Math.sign(t2.getItemCount() - t1.getItemCount())); // Integer.compare
|
|
208
|
+
return sortedList;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Java: BeoLingusTranslator#getTranslationsForBaseforms(String,Map)
|
|
212
|
+
getTranslationsForBaseforms(term, map) {
|
|
213
|
+
const result = [];
|
|
214
|
+
try {
|
|
215
|
+
const readings = this.tagger.tag([term]);
|
|
216
|
+
readings.push(...this.tagger.tag([uppercaseFirstChar(term)])); // user can spell German noun lowercase here
|
|
217
|
+
for (const reading of readings) {
|
|
218
|
+
const aTokens = reading.getReadings();
|
|
219
|
+
this.addResultsForTokens(map, aTokens, result);
|
|
220
|
+
}
|
|
221
|
+
return result;
|
|
222
|
+
} catch (e) {
|
|
223
|
+
if (e instanceof IOException) throw new RuntimeException(`Could not tag '${term}'`, e);
|
|
224
|
+
throw e;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Java: BeoLingusTranslator#addResultsForTokens(Map,List,List)
|
|
229
|
+
addResultsForTokens(map, aTokens, result) {
|
|
230
|
+
for (const aToken of aTokens) {
|
|
231
|
+
const lemma = aToken.getLemma();
|
|
232
|
+
if (lemma !== null && lemma !== undefined) {
|
|
233
|
+
const tmp = map.get(toLowerCase(lemma));
|
|
234
|
+
if (tmp !== undefined) {
|
|
235
|
+
for (const tmpEntry of tmp) {
|
|
236
|
+
if (!result.some((r) => r.equals(tmpEntry))) {
|
|
237
|
+
const entry = this.cleanTranslationEntry(tmpEntry, aToken);
|
|
238
|
+
if (entry !== null) {
|
|
239
|
+
result.push(entry);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Java: BeoLingusTranslator#cleanTranslationEntry(TranslationEntry,AnalyzedToken)
|
|
249
|
+
cleanTranslationEntry(tmpEntry, aToken) {
|
|
250
|
+
const l = [];
|
|
251
|
+
for (const s of tmpEntry.getL2()) {
|
|
252
|
+
const inflected = this.inflector.inflect(this.cleanTranslationForReplace(s, null), aToken.getPOSTag());
|
|
253
|
+
for (const inflectedForm of inflected) {
|
|
254
|
+
const cleanEntry = `${inflectedForm} ${this.getTranslationSuffix(s)}`;
|
|
255
|
+
l.push(javaTrim(cleanEntry));
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return l.length > 0 ? new TranslationEntry(tmpEntry.getL1(), l, tmpEntry.getItemCount()) : null;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Java: BeoLingusTranslator#cleanForLookup(String)
|
|
262
|
+
cleanForLookup(s) {
|
|
263
|
+
let r = javaReplaceAll(s, '\\{.*?\\}', '');
|
|
264
|
+
r = javaReplaceAll(r, '\\[.*?\\]', '');
|
|
265
|
+
r = javaReplaceAll(r, '\\(.*?\\)', '');
|
|
266
|
+
r = javaReplaceAll(r, '/.*?/\\b', ''); // abbreviations, e.g. "oder {conj} /o.; od./"
|
|
267
|
+
r = javaReplace(r, 'jdn./etw. ', '');
|
|
268
|
+
r = javaReplace(r, 'jdm./etw. ', '');
|
|
269
|
+
r = javaReplace(r, 'etw./jdn. ', '');
|
|
270
|
+
r = javaReplace(r, 'etw./jdm. ', '');
|
|
271
|
+
r = javaReplace(r, 'etw. ', '');
|
|
272
|
+
r = javaReplace(r, 'jdn. ', '');
|
|
273
|
+
r = javaReplace(r, 'jdm. ', '');
|
|
274
|
+
return toLowerCase(javaTrim(r));
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Java: BeoLingusTranslator#cleanTranslationForReplace(String,String)
|
|
278
|
+
cleanTranslationForReplace(s, prevWord) {
|
|
279
|
+
let clean = javaReplaceAll(s, '\\[.*?\\]', ''); // e.g. "[coll.]", "[Br.]"
|
|
280
|
+
clean = javaReplaceAll(clean, '\\{.*?\\}', ''); // e.g. "to go {went; gone}"
|
|
281
|
+
clean = javaReplaceAll(clean, '\\(.*?\\)', ''); // e.g. "icebox (old-fashioned)"
|
|
282
|
+
clean = javaReplace(clean, 'sth./sb.', '');
|
|
283
|
+
clean = javaReplace(clean, 'sb./sth.', '');
|
|
284
|
+
clean = javaReplace(clean, 'sth.', '');
|
|
285
|
+
clean = javaReplace(clean, 'sb.', '');
|
|
286
|
+
clean = javaReplaceAll(clean, '/[A-Z]+/', ''); // e.g. "heavy goods vehicle /HGV/"
|
|
287
|
+
clean = javaReplaceAll(clean, ' /[A-Z][a-z]+\\.?/', ''); // e.g. "Tuesday /Tue/", "station /Sta./"
|
|
288
|
+
clean = javaReplace(clean, '<> ', ''); // "to fathom out <> sth."
|
|
289
|
+
clean = javaReplaceAll(clean, '<(.*)>', ''); // "decease [adm.]; demise [poet.] <death>"
|
|
290
|
+
clean = javaReplaceAll(clean, '\\s+', ' ');
|
|
291
|
+
clean = javaTrim(clean);
|
|
292
|
+
if ('to' === prevWord && clean.startsWith('to ')) {
|
|
293
|
+
return clean.substring(3);
|
|
294
|
+
}
|
|
295
|
+
if ('to' !== prevWord && clean.startsWith('to ') && !verbsWithTo.has(prevWord)) {
|
|
296
|
+
return clean.substring(3);
|
|
297
|
+
}
|
|
298
|
+
return clean;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Java: BeoLingusTranslator#getMessage()
|
|
302
|
+
getMessage() {
|
|
303
|
+
return 'Translate to English?';
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Java: BeoLingusTranslator#getTranslationSuffix(String)
|
|
307
|
+
getTranslationSuffix(s) {
|
|
308
|
+
let sb = '';
|
|
309
|
+
const lookingFor = [];
|
|
310
|
+
const remove = (x) => {
|
|
311
|
+
const idx = lookingFor.indexOf(x);
|
|
312
|
+
if (idx >= 0) lookingFor.splice(idx, 1);
|
|
313
|
+
};
|
|
314
|
+
for (let i = 0; i < s.length; i++) {
|
|
315
|
+
const c = s.charAt(i);
|
|
316
|
+
if (c === '[') {
|
|
317
|
+
lookingFor.push(']');
|
|
318
|
+
} else if (c === ']' && lookingFor.includes(']')) {
|
|
319
|
+
sb += c;
|
|
320
|
+
sb += ' ';
|
|
321
|
+
remove(']');
|
|
322
|
+
} else if (c === '<') {
|
|
323
|
+
lookingFor.push('>');
|
|
324
|
+
} else if (c === '>' && lookingFor.includes('>')) {
|
|
325
|
+
sb += c;
|
|
326
|
+
sb += ' ';
|
|
327
|
+
remove('>');
|
|
328
|
+
} else if (c === '(') {
|
|
329
|
+
lookingFor.push(')');
|
|
330
|
+
} else if (c === ')') {
|
|
331
|
+
sb += c;
|
|
332
|
+
sb += ' ';
|
|
333
|
+
remove(')');
|
|
334
|
+
} else if (c === '{') {
|
|
335
|
+
lookingFor.push('}');
|
|
336
|
+
} else if (c === '}') {
|
|
337
|
+
sb += c;
|
|
338
|
+
sb += ' ';
|
|
339
|
+
remove('}');
|
|
340
|
+
}
|
|
341
|
+
if (lookingFor.length > 0) {
|
|
342
|
+
sb += c;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
return javaTrim(sb);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// Java: BeoLingusTranslator#getDataSource()
|
|
349
|
+
getDataSource() {
|
|
350
|
+
return new DataSource('https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html', 'BEOLINGUS', 'http://dict.tu-chemnitz.de');
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// Java: List#equals(Object) for lists of strings
|
|
355
|
+
function listEquals(a, b) {
|
|
356
|
+
return a.length === b.length && a.every((x, i) => x === b[i]);
|
|
357
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// org.languagetool.rules.en.translation.Inflector (package-private in Java)
|
|
2
|
+
import { AnalyzedToken } from '@valueerror/ltjs-core/src/core/AnalyzedToken.js';
|
|
3
|
+
import { Languages } from '@valueerror/ltjs-core/src/core/Languages.js';
|
|
4
|
+
import { ArrayIndexOutOfBoundsException, IOException, RuntimeException } from '@valueerror/ltjs-core/src/lib/java/errors.js';
|
|
5
|
+
import { replaceOnce } from '@valueerror/ltjs-core/src/lib/java/StringUtils.js';
|
|
6
|
+
import { javaMatches, javaSplit } from '@valueerror/ltjs-core/src/lib/java/regex/index.js';
|
|
7
|
+
|
|
8
|
+
// Java: Inflector
|
|
9
|
+
export class Inflector {
|
|
10
|
+
static FQCN = 'org.languagetool.rules.en.translation.Inflector';
|
|
11
|
+
|
|
12
|
+
// Java: Inflector#Inflector()
|
|
13
|
+
constructor() {
|
|
14
|
+
this.enSynth = Languages.getLanguageForShortCode('en').getSynthesizer();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @param enToken base form of English token (from BeoLingus)
|
|
19
|
+
*/
|
|
20
|
+
// Java: Inflector#inflect(String,String)
|
|
21
|
+
inflect(enToken, dePosTag) {
|
|
22
|
+
const parts = javaSplit(replaceOnce(enToken, 'to ', ''), ' ');
|
|
23
|
+
if (parts.length === 0) {
|
|
24
|
+
throw new ArrayIndexOutOfBoundsException(`Index ${parts.length - 1} out of bounds for length ${parts.length}`);
|
|
25
|
+
}
|
|
26
|
+
const lastPartForms = this.inflectSingleWord(parts[parts.length - 1], dePosTag);
|
|
27
|
+
const startParts = parts.length > 1 ? parts.slice(0, parts.length - 1).join(' ') : '';
|
|
28
|
+
const result = [];
|
|
29
|
+
for (const lastPartForm of lastPartForms) {
|
|
30
|
+
// only the last part is inflected, e.g. "tire pump" -> "tire pumps"
|
|
31
|
+
result.push(`${startParts} ${lastPartForm}`.trim());
|
|
32
|
+
}
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Java: Inflector#inflectSingleWord(String,String)
|
|
37
|
+
inflectSingleWord(enToken, dePosTag) {
|
|
38
|
+
const forms = [];
|
|
39
|
+
if (dePosTag === null || dePosTag === undefined) {
|
|
40
|
+
forms.push(enToken);
|
|
41
|
+
return forms;
|
|
42
|
+
}
|
|
43
|
+
if (javaMatches(dePosTag, 'SUB.*PLU.*')) {
|
|
44
|
+
forms.push(...this.getForms(enToken, 'NNP?S'));
|
|
45
|
+
} else if (javaMatches(dePosTag, 'VER:3:SIN:PRÄ.*')) {
|
|
46
|
+
forms.push(...this.getForms(enToken, 'VBZ'));
|
|
47
|
+
} else if (javaMatches(dePosTag, 'VER:3:SIN:PRT:.*')) {
|
|
48
|
+
forms.push(...this.getForms(enToken, 'VBD'));
|
|
49
|
+
} else if (javaMatches(dePosTag, 'PA1:PRD:GRU:VER')) {
|
|
50
|
+
forms.push(...this.getForms(enToken, 'VBG'));
|
|
51
|
+
} else if (javaMatches(dePosTag, 'PA2:PRD:GRU:VER')) {
|
|
52
|
+
forms.push(...this.getForms(enToken, 'VBN'));
|
|
53
|
+
} else if (javaMatches(dePosTag, 'ADJ:PRD:KOM|ADJ:.*:KOM.*')) {
|
|
54
|
+
forms.push(...this.getForms(enToken, 'JJR'));
|
|
55
|
+
} else if (javaMatches(dePosTag, 'ADJ:.*:SUP.*')) {
|
|
56
|
+
forms.push(...this.getForms(enToken, 'JJS'));
|
|
57
|
+
} else {
|
|
58
|
+
forms.push(enToken);
|
|
59
|
+
}
|
|
60
|
+
return forms;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Java: Inflector#getForms(String,String)
|
|
64
|
+
getForms(enToken, posTagRegex) {
|
|
65
|
+
try {
|
|
66
|
+
return [...this.enSynth.synthesize(new AnalyzedToken(enToken, 'fake-value', enToken), posTagRegex, true)];
|
|
67
|
+
} catch (e) {
|
|
68
|
+
if (e instanceof IOException) throw new RuntimeException(e);
|
|
69
|
+
throw e;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// Java: org.languagetool.synthesis.en.EnglishSynthesizer
|
|
2
|
+
import { getMessageBundleForLanguage } from '@valueerror/ltjs-core/src/core/resources/ResourceBundleTools.js';
|
|
3
|
+
import { Languages } from '@valueerror/ltjs-core/src/core/Languages.js';
|
|
4
|
+
import { registerComponent, sharedComponent } from '@valueerror/ltjs-core/src/core/language/components.js';
|
|
5
|
+
import { BaseSynthesizer } from '@valueerror/ltjs-core/src/core/tagging/synthesis/BaseSynthesizer.js';
|
|
6
|
+
import { lowercaseFirstCharIfCapitalized } from '@valueerror/ltjs-core/src/core/text/StringTools.js';
|
|
7
|
+
import { NullPointerException } from '@valueerror/ltjs-core/src/lib/java/errors.js';
|
|
8
|
+
import { substring } from '@valueerror/ltjs-core/src/lib/java/strings.js';
|
|
9
|
+
import { Pattern } from '@valueerror/ltjs-core/src/lib/java/regex/index.js';
|
|
10
|
+
import { AvsAnRule } from '../rules/AvsAnRule.js';
|
|
11
|
+
|
|
12
|
+
const RESOURCE_FILENAME = '/en/english_synth.dict';
|
|
13
|
+
const TAGS_FILE_NAME = '/en/english_tags.txt';
|
|
14
|
+
const SOR_FILE_NAME = '/en/en.sor';
|
|
15
|
+
|
|
16
|
+
const exceptions = ["ne'er", "e'er", "o'er", "ol'", "ma'am", "n't", 'informations'];
|
|
17
|
+
|
|
18
|
+
// A special tag to add determiners.
|
|
19
|
+
const ADD_DETERMINER = '+DT';
|
|
20
|
+
|
|
21
|
+
// A special tag to add only indefinite articles.
|
|
22
|
+
const ADD_IND_DETERMINER = '+INDT';
|
|
23
|
+
|
|
24
|
+
// Java: EnglishSynthesizer
|
|
25
|
+
export class EnglishSynthesizer extends BaseSynthesizer {
|
|
26
|
+
static FQCN = 'org.languagetool.synthesis.en.EnglishSynthesizer';
|
|
27
|
+
|
|
28
|
+
// Java: EnglishSynthesizer#INSTANCE
|
|
29
|
+
static get INSTANCE() {
|
|
30
|
+
return sharedComponent(EnglishSynthesizer.FQCN);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Java: EnglishSynthesizer#EnglishSynthesizer() (the deprecated (Language) constructor delegates here)
|
|
34
|
+
constructor() {
|
|
35
|
+
super(SOR_FILE_NAME, RESOURCE_FILENAME, TAGS_FILE_NAME, 'en');
|
|
36
|
+
this.aVsAnRule = new AvsAnRule(getMessageBundleForLanguage(Languages.getLanguageForShortCode('en')));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Java: EnglishSynthesizer#synthesize(AnalyzedToken,String)
|
|
40
|
+
synthesize2(token, posTag) {
|
|
41
|
+
if (posTag === null || posTag === undefined) {
|
|
42
|
+
throw new NullPointerException('Cannot invoke "String.startsWith(String)" because "posTag" is null');
|
|
43
|
+
}
|
|
44
|
+
if (posTag.startsWith(this.SPELLNUMBER_TAG)) {
|
|
45
|
+
return super.synthesize2(token, posTag);
|
|
46
|
+
}
|
|
47
|
+
if (token === null || token === undefined) {
|
|
48
|
+
throw new NullPointerException('Cannot invoke "org.languagetool.AnalyzedToken.getToken()" because "token" is null');
|
|
49
|
+
}
|
|
50
|
+
const aOrAn = this.aVsAnRule.suggestAorAn(token.getToken());
|
|
51
|
+
if (ADD_DETERMINER === posTag) {
|
|
52
|
+
return [aOrAn, `the ${lowercaseFirstCharIfCapitalized(token.getToken())}`];
|
|
53
|
+
} else if (ADD_IND_DETERMINER === posTag) {
|
|
54
|
+
return [aOrAn];
|
|
55
|
+
}
|
|
56
|
+
return this.removeExceptions(super.synthesize2(token, posTag));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Java: EnglishSynthesizer#synthesize(AnalyzedToken,String,boolean)
|
|
60
|
+
synthesize3(token, posTag, posTagRegExp) {
|
|
61
|
+
if (posTag === null || posTag === undefined) {
|
|
62
|
+
throw new NullPointerException('Cannot invoke "String.startsWith(String)" because "posTag" is null');
|
|
63
|
+
}
|
|
64
|
+
if (posTag.startsWith(this.SPELLNUMBER_TAG)) {
|
|
65
|
+
return this.synthesize2(token, posTag);
|
|
66
|
+
}
|
|
67
|
+
if (posTagRegExp) {
|
|
68
|
+
let myPosTag = posTag;
|
|
69
|
+
let det = '';
|
|
70
|
+
if (posTag.endsWith(ADD_IND_DETERMINER)) {
|
|
71
|
+
myPosTag = substring(myPosTag, 0, myPosTag.indexOf(ADD_IND_DETERMINER) - '\\'.length);
|
|
72
|
+
det = this.aVsAnRule.suggestAorAn(token.getLemma());
|
|
73
|
+
det = det.substring(0, det.indexOf(' ') + ' '.length);
|
|
74
|
+
} else if (posTag.endsWith(ADD_DETERMINER)) {
|
|
75
|
+
myPosTag = substring(myPosTag, 0, myPosTag.indexOf(ADD_DETERMINER) - '\\'.length);
|
|
76
|
+
det = 'the ';
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
this.initPossibleTags();
|
|
80
|
+
const p = Pattern.compile(myPosTag);
|
|
81
|
+
const results = [];
|
|
82
|
+
|
|
83
|
+
for (const tag of this.possibleTags) {
|
|
84
|
+
const m = p.matcher(tag);
|
|
85
|
+
if (m.matches() && token.getLemma() !== null) {
|
|
86
|
+
this.lookupWithDeterminer(token.getLemma(), tag, results, det);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return this.removeExceptions(results);
|
|
90
|
+
}
|
|
91
|
+
return this.removeExceptions(this.synthesize2(token, posTag));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Java: EnglishSynthesizer#lookup(String,String,List,String)
|
|
95
|
+
lookupWithDeterminer(lemma, posTag, results, determiner) {
|
|
96
|
+
const lookup = super.lookup(lemma, posTag);
|
|
97
|
+
for (const result of lookup) {
|
|
98
|
+
results.push(determiner + result);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Java: EnglishSynthesizer#isException(String)
|
|
103
|
+
isException(w) {
|
|
104
|
+
// remove: 've, 's, 're...
|
|
105
|
+
return w.startsWith("'") || exceptions.includes(w);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
registerComponent(EnglishSynthesizer.FQCN, () => new EnglishSynthesizer());
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// org.languagetool.tagging.en.EnglishHybridDisambiguator (spelling_global + multiwords chunkers, then XML rules)
|
|
2
|
+
import { registerComponent } from '@valueerror/ltjs-core/src/core/language/components.js';
|
|
3
|
+
import { AbstractDisambiguator } from '@valueerror/ltjs-core/src/core/tagging/disambiguation/AbstractDisambiguator.js';
|
|
4
|
+
import { MultiWordChunker } from '@valueerror/ltjs-core/src/core/tagging/disambiguation/MultiWordChunker.js';
|
|
5
|
+
import { XmlRuleDisambiguator } from '@valueerror/ltjs-core/src/core/disambiguation/XmlRuleDisambiguator.js';
|
|
6
|
+
|
|
7
|
+
// Java: EnglishHybridDisambiguator
|
|
8
|
+
export class EnglishHybridDisambiguator extends AbstractDisambiguator {
|
|
9
|
+
static FQCN = 'org.languagetool.tagging.en.EnglishHybridDisambiguator';
|
|
10
|
+
|
|
11
|
+
// Java: EnglishHybridDisambiguator#EnglishHybridDisambiguator(Language)
|
|
12
|
+
constructor(lang) {
|
|
13
|
+
super();
|
|
14
|
+
this.chunker = MultiWordChunker.getInstance('/en/multiwords.txt', true, true, false);
|
|
15
|
+
this.chunkerGlobal = MultiWordChunker.getInstance('/spelling_global.txt', true, true, false, MultiWordChunker.tagForNotAddingTags);
|
|
16
|
+
this.disambiguator = new XmlRuleDisambiguator(lang, true);
|
|
17
|
+
this.chunker.setIgnoreSpelling(true);
|
|
18
|
+
this.chunker.setRemovePreviousTags(true);
|
|
19
|
+
this.chunkerGlobal.setIgnoreSpelling(true);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Java: EnglishHybridDisambiguator#disambiguate(AnalyzedSentence) / disambiguate(AnalyzedSentence,CheckCancelledCallback)
|
|
23
|
+
disambiguate(input, checkCanceled = null) {
|
|
24
|
+
return this.disambiguator.disambiguate(this.chunker.disambiguate(this.chunkerGlobal.disambiguate(input, checkCanceled), checkCanceled), checkCanceled);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
registerComponent(EnglishHybridDisambiguator.FQCN, (lang) => new EnglishHybridDisambiguator(lang));
|