Chúng ta sẽ tham khảo ví dụ sau:
https://github.com/go-playground/validator/blob/master/_examples/translations/main.go
Mục đích ở đây chúng ta custom lại message mà chúng ta trả về khi mà chúng ta validate 1 value nào đó.
Chúng ta học theo translateOverride(trans)
Mặc định thì validate trả về message như link sau:
https://github.com/go-playground/validator/blob/master/translations/en/en.go#L26-L30
Mình muốn custom lại là:translation: "{0} trường này là bắt buộc!",
Một số chú thích thêm bằng hình ảnh:
Và mình sử dụng file code của anh này.
https://github.com/thanhniencung/backend-github-trending/blob/master/helper/struct_validator.go
package helper
import (
"backend-github-trending/log"
"github.com/go-playground/locales/en"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
en_translations "github.com/go-playground/validator/v10/translations/en"
"github.com/pkg/errors"
"strings"
)
type StructValidator struct {
Validator *validator.Validate
Uni *ut.UniversalTranslator
Trans ut.Translator
}
func NewStructValidator() *StructValidator {
translator := en.New()
uni := ut.New(translator, translator)
trans, _ := uni.GetTranslator("en")
return &StructValidator{
Validator: validator.New(),
Uni: uni,
Trans: trans,
}
}
func (cv *StructValidator) RegisterValidate() {
if err := en_translations.RegisterDefaultTranslations(cv.Validator, cv.Trans); err != nil {
log.Error(err.Error())
}
cv.Validator.RegisterValidation("pwd", func(fl validator.FieldLevel) bool {
return len(fl.Field().String()) >= 8
})
cv.Validator.RegisterTranslation("required", cv.Trans, func(ut ut.Translator) error {
return ut.Add("required", "{0} là bắt buộc", true)
}, func(ut ut.Translator, fe validator.FieldError) string {
t, _ := ut.T("required", fe.Field())
return t
})
cv.Validator.RegisterTranslation("email", cv.Trans, func(ut ut.Translator) error {
return ut.Add("email", "{0} không hợp lệ", true)
}, func(ut ut.Translator, fe validator.FieldError) string {
t, _ := ut.T("email", fe.Field())
return t
})
cv.Validator.RegisterTranslation("pwd", cv.Trans, func(ut ut.Translator) error {
return ut.Add("pwd", "Mật khẩu tối thiểu 8 kí tự", true)
}, func(ut ut.Translator, fe validator.FieldError) string {
t, _ := ut.T("pwd", fe.Field())
return t
})
}
func (cv *StructValidator) Validate(i interface{}) error {
err := cv.Validator.Struct(i)
if err == nil {
return nil
}
transErrors := make([]string, 0)
for _, e := range err.(validator.ValidationErrors) {
transErrors = append(transErrors, e.Translate(cv.Trans))
}
return errors.Errorf("%s", strings.Join(transErrors, " \n "))
}
ví dụ chúng ta tự design 1 validate MỚI:
package req
type ReqSignIn struct {
Email string `json:"email,omitempty" validate:"required"`
Password string `json:"password,omitempty" validate:"pwd"`
}
trong file struct_validator.go vào trong hàm func (cv *StructValidator) RegisterValidate()
chúng ta cần đăng ký 1 validate:
cv.Validator.RegisterValidation("pwd", func(fl validator.FieldLevel) bool {
return len(fl.Field().String()) >= 8
})
cv.Validator.RegisterTranslation("pwd", cv.Trans, func(ut ut.Translator) error {
return ut.Add("pwd", "Mật khẩu tối thiểu 8 kí tự", true)
}, func(ut ut.Translator, fe validator.FieldError) string {
t, _ := ut.T("pwd", fe.Field())
return t
})
với các tag name đã có săn ở validate (required, email) và giờ chúng ta muốn biên dịch lại thì:
cv.Validator.RegisterTranslation("required", cv.Trans, func(ut ut.Translator) error {
return ut.Add("required", "{0} là bắt buộc", true)
}, func(ut ut.Translator, fe validator.FieldError) string {
t, _ := ut.T("required", fe.Field())
return t
})
Một điểm hay mà minh được dạy là thằng echo framework cũng có validate riêng và cũng sử dụng go-playground/validator
https://echo.labstack.com/guide/request/#validate-data
tiếp tục vì mình muốn sài structValidator trên toàn bộ project của mình nên ở file main.go
structValidator := helper.NewStructValidator()
structValidator.RegisterValidate()
và làm sao gán được như thế?
trong file struct_validator.go
anh đã implement như sau:
func (cv *StructValidator) Validate(i interface{}) error {
err := cv.Validator.Struct(i)
if err == nil {
return nil
}
transErrors := make([]string, 0)
for _, e := range err.(validator.ValidationErrors) {
transErrors = append(transErrors, e.Translate(cv.Trans))
}
return errors.Errorf("%s", strings.Join(transErrors, " \n "))
}
trong handler thì chúng ta sử dụng như sau:
if err := c.Validate(req); err != nil {
log.Error(err.Error())
return c.JSON(http.StatusBadRequest, model.Response{
StatusCode: http.StatusBadRequest,
Message: err.Error(),
Data: nil,
})
}