Go 言語
で validation
するときに go-playground/validator
を使っているんですが、普通に使うとバリデーションエラー時にフィールド名が構造体の名前のまま表示されてしまいます。
GitHub - go-playground/validator: :100:Go Struct and Field validation, including Cross Field, Cross Struct, Map, Slice and Array diving
:100:Go Struct and Field validation, including Cross Field, ...
日本語で表示、というよりは画面に表示されている項目名と一致させないと、ユーザーが何のエラーが出てるのか分からないので困ってしまいます。
今回は上手くフィールド名の日本語化ができたので、その実装方法を重要な部分だけ抜き出して説明していきたいと思います。
前提条件
- Go言語 : 1.18.1
- Echo : 4.7.2
カスタムバリーデータ作成
package infrastructure
import (
"errors"
"github.com/go-playground/locales/ja_JP"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
ja_translations "github.com/go-playground/validator/v10/translations/ja"
"github.com/labstack/echo/v4"
"log"
"reflect"
)
type CustomValidator struct {
trans ut.Translator
validator *validator.Validate
}
func (cv *CustomValidator) Validate(i interface{}) error {
err := cv.validator.Struct(i)
if err == nil {
return err
}
errs := err.(validator.ValidationErrors)
msg := ""
for _, ve := range errs.Translate(cv.trans) {
if msg != "" {
msg += ", "
}
msg += ve
}
return errors.New(msg)
}
func NewValidator() echo.Validator {
japanese := ja_JP.New()
uni := ut.New(japanese, japanese)
trans, _ := uni.GetTranslator("ja")
validate := validator.New()
validate.RegisterTagNameFunc(func(field reflect.StructField) string {
fieldName := field.Tag.Get("ja")
if fieldName == "-" {
return ""
}
return fieldName
})
err := ja_translations.RegisterDefaultTranslations(validate, trans)
if err != nil {
log.Fatal(err)
}
return &CustomValidator{
trans: trans,
validator: validate,
}
}
このカスタムバリデータでバリデーションエラー時のフィールド名を日本語に変換しています。
構造体をカスタムする
type Admin struct {
ID int `json:"id" gorm:"primary_key"`
Name string `json:"name" validate:"required" ja:"名前"`
Username string `json:"username" validate:"required" db:"username" ja:"ユーザID"`
Password string `json:"password" validate:"required" ja:"パスワード"`
}
構造体のフィールドにja
というタグを追加しフィールド名に対応する日本語を設定します。このja
というタグがカスタムバリデータのNewValidator
関数で使用しているja
となります。
ルーティング実装部でバリデータ設定
func accessible(c echo.Context) error {
return c.String(http.StatusOK, "Accessible!!")
}
func NewRouting() {
e := echo.New()
e.Debug = true
e.Logger.SetOutput(os.Stderr)
e.Use(middleware.Logger())
//e.Use(middleware.Recover())
e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
AllowCredentials: true,
AllowOrigins: []string{"*"},
AllowHeaders: []string{
echo.HeaderAuthorization,
echo.HeaderContentType,
},
AllowMethods: []string{http.MethodOptions, http.MethodGet, http.MethodHead, http.MethodPut, http.MethodPatch, http.MethodPost, http.MethodDelete},
}))
e.Validator = infrastructure.NewValidator()
e.GET("/", accessible)
e.Logger.Fatal(e.Start(":8080"))
}
Go 言語
の Web アプリケーションフレームワークの Echo
のバリデータにカスタムバリデータを設定しています。
これでフィールド名まで含めたバリデーションの日本語化が実装できます。
最後に
画面から入力された値のバリデーションはロジックの中に入れたくないので、今回のようにルーティング部分に実装するのが良いと思います。フィールド名を日本語に翻訳することはできましたが、多言語対応となると実装方法をもうちょっと考えなければいけないかもしれません。多言語への対応は今後の課題ですね。
コメント