Die normale Textkorrektur mit aspell (oder ispell oder hunspell) prüft leider nur einzelne Wörter. Fehler bei der Groß-/Kleinschreibung und Grammatikfehler werden zum Beispiel häufig nicht erkannt: »Die Text ist am Besten.« Das Programm LanguageTool hingegen kann dies, weshalb es sich als Ergänzung oder Ersatz für die Textprüfung lohnt. Da das Programm unter der LGPL entwickelt wird, steht der Quelltext zur Verfügung und somit lässt sich eine eigene Instanz einrichten.
Installation
Für LanguageTool wird die Java-Umgebung benötigt: apt install
default-jre-headless
oder konkret eine aktuelle Version von OpenJDK apt
install openjdk-11-jre-headless
. Das Paket mit LanguageTool muss von dessen
Webseite
(Alternative) geladen und in ein
Verzeichnis entpackt werden:
% wget https://languagetool.org/download/LanguageTool-stable.zip
% sudo unzip LanguageTool-stable.zip -d /opt
% sudo mv /opt/LanguageTool-stable /opt/LanguageTool
Um zu prüfen, ob die Installation funktioniert, kann man das Kommandozeilenprogramm von LanguageTool verwenden und einen einfachen Text überprüfen lassen:
% java -Dfile.encoding=UTF-8 -jar /opt/LanguageTool/languagetool-commandline.jar -c utf8 -l de-DE <<<'Die Text ist am Besten.'
Expected text language: German (Germany)
Working on STDIN...
1.) Line 1, column 1, Rule ID: DE_AGREEMENT
Message: Möglicherweise fehlende grammatische Übereinstimmung des Genus (männlich, weiblich, sächlich - Beispiel: 'der Fahrrad' statt 'das Fahrrad') und Numerus (Einzahl, Mehrzahl - Beispiel: 'das Fahrräder' statt 'die Fahrräder').
Suggestion: Dem Text; Den Text; Der Text; Die Texte
Die Text ist am Besten.
^^^^^^^^
2.) Line 1, column 17, Rule ID: AM_BESTEN[1]
Message: In der Wendung 'am besten' schreibt man 'besten' klein.
Suggestion: besten
Die Text ist am Besten.
^^^^^^
More info: https://www.korrekturen.de/beliebte_fehler/am-besten.shtml
Time: 1496ms for 1 sentences (0.7 sentences/sec)
Daten für n-Gramme installieren
Zur Verbesserung der Fehlererkennung gibt es Erweiterungsdaten für n-Gramme. Die Idee dahinter ist, die Korrektheit von Wörtern mithilfe eines, zweier oder mehrerer Nachbarwörter zu prüfen, also ob das Wort in die Wortgruppe passt.
Vorsicht: Diese Daten sind mehrere Gigabyte groß, also darauf achten, ob das Verzeichnis vom Backup erfasst wird.
Die gewünschten Pakete von languagetool.org/download/ngram-data/ laden und in ein Verzeichnis (z. B. /opt/LanguageTool-ngram) entpacken.
Den Unterschied in der Fehlererkennung sieht man an diesem Beispiel:
% java -Dfile.encoding=UTF-8 -jar /opt/LanguageTool/languagetool-commandline.jar -c utf8 -l de-DE <<<'In den christlichen Traditionen gibt es unterschiedliche Anleitungen zur Mediation und Kontemplation.'
Expected text language: German (Germany)
Working on STDIN...
Time: 1458ms for 1 sentences (0.7 sentences/sec)
java -enableassertions -Dfile.encoding=UTF-8 -jar -c utf8 -l de-DE <<< usr 15,35s sys 0,41s tot 4,838 698MB pf 0 182680 cs 8453 5425
% java -Dfile.encoding=UTF-8 -jar /opt/LanguageTool/languagetool-commandline.jar -c utf8 -l de-DE --languagemodel /opt/LanguageTool-ngram <<<'In den christlichen Traditionen gibt es unterschiedliche Anleitungen zur Mediation und Kontemplation.'
Expected text language: German (Germany)
Working on STDIN...
1.) Line 1, column 74, Rule ID: CONFUSION_RULE
Message: Rein statistisch ist 'Meditation' (spirituelle Übung) in diesem Kontext wahrscheinlicher als 'Mediation' (Verfahren zur Konfliktlösung). Bitte prüfen.
Suggestion: Meditation
...nen gibt es unterschiedliche Anleitungen zur Mediation und Kontemplation.
^^^^^^^^^
Time: 1583ms for 1 sentences (0.6 sentences/sec)
java -enableassertions -Dfile.encoding=UTF-8 -jar -c utf8 -l de-DE <<< usr 17,46s sys 0,41s tot 5,355 701MB pf 0 181455 cs 9875 6135
Daten für word2vec einrichten
Es gibt noch eine weitere Erweiterung für die Erkennung von Fehlern, die mit einem Word2vec-Modell für ein neuronales Netzwerk arbeitet. Aktuell (Juli 2020) funktioniert sie, jedoch kümmert sich nicht niemand mehr um den Code.
Ein Beispiel für die verbesserte Erkennung zeigt sich an diesem Text:
Ich glaube, das der Spieleabend gut besucht sein wir, da wir fiel Werbung gemacht haben. Was machst du den da? Ab wann seit ihr in der Uni? Ich bin gerade ihm Copyshop.
Ob die Erkennung funktioniert, lässt sich mit folgendem kleinen Beispiel prüfen:
% java -Dfile.encoding=UTF-8 -jar /opt/LanguageTool/languagetool-commandline.jar \
-c utf8 -l de-DE --languagemodel /opt/LanguageTool-ngram \
--word2vecmodel /opt/LanguageTool-word2vec <<<'Was machst du den da?'
Expected text language: German (Germany)
Working on STDIN...
1.) Line 1, column 15, Rule ID: DE_den_VS_denn_NEURALNETWORK
Message: Unser neuronales Netz sagt, dass 'denn' hier korrekt sein könnte statt 'den'. Bitte prüfen.
Suggestion: denn
Was machst du den da?
^^^
Time: 1341ms for 1 sentences (0.7 sentences/sec)
Bessere Spracherkennung mit Fasttext
Es gibt noch ein Modul für bessere Spracherkennung, aber deren Sinn hat sich mir nicht so richtig erschlossen. Bei gemischtsprachigen Texten war die Erkennung auch nicht besser und sonst gebe ich immer die Sprache an. Vielleicht ist es für Texte, bei denen keine Sprache angegeben wurde.
Für Fasttext sind zwei Dinge
notwendig: eine
Datenbank und ein Programm. Die Datenbank lid.176.bin muss man von der Seite
fastText laden und
beim Aufruf des Kommandozeilenprogramms mittels --fasttextbinary …
mit dem
Dateinamen angeben.
Das Programm fasttext kann man entweder aus den Quellen
bauen oder man nutzt das
Debian-Paket. Beim Aufruf des
Kommandozeilenprogramms muss man den Pfad zum Programm mit --fasttextbinary …
angeben.
Der Dienst, wie er im Abschnitt über Systemd genutzt wird, benötigt für Fasttext eine Konfigurationsdatei, in der die Pfade angegeben werden:
fasttextModel=/opt/LanguageTool-fasttext-lid.176.bin
fasttextBinary=/usr/bin/fasttext
Beschleunigung der Abfragen
In einer Forumsdiskussion habe ich Einstellungen gefunden, die die Antwortgeschwindigkeit wesentlich beschleunigen. Hierfür muss LanguageTool mit einer Konfigurationsdatei mit folgendem Inhalt gestartet werden:
pipelineCaching=true
maxPipelinePoolSize=500
pipelineExpireTimeInSeconds=3600
Die Datei habe ich der Einfachheit halber als /etc/opt/languagetool.cfg
abgelegt und dem Start die Option --config /etc/opt/languagetool.cfg
ergänzt.
Der Vergleich der beiden Varianten lässt sich sehr schön mit dem Rust-Programm
hyperfine vornehmen (Installation mit
cargo install hyperfine
). Dem Programm werden einfach mehrere Programmaufrufe
übergeben, die dann mehrfach aufgerufen und deren Laufzeit gemessen wird. Als
Beispiele habe ich eine sehr einfache Abfrage und eine Abfrage des
Firefox-Add-ons verwendet.
% hyperfine --warmup 3 \
'curl -s --data "language=de-DE&text=Eine erster Versuch" http://localhost:8081/v2/check' \
"curl -s http://localhost:8081/v2/check?c=1 \
--data-raw 'data=%7B%22text%22%3A%22Einen+guten+Morgen%22%7D&textSessionId=56639%3A1637566034156&enableHiddenRules=true&motherTongue=de&level=picky&language=auto&noopLanguages=de%2Cen&preferredLanguages=de%2Cen&preferredVariants=en-GB%2Cde-DE%2Cpt-BR%2Cca-ES&disabledRules=WHITESPACE_RULE%2CCONSECUTIVE_SPACES&mode=textLevelOnly'"
Werte ohne die Konfigurationsdatei:
Benchmark 1: curl -s --data "language=de-DE&text=Eine erster Versuch" http://localhost:8081/v2/check
Time (mean ± σ): 440.5 ms ± 48.1 ms [User: 5.2 ms, System: 1.6 ms]
Range (min … max): 387.3 ms … 547.8 ms 10 runs
Benchmark 2: curl -s http://localhost:8081/v2/check?c=1 --data-raw 'data=%7B%22text%22%3A%22Einen+guten+Morgen%22%7D&textSessionId=56639%3A1637566034156&enableHiddenRules=true&motherTongue=de&level=picky&language=auto&noopLanguages=de%2Cen&preferredLanguages=de%2Cen&preferredVariants=en-GB%2Cde-DE%2Cpt-BR%2Cca-ES&disabledRules=WHITESPACE_RULE%2CCONSECUTIVE_SPACES&mode=textLevelOnly'
Time (mean ± σ): 82.1 ms ± 10.6 ms [User: 5.2 ms, System: 1.7 ms]
Range (min … max): 72.4 ms … 119.5 ms 31 runs
Werte mit der Konfigurationsdatei:
Benchmark 1: curl -s --data "language=de-DE&text=Eine erster Versuch" http://localhost:8081/v2/check
Time (mean ± σ): 34.0 ms ± 3.5 ms [User: 5.3 ms, System: 1.6 ms]
Range (min … max): 30.7 ms … 50.0 ms 87 runs
Benchmark 2: curl -s http://localhost:8081/v2/check?c=1 --data-raw 'data=%7B%22text%22%3A%22Einen+guten+Morgen%22%7D&textSessionId=56639%3A1637566034156&enableHiddenRules=true&motherTongue=de&level=picky&language=auto&noopLanguages=de%2Cen&preferredLanguages=de%2Cen&preferredVariants=en-GB%2Cde-DE%2Cpt-BR%2Cca-ES&disabledRules=WHITESPACE_RULE%2CCONSECUTIVE_SPACES&mode=textLevelOnly'
Time (mean ± σ): 10.3 ms ± 0.5 ms [User: 4.4 ms, System: 2.2 ms]
Range (min … max): 9.5 ms … 13.4 ms 278 runs
Systemd einrichten
Die Einrichtung des Servers ist
recht einfach, jedoch sollte bedacht werden, dass der Prozess im Betrieb auf
eine Größe von 2,5 Gigabyte RAM anwächst. Der Dienst ist ein HTTP-Server (ohne
SSL), der auf dem Port 8081 lauscht. Wenn man mit --port …
einen anderen Port
wählt, muss man im Browser-Addon als Serveradresse http://localhost:…/v2
angeben.
Wie immer lässt sich ein solcher Dienst leicht mit Systemd einrichten: sudo
systemctl edit --force --full languagetool.service
:
[Unit]
Description=Language checking backend LanguageTool
Documentation=https://languagetool.org/
Documentation=http://wiki.languagetool.org/http-server
[Service]
SyslogIdentifier=langtool
ExecStart=/usr/bin/java -cp /opt/LanguageTool/languagetool-server.jar \
org.languagetool.server.HTTPServer --allow-origin * \
--config /etc/opt/languagetool.cfg \
--languageModel /opt/LanguageTool-ngram \
--word2vecModel /opt/LanguageTool-word2vec
UMask=0077
User=daemon
Group=daemon
# OOM killer should prefer this process
OOMPolicy=kill
OOMScoreAdjust=800
# Common security settings 'https://jo-so.de/2021-05/H%C3%A4rtung-Systemd.html'
CapabilityBoundingSet=
LockPersonality=true
MemoryDenyWriteExecute=true
NoNewPrivileges=true
PrivateDevices=true
PrivateTmp=true
ProtectClock=true
ProtectControlGroups=true
ProtectHostname=true
ProtectKernelLogs=true
ProtectKernelModules=true
ProtectKernelTunables=true
# strict: mounts the whole system read-only
# full: mount only /var as read-write
# true: mount /var and /etc as read-write
ProtectSystem=strict
# Make some paths writable
#ReadWritePaths=/…
ProtectHome=true
# Make sure that the process can only see PIDs and process details of itself,
# and the second option disables seeing details of things like system load and
# I/O etc
ProtectProc=invisible
ProcSubset=pid
RemoveIPC=true
RestrictAddressFamilies=AF_UNIX
RestrictNamespaces=true
RestrictRealtime=true
RestrictSUIDSGID=true
SystemCallArchitectures=native
SystemCallFilter=@system-service
SystemCallFilter=~@privileged @resources @obsolete
# end of common security settings
MemoryDenyWriteExecute=false
RestrictAddressFamilies=AF_INET
[Install]
WantedBy=default.target
Danach den Dienst aktivieren und gleich starten sudo systemctl enable --now
languagetool.service
und mit einer einfach Abfrage prüfen:
% curl -s --data "language=de-DE&text=Eine erster Versuch" http://localhost:8081/v2/check |jq .
{
"software": {
"name": "LanguageTool",
"version": "4.9.1",
"buildDate": "2020-04-27 15:56",
"apiVersion": 1,
"premium": false,
"premiumHint": "You might be missing errors only the Premium version can find. Contact us at support<at>languagetoolplus.com.",
"status": ""
},
"warnings": {
"incompleteResults": false
},
"language": {
"name": "German (Germany)",
"code": "de-DE",
"detectedLanguage": {
"name": "German (Germany)",
"code": "de-DE",
"confidence": 0.9999903
}
},
"matches": [
{
"message": "Möglicherweise fehlende grammatische Übereinstimmung von Kasus, Numerus oder Genus. Beispiel: 'mein kleiner Haus' statt 'mein kleines Haus'",
"shortMessage": "Möglicherweise keine Übereinstimmung von Kasus, Numerus oder Genus",
"replacements": [],
"offset": 0,
"length": 19,
"context": {
"text": "Eine erster Versuch",
"offset": 0,
"length": 19
},
"sentence": "Eine erster Versuch",
"type": {
"typeName": "Other"
},
"rule": {
"id": "DE_AGREEMENT",
"description": "Kongruenz von Nominalphrasen (unvollständig!), z.B. 'mein kleiner(kleines) Haus'",
"issueType": "uncategorized",
"category": {
"id": "GRAMMAR",
"name": "Grammatik"
}
},
"ignoreForIncompleteSentence": true,
"contextForSureMatch": 6
}
]
}
Browser-Addon
Für den Browser Firefox, aber auch für Chrome, gibt es ein Addon, damit während der Eingabe die Rechtschreibkontrolle von LanguageTool genutzt wird. An vielen Stellen ist dies praktisch, aber bei Chats nervt es zum Teil, da man dort nicht immer exaktes Deutsch schreibt. Weiterhin hat die Erweiterung den Nachteil, dass die Korrekturvorschläge mit einem Links-Klick und nicht mit der rechten Maustaste erscheinen und somit die Menütaste an der Tastatur nicht genutzt werden kann. Die Prüfung mit LanguageTool ist auch nicht so schnell wie die eingebaute Rechtschreibprüfung, weshalb man oft Tippfehler erst einige Worte später angezeigt bekommt und dann zurück zum Wort laufen muss und dann wieder an die Tippposition.
Vorsicht ist auch bei der Erweiterung geboten, da man zum Teil sensible
Texte (auch Passwörter z. B. bei /join #channel key
bei IRC und Matrix)
eintippt, die dann an einen Server übertragen werden. Die Erweiterung sollte
also nur mit einem vertrauenswürdigen Server genutzt werden.
Den Server kann man in den Einstellungen zum Addon unter Experimental settings (only for advanced users) auf Local server (localhost) oder einen anderen umschalten.
Emacs-Mode langtool für Servernutzung
Für Emacs gibt es das Melpa-Paket langtool, mit dem man einen LanguageTool-Server nutzen kann. Aber auch hier ist die Warnung wie beim Firefox-Addon: Es sollte nur ein vertrauenswürdiger Server genutzt werden, da alle Texte dorthin gesandt werden.
Die Installation ist recht leicht über M-x package-list-packages
und die
Konfiguration in der init.el ist übersichtlich kurz:
(setq
langtool-http-server-host "localhost"
langtool-http-server-port 8081
langtool-mother-tongue "de-DE"
langtool-default-language "de-DE"
)
Nutzen lässt sich die Textprüfung mit M-x langtool-check
, womit der aktive
Bereich oder die gesamte Datei geprüft werden. Fehler werden dann hervorgehoben
und können mit M-x langtool-correct-buffer
schrittweise bearbeitet werden. Die
Textprüfung kann mit M-x langtool-check-done
abgeschlossen werden, wodurch die
Hervorhebungen verschwinden.
Nützlich ist es, mit M-h
den aktuellen Absatz als Region vor der Prüfung zu
markieren.
Wenn man mit langtool-correct-buffer die Fehlerstellen durchgeht, kann man mit
- der Leertaste auch Fehler überspringen
i
ein Wort im gesamten Dokument ignorierene
den Text direkt bearbeiten, wobei man mitC-M-c
(Strg+Alt+c
) die Bearbeitung beenden kann.
Emacs-Mode languagetool für lokale Nutzung
Den ersten Versuch habe ich mit dem Melpa-Paket
languagetoool
(Installation über M-x package-list-packages
) unternommen, welches den Vorteil
hat, dass es LanguageTool als Prozess aufruft und über eine Standardein- und
-ausgabe kommuniziert. Da ich dann aber auch das Firefox-Addon genutzt habe,
brauchte ich die Servervariante und bin daher auf das Emacs-Paket langtool
umgestiegen.
(setq
languagetool-language-tool-jar (expand-file-name
"/opt/LanguageTool/languagetool-commandline.jar")
languagetool-java-arguments '("-Dfile.encoding=UTF-8")
languagetool-default-language "de-DE"
languagetool-mother-tongue "de-DE"
languagetool-language-tool-arguments '("--languagemodel"
(expand-file-name "/opt/LanguageTool-ngram"))
)
Die Prüfung des Textes kann man mit M-x languagetool-check
vornehmen, ggf.
zuvor mit M-h
den Paragraph markieren. Fehler und Statusmeldungen findet man
im Puffer *LanguageTool Output*.
Beispiele für Fehlererkennung
Im Leben lernt der Mensch als erstes ["Erstes" scheint hier ein Nomen zu sein und muss dann großgeschrieben werden.] das Gehen und Sprechen. Später lernt er still zu sitzen [Wenn der erweiterte Infinitv von dem Verb 'stillsitzen' abgeleitet ist, sollte er zusammengeschrieben werden.] und den Mund zu halten.
Addin für Word
Auf der Webseite wird eine Erweiterung für Microsoft Word angeboten, jedoch habe ich dafür nicht den Quelltext finden können und beim Laden im Microsoft Store werden persönliche Daten wie die Telefonnummer abgefragt. Daher sollte man von diesem Addin abstand nehmen.
Stattdessen sollte besser diese freie Erweiterung für Word genutzt werden.
Weitere Informationen
Bei LWN gibt es den Beitrag »Tools to improve English text«, der auch LanguageTool als hilfreich erwähnt, aber noch weitere Programme aufführt. Das Ziel des Artikels sind die Dokumentation von Software, weshalb auch recht spezielle Programme genannt werden:
- Codespell sucht nach typischen Fehlern in Quelltext. Der Vorteil ist, dass es zwischen Programmcode und Dokumentation unterscheiden kann.
- Vale ist wie ein Coding-Style-Prüfer nur eben für Texte. Man kann ein Regelwerk verfassen, um eine Einheitlichkeit in den Texten zu erreichen. Das ist hilfreich, wenn unterschiedliche Leute (durch Patches) an einem Text schreiben.
- RedPen scheint ähnlich wie LanguageTool eine umfassendere Prüfung vorzunehmen, u. a. werden auch wiederholte Wortvorkommen geprüft. Es gibt eine Online-Demo jedoch ohne Deutsch.