package agent import "strings" // DetectResponseLanguage returns a BCP-47 style language tag for reply policy. // Priority: explicit preference > current user text > last session language > default English. func DetectResponseLanguage(userText, preferred, last string) string { if p := normalizeLang(preferred); p != "" { return p } if detected := detectFromText(userText); detected != "" { return detected } if l := normalizeLang(last); l != "" { return l } return "en" } func detectFromText(text string) string { if text == "" { return "" } var zh, ja, ko, letters int for _, r := range text { switch { case r >= 0x4E00 && r <= 0x9FFF: zh++ case r >= 0x3040 && r <= 0x30FF: ja++ case r >= 0xAC00 && r <= 0xD7AF: ko++ case (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z'): letters++ } } // CJK-first heuristic to match user typing language quickly. if zh > 0 { return "zh-CN" } if ja > 0 { return "ja" } if ko > 0 { return "ko" } if letters > 0 { return "en" } return "" } func normalizeLang(lang string) string { lang = strings.ToLower(lang) switch lang { case "zh", "zh-cn", "zh_hans", "chinese": return "zh-CN" case "en", "en-us", "english": return "en" case "ja", "jp", "japanese": return "ja" case "ko", "kr", "korean": return "ko" default: if lang == "" { return "" } return lang } } // ExtractLanguagePreference detects explicit user instructions for language switch. func ExtractLanguagePreference(text string) string { s := text if s == "" { return "" } enHints := []string{"speak english", "reply in english", "use english"} zhHints := []string{"reply in chinese", "speak chinese", "use chinese"} jaHints := []string{"reply in japanese", "speak japanese", "use japanese"} koHints := []string{"한국어", "reply in korean", "speak korean"} for _, h := range enHints { if strings.Contains(s, h) { return "en" } } for _, h := range zhHints { if strings.Contains(s, h) { return "zh-CN" } } for _, h := range jaHints { if strings.Contains(s, h) { return "ja" } } for _, h := range koHints { if strings.Contains(s, h) { return "ko" } } return "" }