Files
langx/common_test.go
T

118 lines
3.7 KiB
Go
Raw Permalink Normal View History

2026-09-20 22:20:16 +08:00
package langx_test
import (
"context"
"testing"
"github.com/yuninks/langx"
)
func TestGetCtxLang(t *testing.T) {
reset(t)
langx.RegisterTrans("zh", map[string]string{"k": "中文"})
langx.RegisterTrans("en", map[string]string{"k": "English"})
mustInit(t, langx.SetDefaultLanguage("zh"))
// Accept-Language 会与已注册语言协商, 而不是原样返回
ctx := context.WithValue(context.Background(), "Accept-Language", "en-US,en;q=0.9")
if got := langx.GetCtxLang(ctx); got != "en" {
t.Fatalf("GetCtxLang = %q, 期望 en", got)
}
if got := langx.GetMsgCtx(ctx, "k"); got != "English" {
t.Fatalf("GetMsgCtx = %q", got)
}
// []string 形式(http.Header 风格)
ctx = context.WithValue(context.Background(), "Accept-Language", []string{"en-GB"})
if got := langx.GetMsgCtx(ctx, "k"); got != "English" {
t.Fatalf("[]string 形式 = %q", got)
}
// 空 []string
ctx = context.WithValue(context.Background(), "Accept-Language", []string{})
if got := langx.GetCtxLang(ctx); got != "zh" {
t.Fatalf("空 []string = %q", got)
}
// 无法协商时回落默认语言
ctx = context.WithValue(context.Background(), "Accept-Language", "fr-FR,de;q=0.8")
if got := langx.GetCtxLang(ctx); got != "zh" {
t.Fatalf("无法协商 = %q", got)
}
// 通配符
ctx = context.WithValue(context.Background(), "Accept-Language", "*")
if got := langx.GetCtxLang(ctx); got != "zh" {
t.Fatalf("通配符 = %q", got)
}
// 显式设置的语言即使没注册也照用
if got := langx.GetCtxLang(langx.SetCtxLang(context.Background(), "fr")); got != "fr" {
t.Fatalf("显式未注册语言 = %q", got)
}
// 空字符串的显式设置会被忽略
if got := langx.GetCtxLang(langx.SetCtxLang(context.Background(), " ")); got != "zh" {
t.Fatalf("空显式语言 = %q", got)
}
}
// 旧实现在这里会 panic, 现在必须安全回退
func TestGetCtxLangNeverPanics(t *testing.T) {
reset(t)
langx.RegisterTrans("zh", map[string]string{"k": "中文"})
mustInit(t, langx.SetDefaultLanguage("zh"))
if got := langx.GetCtxLang(nil); got != "zh" {
t.Fatalf("nil ctx = %q", got)
}
if got := langx.GetMsgCtx(nil, "k"); got != "中文" {
t.Fatalf("nil ctx GetMsgCtx = %q", got)
}
for _, value := range []interface{}{123, []int{1}, struct{}{}, true} {
ctx := context.WithValue(context.Background(), "Accept-Language", value)
if got := langx.GetCtxLang(ctx); got != "zh" {
t.Fatalf("非法类型 %T = %q", value, got)
}
}
}
func TestParseAcceptLanguage(t *testing.T) {
cases := []struct {
in string
want []string
}{
{"zh-CN,zh;q=0.9,en;q=0.8", []string{"zh-cn", "zh", "en"}},
{"en;q=0.5,zh;q=1.0", []string{"zh", "en"}},
{"en", []string{"en"}},
{" EN-US , zh ", []string{"en-us", "zh"}},
{"*", []string{"*"}},
{"de;q=0", nil},
{"", nil},
{" , ,, ", nil},
{"garbage;;q=x,en", []string{"garbage", "en"}},
{"zh;q=1;charset=utf-8,en;q=0.7", []string{"zh", "en"}},
}
for _, c := range cases {
got := langx.ParseAcceptLanguage(c.in)
assertStrings(t, "ParseAcceptLanguage("+c.in+")", got, c.want)
}
}
func TestNegotiateLang(t *testing.T) {
reset(t)
// 未注册任何语言时无法协商
if got := langx.NegotiateLang("en"); got != "" {
t.Fatalf("无语言时 = %q", got)
}
langx.RegisterTrans("zh", map[string]string{"k": "中文"})
langx.RegisterTrans("en-GB", map[string]string{"k": "English"})
if got := langx.NegotiateLang("en-GB,en;q=0.9"); got != "en-gb" {
t.Fatalf("精确匹配 = %q", got)
}
if got := langx.NegotiateLang("en-US,en;q=0.9"); got != "en-gb" {
t.Fatalf("区域回退 = %q", got)
}
if got := langx.NegotiateLang("fr,zh;q=0.3"); got != "zh" {
t.Fatalf("跳过不支持的语言 = %q", got)
}
if got := langx.NegotiateLang("fr"); got != "" {
t.Fatalf("无匹配 = %q", got)
}
}