busniess-user-center/pkg/validator/validator.go

115 lines
2.6 KiB
Go

package validator
import (
"errors"
"fmt"
"strings"
"sync"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/locales/zh"
uTrans "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"
)
const (
local = "zh"
)
func NewValidator() binding.StructValidator {
return &customValidator{}
}
type customValidator struct {
once sync.Once
validate *validator.Validate
translator uTrans.Translator
}
func (c *customValidator) ValidateStruct(obj interface{}) error {
c.lazyinit()
if err := c.validate.Struct(obj); err != nil {
return c.translate(err)
}
return nil
}
func (c *customValidator) Engine() any {
c.lazyinit()
return c.validate
}
func (c *customValidator) lazyinit() {
c.once.Do(func() {
c.validate = validator.New()
c.validate.SetTagName("binding")
if err := c.setTrans(); err != nil {
fmt.Printf("setTrans fail %s", err.Error())
}
if err := c.registerValidation(); err != nil {
fmt.Printf("registervalidation fail:%s", err.Error())
}
})
}
// 暂时写死英文翻译中文,todo 根据IP或者根据请求头语言决定翻译
func (c *customValidator) setTrans() error {
zh := zh.New()
uni := uTrans.New(zh, zh)
trans, exist := uni.GetTranslator(local)
if !exist {
return fmt.Errorf("uni.GetTranslator %s fail", local)
}
c.translator = trans
switch local {
case "en":
if err := enTranslations.RegisterDefaultTranslations(c.validate, c.translator); err != nil {
return fmt.Errorf("enTranslations fail:%s", err.Error())
}
case "zh":
if err := zhTranslations.RegisterDefaultTranslations(c.validate, c.translator); err != nil {
return fmt.Errorf("zhTranslations fail:%s", err.Error())
}
default:
if err := zhTranslations.RegisterDefaultTranslations(c.validate, c.translator); err != nil {
return fmt.Errorf("zhTranslations fail:%s", err.Error())
}
}
return nil
}
func (c *customValidator) registerValidation() error {
if err := c.validate.RegisterValidation("tableName", tableName); err != nil {
return err
}
return nil
}
func (c *customValidator) translate(err error) error {
if errs, ok := err.(validator.ValidationErrors); ok {
tErrMap := errs.Translate(c.translator)
errMsgs := make([]string, 0)
for _, msg := range tErrMap {
errMsgs = append(errMsgs, msg)
}
return errors.New(strings.Join(errMsgs, ";"))
// todo 根据定制tag,输出定制的msg
// todo 翻译后的错误消息按另外的规则输出(当前json)
}
return err
}