Golang校验库go-playground/validator如何实现多语言翻译支持

Golang校验库go-playground/validator如何实现多语言翻译支持 大家好,

我正在参考这个示例来为验证错误启用翻译功能。 示例可以运行,但我不明白如何添加对多种翻译语言的支持。

我的应用程序是一个 HTTP REST 后端,用于翻译的语言是通过读取 HTTP 请求的 Accept-Language 头部来确定的。

我遇到的主要问题是,即使我使用以下代码注册了多种语言:

uni = ut.New(en, en, it.New(), fr.New())

用于翻译的语言始终是 en,即使在我的处理程序中我执行了:

trans, _ := uni.GetTranslator("it")

errs := err.(validator.ValidationErrors)
errs.Translate(trans)

我检查过,调用:

trans, found := uni.GetTranslator("it")

时,found 的值是 true。

有什么建议吗?


更多关于Golang校验库go-playground/validator如何实现多语言翻译支持的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang校验库go-playground/validator如何实现多语言翻译支持的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在go-playground/validator中实现多语言翻译支持时,需要正确配置翻译器并确保验证错误使用对应的翻译器。根据你的代码片段,问题可能出现在翻译器的注册或使用方式上。

以下是完整的多语言翻译实现示例:

package main

import (
    "fmt"
    "net/http"
    
    "github.com/go-playground/locales/en"
    "github.com/go-playground/locales/it"
    "github.com/go-playground/locales/fr"
    ut "github.com/go-playground/universal-translator"
    "github.com/go-playground/validator/v10"
    enTranslations "github.com/go-playground/validator/v10/translations/en"
    itTranslations "github.com/go-playground/validator/v10/translations/it"
    frTranslations "github.com/go-playground/validator/v10/translations/fr"
)

var (
    uni      *ut.UniversalTranslator
    validate *validator.Validate
)

func init() {
    // 初始化本地化实例
    enLocale := en.New()
    itLocale := it.New()
    frLocale := fr.New()
    
    // 创建通用翻译器,第一个参数是备用语言
    uni = ut.New(enLocale, enLocale, itLocale, frLocale)
    
    // 创建验证器实例
    validate = validator.New()
    
    // 注册各种语言的翻译
    registerTranslations("en")
    registerTranslations("it")
    registerTranslations("fr")
}

func registerTranslations(lang string) {
    if trans, found := uni.GetTranslator(lang); found {
        switch lang {
        case "en":
            enTranslations.RegisterDefaultTranslations(validate, trans)
        case "it":
            itTranslations.RegisterDefaultTranslations(validate, trans)
        case "fr":
            frTranslations.RegisterDefaultTranslations(validate, trans)
        }
    }
}

type User struct {
    Name  string `validate:"required,min=3"`
    Email string `validate:"required,email"`
    Age   int    `validate:"gte=18"`
}

func validateUser(user User, lang string) []string {
    // 获取对应语言的翻译器
    trans, _ := uni.GetTranslator(lang)
    
    // 执行验证
    err := validate.Struct(user)
    if err != nil {
        var errors []string
        if validationErrors, ok := err.(validator.ValidationErrors); ok {
            // 使用正确的翻译器翻译错误
            translatedErrors := validationErrors.Translate(trans)
            for _, errMsg := range translatedErrors {
                errors = append(errors, errMsg)
            }
        }
        return errors
    }
    return nil
}

func handler(w http.ResponseWriter, r *http.Request) {
    // 从Accept-Language头部获取语言
    acceptLanguage := r.Header.Get("Accept-Language")
    // 简化处理:取前两个字符作为语言代码
    lang := "en" // 默认语言
    if len(acceptLanguage) >= 2 {
        lang = acceptLanguage[:2]
    }
    
    user := User{
        Name:  "Jo", // 故意设置短名称触发错误
        Email: "invalid-email",
        Age:   16,
    }
    
    errors := validateUser(user, lang)
    
    if errors != nil {
        fmt.Fprintf(w, "Validation errors (%s):\n", lang)
        for _, err := range errors {
            fmt.Fprintf(w, "- %s\n", err)
        }
    } else {
        fmt.Fprintf(w, "Validation passed")
    }
}

func main() {
    http.HandleFunc("/validate", handler)
    http.ListenAndServe(":8080", nil)
}

关键点说明:

  1. 翻译器注册:确保每种语言都正确注册了默认翻译:
// 每种语言都需要单独注册
registerTranslations("en")
registerTranslations("it")
registerTranslations("fr")
  1. 验证时使用对应翻译器:在验证函数中获取正确的翻译器:
func validateUser(user User, lang string) []string {
    trans, _ := uni.GetTranslator(lang)  // 获取对应语言的翻译器
    // ...
    translatedErrors := validationErrors.Translate(trans)  // 使用该翻译器
}
  1. HTTP头部处理示例
acceptLanguage := r.Header.Get("Accept-Language")
lang := "en" // 默认值
if len(acceptLanguage) >= 2 {
    lang = acceptLanguage[:2]
}

测试不同语言的验证错误输出:

# 英语
curl -H "Accept-Language: en" http://localhost:8080/validate

# 意大利语
curl -H "Accept-Language: it" http://localhost:8080/validate

# 法语
curl -H "Accept-Language: fr" http://localhost:8080/validate

如果问题仍然存在,检查验证器实例是否全局唯一,确保在验证时使用的是同一个validate实例,该实例已经注册了所有语言的翻译。

回到顶部