【Validator】universal-translator,实现动态多语言切换,go案例根据Accept-Language 动态设置 locale
代码实现
根据 locale
设置动态语言翻译,具体包括初始化翻译器、注册多语言翻译规则、动态选择语言、以及输出本地化错误提示。
package validate
import (
"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.UniversalTranslator
func 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.ValidationErrors
if 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 main
import (
"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-Language
lang := c.GetHeader("Accept-Language")
if lang == "" {
lang = "en" // 默认语言
}
// 提取主语言部分(如 zh-CN 取 zh)
lang = strings.Split(lang, ",")[0]
lang = strings.Split(lang, "-")[0]
// 获取对应的 Translator
trans, _ := 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 User
if 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.ValidationErrors
if 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