diff --git a/.example/util/gvalid/gvalid_custom_message.go b/.example/util/gvalid/gvalid_custom_message.go new file mode 100644 index 000000000..816749f10 --- /dev/null +++ b/.example/util/gvalid/gvalid_custom_message.go @@ -0,0 +1,13 @@ +package main + +import ( + "fmt" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/util/gvalid" +) + +func main() { + g.I18n().SetLanguage("cn") + err := gvalid.Check("", "required", nil) + fmt.Println(err.String()) +} diff --git a/.example/util/gvalid/i18n/cn.toml b/.example/util/gvalid/i18n/cn.toml new file mode 100644 index 000000000..498f60e24 --- /dev/null +++ b/.example/util/gvalid/i18n/cn.toml @@ -0,0 +1,14 @@ + + +"gf.gvalid.required" = "字段不能为空" + + + + + + + + + + + diff --git a/encoding/gjson/gjson_api_new_load.go b/encoding/gjson/gjson_api_new_load.go index 680792235..ba7a0a0c9 100644 --- a/encoding/gjson/gjson_api_new_load.go +++ b/encoding/gjson/gjson_api_new_load.go @@ -203,7 +203,7 @@ func checkDataType(content []byte) string { return "yml" } else if (gregex.IsMatch(`^[\s\t\[*\]].?*[\w\-]+\s*=\s*.+`, content) || gregex.IsMatch(`\n[\s\t\[*\]]*[\w\-]+\s*=\s*.+`, content)) && gregex.IsMatch(`\n[\s\t]*[\w\-]+\s*=*\"*.+\"`, content) == false && gregex.IsMatch(`^[\s\t]*[\w\-]+\s*=*\"*.+\"`, content) == false { return "ini" - } else if gregex.IsMatch(`^[\s\t]*[\w\-]+\s*=\s*.+`, content) || gregex.IsMatch(`\n[\s\t]*[\w\-]+\s*=\s*.+`, content) { + } else if gregex.IsMatch(`^[\s\t]*[\w\-\."]+\s*=\s*.+`, content) || gregex.IsMatch(`\n[\s\t]*[\w\-\."]+\s*=\s*.+`, content) { return "toml" } else { return "" diff --git a/util/gvalid/gvalid.go b/util/gvalid/gvalid.go index 7d4c620cb..1e4da1444 100644 --- a/util/gvalid/gvalid.go +++ b/util/gvalid/gvalid.go @@ -66,7 +66,7 @@ type CustomMsg = map[string]interface{} // The sequence tag is like: [alias@]rule[...#msg...] func parseSequenceTag(tag string) (field, rule, msg string) { // Complete sequence tag. - // Eg: required|length:2,20|password3|same:password1#||密码强度不足|两次密码不一致 + // Example: required|length:2,20|password3|same:password1#||密码强度不足|两次密码不一致 match, _ := gregex.MatchString(`\s*((\w+)\s*@){0,1}\s*([^#]+)\s*(#\s*(.*)){0,1}\s*`, tag) return strings.TrimSpace(match[2]), strings.TrimSpace(match[3]), strings.TrimSpace(match[5]) } diff --git a/util/gvalid/gvalid_check.go b/util/gvalid/gvalid_check.go index 7dfe38fa4..03168c3a2 100644 --- a/util/gvalid/gvalid_check.go +++ b/util/gvalid/gvalid_check.go @@ -236,6 +236,11 @@ func Check(value interface{}, rules string, messages interface{}, params ...inte case "date-format": if _, err := gtime.StrToTimeFormat(val, ruleVal); err == nil { match = true + } else { + var msg string + msg = getErrorMessageByRule(ruleKey, customMsgMap) + msg = strings.Replace(msg, ":format", ruleVal, -1) + errorMsgs[ruleKey] = msg } // Values of two fields should be equal as string. @@ -245,6 +250,12 @@ func Check(value interface{}, rules string, messages interface{}, params ...inte match = true } } + if !match { + var msg string + msg = getErrorMessageByRule(ruleKey, customMsgMap) + msg = strings.Replace(msg, ":field", ruleVal, -1) + errorMsgs[ruleKey] = msg + } // Values of two fields should not be equal as string. case "different": @@ -254,6 +265,12 @@ func Check(value interface{}, rules string, messages interface{}, params ...inte match = false } } + if !match { + var msg string + msg = getErrorMessageByRule(ruleKey, customMsgMap) + msg = strings.Replace(msg, ":field", ruleVal, -1) + errorMsgs[ruleKey] = msg + } // Field value should be in range of. case "in": @@ -429,11 +446,7 @@ func Check(value interface{}, rules string, messages interface{}, params ...inte // It does nothing if the error message for this rule // is already set in previous validation. if _, ok := errorMsgs[ruleKey]; !ok { - if msg, ok := customMsgMap[ruleKey]; ok { - errorMsgs[ruleKey] = msg - } else { - errorMsgs[ruleKey] = getDefaultErrorMessageByRule(ruleKey) - } + errorMsgs[ruleKey] = getErrorMessageByRule(ruleKey, customMsgMap) } } index++ diff --git a/util/gvalid/gvalid_check_struct.go b/util/gvalid/gvalid_check_struct.go index 1a91ebf85..80e1352bb 100644 --- a/util/gvalid/gvalid_check_struct.go +++ b/util/gvalid/gvalid_check_struct.go @@ -43,8 +43,10 @@ func CheckStruct(object interface{}, rules interface{}, messages ...CustomMsg) * continue } if len(msg) > 0 { - ruleArray := strings.Split(rule, "|") - msgArray := strings.Split(msg, "|") + var ( + msgArray = strings.Split(msg, "|") + ruleArray = strings.Split(rule, "|") + ) for k, v := range ruleArray { // If length of custom messages is lesser than length of rules, // the rest rules use the default error messages. diff --git a/util/gvalid/gvalid_message.go b/util/gvalid/gvalid_message.go index cc70fd655..175ca3f69 100644 --- a/util/gvalid/gvalid_message.go +++ b/util/gvalid/gvalid_message.go @@ -51,21 +51,24 @@ var defaultMessages = map[string]string{ "integer": "The :attribute value must be an integer", "float": "The :attribute value must be a float", "boolean": "The :attribute value field must be true or false", - "same": "The :attribute value must be the same as field :other", - "different": "The :attribute value must be different from field :other", + "same": "The :attribute value must be the same as field :field", + "different": "The :attribute value must be different from field :field", "in": "The :attribute value is not in acceptable range", "not-in": "The :attribute value is not in acceptable range", "regex": "The :attribute value is invalid", } -// getDefaultErrorMessageByRule retrieves and returns the default error message -// for specified rule. It firstly retrieves the message from i18n manager, it returns -// from default error messages if it's not found in i18n manager. -func getDefaultErrorMessageByRule(rule string) string { - i18nKey := fmt.Sprintf(`gf.gvalid.%s`, rule) - content := gi18n.GetContent(i18nKey) +// getErrorMessageByRule retrieves and returns the error message for specified rule. +// It firstly retrieves the message from custom message map, and then checks i18n manager, +// it returns the default error message if it's not found in custom message map or i18n manager. +func getErrorMessageByRule(ruleKey string, customMsgMap map[string]string) string { + content := customMsgMap[ruleKey] + if content != "" { + return content + } + content = gi18n.GetContent(fmt.Sprintf(`gf.gvalid.%s`, ruleKey)) if content == "" { - content = defaultMessages[rule] + content = defaultMessages[ruleKey] } return content } diff --git a/util/gvalid/gvalid_rule_length.go b/util/gvalid/gvalid_rule_length.go index 4301e6ffc..a88795151 100644 --- a/util/gvalid/gvalid_rule_length.go +++ b/util/gvalid/gvalid_rule_length.go @@ -43,11 +43,7 @@ func checkLength(value, ruleKey, ruleVal string, customMsgMap map[string]string) } } if valueLen < min || valueLen > max { - if v, ok := customMsgMap[ruleKey]; !ok { - msg = getDefaultErrorMessageByRule(ruleKey) - } else { - msg = v - } + msg = getErrorMessageByRule(ruleKey, customMsgMap) msg = strings.Replace(msg, ":min", strconv.Itoa(min), -1) msg = strings.Replace(msg, ":max", strconv.Itoa(max), -1) return msg @@ -56,11 +52,7 @@ func checkLength(value, ruleKey, ruleVal string, customMsgMap map[string]string) case "min-length": if min, err := strconv.Atoi(ruleVal); err == nil { if valueLen < min { - if v, ok := customMsgMap[ruleKey]; !ok { - msg = getDefaultErrorMessageByRule(ruleKey) - } else { - msg = v - } + msg = getErrorMessageByRule(ruleKey, customMsgMap) msg = strings.Replace(msg, ":min", strconv.Itoa(min), -1) } } else { @@ -70,11 +62,7 @@ func checkLength(value, ruleKey, ruleVal string, customMsgMap map[string]string) case "max-length": if max, err := strconv.Atoi(ruleVal); err == nil { if valueLen > max { - if v, ok := customMsgMap[ruleKey]; !ok { - msg = getDefaultErrorMessageByRule(ruleKey) - } else { - msg = v - } + msg = getErrorMessageByRule(ruleKey, customMsgMap) msg = strings.Replace(msg, ":max", strconv.Itoa(max), -1) } } else { diff --git a/util/gvalid/gvalid_rule_range.go b/util/gvalid/gvalid_rule_range.go index fddaea8a3..407654fcb 100644 --- a/util/gvalid/gvalid_rule_range.go +++ b/util/gvalid/gvalid_rule_range.go @@ -36,11 +36,7 @@ func checkRange(value, ruleKey, ruleVal string, customMsgMap map[string]string) } if v, err := strconv.ParseFloat(value, 10); err == nil { if v < min || v > max { - if v, ok := customMsgMap[ruleKey]; !ok { - msg = getDefaultErrorMessageByRule(ruleKey) - } else { - msg = v - } + msg = getErrorMessageByRule(ruleKey, customMsgMap) msg = strings.Replace(msg, ":min", strconv.FormatFloat(min, 'f', -1, 64), -1) msg = strings.Replace(msg, ":max", strconv.FormatFloat(max, 'f', -1, 64), -1) } @@ -53,11 +49,7 @@ func checkRange(value, ruleKey, ruleVal string, customMsgMap map[string]string) if min, err := strconv.ParseFloat(ruleVal, 10); err == nil { if v, err := strconv.ParseFloat(value, 10); err == nil { if v < min { - if v, ok := customMsgMap[ruleKey]; !ok { - msg = getDefaultErrorMessageByRule(ruleKey) - } else { - msg = v - } + msg = getErrorMessageByRule(ruleKey, customMsgMap) msg = strings.Replace(msg, ":min", strconv.FormatFloat(min, 'f', -1, 64), -1) } } else { @@ -72,11 +64,7 @@ func checkRange(value, ruleKey, ruleVal string, customMsgMap map[string]string) if max, err := strconv.ParseFloat(ruleVal, 10); err == nil { if v, err := strconv.ParseFloat(value, 10); err == nil { if v > max { - if v, ok := customMsgMap[ruleKey]; !ok { - msg = getDefaultErrorMessageByRule(ruleKey) - } else { - msg = v - } + msg = getErrorMessageByRule(ruleKey, customMsgMap) msg = strings.Replace(msg, ":max", strconv.FormatFloat(max, 'f', -1, 64), -1) } } else { diff --git a/util/gvalid/i18n/cn/validation.toml b/util/gvalid/i18n/cn/validation.toml new file mode 100644 index 000000000..ccdb8202a --- /dev/null +++ b/util/gvalid/i18n/cn/validation.toml @@ -0,0 +1,43 @@ +"gf.gvalid.required" = ":attribute字段不能为空" +"gf.gvalid.required-if" = ":attribute字段不能为空" +"gf.gvalid.required-unless" = ":attribute字段不能为空" +"gf.gvalid.required-with" = ":attribute字段不能为空" +"gf.gvalid.required-with-all" = ":attribute字段不能为空" +"gf.gvalid.required-without" = ":attribute字段不能为空" +"gf.gvalid.required-without-all" = ":attribute字段不能为空" +"gf.gvalid.date" = ":attribute日期格式不正确" +"gf.gvalid.date-format" = ":attribute日期格式不满足:format" +"gf.gvalid.email" = ":attribute邮箱地址格式不正确" +"gf.gvalid.phone" = ":attribute手机号码格式不正确" +"gf.gvalid.telephone" = ":attribute电话号码格式不正确" +"gf.gvalid.passport" = ":attribute账号格式不合法,必需以字母开头,只能包含字母、数字和下划线,长度在6~18之间" +"gf.gvalid.password" = ":attribute密码格式不合法,密码格式为任意6-18位的可见字符" +"gf.gvalid.password2" = ":attribute密码格式不合法,密码格式为任意6-18位的可见字符,必须包含大小写字母和数字" +"gf.gvalid.password3" = ":attribute密码格式不合法,密码格式为任意6-18位的可见字符,必须包含大小写字母、数字和特殊字符" +"gf.gvalid.postcode" = ":attribute邮政编码不正确" +"gf.gvalid.resident-id" = ":attribute身份证号码格式不正确" +"gf.gvalid.bank-card" = ":attribute银行卡号格式不正确" +"gf.gvalid.qq" = ":attributeQQ号码格式不正确" +"gf.gvalid.ip" = ":attributeIP地址格式不正确" +"gf.gvalid.ipv4" = ":attributeIPv4地址格式不正确" +"gf.gvalid.ipv6" = ":attributeIPv6地址格式不正确" +"gf.gvalid.mac" = ":attributeMAC地址格式不正确" +"gf.gvalid.url" = ":attributeURL地址格式不正确" +"gf.gvalid.domain" = ":attribute域名格式不正确" +"gf.gvalid.length" = ":attribute字段长度为:min到:max个字符" +"gf.gvalid.min-length" = ":attribute字段最小长度为:min" +"gf.gvalid.max-length" = ":attribute字段最大长度为:max" +"gf.gvalid.between" = ":attribute字段大小为:min到:max" +"gf.gvalid.min" = ":attribute字段最小值为:min" +"gf.gvalid.max" = ":attribute字段最大值为:max" +"gf.gvalid.json" = ":attribute字段应当为JSON格式" +"gf.gvalid.xml" = ":attribute字段应当为XML格式" +"gf.gvalid.array" = ":attribute字段应当为数组" +"gf.gvalid.integer" = ":attribute字段应当为整数" +"gf.gvalid.float" = ":attribute字段应当为浮点数" +"gf.gvalid.boolean" = ":attribute字段应当为布尔值" +"gf.gvalid.same" = ":attribute字段值必须和:field相同" +"gf.gvalid.different" = ":attribute字段值不能与:field相同" +"gf.gvalid.in" = ":attribute字段值不合法" +"gf.gvalid.not-in" = ":attribute字段值不合法" +"gf.gvalid.regex" = ":attribute字段值不合法" \ No newline at end of file diff --git a/util/gvalid/i18n/en/validation.toml b/util/gvalid/i18n/en/validation.toml new file mode 100644 index 000000000..90fc69632 --- /dev/null +++ b/util/gvalid/i18n/en/validation.toml @@ -0,0 +1,43 @@ +"gf.gvalid.required" = "The :attribute field is required" +"gf.gvalid.required-if" = "The :attribute field is required" +"gf.gvalid.required-unless" = "The :attribute field is required" +"gf.gvalid.required-with" = "The :attribute field is required" +"gf.gvalid.required-with-all" = "The :attribute field is required" +"gf.gvalid.required-without" = "The :attribute field is required" +"gf.gvalid.required-without-all" = "The :attribute field is required" +"gf.gvalid.date" = "The :attribute value is not a valid date" +"gf.gvalid.date-format" = "The :attribute value does not match the format :format" +"gf.gvalid.email" = "The :attribute value must be a valid email address" +"gf.gvalid.phone" = "The :attribute value must be a valid phone number" +"gf.gvalid.telephone" = "The :attribute value must be a valid telephone number" +"gf.gvalid.passport" = "The :attribute value is not a valid passport format" +"gf.gvalid.password" = "The :attribute value is not a valid passport format" +"gf.gvalid.password2" = "The :attribute value is not a valid passport format" +"gf.gvalid.password3" = "The :attribute value is not a valid passport format" +"gf.gvalid.postcode" = "The :attribute value is not a valid passport format" +"gf.gvalid.resident-id" = "The :attribute value is not a valid resident id number" +"gf.gvalid.bank-card" = "The :attribute value must be a valid bank card number" +"gf.gvalid.qq" = "The :attribute value must be a valid QQ number" +"gf.gvalid.ip" = "The :attribute value must be a valid IP address" +"gf.gvalid.ipv4" = "The :attribute value must be a valid IPv4 address" +"gf.gvalid.ipv6" = "The :attribute value must be a valid IPv6 address" +"gf.gvalid.mac" = "The :attribute value must be a valid MAC address" +"gf.gvalid.url" = "The :attribute value must be a valid URL address" +"gf.gvalid.domain" = "The :attribute value must be a valid domain format" +"gf.gvalid.length" = "The :attribute value length must be between :min and :max" +"gf.gvalid.min-length" = "The :attribute value length must be equal or greater than :min" +"gf.gvalid.max-length" = "The :attribute value length must be equal or lesser than :max" +"gf.gvalid.between" = "The :attribute value must be between :min and :max" +"gf.gvalid.min" = "The :attribute value must be equal or greater than :min" +"gf.gvalid.max" = "The :attribute value must be equal or lesser than :max" +"gf.gvalid.json" = "The :attribute value must be a valid JSON string" +"gf.gvalid.xml" = "The :attribute value must be a valid XML string" +"gf.gvalid.array" = "The :attribute value must be an array" +"gf.gvalid.integer" = "The :attribute value must be an integer" +"gf.gvalid.float" = "The :attribute value must be a float" +"gf.gvalid.boolean" = "The :attribute value field must be true or false" +"gf.gvalid.same" = "The :attribute value must be the same as field :field" +"gf.gvalid.different" = "The :attribute value must be different from field :field" +"gf.gvalid.in" = "The :attribute value is not in acceptable range" +"gf.gvalid.not-in" = "The :attribute value is not in acceptable range" +"gf.gvalid.regex" = "The :attribute value is invalid" \ No newline at end of file