Merge branch 'master' into master

pull/740/head
Vic Shóstak 3 years ago committed by GitHub
commit 2c0d3f7fe4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      .github/workflows/workflow.yml
  2. 2
      Makefile
  3. 4
      README.md
  4. 31
      baked_in.go
  5. 79
      currency_codes.go
  6. 14
      doc.go
  7. 12
      go.mod
  8. 40
      go.sum
  9. 8
      translations/fr/fr_test.go
  10. 113
      translations/ru/ru.go
  11. 374
      translations/ru/ru_test.go
  12. 4
      validator_instance.go
  13. 62
      validator_test.go

@ -45,4 +45,4 @@ jobs:
- name: golangci-lint - name: golangci-lint
uses: golangci/golangci-lint-action@v2 uses: golangci/golangci-lint-action@v2
with: with:
version: v1.39 version: v1.41.1

@ -3,7 +3,7 @@ GOCMD=GO111MODULE=on go
linters-install: linters-install:
@golangci-lint --version >/dev/null 2>&1 || { \ @golangci-lint --version >/dev/null 2>&1 || { \
echo "installing linting tools..."; \ echo "installing linting tools..."; \
curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s v1.39.0; \ curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s v1.41.1; \
} }
lint: linters-install lint: linters-install

@ -1,7 +1,7 @@
Package validator Package validator
================= =================
<img align="right" src="https://raw.githubusercontent.com/go-playground/validator/v9/logo.png">[![Join the chat at https://gitter.im/go-playground/validator](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/go-playground/validator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) <img align="right" src="https://raw.githubusercontent.com/go-playground/validator/v9/logo.png">[![Join the chat at https://gitter.im/go-playground/validator](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/go-playground/validator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
![Project status](https://img.shields.io/badge/version-10.8.0-green.svg) ![Project status](https://img.shields.io/badge/version-10.9.0-green.svg)
[![Build Status](https://travis-ci.org/go-playground/validator.svg?branch=master)](https://travis-ci.org/go-playground/validator) [![Build Status](https://travis-ci.org/go-playground/validator.svg?branch=master)](https://travis-ci.org/go-playground/validator)
[![Coverage Status](https://coveralls.io/repos/go-playground/validator/badge.svg?branch=master&service=github)](https://coveralls.io/github/go-playground/validator?branch=master) [![Coverage Status](https://coveralls.io/repos/go-playground/validator/badge.svg?branch=master&service=github)](https://coveralls.io/github/go-playground/validator?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/go-playground/validator)](https://goreportcard.com/report/github.com/go-playground/validator) [![Go Report Card](https://goreportcard.com/badge/github.com/go-playground/validator)](https://goreportcard.com/report/github.com/go-playground/validator)
@ -126,6 +126,7 @@ Baked-in Validations
| alphanumunicode | Alphanumeric Unicode | | alphanumunicode | Alphanumeric Unicode |
| alphaunicode | Alpha Unicode | | alphaunicode | Alpha Unicode |
| ascii | ASCII | | ascii | ASCII |
| boolean | Boolean |
| contains | Contains | | contains | Contains |
| containsany | Contains Any | | containsany | Contains Any |
| containsrune | Contains Rune | | containsrune | Contains Rune |
@ -169,6 +170,7 @@ Baked-in Validations
| iso3166_1_alpha3 | Three-letter country code (ISO 3166-1 alpha-3) | | iso3166_1_alpha3 | Three-letter country code (ISO 3166-1 alpha-3) |
| iso3166_1_alpha_numeric | Numeric country code (ISO 3166-1 numeric) | | iso3166_1_alpha_numeric | Numeric country code (ISO 3166-1 numeric) |
| iso3166_2 | Country subdivision code (ISO 3166-2) | | iso3166_2 | Country subdivision code (ISO 3166-2) |
| iso4217 | Currency code (ISO 4217) |
| json | JSON | | json | JSON |
| jwt | JSON Web Token (JWT) | | jwt | JSON Web Token (JWT) |
| latitude | Latitude | | latitude | Latitude |

@ -107,6 +107,7 @@ var (
"alphanum": isAlphanum, "alphanum": isAlphanum,
"alphaunicode": isAlphaUnicode, "alphaunicode": isAlphaUnicode,
"alphanumunicode": isAlphanumUnicode, "alphanumunicode": isAlphanumUnicode,
"boolean": isBoolean,
"numeric": isNumeric, "numeric": isNumeric,
"number": isNumber, "number": isNumber,
"hexadecimal": isHexadecimal, "hexadecimal": isHexadecimal,
@ -191,6 +192,8 @@ var (
"iso3166_1_alpha3": isIso3166Alpha3, "iso3166_1_alpha3": isIso3166Alpha3,
"iso3166_1_alpha_numeric": isIso3166AlphaNumeric, "iso3166_1_alpha_numeric": isIso3166AlphaNumeric,
"iso3166_2": isIso31662, "iso3166_2": isIso31662,
"iso4217": isIso4217,
"iso4217_numeric": isIso4217Numeric,
"bcp47_language_tag": isBCP47LanguageTag, "bcp47_language_tag": isBCP47LanguageTag,
"postcode_iso3166_alpha2": isPostcodeByIso3166Alpha2, "postcode_iso3166_alpha2": isPostcodeByIso3166Alpha2,
"postcode_iso3166_alpha2_field": isPostcodeByIso3166Alpha2Field, "postcode_iso3166_alpha2_field": isPostcodeByIso3166Alpha2Field,
@ -1438,6 +1441,12 @@ func isAlphaUnicode(fl FieldLevel) bool {
return alphaUnicodeRegex.MatchString(fl.Field().String()) return alphaUnicodeRegex.MatchString(fl.Field().String())
} }
// isBoolean is the validation function for validating if the current field's value can be safely converted to a boolean.
func isBoolean(fl FieldLevel) bool {
_, err := strconv.ParseBool(fl.Field().String())
return err == nil
}
// isDefault is the opposite of required aka hasValue // isDefault is the opposite of required aka hasValue
func isDefault(fl FieldLevel) bool { func isDefault(fl FieldLevel) bool {
return !hasValue(fl) return !hasValue(fl)
@ -2358,6 +2367,28 @@ func isIso31662(fl FieldLevel) bool {
return iso3166_2[val] return iso3166_2[val]
} }
// isIso4217 is the validation function for validating if the current field's value is a valid iso4217 currency code.
func isIso4217(fl FieldLevel) bool {
val := fl.Field().String()
return iso4217[val]
}
// isIso4217Numeric is the validation function for validating if the current field's value is a valid iso4217 numeric currency code.
func isIso4217Numeric(fl FieldLevel) bool {
field := fl.Field()
var code int
switch field.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
code = int(field.Int())
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
code = int(field.Uint())
default:
panic(fmt.Sprintf("Bad field type %T", field.Interface()))
}
return iso4217_numeric[code]
}
// isBCP47LanguageTag is the validation function for validating if the current field's value is a valid BCP 47 language tag, as parsed by language.Parse // isBCP47LanguageTag is the validation function for validating if the current field's value is a valid BCP 47 language tag, as parsed by language.Parse
func isBCP47LanguageTag(fl FieldLevel) bool { func isBCP47LanguageTag(fl FieldLevel) bool {
field := fl.Field() field := fl.Field()

@ -0,0 +1,79 @@
package validator
var iso4217 = map[string]bool{
"AFN": true, "EUR": true, "ALL": true, "DZD": true, "USD": true,
"AOA": true, "XCD": true, "ARS": true, "AMD": true, "AWG": true,
"AUD": true, "AZN": true, "BSD": true, "BHD": true, "BDT": true,
"BBD": true, "BYN": true, "BZD": true, "XOF": true, "BMD": true,
"INR": true, "BTN": true, "BOB": true, "BOV": true, "BAM": true,
"BWP": true, "NOK": true, "BRL": true, "BND": true, "BGN": true,
"BIF": true, "CVE": true, "KHR": true, "XAF": true, "CAD": true,
"KYD": true, "CLP": true, "CLF": true, "CNY": true, "COP": true,
"COU": true, "KMF": true, "CDF": true, "NZD": true, "CRC": true,
"HRK": true, "CUP": true, "CUC": true, "ANG": true, "CZK": true,
"DKK": true, "DJF": true, "DOP": true, "EGP": true, "SVC": true,
"ERN": true, "SZL": true, "ETB": true, "FKP": true, "FJD": true,
"XPF": true, "GMD": true, "GEL": true, "GHS": true, "GIP": true,
"GTQ": true, "GBP": true, "GNF": true, "GYD": true, "HTG": true,
"HNL": true, "HKD": true, "HUF": true, "ISK": true, "IDR": true,
"XDR": true, "IRR": true, "IQD": true, "ILS": true, "JMD": true,
"JPY": true, "JOD": true, "KZT": true, "KES": true, "KPW": true,
"KRW": true, "KWD": true, "KGS": true, "LAK": true, "LBP": true,
"LSL": true, "ZAR": true, "LRD": true, "LYD": true, "CHF": true,
"MOP": true, "MKD": true, "MGA": true, "MWK": true, "MYR": true,
"MVR": true, "MRU": true, "MUR": true, "XUA": true, "MXN": true,
"MXV": true, "MDL": true, "MNT": true, "MAD": true, "MZN": true,
"MMK": true, "NAD": true, "NPR": true, "NIO": true, "NGN": true,
"OMR": true, "PKR": true, "PAB": true, "PGK": true, "PYG": true,
"PEN": true, "PHP": true, "PLN": true, "QAR": true, "RON": true,
"RUB": true, "RWF": true, "SHP": true, "WST": true, "STN": true,
"SAR": true, "RSD": true, "SCR": true, "SLL": true, "SGD": true,
"XSU": true, "SBD": true, "SOS": true, "SSP": true, "LKR": true,
"SDG": true, "SRD": true, "SEK": true, "CHE": true, "CHW": true,
"SYP": true, "TWD": true, "TJS": true, "TZS": true, "THB": true,
"TOP": true, "TTD": true, "TND": true, "TRY": true, "TMT": true,
"UGX": true, "UAH": true, "AED": true, "USN": true, "UYU": true,
"UYI": true, "UYW": true, "UZS": true, "VUV": true, "VES": true,
"VND": true, "YER": true, "ZMW": true, "ZWL": true, "XBA": true,
"XBB": true, "XBC": true, "XBD": true, "XTS": true, "XXX": true,
"XAU": true, "XPD": true, "XPT": true, "XAG": true,
}
var iso4217_numeric = map[int]bool{
8: true, 12: true, 32: true, 36: true, 44: true,
48: true, 50: true, 51: true, 52: true, 60: true,
64: true, 68: true, 72: true, 84: true, 90: true,
96: true, 104: true, 108: true, 116: true, 124: true,
132: true, 136: true, 144: true, 152: true, 156: true,
170: true, 174: true, 188: true, 191: true, 192: true,
203: true, 208: true, 214: true, 222: true, 230: true,
232: true, 238: true, 242: true, 262: true, 270: true,
292: true, 320: true, 324: true, 328: true, 332: true,
340: true, 344: true, 348: true, 352: true, 356: true,
360: true, 364: true, 368: true, 376: true, 388: true,
392: true, 398: true, 400: true, 404: true, 408: true,
410: true, 414: true, 417: true, 418: true, 422: true,
426: true, 430: true, 434: true, 446: true, 454: true,
458: true, 462: true, 480: true, 484: true, 496: true,
498: true, 504: true, 512: true, 516: true, 524: true,
532: true, 533: true, 548: true, 554: true, 558: true,
566: true, 578: true, 586: true, 590: true, 598: true,
600: true, 604: true, 608: true, 634: true, 643: true,
646: true, 654: true, 682: true, 690: true, 694: true,
702: true, 704: true, 706: true, 710: true, 728: true,
748: true, 752: true, 756: true, 760: true, 764: true,
776: true, 780: true, 784: true, 788: true, 800: true,
807: true, 818: true, 826: true, 834: true, 840: true,
858: true, 860: true, 882: true, 886: true, 901: true,
927: true, 928: true, 929: true, 930: true, 931: true,
932: true, 933: true, 934: true, 936: true, 938: true,
940: true, 941: true, 943: true, 944: true, 946: true,
947: true, 948: true, 949: true, 950: true, 951: true,
952: true, 953: true, 955: true, 956: true, 957: true,
958: true, 959: true, 960: true, 961: true, 962: true,
963: true, 964: true, 965: true, 967: true, 968: true,
969: true, 970: true, 971: true, 972: true, 973: true,
975: true, 976: true, 977: true, 978: true, 979: true,
980: true, 981: true, 984: true, 985: true, 986: true,
990: true, 994: true, 997: true, 999: true,
}

@ -7,6 +7,14 @@ and has the ability to dive into arrays and maps of any type.
see more examples https://github.com/go-playground/validator/tree/master/_examples see more examples https://github.com/go-playground/validator/tree/master/_examples
Singleton
Validator is designed to be thread-safe and used as a singleton instance.
It caches information about your struct and validations,
in essence only parsing your validation tags once per struct type.
Using multiple instances neglects the benefit of caching.
The not thread-safe functions are explicitly marked as such in the documentation.
Validation Functions Return Type error Validation Functions Return Type error
Doing things this way is actually the way the standard library does, see the Doing things this way is actually the way the standard library does, see the
@ -726,6 +734,12 @@ This validates that a string value contains unicode alphanumeric characters only
Usage: alphanumunicode Usage: alphanumunicode
Boolean
This validates that a string value can successfully be parsed into a boolean with strconv.ParseBool
Usage: boolean
Number Number
This validates that a string value contains number values only. This validates that a string value contains number values only.

@ -3,11 +3,17 @@ module github.com/go-playground/validator/v10
go 1.13 go 1.13
require ( require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-playground/assert/v2 v2.0.1 github.com/go-playground/assert/v2 v2.0.1
github.com/go-playground/locales v0.13.0 github.com/go-playground/locales v0.14.0
github.com/go-playground/universal-translator v0.17.0 github.com/go-playground/universal-translator v0.18.0
github.com/kr/pretty v0.3.0 // indirect
github.com/leodido/go-urn v1.2.1 github.com/leodido/go-urn v1.2.1
github.com/rogpeppe/go-internal v1.8.0 // indirect
github.com/stretchr/testify v1.7.0 // indirect
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 // indirect
golang.org/x/text v0.3.6 golang.org/x/text v0.3.6
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
) )

@ -1,32 +1,50 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 h1:siQdpVirKtzPhKl3lZWozZraCFObP8S1v6PRp0bLrtU=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

@ -4,9 +4,9 @@ import (
"testing" "testing"
"time" "time"
. "github.com/go-playground/assert/v2"
french "github.com/go-playground/locales/fr" french "github.com/go-playground/locales/fr"
ut "github.com/go-playground/universal-translator" ut "github.com/go-playground/universal-translator"
. "github.com/go-playground/assert/v2"
"github.com/go-playground/validator/v10" "github.com/go-playground/validator/v10"
) )
@ -536,7 +536,7 @@ func TestTranslations(t *testing.T) {
}, },
{ {
ns: "Test.MaxNumber", ns: "Test.MaxNumber",
expected: "MaxNumber doit être égal à 1 113,00 ou moins", expected: "MaxNumber doit être égal à 1113,00 ou moins",
}, },
{ {
ns: "Test.MaxMultiple", ns: "Test.MaxMultiple",
@ -548,7 +548,7 @@ func TestTranslations(t *testing.T) {
}, },
{ {
ns: "Test.MinNumber", ns: "Test.MinNumber",
expected: "MinNumber doit être égal à 1 113,00 ou plus", expected: "MinNumber doit être égal à 1113,00 ou plus",
}, },
{ {
ns: "Test.MinMultiple", ns: "Test.MinMultiple",
@ -560,7 +560,7 @@ func TestTranslations(t *testing.T) {
}, },
{ {
ns: "Test.LenNumber", ns: "Test.LenNumber",
expected: "LenNumber doit être égal à 1 113,00", expected: "LenNumber doit être égal à 1113,00",
}, },
{ {
ns: "Test.LenMultiple", ns: "Test.LenMultiple",

@ -41,6 +41,14 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
return return
} }
if err = ut.AddCardinal("len-string-character", "{0} символа", locales.PluralRuleFew, false); err != nil {
return
}
if err = ut.AddCardinal("len-string-character", "{0} символов", locales.PluralRuleMany, false); err != nil {
return
}
if err = ut.AddCardinal("len-string-character", "{0} символы", locales.PluralRuleOther, false); err != nil { if err = ut.AddCardinal("len-string-character", "{0} символы", locales.PluralRuleOther, false); err != nil {
return return
} }
@ -52,10 +60,19 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
if err = ut.Add("len-items", "{0} должен содержать {1}", false); err != nil { if err = ut.Add("len-items", "{0} должен содержать {1}", false); err != nil {
return return
} }
if err = ut.AddCardinal("len-items-item", "{0} элемент", locales.PluralRuleOne, false); err != nil { if err = ut.AddCardinal("len-items-item", "{0} элемент", locales.PluralRuleOne, false); err != nil {
return return
} }
if err = ut.AddCardinal("len-items-item", "{0} элемента", locales.PluralRuleFew, false); err != nil {
return
}
if err = ut.AddCardinal("len-items-item", "{0} элементов", locales.PluralRuleMany, false); err != nil {
return
}
if err = ut.AddCardinal("len-items-item", "{0} элементы", locales.PluralRuleOther, false); err != nil { if err = ut.AddCardinal("len-items-item", "{0} элементы", locales.PluralRuleOther, false); err != nil {
return return
} }
@ -132,6 +149,14 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
return return
} }
if err = ut.AddCardinal("min-string-character", "{0} символа", locales.PluralRuleFew, false); err != nil {
return
}
if err = ut.AddCardinal("min-string-character", "{0} символов", locales.PluralRuleMany, false); err != nil {
return
}
if err = ut.AddCardinal("min-string-character", "{0} символы", locales.PluralRuleOther, false); err != nil { if err = ut.AddCardinal("min-string-character", "{0} символы", locales.PluralRuleOther, false); err != nil {
return return
} }
@ -147,6 +172,14 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
return return
} }
if err = ut.AddCardinal("min-items-item", "{0} элемента", locales.PluralRuleFew, false); err != nil {
return
}
if err = ut.AddCardinal("min-items-item", "{0} элементов", locales.PluralRuleMany, false); err != nil {
return
}
if err = ut.AddCardinal("min-items-item", "{0} элементы", locales.PluralRuleOther, false); err != nil { if err = ut.AddCardinal("min-items-item", "{0} элементы", locales.PluralRuleOther, false); err != nil {
return return
} }
@ -223,6 +256,14 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
return return
} }
if err = ut.AddCardinal("max-string-character", "{0} символа", locales.PluralRuleFew, false); err != nil {
return
}
if err = ut.AddCardinal("max-string-character", "{0} символов", locales.PluralRuleMany, false); err != nil {
return
}
if err = ut.AddCardinal("max-string-character", "{0} символы", locales.PluralRuleOther, false); err != nil { if err = ut.AddCardinal("max-string-character", "{0} символы", locales.PluralRuleOther, false); err != nil {
return return
} }
@ -238,6 +279,14 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
return return
} }
if err = ut.AddCardinal("max-items-item", "{0} элемента", locales.PluralRuleFew, false); err != nil {
return
}
if err = ut.AddCardinal("max-items-item", "{0} элементов", locales.PluralRuleMany, false); err != nil {
return
}
if err = ut.AddCardinal("max-items-item", "{0} элементы", locales.PluralRuleOther, false); err != nil { if err = ut.AddCardinal("max-items-item", "{0} элементы", locales.PluralRuleOther, false); err != nil {
return return
} }
@ -344,6 +393,14 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
return return
} }
if err = ut.AddCardinal("lt-string-character", "{0} символов", locales.PluralRuleFew, false); err != nil {
return
}
if err = ut.AddCardinal("lt-string-character", "{0} символов", locales.PluralRuleMany, false); err != nil {
return
}
if err = ut.AddCardinal("lt-string-character", "{0} символы", locales.PluralRuleOther, false); err != nil { if err = ut.AddCardinal("lt-string-character", "{0} символы", locales.PluralRuleOther, false); err != nil {
return return
} }
@ -360,6 +417,14 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
return return
} }
if err = ut.AddCardinal("lt-items-item", "{0} элементов", locales.PluralRuleFew, false); err != nil {
return
}
if err = ut.AddCardinal("lt-items-item", "{0} элементов", locales.PluralRuleMany, false); err != nil {
return
}
if err = ut.AddCardinal("lt-items-item", "{0} элементы", locales.PluralRuleOther, false); err != nil { if err = ut.AddCardinal("lt-items-item", "{0} элементы", locales.PluralRuleOther, false); err != nil {
return return
} }
@ -465,6 +530,14 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
return return
} }
if err = ut.AddCardinal("lte-string-character", "{0} символа", locales.PluralRuleFew, false); err != nil {
return
}
if err = ut.AddCardinal("lte-string-character", "{0} символов", locales.PluralRuleMany, false); err != nil {
return
}
if err = ut.AddCardinal("lte-string-character", "{0} символы", locales.PluralRuleOther, false); err != nil { if err = ut.AddCardinal("lte-string-character", "{0} символы", locales.PluralRuleOther, false); err != nil {
return return
} }
@ -481,6 +554,14 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
return return
} }
if err = ut.AddCardinal("lte-items-item", "{0} элемента", locales.PluralRuleFew, false); err != nil {
return
}
if err = ut.AddCardinal("lte-items-item", "{0} элементов", locales.PluralRuleMany, false); err != nil {
return
}
if err = ut.AddCardinal("lte-items-item", "{0} элементы", locales.PluralRuleOther, false); err != nil { if err = ut.AddCardinal("lte-items-item", "{0} элементы", locales.PluralRuleOther, false); err != nil {
return return
} }
@ -585,6 +666,14 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
return return
} }
if err = ut.AddCardinal("gt-string-character", "{0} символов", locales.PluralRuleFew, false); err != nil {
return
}
if err = ut.AddCardinal("gt-string-character", "{0} символов", locales.PluralRuleMany, false); err != nil {
return
}
if err = ut.AddCardinal("gt-string-character", "{0} символы", locales.PluralRuleOther, false); err != nil { if err = ut.AddCardinal("gt-string-character", "{0} символы", locales.PluralRuleOther, false); err != nil {
return return
} }
@ -601,6 +690,14 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
return return
} }
if err = ut.AddCardinal("gt-items-item", "{0} элементов", locales.PluralRuleFew, false); err != nil {
return
}
if err = ut.AddCardinal("gt-items-item", "{0} элементов", locales.PluralRuleMany, false); err != nil {
return
}
if err = ut.AddCardinal("gt-items-item", "{0} элементы", locales.PluralRuleOther, false); err != nil { if err = ut.AddCardinal("gt-items-item", "{0} элементы", locales.PluralRuleOther, false); err != nil {
return return
} }
@ -705,6 +802,14 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
return return
} }
if err = ut.AddCardinal("gte-string-character", "{0} символа", locales.PluralRuleFew, false); err != nil {
return
}
if err = ut.AddCardinal("gte-string-character", "{0} символов", locales.PluralRuleMany, false); err != nil {
return
}
if err = ut.AddCardinal("gte-string-character", "{0} символы", locales.PluralRuleOther, false); err != nil { if err = ut.AddCardinal("gte-string-character", "{0} символы", locales.PluralRuleOther, false); err != nil {
return return
} }
@ -721,6 +826,14 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
return return
} }
if err = ut.AddCardinal("gte-items-item", "{0} элемента", locales.PluralRuleFew, false); err != nil {
return
}
if err = ut.AddCardinal("gte-items-item", "{0} элементов", locales.PluralRuleMany, false); err != nil {
return
}
if err = ut.AddCardinal("gte-items-item", "{0} элементы", locales.PluralRuleOther, false); err != nil { if err = ut.AddCardinal("gte-items-item", "{0} элементы", locales.PluralRuleOther, false); err != nil {
return return
} }

@ -7,7 +7,7 @@ import (
"time" "time"
. "github.com/go-playground/assert/v2" . "github.com/go-playground/assert/v2"
russian "github.com/go-playground/locales/en" russian "github.com/go-playground/locales/ru"
ut "github.com/go-playground/universal-translator" ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10" "github.com/go-playground/validator/v10"
) )
@ -33,116 +33,136 @@ func TestTranslations(t *testing.T) {
} }
type Test struct { type Test struct {
Inner Inner Inner Inner
RequiredString string `validate:"required"` RequiredString string `validate:"required"`
RequiredNumber int `validate:"required"` RequiredNumber int `validate:"required"`
RequiredMultiple []string `validate:"required"` RequiredMultiple []string `validate:"required"`
LenString string `validate:"len=1"` LenString string `validate:"len=1"`
LenNumber float64 `validate:"len=1113.00"` LenNumber float64 `validate:"len=1113.00"`
LenMultiple []string `validate:"len=7"` LenMultiple []string `validate:"len=7"`
MinString string `validate:"min=1"` LenMultipleSecond []string `validate:"len=2"`
MinNumber float64 `validate:"min=1113.00"` MinString string `validate:"min=1"`
MinMultiple []string `validate:"min=7"` MinStringMultiple string `validate:"min=2"`
MaxString string `validate:"max=3"` MinStringMultipleSecond string `validate:"min=7"`
MaxNumber float64 `validate:"max=1113.00"` MinNumber float64 `validate:"min=1113.00"`
MaxMultiple []string `validate:"max=7"` MinMultiple []string `validate:"min=7"`
EqString string `validate:"eq=3"` MinMultipleSecond []string `validate:"min=2"`
EqNumber float64 `validate:"eq=2.33"` MaxString string `validate:"max=3"`
EqMultiple []string `validate:"eq=7"` MaxStringSecond string `validate:"max=7"`
NeString string `validate:"ne="` MaxNumber float64 `validate:"max=1113.00"`
NeNumber float64 `validate:"ne=0.00"` MaxMultiple []string `validate:"max=7"`
NeMultiple []string `validate:"ne=0"` MaxMultipleSecond []string `validate:"max=2"`
LtString string `validate:"lt=3"` EqString string `validate:"eq=3"`
LtNumber float64 `validate:"lt=5.56"` EqNumber float64 `validate:"eq=2.33"`
LtMultiple []string `validate:"lt=2"` EqMultiple []string `validate:"eq=7"`
LtTime time.Time `validate:"lt"` NeString string `validate:"ne="`
LteString string `validate:"lte=3"` NeNumber float64 `validate:"ne=0.00"`
LteNumber float64 `validate:"lte=5.56"` NeMultiple []string `validate:"ne=0"`
LteMultiple []string `validate:"lte=2"` LtString string `validate:"lt=3"`
LteTime time.Time `validate:"lte"` LtStringSecond string `validate:"lt=7"`
GtString string `validate:"gt=3"` LtNumber float64 `validate:"lt=5.56"`
GtNumber float64 `validate:"gt=5.56"` LtMultiple []string `validate:"lt=2"`
GtMultiple []string `validate:"gt=2"` LtMultipleSecond []string `validate:"lt=7"`
GtTime time.Time `validate:"gt"` LtTime time.Time `validate:"lt"`
GteString string `validate:"gte=3"` LteString string `validate:"lte=3"`
GteNumber float64 `validate:"gte=5.56"` LteStringSecond string `validate:"lte=7"`
GteMultiple []string `validate:"gte=2"` LteNumber float64 `validate:"lte=5.56"`
GteTime time.Time `validate:"gte"` LteMultiple []string `validate:"lte=2"`
EqFieldString string `validate:"eqfield=MaxString"` LteMultipleSecond []string `validate:"lte=7"`
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"` LteTime time.Time `validate:"lte"`
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"` GtString string `validate:"gt=3"`
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"` GtStringSecond string `validate:"gt=7"`
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"` GtNumber float64 `validate:"gt=5.56"`
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"` GtMultiple []string `validate:"gt=2"`
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"` GtMultipleSecond []string `validate:"gt=7"`
NeFieldString string `validate:"nefield=EqFieldString"` GtTime time.Time `validate:"gt"`
GtFieldString string `validate:"gtfield=MaxString"` GteString string `validate:"gte=3"`
GteFieldString string `validate:"gtefield=MaxString"` GteStringSecond string `validate:"gte=7"`
LtFieldString string `validate:"ltfield=MaxString"` GteNumber float64 `validate:"gte=5.56"`
LteFieldString string `validate:"ltefield=MaxString"` GteMultiple []string `validate:"gte=2"`
AlphaString string `validate:"alpha"` GteMultipleSecond []string `validate:"gte=7"`
AlphanumString string `validate:"alphanum"` GteTime time.Time `validate:"gte"`
NumericString string `validate:"numeric"` EqFieldString string `validate:"eqfield=MaxString"`
NumberString string `validate:"number"` EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"`
HexadecimalString string `validate:"hexadecimal"` NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"`
HexColorString string `validate:"hexcolor"` GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"`
RGBColorString string `validate:"rgb"` GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"`
RGBAColorString string `validate:"rgba"` LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"`
HSLColorString string `validate:"hsl"` LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"`
HSLAColorString string `validate:"hsla"` NeFieldString string `validate:"nefield=EqFieldString"`
Email string `validate:"email"` GtFieldString string `validate:"gtfield=MaxString"`
URL string `validate:"url"` GteFieldString string `validate:"gtefield=MaxString"`
URI string `validate:"uri"` LtFieldString string `validate:"ltfield=MaxString"`
Base64 string `validate:"base64"` LteFieldString string `validate:"ltefield=MaxString"`
Contains string `validate:"contains=purpose"` AlphaString string `validate:"alpha"`
ContainsAny string `validate:"containsany=!@#$"` AlphanumString string `validate:"alphanum"`
Excludes string `validate:"excludes=text"` NumericString string `validate:"numeric"`
ExcludesAll string `validate:"excludesall=!@#$"` NumberString string `validate:"number"`
ExcludesRune string `validate:"excludesrune=☻"` HexadecimalString string `validate:"hexadecimal"`
ISBN string `validate:"isbn"` HexColorString string `validate:"hexcolor"`
ISBN10 string `validate:"isbn10"` RGBColorString string `validate:"rgb"`
ISBN13 string `validate:"isbn13"` RGBAColorString string `validate:"rgba"`
UUID string `validate:"uuid"` HSLColorString string `validate:"hsl"`
UUID3 string `validate:"uuid3"` HSLAColorString string `validate:"hsla"`
UUID4 string `validate:"uuid4"` Email string `validate:"email"`
UUID5 string `validate:"uuid5"` URL string `validate:"url"`
ASCII string `validate:"ascii"` URI string `validate:"uri"`
PrintableASCII string `validate:"printascii"` Base64 string `validate:"base64"`
MultiByte string `validate:"multibyte"` Contains string `validate:"contains=purpose"`
DataURI string `validate:"datauri"` ContainsAny string `validate:"containsany=!@#$"`
Latitude string `validate:"latitude"` Excludes string `validate:"excludes=text"`
Longitude string `validate:"longitude"` ExcludesAll string `validate:"excludesall=!@#$"`
SSN string `validate:"ssn"` ExcludesRune string `validate:"excludesrune=☻"`
IP string `validate:"ip"` ISBN string `validate:"isbn"`
IPv4 string `validate:"ipv4"` ISBN10 string `validate:"isbn10"`
IPv6 string `validate:"ipv6"` ISBN13 string `validate:"isbn13"`
CIDR string `validate:"cidr"` UUID string `validate:"uuid"`
CIDRv4 string `validate:"cidrv4"` UUID3 string `validate:"uuid3"`
CIDRv6 string `validate:"cidrv6"` UUID4 string `validate:"uuid4"`
TCPAddr string `validate:"tcp_addr"` UUID5 string `validate:"uuid5"`
TCPAddrv4 string `validate:"tcp4_addr"` ASCII string `validate:"ascii"`
TCPAddrv6 string `validate:"tcp6_addr"` PrintableASCII string `validate:"printascii"`
UDPAddr string `validate:"udp_addr"` MultiByte string `validate:"multibyte"`
UDPAddrv4 string `validate:"udp4_addr"` DataURI string `validate:"datauri"`
UDPAddrv6 string `validate:"udp6_addr"` Latitude string `validate:"latitude"`
IPAddr string `validate:"ip_addr"` Longitude string `validate:"longitude"`
IPAddrv4 string `validate:"ip4_addr"` SSN string `validate:"ssn"`
IPAddrv6 string `validate:"ip6_addr"` IP string `validate:"ip"`
UinxAddr string `validate:"unix_addr"` // can't fail from within Go's net package currently, but maybe in the future IPv4 string `validate:"ipv4"`
MAC string `validate:"mac"` IPv6 string `validate:"ipv6"`
IsColor string `validate:"iscolor"` CIDR string `validate:"cidr"`
StrPtrMinLen *string `validate:"min=10"` CIDRv4 string `validate:"cidrv4"`
StrPtrMaxLen *string `validate:"max=1"` CIDRv6 string `validate:"cidrv6"`
StrPtrLen *string `validate:"len=2"` TCPAddr string `validate:"tcp_addr"`
StrPtrLt *string `validate:"lt=1"` TCPAddrv4 string `validate:"tcp4_addr"`
StrPtrLte *string `validate:"lte=1"` TCPAddrv6 string `validate:"tcp6_addr"`
StrPtrGt *string `validate:"gt=10"` UDPAddr string `validate:"udp_addr"`
StrPtrGte *string `validate:"gte=10"` UDPAddrv4 string `validate:"udp4_addr"`
OneOfString string `validate:"oneof=red green"` UDPAddrv6 string `validate:"udp6_addr"`
OneOfInt int `validate:"oneof=5 63"` IPAddr string `validate:"ip_addr"`
UniqueSlice []string `validate:"unique"` IPAddrv4 string `validate:"ip4_addr"`
UniqueArray [3]string `validate:"unique"` IPAddrv6 string `validate:"ip6_addr"`
UniqueMap map[string]string `validate:"unique"` UinxAddr string `validate:"unix_addr"` // can't fail from within Go's net package currently, but maybe in the future
MAC string `validate:"mac"`
IsColor string `validate:"iscolor"`
StrPtrMinLen *string `validate:"min=10"`
StrPtrMinLenSecond *string `validate:"min=2"`
StrPtrMaxLen *string `validate:"max=1"`
StrPtrLen *string `validate:"len=2"`
StrPtrLenSecond *string `validate:"len=7"`
StrPtrLt *string `validate:"lt=1"`
StrPtrLte *string `validate:"lte=1"`
StrPtrLteMultiple *string `validate:"lte=2"`
StrPtrLteMultipleSecond *string `validate:"lte=7"`
StrPtrGt *string `validate:"gt=10"`
StrPtrGte *string `validate:"gte=10"`
StrPtrGtSecond *string `validate:"gt=2"`
StrPtrGteSecond *string `validate:"gte=2"`
OneOfString string `validate:"oneof=red green"`
OneOfInt int `validate:"oneof=5 63"`
UniqueSlice []string `validate:"unique"`
UniqueArray [3]string `validate:"unique"`
UniqueMap map[string]string `validate:"unique"`
} }
var test Test var test Test
@ -152,17 +172,23 @@ func TestTranslations(t *testing.T) {
test.Inner.GteCSFieldString = "1234" test.Inner.GteCSFieldString = "1234"
test.MaxString = "1234" test.MaxString = "1234"
test.MaxStringSecond = "12345678"
test.MaxNumber = 2000 test.MaxNumber = 2000
test.MaxMultiple = make([]string, 9) test.MaxMultiple = make([]string, 9)
test.MaxMultipleSecond = make([]string, 3)
test.LtString = "1234" test.LtString = "1234"
test.LtStringSecond = "12345678"
test.LtNumber = 6 test.LtNumber = 6
test.LtMultiple = make([]string, 3) test.LtMultiple = make([]string, 3)
test.LtMultipleSecond = make([]string, 8)
test.LtTime = time.Now().Add(time.Hour * 24) test.LtTime = time.Now().Add(time.Hour * 24)
test.LteString = "1234" test.LteString = "1234"
test.LteStringSecond = "12345678"
test.LteNumber = 6 test.LteNumber = 6
test.LteMultiple = make([]string, 3) test.LteMultiple = make([]string, 3)
test.LteMultipleSecond = make([]string, 8)
test.LteTime = time.Now().Add(time.Hour * 24) test.LteTime = time.Now().Add(time.Hour * 24)
test.LtFieldString = "12345" test.LtFieldString = "12345"
@ -452,15 +478,23 @@ func TestTranslations(t *testing.T) {
}, },
{ {
ns: "Test.GteString", ns: "Test.GteString",
expected: "GteString должен содержать минимум 3 символы", expected: "GteString должен содержать минимум 3 символа",
},
{
ns: "Test.GteStringSecond",
expected: "GteStringSecond должен содержать минимум 7 символов",
}, },
{ {
ns: "Test.GteNumber", ns: "Test.GteNumber",
expected: "GteNumber должен быть больше или равно 5.56", expected: "GteNumber должен быть больше или равно 5,56",
}, },
{ {
ns: "Test.GteMultiple", ns: "Test.GteMultiple",
expected: "GteMultiple должен содержать минимум 2 элементы", expected: "GteMultiple должен содержать минимум 2 элемента",
},
{
ns: "Test.GteMultipleSecond",
expected: "GteMultipleSecond должен содержать минимум 7 элементов",
}, },
{ {
ns: "Test.GteTime", ns: "Test.GteTime",
@ -468,15 +502,23 @@ func TestTranslations(t *testing.T) {
}, },
{ {
ns: "Test.GtString", ns: "Test.GtString",
expected: "GtString должен быть длиннее 3 символы", expected: "GtString должен быть длиннее 3 символов",
},
{
ns: "Test.GtStringSecond",
expected: "GtStringSecond должен быть длиннее 7 символов",
}, },
{ {
ns: "Test.GtNumber", ns: "Test.GtNumber",
expected: "GtNumber должен быть больше 5.56", expected: "GtNumber должен быть больше 5,56",
}, },
{ {
ns: "Test.GtMultiple", ns: "Test.GtMultiple",
expected: "GtMultiple должен содержать более 2 элементы", expected: "GtMultiple должен содержать более 2 элементов",
},
{
ns: "Test.GtMultipleSecond",
expected: "GtMultipleSecond должен содержать более 7 элементов",
}, },
{ {
ns: "Test.GtTime", ns: "Test.GtTime",
@ -484,15 +526,23 @@ func TestTranslations(t *testing.T) {
}, },
{ {
ns: "Test.LteString", ns: "Test.LteString",
expected: "LteString должен содержать максимум 3 символы", expected: "LteString должен содержать максимум 3 символа",
},
{
ns: "Test.LteStringSecond",
expected: "LteStringSecond должен содержать максимум 7 символов",
}, },
{ {
ns: "Test.LteNumber", ns: "Test.LteNumber",
expected: "LteNumber должен быть менее или равен 5.56", expected: "LteNumber должен быть менее или равен 5,56",
}, },
{ {
ns: "Test.LteMultiple", ns: "Test.LteMultiple",
expected: "LteMultiple должен содержать максимум 2 элементы", expected: "LteMultiple должен содержать максимум 2 элемента",
},
{
ns: "Test.LteMultipleSecond",
expected: "LteMultipleSecond должен содержать максимум 7 элементов",
}, },
{ {
ns: "Test.LteTime", ns: "Test.LteTime",
@ -500,15 +550,23 @@ func TestTranslations(t *testing.T) {
}, },
{ {
ns: "Test.LtString", ns: "Test.LtString",
expected: "LtString должен иметь менее 3 символы", expected: "LtString должен иметь менее 3 символов",
},
{
ns: "Test.LtStringSecond",
expected: "LtStringSecond должен иметь менее 7 символов",
}, },
{ {
ns: "Test.LtNumber", ns: "Test.LtNumber",
expected: "LtNumber должен быть менее 5.56", expected: "LtNumber должен быть менее 5,56",
}, },
{ {
ns: "Test.LtMultiple", ns: "Test.LtMultiple",
expected: "LtMultiple должен содержать менее 2 элементы", expected: "LtMultiple должен содержать менее 2 элементов",
},
{
ns: "Test.LtMultipleSecond",
expected: "LtMultipleSecond должен содержать менее 7 элементов",
}, },
{ {
ns: "Test.LtTime", ns: "Test.LtTime",
@ -540,27 +598,47 @@ func TestTranslations(t *testing.T) {
}, },
{ {
ns: "Test.MaxString", ns: "Test.MaxString",
expected: "MaxString должен содержать максимум 3 символы", expected: "MaxString должен содержать максимум 3 символа",
},
{
ns: "Test.MaxStringSecond",
expected: "MaxStringSecond должен содержать максимум 7 символов",
}, },
{ {
ns: "Test.MaxNumber", ns: "Test.MaxNumber",
expected: "MaxNumber должен быть меньше или равно 1,113.00", expected: "MaxNumber должен быть меньше или равно 1 113,00",
}, },
{ {
ns: "Test.MaxMultiple", ns: "Test.MaxMultiple",
expected: "MaxMultiple должен содержать максимум 7 элементы", expected: "MaxMultiple должен содержать максимум 7 элементов",
},
{
ns: "Test.MaxMultipleSecond",
expected: "MaxMultipleSecond должен содержать максимум 2 элемента",
}, },
{ {
ns: "Test.MinString", ns: "Test.MinString",
expected: "MinString должен содержать минимум 1 символ", expected: "MinString должен содержать минимум 1 символ",
}, },
{
ns: "Test.MinStringMultiple",
expected: "MinStringMultiple должен содержать минимум 2 символа",
},
{
ns: "Test.MinStringMultipleSecond",
expected: "MinStringMultipleSecond должен содержать минимум 7 символов",
},
{ {
ns: "Test.MinNumber", ns: "Test.MinNumber",
expected: "MinNumber должен быть больше или равно 1,113.00", expected: "MinNumber должен быть больше или равно 1 113,00",
}, },
{ {
ns: "Test.MinMultiple", ns: "Test.MinMultiple",
expected: "MinMultiple должен содержать минимум 7 элементы", expected: "MinMultiple должен содержать минимум 7 элементов",
},
{
ns: "Test.MinMultipleSecond",
expected: "MinMultipleSecond должен содержать минимум 2 элемента",
}, },
{ {
ns: "Test.LenString", ns: "Test.LenString",
@ -568,11 +646,15 @@ func TestTranslations(t *testing.T) {
}, },
{ {
ns: "Test.LenNumber", ns: "Test.LenNumber",
expected: "LenNumber должен быть равен 1,113.00", expected: "LenNumber должен быть равен 1 113,00",
}, },
{ {
ns: "Test.LenMultiple", ns: "Test.LenMultiple",
expected: "LenMultiple должен содержать 7 элементы", expected: "LenMultiple должен содержать 7 элементов",
},
{
ns: "Test.LenMultipleSecond",
expected: "LenMultipleSecond должен содержать 2 элемента",
}, },
{ {
ns: "Test.RequiredString", ns: "Test.RequiredString",
@ -588,7 +670,11 @@ func TestTranslations(t *testing.T) {
}, },
{ {
ns: "Test.StrPtrMinLen", ns: "Test.StrPtrMinLen",
expected: "StrPtrMinLen должен содержать минимум 10 символы", expected: "StrPtrMinLen должен содержать минимум 10 символов",
},
{
ns: "Test.StrPtrMinLenSecond",
expected: "StrPtrMinLenSecond должен содержать минимум 2 символа",
}, },
{ {
ns: "Test.StrPtrMaxLen", ns: "Test.StrPtrMaxLen",
@ -596,7 +682,11 @@ func TestTranslations(t *testing.T) {
}, },
{ {
ns: "Test.StrPtrLen", ns: "Test.StrPtrLen",
expected: "StrPtrLen должен быть длиной в 2 символы", expected: "StrPtrLen должен быть длиной в 2 символа",
},
{
ns: "Test.StrPtrLenSecond",
expected: "StrPtrLenSecond должен быть длиной в 7 символов",
}, },
{ {
ns: "Test.StrPtrLt", ns: "Test.StrPtrLt",
@ -606,13 +696,29 @@ func TestTranslations(t *testing.T) {
ns: "Test.StrPtrLte", ns: "Test.StrPtrLte",
expected: "StrPtrLte должен содержать максимум 1 символ", expected: "StrPtrLte должен содержать максимум 1 символ",
}, },
{
ns: "Test.StrPtrLteMultiple",
expected: "StrPtrLteMultiple должен содержать максимум 2 символа",
},
{
ns: "Test.StrPtrLteMultipleSecond",
expected: "StrPtrLteMultipleSecond должен содержать максимум 7 символов",
},
{ {
ns: "Test.StrPtrGt", ns: "Test.StrPtrGt",
expected: "StrPtrGt должен быть длиннее 10 символы", expected: "StrPtrGt должен быть длиннее 10 символов",
},
{
ns: "Test.StrPtrGtSecond",
expected: "StrPtrGtSecond должен быть длиннее 2 символов",
}, },
{ {
ns: "Test.StrPtrGte", ns: "Test.StrPtrGte",
expected: "StrPtrGte должен содержать минимум 10 символы", expected: "StrPtrGte должен содержать минимум 10 символов",
},
{
ns: "Test.StrPtrGteSecond",
expected: "StrPtrGteSecond должен содержать минимум 2 символа",
}, },
{ {
ns: "Test.OneOfString", ns: "Test.OneOfString",

@ -89,6 +89,10 @@ type Validate struct {
} }
// New returns a new instance of 'validate' with sane defaults. // New returns a new instance of 'validate' with sane defaults.
// Validate is designed to be thread-safe and used as a singleton instance.
// It caches information about your struct and validations,
// in essence only parsing your validation tags once per struct type.
// Using multiple instances neglects the benefit of caching.
func New() *Validate { func New() *Validate {
tc := new(tagCache) tc := new(tagCache)

@ -71,6 +71,7 @@ type TestString struct {
Gt string `validate:"gt=10"` Gt string `validate:"gt=10"`
Gte string `validate:"gte=10"` Gte string `validate:"gte=10"`
OmitEmpty string `validate:"omitempty,min=1,max=10"` OmitEmpty string `validate:"omitempty,min=1,max=10"`
Boolean string `validate:"boolean"`
Sub *SubTest Sub *SubTest
SubIgnore *SubTest `validate:"-"` SubIgnore *SubTest `validate:"-"`
Anonymous struct { Anonymous struct {
@ -7943,6 +7944,7 @@ func TestStructStringValidation(t *testing.T) {
Lte: "0123456789", Lte: "0123456789",
Gt: "01234567890", Gt: "01234567890",
Gte: "0123456789", Gte: "0123456789",
Boolean: "true",
OmitEmpty: "", OmitEmpty: "",
Sub: &SubTest{ Sub: &SubTest{
Test: "1", Test: "1",
@ -7974,6 +7976,7 @@ func TestStructStringValidation(t *testing.T) {
Gt: "1", Gt: "1",
Gte: "1", Gte: "1",
OmitEmpty: "12345678901", OmitEmpty: "12345678901",
Boolean: "nope",
Sub: &SubTest{ Sub: &SubTest{
Test: "", Test: "",
}, },
@ -7991,7 +7994,7 @@ func TestStructStringValidation(t *testing.T) {
// Assert Top Level // Assert Top Level
NotEqual(t, errs, nil) NotEqual(t, errs, nil)
Equal(t, len(errs.(ValidationErrors)), 13) Equal(t, len(errs.(ValidationErrors)), 14)
// Assert Fields // Assert Fields
AssertError(t, errs, "TestString.Required", "TestString.Required", "Required", "Required", "required") AssertError(t, errs, "TestString.Required", "TestString.Required", "Required", "Required", "required")
@ -8004,6 +8007,7 @@ func TestStructStringValidation(t *testing.T) {
AssertError(t, errs, "TestString.Gt", "TestString.Gt", "Gt", "Gt", "gt") AssertError(t, errs, "TestString.Gt", "TestString.Gt", "Gt", "Gt", "gt")
AssertError(t, errs, "TestString.Gte", "TestString.Gte", "Gte", "Gte", "gte") AssertError(t, errs, "TestString.Gte", "TestString.Gte", "Gte", "Gte", "gte")
AssertError(t, errs, "TestString.OmitEmpty", "TestString.OmitEmpty", "OmitEmpty", "OmitEmpty", "max") AssertError(t, errs, "TestString.OmitEmpty", "TestString.OmitEmpty", "OmitEmpty", "OmitEmpty", "max")
AssertError(t, errs, "TestString.Boolean", "TestString.Boolean", "Boolean", "Boolean", "boolean")
// Nested Struct Field Errs // Nested Struct Field Errs
AssertError(t, errs, "TestString.Anonymous.A", "TestString.Anonymous.A", "A", "A", "required") AssertError(t, errs, "TestString.Anonymous.A", "TestString.Anonymous.A", "A", "A", "required")
@ -11079,6 +11083,62 @@ func TestIsIso3166AlphaNumericValidation(t *testing.T) {
}, "Bad field type string") }, "Bad field type string")
} }
func TestIsIso4217Validation(t *testing.T) {
tests := []struct {
value string `validate:"iso4217"`
expected bool
}{
{"TRY", true},
{"EUR", true},
{"USA", false},
}
validate := New()
for i, test := range tests {
errs := validate.Var(test.value, "iso4217")
if test.expected {
if !IsEqual(errs, nil) {
t.Fatalf("Index: %d iso4217 failed Error: %s", i, errs)
}
} else {
if IsEqual(errs, nil) {
t.Fatalf("Index: %d iso4217 failed Error: %s", i, errs)
}
}
}
}
func TestIsIso4217NumericValidation(t *testing.T) {
tests := []struct {
value int `validate:"iso4217_numeric"`
expected bool
}{
{8, true},
{12, true},
{13, false},
}
validate := New()
for i, test := range tests {
errs := validate.Var(test.value, "iso4217_numeric")
if test.expected {
if !IsEqual(errs, nil) {
t.Fatalf("Index: %d iso4217 failed Error: %s", i, errs)
}
} else {
if IsEqual(errs, nil) {
t.Fatalf("Index: %d iso4217 failed Error: %s", i, errs)
}
}
}
}
func TestTimeZoneValidation(t *testing.T) { func TestTimeZoneValidation(t *testing.T) {
tests := []struct { tests := []struct {
value string `validate:"timezone"` value string `validate:"timezone"`

Loading…
Cancel
Save