-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathlang.py
More file actions
52 lines (47 loc) · 1.55 KB
/
lang.py
File metadata and controls
52 lines (47 loc) · 1.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
from _collections_abc import MutableMapping
import locale
import os
def _langFromEnv(env: MutableMapping) -> str | None:
# 1) GNU LANGUAGE: colon-separated fallbacks (e.g., "de:en_US:en")
lng = env.get("LANGUAGE")
if lng:
for part in lng.split(":"):
part = part.strip()
if part:
return part
# 2) POSIX locale vars in order of precedence
for var in ("LC_ALL", "LC_MESSAGES", "LANG"):
val = env.get(var)
if val and val not in ("C", "POSIX"):
return val
# 3) locale module fallback (works cross-platform-ish)
try:
locale.setlocale(locale.LC_CTYPE, "") # load user default
except locale.Error:
pass
lang, _enc = locale.getlocale() # e.g. "de_DE"
return lang
def _normLang(tag: str) -> str:
# "de-DE.UTF-8" -> "de_DE"
tag = tag.replace("-", "_")
if "." in tag:
tag = tag.split(".", 1)[0]
return tag
def pickLanguage[T: str](supported: list[T], default: T) -> T:
"""Return best match like 'de' or 'de_DE' from supported codes."""
(raw, _) = locale.getlocale()
if not raw:
raw = _langFromEnv(os.environ)
if not raw:
return default
want = _normLang(raw)
# exact match first
for s in supported:
if _normLang(s).lower() == want.lower():
return s
# fallback to language-only match (de_DE -> de)
wantBase = want.split("_")[0].lower()
for s in supported:
if _normLang(s).split('_')[0].lower() == wantBase:
return s
return default