Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 0ffcb3a

Browse filesBrowse files
committed
Adds MessageKey ,ErrorKey to Validation object.
You can invoke those functions within a model to attach a translated message to the ValidationError.Message object The translator is taken from Revel.MessageFunc and is attached during the ValidationFilter process closes revel#706
1 parent a6d8a1f commit 0ffcb3a
Copy full SHA for 0ffcb3a

File tree

3 files changed

+70
-14
lines changed
Filter options

3 files changed

+70
-14
lines changed

‎http.go

Copy file name to clipboardExpand all lines: http.go
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ func (al AcceptLanguages) String() string {
413413
func ResolveAcceptLanguage(req *Request) AcceptLanguages {
414414
header := req.ServerHeader.Get("Accept-Language")
415415
if header == "" {
416-
return nil
416+
return req.AcceptLanguages
417417
}
418418

419419
acceptLanguageHeaderValues := strings.Split(header, ",")

‎validation.go

Copy file name to clipboardExpand all lines: validation.go
+43-11Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ func (e *ValidationError) String() string {
2828
// Validation context manages data validation and error messages.
2929
type Validation struct {
3030
Errors []*ValidationError
31+
Request *Request
32+
Translator func(locale, message string, args ...interface{}) string
3133
keep bool
3234
}
3335

@@ -66,19 +68,31 @@ func (v *Validation) ErrorMap() map[string]*ValidationError {
6668

6769
// Error adds an error to the validation context.
6870
func (v *Validation) Error(message string, args ...interface{}) *ValidationResult {
69-
result := (&ValidationResult{
70-
Ok: false,
71-
Error: &ValidationError{},
72-
}).Message(message, args...)
71+
result := v.ValidationResult(false).Message(message,args...)
7372
v.Errors = append(v.Errors, result.Error)
7473
return result
7574
}
76-
75+
// Error adds an error to the validation context.
76+
func (v *Validation) ErrorKey(message string, args ...interface{}) *ValidationResult {
77+
result := v.ValidationResult(false).MessageKey(message,args...)
78+
v.Errors = append(v.Errors, result.Error)
79+
return result
80+
}
81+
// Error adds an error to the validation context.
82+
func (v *Validation) ValidationResult(ok bool) *ValidationResult {
83+
if ok {
84+
return &ValidationResult{Ok:ok}
85+
} else {
86+
return &ValidationResult{Ok:ok, Error: &ValidationError{}, Locale:v.Request.Locale, Translator:v.Translator}
87+
}
88+
}
7789
// ValidationResult is returned from every validation method.
7890
// It provides an indication of success, and a pointer to the Error (if any).
7991
type ValidationResult struct {
8092
Error *ValidationError
8193
Ok bool
94+
Locale string
95+
Translator func(locale, message string, args ...interface{}) string
8296
}
8397

8498
// Key sets the ValidationResult's Error "key" and returns itself for chaining
@@ -102,6 +116,23 @@ func (r *ValidationResult) Message(message string, args ...interface{}) *Validat
102116
return r
103117
}
104118

119+
// Allow a message key to be passed into the validation result. The Validation has already
120+
// setup the translator to translate the message key
121+
func (r *ValidationResult) MessageKey(message string, args ...interface{}) *ValidationResult {
122+
if r.Error == nil {
123+
return r
124+
}
125+
126+
// If translator found, use that to create the message, otherwise call Message method
127+
if r.Translator!=nil {
128+
r.Error.Message = r.Translator(r.Locale, message, args...)
129+
} else {
130+
r.Message(message, args...)
131+
}
132+
133+
return r
134+
}
135+
105136
// Required tests that the argument is non-nil and non-empty (if string or list)
106137
func (v *Validation) Required(obj interface{}) *ValidationResult {
107138
return v.apply(Required{}, obj)
@@ -177,7 +208,7 @@ func (v *Validation) FilePath(str string, m int) *ValidationResult {
177208

178209
func (v *Validation) apply(chk Validator, obj interface{}) *ValidationResult {
179210
if chk.IsSatisfied(obj) {
180-
return &ValidationResult{Ok: true}
211+
return v.ValidationResult(true)
181212
}
182213

183214
// Get the default key.
@@ -199,10 +230,9 @@ func (v *Validation) apply(chk Validator, obj interface{}) *ValidationResult {
199230
v.Errors = append(v.Errors, err)
200231

201232
// Also return it in the result.
202-
return &ValidationResult{
203-
Ok: false,
204-
Error: err,
205-
}
233+
vr := v.ValidationResult(false)
234+
vr.Error = err
235+
return vr
206236
}
207237

208238
// Check applies a group of validators to a field, in order, and return the
@@ -224,13 +254,15 @@ func ValidationFilter(c *Controller, fc []Filter) {
224254
// If json request, we shall assume json response is intended,
225255
// as such no validation cookies should be tied response
226256
if c.Params != nil && c.Params.JSON != nil {
227-
c.Validation = &Validation{}
257+
c.Validation = &Validation{Request:c.Request, Translator:MessageFunc}
228258
fc[0](c, fc[1:])
229259
} else {
230260
errors, err := restoreValidationErrors(c.Request)
231261
c.Validation = &Validation{
232262
Errors: errors,
233263
keep: false,
264+
Request:c.Request,
265+
Translator:MessageFunc,
234266
}
235267
hasCookie := (err != http.ErrNoCookie)
236268

‎validation_test.go

Copy file name to clipboardExpand all lines: validation_test.go
+26-2Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,13 @@ func getRecordedCookie(recorder *httptest.ResponseRecorder, name string) (*http.
2121
}
2222
return nil, http.ErrNoCookie
2323
}
24-
24+
// r.Original.URL.String()
2525
func validationTester(req *Request, fn func(c *Controller)) *httptest.ResponseRecorder {
2626
recorder := httptest.NewRecorder()
2727
c := NewTestController(recorder,req.In.GetRaw().(*http.Request))
28+
c.Request = req
2829

29-
ValidationFilter(c, []Filter{func(c *Controller, _ []Filter) {
30+
ValidationFilter(c, []Filter{I18nFilter, func(c *Controller, _ []Filter) {
3031
fn(c)
3132
}})
3233
return recorder
@@ -79,3 +80,26 @@ func TestValidationNoKeepCookiePreviouslySet(t *testing.T) {
7980
t.Fatalf("cookie should be deleted")
8081
}
8182
}
83+
84+
func TestValidateMessageKey(t *testing.T) {
85+
Init("prod", "github.com/revel/revel/testdata", "")
86+
loadMessages(testDataPath)
87+
88+
// Assert that we have the expected number of languages
89+
if len(MessageLanguages()) != 2 {
90+
t.Fatalf("Expected messages to contain no more or less than 2 languages, instead there are %d languages", len(MessageLanguages()))
91+
}
92+
req := buildRequestWithAcceptLanguages("nl").Request
93+
94+
validationTester(req, func(c *Controller) {
95+
c.Validation.Required("").MessageKey("greeting")
96+
if msg:=c.Validation.Errors[0].Message; msg!="Hallo" {
97+
t.Errorf("Failed expected message Hallo got %s", msg)
98+
}
99+
100+
if !c.Validation.HasErrors() {
101+
t.Fatal("errors should not be present")
102+
}
103+
})
104+
105+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.