需注册多语言translator并调用Translate()方法实现动态提示,推荐使用zh-translations包预置模板,自定义校验函数注册时需启用translate=true参数。
用 go-playground/validator 做基础校验时,提示语怎么动态换语言
默认的 validator 错误信息是英文硬编码的,比如 "key: 'user.email' error:field validation for 'email' failed on the 'email' tag"。要实现中文、日文等多语言提示,不能靠改源码或拼字符串,得接管错误翻译逻辑。
核心思路是:注册自定义的 translator,把原始字段+tag映射到对应语言的提示模板,再用实际值填充(比如把 {0} 替换成字段名,{1} 替换成邮箱格式要求)。
- 必须先调用
ut.RegisterFallbackTranslations()或ut.AddTranslator()注册目标语言的翻译器,否则Validate.Struct()返回的错误里没有本地化内容 - 推荐用
ut.New()创建独立的UniversalTranslator实例,避免全局状态污染 - 中文翻译包推荐直接用社区维护的
go-playground/validator/v10/translations/zh,它已预置了常见 tag(required、email、min等)的中文模板
结构体字段加 translatable 标签后,怎么让 validator 识别并替换
validator 本身不解析 translatable 这类自定义标签——那是你自己的业务逻辑。真正起作用的是 FieldError.Translate() 方法,它依赖 translator 提供的模板和参数。
所以关键不是“加什么标签”,而是确保 FieldError 的 Tag()、Field()、Param() 字段能被 translator 正确匹配。例如:
type User struct {
Email string `json:"email" validate:"required,email" translatable:"邮箱"`
}
上面的 translatable:"邮箱" 不会被 validator 使用,但你可以把它存在结构体反射信息里,在翻译阶段手动覆盖 Field() 返回值(不推荐),更稳妥的做法是:
- 在注册中文 translator 后,调用
zh_translations.RegisterDefaultTranslations(validate, ut) - 用
err.(validator.ValidationErrors).Translate(ut)得到带中文的字符串,如"邮箱为必填项" - 如果需要字段别名(比如把
Email显示成邮箱),建议在 translator 初始化时用ut.Add("zh", "User.Email", "邮箱")单独注册字段名映射
多个语言切换时,Validate.Struct() 怎么按请求头选 translator
validator 实例本身不绑定语言,Translate() 是 translator 的方法。所以语言选择发生在错误生成之后,而非校验之前。
典型 HTTP 场景下,你应该:
- 从
r.Header.Get("Accept-Language")解析首选语言(如zh-CN、ja-JP) - 查表拿到对应的
ut.Translator实例(注意:每个语言一个 translator,复用UniversalTranslator底层) - 调用
errs.Translate(translator),而不是固定用某个语言的 translator
别在 handler 里反复新建 translator——初始化时就准备好所有支持语言的 translator,并缓存起来。否则每次请求都调 ut.New() + AddTranslator(),性能会明显下降。
自定义校验函数返回的错误怎么也走国际化流程
如果你写了 func(email string) bool 这样的自定义校验函数,并通过 validate.RegisterValidation() 注册,那它的错误默认不会进 translator 流程,FieldError.Tag() 会是你的注册名(比如 "my_email_check"),而 translator 里没这个 key。
解决办法只有两个:
- 注册时传入
translate = true参数:v10.RegisterValidation("my_email_check", myCheckFunc, true),这样 validator 才会在错误中保留可翻译的上下文 - 手动给 translator 添加该 tag 的翻译:
ut.Add("zh", "my_email_check", "邮箱格式不正确") - 注意:自定义函数的
Param()值(比如FieldError.Param())会是你注册时传的第 3 个参数,可用于构造动态提示,但需 translator 模板支持占位符(如"{0} 格式不正确")
最易忽略的一点:自定义校验函数抛出的 panic 不会进入 translator,必须确保函数内部不 panic,错误全靠返回 false + 提前注册好翻译项来兜底。











