detector.go

 1package i18n
 2
 3import (
 4	"os"
 5	"strings"
 6
 7	"github.com/floatpane/matcha/config"
 8)
 9
10// DetectLanguage determines the language to use based on config and environment.
11func DetectLanguage(cfg *config.Config) string {
12	// 1. Check config first
13	if lang := detectFromConfig(cfg); lang != "" {
14		return normalizeLanguageCode(lang)
15	}
16
17	// 2. Check environment variables
18	if lang := detectFromEnv(); lang != "" {
19		return normalizeLanguageCode(lang)
20	}
21
22	// 3. Default to English
23	return "en"
24}
25
26// detectFromConfig gets language from configuration.
27func detectFromConfig(cfg *config.Config) string {
28	if cfg == nil {
29		return ""
30	}
31	return cfg.GetLanguage()
32}
33
34// detectFromEnv gets language from environment variables.
35func detectFromEnv() string {
36	// Check standard language environment variables
37	for _, envVar := range []string{"LANGUAGE", "LC_ALL", "LC_MESSAGES", "LANG"} {
38		if lang := os.Getenv(envVar); lang != "" {
39			return lang
40		}
41	}
42	return ""
43}
44
45// normalizeLanguageCode converts various language code formats to a standard form.
46// Examples:
47//   - "en_US.UTF-8" -> "en"
48//   - "en-US" -> "en"
49//   - "pt_BR" -> "pt"
50func normalizeLanguageCode(code string) string {
51	if code == "" {
52		return ""
53	}
54
55	// Remove encoding (e.g., ".UTF-8")
56	if idx := strings.Index(code, "."); idx != -1 {
57		code = code[:idx]
58	}
59
60	// Replace underscore with hyphen
61	code = strings.ReplaceAll(code, "_", "-")
62
63	// Split on hyphen and take base language
64	parts := strings.Split(code, "-")
65	if len(parts) > 0 {
66		base := strings.ToLower(parts[0])
67
68		// Validate it's a known language
69		if HasLanguage(base) {
70			return base
71		}
72	}
73
74	return code
75}