94 lines
2.6 KiB
Go
94 lines
2.6 KiB
Go
package middleware
|
||
|
||
import (
|
||
"context"
|
||
"net/http"
|
||
"strings"
|
||
|
||
"git.toowon.com/jimmy/go-common/requestctx"
|
||
)
|
||
|
||
// LanguageHeaderName 语言请求头名称
|
||
const LanguageHeaderName = "X-Language"
|
||
|
||
// AcceptLanguageHeaderName Accept-Language 请求头名称
|
||
const AcceptLanguageHeaderName = "Accept-Language"
|
||
|
||
// GetLanguageFromContext 从 context 中获取语言
|
||
func GetLanguageFromContext(ctx context.Context) string {
|
||
return requestctx.Language(ctx)
|
||
}
|
||
|
||
// 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 = requestctx.DefaultLanguage
|
||
}
|
||
|
||
ctx := requestctx.WithLanguage(r.Context(), 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
|
||
}
|
||
|
||
ctx := requestctx.WithLanguage(r.Context(), 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
|
||
}
|