From 26271819bf71145e6914096002e55df78110c0a9 Mon Sep 17 00:00:00 2001 From: affemitkaraffe Date: Fri, 17 May 2024 15:59:48 +0200 Subject: [PATCH] [de] *part1*s that do not have a POS tag --- .../rules/de/GermanSpellerRule.java | 17 +- .../resource/de/other_prefixes.txt | 411 ++++++++++++++++++ .../languagetool/resource/de/verb_stems.txt | 24 +- .../rules/de/GermanSpellerRuleTest.java | 14 + 4 files changed, 451 insertions(+), 15 deletions(-) create mode 100644 languagetool-language-modules/de/src/main/resources/org/languagetool/resource/de/other_prefixes.txt diff --git a/languagetool-language-modules/de/src/main/java/org/languagetool/rules/de/GermanSpellerRule.java b/languagetool-language-modules/de/src/main/java/org/languagetool/rules/de/GermanSpellerRule.java index f2d922d35ebb..de2e2cecef1b 100644 --- a/languagetool-language-modules/de/src/main/java/org/languagetool/rules/de/GermanSpellerRule.java +++ b/languagetool-language-modules/de/src/main/java/org/languagetool/rules/de/GermanSpellerRule.java @@ -136,7 +136,8 @@ public class GermanSpellerRule extends CompoundAwareHunspellRule { private static final Pattern COMPOUND_END_TYPOS = compile(".*(gruße|schaf(s|en)?)$"); private static final Pattern INFIX_S_SUFFIXES = compile(".*(heit|ion|ität|keit|ling|ung|schaft|tum)$"); private static final Pattern WECHSELINFIX = compile("(arbeit|dienstag|donnerstag|freitag|montag|mittwoch|link|recht|samstag|sonntag|verband)s?"); - private static final Pattern NEEDS_TO_BE_PLURAL = compile("adresse|aktie|antenne|apache|arbeitnehmerin|autor|bakterie|bauer|bisexuelle|bürge|blume|börse|buche|däne|debatte|decke|diakon(in)?|drohne|druide|ehre|eibe|emittent(in)?|elfe|elle|enge|erde|erste|esche|fassade|farbe|felge|ferien|fluor|frage|frau|förde|galle|gerät|gilde|göttin|halt|heide|historie|hose|hund|jungfer|kante|kathode|katze|kette|kid|klasse|kirche|klaue|klinge|knappe|koeffizient|kojote|kontrahent|kontrolle|krake|kralle|kranke|krähe|kraut|kuriosität|kurve|kusine|küste|laterne|laute|legende|lehne|leise|leuchte|lippe|loge|lotse|länge|läuse|löwe|lücke|made|maske|maßnahme|menge|mensch|metapher|methode|metropole|miene|miete|million|miniatur|mitte|maus|mücke|mühle|nerv|niederlage|nixe|nonne|note|obdachlose|ode|organist|panne|parzelle|pate|patient|petze|pfanne|pfeife|platte|polle|pomade|pomeranze|posse|prise|prominente|prälat|puppe|pädophile|radikale|rakete|rampe|ranke|rate|rendite|repressalie|rest|riese|rinde|rind|robbe|robe|romanist|rose|ross|route|nummer|runde|röhre|rübe|salbe|schabe|schale|scheide|schelle|schenke|schere|sphäre|dicke|kröte|schlampe|schlange|schluchte|schmiere|schnake|schnalle|schneide|schnelle|schokolade|schotte|schwabe|schwalbe|schwule|seele|seide|hölle|höhle|seite|sonne|sorge|spanne|sparte|sperre|spitze|sproße|spule|steppe|straße|streife|studie|stunde|stütze|tabelle|tinte|tote|toilette|traube|treffe|treppe|truhe|träne|tunte|tüte|urne|vene|versicherte|verwandte|virtuose|vorname|waffe|wanne|ware|watte|wehe|welle|wiese"); + private static final Pattern NEEDS_TO_BE_PLURAL = compile("adresse|aktie|antenne|apache|arbeitnehmerin|autor|bakterie|bauer|bisexuelle|bürge|blume|börse|buche|däne|debatte|decke|diakon(in)?|drohne|druide|ehre|eibe|emittent(in)?|elfe|elle|enge|erde|erste|esche|fassade|farbe|felge|ferien|fluor|frage|frau|förde|galle|gerät|gilde|göttin|halt|heide|historie|hose|hund|jungfer|kante|kathode|katze|kette|kid|klasse|kirche|klaue|klinge|knappe|koeffizient|kojote|kontrahent|krake|kralle|kranke|krähe|kraut|kuriosität|kurve|kusine|küste|laterne|laute|legende|lehne|leise|leuchte|lippe|loge|lotse|länge|läuse|löwe|lücke|made|maske|maßnahme|menge|mensch|metapher|methode|metropole|miene|miete|million|miniatur|mitte|maus|mücke|mühle|nerv|niederlage|nixe|nonne|note|obdachlose|ode|organist|panne|parzelle|pate|patient|petze|pfanne|pfeife|platte|polle|pomade|pomeranze|posse|prise|prominente|prälat|puppe|pädophile|radikale|rakete|rampe|ranke|rate|rendite|repressalie|rest|riese|rinde|rind|robbe|robe|romanist|rose|ross|route|nummer|runde|röhre|rübe|salbe|schabe|schale|scheide|schelle|schenke|schere|sphäre|dicke|kröte|schlampe|schlange|schluchte|schmiere|schnake|schnalle|schneide|schnelle|schokolade|schotte|schwabe|schwalbe|schwule|seele|seide|hölle|höhle|seite|sonne|sorge|spanne|sparte|sperre|spitze|sproße|spule|steppe|straße|streife|studie|stunde|stütze|tabelle|tinte|tote|toilette|traube|treffe|treppe|truhe|träne|tunte|tüte|urne|vene|versicherte|verwandte|virtuose|vorname|waffe|wanne|ware|watte|wehe|welle|wiese"); + private static final Pattern INVALID_COMP_PART = compile("kontrolle|perspektive|schule|sprache|stelle|suche"); private static final Pattern SUBINF_SINGULAR_OBJECT = compile("putzen|rauchen|sein|spielen"); private static final Pattern ARBEIT_COMP = compile("(gebe|nehme)(r(s|n|innen|in)?|nde[mnr]?)"); private static final Pattern LINK_COMP = compile("element|inhalt|liste|portal|text|titel|tracking|verzeichnis"); @@ -160,6 +161,7 @@ public class GermanSpellerRule extends CompoundAwareHunspellRule { private final Set germanPrefixes = new HashSet<>(); private static Set verbStems = new HashSet<>(); private static Set verbPrefixes = new HashSet<>(); + private static Set otherPrefixes = new HashSet<>(); private static Set oldSpelling = new HashSet<>(); private static final Map>> ADDITIONAL_SUGGESTIONS = new HashMap<>(); static { @@ -1749,6 +1751,7 @@ public GermanSpellerRule(ResourceBundle messages, German language, UserConfig us loadFile("/de/german_prefix.txt", germanPrefixes); loadFile("/de/verb_stems.txt", verbStems); loadFile("/de/verb_prefixes.txt", verbPrefixes); + loadFile("/de/other_prefixes.txt", otherPrefixes); loadFile("/de/alt_neu.csv", oldSpelling); } @@ -2465,6 +2468,10 @@ private boolean processTwoPartCompounds(String part1, String part2) throws IOExc boolean part2upcasedIsNoun = isNoun(part2upcased); boolean part2upcasedIsMispelled = isMisspelled(uppercaseFirstChar(part2upcased)); + if (INVALID_COMP_PART.matcher(lowercaseFirstChar(part1WithoutHyphen)).matches()) { + return false; + } + String part1_without_infix_s = part1upcased; // Sometimes part1 requires singular or plural @@ -2524,8 +2531,8 @@ private boolean processTwoPartCompounds(String part1, String part2) throws IOExc return true; } if (part2upcasedIsNoun && !part2upcasedIsMispelled && - // *part1* is acronym, e. g. "SEO-Expertinnen" - isAllUppercase(removeTrailingSAndHyphen(part1)) && !isMisspelled(removeTrailingSAndHyphen(part1))) { + // *part1* is acronym or other prefix, e. g. "SEO-Expertinnen", "Sprachvariante" + ((isAllUppercase(removeTrailingSAndHyphen(part1)) && !isMisspelled(removeTrailingSAndHyphen(part1))) || isOtherPrefix(part1))) { return true; } return false; @@ -2761,6 +2768,10 @@ private boolean isNounNomPlu(String word) throws IOException { return getTagger().tag(singletonList(word)).stream().anyMatch(k -> k.hasPosTagStartingWith("SUB:NOM:PLU")); } + private boolean isOtherPrefix(String word) throws IOException { + return otherPrefixes.contains(lowercaseFirstChar(word)); + } + private boolean isVerbPrefix(String word) throws IOException { return verbPrefixes.contains(lowercaseFirstChar(word)); } diff --git a/languagetool-language-modules/de/src/main/resources/org/languagetool/resource/de/other_prefixes.txt b/languagetool-language-modules/de/src/main/resources/org/languagetool/resource/de/other_prefixes.txt new file mode 100644 index 000000000000..e324ebad7cbd --- /dev/null +++ b/languagetool-language-modules/de/src/main/resources/org/languagetool/resource/de/other_prefixes.txt @@ -0,0 +1,411 @@ +#list of prefixes comes from https://github.com/danielnaber/jwordsplitter/ +sach +hilf +eß +sprach +sozial +freß +früh +spät +fuhr +zwei +drei +vier +fünf +sechs +sieben +neun +zehn +ganz +gedenk +gefolg +gegen +geheim +genital +geo +geschicht +gesund +glatt +grob +fein +groß +klein +gymnasial +halb +zentral +zurecht +zurück +zusammen +national +nicht +nieder +hoch +front +interim +ober +zwischen +wieder +außen +gesamt +polar +sanitär +rechtschreib +lese +allein +anti +bordstein +boykott +fundamental +einhalb +horizontal +kurz +maximal +minimal +natural +universal +zweit +dritt +viert +längs +unter +nach +selbst +einmal +meist +relativ +schon +gering +höchst +tiefst +auseinander +besetzt +normal +fremd +extrem +jung +alt +regional +proportional +sekundär +nutzer +passiv +aktiv +individual +real +brigade +migranten +anwender +massiv +kalt +vielfach +wild +privat +parallel +populär +schön +komplett +nackt +zivil +akut +pauschal +netto +brutto +kontroll +sparten +experimental +bio +kirsch +einfach +mehrfach +nuklear +kolonial +seefahrende +seefahrenden +seefahrendes +oster +abwärts +aufwärts +achilles +adoptiv +adress +afro +agrar +ahorn +allgemein +alternativ +anal +audio +auswärts +basken +baumwoll +beicht +bekanntheit +benelux +bermuda +binnen +farb +über +spezial +neben +erd +lehr +innen +eigen +förder +hochschul +fern +zell +elektro +trocken +mindest +frei +direkt +überwasser +hinter +vorder +langzeit +sexual +erz +wett +edel +schauspiel +luftfahrt +kriminal +eich +digital +analog +elementar +kirch +tele +quer +vorkrieg +kommunal +wund +höllen +heraus +hart +total +herunter +melde +territorial +makro +harn +hanf +grundschul +leicht +thermo +vorzeige +dokumentar +sauer +fähr +textil +gebirg +flüssig +herüber +defensiv +offensiv +hinüber +editier +mini +kontinental +buß +links +absolut +blind +hinaus +herauf +disziplinar +kompakt +dezimal +vorwärts +schwer +immun +hinauf +nobel +allzweck +überland +töpfer +exekutiv +synchron +klebe +breitband +schiffer +einweg +mehrweg +human +exklusiv +schieds +polit +umsteige +diskont +bauspar +ultra +pharma +nähr +granat +hebe +binär +transit +schweige +nominal +allrad +falsch +aushilf +neuro +mehrzweck +schiebe +registrier +meta +gratis +gemein +allround +sofort +explosiv +kausal +vorschul +tarn +pseudo +fachschul +zeige +erdbeer +premium +mega +giga +tech +kalibrier +mikroskopier +end +löse +regenerier +dechiffrier +kommissionier +filial +final +finanz +primär +instand +übereinander +hygro +palliativ +permanent +erst +quintil +viertel +hypo +rechts +niedrig +komplementär +schwach +konstant +weiter +verschieden +multinomial +rundum +einzel +filigran +#krank +vertikal +exponential +feudal +finder +fäkal +einfamilien +mehrfamilien +gebraucht +gebär +hohl +kleinst +median +mikro +pronominal +schmuddel +zentrifugal +bücherei +büchereien +intensiv +ministerial +abdominal +alkali +alveolar +anderthalb +aneinander +anglo +asynchron +aufrecht +außer +beieinander +beinahe +bronchial +chemo +dental +diözes +diözesan +durch +durchschnitts +echt +effektiv +#ein +eventual +existenzial +gegeneinander +geistig +getrennt +global +hetero +hispano +hydro +hyper +ibero +inbetrieb +indo +indoor +initial +instrumental +inter +interims +interkontinental +interrogativ +intra +invert +konjunktional +kontra +konzessiv +kraniosakral +krank +longitudinal +miss +mit +neo +neu +neutral +nichts +offen +outdoor +parodontal +partial +physio +präsidial +primar +psycho +pulmonal +retikular +rückwärts +schlecht +schmal +schwerst +schwipp +selfmade +semi +senkrecht +simultan +tertiär +thermal +trans +transparent +vital +voll +waagrecht +warm +weiter +zueinander +perspektiv \ No newline at end of file diff --git a/languagetool-language-modules/de/src/main/resources/org/languagetool/resource/de/verb_stems.txt b/languagetool-language-modules/de/src/main/resources/org/languagetool/resource/de/verb_stems.txt index ff9dc3c3d751..73de475e9f4f 100644 --- a/languagetool-language-modules/de/src/main/resources/org/languagetool/resource/de/verb_stems.txt +++ b/languagetool-language-modules/de/src/main/resources/org/languagetool/resource/de/verb_stems.txt @@ -25,13 +25,13 @@ abbezahl abbiege abbild abbims -abbind +abbinde abbitt abblas abblass abbleib abbleich -abblend +abblende abblitz abblock abblätter @@ -104,7 +104,7 @@ abfiesel abfilm abfilter abfiltrier -abfind +abfinde abfinger abfisch abflach @@ -468,7 +468,7 @@ abseh abseif abseih abseil -absend +absende abseng absenk absentier @@ -2163,7 +2163,7 @@ ausschütt ausschüttel #aussegn ausseh -aussend +aussende aussetz aussieb aussiedel @@ -3248,7 +3248,7 @@ einschütt #einsegn einseh einseif -einsend +einsende einsenk einsetz einsicker @@ -5572,7 +5572,7 @@ nachschul nachschwing nachschütt nachseh -nachsend +nachsende nachsetz nachsing nachsinn @@ -7403,7 +7403,7 @@ zurückschreib zurückschreit zurückseh zurücksehn -zurücksend +zurücksende zurücksetz zurücksink zurücksoll @@ -7619,7 +7619,7 @@ zuschwell zuschwimm zuschütt zuseh -zusend +zusende zusetz zusicher zuspachtel @@ -7767,7 +7767,7 @@ verscherbel verscheuer verschick verschieb -versende +versendee versetz versicher versorg @@ -9101,7 +9101,7 @@ sehn seif seih seil -send +sende seng senk sentier @@ -9380,7 +9380,7 @@ weit weiß welk well -wend +wende werb werbe werd diff --git a/languagetool-language-modules/de/src/test/java/org/languagetool/rules/de/GermanSpellerRuleTest.java b/languagetool-language-modules/de/src/test/java/org/languagetool/rules/de/GermanSpellerRuleTest.java index b0a4cd4d136f..f37ed2d6e0ea 100644 --- a/languagetool-language-modules/de/src/test/java/org/languagetool/rules/de/GermanSpellerRuleTest.java +++ b/languagetool-language-modules/de/src/test/java/org/languagetool/rules/de/GermanSpellerRuleTest.java @@ -77,6 +77,20 @@ public void testGetMessage() { @Test public void testIgnoreMisspelledWord() throws IOException { GermanSpellerRule rule = new GermanSpellerRule(TestTools.getMessages("de"), GERMAN_DE); + assertTrue(rule.ignorePotentiallyMisspelledWord("Perspektivwechsel")); + assertFalse(rule.ignorePotentiallyMisspelledWord("Perspektivewechsel")); + assertFalse(rule.ignorePotentiallyMisspelledWord("Suchemaschine")); + assertTrue(rule.ignorePotentiallyMisspelledWord("Sprachvariante")); + assertFalse(rule.ignorePotentiallyMisspelledWord("Sprachevariante")); + assertFalse(rule.ignorePotentiallyMisspelledWord("Sprachenvariante")); + assertTrue(rule.ignorePotentiallyMisspelledWord("Kontrollgremiums")); + assertFalse(rule.ignorePotentiallyMisspelledWord("Kontrollegremiums")); + assertFalse(rule.ignorePotentiallyMisspelledWord("Kontrollengremiums")); + assertTrue(rule.ignorePotentiallyMisspelledWord("Leuchtfunktion")); + assertFalse(rule.ignorePotentiallyMisspelledWord("Leuchtefunktion")); + assertTrue(rule.ignorePotentiallyMisspelledWord("Schulstreit")); + assertFalse(rule.ignorePotentiallyMisspelledWord("Schulestreit")); + assertFalse(rule.ignorePotentiallyMisspelledWord("Stelleplätze")); assertTrue(rule.ignorePotentiallyMisspelledWord("Herzensanliegen")); assertFalse(rule.ignorePotentiallyMisspelledWord("Herzenanliegen")); assertTrue(rule.ignorePotentiallyMisspelledWord("Vornamensliste"));