Skip to content

Commit 866bd2a

Browse files
committed
Support translating field errors when field is of kind reflect.Ptr
Previously, if fields were of kind `reflect.Ptr`, the translation of validation errors used the default string, resulting in unexpected output. Now the default translations use the field's `Elem()` kind (for example for `*string` the `Elem()` is `string`), resulting in much more natural output.
1 parent 48a433b commit 866bd2a

File tree

2 files changed

+88
-7
lines changed

2 files changed

+88
-7
lines changed

translations/en/en.go

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
6969
var t string
7070

7171
var digits uint64
72+
var kind reflect.Kind
7273

7374
if idx := strings.Index(fe.Param(), "."); idx != -1 {
7475
digits = uint64(len(fe.Param()[idx+1:]))
@@ -79,7 +80,12 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
7980
goto END
8081
}
8182

82-
switch fe.Kind() {
83+
kind = fe.Kind()
84+
if kind == reflect.Ptr {
85+
kind = fe.Type().Elem().Kind()
86+
}
87+
88+
switch kind {
8389
case reflect.String:
8490

8591
var c string
@@ -154,6 +160,7 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
154160
var t string
155161

156162
var digits uint64
163+
var kind reflect.Kind
157164

158165
if idx := strings.Index(fe.Param(), "."); idx != -1 {
159166
digits = uint64(len(fe.Param()[idx+1:]))
@@ -164,7 +171,12 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
164171
goto END
165172
}
166173

167-
switch fe.Kind() {
174+
kind = fe.Kind()
175+
if kind == reflect.Ptr {
176+
kind = fe.Type().Elem().Kind()
177+
}
178+
179+
switch kind {
168180
case reflect.String:
169181

170182
var c string
@@ -239,6 +251,7 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
239251
var t string
240252

241253
var digits uint64
254+
var kind reflect.Kind
242255

243256
if idx := strings.Index(fe.Param(), "."); idx != -1 {
244257
digits = uint64(len(fe.Param()[idx+1:]))
@@ -249,7 +262,12 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
249262
goto END
250263
}
251264

252-
switch fe.Kind() {
265+
kind = fe.Kind()
266+
if kind == reflect.Ptr {
267+
kind = fe.Type().Elem().Kind()
268+
}
269+
270+
switch kind {
253271
case reflect.String:
254272

255273
var c string
@@ -359,6 +377,7 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
359377
var t string
360378
var f64 float64
361379
var digits uint64
380+
var kind reflect.Kind
362381

363382
fn := func() (err error) {
364383

@@ -371,7 +390,12 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
371390
return
372391
}
373392

374-
switch fe.Kind() {
393+
kind = fe.Kind()
394+
if kind == reflect.Ptr {
395+
kind = fe.Type().Elem().Kind()
396+
}
397+
398+
switch kind {
375399
case reflect.String:
376400

377401
var c string
@@ -472,6 +496,7 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
472496
var t string
473497
var f64 float64
474498
var digits uint64
499+
var kind reflect.Kind
475500

476501
fn := func() (err error) {
477502

@@ -484,7 +509,12 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
484509
return
485510
}
486511

487-
switch fe.Kind() {
512+
kind = fe.Kind()
513+
if kind == reflect.Ptr {
514+
kind = fe.Type().Elem().Kind()
515+
}
516+
517+
switch kind {
488518
case reflect.String:
489519

490520
var c string
@@ -585,6 +615,7 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
585615
var t string
586616
var f64 float64
587617
var digits uint64
618+
var kind reflect.Kind
588619

589620
fn := func() (err error) {
590621

@@ -597,7 +628,12 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
597628
return
598629
}
599630

600-
switch fe.Kind() {
631+
kind = fe.Kind()
632+
if kind == reflect.Ptr {
633+
kind = fe.Type().Elem().Kind()
634+
}
635+
636+
switch kind {
601637
case reflect.String:
602638

603639
var c string
@@ -698,6 +734,7 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
698734
var t string
699735
var f64 float64
700736
var digits uint64
737+
var kind reflect.Kind
701738

702739
fn := func() (err error) {
703740

@@ -710,7 +747,12 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
710747
return
711748
}
712749

713-
switch fe.Kind() {
750+
kind = fe.Kind()
751+
if kind == reflect.Ptr {
752+
kind = fe.Type().Elem().Kind()
753+
}
754+
755+
switch kind {
714756
case reflect.String:
715757

716758
var c string

translations/en/en_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,13 @@ func TestTranslations(t *testing.T) {
129129
UinxAddr string `validate:"unix_addr"` // can't fail from within Go's net package currently, but maybe in the future
130130
MAC string `validate:"mac"`
131131
IsColor string `validate:"iscolor"`
132+
StrPtrMinLen *string `validate:"min=10"`
133+
StrPtrMaxLen *string `validate:"max=1"`
134+
StrPtrLen *string `validate:"len=2"`
135+
StrPtrLt *string `validate:"lt=1"`
136+
StrPtrLte *string `validate:"lte=1"`
137+
StrPtrGt *string `validate:"gt=10"`
138+
StrPtrGte *string `validate:"gte=10"`
132139
}
133140

134141
var test Test
@@ -171,6 +178,10 @@ func TestTranslations(t *testing.T) {
171178

172179
test.MultiByte = "1234feerf"
173180

181+
s := "toolong"
182+
test.StrPtrMaxLen = &s
183+
test.StrPtrLen = &s
184+
174185
err = validate.Struct(test)
175186
NotEqual(t, err, nil)
176187

@@ -565,6 +576,34 @@ func TestTranslations(t *testing.T) {
565576
ns: "Test.RequiredMultiple",
566577
expected: "RequiredMultiple is a required field",
567578
},
579+
{
580+
ns: "Test.StrPtrMinLen",
581+
expected: "StrPtrMinLen must be at least 10 characters in length",
582+
},
583+
{
584+
ns: "Test.StrPtrMaxLen",
585+
expected: "StrPtrMaxLen must be a maximum of 1 character in length",
586+
},
587+
{
588+
ns: "Test.StrPtrLen",
589+
expected: "StrPtrLen must be 2 characters in length",
590+
},
591+
{
592+
ns: "Test.StrPtrLt",
593+
expected: "StrPtrLt must be less than 1 character in length",
594+
},
595+
{
596+
ns: "Test.StrPtrLte",
597+
expected: "StrPtrLte must be at maximum 1 character in length",
598+
},
599+
{
600+
ns: "Test.StrPtrGt",
601+
expected: "StrPtrGt must be greater than 10 characters in length",
602+
},
603+
{
604+
ns: "Test.StrPtrGte",
605+
expected: "StrPtrGte must be at least 10 characters in length",
606+
},
568607
}
569608

570609
for _, tt := range tests {

0 commit comments

Comments
 (0)