103 lines
2.9 KiB
Go
103 lines
2.9 KiB
Go
package middleware
|
||
|
||
import (
|
||
"context"
|
||
"net/http"
|
||
"strings"
|
||
)
|
||
|
||
// LanguageKey context中存储语言的key
|
||
type languageKey struct{}
|
||
|
||
// LanguageHeaderName 语言请求头名称
|
||
const LanguageHeaderName = "X-Language"
|
||
|
||
// AcceptLanguageHeaderName Accept-Language 请求头名称
|
||
const AcceptLanguageHeaderName = "Accept-Language"
|
||
|
||
// DefaultLanguage 默认语言
|
||
const DefaultLanguage = "zh-CN"
|
||
|
||
// GetLanguageFromContext 从context中获取语言
|
||
func GetLanguageFromContext(ctx context.Context) string {
|
||
if lang, ok := ctx.Value(languageKey{}).(string); ok && lang != "" {
|
||
return lang
|
||
}
|
||
return DefaultLanguage
|
||
}
|
||
|
||
// Language 语言处理中间件
|
||
// 从请求头 X-Language 或 Accept-Language 读取语言信息,如果未传递则使用默认语言 zh-CN
|
||
// 语言信息会存储到context中,可以通过 GetLanguageFromContext 获取
|
||
func Language(next http.Handler) http.Handler {
|
||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
// 1. 优先从 X-Language 请求头获取(显式指定)
|
||
lang := r.Header.Get(LanguageHeaderName)
|
||
|
||
// 2. 如果未设置,从 Accept-Language 请求头解析
|
||
if lang == "" {
|
||
acceptLang := r.Header.Get(AcceptLanguageHeaderName)
|
||
if acceptLang != "" {
|
||
lang = parseAcceptLanguage(acceptLang)
|
||
}
|
||
}
|
||
|
||
// 3. 如果都未设置,使用默认语言
|
||
if lang == "" {
|
||
lang = DefaultLanguage
|
||
}
|
||
|
||
// 将语言存储到context中
|
||
ctx := context.WithValue(r.Context(), languageKey{}, lang)
|
||
next.ServeHTTP(w, r.WithContext(ctx))
|
||
})
|
||
}
|
||
|
||
// LanguageWithDefault 语言处理中间件(可自定义默认语言)
|
||
// defaultLanguage: 默认语言,如果未指定则使用 zh-CN
|
||
func LanguageWithDefault(defaultLanguage string) func(http.Handler) http.Handler {
|
||
return func(next http.Handler) http.Handler {
|
||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
// 1. 优先从 X-Language 请求头获取(显式指定)
|
||
lang := r.Header.Get(LanguageHeaderName)
|
||
|
||
// 2. 如果未设置,从 Accept-Language 请求头解析
|
||
if lang == "" {
|
||
acceptLang := r.Header.Get(AcceptLanguageHeaderName)
|
||
if acceptLang != "" {
|
||
lang = parseAcceptLanguage(acceptLang)
|
||
}
|
||
}
|
||
|
||
// 3. 如果都未设置,使用指定的默认语言
|
||
if lang == "" {
|
||
lang = defaultLanguage
|
||
}
|
||
|
||
// 将语言存储到context中
|
||
ctx := context.WithValue(r.Context(), languageKey{}, lang)
|
||
next.ServeHTTP(w, r.WithContext(ctx))
|
||
})
|
||
}
|
||
}
|
||
|
||
// parseAcceptLanguage 解析 Accept-Language 请求头
|
||
// 返回第一个语言代码(去掉权重信息)
|
||
func parseAcceptLanguage(acceptLang string) string {
|
||
if acceptLang == "" {
|
||
return ""
|
||
}
|
||
|
||
// 分割语言列表
|
||
parts := strings.Split(acceptLang, ",")
|
||
if len(parts) == 0 {
|
||
return ""
|
||
}
|
||
|
||
// 取第一个语言代码,去掉权重信息(如 ";q=0.9")
|
||
firstLang := strings.Split(parts[0], ";")[0]
|
||
firstLang = strings.TrimSpace(firstLang)
|
||
|
||
return firstLang
|
||
}
|