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 }