67 lines
1.5 KiB
Go
67 lines
1.5 KiB
Go
package i18n
|
|
|
|
import (
|
|
"strings"
|
|
)
|
|
|
|
// Lang is a canonical UI language. Only these three are served.
|
|
type Lang string
|
|
|
|
const (
|
|
ZhCN Lang = "zh-CN"
|
|
En Lang = "en"
|
|
ZhTW Lang = "zh-TW"
|
|
Default = En
|
|
)
|
|
|
|
func (l Lang) String() string {
|
|
if l == "" {
|
|
return string(Default)
|
|
}
|
|
return string(l)
|
|
}
|
|
|
|
// Parse maps Accept-Language, X-Language, or TCP AUTH language to ZhCN / En / ZhTW.
|
|
// Unknown or empty input falls back to Default (en).
|
|
func Parse(raw string) Lang {
|
|
for _, part := range strings.Split(raw, ",") {
|
|
tag, _, _ := strings.Cut(strings.TrimSpace(part), ";")
|
|
if lang, ok := match(tag); ok {
|
|
return lang
|
|
}
|
|
}
|
|
return Default
|
|
}
|
|
|
|
// ParseExplicit requires a recognized language tag; ok is false when raw is empty or unknown.
|
|
func ParseExplicit(raw string) (Lang, bool) {
|
|
raw = strings.TrimSpace(raw)
|
|
if raw == "" {
|
|
return Default, false
|
|
}
|
|
for _, part := range strings.Split(raw, ",") {
|
|
tag, _, _ := strings.Cut(strings.TrimSpace(part), ";")
|
|
if lang, ok := match(tag); ok {
|
|
return lang, true
|
|
}
|
|
}
|
|
return Default, false
|
|
}
|
|
|
|
func match(tag string) (Lang, bool) {
|
|
t := strings.ToLower(strings.ReplaceAll(strings.TrimSpace(tag), "_", "-"))
|
|
if t == "" {
|
|
return "", false
|
|
}
|
|
switch {
|
|
case t == "en" || strings.HasPrefix(t, "en-"):
|
|
return En, true
|
|
case t == "zh-tw" || t == "zh-hk" || t == "zh-mo" || t == "zh-hant" || strings.HasPrefix(t, "zh-hant"):
|
|
return ZhTW, true
|
|
case t == "zh" || t == "zh-cn" || t == "zh-sg" || t == "zh-hans" || strings.HasPrefix(t, "zh-hans"):
|
|
return ZhCN, true
|
|
default:
|
|
return "", false
|
|
}
|
|
}
|