go-playground / validator

:100:Go Struct and Field validation, including Cross Field, Cross Struct, Map, Slice and Array diving
MIT License
16.53k stars 1.31k forks source link

Custom Translation in CustomValidations #1052

Open Awadabang opened 1 year ago

Awadabang commented 1 year ago

Package version eg. v9, v10:

v10

Issue, Question or Enhancement:

Question

Code sample, to showcase or reproduce:

func CustomValidation(sl validator.StructLevel) {
    if req, ok := sl.Current().Interface().(CreateEventReq); ok {
        if len(req.NotifyUsers)+len(req.NotifyUserGroups) < 1 {
            sl.ReportError(req.NotifyUsers, "", "", "", "")
            sl.ReportError(req.NotifyUserGroups, "", "", "", "")
        }
    }
}

validations like this cannot be translated, is there some way I can customize translation info in this function?

anadrosos commented 1 year ago

Hello, I do not see why you can not translate validation errors, unless I miss something:

        1. register custom translations
    if err := v.RegisterTranslation("gte", trans, func(ut ut.Translator) error { return nil },
        func(ut ut.Translator, fe validator.FieldError) string {
            t, _ := ut.T("validation_field_minimum_limit_characters", fe.Param())
            return t
        }); err != nil {
        return err
    }

    2. report the errors using the proper tags. e.g. gte passing the parameter 2.
    sl.ReportError(struct, "fieldName", "structFieldName", "gte", "2")

    3. Create the actual translations.
    {
          "key": "validation_field_minimum_limit_characters",
          "trans": "Please enter a minimum of {0} characters",
          "locale": "en"
        },
Awadabang commented 1 year ago

hi, anadrosos. I don't mean to register custom translations, but a custom validation with custom translations. My struct is like:

type Req struct {
    Name             string          `json:"name,omitempty" validate:"required"`
    NotifyUsers      []string        `json:"notifyUsers,omitempty"`
    NotifyUserGroups []string        `json:"notifyUserGroups,omitempty"`
    NotifyContent    string          `json:"notifyContent,omitempty" validate:"required"`
}

I want limit the number of NotifyUsers and NotifyUserGroups to a minimum of 1. So I write a custom validation. But it's error output is like: Key: 'Req.NotifyUsers' Error:Field validation for 'NotifyUsers' failed on the '' tag,Key: 'Req.NotifyUserGroups' Error:Field validation for 'NotifyUserGroups' failed on the '' tag". Is there some way to translate it?

anadrosos commented 1 year ago

Do you translate your validation errors?

errs := err.(validator.ValidationErrors)
fmt.Println(errs.Translate(trans))
Awadabang commented 1 year ago

Yes, I do this step, but it outputs: Key: 'Req.NotifyUsers' Error:Field validation for 'NotifyUsers' failed on the '' tag,Key: 'Req.NotifyUserGroups' Error:Field validation for 'NotifyUserGroups' failed on the '' tag"

anadrosos commented 1 year ago

This error is telling us that you have not added a tag when you reported an error. As on my first reply, do you want to set a tag when you report this error? You also might have to add a custom translation that matches this tag if its not one of the predefined tags.

Awadabang commented 1 year ago

The point is in this case, I cannot find a way to add a custom tag to validate these two fields, do you have any solution?

feel like it should be done this way:

func CustomValidation(sl validator.StructLevel) {
    if req, ok := sl.Current().Interface().(CreateEventReq); ok {
        if len(req.NotifyUsers)+len(req.NotifyUserGroups) < 1 {
            sl.ReportErrorWithTranslate(req.NotifyUsers, "", "", "", "")  // bind a translation
            sl.ReportErrorWithTranslate(req.NotifyUserGroups, "", "", "", "")
        }
    }
}