I'm trying to translate the validation errors message because I don't like the default error message. When I pass the trans variable via param from controllers to a helper (to handle validation error), err.Translate(trans) worked just like what I want.
Here is the controllers/handler
package handler
import (
"base-trade-rest/api/request"
"base-trade-rest/core/helpers"
"base-trade-rest/core/model"
"base-trade-rest/core/service"
"net/http"
"github.com/gin-gonic/gin"
en "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"
)
type ProductHandler struct {
ProductService service.IProductService
Validate *validator.Validate
Trans ut.Translator
}
func NewProductHandler(productService service.IProductService) *ProductHandler {
// NOTE: omitting allot of error checking for brevity
en := en.New()
uni := ut.New(en, en)
// this is usually know or extracted from http 'Accept-Language' header
// also see uni.FindTranslator(...)
trans, _ := uni.GetTranslator("en")
validate := validator.New()
en_translations.RegisterDefaultTranslations(validate, trans)
var productHandler = ProductHandler{
ProductService: productService,
Validate: validate,
Trans: trans,
}
return &productHandler
}
func (h *ProductHandler) Store(ctx *gin.Context) {
var request request.ProductCreateRequest
err := ctx.ShouldBind(&request)
if err != nil {
helpers.CreateFailedResponse(ctx, http.StatusBadRequest, err.Error())
return
}
err = h.Validate.Struct(request)
if err != nil {
helpers.HandleValidationError(ctx, err, h.Trans)
return
}
// Get authenticated user
userData := helpers.GetAuthUser(ctx)
product := model.Product{
Name: request.Name,
ImageURL: nil,
UserID: userData.ID,
}
newUser, err := h.ProductService.CreateProduct(&product)
if err != nil {
helpers.CreateFailedResponse(ctx, http.StatusBadRequest, err.Error())
return
}
helpers.CreateSuccessfulResponse(ctx, http.StatusOK, "Product successfully created", newUser)
}
And the helpers
package helpers
import (
"strings"
"github.com/gin-gonic/gin"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
)
func getValidationErrors(err error, trans ut.Translator) map[string]string {
var errors = make(map[string]string)
errs := err.(validator.ValidationErrors)
for _, e := range errs {
errors[strings.ToLower(e.Field())] = e.Translate(trans)
}
return errors
}
func HandleValidationError(ctx *gin.Context, err error, trans ut.Translator) {
CreateValidationErrorResponse(ctx, getValidationErrors(err, trans))
}
The getValidationErrors() returns just like i expected
{
"name": "Name is a required field"
}
But because i dont want to repeat the code in every controllers/handlers, i created a helper and init the trans there
package helpers
import (
"strings"
"github.com/gin-gonic/gin"
en "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"
)
// use single instances, it caches struct info
var trans ut.Translator
func init() {
en := en.New()
uni := ut.New(en, en)
trans, _ = uni.GetTranslator("en")
validate := validator.New()
en_translations.RegisterDefaultTranslations(validate, trans)
}
func getValidationErrors(err error) map[string]string {
var errors = make(map[string]string)
errs := err.(validator.ValidationErrors)
for _, e := range errs {
errors[strings.ToLower(e.Field())] = e.Translate(trans)
}
return errors
}
func HandleValidationError(ctx *gin.Context, err error) {
CreateValidationErrorResponse(ctx, getValidationErrorsTest(err))
}
And call it from controllers like this without passing the h.Trans
I'm trying to translate the validation errors message because I don't like the default error message. When I pass the trans variable via param from controllers to a helper (to handle validation error), err.Translate(trans) worked just like what I want.
Here is the controllers/handler
And the helpers
The getValidationErrors() returns just like i expected
But because i dont want to repeat the code in every controllers/handlers, i created a helper and init the trans there
And call it from controllers like this without passing the h.Trans
But it returns something like this which i don't want
Is there something i missed or is this a wrong way?