feat(langdetect): deutsche/englische Spracherkennung als reine Funktion
Detect(text) → "de" | "en" (Default "de"): Common-Word-Listen plus Umlaute/ß als Deutsch-Signale; Englisch gewinnt nur bei strikter Mehrheit. Tischgesteuerte Tests für de/en/gemischt/leer.
This commit is contained in:
1 parent
fa4f193be2
commit
de1ef64b8f
3 files changed
+115
-1
No files matched your search
@@ -0,0 +1,77 @@
|
||||
package langdetect
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// Detect erkennt die Sprache eines Ansage-Texts und liefert "de" oder "en".
|
||||
// Default (auch bei leerem oder unentscheidbarem Text) ist "de".
|
||||
//
|
||||
// Heuristik: Common-Word-Listen deutscher und englischer Wörter plus
|
||||
// Umlaute/ß als starke Deutsch-Signale. Englisch gewinnt nur bei strikt
|
||||
// mehr englischen Signalen als deutschen; bei Gleichstand entscheidet der
|
||||
// Default "de". Die Funktion ist rein (kein globaler Zustand, keine IO).
|
||||
func Detect(text string) string {
|
||||
var de, en int
|
||||
for _, r := range text {
|
||||
switch r {
|
||||
case 'ä', 'ö', 'ü', 'ß', 'Ä', 'Ö', 'Ü':
|
||||
de++
|
||||
}
|
||||
}
|
||||
|
||||
for _, word := range strings.FieldsFunc(text, func(r rune) bool {
|
||||
return !unicode.IsLetter(r) && r != '\'' && r != '’'
|
||||
}) {
|
||||
word = strings.ToLower(word)
|
||||
if _, ok := germanWords[word]; ok {
|
||||
de++
|
||||
}
|
||||
if _, ok := englishWords[word]; ok {
|
||||
en++
|
||||
}
|
||||
}
|
||||
|
||||
if en > de {
|
||||
return "en"
|
||||
}
|
||||
return "de"
|
||||
}
|
||||
|
||||
// germanWords sind häufige deutsche Wörter, die im Englischen nicht
|
||||
// vorkommen (Mehrdeutigkeiten wie „was" und „in" wurden weggelassen).
|
||||
var germanWords = map[string]struct{}{
|
||||
"der": {}, "die": {}, "das": {}, "und": {}, "nicht": {}, "ist": {},
|
||||
"ein": {}, "eine": {}, "einen": {}, "einem": {}, "einer": {},
|
||||
"mit": {}, "für": {}, "auf": {}, "von": {}, "vom": {}, "zum": {},
|
||||
"zur": {}, "den": {}, "dem": {}, "des": {}, "wir": {}, "ihr": {},
|
||||
"sie": {}, "auch": {}, "als": {}, "wie": {}, "bei": {},
|
||||
"aus": {}, "nach": {}, "noch": {}, "nur": {}, "schon": {},
|
||||
"wenn": {}, "dann": {}, "aber": {}, "oder": {}, "doch": {},
|
||||
"mehr": {}, "sehr": {}, "über": {}, "unter": {}, "jetzt": {},
|
||||
"hier": {}, "heute": {}, "morgen": {}, "danke": {}, "bitte": {},
|
||||
"erfolgreich": {}, "fehlgeschlagen": {}, "fertig": {},
|
||||
"gestartet": {}, "beendet": {}, "abgeschlossen": {}, "warten": {},
|
||||
"läuft": {}, "kannst": {}, "muss": {}, "soll": {},
|
||||
"kein": {}, "keine": {}, "wieder": {}, "werden": {}, "wurde": {},
|
||||
"wurden": {}, "haben": {}, "geht": {}, "machen": {},
|
||||
}
|
||||
|
||||
// englishWords sind häufige englische Wörter, die im Deutschen nicht
|
||||
// vorkommen.
|
||||
var englishWords = map[string]struct{}{
|
||||
"the": {}, "is": {}, "not": {}, "and": {}, "with": {}, "for": {},
|
||||
"on": {}, "of": {}, "to": {}, "from": {}, "by": {}, "at": {},
|
||||
"or": {}, "but": {}, "if": {}, "then": {}, "when": {}, "how": {},
|
||||
"what": {}, "why": {}, "who": {}, "done": {}, "failed": {},
|
||||
"finished": {}, "started": {}, "completed": {}, "error": {},
|
||||
"warning": {}, "thanks": {}, "you": {}, "your": {},
|
||||
"we": {}, "it": {}, "this": {}, "that": {}, "these": {},
|
||||
"those": {}, "was": {}, "were": {}, "are": {}, "be": {},
|
||||
"been": {}, "has": {}, "have": {}, "had": {}, "can": {},
|
||||
"will": {}, "would": {}, "should": {}, "could": {}, "just": {},
|
||||
"only": {}, "still": {}, "already": {}, "now": {}, "today": {},
|
||||
"tomorrow": {}, "waiting": {}, "running": {}, "please": {},
|
||||
"needs": {}, "need": {}, "succeeded": {},
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package langdetect
|
||||
|
||||
import "testing"
|
||||
|
||||
// TestDetect ist tischgesteuert: Eingabetext → erwartete Sprache.
|
||||
// Der Default "de" gilt für leeren, unentscheidbaren und gemischten
|
||||
// Text ohne englische Mehrheit.
|
||||
func TestDetect(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
text string
|
||||
want string
|
||||
}{
|
||||
{"leer", "", "de"},
|
||||
{"nur whitespace", " \n\t ", "de"},
|
||||
{"nur interpunktion", "!!! ??? ...", "de"},
|
||||
{"deutsch satz", "Der Build wurde erfolgreich abgeschlossen und das Deployment ist fertig.", "de"},
|
||||
{"deutsch umlaute", "Größe früh Ärzteübung — schön daß es klappt", "de"},
|
||||
{"ß alleine", "weiß", "de"},
|
||||
{"englisch satz", "The build has finished and the deployment is done.", "en"},
|
||||
{"englisch imperativ", "Please wait until the tests are green.", "en"},
|
||||
{"englisch kurz", "done", "en"},
|
||||
{"gemischt englisch dominiert", "the build is done and ready for you", "en"},
|
||||
{"gemischt deutsch dominiert", "Der build ist done und fertig für dich", "de"},
|
||||
{"gemischt gleichstand", "der the", "de"},
|
||||
{"unklare sprache", "Build 2026-10-18 14:22 UTC", "de"},
|
||||
{"agenten-typisch en", "Task completed. Please review the changes and approve.", "en"},
|
||||
{"agenten-typisch de", "Aufgabe abgeschlossen. Bitte prüfen und freigeben.", "de"},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
if got := Detect(tc.text); got != tc.want {
|
||||
t.Errorf("Detect(%q) = %q, want %q", tc.text, got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Package langdetect erkennt die Sprache eines Ansage-Texts als reine
|
||||
// Funktion Detect(text) → "de" | "en" (Default "de"; Heuristik über
|
||||
// Common-Word-Listen und Umlaute/ß). Implementierung folgt in Task 02.
|
||||
// Common-Word-Listen und Umlaute/ß).
|
||||
package langdetect
|
||||
Reference in new issue
Block a user