代码实现
根据 locale
设置动态语言翻译,具体包括初始化翻译器、注册多语言翻译规则、动态选择语言、以及输出本地化错误提示。
package validateimport ("errors""fmt""github.com/go-playground/locales/en""github.com/go-playground/locales/zh"ut "github.com/go-playground/universal-translator""github.com/go-playground/validator/v10"enTranslations "github.com/go-playground/validator/v10/translations/en"zhTranslations "github.com/go-playground/validator/v10/translations/zh"
)var validate = validator.New()
var uni *ut.UniversalTranslatorfunc LocalizedValidation() {// 初始化支持语言en := en.New()zh := zh.New()uni = ut.New(en, zh) // 初始化翻译器支持中英文locale := "zh" // 动态设置语言,可从配置或用户选择中获取// 根据 locale 获取翻译器trans, _ := uni.GetTranslator(locale)switch locale {case "en":enTranslations.RegisterDefaultTranslations(validate, trans)case "zh":zhTranslations.RegisterDefaultTranslations(validate, trans)default:fmt.Println("Unsupported locale, defaulting to English")enTranslations.RegisterDefaultTranslations(validate, trans)}// 定义需要验证的结构体type User struct {Name string `validate:"required"` // 必填字段Email string `validate:"required,email"` // 必填且必须是邮箱格式}user := User{}// 验证结构体err := validate.Struct(user)if err != nil {var validationErrors validator.ValidationErrorsif errors.As(err, &validationErrors) {for _, e := range validationErrors {// 输出本地化的错误提示信息fmt.Println(e.Translate(trans))}}}
}
核心功能点
功能模块 | 关键代码/方法 | 描述 |
---|---|---|
初始化翻译器 | ut.New(en, zh) | 支持多种语言的翻译器初始化。 |
动态语言选择 | uni.GetTranslator(locale) | 根据用户 locale 设置动态语言翻译。 |
注册翻译规则 | enTranslations.RegisterDefaultTranslations | 为不同语言注册默认验证规则翻译。 |
捕获验证错误 | validator.ValidationErrors | 验证失败时,捕获错误信息。 |
本地化错误输出 | FieldError.Translate(trans) | 将错误翻译为用户指定语言的提示信息。 |
运行效果示例
-
输入
User{Name: "",Email: "invalid-email", }
-
输出(
locale = "zh"
)Name 为必填字段 Email 必须是一个有效的邮箱地址
-
输出(
locale = "en"
)Name is a required field Email must be a valid email address
根据Accept-Language 动态设置 locale
package mainimport ("errors""fmt""net/http""strings""github.com/gin-gonic/gin""github.com/go-playground/locales/en""github.com/go-playground/locales/zh"ut "github.com/go-playground/universal-translator""github.com/go-playground/validator/v10"enTranslations "github.com/go-playground/validator/v10/translations/en"zhTranslations "github.com/go-playground/validator/v10/translations/zh"
)var validate = validator.New()
var uni *ut.UniversalTranslator// 初始化翻译器支持的语言
func initTranslator() {en := en.New()zh := zh.New()uni = ut.New(en, zh)
}// 动态获取 locale 并设置翻译器
func getTranslator(c *gin.Context) ut.Translator {// 获取请求头的 Accept-Languagelang := c.GetHeader("Accept-Language")if lang == "" {lang = "en" // 默认语言}// 提取主语言部分(如 zh-CN 取 zh)lang = strings.Split(lang, ",")[0]lang = strings.Split(lang, "-")[0]// 获取对应的 Translatortrans, _ := uni.GetTranslator(lang)switch lang {case "en":enTranslations.RegisterDefaultTranslations(validate, trans)case "zh":zhTranslations.RegisterDefaultTranslations(validate, trans)default:// 如果不支持该语言,默认使用英文trans, _ = uni.GetTranslator("en")enTranslations.RegisterDefaultTranslations(validate, trans)}return trans
}// 定义需要验证的结构体
type User struct {Name string `validate:"required"`Email string `validate:"required,email"`
}func main() {initTranslator()r := gin.Default()r.POST("/validate", func(c *gin.Context) {// 动态获取翻译器trans := getTranslator(c)// 从请求体解析用户数据var user Userif err := c.ShouldBindJSON(&user); err != nil {c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"})return}// 验证结构体err := validate.Struct(user)if err != nil {var validationErrors validator.ValidationErrorsif errors.As(err, &validationErrors) {// 收集本地化错误信息errorMessages := make([]string, len(validationErrors))for i, e := range validationErrors {errorMessages[i] = e.Translate(trans)}c.JSON(http.StatusBadRequest, gin.H{"errors": errorMessages})return}}// 验证成功c.JSON(http.StatusOK, gin.H{"message": "Validation passed!"})})// 启动服务r.Run(":8080")
}
核心步骤
- 初始化翻译器
- 使用
ut.New()
初始化支持的语言翻译器(如英文en
和中文zh
)。
- 从请求头获取
Accept-Language
- 提取用户请求中的
Accept-Language
,如zh-CN
或en-US
,并解析主语言部分(zh
或en
)。
- 动态注册翻译规则
- 根据解析出的语言动态注册相应的翻译规则(
enTranslations
或zhTranslations
)。
- 结构体验证
- 使用
validator
验证用户提交的数据,捕获验证错误。
- 本地化错误输出
- 将验证错误信息翻译为用户选择的语言,并返回给前端。
测试效果
请求 1:语言为中文
- 请求头
Accept-Language: zh-CN
- 请求体
{"Name": "","Email": "invalid-email"}
- 响应
{"errors": ["Name 为必填字段","Email 必须是一个有效的邮箱地址"]}
请求 2:语言为英文
- 请求头
Accept-Language: en-US
- 请求体
{"Name": "","Email": "invalid-email"}
- 响应
{"errors": ["Name is a required field","Email must be a valid email address"]}
请求 3:语言为空(默认英文)
- 请求头
Accept-Language:
- 请求体
{"Name": "","Email": "invalid-email"}
- 响应
{"errors": ["Name is a required field","Email must be a valid email address"]}
https://github.com/0voice