locale.go RawHistoryFolder
1package environment
2
3import (
4 "log"
5 "os"
6 "os/exec"
7 "strings"
8)
9
10// DetectAndSetKeyboardLocale attempts to determine the current keyboard layout
11// and hints it to the webkit input layer for accelerator compatibility.
12func DetectAndSetKeyboardLocale() {
13 const colonSplitParts = 2 // Number of parts when splitting on colon
14
15 // 0) Explicit override
16 locale := os.Getenv("DUMBER_KEYBOARD_LOCALE")
17 if locale == "" {
18 locale = os.Getenv("DUMB_BROWSER_KEYBOARD_LOCALE") // legacy prefix
19 }
20 // 1) Environment
21 if locale == "" {
22 locale = os.Getenv("LC_ALL")
23 }
24 if locale == "" {
25 locale = os.Getenv("LANG")
26 }
27 if locale == "" {
28 locale = os.Getenv("LC_CTYPE")
29 }
30 // Trim variants
31 if i := strings.IndexByte(locale, '.'); i > 0 {
32 locale = locale[:i]
33 }
34 if i := strings.IndexByte(locale, '@'); i > 0 {
35 locale = locale[:i]
36 }
37 if i := strings.IndexByte(locale, '_'); i > 0 {
38 locale = locale[:i]
39 }
40
41 // 2) Try XKB env override
42 if locale == "" {
43 locale = os.Getenv("XKB_DEFAULT_LAYOUT")
44 }
45
46 // 3) Best-effort probe of setxkbmap/localectl (non-fatal)
47 if locale == "" {
48 if out, err := exec.Command("localectl", "status").Output(); err == nil {
49 s := string(out)
50 for _, line := range strings.Split(s, "\n") {
51 line = strings.TrimSpace(line)
52 if strings.HasPrefix(strings.ToLower(line), "x11 layout:") || strings.HasPrefix(strings.ToLower(line), "keyboard layout:") {
53 parts := strings.SplitN(line, ":", colonSplitParts)
54 if len(parts) == colonSplitParts {
55 cand := strings.TrimSpace(parts[1])
56 if cand != "" {
57 locale = cand
58 }
59 }
60 break
61 }
62 }
63 }
64 }
65 if locale == "" {
66 if out, err := exec.Command("setxkbmap", "-query").Output(); err == nil {
67 s := string(out)
68 for _, line := range strings.Split(s, "\n") {
69 line = strings.TrimSpace(line)
70 if strings.HasPrefix(strings.ToLower(line), "layout:") {
71 parts := strings.SplitN(line, ":", colonSplitParts)
72 if len(parts) == colonSplitParts {
73 cand := strings.TrimSpace(parts[1])
74 if cand != "" {
75 locale = cand
76 }
77 }
78 break
79 }
80 }
81 }
82 }
83
84 if locale == "" {
85 locale = "en"
86 }
87 // No layout-specific remaps; log for diagnostics only
88 log.Printf("[locale] keyboard locale detected: %s", locale)
89}