From 9ae7f28ff3d7b90800b131fa4f8d9136f98e4a5d Mon Sep 17 00:00:00 2001 From: Ali Date: Sun, 30 Mar 2025 13:02:44 +0330 Subject: [PATCH 1/3] Register Translator and get it as a function --- validator_instance.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/validator_instance.go b/validator_instance.go index 779f689a..1dbabd5e 100644 --- a/validator_instance.go +++ b/validator_instance.go @@ -89,6 +89,7 @@ type Validate struct { aliases map[string]string validations map[string]internalValidationFuncWrapper transTagFunc map[ut.Translator]map[string]TranslationFunc // map[]map[]TranslationFunc + translator ut.Translator rules map[reflect.Type]map[string]string tagCache *tagCache structCache *structCache @@ -361,6 +362,14 @@ func (v *Validate) RegisterTranslation(tag string, trans ut.Translator, register return } +func (v *Validate) RegisterTranslator(trans ut.Translator) { + v.translator = trans +} + +func (v *Validate) Translator() ut.Translator { + return v.translator +} + // Struct validates a structs exposed fields, and automatically validates nested structs, unless otherwise specified. // // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise. From fdb018aa9fac005e092de97a692af53ab5af447c Mon Sep 17 00:00:00 2001 From: Ali Date: Sun, 30 Mar 2025 13:14:13 +0330 Subject: [PATCH 2/3] add translator test --- validator_test.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/validator_test.go b/validator_test.go index 11013bc0..b718fcfe 100644 --- a/validator_test.go +++ b/validator_test.go @@ -9489,6 +9489,7 @@ func TestTranslations(t *testing.T) { fr, _ := uni.GetTranslator("fr") validate := New() + validate.RegisterTranslator(trans) err := validate.RegisterTranslation("required", trans, func(ut ut.Translator) (err error) { // using this stype because multiple translation may have to be added for the full translation @@ -9543,7 +9544,7 @@ func TestTranslations(t *testing.T) { fe := errs[0] Equal(t, fe.Tag(), "required") Equal(t, fe.Namespace(), "Test.Value") - Equal(t, fe.Translate(trans), fmt.Sprintf("%s is a required field", fe.Field())) + Equal(t, fe.Translate(validate.Translator()), fmt.Sprintf("%s is a required field", fe.Field())) Equal(t, fe.Translate(fr), fmt.Sprintf("%s est un champ obligatoire", fe.Field())) nl := nl.New() @@ -9551,7 +9552,7 @@ func TestTranslations(t *testing.T) { trans2, _ := uni2.GetTranslator("nl") Equal(t, fe.Translate(trans2), "Key: 'Test.Value' Error:Field validation for 'Value' failed on the 'required' tag") - terrs := errs.Translate(trans) + terrs := errs.Translate(validate.Translator()) Equal(t, len(terrs), 1) v, ok := terrs["Test.Value"] @@ -9580,7 +9581,7 @@ func TestTranslations(t *testing.T) { fe = errs[0] Equal(t, fe.Tag(), "gt") Equal(t, fe.Namespace(), "Test2.Value") - Equal(t, fe.Translate(trans), "Key: 'Test2.Value' Error:Field validation for 'Value' failed on the 'gt' tag") + Equal(t, fe.Translate(validate.Translator()), "Key: 'Test2.Value' Error:Field validation for 'Value' failed on the 'gt' tag") } func TestTranslationErrors(t *testing.T) { From 49b01e65bc061c8b6617403e7ff8216b5c85b702 Mon Sep 17 00:00:00 2001 From: Ali Date: Sun, 30 Mar 2025 13:19:37 +0330 Subject: [PATCH 3/3] add multi locale to validator Translator --- validator_instance.go | 11 ++++++----- validator_test.go | 15 ++++++++------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/validator_instance.go b/validator_instance.go index 1dbabd5e..b40fc32f 100644 --- a/validator_instance.go +++ b/validator_instance.go @@ -89,7 +89,7 @@ type Validate struct { aliases map[string]string validations map[string]internalValidationFuncWrapper transTagFunc map[ut.Translator]map[string]TranslationFunc // map[]map[]TranslationFunc - translator ut.Translator + translator map[string]ut.Translator rules map[reflect.Type]map[string]string tagCache *tagCache structCache *structCache @@ -116,6 +116,7 @@ func New(options ...Option) *Validate { tagName: defaultTagName, aliases: make(map[string]string, len(bakedInAliases)), validations: make(map[string]internalValidationFuncWrapper, len(bakedInValidators)), + translator: make(map[string]ut.Translator), tagCache: tc, structCache: sc, } @@ -362,12 +363,12 @@ func (v *Validate) RegisterTranslation(tag string, trans ut.Translator, register return } -func (v *Validate) RegisterTranslator(trans ut.Translator) { - v.translator = trans +func (v *Validate) RegisterTranslator(trans ut.Translator, locale string) { + v.translator[locale] = trans } -func (v *Validate) Translator() ut.Translator { - return v.translator +func (v *Validate) Translator(locale string) ut.Translator { + return v.translator[locale] } // Struct validates a structs exposed fields, and automatically validates nested structs, unless otherwise specified. diff --git a/validator_test.go b/validator_test.go index b718fcfe..6d246a07 100644 --- a/validator_test.go +++ b/validator_test.go @@ -9489,8 +9489,9 @@ func TestTranslations(t *testing.T) { fr, _ := uni.GetTranslator("fr") validate := New() - validate.RegisterTranslator(trans) - err := validate.RegisterTranslation("required", trans, + validate.RegisterTranslator(trans, "en") + validate.RegisterTranslator(fr, "fr") + err := validate.RegisterTranslation("required", validate.Translator("en"), func(ut ut.Translator) (err error) { // using this stype because multiple translation may have to be added for the full translation if err = ut.Add("required", "{0} is a required field", false); err != nil { @@ -9509,7 +9510,7 @@ func TestTranslations(t *testing.T) { }) Equal(t, err, nil) - err = validate.RegisterTranslation("required", fr, + err = validate.RegisterTranslation("required", validate.Translator("fr"), func(ut ut.Translator) (err error) { // using this stype because multiple translation may have to be added for the full translation if err = ut.Add("required", "{0} est un champ obligatoire", false); err != nil { @@ -9544,7 +9545,7 @@ func TestTranslations(t *testing.T) { fe := errs[0] Equal(t, fe.Tag(), "required") Equal(t, fe.Namespace(), "Test.Value") - Equal(t, fe.Translate(validate.Translator()), fmt.Sprintf("%s is a required field", fe.Field())) + Equal(t, fe.Translate(validate.Translator("en")), fmt.Sprintf("%s is a required field", fe.Field())) Equal(t, fe.Translate(fr), fmt.Sprintf("%s est un champ obligatoire", fe.Field())) nl := nl.New() @@ -9552,14 +9553,14 @@ func TestTranslations(t *testing.T) { trans2, _ := uni2.GetTranslator("nl") Equal(t, fe.Translate(trans2), "Key: 'Test.Value' Error:Field validation for 'Value' failed on the 'required' tag") - terrs := errs.Translate(validate.Translator()) + terrs := errs.Translate(validate.Translator("en")) Equal(t, len(terrs), 1) v, ok := terrs["Test.Value"] Equal(t, ok, true) Equal(t, v, fmt.Sprintf("%s is a required field", fe.Field())) - terrs = errs.Translate(fr) + terrs = errs.Translate(validate.Translator("fr")) Equal(t, len(terrs), 1) v, ok = terrs["Test.Value"] @@ -9581,7 +9582,7 @@ func TestTranslations(t *testing.T) { fe = errs[0] Equal(t, fe.Tag(), "gt") Equal(t, fe.Namespace(), "Test2.Value") - Equal(t, fe.Translate(validate.Translator()), "Key: 'Test2.Value' Error:Field validation for 'Value' failed on the 'gt' tag") + Equal(t, fe.Translate(validate.Translator("en")), "Key: 'Test2.Value' Error:Field validation for 'Value' failed on the 'gt' tag") } func TestTranslationErrors(t *testing.T) {