-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
youthlin
committed
Jun 25, 2023
1 parent
4bb56f3
commit b7930c5
Showing
4 changed files
with
144 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package t | ||
|
||
import "context" | ||
|
||
type ( | ||
typeLang struct{} | ||
typeDomain struct{} | ||
) | ||
|
||
var ( | ||
keyLang = typeLang{} | ||
keyDomain = typeDomain{} | ||
) | ||
|
||
func SetCtxLocale(ctx context.Context, lang string) context.Context { | ||
return context.WithValue(ctx, keyLang, lang) | ||
} | ||
|
||
func SetCtxDomain(ctx context.Context, domain string) context.Context { | ||
return context.WithValue(ctx, keyDomain, domain) | ||
} | ||
|
||
func GetCtxLocale(ctx context.Context) (string, bool) { | ||
v := ctx.Value(keyLang) | ||
lang, ok := v.(string) | ||
return lang, ok | ||
} | ||
|
||
func GetCtxDomain(ctx context.Context) (string, bool) { | ||
v := ctx.Value(keyDomain) | ||
domain, ok := v.(string) | ||
return domain, ok | ||
} | ||
|
||
func WithContext(ctx context.Context) *Translations { | ||
t := Global() | ||
if lang, ok := GetCtxLocale(ctx); ok { | ||
t = t.L(lang) | ||
} | ||
if domain, ok := GetCtxDomain(ctx); ok { | ||
t = t.D(domain) | ||
} | ||
return t | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package t | ||
|
||
import ( | ||
"context" | ||
"reflect" | ||
"testing" | ||
) | ||
|
||
func TestWithContext(t *testing.T) { | ||
ctx := context.Background() | ||
type args struct { | ||
ctx context.Context | ||
} | ||
tests := []struct { | ||
name string | ||
args args | ||
want *Translations | ||
}{ | ||
{name: "init", args: args{ctx: ctx}, want: NewTranslations()}, | ||
{name: "locale", args: args{ctx: SetCtxLocale(ctx, "zh_CN")}, want: NewTranslations().L("zh_CN")}, | ||
{name: "domain", args: args{ctx: SetCtxDomain(ctx, "my-domain")}, want: NewTranslations().D("my-domain")}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
if got := WithContext(tt.args.ctx); !reflect.DeepEqual(got, tt.want) { | ||
t.Errorf("WithContext() = %v, want %v", got, tt.want) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package t | ||
|
||
import ( | ||
"net/http" | ||
|
||
"golang.org/x/text/language" | ||
) | ||
|
||
type httpConfig struct { | ||
cookieName string | ||
} | ||
type getUserLangOpt func(*httpConfig) | ||
|
||
func WithCookieName(cookieName string) getUserLangOpt { | ||
return func(hc *httpConfig) { hc.cookieName = cookieName } | ||
} | ||
|
||
const HTTPHeaderAcceptLanguage = "Accept-Language" | ||
|
||
func GetUserLang(request *http.Request, opts ...getUserLangOpt) string { | ||
cfg := &httpConfig{cookieName: "lang"} | ||
for _, opt := range opts { | ||
opt(cfg) | ||
} | ||
if cookie, err := request.Cookie(cfg.cookieName); err == nil { | ||
return cookie.Value | ||
} | ||
|
||
langs := Locales() | ||
var supported []language.Tag // 转换为 Tag | ||
for _, lang := range langs { | ||
supported = append(supported, language.Make(lang)) | ||
} | ||
matcher := language.NewMatcher(supported) // 匹配器 | ||
acceptLangs := request.Header.Get(HTTPHeaderAcceptLanguage) // 用户支持的语言 | ||
userAccept, _, _ := language.ParseAcceptLanguage(acceptLangs) // 转为 Tag | ||
_, index, _ := matcher.Match(userAccept...) // 找到最匹配的语言 | ||
return langs[index] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package t | ||
|
||
import ( | ||
"net/http" | ||
"testing" | ||
) | ||
|
||
func TestGetUserLang(t *testing.T) { | ||
r, _ := http.NewRequest("GET", "/", nil) | ||
r.AddCookie(&http.Cookie{Name: "language", Value: "zh_CN"}) | ||
r.Header.Add(HTTPHeaderAcceptLanguage, "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6") | ||
type args struct { | ||
request *http.Request | ||
opts []getUserLangOpt | ||
} | ||
tests := []struct { | ||
name string | ||
args args | ||
want string | ||
}{ | ||
{name: "cookie", args: args{request: r, opts: []getUserLangOpt{WithCookieName("language")}}, want: "zh_CN"}, | ||
{name: "header", args: args{request: r}, want: "en_US"}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
if got := GetUserLang(tt.args.request, tt.args.opts...); got != tt.want { | ||
t.Errorf("GetUserLang() = %v, want %v", got, tt.want) | ||
} | ||
}) | ||
} | ||
} |