Realization of golang validator parameter calibration

  • 2020-11-20 06:08:13
  • OfStack

Today, when I was changing the background page, the output was all In English when the parameter verification error was used. It was very difficult to understand what was wrong
Therefore, I decided to do the front-end internationalization of i18n. I stepped on a lot of holes in the process of modification, so I recorded 1, and also the following ways of checking the problems.

The effect

Title is required changed from Title is required to a required field with a title

Completed code:

Here we mainly define the variables that initialize 1 Chinese trans and Validate, and initialize them
Initialization mainly does the following things:

The TagName function is registered
// RegisterTagNameFunc registers a function to get alternate names for StructFields.
This method basically provides 1 tag parser and returns 1 Field substitution string
I myself defined an tag for label substitution

validate's translation function is registered
The original Chinese translation is directly used to internationalize required and other tags


package service

import (
  zhongwen "github.com/go-playground/locales/zh"
  ut "github.com/go-playground/universal-translator"
  "github.com/go-playground/validator/v10"
  zh_translations "github.com/go-playground/validator/v10/translations/zh"
  "reflect"
  "strings"
)

var Validate *validator.Validate
var trans ut.Translator

func init() {
  zh := zhongwen.New()
  uni := ut.New(zh, zh)
  trans, _ = uni.GetTranslator("zh")

  Validate = validator.New()
  Validate.RegisterTagNameFunc(func(field reflect.StructField) string {
    label := field.Tag.Get("label")
    if label == "" {
      return field.Name
    }
    return label
  })
  zh_translations.RegisterDefaultTranslations(Validate, trans)
}
func Translate(errs validator.ValidationErrors) string {
  var errList []string
  for _, e := range errs {
    // can translate each error one at a time.
    errList = append(errList,e.Translate(trans))
  }
  return strings.Join(errList,"|")
}

Call way


type ArticlesPost struct {
  Title      string `json:"title" validate:"required,max=32,min=4" label:" The title "`
}
var ap ArticlePost
err = service.Validate.Struct(ap)
if err!=nil{
 errStr =Translate(errs)
 fmt.Sprintln(errStr)
}

Train of thought

Just began to search baidu most, fruitless
I checked iris's documentation, but nothing happened
I went to the document of validate and found the package of ES51en-ES52en. I can preliminarily change the styles of is required to required fields Still unable to map the field name into Chinese, google searched How can I fieldName? #364, issue, the comment gives the mapping of en.Add ("MyField", "Field", false). Finally, when alidate.RegisterTranslation registers required, the method of T is converted to the corresponding Chinese fld, _ := ut.T ()). Considering that the field of Struct should be registered every time, In addition, the same key globally cannot define different values, so it should be abandoned For the first time, I was thinking about whether the verification itself had provided the corresponding position. After reading interface, I found some half-known and half-solved solutions in English, but failed to find the results, so I gave up Go ahead and think about whether you can customize tag, and then rewrite the type TranslationFunc func(ut ES84en.Translator, fe FieldError) string function to dynamically pass the value of the tag in struct at this translation stage, so that it does not repeat. After studying the passing parameters of this function, only the data corresponding to the field is left in FieldError, so the tag information cannot be obtained, and I almost want to give up Again, consider the function of validator with respect to tag

The first is to set a new tag to replace validate, and the other is to register a method to get the replacement name for the structure field

Take a closer look at the instructions, and sure enough it is this. After looking at the signature of TagNameFunc, the parameter is ES102en. StructField, you can get tag and other 1 series information


// TagNameFunc allows for adding of a custom tag name parser
type TagNameFunc func(field reflect.StructField) string
// SetTagName allows for changing of the default tag name of 'validate'
func (v *Validate) SetTagName(name string) {
  v.tagName = name
}

// RegisterTagNameFunc registers a function to get alternate names for StructFields.
//
// eg. to use the names which have been specified for JSON representations of structs, rather than normal Go field names:
//
//  validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
//    name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
//    if name == "-" {
//      return ""
//    }
//    return name
//  })
func (v *Validate) RegisterTagNameFunc(fn TagNameFunc) {
  v.tagNameFunc = fn
  v.hasTagNameFunc = true
}

So far, finally found the right solution

conclusion

In order to solve this problem found here took a lot of detours, looked up a lot of information only to find that even the original is provided with this function.

Discover some of your problems:

English is not very good, occasionally some words do not know, prevented from 1 step to find out the problem, here also suddenly thought that better English 1 can indeed learn programming this way to benefit a lot I don't read the documents very carefully. I think most of the programming problems are not very sophisticated, so I can understand the meaning of errors and then check the documents or search engines to solve them. The other one is that most of the programming documents are in English.

Related articles: