Compare commits

...

883 Commits
v4 ... master

Author SHA1 Message Date
Dean Karn f5e5146b31 update version README 2 years ago
Cyro Dubeux 56e2f31322
pt_BR translation improvements (#967) 2 years ago
Joselito Viveiros Nogueira Filho e9f2d9f21a
fix: removed unnecessary cast so we can mock ValidationErrors (#980) (#981) 2 years ago
Eduardo Mello b43d437012
feat: add cve validator (#983) 2 years ago
João Fonseca 58d420de41
add kosovo (#1081) 2 years ago
Aleksander Dejewski c6f8637983
Fixed NotBlank validator to cover all whitespace characters (#997) 2 years ago
Gatis Rīders f6f934c4e9
Added Latvian translations (#1005) 2 years ago
konstantin ae3e728763
Introduce Luhn Checksum Validation (#1009) 2 years ago
Tanryberdi 0665b9518a
Refactor: fix for lint errors (#1011) 2 years ago
jnst 21b88d1a25
Fix the Japanese translations of gte and lte (#1012) 2 years ago
jnst 4f5cf1d499
Update Japanese translations (#1013) 2 years ago
Kmilo Denis González 2f3efda84f
Added a genre enum to the user model and a custom validation (#1014) 2 years ago
brent s 2e43671001
(New validator) Validate non-existing but valid file/directory paths (#1022) 2 years ago
just Alan f560fd4e07
Feat: support mongodb objectID validation (#1023) 2 years ago
Yasoob Haider 29d50ba963
add validation for base64 url without = padding (#1024) 2 years ago
zemzale 1c1f70d35b
feat(unique): Add support for struct memember validation (#1048) 2 years ago
Yann Salaün cc768b176d
fix unique= when struct field is a nil pointer (#1041) 2 years ago
Alberto Forcato 3ee65f8c59
Add cron support (#1045) 2 years ago
Owen Gong 89b91cea99
Added "http_url" tag to validate if the variable is a HTTP(s) URL (#1047) 2 years ago
Vijay Nallagatla f2078f7696
Fix unique validator for map with Pointer value (#1062) 2 years ago
Arthur Jenoudet ef342b6f7c
fix validator excluded_unless (#1064) 2 years ago
Dean Karn f3086daf63 fix README 2 years ago
Vitor Hugo 75ba9f6a84
Update README.md (#1066) 2 years ago
Dean Karn 13ad6f5b30 update deps 2 years ago
Simon Tremblay c242c49c02
Update go.mod/go.sum using go mod tidy (#1071) 2 years ago
Dean Karn f17b3458fa fix README 2 years ago
Dean Karn d1178535f7 change eq and ne ignore case tag names 2 years ago
sgallizia 72a3e75460
added IsEqIgnoreCase and IsNeIgnoreCase (#1076) 2 years ago
Phil Porada c0b3430b1f
Fix spelling error in doc (#1078) 2 years ago
Mohamed Sohail b95730fb11
feat: add eth_addr_checksum validation, update eth_addr (#1080) 2 years ago
Dean Karn 8f07b03682
update deps (#1061) 2 years ago
Roberto Ramírez 7edc63a0be
#updated Added required_id spanish translation (#1026) 2 years ago
Marc Brugger 3201fe42fe
Add FQDN en translation (#1058) 2 years ago
wjl110 5aa5f93593
update gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b to 3.0.0 (#1057) 2 years ago
tomaisthorpe f036dd475d
update golang.org/x/text to resolve CVE-2022-32149 (#1015) 2 years ago
Dean Karn c7e0172e0f
Update README.md 2 years ago
Vaibhav Dighe 1e8c614c2a
Fixed boolean validation to handle bool kind (#988) 2 years ago
Dean Karn 9e2ea40380 update ci action versions 3 years ago
Dean Karn 29bf2a5bd0 bump version 3 years ago
Dean Karn 02c12dd7ef update RegisterStructValidationMapRules docs 3 years ago
Leo Liang d0d0c355aa
Feat: support validate struct without struct tag (#934) 3 years ago
Jason.Zhang d3e4be3e44
Enhanced ValidationCtx method to support nested map in slice #915 (#917) 3 years ago
gosua 99922fccc7
Enhance example in function docu (#858) 3 years ago
Sec Cake 4f55647bd7
Added some hash validation (#875) 3 years ago
mrkongo 39aa2e3a27
add it_IT translation (#694) 3 years ago
Vuong 7fa836dc0a
Add Vietnamese translations (#820) 3 years ago
Ayoob Mohammed 21a103f428
Add Arabic translations (#825) 3 years ago
Eduardo Mello e3f29bf088
Boolean translation (#930) 3 years ago
Renato Alves Torres d37da5e53c
fix: add en translation for required_if (#884) 3 years ago
Ciprian 0a26ee57e4
Updated `endsnotwith` description in Readme (#824) 3 years ago
Lauris BH f09500fca7
Fix support for aliased time.Time types (#890) 3 years ago
Massimo Costa 090afeb8ac
enhancement: add italian translation (#914) 3 years ago
XIE Long af72f63d39
Result is wrong while there are multiple group of OR operators #910 (#911) 3 years ago
Stefan Dillenburg f2d3ff7f98
fix: Remove underscore from RFC-1123 based regex (#912) 3 years ago
hehe.bu aea8782168
fix ja typos (#898) 3 years ago
Sol 24b5175a34
Fix typo (#891) 3 years ago
NgeKaworu bc9f9dd2eb
Update zh.go (#856) 3 years ago
alessmar dd2857a4cb
Credit card validation (#924) 3 years ago
Dean Karn bb30072b48 update ci config 3 years ago
Jacob Hochstetler c0195b2b40
added excluded_if/excluded_unless tags + tests (#847) 3 years ago
Dean Karn 58d5778b18
Update README.md 3 years ago
Johannes 3e49fe4eb8
bump golang.org/x/text to fix CVE-2021-38561 (#881) 3 years ago
Anmar85 dd2de9c1f7
update /x/crypto to resolve CVE-2021-43565 (#904) 3 years ago
Dean Karn 88976f39f6
Update README.md 3 years ago
jtseng-godaddy 06ec79d987
Including regex version validation (#831) 3 years ago
Markus Tenghamn 8fe074c546
Added ulid validation (#826) 3 years ago
Kazuki Onishi ec2071b383
Add DNS RFC 1035 label format validator (#833) 3 years ago
nesty92 c67d01d610
Add support for all hex color notations (#866) (#867) 3 years ago
Markus Tenghamn 19f8e61dba
Fixed country_code validation to properly handle strings (#873) 3 years ago
Dean Karn ce34f361cc
update ut dep (#816) 3 years ago
Metin Oğurlu d4271985b4
Feature/currency codes (#811) 3 years ago
András Czigány 42525d89ab
document thread safety and recommended singleton usage (#809) 3 years ago
Xavier Vello a67baa74f1
feature/boolean (#804) 3 years ago
Dmitriy 14221d02a5
fix: Fixed panic when use ru lang for translation, added and fixed tests (#814) 3 years ago
Dean Karn 6dbf61e046
update deps (#815) 3 years ago
Dean Karn 9a5bce3253
Update README.md 3 years ago
Dean Karn b03f1f453e
update all deps to latest versions (#801) 3 years ago
cokezhang 61a982014e
enhancement: add zh translations for tag alphaunicode,alphanumunicode,containsrune,startswith,endswith (#799) 3 years ago
Oleg Nikachev 44c2696cbd
Minor fixes. (#798) 3 years ago
steveorourke e40bece342
Add support for jwt validation (#783) 3 years ago
Brian Leishman 8cfa1e93b6
Update README.md (#765) 3 years ago
Saed SayedAhmed f1befad848
Addressing security vulnerabilities (#774) 3 years ago
Dean Karn 65bb123677
Update README.md 3 years ago
amir e3e38634b1
Add persian translations (#771) 3 years ago
N/A af8b8d1c88
Add iso-3166-2 (#788) 3 years ago
Levani 8bfa88a462
Update README.md (#786) 3 years ago
Dean Karn 9104fe2461
Update README.md 3 years ago
masafumi-i 90ab42ba67
fix ja translation (#792) 3 years ago
Alonso Villegas b1b32b2064
Fix map diving validation (#793) 3 years ago
Dean Karn 76b917f432
Update README.md 4 years ago
Dean Karn 95ac68b6d7
fix url_encoded regex (#769) 4 years ago
Dean Karn d07eb88fb0
Pr cleanup (#767) 4 years ago
ѵµσɳɠ a53d64fc35
Postcode validator for value and field (#759) 4 years ago
Oleksii Kulikov c2066206fe
Add BIC ISO format validator (#758) 4 years ago
zytell3301 b95d43b789
Add ability to validate map data (#752) 4 years ago
Zane DeGraffenried 31dd62f1c9
Fix boolean support for required_if, required_unless and eqfield (#754) 4 years ago
Dean Karn b926bf0df9
Update README.md 4 years ago
Josh Slate add373fff7
feat: add bcp 47 language tag validator (#730) 4 years ago
Dean Karn 68248183b4
Update README.md 4 years ago
Deri Herdianto 526b0968b3
Update errors.go (#671) 4 years ago
Sergei Isaev 2b75c46052
version removed from installation and import (#710) 4 years ago
frederikhors 3c8db83c19
New official Documentation URL (#706) 4 years ago
Peperoncino 5b8f3b8a0b
corresponds to boolean value of nefield (#712) 4 years ago
Torwang 882ec0def4
fix StructLevel Parent() (#716) 4 years ago
Qalifah 0e674563ff
error in spelling (#732) 4 years ago
Michał Treter ec1baac93d
Fix accessing fields in composed structs (#733) 4 years ago
João Francisco 514c9dbd77
Fix excludedWithoutAll comment (#673) 4 years ago
Jake-Convictional 9c415c4565
Add support for excluded_with on pointer fields (#746) 4 years ago
Dean Karn f6584a41c8
split listing into separate job (#680) 4 years ago
Dean Karn 3bb4866602
Github Actions Changeover (#679) 4 years ago
Dean Karn 456221b630
Fix time.Duration parsing for int param (#678) 4 years ago
Flávio CF Oliveira d6b17fd90b
Added Translation for pt (#613) 4 years ago
krhubert f32fea830e
Add country code validation (#615) 4 years ago
Brandon Lee 704a814277
accept 0x(0X) start in 'hexadecimal' tag (#620) 4 years ago
Elias Rodrigues 4407f4dea0
Add checksum validation for Ethereum address (#630) 4 years ago
Dean Karn 8941cbd00e
Merge pull request #635 from taybart/master 4 years ago
Dean Karn 8154ee6ca8
Merge branch 'master' into master 4 years ago
Dean Karn f0805c61ba
Merge pull request #641 from math-nao/master 4 years ago
Dean Karn 76981ccf75
Merge pull request #642 from elias19r/issue-584-add-support-for-time-duration-type 4 years ago
Dean Karn 57b4fab34b
Merge pull request #644 from longit644/bugfix/make-unique-tag-work-with-pointer-fields 4 years ago
Dean Karn d9e95d55e9
Update errors.go 4 years ago
Dean Karn 2a5412a1bc
Merge pull request #657 from nigelis/bugfix/omitempty-not-first 4 years ago
Dean Karn 839d050f74
Merge pull request #658 from hzwwen/master 4 years ago
Dean Karn e6eee3ea88
Merge branch 'master' into master 4 years ago
Dean Karn b1ccceeb11
Merge pull request #664 from erma07/master 4 years ago
Dean Karn 4cd2e40256
Merge pull request #666 from xy-planning-network/patch 4 years ago
Dean Karn ace513eddd
Update .travis.yml 4 years ago
Dean Karn 0d657b4731
Update .travis.yml 4 years ago
Dean Karn 0e7e593daa
Merge pull request #667 from arkark/fix/endswith-readme 4 years ago
Takeshi Kaneko f2ce6a4f92 Fix a category of endswith in README 4 years ago
David Ketch 1bf11c9299 Includes Error in FieldError's interface 4 years ago
root ca0533bb97 Closes #660 readme updates 4 years ago
root 490e253792 Closes #660 added excluded with and without tests 4 years ago
root 742006d126 Closes #660 added excluded with and without 4 years ago
hzw 44a150f359 add required_if and required_unless 4 years ago
nigelis 6f81b7d8d0 Validate tag omitempty, only base on field value 4 years ago
math-nao 7dbe685a02 Update timeZone tag name to timezone 4 years ago
Long Bui 67c4fdf0de Make unique tag work with pointer fields. 4 years ago
Elias Rodrigues 1cbd3081e4 Add function asIntFromType 4 years ago
Elias Rodrigues 33ffa4a31f Move var declarations to the top in test functions 4 years ago
Elias Rodrigues 55e0f418d6 Minor edits 4 years ago
Elias Rodrigues 04749bc4d4 Fix golangci-lint issues 4 years ago
Elias Rodrigues fc1b28803a Update docs for baked-in time.Duration supported tags 4 years ago
Elias Rodrigues f525f0b64f Add tests for baked-in time.Duration supported tags 4 years ago
Elias Rodrigues 48684f91aa Add baked-in support for time.Duration 4 years ago
Elias Rodrigues 0c71d5cc08 Add var timeDurationType 4 years ago
Elias Rodrigues 94470e68f3 Add function asIntFromTimeDuration() 4 years ago
Elias Rodrigues 1c4e56307b Add bin to .gitignore 4 years ago
math-nao 44f3347f13 Add support for time zone validation 4 years ago
Taylor 07a4b7aa38 Add wiki link for E.164 4 years ago
Taylor 0bfda52ce1 Add e164 to doc.go 4 years ago
Dean Karn ea924ce89a
Update README.md 5 years ago
Dean Karn 059510c3bf
Merge pull request #612 from Giulianos/bugfix/fqdn 5 years ago
Dean Karn 50166a5a06
Merge branch 'master' into bugfix/fqdn 5 years ago
Dean Karn ab4e67f050
Merge pull request #609 from fourcels/master 5 years ago
Dean Karn ae8ecbca8a
Merge branch 'master' into master 5 years ago
Dean Karn 0ab8e0351d
Merge pull request #607 from johnbailon/number_documentation 5 years ago
Dean Karn 7e978ff872
Merge pull request #600 from amiraliucsc/fix/RFC952-host 5 years ago
Dean Karn 957a452839
Merge pull request #598 from cncal/enhance_zh_translation 5 years ago
Dean Karn 257f202dd1
Merge pull request #588 from erikaleigh/fix-grammatical-errors 5 years ago
Dean Karn dbfcad250f
Merge pull request #583 from metalinspired/master 5 years ago
Dean Karn 07f2314af2
Merge pull request #582 from alfonsoprado/feature/spanish-translation-v10 5 years ago
Dean Karn a5e9e63a9a
Merge pull request #579 from psampaz/readme_updates 5 years ago
Dean Karn 8203121676
Merge pull request #578 from psampaz/validations_list 5 years ago
Dean Karn 175275dfea
Merge pull request #577 from psampaz/travis_1_13_7 5 years ago
Giuliano Scaglioni b610155475 format code 5 years ago
Giuliano Scaglioni 7d6236a898 add updated regex for fqdn 5 years ago
Giuliano Scaglioni ee37674003 add breaking test 5 years ago
Kiyan Gauss b15bf1dead Add zh,zh_tw datetime translation 5 years ago
John Bailon 198646cbd1 Add number validator in documentation 5 years ago
John Bailon 7807a1f36f Add number validator in documentation 5 years ago
amiraliucsc c7dc8812a2 Add more tests 5 years ago
amiraliucsc 1611f1e72c Add test regarding multiple dots in hostname 5 years ago
amiraliucsc 18fba4ba8a Fix the regex for RFC952 hostname validator 5 years ago
cncal 85098861d3 enhancement: add zh translations for tag json, lowercase, uppercase, datetime 5 years ago
erikaleigh 3909783b73 Fix grammatical errors in errors.go 5 years ago
Milan Divkovic f3b347cc29 Add validators that check if string does not start/end with supplied parameter 5 years ago
alfonsoprado a98911a366 fix spanish translations 5 years ago
alfonsoprado c1b73a784d Add spanish translations 5 years ago
Pantelis Sampaziotis afacb47f2b Updated version and go doc link 5 years ago
Pantelis Sampaziotis 9f175c7ece Add list of validation in README 5 years ago
Pantelis Sampaziotis 8a19420dcf Run tests on latest stable version 1.13.7 5 years ago
Dean Karn c68441b7f4
Merge pull request #575 from psampaz/datetime 5 years ago
Pantelis Sampaziotis 912fcd16a8 resovle conflict 5 years ago
Pantelis Sampaziotis 14f963703b Add datetime validation 5 years ago
Dean Karn b7430f8e39
Merge pull request #571 from psampaz/json 5 years ago
Dean Karn 0c80f876cd Merge branch 'master' into json 5 years ago
Dean Karn 68e8e137fa Merge pull request #563 from terala/master 5 years ago
Dean Karn 1f676c755a
Merge branch 'master' into master 5 years ago
Dean Karn fa149de298 Merge pull request #569 from Rustery/feature/russian-translation 5 years ago
Dean Karn fdd54d3fc2 Merge pull request #572 from psampaz/lowercase 5 years ago
Dean Karn b541462b5a Merge pull request #574 from shenyiling/master 5 years ago
Pantelis Sampaziotis 2109f86248 Update documenation 5 years ago
Pantelis Sampaziotis 9e58bcdee1 Empty strings are not lowercase or uppercase 5 years ago
shenyiling 6d2c659585 fix: typo 5 years ago
Pantelis Sampaziotis 5b51bff4e6 Add isLowercase and isUppercase valitation 5 years ago
Pantelis Sampaziotis 581d2698d5 Added isJSON validation 5 years ago
Rustam eb11afd9a8 Added russian translation 5 years ago
Ravi Terala a1ac82a865 Add documentation 5 years ago
Ravi Terala 893747e5ee Add hostname_port validator feature 5 years ago
Dean Karn fb6c45823a
Update README.md 5 years ago
Dean Karn 5b97da4cbf
Merge pull request #560 from go-playground/cherry-pick-v9 5 years ago
Dean Karn c2546fb355 Add test + docs for FieldLevel.GetTag 5 years ago
richi f8a081fd83 Added the function GetTag. 5 years ago
Shi Han NG e73ec5f5ab Update doc for unique=field 5 years ago
Shi Han NG 8f604265e0 Implement unique=FieldName 5 years ago
Jean-Philippe Moal 1effcb06a7 Clarify and complete tag names example 5 years ago
Jean-Philippe Moal 703c0b681a Rework the non standard validators documentation 5 years ago
Taylor e7c70798c9 Add e.164 support 5 years ago
Dean Karn a6a294bfeb
Merge pull request #541 from JonathanWThom/jt/space-separated-oneof 5 years ago
Dean Karn c067a8f197
Merge pull request #539 from sclaire-1/master 5 years ago
Dean Karn 1d93fb999e
Merge pull request #547 from atomicleads/master 5 years ago
Dean Karn 5356060ec3
Merge pull request #548 from JonathanWThom/jt/datauri 5 years ago
Dean Karn 361bf41fb9
Merge pull request #550 from Streppel/patch-1 5 years ago
Dean Karn ae15ced5e1
Merge pull request #558 from whatvn/master 5 years ago
Nguyễn Văn Hưng da6897303a error is always nil 5 years ago
Streppel 0849b1840e
removing unecessary type conversion 5 years ago
Jonathan Thom bb5fd36827
Improves accuracy of datauri regex 5 years ago
Jonathan Thom 685d3e21f3
Makes regex constant & moves single quote replace logic to parseOneOfParam2 5 years ago
Dmitry M. Gavrovsky d149847e8a test case for “eq” comparing boolean values #547 5 years ago
Dmitry M. Gavrovsky dfc652373a Added boolean type support for “eq” validator 5 years ago
Dean Karn 691a5f5f25
Update README.md 5 years ago
Dean Karn bec732e9de
Merge pull request #543 from go-playground/fix-required-without 5 years ago
Dean Karn a346f2eea4 Merge branch 'master' into fix-required-without 5 years ago
Dean Karn b11fb5f16e fix typo 5 years ago
Dean Karn c0f05c7b3d fix required_* 5 years ago
Dean Karn fe89c745f6
Merge pull request #542 from kaelanfouwels/master 5 years ago
Kaelan Thijs Fouwels 8678802a39
Correction of documentation URL 5 years ago
Jonathan Thom 432c17028a
Adds ability to validate oneof for space separated strings 5 years ago
sclaire-1 4be5d19c39
Edit CONTRIBUTING.md 5 years ago
Dean Karn dbbe6958b3 update doc v9 url to v10 5 years ago
Dean Karn 7e57ca0cf5 convert to go modules 5 years ago
Dean Karn cd1bd58169
Update README.md 5 years ago
Dean Karn 883a9e06c8
Merge pull request #523 from go-playground/fixes 5 years ago
Dean Karn 9593a0f77e add test for new nil validation 5 years ago
Dean Karn 06f92248de linting cleanup 5 years ago
Dean Karn 6484d9f2fb fix required_with_* 5 years ago
Dean Karn cc25246f01 fix required_without_* 5 years ago
Dean Karn 51fcc303b3
Merge pull request #507 from UgurAsaner/v9 5 years ago
Dean Karn 205b733988
Merge pull request #522 from teejays/v9 5 years ago
Talha Ansari 4e2a13b9bf
Updated tests to reflect the import change 5 years ago
Talha Ansari 2367d307c5
Fix the import path for non-standard validators 5 years ago
baran.asaner 80a8449877 Add Turkish translations 5 years ago
Dean Karn 556b9da3c0
Update README.md 5 years ago
Dean Karn ab2452c1ce
Merge pull request #489 from tobiassjosten/patch-1 5 years ago
Dean Karn d6546ee64a
Merge pull request #484 from leafduo/v9 5 years ago
Tobias Sjösten 9f6c1cdebf
Fixed typo 5 years ago
Zuyang Kou 54db112759 Make `required_without` work with pointer 6 years ago
Dean Karn 884d31b8ca
Update README.md 6 years ago
Dean Karn 56b7caa399
Merge pull request #469 from mashmooli/v9 6 years ago
Dean Karn 727e327e57
Merge pull request #471 from Zeroen/fix-hostname-regexp 6 years ago
criherna 38f91ec1a1 Merge branch 'master' into fix-hostname-regexp 6 years ago
criherna 9dedb06449 fix hostname regex 6 years ago
A Mashmooli 8c221696bb simplify required check field kind 6 years ago
A Mashmooli d89801fc29 fix required_* test 6 years ago
A Mashmooli de92ea70b4 fix required_* test 6 years ago
A Mashmooli 22eebe9ac5 add required_without_all to doc 6 years ago
A Mashmooli a9e1a9226c add required_without to doc 6 years ago
A Mashmooli 678f8d753f add required_with_all to doc 6 years ago
A Mashmooli 5a98da4e8c add required_with to doc 6 years ago
Dean Karn e25e66164b
Merge pull request #460 from masseelch/patch-1 6 years ago
A Mashmooli 3ec10f9949 add required_without_all validator 6 years ago
A Mashmooli 03bfd38cc1 add required_without validator 6 years ago
A Mashmooli ebfddc5784 add required_with_all validator 6 years ago
A Mashmooli 1e6bddb6b3 fix comment 6 years ago
A Mashmooli adbd5e9b33 add required_with validator 6 years ago
Dean Karn 46b4b1e301
Update README.md 6 years ago
Dean Karn c0a5f73741
Merge pull request #463 from benpaxton-hf/fix-email-regex 6 years ago
Dean Karn 9cbbfdd691
Merge pull request #461 from alexbilbie/patch-1 6 years ago
Dean Karn 9980009549
Merge pull request #459 from thcipriani/v9 6 years ago
Dean Karn 5ed5b2eeeb
Merge pull request #451 from rucas/v9 6 years ago
Dean Karn ce0e3d1c6d
Merge pull request #421 from andreiavrammsd/notblank 6 years ago
Ben Paxton 9099388d96 Fix email regex 6 years ago
Alex Bilbie ab7e4092fb
Grammar fix 6 years ago
Alex Bilbie a918b74270
Updated doc.go with uuid_rfc4122 examples 6 years ago
Jannik C 8a9497f4bd
Update main.go 6 years ago
Tyler Cipriani 3945da16ee Add `startswith` and `endswith` validators 6 years ago
rucas dbd65cccbc better SSN regex 6 years ago
Andrei Avram f2ac4efd57 Update non standard validation docs. 6 years ago
Dean Karn b199fa0642
Update README.md 6 years ago
Dean Karn 1b32ac03ca
Merge pull request #450 from agalal/add-dir-validator 6 years ago
Dean Karn e10c2c9ddb
Merge pull request #440 from RaMin0/feature/numeric_geo_coords 6 years ago
Dean Karn 6cdb5bb480
Merge pull request #446 from Esslamb/v9 6 years ago
Dean Karn cf7eb8fabc
Merge pull request #443 from kszafran/patch-1 6 years ago
Andrei Avram 1d286c8332 Define NotBlank as non standard validator. 6 years ago
Andrei Avram faaace938d Add documentation. 6 years ago
Andrei Avram 6b29637aaa Add NotBlank validation function. 6 years ago
Abdallah Galal 94ba218708 Add validation for directories 6 years ago
Esslam 891b7807f8 Fixed Typos 6 years ago
Krzysztof Szafrański fdbd8ba577
Fix typos 6 years ago
Ramy Aboul Naga d1d2da5f73 Fix typo in isLongitude test 6 years ago
Ramy Aboul Naga cbd5cf6393 Use type switch in favor of fmt.Sprint 6 years ago
Dean Karn 774d09c386
Update README.md 6 years ago
Rohan Sathe 76020d061e Fixes #26 (#437) 6 years ago
Ramy Aboul Naga 52ea448998 Allow latitude/longitude validation for numeric values 6 years ago
Dean Karn cdd5c28d21
Update README.md 6 years ago
franklin 91d81934ab Add baked in validators for containsfield and excludesfield (#424) 6 years ago
Takeshi Akima 9af2aa2cc3 Fixes Japanese translation (#433) 6 years ago
Dean Karn 0277b12d53
Update README.md 6 years ago
Dean Karn bc745fba53
Merge pull request #430 from akm/japanese_translation 6 years ago
Dean Karn 35d48effb5
Merge pull request #419 from holyspectral/unique_translation 6 years ago
Dean Karn df119a3494
Merge pull request #427 from AGPDev/v9 6 years ago
Dean Karn c7005d73ef
Merge pull request #429 from leodido/feat/is-urn 6 years ago
akm 578166faf7 Implement translation of ne-items 6 years ago
akm 37128de86f Add japanese translation 6 years ago
Leonardo Di Donato 2bb313f957
Docs: Update URN RFC2141 documentation 6 years ago
Leonardo Di Donato 0482874b86
Update: Rename urn tag into urn_rfc2141 6 years ago
Leonardo Di Donato c5423e4116
New: URN 6 years ago
Anderson Guilherme Porto 20357ae332 fix import avoid wrong type when apply custom translates. 6 years ago
Dean Karn 6079fcc186
Merge pull request #423 from mitsuyoshi4/v9 6 years ago
満行芳樹 aaf2c06dbe fixed typo 6 years ago
Sam Wang df107f0184 Add English translation for "unique" validation. 6 years ago
Dean Karn 1fa3c8d633 fix indonesian translation test 6 years ago
Dean Karn 9c187c39d8
Merge pull request #414 from sulthonzh/v9 6 years ago
Dean Karn 1730262625
Merge pull request #413 from suekto-andreas/v9 6 years ago
andreas 8ed00e2e12 Change behavior instead of error, we Indirect it to get the non-pointer value 6 years ago
andreas 9eeca29136 detail error message on RegisterStructValidationCtx finding pointer arg 6 years ago
Sulthon Zainul Habib 38f9a73e57 Add Indonesian translations 6 years ago
andreas 5b14fca011 Returns error when passing pointer to RegisterStructValidation 6 years ago
Dean Karn 3be3142400
Merge pull request #408 from kanozec/v9 6 years ago
Dean Karn 9f802bbd9b
Merge pull request #406 from frou/doc-registertagnamefunc 6 years ago
kanozec 532cde1085 Add Chinese(zh-tw) translations 6 years ago
Duncan Holm 29b73202fe Document RegisterTagNameFunc more 6 years ago
Dean Karn f8af4b15db
Merge pull request #404 from 44px/patch-1 6 years ago
Alexander Shepelin 868936b862
Fix FieldError doc 6 years ago
Dean Karn 16a72ff827
Merge pull request #388 from sakura1116vg/fix-doc 6 years ago
sakura1116vg 9c31c8d387 fix doc 6 years ago
Dean Karn e69e9a28bb
Update README.md 6 years ago
Dean Karn 4c0b0c3d27
Merge pull request #387 from wesselvanderlinden/v9 6 years ago
wessel.linden@gmail.com 1ae2003487 Add dutch translations 6 years ago
Dean Karn ab2a8a9908
Update README.md 6 years ago
Dean Karn e4e19c02df
Merge pull request #381 from foolin/v9 6 years ago
foolin a2ec0a8018 fix package name 6 years ago
Dean Karn e055f4eb7f
Update README.md 6 years ago
Dean Karn 29f025ab2f
Merge pull request #380 from qdentity/struct-filtered-ctx-fix 6 years ago
Damir Vandic bdae516532
Fix unused ctx in StructFilteredCtx 6 years ago
Dean Karn d942191d51
Update README.md 6 years ago
Dean Karn 5d3224279f
Merge pull request #379 from foolin/v9 6 years ago
foolin 11caf00975 Merge branch 'v9' of https://github.com/go-playground/validator into v9 6 years ago
Foolin d1a82a6cdc add chinese translations 6 years ago
Foolin 801b2c40bc update 6 years ago
Foolin 83b055d6df add chinese lang 6 years ago
Dean Karn ce9336f6e2
Update README.md 6 years ago
Dean Karn c52a27f737
Merge pull request #377 from heatwole/add-html-url-encoding 6 years ago
heatwole 0a9b75fbfd Adding html and url encoding and updating docs 6 years ago
Dean Karn 9d03e2526a
Merge pull request #376 from noibar/add_file_validation 6 years ago
Noi Bar ea9cb424fd
doc: add file validation documentation 6 years ago
Dean Karn fb72538343
Update README.md 6 years ago
Dean Karn 71510749b8
Merge pull request #375 from noibar/add_file_validation 6 years ago
Noi Bar f2fdb60d7d Add file path validation 7 years ago
Dean Karn f28cb45dc0
Update README.md 7 years ago
Dean Karn 3e51773f21
Merge pull request #363 from tengis617/fix-comment-typo 7 years ago
Tengis B 8d3aa5bde2 ✏️ fixed typo in comment 7 years ago
Dean Karn ffe836d736 Expanded numeric & number validations 7 years ago
Dean Karn 801c8790f3
Update README.md 7 years ago
Dean Karn 9848c01055
Merge pull request #362 from jadhub/domainnamefix 7 years ago
Joachim Adomeit 379fb67047 Fix for Email - Hostname is not validated correctly #359 7 years ago
Dean Karn ee0bbdea51 increment version 7 years ago
Dean Karn 54da7fa48f fix linting and spelling errors 7 years ago
Dean Karn b297167b88
Merge pull request #361 from jservice-rvbd/unique-for-maps 7 years ago
Dean Karn f459c64611
Merge pull request #358 from Ashtonian/patch-1 7 years ago
James Service d978a4b421 Undo whitespace changes from gofmt. 7 years ago
James Service fc5fbce706 Add new unique functionality to docstring. 7 years ago
James Service 8ae3903dd3 Extend the unique tag to also cover map values. 7 years ago
Ashton Kinslow 9f62099643
add missing Engine() to default validator 7 years ago
Dean Karn 14984d9132 Merge branch 'QuestofIranon-patch-1' into v9 7 years ago
Dean Karn b5512bc1ff Merge branch 'patch-1' of https://github.com/QuestofIranon/validator into QuestofIranon-patch-1 7 years ago
josh 073682ea75 added in more test cases and removed some redundant validation steps 7 years ago
josh ce6284a6fc confirm only all upper or all lower case address are valid 7 years ago
josh 6deddf27eb proper bech32 address validation 7 years ago
josh 3df85bdcfc p2sh validation and more tests 7 years ago
josh 60417282a4 verifies p2pkh addresses 7 years ago
josh 36d83b0b83 Added in validation function, tests, and docs 7 years ago
Dean Karn ff1ee42e83
Update README.md 7 years ago
Dean Karn d3984c2e0b
Update main.go 7 years ago
Dean Karn 2a8a333913
Update doc.go 7 years ago
Dean Karn 4894e4ca6c
Merge pull request #351 from kgeorgiou/v9 7 years ago
josh ba5836f763 add bitcoin and ethereum address regexes 7 years ago
Kyriakos Georgiou 030800a855 Add validation for base64 URL safe values 7 years ago
Dean Karn 8ce234ff02
Update README.md 7 years ago
Dean Karn b226c5e0d7
Merge pull request #350 from afranioce/v9 7 years ago
Afranio Martins 5186bfe8b5 add brazilian portuguese translations 7 years ago
Dean Karn 1b8c8e19cd
Merge pull request #348 from fdelbos/french-translation 7 years ago
Frederic Delbos 4dbd40f597 add french translations 7 years ago
Dean Karn 150fe5b6a4
Update README.md 7 years ago
Dean Karn 34ccc97914
Merge pull request #343 from ansel1/oneof 7 years ago
Russ Egan 2e9adc3329 swapped mutex for rwmutex 7 years ago
Russ Egan 15217303f9 Add oneof validation 7 years ago
Dean Karn 535f85221e
Update README.md 7 years ago
Dean Karn 5e036656b8 Add hostname_rfc1123 validation 7 years ago
Dean Karn 3620d3c069 update docs for FieldWithValue=>VarWithValue 7 years ago
Dean Karn 36cd0d5b69
Merge pull request #340 from glb/v9 7 years ago
Geoff Baskwill 866bd2a946 Support translating field errors when field is of kind reflect.Ptr 7 years ago
Dean Karn 48a433ba4b
Merge pull request #336 from go-playground/correct-var-lock 7 years ago
Dean Karn e00f5e092a split out to function, defer is needed to handle panics 7 years ago
Dean Karn b962f3d7d5 Correct Var tagCache locking 7 years ago
Dean Karn 230db62e07
update docs to clarify or vs tag separators (#334) 7 years ago
Dean Karn b1f51f36f1
Correct consequtive or logic (#330) 7 years ago
Dean Karn 61caf9d303
add map key validation support (#324) 7 years ago
Dean Karn 1304298bf1 Update README.md 7 years ago
Dean Karn 11e5ebe8a1 Merge pull request #317 from go-playground/add-unique 7 years ago
Dean Karn 34b84953ff change related software 7 years ago
Dean Karn 11a1fab51d Add unique validation 7 years ago
Dean Karn 946d444376 Add custom validation example 7 years ago
Dean Karn a021b2ec9a Merge pull request #307 from go-playground/fix_fqdn 7 years ago
Dean Karn f16354ec03 Add isdefault + fix fqdn 7 years ago
Dean Karn e3037695c7 Merge pull request #304 from aaronlehmann/doc-fixes 7 years ago
Aaron Lehmann 770163b1e1 Documentation fixes 7 years ago
Dean Karn 0d09605a05 100% test coverage 7 years ago
Dean Karn 0b5dc7605b Add isdefault validation 7 years ago
Dean Karn 893aecca31 Merge pull request #302 from pigi72333/v9 7 years ago
pigi72333 17c6ef0e87 Fix doc typo 7 years ago
Dean Karn 65480b6f6c Merge pull request #301 from lucasmundim/v9 7 years ago
Lucas Mundim 8e400db116 Fix doc typo 7 years ago
Dean Karn 5c4193d98e Update README.md 7 years ago
Dean Karn d529ee1b0f Merge pull request #298 from senuphtyz/v9 7 years ago
Bruno Lorenz dbd50b343f Code hygiene 7 years ago
Bruno Lorenz 1669b6e0ee Fixed "Assignment Branch Condition too high" 7 years ago
Bruno Lorenz 08796346a0 Append new validations 7 years ago
Dean Karn 44d9acf0a8 Update README.md 7 years ago
Dean Karn 0f6f568263 Add contextual validation support via context.Context (#296) 7 years ago
Dean Karn fb68f39656 Add Access to Field Name from FieldLevel (#284) 8 years ago
Dean Karn 27158c7a84 Update README.md 8 years ago
Dean Karn 6d8c18553e Merge pull request #278 from flebel/fix_typo 8 years ago
Dean Karn 755afb9dde Update README.md 8 years ago
Francois Lebel 7a2859f38d Fix typo 8 years ago
Dean Karn 4bd1935852 Updated README 8 years ago
Dean Karn b250b44763 Update test & benchmarks 8 years ago
Dean Karn 691ea55063 Update README.md 8 years ago
Dean Karn 0cc1e78abb Merge pull request #271 from ellisonleao/patch-1 8 years ago
Ellison Leão 7cd869b083 fix small doc typo 8 years ago
Dean Karn fb258d3590 Merge pull request #267 from osamingo/osamingo-patch-1 8 years ago
Osamu TONOMORI cf230a98d7 Fix usage of printable ascii 8 years ago
Dean Karn 077c3830f3 Correct Namespace when array or map of structs 8 years ago
Dean Karn 49fccadad1 correct structonly functionality 8 years ago
Dean Karn 941ce2cabc Merge pull request #262 from go-playground/unicode-alphas 8 years ago
Dean Karn 4d76b0dd81 Add alphaunicode & aplhanumericunicode 8 years ago
Dean Karn 597f93b316 Merge branch 'correct-error-order' into v9 8 years ago
Dean Karn 4e43fa1562 change field cache to array 8 years ago
Dean Karn 493dfb6209 correct required tag functionality for pointers, now works like old `exists` tag. 8 years ago
Dean Karn 506cc5da56 Add Filter logic 8 years ago
Dean Karn 0c0ae405d3 Update README.md 8 years ago
Dean Karn 335c8e2fac Merge pull request #256 from jawher/fix-goimports-diff 8 years ago
Jawher Moussa 73e8e76de2 Fix universal translator imports so that goimports doesn't get remove them 8 years ago
Dean Karn 23e84d2f88 Update README.md 8 years ago
Dean Karn 678f8cf9a3 Merge branch 'field-level-validation2' into v9 8 years ago
Dean Karn cddc415625 perf enhancements + corrected issue with or's 8 years ago
Dean Karn 42a0d6df3b some minor perf with recursion 8 years ago
Dean Karn 7c2b5d8471 Update README.md 8 years ago
Dean Karn 4b3eedc379 Merge branch 'i18n-custom-errors' into v9 8 years ago
Dean Karn 110c8638eb add good documentation 8 years ago
Dean Karn 0e70fdfc72 add translation example + documentation 8 years ago
Dean Karn a7ca4a1d32 add default translations for "en" 8 years ago
Dean Karn 532878b008 initial translation/custom error code 8 years ago
Dean Karn 6f98212623 Update CONTRIBUTING.md 8 years ago
Dean Karn 0af0043f29 update CI badge to v9 8 years ago
Dean Karn a7cc53a707 documentation, examples and template updates. 8 years ago
Dean Karn 9ba3297c49 Update benchmarks run against Go 1.7 8 years ago
Dean Karn 1cbfa0bbff RC1 Release 8 years ago
joeybloggs b0883e6ed8 RC1 Release 8 years ago
Dean Karn 852e5ff9f9 Merge pull request #252 from go-playground/v8 8 years ago
joeybloggs 2de56ed26a add parallel versions of all benchmarks 8 years ago
joeybloggs 3e196d49c6 saving some bytes uint8 vs int 8 years ago
joeybloggs b2c8f66e7b why pass the Field names, they already belong to the namespaces... 8 years ago
joeybloggs ea09db9292 aha! there's the extra allocation(s) Ive been chasing down! 8 years ago
joeybloggs 1714ba2b67 convert switch to if 8 years ago
joeybloggs 6765805f88 continuing perf optimizations 8 years ago
joeybloggs 27b607d6ad avoid a couple of dive allocations 8 years ago
joeybloggs 01925e342a regain 100% test coverage 8 years ago
joeybloggs ecad6333b1 increase dive tag performance. 8 years ago
joeybloggs dcdba454d7 some variable cleanup 8 years ago
joeybloggs d9bfef9fe0 speed up structPartial and structExcept string parsing 8 years ago
joeybloggs 8d0fd80a80 removed creation of a couple stack variables and creation of errors 8 years ago
joeybloggs a8f7aaba72 remove TODO: tried it, only helped with 1 allocation, not worth the overhead and potential contention 8 years ago
joeybloggs f581a2d517 reuse field 8 years ago
joeybloggs 98dee40973 perf updates all around! 8 years ago
joeybloggs 560bff6526 testing 8 years ago
joeybloggs 8c60a612c5 code coverage back to 100% + some code cleanup 8 years ago
joeybloggs 2fe87f7a8d better error message. 8 years ago
joeybloggs 5fedd8c08a buffer errTag + errs array. 8 years ago
joeybloggs 5d28ac67f7 remove validatable logic as it does't really work, both with clarity and pointer vs non-pointer receivers 8 years ago
joeybloggs 1ff58be284 finish conversion of test + some fixes. 8 years ago
joeybloggs 3bf69e2bbd converting tests 8 years ago
joeybloggs 7e731afde9 field name updates 8 years ago
joeybloggs e0e1af6a61 working instance 8 years ago
Dean Karn 598aac293f Update README.md 8 years ago
joeybloggs 5f57d2222a increment version in README 8 years ago
joeybloggs 77f59a0ea0 corrected some spelling mistakes in documentation 8 years ago
joeybloggs 1d3a3d281b Merge branch 'minor-perf-1' into v8 8 years ago
joeybloggs 89d5a94084 final touches + README updates 8 years ago
joeybloggs 80301d1184 fix go report card badge. 8 years ago
joeybloggs 49d9b2c35e Merge branch 'minor-perf-merge' into minor-perf-1 8 years ago
joeybloggs 99a0f5e141 Merge branch 'merge' into minor-perf-merge 8 years ago
joeybloggs 7a080ada5b Fix issue with omitempty combined with nullable types in combination with a default static value set as the value 8 years ago
Dean Karn 393130c3f4 Merge pull request #248 from go-playground/v8 8 years ago
joeybloggs 3ef55a89aa fix some needed Type() calls. 8 years ago
joeybloggs 43f7b7d61a save some bytes 8 years ago
joeybloggs 05d6aece82 remove a few TODO's attempted but perf didn't increase. 8 years ago
joeybloggs 4ce4d1cd71 gain another 5% on average by changing tag type from bool's to enum 8 years ago
joeybloggs 330b12dacd Phase 1 optimization complete, Phase 2 ( Warm liquid goo phase ) commencing 8 years ago
joeybloggs 210684a828 code cleanup + add missing tag cache with FieldWith func 8 years ago
joeybloggs c0a414dc9e initial un-refined new caching system 8 years ago
joeybloggs 5c8ad6a1a9 only check struct validity once 8 years ago
joeybloggs cdfcf16a86 fix some minor listing. 8 years ago
Dean Karn 25f1823069 Merge pull request #243 from kenkouot/patch-1 9 years ago
Kenneth Kouot 719d0b12ee Fix another typo: eq to ne 9 years ago
Kenneth Kouot 3499e730cb Fix typo: ne is validation key for not equal 9 years ago
joeybloggs 014792cf3e Update README version 9 years ago
joeybloggs e7749ea250 Update validations for "url" and "uri" because of Go 1.6 changes 9 years ago
joeybloggs 93bb347253 Update validations for "url" and "uri" because of Go 1.6 changes 9 years ago
Dean Karn 1214d3629c Update README.md 9 years ago
Dean Karn bd356b6899 Merge pull request #235 from moogle19/master 9 years ago
Kevin Seidel 851787be1b Add unicode email tests 9 years ago
joeybloggs f38559b489 Update checking unexpected fields for Go 1.6 https://tip.golang.org/doc/go1.6#reflect 9 years ago
Dean Karn 4c79e69823 Merge pull request #234 from go-playground/krhubert 9 years ago
joeybloggs bf5ac690d6 Add a couple more test cases 9 years ago
joeybloggs 6851add4e4 Update to avoid double resolves 9 years ago
joeybloggs 4cb9152af0 correct IsUPDAddrResolvable functions 9 years ago
joeybloggs faf40fd62f Correct validation for TCPAddrResolvable 9 years ago
Dean Karn 73aaa89512 Update README.md 9 years ago
joeybloggs 7b758151c6 Add workaround for go issue 9 years ago
Hubert Krauze 3eaf857419 Add docs tcp/udp/ip/unix addresses resolve 9 years ago
Hubert Krauze ee0ce7d37e Add test for tcp/udp/ip/unix addresses resolve 9 years ago
Hubert Krauze 312ba49f28 Remove duplicated "Usage: mac" from docs 9 years ago
Hubert Krauze def24ae611 Add Resolvable suffix to functions so they can be more meaningful 9 years ago
Hubert Krauze 5a99cf6052 Add validation functions for tcp/udp/ip/unix addresses 9 years ago
joeybloggs c193cecd12 Merge branch 'complimentary-software-section' into v8 9 years ago
joeybloggs 64b7e2bb79 correct CI links 9 years ago
joeybloggs 50ada8d03a Add Complimentary software section README 9 years ago
Dean Karn d370e28d44 Merge pull request #232 from aarongreenlee/v8 9 years ago
Aaron Greenlee 0b51ee1e8e Removed duplicate punctuation. 9 years ago
Aaron Greenlee 71d9b9e91c Some grammer corrections; Formatting of GoDoc 9 years ago
Aaron Greenlee 24ea3a17b5 Minor typo corrected in doc.go 9 years ago
Dean Karn e8d470cd7a Merge pull request #229 from go-playground/v8-development 9 years ago
Dean Karn b737e38edb Merge pull request #228 from joeybloggs/v8-development 9 years ago
joeybloggs 0862513fbf Add some string check optimizations 9 years ago
joeybloggs 0b533f264c Only set namespace prefix when using FieldNameTag 9 years ago
joeybloggs afbcf59553 Add FieldNamespace and NameNamespace 9 years ago
Dean Karn bc50625289 Merge pull request #222 from go-playground/v8-development 9 years ago
Dean Karn e7cce24a67 Merge pull request #221 from muyiwaolurin/v8-development 9 years ago
Anthony Olurin c4d5999ec0 Added logo to ReadMe 9 years ago
Dean Karn 43f534e655 Merge pull request #220 from go-playground/v8-development 9 years ago
Dean Karn 8040a52f21 Merge pull request #219 from joeybloggs/v8-development 9 years ago
joeybloggs 934bef0ce5 Add new Anonymous test to hit new code 9 years ago
Dean Karn 0794474f60 Merge pull request #218 from go-playground/v8-development 9 years ago
Dean Karn 589c2ad113 Merge pull request #217 from joeybloggs/v8-development 9 years ago
joeybloggs e019c28542 Add struct field + associated tags caching 9 years ago
joeybloggs 94182a2199 init struct cache changes 9 years ago
Dean Karn 638ea8a3f8 Merge pull request #216 from go-playground/v8-development 9 years ago
Dean Karn d5987d5437 Merge pull request #215 from joeybloggs/v8-development 9 years ago
joeybloggs b0bd08d7c8 Micro optimization in Tag Cache 9 years ago
Dean Karn ec28e2da37 Merge pull request #214 from go-playground/v8-development 9 years ago
Dean Karn 47c3cabf25 Merge pull request #213 from joeybloggs/v8-development 9 years ago
joeybloggs d451d57023 Update benchmarks + correct benchmark error 9 years ago
Dean Karn d776d3eb2e Merge pull request #212 from go-playground/v8-development 9 years ago
Dean Karn ba623db026 Merge pull request #211 from joeybloggs/v8-development 9 years ago
joeybloggs 41828a2d17 Merge remote-tracking branch 'upstream/v8' into v8-development 9 years ago
joeybloggs cab69bdd13 Add minor optimization for structonly & nostructlevel checks 9 years ago
Dean Karn 82faf6f72a Merge pull request #210 from go-playground/v8-development 9 years ago
Dean Karn aea222d51c Merge pull request #209 from joeybloggs/v8-development 9 years ago
joeybloggs 24c1c6819f Add nostructlevel tag 9 years ago
Dean Karn 27557e4813 Merge pull request #208 from go-playground/v8-development 9 years ago
Dean Karn 5ad5c12aab Merge pull request #207 from joeybloggs/v8-development 9 years ago
joeybloggs 59859969c6 Fix issue with structOnly + struct level validation 9 years ago
Dean Karn c5efdc9576 Merge pull request #206 from go-playground/v8-development 9 years ago
Dean Karn 6268452877 Merge pull request #205 from joeybloggs/v8-development 9 years ago
joeybloggs 29403404e4 Added Helper method to Report errors from struct level. 9 years ago
Dean Karn 2ecdb677b3 Merge pull request #204 from go-playground/v8-development 9 years ago
Dean Karn 885fd6cb97 Merge pull request #203 from joeybloggs/v8-development 9 years ago
joeybloggs a48387a078 Merge remote-tracking branch 'upstream/v8-development' into v8-development 9 years ago
joeybloggs f1acffdfe0 Add Struct Level Validation! 9 years ago
Dean Karn 5f64c229a4 Merge pull request #202 from go-playground/v8 9 years ago
Dean Karn 11b132ba0b Update README.md 9 years ago
Dean Karn a21885483f Merge pull request #201 from go-playground/v8-development 9 years ago
Dean Karn 9a3b21ded0 Merge pull request #200 from joeybloggs/v8-development 9 years ago
joeybloggs 1570c9b6b3 Update Error message quotes to single quotes 9 years ago
Dean Karn d5305abfab Merge pull request #197 from go-playground/v8-development 9 years ago
Dean Karn 377e5e06a1 Merge pull request #196 from joeybloggs/v8-development 9 years ago
joeybloggs fc5d9f3ae0 Exposed Baked In Validators 9 years ago
Dean Karn 247a19d4b0 Merge pull request #194 from go-playground/v8 9 years ago
Dean Karn 17084684e6 Merge pull request #193 from krhubert/v8 9 years ago
Hubert d015334e09 fix docs usage for cidr validator 9 years ago
Hubert 9ffc753204 add cidr, cidrv4 and cidrv6 validators 9 years ago
Dean Karn ea31d3ec23 Merge pull request #192 from fabioxgn/patch-1 9 years ago
Fábio Gomes 28b6964c53 Fix typo on README so the example compiles 9 years ago
Dean Karn 7bfad40793 Merge pull request #191 from go-playground/v8-development 9 years ago
Dean Karn e82c80a530 Merge pull request #190 from joeybloggs/v8-development 9 years ago
joeybloggs 46f4476335 Update README 9 years ago
joeybloggs 3cef97a452 minor speed improvements 9 years ago
Dean Karn 344bcd6e10 Merge pull request #188 from ilgooz/fieldname 9 years ago
İlker Göktuğ Öztürk 5bc0ff91f8 configurable field name support 9 years ago
Dean Karn 92ddaeb7d8 Merge pull request #185 from go-playground/v8-development 9 years ago
Dean Karn 8818fdcf0b Merge pull request #184 from joeybloggs/v8-development 9 years ago
joeybloggs c8fb9a5e7c Merge remote-tracking branch 'upstream/v8' into v8-development 9 years ago
Dean Karn 5b7705b83f Merge pull request #175 from joeybloggs/v8-development 9 years ago
joeybloggs 36c0f0aa99 Update for repo move 9 years ago
Dean Karn 8324129b02 Merge pull request #173 from bluesuncorp/v8-development 9 years ago
Dean Karn d173a35b5c Merge pull request #172 from joeybloggs/v8-development 9 years ago
joeybloggs 95e8b47837 Merge remote-tracking branch 'upstream/v8-development' into v8-development 9 years ago
joeybloggs 830d270923 Expose Methods for Custom functions 9 years ago
Dean Karn ec1066576d Update README.md 9 years ago
Dean Karn 1a791b52ba Merge pull request #171 from bluesuncorp/v8-development 9 years ago
Dean Karn 0f4bcfc83f Merge pull request #170 from joeybloggs/v8-development 9 years ago
joeybloggs eab946fcd9 update CI and coverage badger to v8-development 9 years ago
joeybloggs d5f9115ad5 update all example references to v8 9 years ago
Dean Karn 40bd6a0bc0 Merge pull request #169 from joeybloggs/v8-development 9 years ago
joeybloggs aa72515d75 update benchmarks 9 years ago
joeybloggs 8119861695 inline Regex calls 9 years ago
joeybloggs 9e4314f9ab add more docs to doc.go 9 years ago
joeybloggs b366564cbe update to v8 benchmarks 9 years ago
joeybloggs e8133a0b33 Merge branch 'v7-development' into merge 9 years ago
Dean Karn e66bd708c4 Merge pull request #167 from joeybloggs/v7-development 9 years ago
joeybloggs 14df416126 Update Validator instance check 9 years ago
Dean Karn 0650f73d40 Merge pull request #166 from flowonyx/v7-development 9 years ago
Joel Williams 715aa553c8 Added checking for nil receiver on Validator methods 9 years ago
joeybloggs 22a5f70a0e Add Error handling info to README 9 years ago
joeybloggs d792c5a578 Add validation error info to DOC 9 years ago
joeybloggs 19b2f07d98 Update README for v8 9 years ago
joeybloggs b2d8b4186c update more comments 9 years ago
joeybloggs 9990e055a3 update comments 9 years ago
joeybloggs 0b51279b05 Update Error Pool 9 years ago
joeybloggs 70cb087d5a update how config is passed in and assigned to validator 9 years ago
joeybloggs 10cf645b91 reorganization of code + variables to more appropriate structs 9 years ago
joeybloggs 9988ba3f45 update New to use register functions to avoid errors 9 years ago
joeybloggs 4807bf93bb unexpose baked in validators map for safety. 9 years ago
joeybloggs c293315337 updated tag caching for maximum performance 9 years ago
joeybloggs b213226b01 Add Alias to the unique features section of README 9 years ago
joeybloggs b4563c2cf6 Add alias docs + notes 9 years ago
joeybloggs a964f5384a Completed 100% test coverage for alis registration 9 years ago
joeybloggs 407aac458f Update Alias logic 9 years ago
joeybloggs 2cda50fb41 Add Tag Alias + basic tests 9 years ago
Dean Karn f6ff3d4da3 Merge pull request #164 from bluesuncorp/v7-development 9 years ago
Dean Karn ca7facef9c Update README.md 9 years ago
joeybloggs 3191556e30 Merge branch 'v7-development' into v7 9 years ago
Dean Karn 9a7e605915 Update README.md 9 years ago
Dean Karn d5462d5b41 Merge pull request #163 from bluesuncorp/v7-development 9 years ago
Dean Karn 8146ec40c7 Merge pull request #162 from joeybloggs/v7-development 9 years ago
joeybloggs 77751ca042 update external references from v6 to v7 9 years ago
joeybloggs 4ab8352362 update benchmarks after nefield + necsfield changes 9 years ago
Dean Karn 72a602000a Update README.md 9 years ago
Dean Karn 95213db264 Update README.md 9 years ago
Dean Karn d423756cc0 Merge pull request #161 from joeybloggs/v7-development 9 years ago
joeybloggs ce06c47267 rename some variable for clarity 9 years ago
joeybloggs 43d7f25cfb update nefield and necsfield to hav own logic instead of calling !eqfield... 9 years ago
joeybloggs 55f9e44ce5 Update benchmarks for new go 1.5! 9 years ago
joeybloggs 15fdf82c30 Update verbiage for unique features for v7 cross struct cross field validation tags. 9 years ago
joeybloggs 3f4f84c358 Merge branch 'v6-development' into merge 9 years ago
Dean Karn 19d8904f2c Merge pull request #157 from joeybloggs/v6-development 9 years ago
joeybloggs 14b90946b3 Backport v7 updates 9 years ago
joeybloggs d7b348e4b3 Merge branch 'v6-development' into v7-development 9 years ago
Dean Karn b5317c5c5c Update examples_test.go 9 years ago
joeybloggs 7757a227ed Add benchmark for StructExcept 9 years ago
joeybloggs 883731a774 Updates + Benchmarks 9 years ago
joeybloggs 4f46e02133 Add documentation for cross struct validation tags + Struct Partials 9 years ago
joeybloggs 387cfe5aa9 Complete adding StructPartial and StructExcept 9 years ago
joeybloggs 656ae32e8b Updated PanicMatches after assertion library updates 9 years ago
joeybloggs 4a8a489366 Merge remote-tracking branch 'upstream/v7-development' into merge 9 years ago
Dean Karn 305c50fb58 Merge pull request #153 from bluesuncorp/v6 9 years ago
Dean Karn 6df82fdf49 Merge pull request #152 from bluesuncorp/v6-development 9 years ago
Dean Karn 8a9ed1f107 Merge pull request #151 from joeybloggs/v6-development 9 years ago
joeybloggs 844f5f46f7 Updated Panic Tests after updates to assertion library 9 years ago
joeybloggs 8ae139a445 Partially Merged in Partial struct methods + Tests 9 years ago
joeybloggs 3697be93be update benchmarks, pretty much the same 9 years ago
joeybloggs 8ff687aae4 code cleanup 9 years ago
joeybloggs 1fbc384272 Complete test coverage for gecsfield, gtecsfield, ltcsfield and ltecsfield 9 years ago
joeybloggs 327aa2e826 Add gtcsfield, gtecsfield, ltcsfield and ltecsfield 9 years ago
joeybloggs cd50c5e085 Added necsfield method + tests 9 years ago
joeybloggs 3a0791591a Add cross struct map support for all types not just string 9 years ago
joeybloggs 4cbf0659ce convert isLtField & isLteField to use new functions + test coverage 9 years ago
joeybloggs 5989727cf7 complete test coverage for IsGteField after conversion 9 years ago
joeybloggs 8aea478060 Update isGtField to user new functions 9 years ago
joeybloggs 2fe52ca08f finish eqcsfield + test coverage 9 years ago
joeybloggs d19088f865 Code Cleanup + some renaming 9 years ago
joeybloggs 81e29d3724 Complete Test Cases for getStructFieldOK 9 years ago
joeybloggs 2ea9043764 update to handle nested map + Array + Slice structs 9 years ago
joeybloggs 3ab458c80c Updates 9 years ago
Dean Karn c62ee7ccdf Merge pull request #148 from bluesuncorp/v6-development 9 years ago
Dean Karn 494e1360ec Merge pull request #147 from joeybloggs/v6-development 9 years ago
joeybloggs 50f0798342 Run gofmt -s -w . on code 9 years ago
Dean Karn 0cd5e89c38 Merge pull request #146 from bluesuncorp/v6-development 9 years ago
Dean Karn 3f5b785707 Merge pull request #144 from joeybloggs/v6-development 9 years ago
joeybloggs 7e97fcf2c4 Add exists tag 9 years ago
Dean Karn f8fd45620a Update README.md 9 years ago
Dean Karn a13509df8f Merge pull request #141 from bluesuncorp/v6-development 9 years ago
Dean Karn 442b210016 Merge pull request #140 from joeybloggs/v6-development 9 years ago
joeybloggs d2ea21ad15 Add RegisterCustomTypeFunc for easier adding of CustomTypeFunc 9 years ago
Kevin Harrington 7c844893e1 Added RegisterCustomTypeFunc method and usage example. 9 years ago
joeybloggs 048d7b8100 Merge branch 'v6-development' into v6 9 years ago
Dean Karn 32910f84c4 Merge pull request #137 from joeybloggs/v6-development 9 years ago
joeybloggs 6a8ed5612a Update simple.go file && README 9 years ago
Dean Karn 790122c21c Update simple.go 9 years ago
Dean Karn d802346da4 Merge pull request #136 from bluesuncorp/v6-development 9 years ago
Dean Karn a05046f9e7 Merge pull request #135 from joeybloggs/v6-development 9 years ago
joeybloggs d363ed316c Add handling of custom types 9 years ago
Dean Karn 55e8c8d9ca Merge pull request #129 from bluesuncorp/v6-development 9 years ago
Dean Karn a7e8a12f07 Merge pull request #128 from joeybloggs/v6-development 9 years ago
joeybloggs 143b21eba1 Add mac validator 9 years ago
joeybloggs bd16331fc0 Add ip, ipv4 and ipv6 validators 9 years ago
Dean Karn c0001173ee Merge pull request #127 from bluesuncorp/v6-development 9 years ago
Dean Karn a56318009b Merge pull request #126 from joeybloggs/v6-development 9 years ago
joeybloggs e078205c78 Update Required & Invalid logic 9 years ago
Dean Karn 54927e92d9 Merge pull request #124 from bluesuncorp/v6-development 9 years ago
Dean Karn f4625158e0 Merge pull request #123 from joeybloggs/v6-development 9 years ago
joeybloggs ea0db1fa47 Add single Field validation example 9 years ago
Dean Karn c59a51f3e9 Merge pull request #122 from joeybloggs/v6-development 9 years ago
joeybloggs 201c892979 Split out assertions and put in external repo 9 years ago
Dean Karn b9cdaa4346 Merge pull request #121 from bluesuncorp/v6-development 9 years ago
Dean Karn 781f596065 Merge pull request #120 from joeybloggs/v6-development 9 years ago
joeybloggs aef21d4d30 Update Benchmarks 9 years ago
joeybloggs a5d0ef37b8 update doc.go, some v5 specific notes were left. 9 years ago
Dean Karn a87651c07b Update README.md 9 years ago
Dean Karn fd0f7cd349 Merge pull request #119 from bluesuncorp/v6-development 9 years ago
Dean Karn 06ad2498ab Merge pull request #118 from joeybloggs/v6-development 9 years ago
joeybloggs cdc48b4f90 Fix Bug in Ptr tests 9 years ago
joeybloggs 506e57e4d7 Merge remote-tracking branch 'upstream/v6-development' into v6-development 9 years ago
Dean Karn b009996c4a Update README.md 9 years ago
Dean Karn d078eb5498 Merge pull request #117 from bluesuncorp/v6-development 9 years ago
Dean Karn 9e60f7d11b Merge pull request #116 from joeybloggs/v6-development 9 years ago
joeybloggs 2baa4bd353 Minor code cleanup 9 years ago
Dean Karn 347979cec7 Delete .travis.yml 9 years ago
Dean Karn 2a2b70052e Merge pull request #115 from bluesuncorp/v6-development 9 years ago
Dean Karn ae135ef613 Update README.md 9 years ago
Dean Karn fbc15ff5c6 Merge pull request #114 from joeybloggs/v6-development 9 years ago
joeybloggs 41b4a43989 Updated documentation for new v6 9 years ago
joeybloggs 933fe0b7a9 Add test for comma and pipe obfuscation 9 years ago
joeybloggs e005b06f11 Add Field Tag caching 9 years ago
joeybloggs e2a5b9881e Add ValidationErrs Caching 9 years ago
joeybloggs 4bdd703409 Remove old validator code 9 years ago
joeybloggs 07f2263b41 Benchmark Updates 9 years ago
joeybloggs 7f4b49c751 Finished Tests, now at 100% test converage! 9 years ago
joeybloggs 4ce39526f6 Update Test Case + fix errors 9 years ago
joeybloggs 24d46304a8 Updating & re-injecting tests 9 years ago
joeybloggs 88cc19b9e1 Add traverseMap function 9 years ago
joeybloggs 4d2ffbedfc Added traverseSlice function 9 years ago
joeybloggs 019c5fc4ac Finished converting baked in functions & some updates 9 years ago
joeybloggs 68ba87af24 More Progess 9 years ago
joeybloggs 7af3fb7c1f initial validation logic reworked 9 years ago
joeybloggs 953cc993e6 Merge remote-tracking branch 'upstream/v5' into v6-development 10 years ago
Dean Karn ac33a23e6e Merge pull request #113 from bluesuncorp/v5-development 10 years ago
Dean Karn 8a9bd75ae8 Merge pull request #112 from joeybloggs/v5-development 10 years ago
joeybloggs 89e9d9731d update to use utf8.RuneCountInString for string length comparisons 10 years ago
joeybloggs b52f154023 Merge remote-tracking branch 'upstream/v5-development' into v5-development 10 years ago
Dean Karn 314b33a481 Merge pull request #111 from zhing/v5-development 10 years ago
joeybloggs 9596b89a26 working on traversing field values 10 years ago
zhing 3bece518fa Merge branch 'v5-development' of https://gopkg.in/bluesuncorp/validator.v5 into v5-development 10 years ago
zhing 0fa8dd2a3e add validate:len=? support for utf-8 10 years ago
joeybloggs e42d7b683a determined variable values to be passed 10 years ago
joeybloggs c62550c414 Investigating difference speed architectures 10 years ago
Dean Karn ed304c7fdf Merge pull request #110 from bluesuncorp/v5 10 years ago
Dean Karn 06aac46c91 Merge pull request #109 from bluesuncorp/v5-development 10 years ago
Dean Karn 988489de15 Merge pull request #108 from joeybloggs/v5-development 10 years ago
joeybloggs 9d2b8ee9d4 updated coverage tests to be 100% 10 years ago
joeybloggs e1fd32247f Fix interface issue when value is set but no validation tag exists 10 years ago
Dean Karn e02a29b19b Merge pull request #105 from gitter-badger/gitter-badge 10 years ago
The Gitter Badger c4ae288afd Added Gitter badge 10 years ago
Dean Karn 7422dd4828 update latest benchmarks 10 years ago
Dean Karn 6ae2952f55 Merge pull request #104 from bluesuncorp/v5 10 years ago
Dean Karn d2748d5ae5 Merge pull request #103 from bluesuncorp/v5-development 10 years ago
Dean Karn 28b71ba8ae Merge pull request #102 from joeybloggs/v5-development 10 years ago
joeybloggs 9d4c0ec302 update travis.ml for overalls, which is giving nothing but problems! 10 years ago
joeybloggs 302c3cffdd to use new sync pool remove go 1.2 support 10 years ago
joeybloggs 562e77833a change to use native sync.Pool 10 years ago
Dean Karn 31fb6bb006 Merge pull request #97 from bluesuncorp/v5 10 years ago
Dean Karn b9105b5bf7 Merge pull request #96 from bluesuncorp/v5-development 10 years ago
Dean Karn e5ebe76ccf Merge pull request #95 from joeybloggs/v5-development 10 years ago
joeybloggs 46b655a956 add some benchmarks to readme 10 years ago
joeybloggs c4203fff25 add file and README example 10 years ago
joeybloggs 89a5909004 add test to ensure 100% of the lines of code are called, even in the pool 10 years ago
Dean Karn f88ea46a9a Merge pull request #94 from bluesuncorp/v5 10 years ago
Dean Karn 0e7326e6a7 Merge pull request #93 from bluesuncorp/v5 10 years ago
Dean Karn 82abe38795 Add test coverage badge 10 years ago
Dean Karn 26333a65c1 add goveralls test coverage 10 years ago
Dean Karn 5ca3cffc8c Merge pull request #91 from bluesuncorp/v5 10 years ago
Dean Karn d8e0c4d936 Merge pull request #90 from bluesuncorp/v5-development 10 years ago
Dean Karn 4f5ff0f3b4 Merge pull request #89 from joeybloggs/v5-development 10 years ago
joeybloggs 92bd6b335a code cleanup 10 years ago
joeybloggs f604b6cc96 Complete Flatten logic 10 years ago
joeybloggs 4d57165562 fix wrong variable used in checking for "[" char 10 years ago
joeybloggs 7d55bfddde complete flatten logic for array elements 10 years ago
Dean Karn d627af88ac Merge pull request #87 from bluesuncorp/v5-development 10 years ago
Dean Karn f6358a9d49 Merge pull request #86 from joeybloggs/v5-development 10 years ago
joeybloggs c7ff296dca correct interface issue 10 years ago
Dean Karn 7ce6ffcb4d Merge pull request #84 from bluesuncorp/v5 10 years ago
Dean Karn 740b7d0daa Merge pull request #83 from bluesuncorp/v5-development 10 years ago
Dean Karn 4574ba54c6 Merge pull request #82 from joeybloggs/v5-development 10 years ago
joeybloggs 22aaa55c7c add dive documentation 10 years ago
joeybloggs 200a5b4aad finish map error handling & complete test coverage 10 years ago
joeybloggs 8bf793acde correct map references pointing to slice after copy/paste 10 years ago
joeybloggs 14f176e8ac add traverseMap 10 years ago
joeybloggs 98f4165fae added time test 10 years ago
joeybloggs a0f6d14ada add more tests 10 years ago
joeybloggs 689d3e9989 finalized array error handling 10 years ago
joeybloggs 1ba858eec1 correct FieldError error printing idea issue 10 years ago
joeybloggs 6eded1f817 correct error output and index out of order error 10 years ago
joeybloggs d019d02290 Add some initial validation 10 years ago
joeybloggs 4afdc19aef Finish initial array traversal logic 10 years ago
joeybloggs a3cf2f5cf3 Merge branch 'v5-development' into add-array-slice-map-dive-support 10 years ago
Dean Karn 27a1d3f158 Merge pull request #81 from bluesuncorp/v5-development 10 years ago
Dean Karn 3e4207bccb Merge pull request #80 from joeybloggs/v5-development 10 years ago
joeybloggs e0e86490bf Fix Issue with nested struct as pointer being nil 10 years ago
joeybloggs e0bfa17b22 add initial dive logic 10 years ago
Dean Karn c06d47f593 Merge pull request #77 from bluesuncorp/v5-development 10 years ago
Dean Karn 64eb07fa30 Merge pull request #76 from joeybloggs/v5-development 10 years ago
joeybloggs 63a3b7e6ad add multibyte test case for blank string to maintain 100% test coverage 10 years ago
joeybloggs 35aff710e4 added many new validator + tests + documentation: 10 years ago
joeybloggs 7aa70841bc add uuid, uuid3, uuid4 and uuid5 validators + tests + documentation 10 years ago
joeybloggs 20d9b7909f add isbn, isbn10 and isbn validators + tests + documentation 10 years ago
joeybloggs 05e0fe1f85 updated various regex's to remove any capturing groups 10 years ago
joeybloggs 5db5165e2c update rub and reba regex 10 years ago
joeybloggs 9ff11ae808 break out benchmarks into separate file 10 years ago
Dean Karn 049d448603 Merge pull request #73 from bluesuncorp/v5 10 years ago
Dean Karn df95f9de27 Merge pull request #71 from bluesuncorp/v5-development 10 years ago
Dean Karn be66dfe125 Merge pull request #70 from joeybloggs/v5-development 10 years ago
joeybloggs f4837a073b add call to SetMaxStructPoolSize in test to ensure continued 100% test coverage 10 years ago
Dean Karn ecfab4f37a Merge pull request #69 from bluesuncorp/v5-development 10 years ago
Dean Karn ac10117172 Merge pull request #68 from joeybloggs/v5-development 10 years ago
joeybloggs fcbf6b65e4 add caching pool of StructErrors to reuse objects, reduce garbage collection and reduce memory allocations 10 years ago
joeybloggs 678d778cba Merge branch 'investigate-including-comma-in-data' into v5-development 10 years ago
joeybloggs 0fbc3228e8 rework code to allow handling of comma (,) and = within the params i.e. excludesall=,= 10 years ago
Dean Karn 4cf1b67b2d Merge pull request #66 from bluesuncorp/v5 10 years ago
Dean Karn c6a510f8a9 Merge pull request #65 from bluesuncorp/v5-development 10 years ago
Dean Karn d40121962a Merge pull request #64 from joeybloggs/v5-development 10 years ago
joeybloggs 793099be40 remove trimming of param option as space could be a valid param option or char 10 years ago
Dean Karn 6ae296cb93 Update README.md 10 years ago
Dean Karn 76bccce51f Merge pull request #62 from bluesuncorp/v5 10 years ago
Dean Karn 8461815c10 Merge pull request #61 from bluesuncorp/v5-development 10 years ago
Dean Karn 3d15a126d3 Merge pull request #60 from joeybloggs/cache-struct-schema-metadata 10 years ago
joeybloggs 1fda4930f6 comment out parallel benchmarks to maintain go 1.2 compatibility 10 years ago
joeybloggs aa275c658d merge pul request changes from @xboston 10 years ago
joeybloggs 39656b5186 Merge branch 'v5-development' into cache-struct-schema-metadata 10 years ago
joeybloggs 98ee4c3a5d Merge branch 'v6-development' into v5-development 10 years ago
Dean Karn c085ab22ea Merge pull request #58 from xboston/patch-1 10 years ago
Nikolay Kirsh c09c7a1231 fix UserDetail type 10 years ago
joeybloggs 56b4ce1811 add larger tests for benchmarks 10 years ago
joeybloggs 81ce302975 add parallel benchmark 10 years ago
joeybloggs ad39bb92dd code cleanup 10 years ago
joeybloggs 6ffa5d1455 add thread safety note to AddFunction and SetTag functions 10 years ago
joeybloggs 8c2248a5ce add map thread safety 10 years ago
joeybloggs 0c5fbee316 code cleanup + variable renaming 10 years ago
joeybloggs e4f2ff67bd add caching of field only tags, now less time, memory and only 2 allocations vs 9 10 years ago
joeybloggs 22d031deb0 add struct caching, significant speedup even in a simple test 10 years ago
Dean Karn 6fe54bc1d3 Merge pull request #54 from bluesuncorp/v5 10 years ago
Dean Karn 1d61bf3148 Merge pull request #53 from bluesuncorp/v5-development 10 years ago
Dean Karn 61e4429b20 Merge pull request #52 from joeybloggs/v5-development 10 years ago
joeybloggs fbb3befecb update validate struct benchmark for lager struct with nested struct 10 years ago
joeybloggs beaa9adf31 minor performance updates 10 years ago
Dean Karn 8df4eb813b Merge pull request #51 from bluesuncorp/v5 10 years ago
Dean Karn 479d3f0fd9 Merge pull request #50 from bluesuncorp/v5-development 10 years ago
Dean Karn 756455cce5 Merge pull request #49 from joeybloggs/change-to-native-golang-testing 10 years ago
joeybloggs e5c73961c7 finish test conversion 10 years ago
joeybloggs ae2d0646af add more checks to IsEqual function 10 years ago
joeybloggs e0b68a7520 initial commit of helper functions 10 years ago
Dean Karn 2be1659b5b Merge pull request #47 from bluesuncorp/v5 10 years ago
Dean Karn 07cbdd2e6d Merge pull request #46 from bluesuncorp/v5-development 10 years ago
Dean Karn 5ab4925073 Merge pull request #45 from joeybloggs/v5-development 10 years ago
joeybloggs 3dcc019b64 add contains, contains any, contains rune, excludes, excludes and excludesrune validation functions + tests + docuemtation 10 years ago
joeybloggs 9d18657e1f remove extra carriage returns 10 years ago
joeybloggs fd059fe2f1 remove unnecessary carriage returns 10 years ago
Dean Karn 40c38f9931 Merge pull request #42 from bluesuncorp/v5 10 years ago
Dean Karn 63658537be Merge pull request #41 from bluesuncorp/v5 10 years ago
Dean Karn d780b124a9 Merge pull request #40 from bluesuncorp/v5-development 10 years ago
Dean Karn ee35a115e9 Merge pull request #39 from joeybloggs/v5-development 10 years ago
joeybloggs f7f779fb31 add documentation for ne and nefield validation function 10 years ago
joeybloggs 23c3fa6b63 add ne and nefield functions to validator 10 years ago
Dean Karn 74d0e52ab3 Update README.md 10 years ago
Dean Karn 73747bdf83 Merge pull request #37 from bluesuncorp/v5-development 10 years ago
Dean Karn 1a0a2f52c4 Merge pull request #36 from joeybloggs/v5-development 10 years ago
joeybloggs b891b1cf3c add eq baked in function + tests 10 years ago
Dean Karn 98f3221631 Merge pull request #34 from bluesuncorp/v5 10 years ago
Dean Karn 4e9461558c Update README.md 10 years ago
Dean Karn fa8e0664b2 Merge pull request #33 from bluesuncorp/v5-development 10 years ago
Dean Karn 765fb71956 Merge pull request #32 from joeybloggs/v5-development 10 years ago
Dean Karn e530eb5470 add documentation for new base64 validator 10 years ago
Dean Karn 1d008b4ad2 add base64 validate as requested in issue #30 10 years ago
Dean Karn 4c73ffba66 update verbiage after pull request 10 years ago
Dean Karn d400cda52e Merge pull request #31 from muyiwaolurin/v5-development 10 years ago
Anthony Olurin 700e5f4b46 Minor typos 10 years ago
Dean Karn 829b13775f Update validator_test.go 10 years ago
Dean Karn 04b0ff368d Update README.md 10 years ago
Dean Karn 42419864c0 Merge pull request #29 from joeybloggs/v5 10 years ago
Dean Karn d474ce1ce6 update test import path 10 years ago
Dean Karn 9d1ffaeb87 Merge pull request #28 from joeybloggs/v5 10 years ago
Dean Karn 7ac98be692 changes in preparation for package rename to validator 10 years ago
  1. 1
      .github/CODEOWNERS
  2. 9
      .github/CONTRIBUTING.md
  3. 16
      .github/ISSUE_TEMPLATE.md
  4. 7
      .github/PULL_REQUEST_TEMPLATE.md
  5. 51
      .github/workflows/workflow.yml
  6. 7
      .gitignore
  7. 16
      .travis.yml
  8. 16
      MAINTAINERS.md
  9. 18
      Makefile
  10. 355
      README.md
  11. 39
      _examples/custom-validation/main.go
  12. 51
      _examples/custom/main.go
  13. 39
      _examples/dive/main.go
  14. 10
      _examples/gin-upgrading-overriding/main.go
  15. 55
      _examples/gin-upgrading-overriding/v8_to_v9.go
  16. 87
      _examples/map-validation/main.go
  17. 101
      _examples/simple/main.go
  18. 172
      _examples/struct-level/main.go
  19. 92
      _examples/struct-map-rules-validation/main.go
  20. 129
      _examples/translations/main.go
  21. 2835
      baked_in.go
  22. 1099
      benchmarks_test.go
  23. 327
      cache.go
  24. 1132
      country_codes.go
  25. 79
      currency_codes.go
  26. 1663
      doc.go
  27. 272
      errors.go
  28. 120
      field_level.go
  29. 14
      go.mod
  30. 31
      go.sum
  31. BIN
      logo.png
  32. 25
      non-standard/validators/notblank.go
  33. 65
      non-standard/validators/notblank_test.go
  34. 173
      postcode_regexes.go
  35. 155
      regexes.go
  36. 175
      struct_level.go
  37. 1
      testdata/a.go
  38. 11
      translations.go
  39. 1389
      translations/ar/ar.go
  40. 695
      translations/ar/ar_test.go
  41. 1414
      translations/en/en.go
  42. 720
      translations/en/en_test.go
  43. 1385
      translations/es/es.go
  44. 658
      translations/es/es_test.go
  45. 1384
      translations/fa/fa.go
  46. 690
      translations/fa/fa_test.go
  47. 1370
      translations/fr/fr.go
  48. 639
      translations/fr/fr_test.go
  49. 1370
      translations/id/id.go
  50. 639
      translations/id/id_test.go
  51. 1261
      translations/it/it.go
  52. 725
      translations/it/it_test.go
  53. 1466
      translations/ja/ja.go
  54. 710
      translations/ja/ja_test.go
  55. 1399
      translations/lv/lv.go
  56. 709
      translations/lv/lv_test.go
  57. 1370
      translations/nl/nl.go
  58. 639
      translations/nl/nl_test.go
  59. 1410
      translations/pt/pt.go
  60. 682
      translations/pt/pt_test.go
  61. 1380
      translations/pt_BR/pt_BR.go
  62. 651
      translations/pt_BR/pt_BR_test.go
  63. 1493
      translations/ru/ru.go
  64. 767
      translations/ru/ru_test.go
  65. 1375
      translations/tr/tr.go
  66. 657
      translations/tr/tr_test.go
  67. 1384
      translations/vi/vi.go
  68. 690
      translations/vi/vi_test.go
  69. 1482
      translations/zh/zh.go
  70. 696
      translations/zh/zh_test.go
  71. 1378
      translations/zh_tw/zh_tw.go
  72. 646
      translations/zh_tw/zh_tw_test.go
  73. 288
      util.go
  74. 662
      validator.go
  75. 700
      validator_instance.go
  76. 13555
      validator_test.go

@ -0,0 +1 @@
* @go-playground/validator-maintainers

@ -0,0 +1,9 @@
# Contribution Guidelines
## Quality Standard
To ensure the continued stability of this package, tests are required that cover the change in order for a pull request to be merged.
## Reporting issues
Please open an issue or join the gitter chat [![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) for any issues, questions or possible enhancements to the package.

@ -0,0 +1,16 @@
- [ ] I have looked at the documentation [here](https://pkg.go.dev/github.com/go-playground/validator/v10#section-documentation) first?
- [ ] I have looked at the examples provided that may showcase my question [here](/_examples)?
### Package version eg. v9, v10:
### Issue, Question or Enhancement:
### Code sample, to showcase or reproduce:
```go
```

@ -0,0 +1,7 @@
## Fixes Or Enhances
**Make sure that you've checked the boxes below before you submit PR:**
- [ ] Tests exist or have been written that cover this particular change.
@go-playground/validator-maintainers

@ -0,0 +1,51 @@
on:
push:
branches:
- master
pull_request:
name: Test
jobs:
test:
strategy:
matrix:
go-version: [1.19.x]
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Install Go
uses: actions/setup-go@v3
with:
go-version: ${{ matrix.go-version }}
- name: Checkout code
uses: actions/checkout@v3
- name: Restore Cache
uses: actions/cache@v3
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-v1-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-v1-go-
- name: Test
run: go test -race -covermode=atomic -coverprofile="profile.cov" ./...
- name: Send Coverage
if: matrix.os == 'ubuntu-latest' && matrix.go-version == '1.19.x'
uses: shogo82148/actions-goveralls@v1
with:
path-to-profile: profile.cov
golangci:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/setup-go@v3
with:
go-version: 1.19.x
- uses: actions/checkout@v3
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
version: v1.50.1

7
.gitignore vendored

@ -6,6 +6,7 @@
# Folders
_obj
_test
bin
# Architecture specific extensions/prefixes
*.[568vq]
@ -22,3 +23,9 @@ _testmain.go
*.exe
*.test
*.prof
*.test
*.out
*.txt
cover.html
README.html
.idea

@ -1,16 +0,0 @@
language: go
notificaitons:
email:
recipients: bluesuncorp01@gmail.com
on_success: change
on_failure: always
before_script:
- go get gopkg.in/check.v1
go:
- 1.2
- 1.3
- 1.4
- tip

@ -0,0 +1,16 @@
## Maintainers Guide
### Semantic Versioning
Semantic versioning as defined [here](https://semver.org) must be strictly adhered to.
### External Dependencies
Any new external dependencies MUST:
- Have a compatible LICENSE present.
- Be actively maintained.
- Be approved by @go-playground/admins
### PR Merge Requirements
- Up-to-date branch.
- Passing tests and linting.
- CODEOWNERS approval.
- Tests that cover both the Happy and Unhappy paths.

@ -0,0 +1,18 @@
GOCMD=GO111MODULE=on go
linters-install:
@golangci-lint --version >/dev/null 2>&1 || { \
echo "installing linting tools..."; \
curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s v1.41.1; \
}
lint: linters-install
golangci-lint run
test:
$(GOCMD) test -cover -race ./...
bench:
$(GOCMD) test -bench=. -benchmem ./...
.PHONY: test lint linters-install

@ -1,43 +1,348 @@
Package go-validate-yourself
================
[![Build Status](https://travis-ci.org/bluesuncorp/go-validate-yourself.svg?branch=v4)](https://travis-ci.org/bluesuncorp/go-validate-yourself)
[![GoDoc](https://godoc.org/gopkg.in/bluesuncorp/go-validate-yourself.v4?status.svg)](https://godoc.org/gopkg.in/bluesuncorp/go-validate-yourself.v4)
Package validator
=================
<img align="right" src="https://raw.githubusercontent.com/go-playground/validator/v10/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.12.0-green.svg)
[![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)
[![Go Report Card](https://goreportcard.com/badge/github.com/go-playground/validator)](https://goreportcard.com/report/github.com/go-playground/validator)
[![GoDoc](https://godoc.org/github.com/go-playground/validator?status.svg)](https://pkg.go.dev/github.com/go-playground/validator/v10)
![License](https://img.shields.io/dub/l/vibe-d.svg)
Package validator implements value validations for structs and individual fields based on tags.
It has the following **unique** features:
- Cross Field and Cross Struct validations by using validation tags or custom validators.
- Slice, Array and Map diving, which allows any or all levels of a multidimensional field to be validated.
- Ability to dive into both map keys and values for validation
- Handles type interface by determining it's underlying type prior to validation.
- Handles custom field types such as sql driver Valuer see [Valuer](https://golang.org/src/database/sql/driver/types.go?s=1210:1293#L29)
- Alias validation tags, which allows for mapping of several validations to a single tag for easier defining of validations on structs
- Extraction of custom defined Field Name e.g. can specify to extract the JSON name while validating and have it available in the resulting FieldError
- Customizable i18n aware error messages.
- Default validator for the [gin](https://github.com/gin-gonic/gin) web framework; upgrading from v8 to v9 in gin see [here](https://github.com/go-playground/validator/tree/master/_examples/gin-upgrading-overriding)
Installation
============
------------
Use go get.
go get github.com/go-playground/validator/v10
Then import the validator package into your own code.
import "github.com/go-playground/validator/v10"
Error Return Value
-------
Validation functions return type error
They return type error to avoid the issue discussed in the following, where err is always != nil:
* http://stackoverflow.com/a/29138676/3158232
* https://github.com/go-playground/validator/issues/134
Validator returns only InvalidValidationError for bad validation input, nil or ValidationErrors as type error; so, in your code all you need to do is check if the error returned is not nil, and if it's not check if error is InvalidValidationError ( if necessary, most of the time it isn't ) type cast it to type ValidationErrors like so:
Just use go get.
```go
err := validate.Struct(mystruct)
validationErrors := err.(validator.ValidationErrors)
```
go get gopkg.in/bluesuncorp/go-validate-yourself.v4
Usage and documentation
------
or to update
Please see https://pkg.go.dev/github.com/go-playground/validator/v10 for detailed usage docs.
go get -u gopkg.in/bluesuncorp/go-validate-yourself.v4
##### Examples:
And then just import the package into your own code.
- [Simple](https://github.com/go-playground/validator/blob/master/_examples/simple/main.go)
- [Custom Field Types](https://github.com/go-playground/validator/blob/master/_examples/custom/main.go)
- [Struct Level](https://github.com/go-playground/validator/blob/master/_examples/struct-level/main.go)
- [Translations & Custom Errors](https://github.com/go-playground/validator/blob/master/_examples/translations/main.go)
- [Gin upgrade and/or override validator](https://github.com/go-playground/validator/tree/v9/_examples/gin-upgrading-overriding)
- [wash - an example application putting it all together](https://github.com/bluesuncorp/wash)
import "gopkg.in/bluesuncorp/go-validate-yourself.v4"
Baked-in Validations
------
Usage
=====
### Fields:
Please see http://godoc.org/gopkg.in/bluesuncorp/go-validate-yourself.v4 for detailed usage docs.
| Tag | Description |
| - | - |
| eqcsfield | Field Equals Another Field (relative)|
| eqfield | Field Equals Another Field |
| fieldcontains | Check the indicated characters are present in the Field |
| fieldexcludes | Check the indicated characters are not present in the field |
| gtcsfield | Field Greater Than Another Relative Field |
| gtecsfield | Field Greater Than or Equal To Another Relative Field |
| gtefield | Field Greater Than or Equal To Another Field |
| gtfield | Field Greater Than Another Field |
| ltcsfield | Less Than Another Relative Field |
| ltecsfield | Less Than or Equal To Another Relative Field |
| ltefield | Less Than or Equal To Another Field |
| ltfield | Less Than Another Field |
| necsfield | Field Does Not Equal Another Field (relative) |
| nefield | Field Does Not Equal Another Field |
Contributing
============
### Network:
There will be a development branch for each version of this package i.e. v1-development, please
make your pull requests against those branches.
| Tag | Description |
| - | - |
| cidr | Classless Inter-Domain Routing CIDR |
| cidrv4 | Classless Inter-Domain Routing CIDRv4 |
| cidrv6 | Classless Inter-Domain Routing CIDRv6 |
| datauri | Data URL |
| fqdn | Full Qualified Domain Name (FQDN) |
| hostname | Hostname RFC 952 |
| hostname_port | HostPort |
| hostname_rfc1123 | Hostname RFC 1123 |
| ip | Internet Protocol Address IP |
| ip4_addr | Internet Protocol Address IPv4 |
| ip6_addr | Internet Protocol Address IPv6 |
| ip_addr | Internet Protocol Address IP |
| ipv4 | Internet Protocol Address IPv4 |
| ipv6 | Internet Protocol Address IPv6 |
| mac | Media Access Control Address MAC |
| tcp4_addr | Transmission Control Protocol Address TCPv4 |
| tcp6_addr | Transmission Control Protocol Address TCPv6 |
| tcp_addr | Transmission Control Protocol Address TCP |
| udp4_addr | User Datagram Protocol Address UDPv4 |
| udp6_addr | User Datagram Protocol Address UDPv6 |
| udp_addr | User Datagram Protocol Address UDP |
| unix_addr | Unix domain socket end point Address |
| uri | URI String |
| url | URL String |
| http_url | HTTP URL String |
| url_encoded | URL Encoded |
| urn_rfc2141 | Urn RFC 2141 String |
If changes are breaking please create an issue, for discussion and create a pull request against
the highest development branch for example this package has a v1 and v1-development branch
however, there will also be a v2-development brach even though v2 doesn't exist yet.
### Strings:
I strongly encourage everyone whom creates a custom validation function to contribute them and
help make this package even better.
| Tag | Description |
| - | - |
| alpha | Alpha Only |
| alphanum | Alphanumeric |
| alphanumunicode | Alphanumeric Unicode |
| alphaunicode | Alpha Unicode |
| ascii | ASCII |
| boolean | Boolean |
| contains | Contains |
| containsany | Contains Any |
| containsrune | Contains Rune |
| endsnotwith | Ends Not With |
| endswith | Ends With |
| excludes | Excludes |
| excludesall | Excludes All |
| excludesrune | Excludes Rune |
| lowercase | Lowercase |
| multibyte | Multi-Byte Characters |
| number | Number |
| numeric | Numeric |
| printascii | Printable ASCII |
| startsnotwith | Starts Not With |
| startswith | Starts With |
| uppercase | Uppercase |
### Format:
| Tag | Description |
| - | - |
| base64 | Base64 String |
| base64url | Base64URL String |
| base64rawurl | Base64RawURL String |
| bic | Business Identifier Code (ISO 9362) |
| bcp47_language_tag | Language tag (BCP 47) |
| btc_addr | Bitcoin Address |
| btc_addr_bech32 | Bitcoin Bech32 Address (segwit) |
| credit_card | Credit Card Number |
| mongodb | MongoDB ObjectID |
| cron | Cron |
| datetime | Datetime |
| e164 | e164 formatted phone number |
| email | E-mail String
| eth_addr | Ethereum Address |
| hexadecimal | Hexadecimal String |
| hexcolor | Hexcolor String |
| hsl | HSL String |
| hsla | HSLA String |
| html | HTML Tags |
| html_encoded | HTML Encoded |
| isbn | International Standard Book Number |
| isbn10 | International Standard Book Number 10 |
| isbn13 | International Standard Book Number 13 |
| iso3166_1_alpha2 | Two-letter country code (ISO 3166-1 alpha-2) |
| iso3166_1_alpha3 | Three-letter country code (ISO 3166-1 alpha-3) |
| iso3166_1_alpha_numeric | Numeric country code (ISO 3166-1 numeric) |
| iso3166_2 | Country subdivision code (ISO 3166-2) |
| iso4217 | Currency code (ISO 4217) |
| json | JSON |
| jwt | JSON Web Token (JWT) |
| latitude | Latitude |
| longitude | Longitude |
| luhn_checksum | Luhn Algorithm Checksum (for strings and (u)int) |
| postcode_iso3166_alpha2 | Postcode |
| postcode_iso3166_alpha2_field | Postcode |
| rgb | RGB String |
| rgba | RGBA String |
| ssn | Social Security Number SSN |
| timezone | Timezone |
| uuid | Universally Unique Identifier UUID |
| uuid3 | Universally Unique Identifier UUID v3 |
| uuid3_rfc4122 | Universally Unique Identifier UUID v3 RFC4122 |
| uuid4 | Universally Unique Identifier UUID v4 |
| uuid4_rfc4122 | Universally Unique Identifier UUID v4 RFC4122 |
| uuid5 | Universally Unique Identifier UUID v5 |
| uuid5_rfc4122 | Universally Unique Identifier UUID v5 RFC4122 |
| uuid_rfc4122 | Universally Unique Identifier UUID RFC4122 |
| md4 | MD4 hash |
| md5 | MD5 hash |
| sha256 | SHA256 hash |
| sha384 | SHA384 hash |
| sha512 | SHA512 hash |
| ripemd128 | RIPEMD-128 hash |
| ripemd128 | RIPEMD-160 hash |
| tiger128 | TIGER128 hash |
| tiger160 | TIGER160 hash |
| tiger192 | TIGER192 hash |
| semver | Semantic Versioning 2.0.0 |
| ulid | Universally Unique Lexicographically Sortable Identifier ULID |
| cve | Common Vulnerabilities and Exposures Identifier (CVE id) |
### Comparisons:
| Tag | Description |
| - | - |
| eq | Equals |
| eq_ignore_case | Equals ignoring case |
| gt | Greater than|
| gte | Greater than or equal |
| lt | Less Than |
| lte | Less Than or Equal |
| ne | Not Equal |
| ne_ignore_case | Not Equal ignoring case |
### Other:
| Tag | Description |
| - | - |
| dir | Existing Directory |
| dirpath | Directory Path |
| file | Existing File |
| filepath | File Path |
| isdefault | Is Default |
| len | Length |
| max | Maximum |
| min | Minimum |
| oneof | One Of |
| required | Required |
| required_if | Required If |
| required_unless | Required Unless |
| required_with | Required With |
| required_with_all | Required With All |
| required_without | Required Without |
| required_without_all | Required Without All |
| excluded_if | Excluded If |
| excluded_unless | Excluded Unless |
| excluded_with | Excluded With |
| excluded_with_all | Excluded With All |
| excluded_without | Excluded Without |
| excluded_without_all | Excluded Without All |
| unique | Unique |
#### Aliases:
| Tag | Description |
| - | - |
| iscolor | hexcolor\|rgb\|rgba\|hsl\|hsla |
| country_code | iso3166_1_alpha2\|iso3166_1_alpha3\|iso3166_1_alpha_numeric |
Benchmarks
------
###### Run on MacBook Pro (15-inch, 2017) go version go1.10.2 darwin/amd64
```go
goos: darwin
goarch: amd64
pkg: github.com/go-playground/validator
BenchmarkFieldSuccess-8 20000000 83.6 ns/op 0 B/op 0 allocs/op
BenchmarkFieldSuccessParallel-8 50000000 26.8 ns/op 0 B/op 0 allocs/op
BenchmarkFieldFailure-8 5000000 291 ns/op 208 B/op 4 allocs/op
BenchmarkFieldFailureParallel-8 20000000 107 ns/op 208 B/op 4 allocs/op
BenchmarkFieldArrayDiveSuccess-8 2000000 623 ns/op 201 B/op 11 allocs/op
BenchmarkFieldArrayDiveSuccessParallel-8 10000000 237 ns/op 201 B/op 11 allocs/op
BenchmarkFieldArrayDiveFailure-8 2000000 859 ns/op 412 B/op 16 allocs/op
BenchmarkFieldArrayDiveFailureParallel-8 5000000 335 ns/op 413 B/op 16 allocs/op
BenchmarkFieldMapDiveSuccess-8 1000000 1292 ns/op 432 B/op 18 allocs/op
BenchmarkFieldMapDiveSuccessParallel-8 3000000 467 ns/op 432 B/op 18 allocs/op
BenchmarkFieldMapDiveFailure-8 1000000 1082 ns/op 512 B/op 16 allocs/op
BenchmarkFieldMapDiveFailureParallel-8 5000000 425 ns/op 512 B/op 16 allocs/op
BenchmarkFieldMapDiveWithKeysSuccess-8 1000000 1539 ns/op 480 B/op 21 allocs/op
BenchmarkFieldMapDiveWithKeysSuccessParallel-8 3000000 613 ns/op 480 B/op 21 allocs/op
BenchmarkFieldMapDiveWithKeysFailure-8 1000000 1413 ns/op 721 B/op 21 allocs/op
BenchmarkFieldMapDiveWithKeysFailureParallel-8 3000000 575 ns/op 721 B/op 21 allocs/op
BenchmarkFieldCustomTypeSuccess-8 10000000 216 ns/op 32 B/op 2 allocs/op
BenchmarkFieldCustomTypeSuccessParallel-8 20000000 82.2 ns/op 32 B/op 2 allocs/op
BenchmarkFieldCustomTypeFailure-8 5000000 274 ns/op 208 B/op 4 allocs/op
BenchmarkFieldCustomTypeFailureParallel-8 20000000 116 ns/op 208 B/op 4 allocs/op
BenchmarkFieldOrTagSuccess-8 2000000 740 ns/op 16 B/op 1 allocs/op
BenchmarkFieldOrTagSuccessParallel-8 3000000 474 ns/op 16 B/op 1 allocs/op
BenchmarkFieldOrTagFailure-8 3000000 471 ns/op 224 B/op 5 allocs/op
BenchmarkFieldOrTagFailureParallel-8 3000000 414 ns/op 224 B/op 5 allocs/op
BenchmarkStructLevelValidationSuccess-8 10000000 213 ns/op 32 B/op 2 allocs/op
BenchmarkStructLevelValidationSuccessParallel-8 20000000 91.8 ns/op 32 B/op 2 allocs/op
BenchmarkStructLevelValidationFailure-8 3000000 473 ns/op 304 B/op 8 allocs/op
BenchmarkStructLevelValidationFailureParallel-8 10000000 234 ns/op 304 B/op 8 allocs/op
BenchmarkStructSimpleCustomTypeSuccess-8 5000000 385 ns/op 32 B/op 2 allocs/op
BenchmarkStructSimpleCustomTypeSuccessParallel-8 10000000 161 ns/op 32 B/op 2 allocs/op
BenchmarkStructSimpleCustomTypeFailure-8 2000000 640 ns/op 424 B/op 9 allocs/op
BenchmarkStructSimpleCustomTypeFailureParallel-8 5000000 318 ns/op 440 B/op 10 allocs/op
BenchmarkStructFilteredSuccess-8 2000000 597 ns/op 288 B/op 9 allocs/op
BenchmarkStructFilteredSuccessParallel-8 10000000 266 ns/op 288 B/op 9 allocs/op
BenchmarkStructFilteredFailure-8 3000000 454 ns/op 256 B/op 7 allocs/op
BenchmarkStructFilteredFailureParallel-8 10000000 214 ns/op 256 B/op 7 allocs/op
BenchmarkStructPartialSuccess-8 3000000 502 ns/op 256 B/op 6 allocs/op
BenchmarkStructPartialSuccessParallel-8 10000000 225 ns/op 256 B/op 6 allocs/op
BenchmarkStructPartialFailure-8 2000000 702 ns/op 480 B/op 11 allocs/op
BenchmarkStructPartialFailureParallel-8 5000000 329 ns/op 480 B/op 11 allocs/op
BenchmarkStructExceptSuccess-8 2000000 793 ns/op 496 B/op 12 allocs/op
BenchmarkStructExceptSuccessParallel-8 10000000 193 ns/op 240 B/op 5 allocs/op
BenchmarkStructExceptFailure-8 2000000 639 ns/op 464 B/op 10 allocs/op
BenchmarkStructExceptFailureParallel-8 5000000 300 ns/op 464 B/op 10 allocs/op
BenchmarkStructSimpleCrossFieldSuccess-8 3000000 417 ns/op 72 B/op 3 allocs/op
BenchmarkStructSimpleCrossFieldSuccessParallel-8 10000000 163 ns/op 72 B/op 3 allocs/op
BenchmarkStructSimpleCrossFieldFailure-8 2000000 645 ns/op 304 B/op 8 allocs/op
BenchmarkStructSimpleCrossFieldFailureParallel-8 5000000 285 ns/op 304 B/op 8 allocs/op
BenchmarkStructSimpleCrossStructCrossFieldSuccess-8 3000000 588 ns/op 80 B/op 4 allocs/op
BenchmarkStructSimpleCrossStructCrossFieldSuccessParallel-8 10000000 221 ns/op 80 B/op 4 allocs/op
BenchmarkStructSimpleCrossStructCrossFieldFailure-8 2000000 868 ns/op 320 B/op 9 allocs/op
BenchmarkStructSimpleCrossStructCrossFieldFailureParallel-8 5000000 337 ns/op 320 B/op 9 allocs/op
BenchmarkStructSimpleSuccess-8 5000000 260 ns/op 0 B/op 0 allocs/op
BenchmarkStructSimpleSuccessParallel-8 20000000 90.6 ns/op 0 B/op 0 allocs/op
BenchmarkStructSimpleFailure-8 2000000 619 ns/op 424 B/op 9 allocs/op
BenchmarkStructSimpleFailureParallel-8 5000000 296 ns/op 424 B/op 9 allocs/op
BenchmarkStructComplexSuccess-8 1000000 1454 ns/op 128 B/op 8 allocs/op
BenchmarkStructComplexSuccessParallel-8 3000000 579 ns/op 128 B/op 8 allocs/op
BenchmarkStructComplexFailure-8 300000 4140 ns/op 3041 B/op 53 allocs/op
BenchmarkStructComplexFailureParallel-8 1000000 2127 ns/op 3041 B/op 53 allocs/op
BenchmarkOneof-8 10000000 140 ns/op 0 B/op 0 allocs/op
BenchmarkOneofParallel-8 20000000 70.1 ns/op 0 B/op 0 allocs/op
```
Complementary Software
----------------------
Here is a list of software that complements using this library either pre or post validation.
* [form](https://github.com/go-playground/form) - Decodes url.Values into Go value(s) and Encodes Go value(s) into url.Values. Dual Array and Full map support.
* [mold](https://github.com/go-playground/mold) - A general library to help modify or set data within data structures and other objects
How to Contribute
------
Make a pull request...
License
=======
Distributed under MIT License, please see license file in code for more details.
-------
Distributed under MIT License, please see license file within the code for more details.
Maintainers
-----------
This project has grown large enough that more than one person is required to properly support the community.
If you are interested in becoming a maintainer please reach out to me https://github.com/deankarn

@ -0,0 +1,39 @@
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
// MyStruct ..
type MyStruct struct {
String string `validate:"is-awesome"`
}
// use a single instance of Validate, it caches struct info
var validate *validator.Validate
func main() {
validate = validator.New()
validate.RegisterValidation("is-awesome", ValidateMyVal)
s := MyStruct{String: "awesome"}
err := validate.Struct(s)
if err != nil {
fmt.Printf("Err(s):\n%+v\n", err)
}
s.String = "not awesome"
err = validate.Struct(s)
if err != nil {
fmt.Printf("Err(s):\n%+v\n", err)
}
}
// ValidateMyVal implements validator.Func
func ValidateMyVal(fl validator.FieldLevel) bool {
return fl.Field().String() == "awesome"
}

@ -0,0 +1,51 @@
package main
import (
"database/sql"
"database/sql/driver"
"fmt"
"reflect"
"github.com/go-playground/validator/v10"
)
// DbBackedUser User struct
type DbBackedUser struct {
Name sql.NullString `validate:"required"`
Age sql.NullInt64 `validate:"required"`
}
// use a single instance of Validate, it caches struct info
var validate *validator.Validate
func main() {
validate = validator.New()
// register all sql.Null* types to use the ValidateValuer CustomTypeFunc
validate.RegisterCustomTypeFunc(ValidateValuer, sql.NullString{}, sql.NullInt64{}, sql.NullBool{}, sql.NullFloat64{})
// build object for validation
x := DbBackedUser{Name: sql.NullString{String: "", Valid: true}, Age: sql.NullInt64{Int64: 0, Valid: false}}
err := validate.Struct(x)
if err != nil {
fmt.Printf("Err(s):\n%+v\n", err)
}
}
// ValidateValuer implements validator.CustomTypeFunc
func ValidateValuer(field reflect.Value) interface{} {
if valuer, ok := field.Interface().(driver.Valuer); ok {
val, err := valuer.Value()
if err == nil {
return val
}
// handle the error how you want
}
return nil
}

@ -0,0 +1,39 @@
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
// Test ...
type Test struct {
Array []string `validate:"required,gt=0,dive,required"`
Map map[string]string `validate:"required,gt=0,dive,keys,keymax,endkeys,required,max=1000"`
}
// use a single instance of Validate, it caches struct info
var validate *validator.Validate
func main() {
validate = validator.New()
// registering alias so we can see the differences between
// map key, value validation errors
validate.RegisterAlias("keymax", "max=10")
var test Test
val(test)
test.Array = []string{""}
test.Map = map[string]string{"test > than 10": ""}
val(test)
}
func val(test Test) {
fmt.Println("testing")
err := validate.Struct(test)
fmt.Println(err)
}

@ -0,0 +1,10 @@
package main
import "github.com/gin-gonic/gin/binding"
func main() {
binding.Validator = new(defaultValidator)
// regular gin logic
}

@ -0,0 +1,55 @@
package main
import (
"reflect"
"sync"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/validator/v10"
)
type defaultValidator struct {
once sync.Once
validate *validator.Validate
}
var _ binding.StructValidator = &defaultValidator{}
func (v *defaultValidator) ValidateStruct(obj interface{}) error {
if kindOfData(obj) == reflect.Struct {
v.lazyinit()
if err := v.validate.Struct(obj); err != nil {
return err
}
}
return nil
}
func (v *defaultValidator) Engine() interface{} {
v.lazyinit()
return v.validate
}
func (v *defaultValidator) lazyinit() {
v.once.Do(func() {
v.validate = validator.New()
v.validate.SetTagName("binding")
// add any custom validations etc. here
})
}
func kindOfData(data interface{}) reflect.Kind {
value := reflect.ValueOf(data)
valueType := value.Kind()
if valueType == reflect.Ptr {
valueType = value.Elem().Kind()
}
return valueType
}

@ -0,0 +1,87 @@
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
var validate *validator.Validate
func main() {
validate = validator.New()
validateMap()
validateNestedMap()
}
func validateMap() {
user := map[string]interface{}{"name": "Arshiya Kiani", "email": "zytel3301@gmail.com"}
// Every rule will be applied to the item of the data that the offset of rule is pointing to.
// So if you have a field "email": "omitempty,required,email", the validator will apply these
// rules to offset of email in user data
rules := map[string]interface{}{"name": "required,min=8,max=32", "email": "omitempty,required,email"}
// ValidateMap will return map[string]error.
// The offset of every item in errs is the name of invalid field and the value
// is the message of error. If there was no error, ValidateMap method will
// return an EMPTY map of errors, not nil. If you want to check that
// if there was an error or not, you must check the length of the return value
errs := validate.ValidateMap(user, rules)
if len(errs) > 0 {
fmt.Println(errs)
// The user is invalid
}
// The user is valid
}
func validateNestedMap() {
data := map[string]interface{}{
"name": "Arshiya Kiani",
"email": "zytel3301@gmail.com",
"details": map[string]interface{}{
"family_members": map[string]interface{}{
"father_name": "Micheal",
"mother_name": "Hannah",
},
"salary": "1000",
"phones": []map[string]interface{}{
{
"number": "11-111-1111",
"remark": "home",
},
{
"number": "22-222-2222",
"remark": "work",
},
},
},
}
// Rules must be set as the structure as the data itself. If you want to dive into the
// map, just declare its rules as a map
rules := map[string]interface{}{
"name": "min=4,max=32",
"email": "required,email",
"details": map[string]interface{}{
"family_members": map[string]interface{}{
"father_name": "required,min=4,max=32",
"mother_name": "required,min=4,max=32",
},
"salary": "number",
"phones": map[string]interface{}{
"number": "required,min=4,max=32",
"remark": "required,min=1,max=32",
},
},
}
if len(validate.ValidateMap(data, rules)) == 0 {
// Data is valid
}
// Data is invalid
}

@ -0,0 +1,101 @@
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
// User contains user information
type User struct {
FirstName string `validate:"required"`
LastName string `validate:"required"`
Age uint8 `validate:"gte=0,lte=130"`
Email string `validate:"required,email"`
FavouriteColor string `validate:"iscolor"` // alias for 'hexcolor|rgb|rgba|hsl|hsla'
Addresses []*Address `validate:"required,dive,required"` // a person can have a home and cottage...
}
// Address houses a users address information
type Address struct {
Street string `validate:"required"`
City string `validate:"required"`
Planet string `validate:"required"`
Phone string `validate:"required"`
}
// use a single instance of Validate, it caches struct info
var validate *validator.Validate
func main() {
validate = validator.New()
validateStruct()
validateVariable()
}
func validateStruct() {
address := &Address{
Street: "Eavesdown Docks",
Planet: "Persphone",
Phone: "none",
}
user := &User{
FirstName: "Badger",
LastName: "Smith",
Age: 135,
Email: "Badger.Smith@gmail.com",
FavouriteColor: "#000-",
Addresses: []*Address{address},
}
// returns nil or ValidationErrors ( []FieldError )
err := validate.Struct(user)
if err != nil {
// this check is only needed when your code could produce
// an invalid value for validation such as interface with nil
// value most including myself do not usually have code like this.
if _, ok := err.(*validator.InvalidValidationError); ok {
fmt.Println(err)
return
}
for _, err := range err.(validator.ValidationErrors) {
fmt.Println(err.Namespace())
fmt.Println(err.Field())
fmt.Println(err.StructNamespace())
fmt.Println(err.StructField())
fmt.Println(err.Tag())
fmt.Println(err.ActualTag())
fmt.Println(err.Kind())
fmt.Println(err.Type())
fmt.Println(err.Value())
fmt.Println(err.Param())
fmt.Println()
}
// from here you can create your own error messages in whatever language you wish
return
}
// save user to database
}
func validateVariable() {
myEmail := "joeybloggs.gmail.com"
errs := validate.Var(myEmail, "required,email")
if errs != nil {
fmt.Println(errs) // output: Key: "" Error:Field validation for "" failed on the "email" tag
return
}
// email ok, move on
}

@ -0,0 +1,172 @@
package main
import (
"encoding/json"
"fmt"
"reflect"
"strings"
"github.com/go-playground/validator/v10"
)
type validationError struct {
Namespace string `json:"namespace"` // can differ when a custom TagNameFunc is registered or
Field string `json:"field"` // by passing alt name to ReportError like below
StructNamespace string `json:"structNamespace"`
StructField string `json:"structField"`
Tag string `json:"tag"`
ActualTag string `json:"actualTag"`
Kind string `json:"kind"`
Type string `json:"type"`
Value string `json:"value"`
Param string `json:"param"`
Message string `json:"message"`
}
type Gender uint
const (
Male Gender = iota + 1
Female
Intersex
)
func (gender Gender) String() string {
terms := []string{"Male", "Female", "Intersex"}
if gender < Male || gender > Intersex {
return "unknown"
}
return terms[gender]
}
// User contains user information
type User struct {
FirstName string `json:"fname"`
LastName string `json:"lname"`
Age uint8 `validate:"gte=0,lte=130"`
Email string `json:"e-mail" validate:"required,email"`
FavouriteColor string `validate:"hexcolor|rgb|rgba"`
Addresses []*Address `validate:"required,dive,required"` // a person can have a home and cottage...
Gender Gender `json:"gender" validate:"required,gender_custom_validation"`
}
// Address houses a users address information
type Address struct {
Street string `validate:"required"`
City string `validate:"required"`
Planet string `validate:"required"`
Phone string `validate:"required"`
}
// use a single instance of Validate, it caches struct info
var validate *validator.Validate
func main() {
validate = validator.New()
// register function to get tag name from json tags.
validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
if name == "-" {
return ""
}
return name
})
// register validation for 'User'
// NOTE: only have to register a non-pointer type for 'User', validator
// internally dereferences during it's type checks.
validate.RegisterStructValidation(UserStructLevelValidation, User{})
// register a custom validation for user genre on a line
// validates that an enum is within the interval
err := validate.RegisterValidation("gender_custom_validation", func(fl validator.FieldLevel) bool {
value := fl.Field().Interface().(Gender)
return value.String() != "unknown"
})
if err != nil {
fmt.Println(err)
return
}
// build 'User' info, normally posted data etc...
address := &Address{
Street: "Eavesdown Docks",
Planet: "Persphone",
Phone: "none",
City: "Unknown",
}
user := &User{
FirstName: "",
LastName: "",
Age: 45,
Email: "Badger.Smith@gmail",
FavouriteColor: "#000",
Addresses: []*Address{address},
}
// returns InvalidValidationError for bad validation input, nil or ValidationErrors ( []FieldError )
err = validate.Struct(user)
if err != nil {
// this check is only needed when your code could produce
// an invalid value for validation such as interface with nil
// value most including myself do not usually have code like this.
if _, ok := err.(*validator.InvalidValidationError); ok {
fmt.Println(err)
return
}
for _, err := range err.(validator.ValidationErrors) {
e := validationError{
Namespace: err.Namespace(),
Field: err.Field(),
StructNamespace: err.StructNamespace(),
StructField: err.StructField(),
Tag: err.Tag(),
ActualTag: err.ActualTag(),
Kind: fmt.Sprintf("%v", err.Kind()),
Type: fmt.Sprintf("%v", err.Type()),
Value: fmt.Sprintf("%v", err.Value()),
Param: err.Param(),
Message: err.Error(),
}
indent, err := json.MarshalIndent(e, "", " ")
if err != nil {
fmt.Println(err)
panic(err)
}
fmt.Println(string(indent))
}
// from here you can create your own error messages in whatever language you wish
return
}
// save user to database
}
// UserStructLevelValidation contains custom struct level validations that don't always
// make sense at the field validation level. For Example this function validates that either
// FirstName or LastName exist; could have done that with a custom field validation but then
// would have had to add it to both fields duplicating the logic + overhead, this way it's
// only validated once.
//
// NOTE: you may ask why wouldn't I just do this outside of validator, because doing this way
// hooks right into validator and you can combine with validation tags and still have a
// common error output format.
func UserStructLevelValidation(sl validator.StructLevel) {
user := sl.Current().Interface().(User)
if len(user.FirstName) == 0 && len(user.LastName) == 0 {
sl.ReportError(user.FirstName, "fname", "FirstName", "fnameorlname", "")
sl.ReportError(user.LastName, "lname", "LastName", "fnameorlname", "")
}
// plus can do more, even with different tag than "fnameorlname"
}

@ -0,0 +1,92 @@
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
type Data struct {
Name string
Email string
Details *Details
}
type Details struct {
FamilyMembers *FamilyMembers
Salary string
}
type FamilyMembers struct {
FatherName string
MotherName string
}
type Data2 struct {
Name string
Age uint32
}
var validate = validator.New()
func main() {
validateStruct()
// output
// Key: 'Data2.Name' Error:Field validation for 'Name' failed on the 'min' tag
// Key: 'Data2.Age' Error:Field validation for 'Age' failed on the 'max' tag
validateStructNested()
// output
// Key: 'Data.Name' Error:Field validation for 'Name' failed on the 'max' tag
// Key: 'Data.Details.FamilyMembers' Error:Field validation for 'FamilyMembers' failed on the 'required' tag
}
func validateStruct() {
data := Data2{
Name: "leo",
Age: 1000,
}
rules := map[string]string{
"Name": "min=4,max=6",
"Age": "min=4,max=6",
}
validate.RegisterStructValidationMapRules(rules, Data2{})
err := validate.Struct(data)
fmt.Println(err)
fmt.Println()
}
func validateStructNested() {
data := Data{
Name: "11sdfddd111",
Email: "zytel3301@mail.com",
Details: &Details{
Salary: "1000",
},
}
rules1 := map[string]string{
"Name": "min=4,max=6",
"Email": "required,email",
"Details": "required",
}
rules2 := map[string]string{
"Salary": "number",
"FamilyMembers": "required",
}
rules3 := map[string]string{
"FatherName": "required,min=4,max=32",
"MotherName": "required,min=4,max=32",
}
validate.RegisterStructValidationMapRules(rules1, Data{})
validate.RegisterStructValidationMapRules(rules2, Details{})
validate.RegisterStructValidationMapRules(rules3, FamilyMembers{})
err := validate.Struct(data)
fmt.Println(err)
}

@ -0,0 +1,129 @@
package main
import (
"fmt"
"github.com/go-playground/locales/en"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
en_translations "github.com/go-playground/validator/v10/translations/en"
)
// User contains user information
type User struct {
FirstName string `validate:"required"`
LastName string `validate:"required"`
Age uint8 `validate:"gte=0,lte=130"`
Email string `validate:"required,email"`
FavouriteColor string `validate:"iscolor"` // alias for 'hexcolor|rgb|rgba|hsl|hsla'
Addresses []*Address `validate:"required,dive,required"` // a person can have a home and cottage...
}
// Address houses a users address information
type Address struct {
Street string `validate:"required"`
City string `validate:"required"`
Planet string `validate:"required"`
Phone string `validate:"required"`
}
// use a single instance , it caches struct info
var (
uni *ut.UniversalTranslator
validate *validator.Validate
)
func main() {
// NOTE: ommitting allot of error checking for brevity
en := en.New()
uni = ut.New(en, en)
// this is usually know or extracted from http 'Accept-Language' header
// also see uni.FindTranslator(...)
trans, _ := uni.GetTranslator("en")
validate = validator.New()
en_translations.RegisterDefaultTranslations(validate, trans)
translateAll(trans)
translateIndividual(trans)
translateOverride(trans) // yep you can specify your own in whatever locale you want!
}
func translateAll(trans ut.Translator) {
type User struct {
Username string `validate:"required"`
Tagline string `validate:"required,lt=10"`
Tagline2 string `validate:"required,gt=1"`
}
user := User{
Username: "Joeybloggs",
Tagline: "This tagline is way too long.",
Tagline2: "1",
}
err := validate.Struct(user)
if err != nil {
// translate all error at once
errs := err.(validator.ValidationErrors)
// returns a map with key = namespace & value = translated error
// NOTICE: 2 errors are returned and you'll see something surprising
// translations are i18n aware!!!!
// eg. '10 characters' vs '1 character'
fmt.Println(errs.Translate(trans))
}
}
func translateIndividual(trans ut.Translator) {
type User struct {
Username string `validate:"required"`
}
var user User
err := validate.Struct(user)
if err != nil {
errs := err.(validator.ValidationErrors)
for _, e := range errs {
// can translate each error one at a time.
fmt.Println(e.Translate(trans))
}
}
}
func translateOverride(trans ut.Translator) {
validate.RegisterTranslation("required", trans, func(ut ut.Translator) error {
return ut.Add("required", "{0} must have a value!", true) // see universal-translator for details
}, func(ut ut.Translator, fe validator.FieldError) string {
t, _ := ut.T("required", fe.Field())
return t
})
type User struct {
Username string `validate:"required"`
}
var user User
err := validate.Struct(user)
if err != nil {
errs := err.(validator.ValidationErrors)
for _, e := range errs {
// can translate each error one at a time.
fmt.Println(e.Translate(trans))
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,327 @@
package validator
import (
"fmt"
"reflect"
"strings"
"sync"
"sync/atomic"
)
type tagType uint8
const (
typeDefault tagType = iota
typeOmitEmpty
typeIsDefault
typeNoStructLevel
typeStructOnly
typeDive
typeOr
typeKeys
typeEndKeys
)
const (
invalidValidation = "Invalid validation tag on field '%s'"
undefinedValidation = "Undefined validation function '%s' on field '%s'"
keysTagNotDefined = "'" + endKeysTag + "' tag encountered without a corresponding '" + keysTag + "' tag"
)
type structCache struct {
lock sync.Mutex
m atomic.Value // map[reflect.Type]*cStruct
}
func (sc *structCache) Get(key reflect.Type) (c *cStruct, found bool) {
c, found = sc.m.Load().(map[reflect.Type]*cStruct)[key]
return
}
func (sc *structCache) Set(key reflect.Type, value *cStruct) {
m := sc.m.Load().(map[reflect.Type]*cStruct)
nm := make(map[reflect.Type]*cStruct, len(m)+1)
for k, v := range m {
nm[k] = v
}
nm[key] = value
sc.m.Store(nm)
}
type tagCache struct {
lock sync.Mutex
m atomic.Value // map[string]*cTag
}
func (tc *tagCache) Get(key string) (c *cTag, found bool) {
c, found = tc.m.Load().(map[string]*cTag)[key]
return
}
func (tc *tagCache) Set(key string, value *cTag) {
m := tc.m.Load().(map[string]*cTag)
nm := make(map[string]*cTag, len(m)+1)
for k, v := range m {
nm[k] = v
}
nm[key] = value
tc.m.Store(nm)
}
type cStruct struct {
name string
fields []*cField
fn StructLevelFuncCtx
}
type cField struct {
idx int
name string
altName string
namesEqual bool
cTags *cTag
}
type cTag struct {
tag string
aliasTag string
actualAliasTag string
param string
keys *cTag // only populated when using tag's 'keys' and 'endkeys' for map key validation
next *cTag
fn FuncCtx
typeof tagType
hasTag bool
hasAlias bool
hasParam bool // true if parameter used eg. eq= where the equal sign has been set
isBlockEnd bool // indicates the current tag represents the last validation in the block
runValidationWhenNil bool
}
func (v *Validate) extractStructCache(current reflect.Value, sName string) *cStruct {
v.structCache.lock.Lock()
defer v.structCache.lock.Unlock() // leave as defer! because if inner panics, it will never get unlocked otherwise!
typ := current.Type()
// could have been multiple trying to access, but once first is done this ensures struct
// isn't parsed again.
cs, ok := v.structCache.Get(typ)
if ok {
return cs
}
cs = &cStruct{name: sName, fields: make([]*cField, 0), fn: v.structLevelFuncs[typ]}
numFields := current.NumField()
rules := v.rules[typ]
var ctag *cTag
var fld reflect.StructField
var tag string
var customName string
for i := 0; i < numFields; i++ {
fld = typ.Field(i)
if !fld.Anonymous && len(fld.PkgPath) > 0 {
continue
}
if rtag, ok := rules[fld.Name]; ok {
tag = rtag
} else {
tag = fld.Tag.Get(v.tagName)
}
if tag == skipValidationTag {
continue
}
customName = fld.Name
if v.hasTagNameFunc {
name := v.tagNameFunc(fld)
if len(name) > 0 {
customName = name
}
}
// NOTE: cannot use shared tag cache, because tags may be equal, but things like alias may be different
// and so only struct level caching can be used instead of combined with Field tag caching
if len(tag) > 0 {
ctag, _ = v.parseFieldTagsRecursive(tag, fld.Name, "", false)
} else {
// even if field doesn't have validations need cTag for traversing to potential inner/nested
// elements of the field.
ctag = new(cTag)
}
cs.fields = append(cs.fields, &cField{
idx: i,
name: fld.Name,
altName: customName,
cTags: ctag,
namesEqual: fld.Name == customName,
})
}
v.structCache.Set(typ, cs)
return cs
}
func (v *Validate) parseFieldTagsRecursive(tag string, fieldName string, alias string, hasAlias bool) (firstCtag *cTag, current *cTag) {
var t string
noAlias := len(alias) == 0
tags := strings.Split(tag, tagSeparator)
for i := 0; i < len(tags); i++ {
t = tags[i]
if noAlias {
alias = t
}
// check map for alias and process new tags, otherwise process as usual
if tagsVal, found := v.aliases[t]; found {
if i == 0 {
firstCtag, current = v.parseFieldTagsRecursive(tagsVal, fieldName, t, true)
} else {
next, curr := v.parseFieldTagsRecursive(tagsVal, fieldName, t, true)
current.next, current = next, curr
}
continue
}
var prevTag tagType
if i == 0 {
current = &cTag{aliasTag: alias, hasAlias: hasAlias, hasTag: true, typeof: typeDefault}
firstCtag = current
} else {
prevTag = current.typeof
current.next = &cTag{aliasTag: alias, hasAlias: hasAlias, hasTag: true}
current = current.next
}
switch t {
case diveTag:
current.typeof = typeDive
continue
case keysTag:
current.typeof = typeKeys
if i == 0 || prevTag != typeDive {
panic(fmt.Sprintf("'%s' tag must be immediately preceded by the '%s' tag", keysTag, diveTag))
}
current.typeof = typeKeys
// need to pass along only keys tag
// need to increment i to skip over the keys tags
b := make([]byte, 0, 64)
i++
for ; i < len(tags); i++ {
b = append(b, tags[i]...)
b = append(b, ',')
if tags[i] == endKeysTag {
break
}
}
current.keys, _ = v.parseFieldTagsRecursive(string(b[:len(b)-1]), fieldName, "", false)
continue
case endKeysTag:
current.typeof = typeEndKeys
// if there are more in tags then there was no keysTag defined
// and an error should be thrown
if i != len(tags)-1 {
panic(keysTagNotDefined)
}
return
case omitempty:
current.typeof = typeOmitEmpty
continue
case structOnlyTag:
current.typeof = typeStructOnly
continue
case noStructLevelTag:
current.typeof = typeNoStructLevel
continue
default:
if t == isdefault {
current.typeof = typeIsDefault
}
// if a pipe character is needed within the param you must use the utf8Pipe representation "0x7C"
orVals := strings.Split(t, orSeparator)
for j := 0; j < len(orVals); j++ {
vals := strings.SplitN(orVals[j], tagKeySeparator, 2)
if noAlias {
alias = vals[0]
current.aliasTag = alias
} else {
current.actualAliasTag = t
}
if j > 0 {
current.next = &cTag{aliasTag: alias, actualAliasTag: current.actualAliasTag, hasAlias: hasAlias, hasTag: true}
current = current.next
}
current.hasParam = len(vals) > 1
current.tag = vals[0]
if len(current.tag) == 0 {
panic(strings.TrimSpace(fmt.Sprintf(invalidValidation, fieldName)))
}
if wrapper, ok := v.validations[current.tag]; ok {
current.fn = wrapper.fn
current.runValidationWhenNil = wrapper.runValidatinOnNil
} else {
panic(strings.TrimSpace(fmt.Sprintf(undefinedValidation, current.tag, fieldName)))
}
if len(orVals) > 1 {
current.typeof = typeOr
}
if len(vals) > 1 {
current.param = strings.Replace(strings.Replace(vals[1], utf8HexComma, ",", -1), utf8Pipe, "|", -1)
}
}
current.isBlockEnd = true
}
}
return
}
func (v *Validate) fetchCacheTag(tag string) *cTag {
// find cached tag
ctag, found := v.tagCache.Get(tag)
if !found {
v.tagCache.lock.Lock()
defer v.tagCache.lock.Unlock()
// could have been multiple trying to access, but once first is done this ensures tag
// isn't parsed again.
ctag, found = v.tagCache.Get(tag)
if !found {
ctag, _ = v.parseFieldTagsRecursive(tag, "", "", false)
v.tagCache.Set(tag, ctag)
}
}
return ctag
}

File diff suppressed because it is too large Load Diff

@ -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,
}

1663
doc.go

File diff suppressed because it is too large Load Diff

@ -0,0 +1,272 @@
package validator
import (
"bytes"
"fmt"
"reflect"
"strings"
ut "github.com/go-playground/universal-translator"
)
const (
fieldErrMsg = "Key: '%s' Error:Field validation for '%s' failed on the '%s' tag"
)
// ValidationErrorsTranslations is the translation return type
type ValidationErrorsTranslations map[string]string
// InvalidValidationError describes an invalid argument passed to
// `Struct`, `StructExcept`, StructPartial` or `Field`
type InvalidValidationError struct {
Type reflect.Type
}
// Error returns InvalidValidationError message
func (e *InvalidValidationError) Error() string {
if e.Type == nil {
return "validator: (nil)"
}
return "validator: (nil " + e.Type.String() + ")"
}
// ValidationErrors is an array of FieldError's
// for use in custom error messages post validation.
type ValidationErrors []FieldError
// Error is intended for use in development + debugging and not intended to be a production error message.
// It allows ValidationErrors to subscribe to the Error interface.
// All information to create an error message specific to your application is contained within
// the FieldError found within the ValidationErrors array
func (ve ValidationErrors) Error() string {
buff := bytes.NewBufferString("")
for i := 0; i < len(ve); i++ {
buff.WriteString(ve[i].Error())
buff.WriteString("\n")
}
return strings.TrimSpace(buff.String())
}
// Translate translates all of the ValidationErrors
func (ve ValidationErrors) Translate(ut ut.Translator) ValidationErrorsTranslations {
trans := make(ValidationErrorsTranslations)
var fe *fieldError
for i := 0; i < len(ve); i++ {
fe = ve[i].(*fieldError)
// // in case an Anonymous struct was used, ensure that the key
// // would be 'Username' instead of ".Username"
// if len(fe.ns) > 0 && fe.ns[:1] == "." {
// trans[fe.ns[1:]] = fe.Translate(ut)
// continue
// }
trans[fe.ns] = fe.Translate(ut)
}
return trans
}
// FieldError contains all functions to get error details
type FieldError interface {
// Tag returns the validation tag that failed. if the
// validation was an alias, this will return the
// alias name and not the underlying tag that failed.
//
// eg. alias "iscolor": "hexcolor|rgb|rgba|hsl|hsla"
// will return "iscolor"
Tag() string
// ActualTag returns the validation tag that failed, even if an
// alias the actual tag within the alias will be returned.
// If an 'or' validation fails the entire or will be returned.
//
// eg. alias "iscolor": "hexcolor|rgb|rgba|hsl|hsla"
// will return "hexcolor|rgb|rgba|hsl|hsla"
ActualTag() string
// Namespace returns the namespace for the field error, with the tag
// name taking precedence over the field's actual name.
//
// eg. JSON name "User.fname"
//
// See StructNamespace() for a version that returns actual names.
//
// NOTE: this field can be blank when validating a single primitive field
// using validate.Field(...) as there is no way to extract it's name
Namespace() string
// StructNamespace returns the namespace for the field error, with the field's
// actual name.
//
// eq. "User.FirstName" see Namespace for comparison
//
// NOTE: this field can be blank when validating a single primitive field
// using validate.Field(...) as there is no way to extract its name
StructNamespace() string
// Field returns the fields name with the tag name taking precedence over the
// field's actual name.
//
// eq. JSON name "fname"
// see StructField for comparison
Field() string
// StructField returns the field's actual name from the struct, when able to determine.
//
// eq. "FirstName"
// see Field for comparison
StructField() string
// Value returns the actual field's value in case needed for creating the error
// message
Value() interface{}
// Param returns the param value, in string form for comparison; this will also
// help with generating an error message
Param() string
// Kind returns the Field's reflect Kind
//
// eg. time.Time's kind is a struct
Kind() reflect.Kind
// Type returns the Field's reflect Type
//
// eg. time.Time's type is time.Time
Type() reflect.Type
// Translate returns the FieldError's translated error
// from the provided 'ut.Translator' and registered 'TranslationFunc'
//
// NOTE: if no registered translator can be found it returns the same as
// calling fe.Error()
Translate(ut ut.Translator) string
// Error returns the FieldError's message
Error() string
}
// compile time interface checks
var _ FieldError = new(fieldError)
var _ error = new(fieldError)
// fieldError contains a single field's validation error along
// with other properties that may be needed for error message creation
// it complies with the FieldError interface
type fieldError struct {
v *Validate
tag string
actualTag string
ns string
structNs string
fieldLen uint8
structfieldLen uint8
value interface{}
param string
kind reflect.Kind
typ reflect.Type
}
// Tag returns the validation tag that failed.
func (fe *fieldError) Tag() string {
return fe.tag
}
// ActualTag returns the validation tag that failed, even if an
// alias the actual tag within the alias will be returned.
func (fe *fieldError) ActualTag() string {
return fe.actualTag
}
// Namespace returns the namespace for the field error, with the tag
// name taking precedence over the field's actual name.
func (fe *fieldError) Namespace() string {
return fe.ns
}
// StructNamespace returns the namespace for the field error, with the field's
// actual name.
func (fe *fieldError) StructNamespace() string {
return fe.structNs
}
// Field returns the field's name with the tag name taking precedence over the
// field's actual name.
func (fe *fieldError) Field() string {
return fe.ns[len(fe.ns)-int(fe.fieldLen):]
// // return fe.field
// fld := fe.ns[len(fe.ns)-int(fe.fieldLen):]
// log.Println("FLD:", fld)
// if len(fld) > 0 && fld[:1] == "." {
// return fld[1:]
// }
// return fld
}
// StructField returns the field's actual name from the struct, when able to determine.
func (fe *fieldError) StructField() string {
// return fe.structField
return fe.structNs[len(fe.structNs)-int(fe.structfieldLen):]
}
// Value returns the actual field's value in case needed for creating the error
// message
func (fe *fieldError) Value() interface{} {
return fe.value
}
// Param returns the param value, in string form for comparison; this will
// also help with generating an error message
func (fe *fieldError) Param() string {
return fe.param
}
// Kind returns the Field's reflect Kind
func (fe *fieldError) Kind() reflect.Kind {
return fe.kind
}
// Type returns the Field's reflect Type
func (fe *fieldError) Type() reflect.Type {
return fe.typ
}
// Error returns the fieldError's error message
func (fe *fieldError) Error() string {
return fmt.Sprintf(fieldErrMsg, fe.ns, fe.Field(), fe.tag)
}
// Translate returns the FieldError's translated error
// from the provided 'ut.Translator' and registered 'TranslationFunc'
//
// NOTE: if no registered translation can be found, it returns the original
// untranslated error message.
func (fe *fieldError) Translate(ut ut.Translator) string {
m, ok := fe.v.transTagFunc[ut]
if !ok {
return fe.Error()
}
fn, ok := m[fe.tag]
if !ok {
return fe.Error()
}
return fn(ut, fe)
}

@ -0,0 +1,120 @@
package validator
import "reflect"
// FieldLevel contains all the information and helper functions
// to validate a field
type FieldLevel interface {
// Top returns the top level struct, if any
Top() reflect.Value
// Parent returns the current fields parent struct, if any or
// the comparison value if called 'VarWithValue'
Parent() reflect.Value
// Field returns current field for validation
Field() reflect.Value
// FieldName returns the field's name with the tag
// name taking precedence over the fields actual name.
FieldName() string
// StructFieldName returns the struct field's name
StructFieldName() string
// Param returns param for validation against current field
Param() string
// GetTag returns the current validations tag name
GetTag() string
// ExtractType gets the actual underlying type of field value.
// It will dive into pointers, customTypes and return you the
// underlying value and it's kind.
ExtractType(field reflect.Value) (value reflect.Value, kind reflect.Kind, nullable bool)
// GetStructFieldOK traverses the parent struct to retrieve a specific field denoted by the provided namespace
// in the param and returns the field, field kind and whether is was successful in retrieving
// the field at all.
//
// NOTE: when not successful ok will be false, this can happen when a nested struct is nil and so the field
// could not be retrieved because it didn't exist.
//
// Deprecated: Use GetStructFieldOK2() instead which also return if the value is nullable.
GetStructFieldOK() (reflect.Value, reflect.Kind, bool)
// GetStructFieldOKAdvanced is the same as GetStructFieldOK except that it accepts the parent struct to start looking for
// the field and namespace allowing more extensibility for validators.
//
// Deprecated: Use GetStructFieldOKAdvanced2() instead which also return if the value is nullable.
GetStructFieldOKAdvanced(val reflect.Value, namespace string) (reflect.Value, reflect.Kind, bool)
// GetStructFieldOK2 traverses the parent struct to retrieve a specific field denoted by the provided namespace
// in the param and returns the field, field kind, if it's a nullable type and whether is was successful in retrieving
// the field at all.
//
// NOTE: when not successful ok will be false, this can happen when a nested struct is nil and so the field
// could not be retrieved because it didn't exist.
GetStructFieldOK2() (reflect.Value, reflect.Kind, bool, bool)
// GetStructFieldOKAdvanced2 is the same as GetStructFieldOK except that it accepts the parent struct to start looking for
// the field and namespace allowing more extensibility for validators.
GetStructFieldOKAdvanced2(val reflect.Value, namespace string) (reflect.Value, reflect.Kind, bool, bool)
}
var _ FieldLevel = new(validate)
// Field returns current field for validation
func (v *validate) Field() reflect.Value {
return v.flField
}
// FieldName returns the field's name with the tag
// name taking precedence over the fields actual name.
func (v *validate) FieldName() string {
return v.cf.altName
}
// GetTag returns the current validations tag name
func (v *validate) GetTag() string {
return v.ct.tag
}
// StructFieldName returns the struct field's name
func (v *validate) StructFieldName() string {
return v.cf.name
}
// Param returns param for validation against current field
func (v *validate) Param() string {
return v.ct.param
}
// GetStructFieldOK returns Param returns param for validation against current field
//
// Deprecated: Use GetStructFieldOK2() instead which also return if the value is nullable.
func (v *validate) GetStructFieldOK() (reflect.Value, reflect.Kind, bool) {
current, kind, _, found := v.getStructFieldOKInternal(v.slflParent, v.ct.param)
return current, kind, found
}
// GetStructFieldOKAdvanced is the same as GetStructFieldOK except that it accepts the parent struct to start looking for
// the field and namespace allowing more extensibility for validators.
//
// Deprecated: Use GetStructFieldOKAdvanced2() instead which also return if the value is nullable.
func (v *validate) GetStructFieldOKAdvanced(val reflect.Value, namespace string) (reflect.Value, reflect.Kind, bool) {
current, kind, _, found := v.GetStructFieldOKAdvanced2(val, namespace)
return current, kind, found
}
// GetStructFieldOK2 returns Param returns param for validation against current field
func (v *validate) GetStructFieldOK2() (reflect.Value, reflect.Kind, bool, bool) {
return v.getStructFieldOKInternal(v.slflParent, v.ct.param)
}
// GetStructFieldOKAdvanced2 is the same as GetStructFieldOK except that it accepts the parent struct to start looking for
// the field and namespace allowing more extensibility for validators.
func (v *validate) GetStructFieldOKAdvanced2(val reflect.Value, namespace string) (reflect.Value, reflect.Kind, bool, bool) {
return v.getStructFieldOKInternal(val, namespace)
}

@ -0,0 +1,14 @@
module github.com/go-playground/validator/v10
go 1.18
require (
github.com/go-playground/assert/v2 v2.2.0
github.com/go-playground/locales v0.14.1
github.com/go-playground/universal-translator v0.18.1
github.com/leodido/go-urn v1.2.2
golang.org/x/crypto v0.7.0
golang.org/x/text v0.8.0
)
require golang.org/x/sys v0.6.0 // indirect

@ -0,0 +1,31 @@
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.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/leodido/go-urn v1.2.2 h1:7z68G0FCGvDk646jz1AelTYNYWrTNm0bEcFAo147wt4=
github.com/leodido/go-urn v1.2.2/go.mod h1:kUaIbLZWttglzwNuG0pgsh5vuV6u2YcGBYz1hIPjtOQ=
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/rwtodd/Go.Sed v0.0.0-20210816025313-55464686f9ef/go.mod h1:8AEUvGVi2uQ5b24BIhcr0GCcpd/RNAFWaN2CJFrWIIQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

@ -0,0 +1,25 @@
package validators
import (
"reflect"
"strings"
"github.com/go-playground/validator/v10"
)
// NotBlank is the validation function for validating if the current field
// has a value or length greater than zero, or is not a space only string.
func NotBlank(fl validator.FieldLevel) bool {
field := fl.Field()
switch field.Kind() {
case reflect.String:
return len(strings.Trim(strings.TrimSpace(field.String()), "\x1c\x1d\x1e\x1f")) > 0
case reflect.Chan, reflect.Map, reflect.Slice, reflect.Array:
return field.Len() > 0
case reflect.Ptr, reflect.Interface, reflect.Func:
return !field.IsNil()
default:
return field.IsValid() && field.Interface() != reflect.Zero(field.Type()).Interface()
}
}

@ -0,0 +1,65 @@
package validators
import (
"testing"
"github.com/go-playground/assert/v2"
"github.com/go-playground/validator/v10"
)
type test struct {
String string `validate:"notblank"`
Array []int `validate:"notblank"`
Pointer *int `validate:"notblank"`
Number int `validate:"notblank"`
Interface interface{} `validate:"notblank"`
Func func() `validate:"notblank"`
}
func TestNotBlank(t *testing.T) {
v := validator.New()
err := v.RegisterValidation("notblank", NotBlank)
assert.Equal(t, nil, err)
// Errors
var x *int
invalid := test{
String: " \x1c\x1d\x1e\x1f\r\n",
Array: []int{},
Pointer: x,
Number: 0,
Interface: nil,
Func: nil,
}
fieldsWithError := []string{
"String",
"Array",
"Pointer",
"Number",
"Interface",
"Func",
}
errors := v.Struct(invalid).(validator.ValidationErrors)
var fields []string
for _, err := range errors {
fields = append(fields, err.Field())
}
assert.Equal(t, fieldsWithError, fields)
// No errors
y := 1
x = &y
valid := test{
String: "str",
Array: []int{1},
Pointer: x,
Number: 1,
Interface: "value",
Func: func() {},
}
err = v.Struct(valid)
assert.Equal(t, nil, err)
}

@ -0,0 +1,173 @@
package validator
import "regexp"
var postCodePatternDict = map[string]string{
"GB": `^GIR[ ]?0AA|((AB|AL|B|BA|BB|BD|BH|BL|BN|BR|BS|BT|CA|CB|CF|CH|CM|CO|CR|CT|CV|CW|DA|DD|DE|DG|DH|DL|DN|DT|DY|E|EC|EH|EN|EX|FK|FY|G|GL|GY|GU|HA|HD|HG|HP|HR|HS|HU|HX|IG|IM|IP|IV|JE|KA|KT|KW|KY|L|LA|LD|LE|LL|LN|LS|LU|M|ME|MK|ML|N|NE|NG|NN|NP|NR|NW|OL|OX|PA|PE|PH|PL|PO|PR|RG|RH|RM|S|SA|SE|SG|SK|SL|SM|SN|SO|SP|SR|SS|ST|SW|SY|TA|TD|TF|TN|TQ|TR|TS|TW|UB|W|WA|WC|WD|WF|WN|WR|WS|WV|YO|ZE)(\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}))|BFPO[ ]?\d{1,4}$`,
"JE": `^JE\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}$`,
"GG": `^GY\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}$`,
"IM": `^IM\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}$`,
"US": `^\d{5}([ \-]\d{4})?$`,
"CA": `^[ABCEGHJKLMNPRSTVXY]\d[ABCEGHJ-NPRSTV-Z][ ]?\d[ABCEGHJ-NPRSTV-Z]\d$`,
"DE": `^\d{5}$`,
"JP": `^\d{3}-\d{4}$`,
"FR": `^\d{2}[ ]?\d{3}$`,
"AU": `^\d{4}$`,
"IT": `^\d{5}$`,
"CH": `^\d{4}$`,
"AT": `^\d{4}$`,
"ES": `^\d{5}$`,
"NL": `^\d{4}[ ]?[A-Z]{2}$`,
"BE": `^\d{4}$`,
"DK": `^\d{4}$`,
"SE": `^\d{3}[ ]?\d{2}$`,
"NO": `^\d{4}$`,
"BR": `^\d{5}[\-]?\d{3}$`,
"PT": `^\d{4}([\-]\d{3})?$`,
"FI": `^\d{5}$`,
"AX": `^22\d{3}$`,
"KR": `^\d{3}[\-]\d{3}$`,
"CN": `^\d{6}$`,
"TW": `^\d{3}(\d{2})?$`,
"SG": `^\d{6}$`,
"DZ": `^\d{5}$`,
"AD": `^AD\d{3}$`,
"AR": `^([A-HJ-NP-Z])?\d{4}([A-Z]{3})?$`,
"AM": `^(37)?\d{4}$`,
"AZ": `^\d{4}$`,
"BH": `^((1[0-2]|[2-9])\d{2})?$`,
"BD": `^\d{4}$`,
"BB": `^(BB\d{5})?$`,
"BY": `^\d{6}$`,
"BM": `^[A-Z]{2}[ ]?[A-Z0-9]{2}$`,
"BA": `^\d{5}$`,
"IO": `^BBND 1ZZ$`,
"BN": `^[A-Z]{2}[ ]?\d{4}$`,
"BG": `^\d{4}$`,
"KH": `^\d{5}$`,
"CV": `^\d{4}$`,
"CL": `^\d{7}$`,
"CR": `^\d{4,5}|\d{3}-\d{4}$`,
"HR": `^\d{5}$`,
"CY": `^\d{4}$`,
"CZ": `^\d{3}[ ]?\d{2}$`,
"DO": `^\d{5}$`,
"EC": `^([A-Z]\d{4}[A-Z]|(?:[A-Z]{2})?\d{6})?$`,
"EG": `^\d{5}$`,
"EE": `^\d{5}$`,
"FO": `^\d{3}$`,
"GE": `^\d{4}$`,
"GR": `^\d{3}[ ]?\d{2}$`,
"GL": `^39\d{2}$`,
"GT": `^\d{5}$`,
"HT": `^\d{4}$`,
"HN": `^(?:\d{5})?$`,
"HU": `^\d{4}$`,
"IS": `^\d{3}$`,
"IN": `^\d{6}$`,
"ID": `^\d{5}$`,
"IL": `^\d{5}$`,
"JO": `^\d{5}$`,
"KZ": `^\d{6}$`,
"KE": `^\d{5}$`,
"KW": `^\d{5}$`,
"LA": `^\d{5}$`,
"LV": `^\d{4}$`,
"LB": `^(\d{4}([ ]?\d{4})?)?$`,
"LI": `^(948[5-9])|(949[0-7])$`,
"LT": `^\d{5}$`,
"LU": `^\d{4}$`,
"MK": `^\d{4}$`,
"MY": `^\d{5}$`,
"MV": `^\d{5}$`,
"MT": `^[A-Z]{3}[ ]?\d{2,4}$`,
"MU": `^(\d{3}[A-Z]{2}\d{3})?$`,
"MX": `^\d{5}$`,
"MD": `^\d{4}$`,
"MC": `^980\d{2}$`,
"MA": `^\d{5}$`,
"NP": `^\d{5}$`,
"NZ": `^\d{4}$`,
"NI": `^((\d{4}-)?\d{3}-\d{3}(-\d{1})?)?$`,
"NG": `^(\d{6})?$`,
"OM": `^(PC )?\d{3}$`,
"PK": `^\d{5}$`,
"PY": `^\d{4}$`,
"PH": `^\d{4}$`,
"PL": `^\d{2}-\d{3}$`,
"PR": `^00[679]\d{2}([ \-]\d{4})?$`,
"RO": `^\d{6}$`,
"RU": `^\d{6}$`,
"SM": `^4789\d$`,
"SA": `^\d{5}$`,
"SN": `^\d{5}$`,
"SK": `^\d{3}[ ]?\d{2}$`,
"SI": `^\d{4}$`,
"ZA": `^\d{4}$`,
"LK": `^\d{5}$`,
"TJ": `^\d{6}$`,
"TH": `^\d{5}$`,
"TN": `^\d{4}$`,
"TR": `^\d{5}$`,
"TM": `^\d{6}$`,
"UA": `^\d{5}$`,
"UY": `^\d{5}$`,
"UZ": `^\d{6}$`,
"VA": `^00120$`,
"VE": `^\d{4}$`,
"ZM": `^\d{5}$`,
"AS": `^96799$`,
"CC": `^6799$`,
"CK": `^\d{4}$`,
"RS": `^\d{6}$`,
"ME": `^8\d{4}$`,
"CS": `^\d{5}$`,
"YU": `^\d{5}$`,
"CX": `^6798$`,
"ET": `^\d{4}$`,
"FK": `^FIQQ 1ZZ$`,
"NF": `^2899$`,
"FM": `^(9694[1-4])([ \-]\d{4})?$`,
"GF": `^9[78]3\d{2}$`,
"GN": `^\d{3}$`,
"GP": `^9[78][01]\d{2}$`,
"GS": `^SIQQ 1ZZ$`,
"GU": `^969[123]\d([ \-]\d{4})?$`,
"GW": `^\d{4}$`,
"HM": `^\d{4}$`,
"IQ": `^\d{5}$`,
"KG": `^\d{6}$`,
"LR": `^\d{4}$`,
"LS": `^\d{3}$`,
"MG": `^\d{3}$`,
"MH": `^969[67]\d([ \-]\d{4})?$`,
"MN": `^\d{6}$`,
"MP": `^9695[012]([ \-]\d{4})?$`,
"MQ": `^9[78]2\d{2}$`,
"NC": `^988\d{2}$`,
"NE": `^\d{4}$`,
"VI": `^008(([0-4]\d)|(5[01]))([ \-]\d{4})?$`,
"VN": `^[0-9]{1,6}$`,
"PF": `^987\d{2}$`,
"PG": `^\d{3}$`,
"PM": `^9[78]5\d{2}$`,
"PN": `^PCRN 1ZZ$`,
"PW": `^96940$`,
"RE": `^9[78]4\d{2}$`,
"SH": `^(ASCN|STHL) 1ZZ$`,
"SJ": `^\d{4}$`,
"SO": `^\d{5}$`,
"SZ": `^[HLMS]\d{3}$`,
"TC": `^TKCA 1ZZ$`,
"WF": `^986\d{2}$`,
"XK": `^\d{5}$`,
"YT": `^976\d{2}$`,
}
var postCodeRegexDict = map[string]*regexp.Regexp{}
func init() {
for countryCode, pattern := range postCodePatternDict {
postCodeRegexDict[countryCode] = regexp.MustCompile(pattern)
}
}

@ -3,34 +3,135 @@ package validator
import "regexp"
const (
alphaRegexString = "^[a-zA-Z]+$"
alphaNumericRegexString = "^[a-zA-Z0-9]+$"
numericRegexString = "^[-+]?[0-9]+(?:\\.[0-9]+)?$"
numberRegexString = "^[0-9]+$"
hexadecimalRegexString = "^[0-9a-fA-F]+$"
hexcolorRegexString = "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$"
rgbRegexString = "^rgb\\(\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*\\)$"
rgbaRegexString = "^rgba\\(\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*((0.[1-9]*)|[01])\\s*\\)$"
hslRegexString = "^hsl\\(\\s*(0|[1-9]\\d?|[12]\\d\\d|3[0-5]\\d|360)\\s*,\\s*((0|[1-9]\\d?|100)%)\\s*,\\s*((0|[1-9]\\d?|100)%)\\s*\\)$"
hslaRegexString = "^hsla\\(\\s*(0|[1-9]\\d?|[12]\\d\\d|3[0-5]\\d|360)\\s*,\\s*((0|[1-9]\\d?|100)%)\\s*,\\s*((0|[1-9]\\d?|100)%)\\s*,\\s*((0.[1-9]*)|[01])\\s*\\)$"
emailRegexString = "^(((([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+(\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.)+(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.?$"
alphaRegexString = "^[a-zA-Z]+$"
alphaNumericRegexString = "^[a-zA-Z0-9]+$"
alphaUnicodeRegexString = "^[\\p{L}]+$"
alphaUnicodeNumericRegexString = "^[\\p{L}\\p{N}]+$"
numericRegexString = "^[-+]?[0-9]+(?:\\.[0-9]+)?$"
numberRegexString = "^[0-9]+$"
hexadecimalRegexString = "^(0[xX])?[0-9a-fA-F]+$"
hexColorRegexString = "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$"
rgbRegexString = "^rgb\\(\\s*(?:(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])|(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%)\\s*\\)$"
rgbaRegexString = "^rgba\\(\\s*(?:(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])|(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%)\\s*,\\s*(?:(?:0.[1-9]*)|[01])\\s*\\)$"
hslRegexString = "^hsl\\(\\s*(?:0|[1-9]\\d?|[12]\\d\\d|3[0-5]\\d|360)\\s*,\\s*(?:(?:0|[1-9]\\d?|100)%)\\s*,\\s*(?:(?:0|[1-9]\\d?|100)%)\\s*\\)$"
hslaRegexString = "^hsla\\(\\s*(?:0|[1-9]\\d?|[12]\\d\\d|3[0-5]\\d|360)\\s*,\\s*(?:(?:0|[1-9]\\d?|100)%)\\s*,\\s*(?:(?:0|[1-9]\\d?|100)%)\\s*,\\s*(?:(?:0.[1-9]*)|[01])\\s*\\)$"
emailRegexString = "^(?:(?:(?:(?:[a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+(?:\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+)*)|(?:(?:\\x22)(?:(?:(?:(?:\\x20|\\x09)*(?:\\x0d\\x0a))?(?:\\x20|\\x09)+)?(?:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(?:(?:[\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}]))))*(?:(?:(?:\\x20|\\x09)*(?:\\x0d\\x0a))?(\\x20|\\x09)+)?(?:\\x22))))@(?:(?:(?:[a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(?:(?:[a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])(?:[a-zA-Z]|\\d|-|\\.|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*(?:[a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.)+(?:(?:[a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(?:(?:[a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])(?:[a-zA-Z]|\\d|-|\\.|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*(?:[a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.?$"
e164RegexString = "^\\+[1-9]?[0-9]{7,14}$"
base64RegexString = "^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+\\/]{4})$"
base64URLRegexString = "^(?:[A-Za-z0-9-_]{4})*(?:[A-Za-z0-9-_]{2}==|[A-Za-z0-9-_]{3}=|[A-Za-z0-9-_]{4})$"
base64RawURLRegexString = "^(?:[A-Za-z0-9-_]{4})*(?:[A-Za-z0-9-_]{2,4})$"
iSBN10RegexString = "^(?:[0-9]{9}X|[0-9]{10})$"
iSBN13RegexString = "^(?:(?:97(?:8|9))[0-9]{10})$"
uUID3RegexString = "^[0-9a-f]{8}-[0-9a-f]{4}-3[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$"
uUID4RegexString = "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
uUID5RegexString = "^[0-9a-f]{8}-[0-9a-f]{4}-5[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
uUIDRegexString = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
uUID3RFC4122RegexString = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-3[0-9a-fA-F]{3}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"
uUID4RFC4122RegexString = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
uUID5RFC4122RegexString = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-5[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
uUIDRFC4122RegexString = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"
uLIDRegexString = "^[A-HJKMNP-TV-Z0-9]{26}$"
md4RegexString = "^[0-9a-f]{32}$"
md5RegexString = "^[0-9a-f]{32}$"
sha256RegexString = "^[0-9a-f]{64}$"
sha384RegexString = "^[0-9a-f]{96}$"
sha512RegexString = "^[0-9a-f]{128}$"
ripemd128RegexString = "^[0-9a-f]{32}$"
ripemd160RegexString = "^[0-9a-f]{40}$"
tiger128RegexString = "^[0-9a-f]{32}$"
tiger160RegexString = "^[0-9a-f]{40}$"
tiger192RegexString = "^[0-9a-f]{48}$"
aSCIIRegexString = "^[\x00-\x7F]*$"
printableASCIIRegexString = "^[\x20-\x7E]*$"
multibyteRegexString = "[^\x00-\x7F]"
dataURIRegexString = `^data:((?:\w+\/(?:([^;]|;[^;]).)+)?)`
latitudeRegexString = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$"
longitudeRegexString = "^[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$"
sSNRegexString = `^[0-9]{3}[ -]?(0[1-9]|[1-9][0-9])[ -]?([1-9][0-9]{3}|[0-9][1-9][0-9]{2}|[0-9]{2}[1-9][0-9]|[0-9]{3}[1-9])$`
hostnameRegexStringRFC952 = `^[a-zA-Z]([a-zA-Z0-9\-]+[\.]?)*[a-zA-Z0-9]$` // https://tools.ietf.org/html/rfc952
hostnameRegexStringRFC1123 = `^([a-zA-Z0-9]{1}[a-zA-Z0-9-]{0,62}){1}(\.[a-zA-Z0-9]{1}[a-zA-Z0-9-]{0,62})*?$` // accepts hostname starting with a digit https://tools.ietf.org/html/rfc1123
fqdnRegexStringRFC1123 = `^([a-zA-Z0-9]{1}[a-zA-Z0-9-]{0,62})(\.[a-zA-Z0-9]{1}[a-zA-Z0-9-]{0,62})*?(\.[a-zA-Z]{1}[a-zA-Z0-9]{0,62})\.?$` // same as hostnameRegexStringRFC1123 but must contain a non numerical TLD (possibly ending with '.')
btcAddressRegexString = `^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$` // bitcoin address
btcAddressUpperRegexStringBech32 = `^BC1[02-9AC-HJ-NP-Z]{7,76}$` // bitcoin bech32 address https://en.bitcoin.it/wiki/Bech32
btcAddressLowerRegexStringBech32 = `^bc1[02-9ac-hj-np-z]{7,76}$` // bitcoin bech32 address https://en.bitcoin.it/wiki/Bech32
ethAddressRegexString = `^0x[0-9a-fA-F]{40}$`
ethAddressUpperRegexString = `^0x[0-9A-F]{40}$`
ethAddressLowerRegexString = `^0x[0-9a-f]{40}$`
uRLEncodedRegexString = `^(?:[^%]|%[0-9A-Fa-f]{2})*$`
hTMLEncodedRegexString = `&#[x]?([0-9a-fA-F]{2})|(&gt)|(&lt)|(&quot)|(&amp)+[;]?`
hTMLRegexString = `<[/]?([a-zA-Z]+).*?>`
jWTRegexString = "^[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]*$"
splitParamsRegexString = `'[^']*'|\S+`
bicRegexString = `^[A-Za-z]{6}[A-Za-z0-9]{2}([A-Za-z0-9]{3})?$`
semverRegexString = `^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$` // numbered capture groups https://semver.org/
dnsRegexStringRFC1035Label = "^[a-z]([-a-z0-9]*[a-z0-9]){0,62}$"
cveRegexString = `^CVE-(1999|2\d{3})-(0[^0]\d{2}|0\d[^0]\d{1}|0\d{2}[^0]|[1-9]{1}\d{3,})$` // CVE Format Id https://cve.mitre.org/cve/identifiers/syntaxchange.html
mongodbRegexString = "^[a-f\\d]{24}$"
cronRegexString = `(@(annually|yearly|monthly|weekly|daily|hourly|reboot))|(@every (\d+(ns|us|µs|ms|s|m|h))+)|((((\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*) ?){5,7})`
)
var (
alphaRegex = regexp.MustCompile(alphaRegexString)
alphaNumericRegex = regexp.MustCompile(alphaNumericRegexString)
numericRegex = regexp.MustCompile(numericRegexString)
numberRegex = regexp.MustCompile(numberRegexString)
hexadecimalRegex = regexp.MustCompile(hexadecimalRegexString)
hexcolorRegex = regexp.MustCompile(hexcolorRegexString)
rgbRegex = regexp.MustCompile(rgbRegexString)
rgbaRegex = regexp.MustCompile(rgbaRegexString)
hslRegex = regexp.MustCompile(hslRegexString)
hslaRegex = regexp.MustCompile(hslaRegexString)
emailRegex = regexp.MustCompile(emailRegexString)
alphaRegex = regexp.MustCompile(alphaRegexString)
alphaNumericRegex = regexp.MustCompile(alphaNumericRegexString)
alphaUnicodeRegex = regexp.MustCompile(alphaUnicodeRegexString)
alphaUnicodeNumericRegex = regexp.MustCompile(alphaUnicodeNumericRegexString)
numericRegex = regexp.MustCompile(numericRegexString)
numberRegex = regexp.MustCompile(numberRegexString)
hexadecimalRegex = regexp.MustCompile(hexadecimalRegexString)
hexColorRegex = regexp.MustCompile(hexColorRegexString)
rgbRegex = regexp.MustCompile(rgbRegexString)
rgbaRegex = regexp.MustCompile(rgbaRegexString)
hslRegex = regexp.MustCompile(hslRegexString)
hslaRegex = regexp.MustCompile(hslaRegexString)
e164Regex = regexp.MustCompile(e164RegexString)
emailRegex = regexp.MustCompile(emailRegexString)
base64Regex = regexp.MustCompile(base64RegexString)
base64URLRegex = regexp.MustCompile(base64URLRegexString)
base64RawURLRegex = regexp.MustCompile(base64RawURLRegexString)
iSBN10Regex = regexp.MustCompile(iSBN10RegexString)
iSBN13Regex = regexp.MustCompile(iSBN13RegexString)
uUID3Regex = regexp.MustCompile(uUID3RegexString)
uUID4Regex = regexp.MustCompile(uUID4RegexString)
uUID5Regex = regexp.MustCompile(uUID5RegexString)
uUIDRegex = regexp.MustCompile(uUIDRegexString)
uUID3RFC4122Regex = regexp.MustCompile(uUID3RFC4122RegexString)
uUID4RFC4122Regex = regexp.MustCompile(uUID4RFC4122RegexString)
uUID5RFC4122Regex = regexp.MustCompile(uUID5RFC4122RegexString)
uUIDRFC4122Regex = regexp.MustCompile(uUIDRFC4122RegexString)
uLIDRegex = regexp.MustCompile(uLIDRegexString)
md4Regex = regexp.MustCompile(md4RegexString)
md5Regex = regexp.MustCompile(md5RegexString)
sha256Regex = regexp.MustCompile(sha256RegexString)
sha384Regex = regexp.MustCompile(sha384RegexString)
sha512Regex = regexp.MustCompile(sha512RegexString)
ripemd128Regex = regexp.MustCompile(ripemd128RegexString)
ripemd160Regex = regexp.MustCompile(ripemd160RegexString)
tiger128Regex = regexp.MustCompile(tiger128RegexString)
tiger160Regex = regexp.MustCompile(tiger160RegexString)
tiger192Regex = regexp.MustCompile(tiger192RegexString)
aSCIIRegex = regexp.MustCompile(aSCIIRegexString)
printableASCIIRegex = regexp.MustCompile(printableASCIIRegexString)
multibyteRegex = regexp.MustCompile(multibyteRegexString)
dataURIRegex = regexp.MustCompile(dataURIRegexString)
latitudeRegex = regexp.MustCompile(latitudeRegexString)
longitudeRegex = regexp.MustCompile(longitudeRegexString)
sSNRegex = regexp.MustCompile(sSNRegexString)
hostnameRegexRFC952 = regexp.MustCompile(hostnameRegexStringRFC952)
hostnameRegexRFC1123 = regexp.MustCompile(hostnameRegexStringRFC1123)
fqdnRegexRFC1123 = regexp.MustCompile(fqdnRegexStringRFC1123)
btcAddressRegex = regexp.MustCompile(btcAddressRegexString)
btcUpperAddressRegexBech32 = regexp.MustCompile(btcAddressUpperRegexStringBech32)
btcLowerAddressRegexBech32 = regexp.MustCompile(btcAddressLowerRegexStringBech32)
ethAddressRegex = regexp.MustCompile(ethAddressRegexString)
uRLEncodedRegex = regexp.MustCompile(uRLEncodedRegexString)
hTMLEncodedRegex = regexp.MustCompile(hTMLEncodedRegexString)
hTMLRegex = regexp.MustCompile(hTMLRegexString)
jWTRegex = regexp.MustCompile(jWTRegexString)
splitParamsRegex = regexp.MustCompile(splitParamsRegexString)
bicRegex = regexp.MustCompile(bicRegexString)
semverRegex = regexp.MustCompile(semverRegexString)
dnsRegexRFC1035Label = regexp.MustCompile(dnsRegexStringRFC1035Label)
cveRegex = regexp.MustCompile(cveRegexString)
mongodbRegex = regexp.MustCompile(mongodbRegexString)
cronRegex = regexp.MustCompile(cronRegexString)
)
func matchesRegex(regex *regexp.Regexp, field interface{}) bool {
fieldAsString := field.(string) //this will panic inherently
return regex.MatchString(fieldAsString)
}

@ -0,0 +1,175 @@
package validator
import (
"context"
"reflect"
)
// StructLevelFunc accepts all values needed for struct level validation
type StructLevelFunc func(sl StructLevel)
// StructLevelFuncCtx accepts all values needed for struct level validation
// but also allows passing of contextual validation information via context.Context.
type StructLevelFuncCtx func(ctx context.Context, sl StructLevel)
// wrapStructLevelFunc wraps normal StructLevelFunc makes it compatible with StructLevelFuncCtx
func wrapStructLevelFunc(fn StructLevelFunc) StructLevelFuncCtx {
return func(ctx context.Context, sl StructLevel) {
fn(sl)
}
}
// StructLevel contains all the information and helper functions
// to validate a struct
type StructLevel interface {
// Validator returns the main validation object, in case one wants to call validations internally.
// this is so you don't have to use anonymous functions to get access to the validate
// instance.
Validator() *Validate
// Top returns the top level struct, if any
Top() reflect.Value
// Parent returns the current fields parent struct, if any
Parent() reflect.Value
// Current returns the current struct.
Current() reflect.Value
// ExtractType gets the actual underlying type of field value.
// It will dive into pointers, customTypes and return you the
// underlying value and its kind.
ExtractType(field reflect.Value) (value reflect.Value, kind reflect.Kind, nullable bool)
// ReportError reports an error just by passing the field and tag information
//
// NOTES:
//
// fieldName and altName get appended to the existing namespace that
// validator is on. e.g. pass 'FirstName' or 'Names[0]' depending
// on the nesting
//
// tag can be an existing validation tag or just something you make up
// and process on the flip side it's up to you.
ReportError(field interface{}, fieldName, structFieldName string, tag, param string)
// ReportValidationErrors reports an error just by passing ValidationErrors
//
// NOTES:
//
// relativeNamespace and relativeActualNamespace get appended to the
// existing namespace that validator is on.
// e.g. pass 'User.FirstName' or 'Users[0].FirstName' depending
// on the nesting. most of the time they will be blank, unless you validate
// at a level lower the the current field depth
ReportValidationErrors(relativeNamespace, relativeActualNamespace string, errs ValidationErrors)
}
var _ StructLevel = new(validate)
// Top returns the top level struct
//
// NOTE: this can be the same as the current struct being validated
// if not is a nested struct.
//
// this is only called when within Struct and Field Level validation and
// should not be relied upon for an acurate value otherwise.
func (v *validate) Top() reflect.Value {
return v.top
}
// Parent returns the current structs parent
//
// NOTE: this can be the same as the current struct being validated
// if not is a nested struct.
//
// this is only called when within Struct and Field Level validation and
// should not be relied upon for an acurate value otherwise.
func (v *validate) Parent() reflect.Value {
return v.slflParent
}
// Current returns the current struct.
func (v *validate) Current() reflect.Value {
return v.slCurrent
}
// Validator returns the main validation object, in case one want to call validations internally.
func (v *validate) Validator() *Validate {
return v.v
}
// ExtractType gets the actual underlying type of field value.
func (v *validate) ExtractType(field reflect.Value) (reflect.Value, reflect.Kind, bool) {
return v.extractTypeInternal(field, false)
}
// ReportError reports an error just by passing the field and tag information
func (v *validate) ReportError(field interface{}, fieldName, structFieldName, tag, param string) {
fv, kind, _ := v.extractTypeInternal(reflect.ValueOf(field), false)
if len(structFieldName) == 0 {
structFieldName = fieldName
}
v.str1 = string(append(v.ns, fieldName...))
if v.v.hasTagNameFunc || fieldName != structFieldName {
v.str2 = string(append(v.actualNs, structFieldName...))
} else {
v.str2 = v.str1
}
if kind == reflect.Invalid {
v.errs = append(v.errs,
&fieldError{
v: v.v,
tag: tag,
actualTag: tag,
ns: v.str1,
structNs: v.str2,
fieldLen: uint8(len(fieldName)),
structfieldLen: uint8(len(structFieldName)),
param: param,
kind: kind,
},
)
return
}
v.errs = append(v.errs,
&fieldError{
v: v.v,
tag: tag,
actualTag: tag,
ns: v.str1,
structNs: v.str2,
fieldLen: uint8(len(fieldName)),
structfieldLen: uint8(len(structFieldName)),
value: fv.Interface(),
param: param,
kind: kind,
typ: fv.Type(),
},
)
}
// ReportValidationErrors reports ValidationErrors obtained from running validations within the Struct Level validation.
//
// NOTE: this function prepends the current namespace to the relative ones.
func (v *validate) ReportValidationErrors(relativeNamespace, relativeStructNamespace string, errs ValidationErrors) {
var err *fieldError
for i := 0; i < len(errs); i++ {
err = errs[i].(*fieldError)
err.ns = string(append(append(v.ns, relativeNamespace...), err.ns...))
err.structNs = string(append(append(v.actualNs, relativeStructNamespace...), err.structNs...))
v.errs = append(v.errs, err)
}
}

1
testdata/a.go vendored

@ -0,0 +1 @@
package testdata

@ -0,0 +1,11 @@
package validator
import ut "github.com/go-playground/universal-translator"
// TranslationFunc is the function type used to register or override
// custom translations
type TranslationFunc func(ut ut.Translator, fe FieldError) string
// RegisterTranslationsFunc allows for registering of translations
// for a 'ut.Translator' for use within the 'TranslationFunc'
type RegisterTranslationsFunc func(ut ut.Translator) error

File diff suppressed because it is too large Load Diff

@ -0,0 +1,695 @@
package ar
import (
"testing"
"time"
. "github.com/go-playground/assert/v2"
english "github.com/go-playground/locales/en"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
)
func TestTranslations(t *testing.T) {
eng := english.New()
uni := ut.New(eng, eng)
trans, _ := uni.GetTranslator("en")
validate := validator.New()
err := RegisterDefaultTranslations(validate, trans)
Equal(t, err, nil)
type Inner struct {
EqCSFieldString string
NeCSFieldString string
GtCSFieldString string
GteCSFieldString string
LtCSFieldString string
LteCSFieldString string
}
type Test struct {
Inner Inner
RequiredString string `validate:"required"`
RequiredNumber int `validate:"required"`
RequiredMultiple []string `validate:"required"`
LenString string `validate:"len=1"`
LenNumber float64 `validate:"len=1113.00"`
LenMultiple []string `validate:"len=7"`
MinString string `validate:"min=1"`
MinNumber float64 `validate:"min=1113.00"`
MinMultiple []string `validate:"min=7"`
MaxString string `validate:"max=3"`
MaxNumber float64 `validate:"max=1113.00"`
MaxMultiple []string `validate:"max=7"`
EqString string `validate:"eq=3"`
EqNumber float64 `validate:"eq=2.33"`
EqMultiple []string `validate:"eq=7"`
NeString string `validate:"ne="`
NeNumber float64 `validate:"ne=0.00"`
NeMultiple []string `validate:"ne=0"`
LtString string `validate:"lt=3"`
LtNumber float64 `validate:"lt=5.56"`
LtMultiple []string `validate:"lt=2"`
LtTime time.Time `validate:"lt"`
LteString string `validate:"lte=3"`
LteNumber float64 `validate:"lte=5.56"`
LteMultiple []string `validate:"lte=2"`
LteTime time.Time `validate:"lte"`
GtString string `validate:"gt=3"`
GtNumber float64 `validate:"gt=5.56"`
GtMultiple []string `validate:"gt=2"`
GtTime time.Time `validate:"gt"`
GteString string `validate:"gte=3"`
GteNumber float64 `validate:"gte=5.56"`
GteMultiple []string `validate:"gte=2"`
GteTime time.Time `validate:"gte"`
EqFieldString string `validate:"eqfield=MaxString"`
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"`
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"`
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"`
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"`
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"`
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"`
NeFieldString string `validate:"nefield=EqFieldString"`
GtFieldString string `validate:"gtfield=MaxString"`
GteFieldString string `validate:"gtefield=MaxString"`
LtFieldString string `validate:"ltfield=MaxString"`
LteFieldString string `validate:"ltefield=MaxString"`
AlphaString string `validate:"alpha"`
AlphanumString string `validate:"alphanum"`
NumericString string `validate:"numeric"`
NumberString string `validate:"number"`
HexadecimalString string `validate:"hexadecimal"`
HexColorString string `validate:"hexcolor"`
RGBColorString string `validate:"rgb"`
RGBAColorString string `validate:"rgba"`
HSLColorString string `validate:"hsl"`
HSLAColorString string `validate:"hsla"`
Email string `validate:"email"`
URL string `validate:"url"`
URI string `validate:"uri"`
Base64 string `validate:"base64"`
Contains string `validate:"contains=purpose"`
ContainsAny string `validate:"containsany=!@#$"`
Excludes string `validate:"excludes=text"`
ExcludesAll string `validate:"excludesall=!@#$"`
ExcludesRune string `validate:"excludesrune=☻"`
ISBN string `validate:"isbn"`
ISBN10 string `validate:"isbn10"`
ISBN13 string `validate:"isbn13"`
UUID string `validate:"uuid"`
UUID3 string `validate:"uuid3"`
UUID4 string `validate:"uuid4"`
UUID5 string `validate:"uuid5"`
ULID string `validate:"ulid"`
ASCII string `validate:"ascii"`
PrintableASCII string `validate:"printascii"`
MultiByte string `validate:"multibyte"`
DataURI string `validate:"datauri"`
Latitude string `validate:"latitude"`
Longitude string `validate:"longitude"`
SSN string `validate:"ssn"`
IP string `validate:"ip"`
IPv4 string `validate:"ipv4"`
IPv6 string `validate:"ipv6"`
CIDR string `validate:"cidr"`
CIDRv4 string `validate:"cidrv4"`
CIDRv6 string `validate:"cidrv6"`
TCPAddr string `validate:"tcp_addr"`
TCPAddrv4 string `validate:"tcp4_addr"`
TCPAddrv6 string `validate:"tcp6_addr"`
UDPAddr string `validate:"udp_addr"`
UDPAddrv4 string `validate:"udp4_addr"`
UDPAddrv6 string `validate:"udp6_addr"`
IPAddr string `validate:"ip_addr"`
IPAddrv4 string `validate:"ip4_addr"`
IPAddrv6 string `validate:"ip6_addr"`
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"`
StrPtrMaxLen *string `validate:"max=1"`
StrPtrLen *string `validate:"len=2"`
StrPtrLt *string `validate:"lt=1"`
StrPtrLte *string `validate:"lte=1"`
StrPtrGt *string `validate:"gt=10"`
StrPtrGte *string `validate:"gte=10"`
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"`
JSONString string `validate:"json"`
JWTString string `validate:"jwt"`
LowercaseString string `validate:"lowercase"`
UppercaseString string `validate:"uppercase"`
Datetime string `validate:"datetime=2006-01-02"`
PostCode string `validate:"postcode_iso3166_alpha2=SG"`
PostCodeCountry string
PostCodeByField string `validate:"postcode_iso3166_alpha2_field=PostCodeCountry"`
}
var test Test
test.Inner.EqCSFieldString = "1234"
test.Inner.GtCSFieldString = "1234"
test.Inner.GteCSFieldString = "1234"
test.MaxString = "1234"
test.MaxNumber = 2000
test.MaxMultiple = make([]string, 9)
test.LtString = "1234"
test.LtNumber = 6
test.LtMultiple = make([]string, 3)
test.LtTime = time.Now().Add(time.Hour * 24)
test.LteString = "1234"
test.LteNumber = 6
test.LteMultiple = make([]string, 3)
test.LteTime = time.Now().Add(time.Hour * 24)
test.LtFieldString = "12345"
test.LteFieldString = "12345"
test.LtCSFieldString = "1234"
test.LteCSFieldString = "1234"
test.AlphaString = "abc3"
test.AlphanumString = "abc3!"
test.NumericString = "12E.00"
test.NumberString = "12E"
test.Excludes = "this is some test text"
test.ExcludesAll = "This is Great!"
test.ExcludesRune = "Love it ☻"
test.ASCII = "カタカナ"
test.PrintableASCII = "カタカナ"
test.MultiByte = "1234feerf"
test.LowercaseString = "ABCDEFG"
test.UppercaseString = "abcdefg"
s := "toolong"
test.StrPtrMaxLen = &s
test.StrPtrLen = &s
test.UniqueSlice = []string{"1234", "1234"}
test.UniqueMap = map[string]string{"key1": "1234", "key2": "1234"}
test.Datetime = "2008-Feb-01"
err = validate.Struct(test)
NotEqual(t, err, nil)
errs, ok := err.(validator.ValidationErrors)
Equal(t, ok, true)
tests := []struct {
ns string
expected string
}{
{
ns: "Test.IsColor",
expected: "يجب أن يكون IsColor لون صالح",
},
{
ns: "Test.MAC",
expected: "يجب أن يحتوي MAC على عنوان MAC صالح",
},
{
ns: "Test.IPAddr",
expected: "يجب أن يكون IPAddr عنوان IP قابل للحل",
},
{
ns: "Test.IPAddrv4",
expected: "يجب أن يكون IPAddrv4 عنوان IP قابل للحل",
},
{
ns: "Test.IPAddrv6",
expected: "يجب أن يكون IPAddrv6 عنوان IPv6 قابل للحل",
},
{
ns: "Test.UDPAddr",
expected: "يجب أن يكون UDPAddr عنوان UDP صالح",
},
{
ns: "Test.UDPAddrv4",
expected: "يجب أن يكون UDPAddrv4 عنوان IPv4 UDP صالح",
},
{
ns: "Test.UDPAddrv6",
expected: "يجب أن يكون UDPAddrv6 عنوان IPv6 UDP صالح",
},
{
ns: "Test.TCPAddr",
expected: "يجب أن يكون TCPAddr عنوان TCP صالح",
},
{
ns: "Test.TCPAddrv4",
expected: "يجب أن يكون TCPAddrv4 عنوان IPv4 TCP صالح",
},
{
ns: "Test.TCPAddrv6",
expected: "يجب أن يكون TCPAddrv6 عنوان IPv6 TCP صالح",
},
{
ns: "Test.CIDR",
expected: "يجب أن يحتوي CIDR على علامة CIDR صالحة",
},
{
ns: "Test.CIDRv4",
expected: "يجب أن يحتوي CIDRv4 على علامة CIDR صالحة لعنوان IPv4",
},
{
ns: "Test.CIDRv6",
expected: "يجب أن يحتوي CIDRv6 على علامة CIDR صالحة لعنوان IPv6",
},
{
ns: "Test.SSN",
expected: "يجب أن يكون SSN رقم SSN صالح",
},
{
ns: "Test.IP",
expected: "يجب أن يكون IP عنوان IP صالح",
},
{
ns: "Test.IPv4",
expected: "يجب أن يكون IPv4 عنوان IPv4 صالح",
},
{
ns: "Test.IPv6",
expected: "يجب أن يكون IPv6 عنوان IPv6 صالح",
},
{
ns: "Test.DataURI",
expected: "يجب أن يحتوي DataURI على URI صالح للبيانات",
},
{
ns: "Test.Latitude",
expected: "يجب أن يحتوي Latitude على إحداثيات خط عرض صالحة",
},
{
ns: "Test.Longitude",
expected: "يجب أن يحتوي Longitude على إحداثيات خط طول صالحة",
},
{
ns: "Test.MultiByte",
expected: "يجب أن يحتوي MultiByte على أحرف متعددة البايت",
},
{
ns: "Test.ASCII",
expected: "يجب أن يحتوي ASCII على أحرف ascii فقط",
},
{
ns: "Test.PrintableASCII",
expected: "يجب أن يحتوي PrintableASCII على أحرف ascii قابلة للطباعة فقط",
},
{
ns: "Test.UUID",
expected: "يجب أن يكون UUID UUID صالح",
},
{
ns: "Test.UUID3",
expected: "يجب أن يكون UUID3 UUID صالح من النسخة 3",
},
{
ns: "Test.UUID4",
expected: "يجب أن يكون UUID4 UUID صالح من النسخة 4",
},
{
ns: "Test.UUID5",
expected: "يجب أن يكون UUID5 UUID صالح من النسخة 5",
},
{
ns: "Test.ULID",
expected: "يجب أن يكون ULID ULID صالح من نسخة",
},
{
ns: "Test.ISBN",
expected: "يجب أن يكون ISBN رقم ISBN صالح",
},
{
ns: "Test.ISBN10",
expected: "يجب أن يكون ISBN10 رقم ISBN-10 صالح",
},
{
ns: "Test.ISBN13",
expected: "يجب أن يكون ISBN13 رقم ISBN-13 صالح",
},
{
ns: "Test.Excludes",
expected: "لا يمكن أن يحتوي Excludes على النص 'text'",
},
{
ns: "Test.ExcludesAll",
expected: "لا يمكن أن يحتوي ExcludesAll على أي من الأحرف التالية '!@#$'",
},
{
ns: "Test.ExcludesRune",
expected: "لا يمكن أن يحتوي ExcludesRune على التالي '☻'",
},
{
ns: "Test.ContainsAny",
expected: "يجب أن يحتوي ContainsAny على حرف واحد على الأقل من الأحرف التالية '!@#$'",
},
{
ns: "Test.Contains",
expected: "يجب أن يحتوي Contains على النص 'purpose'",
},
{
ns: "Test.Base64",
expected: "يجب أن يكون Base64 سلسلة Base64 صالحة",
},
{
ns: "Test.Email",
expected: "يجب أن يكون Email عنوان بريد إلكتروني صالح",
},
{
ns: "Test.URL",
expected: "يجب أن يكون URL رابط إنترنت صالح",
},
{
ns: "Test.URI",
expected: "يجب أن يكون URI URI صالح",
},
{
ns: "Test.RGBColorString",
expected: "يجب أن يكون RGBColorString لون RGB صالح",
},
{
ns: "Test.RGBAColorString",
expected: "يجب أن يكون RGBAColorString لون RGBA صالح",
},
{
ns: "Test.HSLColorString",
expected: "يجب أن يكون HSLColorString لون HSL صالح",
},
{
ns: "Test.HSLAColorString",
expected: "يجب أن يكون HSLAColorString لون HSLA صالح",
},
{
ns: "Test.HexadecimalString",
expected: "يجب أن يكون HexadecimalString عددًا سداسيًا عشريًا صالحاً",
},
{
ns: "Test.HexColorString",
expected: "يجب أن يكون HexColorString لون HEX صالح",
},
{
ns: "Test.NumberString",
expected: "يجب أن يكون NumberString رقم صالح",
},
{
ns: "Test.NumericString",
expected: "يجب أن يكون NumericString قيمة رقمية صالحة",
},
{
ns: "Test.AlphanumString",
expected: "يمكن أن يحتوي AlphanumString على أحرف أبجدية رقمية فقط",
},
{
ns: "Test.AlphaString",
expected: "يمكن أن يحتوي AlphaString على أحرف أبجدية فقط",
},
{
ns: "Test.LtFieldString",
expected: "يجب أن يكون LtFieldString أصغر من MaxString",
},
{
ns: "Test.LteFieldString",
expected: "يجب أن يكون LteFieldString أصغر من أو يساوي MaxString",
},
{
ns: "Test.GtFieldString",
expected: "يجب أن يكون GtFieldString أكبر من MaxString",
},
{
ns: "Test.GteFieldString",
expected: "يجب أن يكون GteFieldString أكبر من أو يساوي MaxString",
},
{
ns: "Test.NeFieldString",
expected: "NeFieldString لا يمكن أن يساوي EqFieldString",
},
{
ns: "Test.LtCSFieldString",
expected: "يجب أن يكون LtCSFieldString أصغر من Inner.LtCSFieldString",
},
{
ns: "Test.LteCSFieldString",
expected: "يجب أن يكون LteCSFieldString أصغر من أو يساوي Inner.LteCSFieldString",
},
{
ns: "Test.GtCSFieldString",
expected: "يجب أن يكون GtCSFieldString أكبر من Inner.GtCSFieldString",
},
{
ns: "Test.GteCSFieldString",
expected: "يجب أن يكون GteCSFieldString أكبر من أو يساوي Inner.GteCSFieldString",
},
{
ns: "Test.NeCSFieldString",
expected: "NeCSFieldString لا يمكن أن يساوي Inner.NeCSFieldString",
},
{
ns: "Test.EqCSFieldString",
expected: "يجب أن يكون EqCSFieldString مساويا ل Inner.EqCSFieldString",
},
{
ns: "Test.EqFieldString",
expected: "يجب أن يكون EqFieldString مساويا ل MaxString",
},
{
ns: "Test.GteString",
expected: "يجب أن يكون طول GteString على الأقل 3 أحرف",
},
{
ns: "Test.GteNumber",
expected: "GteNumber يجب أن يكون 5.56 أو أكبر",
},
{
ns: "Test.GteMultiple",
expected: "يجب أن يحتوي GteMultiple على 2 عناصر على الأقل",
},
{
ns: "Test.GteTime",
expected: "يجب أن يكون GteTime أكبر من أو يساوي التاريخ والوقت الحاليين",
},
{
ns: "Test.GtString",
expected: "يجب أن يكون طول GtString أكبر من 3 أحرف",
},
{
ns: "Test.GtNumber",
expected: "يجب أن يكون GtNumber أكبر من 5.56",
},
{
ns: "Test.GtMultiple",
expected: "يجب أن يحتوي GtMultiple على أكثر من 2 عناصر",
},
{
ns: "Test.GtTime",
expected: "يجب أن يكون GtTime أكبر من التاريخ والوقت الحاليين",
},
{
ns: "Test.LteString",
expected: "يجب أن يكون طول LteString كحد أقصى 3 أحرف",
},
{
ns: "Test.LteNumber",
expected: "LteNumber يجب أن يكون 5.56 أو اقل",
},
{
ns: "Test.LteMultiple",
expected: "يجب أن يحتوي LteMultiple على 2 عناصر كحد أقصى",
},
{
ns: "Test.LteTime",
expected: "يجب أن يكون LteTime أقل من أو يساوي التاريخ والوقت الحاليين",
},
{
ns: "Test.LtString",
expected: "يجب أن يكون طول LtString أقل من 3 أحرف",
},
{
ns: "Test.LtNumber",
expected: "يجب أن يكون LtNumber أقل من 5.56",
},
{
ns: "Test.LtMultiple",
expected: "يجب أن يحتوي LtMultiple على أقل من 2 عناصر",
},
{
ns: "Test.LtTime",
expected: "يجب أن يكون LtTime أقل من التاريخ والوقت الحاليين",
},
{
ns: "Test.NeString",
expected: "NeString يجب ألا يساوي ",
},
{
ns: "Test.NeNumber",
expected: "NeNumber يجب ألا يساوي 0.00",
},
{
ns: "Test.NeMultiple",
expected: "NeMultiple يجب ألا يساوي 0",
},
{
ns: "Test.EqString",
expected: "EqString لا يساوي 3",
},
{
ns: "Test.EqNumber",
expected: "EqNumber لا يساوي 2.33",
},
{
ns: "Test.EqMultiple",
expected: "EqMultiple لا يساوي 7",
},
{
ns: "Test.MaxString",
expected: "يجب أن يكون طول MaxString بحد أقصى 3 أحرف",
},
{
ns: "Test.MaxNumber",
expected: "MaxNumber يجب أن يكون 1,113.00 أو اقل",
},
{
ns: "Test.MaxMultiple",
expected: "يجب أن يحتوي MaxMultiple على 7 عناصر كحد أقصى",
},
{
ns: "Test.MinString",
expected: "MinString يجب أن يكون 1 حرف أو اقل",
},
{
ns: "Test.MinNumber",
expected: "MinNumber يجب أن يكون 1,113.00 أو اقل",
},
{
ns: "Test.MinMultiple",
expected: "يجب أن يحتوي MinMultiple على 7 عناصر على الأقل",
},
{
ns: "Test.LenString",
expected: "يجب أن يكون طول LenString مساويا ل 1 حرف",
},
{
ns: "Test.LenNumber",
expected: "يجب أن يكون LenNumber مساويا ل 1,113.00",
},
{
ns: "Test.LenMultiple",
expected: "يجب أن يحتوي LenMultiple على 7 عناصر",
},
{
ns: "Test.RequiredString",
expected: "حقل RequiredString مطلوب",
},
{
ns: "Test.RequiredNumber",
expected: "حقل RequiredNumber مطلوب",
},
{
ns: "Test.RequiredMultiple",
expected: "حقل RequiredMultiple مطلوب",
},
{
ns: "Test.StrPtrMinLen",
expected: "StrPtrMinLen يجب أن يكون 10 أحرف أو اقل",
},
{
ns: "Test.StrPtrMaxLen",
expected: "يجب أن يكون طول StrPtrMaxLen بحد أقصى 1 حرف",
},
{
ns: "Test.StrPtrLen",
expected: "يجب أن يكون طول StrPtrLen مساويا ل 2 أحرف",
},
{
ns: "Test.StrPtrLt",
expected: "يجب أن يكون طول StrPtrLt أقل من 1 حرف",
},
{
ns: "Test.StrPtrLte",
expected: "يجب أن يكون طول StrPtrLte كحد أقصى 1 حرف",
},
{
ns: "Test.StrPtrGt",
expected: "يجب أن يكون طول StrPtrGt أكبر من 10 أحرف",
},
{
ns: "Test.StrPtrGte",
expected: "يجب أن يكون طول StrPtrGte على الأقل 10 أحرف",
},
{
ns: "Test.OneOfString",
expected: "يجب أن يكون OneOfString واحدا من [red green]",
},
{
ns: "Test.OneOfInt",
expected: "يجب أن يكون OneOfInt واحدا من [5 63]",
},
{
ns: "Test.UniqueSlice",
expected: "يجب أن يحتوي UniqueSlice على قيم فريدة",
},
{
ns: "Test.UniqueArray",
expected: "يجب أن يحتوي UniqueArray على قيم فريدة",
},
{
ns: "Test.UniqueMap",
expected: "يجب أن يحتوي UniqueMap على قيم فريدة",
},
{
ns: "Test.JSONString",
expected: "يجب أن يكون JSONString نص json صالح",
},
{
ns: "Test.JWTString",
expected: "يجب أن يكون JWTString نص jwt صالح",
},
{
ns: "Test.LowercaseString",
expected: "يجب أن يكون LowercaseString نص حروف صغيرة",
},
{
ns: "Test.UppercaseString",
expected: "يجب أن يكون UppercaseString نص حروف كبيرة",
},
{
ns: "Test.Datetime",
expected: "لا يتطابق Datetime مع تنسيق 2006-01-02",
},
{
ns: "Test.PostCode",
expected: "لا يتطابق PostCode مع تنسيق الرمز البريدي للبلد SG",
},
{
ns: "Test.PostCodeByField",
expected: "لا يتطابق PostCodeByField مع تنسيق الرمز البريدي للبلد في حقل PostCodeCountry",
},
}
for _, tt := range tests {
var fe validator.FieldError
for _, e := range errs {
if tt.ns == e.Namespace() {
fe = e
break
}
}
NotEqual(t, fe, nil)
Equal(t, tt.expected, fe.Translate(trans))
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,720 @@
package en
import (
"testing"
"time"
. "github.com/go-playground/assert/v2"
english "github.com/go-playground/locales/en"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
)
func TestTranslations(t *testing.T) {
eng := english.New()
uni := ut.New(eng, eng)
trans, _ := uni.GetTranslator("en")
validate := validator.New()
err := RegisterDefaultTranslations(validate, trans)
Equal(t, err, nil)
type Inner struct {
EqCSFieldString string
NeCSFieldString string
GtCSFieldString string
GteCSFieldString string
LtCSFieldString string
LteCSFieldString string
RequiredIf string
}
type Test struct {
Inner Inner
RequiredString string `validate:"required"`
RequiredNumber int `validate:"required"`
RequiredMultiple []string `validate:"required"`
RequiredIf string `validate:"required_if=Inner.RequiredIf abcd"`
LenString string `validate:"len=1"`
LenNumber float64 `validate:"len=1113.00"`
LenMultiple []string `validate:"len=7"`
MinString string `validate:"min=1"`
MinNumber float64 `validate:"min=1113.00"`
MinMultiple []string `validate:"min=7"`
MaxString string `validate:"max=3"`
MaxNumber float64 `validate:"max=1113.00"`
MaxMultiple []string `validate:"max=7"`
EqString string `validate:"eq=3"`
EqNumber float64 `validate:"eq=2.33"`
EqMultiple []string `validate:"eq=7"`
NeString string `validate:"ne="`
NeNumber float64 `validate:"ne=0.00"`
NeMultiple []string `validate:"ne=0"`
LtString string `validate:"lt=3"`
LtNumber float64 `validate:"lt=5.56"`
LtMultiple []string `validate:"lt=2"`
LtTime time.Time `validate:"lt"`
LteString string `validate:"lte=3"`
LteNumber float64 `validate:"lte=5.56"`
LteMultiple []string `validate:"lte=2"`
LteTime time.Time `validate:"lte"`
GtString string `validate:"gt=3"`
GtNumber float64 `validate:"gt=5.56"`
GtMultiple []string `validate:"gt=2"`
GtTime time.Time `validate:"gt"`
GteString string `validate:"gte=3"`
GteNumber float64 `validate:"gte=5.56"`
GteMultiple []string `validate:"gte=2"`
GteTime time.Time `validate:"gte"`
EqFieldString string `validate:"eqfield=MaxString"`
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"`
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"`
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"`
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"`
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"`
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"`
NeFieldString string `validate:"nefield=EqFieldString"`
GtFieldString string `validate:"gtfield=MaxString"`
GteFieldString string `validate:"gtefield=MaxString"`
LtFieldString string `validate:"ltfield=MaxString"`
LteFieldString string `validate:"ltefield=MaxString"`
AlphaString string `validate:"alpha"`
AlphanumString string `validate:"alphanum"`
NumericString string `validate:"numeric"`
NumberString string `validate:"number"`
HexadecimalString string `validate:"hexadecimal"`
HexColorString string `validate:"hexcolor"`
RGBColorString string `validate:"rgb"`
RGBAColorString string `validate:"rgba"`
HSLColorString string `validate:"hsl"`
HSLAColorString string `validate:"hsla"`
Email string `validate:"email"`
URL string `validate:"url"`
URI string `validate:"uri"`
Base64 string `validate:"base64"`
Contains string `validate:"contains=purpose"`
ContainsAny string `validate:"containsany=!@#$"`
Excludes string `validate:"excludes=text"`
ExcludesAll string `validate:"excludesall=!@#$"`
ExcludesRune string `validate:"excludesrune=☻"`
ISBN string `validate:"isbn"`
ISBN10 string `validate:"isbn10"`
ISBN13 string `validate:"isbn13"`
UUID string `validate:"uuid"`
UUID3 string `validate:"uuid3"`
UUID4 string `validate:"uuid4"`
UUID5 string `validate:"uuid5"`
ULID string `validate:"ulid"`
ASCII string `validate:"ascii"`
PrintableASCII string `validate:"printascii"`
MultiByte string `validate:"multibyte"`
DataURI string `validate:"datauri"`
Latitude string `validate:"latitude"`
Longitude string `validate:"longitude"`
SSN string `validate:"ssn"`
IP string `validate:"ip"`
IPv4 string `validate:"ipv4"`
IPv6 string `validate:"ipv6"`
CIDR string `validate:"cidr"`
CIDRv4 string `validate:"cidrv4"`
CIDRv6 string `validate:"cidrv6"`
TCPAddr string `validate:"tcp_addr"`
TCPAddrv4 string `validate:"tcp4_addr"`
TCPAddrv6 string `validate:"tcp6_addr"`
UDPAddr string `validate:"udp_addr"`
UDPAddrv4 string `validate:"udp4_addr"`
UDPAddrv6 string `validate:"udp6_addr"`
IPAddr string `validate:"ip_addr"`
IPAddrv4 string `validate:"ip4_addr"`
IPAddrv6 string `validate:"ip6_addr"`
UinxAddr string `validate:"unix_addr"` // can't fail from within Go's net package currently, but maybe in the future
MAC string `validate:"mac"`
FQDN string `validate:"fqdn"`
IsColor string `validate:"iscolor"`
StrPtrMinLen *string `validate:"min=10"`
StrPtrMaxLen *string `validate:"max=1"`
StrPtrLen *string `validate:"len=2"`
StrPtrLt *string `validate:"lt=1"`
StrPtrLte *string `validate:"lte=1"`
StrPtrGt *string `validate:"gt=10"`
StrPtrGte *string `validate:"gte=10"`
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"`
JSONString string `validate:"json"`
JWTString string `validate:"jwt"`
LowercaseString string `validate:"lowercase"`
UppercaseString string `validate:"uppercase"`
Datetime string `validate:"datetime=2006-01-02"`
PostCode string `validate:"postcode_iso3166_alpha2=SG"`
PostCodeCountry string
PostCodeByField string `validate:"postcode_iso3166_alpha2_field=PostCodeCountry"`
BooleanString string `validate:"boolean"`
CveString string `validate:"cve"`
}
var test Test
test.Inner.EqCSFieldString = "1234"
test.Inner.GtCSFieldString = "1234"
test.Inner.GteCSFieldString = "1234"
test.MaxString = "1234"
test.MaxNumber = 2000
test.MaxMultiple = make([]string, 9)
test.LtString = "1234"
test.LtNumber = 6
test.LtMultiple = make([]string, 3)
test.LtTime = time.Now().Add(time.Hour * 24)
test.LteString = "1234"
test.LteNumber = 6
test.LteMultiple = make([]string, 3)
test.LteTime = time.Now().Add(time.Hour * 24)
test.LtFieldString = "12345"
test.LteFieldString = "12345"
test.LtCSFieldString = "1234"
test.LteCSFieldString = "1234"
test.AlphaString = "abc3"
test.AlphanumString = "abc3!"
test.NumericString = "12E.00"
test.NumberString = "12E"
test.Excludes = "this is some test text"
test.ExcludesAll = "This is Great!"
test.ExcludesRune = "Love it ☻"
test.ASCII = "カタカナ"
test.PrintableASCII = "カタカナ"
test.MultiByte = "1234feerf"
test.LowercaseString = "ABCDEFG"
test.UppercaseString = "abcdefg"
s := "toolong"
test.StrPtrMaxLen = &s
test.StrPtrLen = &s
test.UniqueSlice = []string{"1234", "1234"}
test.UniqueMap = map[string]string{"key1": "1234", "key2": "1234"}
test.Datetime = "2008-Feb-01"
test.BooleanString = "A"
test.CveString = "A"
test.Inner.RequiredIf = "abcd"
err = validate.Struct(test)
NotEqual(t, err, nil)
errs, ok := err.(validator.ValidationErrors)
Equal(t, ok, true)
tests := []struct {
ns string
expected string
}{
{
ns: "Test.IsColor",
expected: "IsColor must be a valid color",
},
{
ns: "Test.MAC",
expected: "MAC must contain a valid MAC address",
},
{
ns: "Test.FQDN",
expected: "FQDN must be a valid FQDN",
},
{
ns: "Test.IPAddr",
expected: "IPAddr must be a resolvable IP address",
},
{
ns: "Test.IPAddrv4",
expected: "IPAddrv4 must be a resolvable IPv4 address",
},
{
ns: "Test.IPAddrv6",
expected: "IPAddrv6 must be a resolvable IPv6 address",
},
{
ns: "Test.UDPAddr",
expected: "UDPAddr must be a valid UDP address",
},
{
ns: "Test.UDPAddrv4",
expected: "UDPAddrv4 must be a valid IPv4 UDP address",
},
{
ns: "Test.UDPAddrv6",
expected: "UDPAddrv6 must be a valid IPv6 UDP address",
},
{
ns: "Test.TCPAddr",
expected: "TCPAddr must be a valid TCP address",
},
{
ns: "Test.TCPAddrv4",
expected: "TCPAddrv4 must be a valid IPv4 TCP address",
},
{
ns: "Test.TCPAddrv6",
expected: "TCPAddrv6 must be a valid IPv6 TCP address",
},
{
ns: "Test.CIDR",
expected: "CIDR must contain a valid CIDR notation",
},
{
ns: "Test.CIDRv4",
expected: "CIDRv4 must contain a valid CIDR notation for an IPv4 address",
},
{
ns: "Test.CIDRv6",
expected: "CIDRv6 must contain a valid CIDR notation for an IPv6 address",
},
{
ns: "Test.SSN",
expected: "SSN must be a valid SSN number",
},
{
ns: "Test.IP",
expected: "IP must be a valid IP address",
},
{
ns: "Test.IPv4",
expected: "IPv4 must be a valid IPv4 address",
},
{
ns: "Test.IPv6",
expected: "IPv6 must be a valid IPv6 address",
},
{
ns: "Test.DataURI",
expected: "DataURI must contain a valid Data URI",
},
{
ns: "Test.Latitude",
expected: "Latitude must contain valid latitude coordinates",
},
{
ns: "Test.Longitude",
expected: "Longitude must contain a valid longitude coordinates",
},
{
ns: "Test.MultiByte",
expected: "MultiByte must contain multibyte characters",
},
{
ns: "Test.ASCII",
expected: "ASCII must contain only ascii characters",
},
{
ns: "Test.PrintableASCII",
expected: "PrintableASCII must contain only printable ascii characters",
},
{
ns: "Test.UUID",
expected: "UUID must be a valid UUID",
},
{
ns: "Test.UUID3",
expected: "UUID3 must be a valid version 3 UUID",
},
{
ns: "Test.UUID4",
expected: "UUID4 must be a valid version 4 UUID",
},
{
ns: "Test.UUID5",
expected: "UUID5 must be a valid version 5 UUID",
},
{
ns: "Test.ULID",
expected: "ULID must be a valid ULID",
},
{
ns: "Test.ISBN",
expected: "ISBN must be a valid ISBN number",
},
{
ns: "Test.ISBN10",
expected: "ISBN10 must be a valid ISBN-10 number",
},
{
ns: "Test.ISBN13",
expected: "ISBN13 must be a valid ISBN-13 number",
},
{
ns: "Test.Excludes",
expected: "Excludes cannot contain the text 'text'",
},
{
ns: "Test.ExcludesAll",
expected: "ExcludesAll cannot contain any of the following characters '!@#$'",
},
{
ns: "Test.ExcludesRune",
expected: "ExcludesRune cannot contain the following '☻'",
},
{
ns: "Test.ContainsAny",
expected: "ContainsAny must contain at least one of the following characters '!@#$'",
},
{
ns: "Test.Contains",
expected: "Contains must contain the text 'purpose'",
},
{
ns: "Test.Base64",
expected: "Base64 must be a valid Base64 string",
},
{
ns: "Test.Email",
expected: "Email must be a valid email address",
},
{
ns: "Test.URL",
expected: "URL must be a valid URL",
},
{
ns: "Test.URI",
expected: "URI must be a valid URI",
},
{
ns: "Test.RGBColorString",
expected: "RGBColorString must be a valid RGB color",
},
{
ns: "Test.RGBAColorString",
expected: "RGBAColorString must be a valid RGBA color",
},
{
ns: "Test.HSLColorString",
expected: "HSLColorString must be a valid HSL color",
},
{
ns: "Test.HSLAColorString",
expected: "HSLAColorString must be a valid HSLA color",
},
{
ns: "Test.HexadecimalString",
expected: "HexadecimalString must be a valid hexadecimal",
},
{
ns: "Test.HexColorString",
expected: "HexColorString must be a valid HEX color",
},
{
ns: "Test.NumberString",
expected: "NumberString must be a valid number",
},
{
ns: "Test.NumericString",
expected: "NumericString must be a valid numeric value",
},
{
ns: "Test.AlphanumString",
expected: "AlphanumString can only contain alphanumeric characters",
},
{
ns: "Test.AlphaString",
expected: "AlphaString can only contain alphabetic characters",
},
{
ns: "Test.LtFieldString",
expected: "LtFieldString must be less than MaxString",
},
{
ns: "Test.LteFieldString",
expected: "LteFieldString must be less than or equal to MaxString",
},
{
ns: "Test.GtFieldString",
expected: "GtFieldString must be greater than MaxString",
},
{
ns: "Test.GteFieldString",
expected: "GteFieldString must be greater than or equal to MaxString",
},
{
ns: "Test.NeFieldString",
expected: "NeFieldString cannot be equal to EqFieldString",
},
{
ns: "Test.LtCSFieldString",
expected: "LtCSFieldString must be less than Inner.LtCSFieldString",
},
{
ns: "Test.LteCSFieldString",
expected: "LteCSFieldString must be less than or equal to Inner.LteCSFieldString",
},
{
ns: "Test.GtCSFieldString",
expected: "GtCSFieldString must be greater than Inner.GtCSFieldString",
},
{
ns: "Test.GteCSFieldString",
expected: "GteCSFieldString must be greater than or equal to Inner.GteCSFieldString",
},
{
ns: "Test.NeCSFieldString",
expected: "NeCSFieldString cannot be equal to Inner.NeCSFieldString",
},
{
ns: "Test.EqCSFieldString",
expected: "EqCSFieldString must be equal to Inner.EqCSFieldString",
},
{
ns: "Test.EqFieldString",
expected: "EqFieldString must be equal to MaxString",
},
{
ns: "Test.GteString",
expected: "GteString must be at least 3 characters in length",
},
{
ns: "Test.GteNumber",
expected: "GteNumber must be 5.56 or greater",
},
{
ns: "Test.GteMultiple",
expected: "GteMultiple must contain at least 2 items",
},
{
ns: "Test.GteTime",
expected: "GteTime must be greater than or equal to the current Date & Time",
},
{
ns: "Test.GtString",
expected: "GtString must be greater than 3 characters in length",
},
{
ns: "Test.GtNumber",
expected: "GtNumber must be greater than 5.56",
},
{
ns: "Test.GtMultiple",
expected: "GtMultiple must contain more than 2 items",
},
{
ns: "Test.GtTime",
expected: "GtTime must be greater than the current Date & Time",
},
{
ns: "Test.LteString",
expected: "LteString must be at maximum 3 characters in length",
},
{
ns: "Test.LteNumber",
expected: "LteNumber must be 5.56 or less",
},
{
ns: "Test.LteMultiple",
expected: "LteMultiple must contain at maximum 2 items",
},
{
ns: "Test.LteTime",
expected: "LteTime must be less than or equal to the current Date & Time",
},
{
ns: "Test.LtString",
expected: "LtString must be less than 3 characters in length",
},
{
ns: "Test.LtNumber",
expected: "LtNumber must be less than 5.56",
},
{
ns: "Test.LtMultiple",
expected: "LtMultiple must contain less than 2 items",
},
{
ns: "Test.LtTime",
expected: "LtTime must be less than the current Date & Time",
},
{
ns: "Test.NeString",
expected: "NeString should not be equal to ",
},
{
ns: "Test.NeNumber",
expected: "NeNumber should not be equal to 0.00",
},
{
ns: "Test.NeMultiple",
expected: "NeMultiple should not be equal to 0",
},
{
ns: "Test.EqString",
expected: "EqString is not equal to 3",
},
{
ns: "Test.EqNumber",
expected: "EqNumber is not equal to 2.33",
},
{
ns: "Test.EqMultiple",
expected: "EqMultiple is not equal to 7",
},
{
ns: "Test.MaxString",
expected: "MaxString must be a maximum of 3 characters in length",
},
{
ns: "Test.MaxNumber",
expected: "MaxNumber must be 1,113.00 or less",
},
{
ns: "Test.MaxMultiple",
expected: "MaxMultiple must contain at maximum 7 items",
},
{
ns: "Test.MinString",
expected: "MinString must be at least 1 character in length",
},
{
ns: "Test.MinNumber",
expected: "MinNumber must be 1,113.00 or greater",
},
{
ns: "Test.MinMultiple",
expected: "MinMultiple must contain at least 7 items",
},
{
ns: "Test.LenString",
expected: "LenString must be 1 character in length",
},
{
ns: "Test.LenNumber",
expected: "LenNumber must be equal to 1,113.00",
},
{
ns: "Test.LenMultiple",
expected: "LenMultiple must contain 7 items",
},
{
ns: "Test.RequiredString",
expected: "RequiredString is a required field",
},
{
ns: "Test.RequiredIf",
expected: "RequiredIf is a required field",
},
{
ns: "Test.RequiredNumber",
expected: "RequiredNumber is a required field",
},
{
ns: "Test.RequiredMultiple",
expected: "RequiredMultiple is a required field",
},
{
ns: "Test.StrPtrMinLen",
expected: "StrPtrMinLen must be at least 10 characters in length",
},
{
ns: "Test.StrPtrMaxLen",
expected: "StrPtrMaxLen must be a maximum of 1 character in length",
},
{
ns: "Test.StrPtrLen",
expected: "StrPtrLen must be 2 characters in length",
},
{
ns: "Test.StrPtrLt",
expected: "StrPtrLt must be less than 1 character in length",
},
{
ns: "Test.StrPtrLte",
expected: "StrPtrLte must be at maximum 1 character in length",
},
{
ns: "Test.StrPtrGt",
expected: "StrPtrGt must be greater than 10 characters in length",
},
{
ns: "Test.StrPtrGte",
expected: "StrPtrGte must be at least 10 characters in length",
},
{
ns: "Test.OneOfString",
expected: "OneOfString must be one of [red green]",
},
{
ns: "Test.OneOfInt",
expected: "OneOfInt must be one of [5 63]",
},
{
ns: "Test.UniqueSlice",
expected: "UniqueSlice must contain unique values",
},
{
ns: "Test.UniqueArray",
expected: "UniqueArray must contain unique values",
},
{
ns: "Test.UniqueMap",
expected: "UniqueMap must contain unique values",
},
{
ns: "Test.JSONString",
expected: "JSONString must be a valid json string",
},
{
ns: "Test.JWTString",
expected: "JWTString must be a valid jwt string",
},
{
ns: "Test.LowercaseString",
expected: "LowercaseString must be a lowercase string",
},
{
ns: "Test.UppercaseString",
expected: "UppercaseString must be an uppercase string",
},
{
ns: "Test.Datetime",
expected: "Datetime does not match the 2006-01-02 format",
},
{
ns: "Test.PostCode",
expected: "PostCode does not match postcode format of SG country",
},
{
ns: "Test.PostCodeByField",
expected: "PostCodeByField does not match postcode format of country in PostCodeCountry field",
},
{
ns: "Test.BooleanString",
expected: "BooleanString must be a valid boolean value",
},
{
ns: "Test.CveString",
expected: "CveString must be a valid cve identifier",
},
}
for _, tt := range tests {
var fe validator.FieldError
for _, e := range errs {
if tt.ns == e.Namespace() {
fe = e
break
}
}
NotEqual(t, fe, nil)
Equal(t, tt.expected, fe.Translate(trans))
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,658 @@
package es
import (
"testing"
"time"
. "github.com/go-playground/assert/v2"
spanish "github.com/go-playground/locales/es"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
)
func TestTranslations(t *testing.T) {
spa := spanish.New()
uni := ut.New(spa, spa)
trans, _ := uni.GetTranslator("es")
validate := validator.New()
err := RegisterDefaultTranslations(validate, trans)
Equal(t, err, nil)
type Inner struct {
EqCSFieldString string
NeCSFieldString string
GtCSFieldString string
GteCSFieldString string
LtCSFieldString string
LteCSFieldString string
}
type Test struct {
Inner Inner
RequiredString string `validate:"required"`
RequiredNumber int `validate:"required"`
RequiredMultiple []string `validate:"required"`
RequiredIf string `validate:"required_if=Inner.RequiredIf abcd"`
LenString string `validate:"len=1"`
LenNumber float64 `validate:"len=1113.00"`
LenMultiple []string `validate:"len=7"`
MinString string `validate:"min=1"`
MinNumber float64 `validate:"min=1113.00"`
MinMultiple []string `validate:"min=7"`
MaxString string `validate:"max=3"`
MaxNumber float64 `validate:"max=1113.00"`
MaxMultiple []string `validate:"max=7"`
EqString string `validate:"eq=3"`
EqNumber float64 `validate:"eq=2.33"`
EqMultiple []string `validate:"eq=7"`
NeString string `validate:"ne="`
NeNumber float64 `validate:"ne=0.00"`
NeMultiple []string `validate:"ne=0"`
LtString string `validate:"lt=3"`
LtNumber float64 `validate:"lt=5.56"`
LtMultiple []string `validate:"lt=2"`
LtTime time.Time `validate:"lt"`
LteString string `validate:"lte=3"`
LteNumber float64 `validate:"lte=5.56"`
LteMultiple []string `validate:"lte=2"`
LteTime time.Time `validate:"lte"`
GtString string `validate:"gt=3"`
GtNumber float64 `validate:"gt=5.56"`
GtMultiple []string `validate:"gt=2"`
GtTime time.Time `validate:"gt"`
GteString string `validate:"gte=3"`
GteNumber float64 `validate:"gte=5.56"`
GteMultiple []string `validate:"gte=2"`
GteTime time.Time `validate:"gte"`
EqFieldString string `validate:"eqfield=MaxString"`
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"`
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"`
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"`
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"`
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"`
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"`
NeFieldString string `validate:"nefield=EqFieldString"`
GtFieldString string `validate:"gtfield=MaxString"`
GteFieldString string `validate:"gtefield=MaxString"`
LtFieldString string `validate:"ltfield=MaxString"`
LteFieldString string `validate:"ltefield=MaxString"`
AlphaString string `validate:"alpha"`
AlphanumString string `validate:"alphanum"`
NumericString string `validate:"numeric"`
NumberString string `validate:"number"`
HexadecimalString string `validate:"hexadecimal"`
HexColorString string `validate:"hexcolor"`
RGBColorString string `validate:"rgb"`
RGBAColorString string `validate:"rgba"`
HSLColorString string `validate:"hsl"`
HSLAColorString string `validate:"hsla"`
Email string `validate:"email"`
URL string `validate:"url"`
URI string `validate:"uri"`
Base64 string `validate:"base64"`
Contains string `validate:"contains=purpose"`
ContainsAny string `validate:"containsany=!@#$"`
Excludes string `validate:"excludes=text"`
ExcludesAll string `validate:"excludesall=!@#$"`
ExcludesRune string `validate:"excludesrune=☻"`
ISBN string `validate:"isbn"`
ISBN10 string `validate:"isbn10"`
ISBN13 string `validate:"isbn13"`
UUID string `validate:"uuid"`
UUID3 string `validate:"uuid3"`
UUID4 string `validate:"uuid4"`
UUID5 string `validate:"uuid5"`
ULID string `validate:"ulid"`
ASCII string `validate:"ascii"`
PrintableASCII string `validate:"printascii"`
MultiByte string `validate:"multibyte"`
DataURI string `validate:"datauri"`
Latitude string `validate:"latitude"`
Longitude string `validate:"longitude"`
SSN string `validate:"ssn"`
IP string `validate:"ip"`
IPv4 string `validate:"ipv4"`
IPv6 string `validate:"ipv6"`
CIDR string `validate:"cidr"`
CIDRv4 string `validate:"cidrv4"`
CIDRv6 string `validate:"cidrv6"`
TCPAddr string `validate:"tcp_addr"`
TCPAddrv4 string `validate:"tcp4_addr"`
TCPAddrv6 string `validate:"tcp6_addr"`
UDPAddr string `validate:"udp_addr"`
UDPAddrv4 string `validate:"udp4_addr"`
UDPAddrv6 string `validate:"udp6_addr"`
IPAddr string `validate:"ip_addr"`
IPAddrv4 string `validate:"ip4_addr"`
IPAddrv6 string `validate:"ip6_addr"`
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"`
StrPtrMaxLen *string `validate:"max=1"`
StrPtrLen *string `validate:"len=2"`
StrPtrLt *string `validate:"lt=1"`
StrPtrLte *string `validate:"lte=1"`
StrPtrGt *string `validate:"gt=10"`
StrPtrGte *string `validate:"gte=10"`
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
test.Inner.EqCSFieldString = "1234"
test.Inner.GtCSFieldString = "1234"
test.Inner.GteCSFieldString = "1234"
test.MaxString = "1234"
test.MaxNumber = 2000
test.MaxMultiple = make([]string, 9)
test.LtString = "1234"
test.LtNumber = 6
test.LtMultiple = make([]string, 3)
test.LtTime = time.Now().Add(time.Hour * 24)
test.LteString = "1234"
test.LteNumber = 6
test.LteMultiple = make([]string, 3)
test.LteTime = time.Now().Add(time.Hour * 24)
test.LtFieldString = "12345"
test.LteFieldString = "12345"
test.LtCSFieldString = "1234"
test.LteCSFieldString = "1234"
test.AlphaString = "abc3"
test.AlphanumString = "abc3!"
test.NumericString = "12E.00"
test.NumberString = "12E"
test.Excludes = "this is some test text"
test.ExcludesAll = "This is Great!"
test.ExcludesRune = "Love it ☻"
test.ASCII = "カタカナ"
test.PrintableASCII = "カタカナ"
test.MultiByte = "1234feerf"
s := "toolong"
test.StrPtrMaxLen = &s
test.StrPtrLen = &s
test.UniqueSlice = []string{"1234", "1234"}
test.UniqueMap = map[string]string{"key1": "1234", "key2": "1234"}
err = validate.Struct(test)
NotEqual(t, err, nil)
errs, ok := err.(validator.ValidationErrors)
Equal(t, ok, true)
tests := []struct {
ns string
expected string
}{
{
ns: "Test.IsColor",
expected: "IsColor debe ser un color válido",
},
{
ns: "Test.MAC",
expected: "MAC debe contener una dirección MAC válida",
},
{
ns: "Test.IPAddr",
expected: "IPAddr debe ser una dirección IP resoluble",
},
{
ns: "Test.IPAddrv4",
expected: "IPAddrv4 debe ser una dirección IPv4 resoluble",
},
{
ns: "Test.IPAddrv6",
expected: "IPAddrv6 debe ser una dirección IPv6 resoluble",
},
{
ns: "Test.UDPAddr",
expected: "UDPAddr debe ser una dirección UDP válida",
},
{
ns: "Test.UDPAddrv4",
expected: "UDPAddrv4 debe ser una dirección IPv4 UDP válida",
},
{
ns: "Test.UDPAddrv6",
expected: "UDPAddrv6 debe ser una dirección IPv6 UDP válida",
},
{
ns: "Test.TCPAddr",
expected: "TCPAddr debe ser una dirección TCP válida",
},
{
ns: "Test.TCPAddrv4",
expected: "TCPAddrv4 debe ser una dirección IPv4 TCP válida",
},
{
ns: "Test.TCPAddrv6",
expected: "TCPAddrv6 debe ser una dirección IPv6 TCP válida",
},
{
ns: "Test.CIDR",
expected: "CIDR debe contener una anotación válida del CIDR",
},
{
ns: "Test.CIDRv4",
expected: "CIDRv4 debe contener una notación CIDR válida para una dirección IPv4",
},
{
ns: "Test.CIDRv6",
expected: "CIDRv6 debe contener una notación CIDR válida para una dirección IPv6",
},
{
ns: "Test.SSN",
expected: "SSN debe ser un número válido de SSN",
},
{
ns: "Test.IP",
expected: "IP debe ser una dirección IP válida",
},
{
ns: "Test.IPv4",
expected: "IPv4 debe ser una dirección IPv4 válida",
},
{
ns: "Test.IPv6",
expected: "IPv6 debe ser una dirección IPv6 válida",
},
{
ns: "Test.DataURI",
expected: "DataURI debe contener un URI de datos válido",
},
{
ns: "Test.Latitude",
expected: "Latitude debe contener coordenadas de latitud válidas",
},
{
ns: "Test.Longitude",
expected: "Longitude debe contener unas coordenadas de longitud válidas",
},
{
ns: "Test.MultiByte",
expected: "MultiByte debe contener caracteres multibyte",
},
{
ns: "Test.ASCII",
expected: "ASCII debe contener sólo caracteres ascii",
},
{
ns: "Test.PrintableASCII",
expected: "PrintableASCII debe contener sólo caracteres ASCII imprimibles",
},
{
ns: "Test.UUID",
expected: "UUID debe ser un UUID válido",
},
{
ns: "Test.UUID3",
expected: "UUID3 debe ser una versión válida 3 UUID",
},
{
ns: "Test.UUID4",
expected: "UUID4 debe ser una versión válida 4 UUID",
},
{
ns: "Test.UUID5",
expected: "UUID5 debe ser una versión válida 5 UUID",
},
{
ns: "Test.ULID",
expected: "ULID debe ser un ULID válido",
},
{
ns: "Test.ISBN",
expected: "ISBN debe ser un número ISBN válido",
},
{
ns: "Test.ISBN10",
expected: "ISBN10 debe ser un número ISBN-10 válido",
},
{
ns: "Test.ISBN13",
expected: "ISBN13 debe ser un número ISBN-13 válido",
},
{
ns: "Test.Excludes",
expected: "Excludes no puede contener el texto 'text'",
},
{
ns: "Test.ExcludesAll",
expected: "ExcludesAll no puede contener ninguno de los siguientes caracteres '!@#$'",
},
{
ns: "Test.ExcludesRune",
expected: "ExcludesRune no puede contener lo siguiente '☻'",
},
{
ns: "Test.ContainsAny",
expected: "ContainsAny debe contener al menos uno de los siguientes caracteres '!@#$'",
},
{
ns: "Test.Contains",
expected: "Contains debe contener el texto 'purpose'",
},
{
ns: "Test.Base64",
expected: "Base64 debe ser una cadena de Base64 válida",
},
{
ns: "Test.Email",
expected: "Email debe ser una dirección de correo electrónico válida",
},
{
ns: "Test.URL",
expected: "URL debe ser un URL válido",
},
{
ns: "Test.URI",
expected: "URI debe ser una URI válida",
},
{
ns: "Test.RGBColorString",
expected: "RGBColorString debe ser un color RGB válido",
},
{
ns: "Test.RGBAColorString",
expected: "RGBAColorString debe ser un color RGBA válido",
},
{
ns: "Test.HSLColorString",
expected: "HSLColorString debe ser un color HSL válido",
},
{
ns: "Test.HSLAColorString",
expected: "HSLAColorString debe ser un color HSL válido",
},
{
ns: "Test.HexadecimalString",
expected: "HexadecimalString debe ser un hexadecimal válido",
},
{
ns: "Test.HexColorString",
expected: "HexColorString debe ser un color HEX válido",
},
{
ns: "Test.NumberString",
expected: "NumberString debe ser un número válido",
},
{
ns: "Test.NumericString",
expected: "NumericString debe ser un valor numérico válido",
},
{
ns: "Test.AlphanumString",
expected: "AlphanumString sólo puede contener caracteres alfanuméricos",
},
{
ns: "Test.AlphaString",
expected: "AlphaString sólo puede contener caracteres alfabéticos",
},
{
ns: "Test.LtFieldString",
expected: "LtFieldString debe ser menor que MaxString",
},
{
ns: "Test.LteFieldString",
expected: "LteFieldString debe ser menor o igual a MaxString",
},
{
ns: "Test.GtFieldString",
expected: "GtFieldString debe ser mayor que MaxString",
},
{
ns: "Test.GteFieldString",
expected: "GteFieldString debe ser mayor o igual a MaxString",
},
{
ns: "Test.NeFieldString",
expected: "NeFieldString no puede ser igual a EqFieldString",
},
{
ns: "Test.LtCSFieldString",
expected: "LtCSFieldString debe ser menor que Inner.LtCSFieldString",
},
{
ns: "Test.LteCSFieldString",
expected: "LteCSFieldString debe ser menor o igual a Inner.LteCSFieldString",
},
{
ns: "Test.GtCSFieldString",
expected: "GtCSFieldString debe ser mayor que Inner.GtCSFieldString",
},
{
ns: "Test.GteCSFieldString",
expected: "GteCSFieldString debe ser mayor o igual a Inner.GteCSFieldString",
},
{
ns: "Test.NeCSFieldString",
expected: "NeCSFieldString no puede ser igual a Inner.NeCSFieldString",
},
{
ns: "Test.EqCSFieldString",
expected: "EqCSFieldString debe ser igual a Inner.EqCSFieldString",
},
{
ns: "Test.EqFieldString",
expected: "EqFieldString debe ser igual a MaxString",
},
{
ns: "Test.GteString",
expected: "GteString debe tener al menos 3 caracteres de longitud",
},
{
ns: "Test.GteNumber",
expected: "GteNumber debe ser 5,56 o mayor",
},
{
ns: "Test.GteMultiple",
expected: "GteMultiple debe contener al menos 2 elementos",
},
{
ns: "Test.GteTime",
expected: "GteTime debe ser después o durante la fecha y hora actuales",
},
{
ns: "Test.GtString",
expected: "GtString debe ser mayor que 3 caracteres en longitud",
},
{
ns: "Test.GtNumber",
expected: "GtNumber debe ser mayor que 5,56",
},
{
ns: "Test.GtMultiple",
expected: "GtMultiple debe contener más de 2 elementos",
},
{
ns: "Test.GtTime",
expected: "GtTime debe ser después de la fecha y hora actual",
},
{
ns: "Test.LteString",
expected: "LteString debe tener un máximo de 3 caracteres de longitud",
},
{
ns: "Test.LteNumber",
expected: "LteNumber debe ser 5,56 o menos",
},
{
ns: "Test.LteMultiple",
expected: "LteMultiple debe contener como máximo 2 elementos",
},
{
ns: "Test.LteTime",
expected: "LteTime debe ser antes o durante la fecha y hora actual",
},
{
ns: "Test.LtString",
expected: "LtString debe tener menos de 3 caracteres de longitud",
},
{
ns: "Test.LtNumber",
expected: "LtNumber debe ser menos de 5,56",
},
{
ns: "Test.LtMultiple",
expected: "LtMultiple debe contener menos de 2 elementos",
},
{
ns: "Test.LtTime",
expected: "LtTime debe ser antes de la fecha y hora actual",
},
{
ns: "Test.NeString",
expected: "NeString no debería ser igual a ",
},
{
ns: "Test.NeNumber",
expected: "NeNumber no debería ser igual a 0.00",
},
{
ns: "Test.NeMultiple",
expected: "NeMultiple no debería ser igual a 0",
},
{
ns: "Test.EqString",
expected: "EqString no es igual a 3",
},
{
ns: "Test.EqNumber",
expected: "EqNumber no es igual a 2.33",
},
{
ns: "Test.EqMultiple",
expected: "EqMultiple no es igual a 7",
},
{
ns: "Test.MaxString",
expected: "MaxString debe tener un máximo de 3 caracteres de longitud",
},
{
ns: "Test.MaxNumber",
expected: "MaxNumber debe ser 1.113,00 o menos",
},
{
ns: "Test.MaxMultiple",
expected: "MaxMultiple debe contener como máximo 7 elementos",
},
{
ns: "Test.MinString",
expected: "MinString debe tener al menos 1 carácter de longitud",
},
{
ns: "Test.MinNumber",
expected: "MinNumber debe ser 1.113,00 o más",
},
{
ns: "Test.MinMultiple",
expected: "MinMultiple debe contener al menos 7 elementos",
},
{
ns: "Test.LenString",
expected: "LenString debe tener 1 carácter de longitud",
},
{
ns: "Test.LenNumber",
expected: "LenNumber debe ser igual a 1.113,00",
},
{
ns: "Test.LenMultiple",
expected: "LenMultiple debe contener 7 elementos",
},
{
ns: "Test.RequiredString",
expected: "RequiredString es un campo requerido",
},
{
ns: "Test.RequiredNumber",
expected: "RequiredNumber es un campo requerido",
},
{
ns: "Test.RequiredMultiple",
expected: "RequiredMultiple es un campo requerido",
},
{
ns: "Test.StrPtrMinLen",
expected: "StrPtrMinLen debe tener al menos 10 caracteres de longitud",
},
{
ns: "Test.StrPtrMaxLen",
expected: "StrPtrMaxLen debe tener un máximo de 1 carácter de longitud",
},
{
ns: "Test.StrPtrLen",
expected: "StrPtrLen debe tener 2 caracteres de longitud",
},
{
ns: "Test.StrPtrLt",
expected: "StrPtrLt debe tener menos de 1 carácter de longitud",
},
{
ns: "Test.StrPtrLte",
expected: "StrPtrLte debe tener un máximo de 1 carácter de longitud",
},
{
ns: "Test.StrPtrGt",
expected: "StrPtrGt debe ser mayor que 10 caracteres en longitud",
},
{
ns: "Test.StrPtrGte",
expected: "StrPtrGte debe tener al menos 10 caracteres de longitud",
},
{
ns: "Test.OneOfString",
expected: "OneOfString debe ser uno de [red green]",
},
{
ns: "Test.OneOfInt",
expected: "OneOfInt debe ser uno de [5 63]",
},
{
ns: "Test.UniqueSlice",
expected: "UniqueSlice debe contener valores únicos",
},
{
ns: "Test.UniqueArray",
expected: "UniqueArray debe contener valores únicos",
},
{
ns: "Test.UniqueMap",
expected: "UniqueMap debe contener valores únicos",
},
}
for _, tt := range tests {
var fe validator.FieldError
for _, e := range errs {
if tt.ns == e.Namespace() {
fe = e
break
}
}
NotEqual(t, fe, nil)
Equal(t, tt.expected, fe.Translate(trans))
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,690 @@
package fa
import (
"testing"
"time"
. "github.com/go-playground/assert/v2"
english "github.com/go-playground/locales/en"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
)
func TestTranslations(t *testing.T) {
eng := english.New()
uni := ut.New(eng, eng)
trans, _ := uni.GetTranslator("en")
validate := validator.New()
err := RegisterDefaultTranslations(validate, trans)
Equal(t, err, nil)
type Inner struct {
EqCSFieldString string
NeCSFieldString string
GtCSFieldString string
GteCSFieldString string
LtCSFieldString string
LteCSFieldString string
}
type Test struct {
Inner Inner
RequiredString string `validate:"required"`
RequiredNumber int `validate:"required"`
RequiredMultiple []string `validate:"required"`
LenString string `validate:"len=1"`
LenNumber float64 `validate:"len=1113.00"`
LenMultiple []string `validate:"len=7"`
MinString string `validate:"min=1"`
MinNumber float64 `validate:"min=1113.00"`
MinMultiple []string `validate:"min=7"`
MaxString string `validate:"max=3"`
MaxNumber float64 `validate:"max=1113.00"`
MaxMultiple []string `validate:"max=7"`
EqString string `validate:"eq=3"`
EqNumber float64 `validate:"eq=2.33"`
EqMultiple []string `validate:"eq=7"`
NeString string `validate:"ne="`
NeNumber float64 `validate:"ne=0.00"`
NeMultiple []string `validate:"ne=0"`
LtString string `validate:"lt=3"`
LtNumber float64 `validate:"lt=5.56"`
LtMultiple []string `validate:"lt=2"`
LtTime time.Time `validate:"lt"`
LteString string `validate:"lte=3"`
LteNumber float64 `validate:"lte=5.56"`
LteMultiple []string `validate:"lte=2"`
LteTime time.Time `validate:"lte"`
GtString string `validate:"gt=3"`
GtNumber float64 `validate:"gt=5.56"`
GtMultiple []string `validate:"gt=2"`
GtTime time.Time `validate:"gt"`
GteString string `validate:"gte=3"`
GteNumber float64 `validate:"gte=5.56"`
GteMultiple []string `validate:"gte=2"`
GteTime time.Time `validate:"gte"`
EqFieldString string `validate:"eqfield=MaxString"`
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"`
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"`
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"`
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"`
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"`
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"`
NeFieldString string `validate:"nefield=EqFieldString"`
GtFieldString string `validate:"gtfield=MaxString"`
GteFieldString string `validate:"gtefield=MaxString"`
LtFieldString string `validate:"ltfield=MaxString"`
LteFieldString string `validate:"ltefield=MaxString"`
AlphaString string `validate:"alpha"`
AlphanumString string `validate:"alphanum"`
NumericString string `validate:"numeric"`
NumberString string `validate:"number"`
HexadecimalString string `validate:"hexadecimal"`
HexColorString string `validate:"hexcolor"`
RGBColorString string `validate:"rgb"`
RGBAColorString string `validate:"rgba"`
HSLColorString string `validate:"hsl"`
HSLAColorString string `validate:"hsla"`
Email string `validate:"email"`
URL string `validate:"url"`
URI string `validate:"uri"`
Base64 string `validate:"base64"`
Contains string `validate:"contains=purpose"`
ContainsAny string `validate:"containsany=!@#$"`
Excludes string `validate:"excludes=text"`
ExcludesAll string `validate:"excludesall=!@#$"`
ExcludesRune string `validate:"excludesrune=☻"`
ISBN string `validate:"isbn"`
ISBN10 string `validate:"isbn10"`
ISBN13 string `validate:"isbn13"`
UUID string `validate:"uuid"`
UUID3 string `validate:"uuid3"`
UUID4 string `validate:"uuid4"`
UUID5 string `validate:"uuid5"`
ULID string `validate:"ulid"`
ASCII string `validate:"ascii"`
PrintableASCII string `validate:"printascii"`
MultiByte string `validate:"multibyte"`
DataURI string `validate:"datauri"`
Latitude string `validate:"latitude"`
Longitude string `validate:"longitude"`
SSN string `validate:"ssn"`
IP string `validate:"ip"`
IPv4 string `validate:"ipv4"`
IPv6 string `validate:"ipv6"`
CIDR string `validate:"cidr"`
CIDRv4 string `validate:"cidrv4"`
CIDRv6 string `validate:"cidrv6"`
TCPAddr string `validate:"tcp_addr"`
TCPAddrv4 string `validate:"tcp4_addr"`
TCPAddrv6 string `validate:"tcp6_addr"`
UDPAddr string `validate:"udp_addr"`
UDPAddrv4 string `validate:"udp4_addr"`
UDPAddrv6 string `validate:"udp6_addr"`
IPAddr string `validate:"ip_addr"`
IPAddrv4 string `validate:"ip4_addr"`
IPAddrv6 string `validate:"ip6_addr"`
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"`
StrPtrMaxLen *string `validate:"max=1"`
StrPtrLen *string `validate:"len=2"`
StrPtrLt *string `validate:"lt=1"`
StrPtrLte *string `validate:"lte=1"`
StrPtrGt *string `validate:"gt=10"`
StrPtrGte *string `validate:"gte=10"`
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"`
JSONString string `validate:"json"`
LowercaseString string `validate:"lowercase"`
UppercaseString string `validate:"uppercase"`
Datetime string `validate:"datetime=2006-01-02"`
PostCode string `validate:"postcode_iso3166_alpha2=SG"`
PostCodeCountry string
PostCodeByField string `validate:"postcode_iso3166_alpha2_field=PostCodeCountry"`
}
var test Test
test.Inner.EqCSFieldString = "1234"
test.Inner.GtCSFieldString = "1234"
test.Inner.GteCSFieldString = "1234"
test.MaxString = "1234"
test.MaxNumber = 2000
test.MaxMultiple = make([]string, 9)
test.LtString = "1234"
test.LtNumber = 6
test.LtMultiple = make([]string, 3)
test.LtTime = time.Now().Add(time.Hour * 24)
test.LteString = "1234"
test.LteNumber = 6
test.LteMultiple = make([]string, 3)
test.LteTime = time.Now().Add(time.Hour * 24)
test.LtFieldString = "12345"
test.LteFieldString = "12345"
test.LtCSFieldString = "1234"
test.LteCSFieldString = "1234"
test.AlphaString = "abc3"
test.AlphanumString = "abc3!"
test.NumericString = "12E.00"
test.NumberString = "12E"
test.Excludes = "this is some test text"
test.ExcludesAll = "This is Great!"
test.ExcludesRune = "Love it ☻"
test.ASCII = "カタカナ"
test.PrintableASCII = "カタカナ"
test.MultiByte = "1234feerf"
test.LowercaseString = "ABCDEFG"
test.UppercaseString = "abcdefg"
s := "toolong"
test.StrPtrMaxLen = &s
test.StrPtrLen = &s
test.UniqueSlice = []string{"1234", "1234"}
test.UniqueMap = map[string]string{"key1": "1234", "key2": "1234"}
test.Datetime = "2008-Feb-01"
err = validate.Struct(test)
NotEqual(t, err, nil)
errs, ok := err.(validator.ValidationErrors)
Equal(t, ok, true)
tests := []struct {
ns string
expected string
}{
{
ns: "Test.IsColor",
expected: "IsColor باید یک رنگ معتبر باشد",
},
{
ns: "Test.MAC",
expected: "MAC باید یک مکآدرس معتبر باشد",
},
{
ns: "Test.IPAddr",
expected: "IPAddr باید یک آدرس آیپی قابل دسترس باشد",
},
{
ns: "Test.IPAddrv4",
expected: "IPAddrv4 باید یک آدرس آیپی IPv4 قابل دسترس باشد",
},
{
ns: "Test.IPAddrv6",
expected: "IPAddrv6 باید یک آدرس آیپی IPv6 قابل دسترس باشد",
},
{
ns: "Test.UDPAddr",
expected: "UDPAddr باید یک آدرس UDP معتبر باشد",
},
{
ns: "Test.UDPAddrv4",
expected: "UDPAddrv4 باید یک آدرس UDP IPv4 معتبر باشد",
},
{
ns: "Test.UDPAddrv6",
expected: "UDPAddrv6 باید یک آدرس UDP IPv6 معتبر باشد",
},
{
ns: "Test.TCPAddr",
expected: "TCPAddr باید یک آدرس TCP معتبر باشد",
},
{
ns: "Test.TCPAddrv4",
expected: "TCPAddrv4 باید یک آدرس TCP IPv4 معتبر باشد",
},
{
ns: "Test.TCPAddrv6",
expected: "TCPAddrv6 باید یک آدرس TCP IPv6 معتبر باشد",
},
{
ns: "Test.CIDR",
expected: "CIDR باید یک نشانهگذاری CIDR معتبر باشد",
},
{
ns: "Test.CIDRv4",
expected: "CIDRv4 باید یک نشانهگذاری CIDR معتبر برای آدرس آیپی IPv4 باشد",
},
{
ns: "Test.CIDRv6",
expected: "CIDRv6 باید یک نشانهگذاری CIDR معتبر برای آدرس آیپی IPv6 باشد",
},
{
ns: "Test.SSN",
expected: "SSN باید یک شماره SSN معتبر باشد",
},
{
ns: "Test.IP",
expected: "IP باید یک آدرس آیپی معتبر باشد",
},
{
ns: "Test.IPv4",
expected: "IPv4 باید یک آدرس آیپی IPv4 معتبر باشد",
},
{
ns: "Test.IPv6",
expected: "IPv6 باید یک آدرس آیپی IPv6 معتبر باشد",
},
{
ns: "Test.DataURI",
expected: "DataURI باید یک Data URI معتبر باشد",
},
{
ns: "Test.Latitude",
expected: "Latitude باید یک عرض جغرافیایی معتبر باشد",
},
{
ns: "Test.Longitude",
expected: "Longitude باید یک طول جغرافیایی معتبر باشد",
},
{
ns: "Test.MultiByte",
expected: "MultiByte باید شامل کاراکترهای چندبایته باشد",
},
{
ns: "Test.ASCII",
expected: "ASCII باید فقط شامل کاراکترهای اسکی باشد",
},
{
ns: "Test.PrintableASCII",
expected: "PrintableASCII باید فقط شامل کاراکترهای اسکی قابل چاپ باشد",
},
{
ns: "Test.UUID",
expected: "UUID باید یک UUID معتبر باشد",
},
{
ns: "Test.UUID3",
expected: "UUID3 باید یک UUID نسخه 3 معتبر باشد",
},
{
ns: "Test.UUID4",
expected: "UUID4 باید یک UUID نسخه 4 معتبر باشد",
},
{
ns: "Test.UUID5",
expected: "UUID5 باید یک UUID نسخه 5 معتبر باشد",
},
{
ns: "Test.ULID",
expected: "ULID باید یک ULID معتبر باشد",
},
{
ns: "Test.ISBN",
expected: "ISBN باید یک شابک معتبر باشد",
},
{
ns: "Test.ISBN10",
expected: "ISBN10 باید یک شابک(ISBN-10) معتبر باشد",
},
{
ns: "Test.ISBN13",
expected: "ISBN13 باید یک شابک(ISBN-13) معتبر باشد",
},
{
ns: "Test.Excludes",
expected: "Excludes نمیتواند شامل 'text' باشد",
},
{
ns: "Test.ExcludesAll",
expected: "ExcludesAll نمیتواند شامل کاراکترهای '!@#$' باشد",
},
{
ns: "Test.ExcludesRune",
expected: "ExcludesRune نمیتواند شامل '☻' باشد",
},
{
ns: "Test.ContainsAny",
expected: "ContainsAny باید شامل کاراکترهای '!@#$' باشد",
},
{
ns: "Test.Contains",
expected: "Contains باید شامل 'purpose' باشد",
},
{
ns: "Test.Base64",
expected: "Base64 باید یک متن درمبنای64 معتبر باشد",
},
{
ns: "Test.Email",
expected: "Email باید یک ایمیل معتبر باشد",
},
{
ns: "Test.URL",
expected: "URL باید یک آدرس اینترنتی معتبر باشد",
},
{
ns: "Test.URI",
expected: "URI باید یک URI معتبر باشد",
},
{
ns: "Test.RGBColorString",
expected: "RGBColorString باید یک کد رنگ RGB باشد",
},
{
ns: "Test.RGBAColorString",
expected: "RGBAColorString باید یک کد رنگ RGBA باشد",
},
{
ns: "Test.HSLColorString",
expected: "HSLColorString باید یک کد رنگ HSL باشد",
},
{
ns: "Test.HSLAColorString",
expected: "HSLAColorString باید یک کد رنگ HSLA باشد",
},
{
ns: "Test.HexadecimalString",
expected: "HexadecimalString باید یک عدد درمبنای16 باشد",
},
{
ns: "Test.HexColorString",
expected: "HexColorString باید یک کد رنگ HEX باشد",
},
{
ns: "Test.NumberString",
expected: "NumberString باید یک عدد معتبر باشد",
},
{
ns: "Test.NumericString",
expected: "NumericString باید یک عدد معتبر باشد",
},
{
ns: "Test.AlphanumString",
expected: "AlphanumString میتواند فقط شامل حروف و اعداد باشد",
},
{
ns: "Test.AlphaString",
expected: "AlphaString میتواند فقط شامل حروف باشد",
},
{
ns: "Test.LtFieldString",
expected: "طول LtFieldString باید کمتر از MaxString باشد",
},
{
ns: "Test.LteFieldString",
expected: "طول LteFieldString باید کمتر یا برابر MaxString باشد",
},
{
ns: "Test.GtFieldString",
expected: "طول GtFieldString باید بیشتر از MaxString باشد",
},
{
ns: "Test.GteFieldString",
expected: "طول GteFieldString باید بیشتر یا برابر MaxString باشد",
},
{
ns: "Test.NeFieldString",
expected: "NeFieldString نمیتواند برابر EqFieldString باشد",
},
{
ns: "Test.LtCSFieldString",
expected: "طول LtCSFieldString باید کمتر از Inner.LtCSFieldString باشد",
},
{
ns: "Test.LteCSFieldString",
expected: "طول LteCSFieldString باید کمتر یا برابر Inner.LteCSFieldString باشد",
},
{
ns: "Test.GtCSFieldString",
expected: "طول GtCSFieldString باید بیشتر از Inner.GtCSFieldString باشد",
},
{
ns: "Test.GteCSFieldString",
expected: "طول GteCSFieldString باید بیشتر یا برابر Inner.GteCSFieldString باشد",
},
{
ns: "Test.NeCSFieldString",
expected: "NeCSFieldString نمیتواند برابر Inner.NeCSFieldString باشد",
},
{
ns: "Test.EqCSFieldString",
expected: "EqCSFieldString باید برابر Inner.EqCSFieldString باشد",
},
{
ns: "Test.EqFieldString",
expected: "EqFieldString باید برابر MaxString باشد",
},
{
ns: "Test.GteString",
expected: "طول GteString باید حداقل 3 کاراکتر باشد",
},
{
ns: "Test.GteNumber",
expected: "GteNumber باید بیشتر یا برابر 5.56 باشد",
},
{
ns: "Test.GteMultiple",
expected: "GteMultiple باید شامل حداقل 2 آیتم باشد",
},
{
ns: "Test.GteTime",
expected: "GteTime باید بعد یا برابر تاریخ و زمان کنونی باشد",
},
{
ns: "Test.GtString",
expected: "طول GtString باید بیشتر از 3 کاراکتر باشد",
},
{
ns: "Test.GtNumber",
expected: "GtNumber باید بیشتر از 5.56 باشد",
},
{
ns: "Test.GtMultiple",
expected: "GtMultiple باید دارای بیشتر از 2 آیتم باشد",
},
{
ns: "Test.GtTime",
expected: "GtTime باید بعد از تاریخ و زمان کنونی باشد",
},
{
ns: "Test.LteString",
expected: "طول LteString باید حداکثر 3 کاراکتر باشد",
},
{
ns: "Test.LteNumber",
expected: "LteNumber باید کمتر یا برابر 5.56 باشد",
},
{
ns: "Test.LteMultiple",
expected: "LteMultiple باید حداکثر شامل 2 آیتم باشد",
},
{
ns: "Test.LteTime",
expected: "LteTime باید قبل یا برابر تاریخ و زمان کنونی باشد",
},
{
ns: "Test.LtString",
expected: "طول LtString باید کمتر از 3 کاراکتر باشد",
},
{
ns: "Test.LtNumber",
expected: "LtNumber باید کمتر از 5.56 باشد",
},
{
ns: "Test.LtMultiple",
expected: "LtMultiple باید دارای کمتر از 2 آیتم باشد",
},
{
ns: "Test.LtTime",
expected: "LtTime باید قبل از تاریخ و زمان کنونی باشد",
},
{
ns: "Test.NeString",
expected: "NeString نباید برابر باشد",
},
{
ns: "Test.NeNumber",
expected: "NeNumber نباید برابر 0.00 باشد",
},
{
ns: "Test.NeMultiple",
expected: "NeMultiple نباید برابر 0 باشد",
},
{
ns: "Test.EqString",
expected: "EqString برابر 3 نمیباشد",
},
{
ns: "Test.EqNumber",
expected: "EqNumber برابر 2.33 نمیباشد",
},
{
ns: "Test.EqMultiple",
expected: "EqMultiple برابر 7 نمیباشد",
},
{
ns: "Test.MaxString",
expected: "طول MaxString باید حداکثر 3 کاراکتر باشد",
},
{
ns: "Test.MaxNumber",
expected: "MaxNumber باید کمتر یا برابر 1,113.00 باشد",
},
{
ns: "Test.MaxMultiple",
expected: "MaxMultiple باید شامل حداکثر 7 آیتم باشد",
},
{
ns: "Test.MinString",
expected: "طول MinString باید حداقل 1 کاراکتر باشد",
},
{
ns: "Test.MinNumber",
expected: "MinNumber باید بزرگتر یا برابر 1,113.00 باشد",
},
{
ns: "Test.MinMultiple",
expected: "MinMultiple باید شامل حداقل 7 آیتم باشد",
},
{
ns: "Test.LenString",
expected: "طول LenString باید 1 کاراکتر باشد",
},
{
ns: "Test.LenNumber",
expected: "طول LenNumber باید برابر 1,113.00 باشد",
},
{
ns: "Test.LenMultiple",
expected: "تعداد LenMultiple باید برابر 7 آیتم باشد",
},
{
ns: "Test.RequiredString",
expected: "فیلد RequiredString اجباری میباشد",
},
{
ns: "Test.RequiredNumber",
expected: "فیلد RequiredNumber اجباری میباشد",
},
{
ns: "Test.RequiredMultiple",
expected: "فیلد RequiredMultiple اجباری میباشد",
},
{
ns: "Test.StrPtrMinLen",
expected: "طول StrPtrMinLen باید حداقل 10 کاراکتر باشد",
},
{
ns: "Test.StrPtrMaxLen",
expected: "طول StrPtrMaxLen باید حداکثر 1 کاراکتر باشد",
},
{
ns: "Test.StrPtrLen",
expected: "طول StrPtrLen باید 2 کاراکتر باشد",
},
{
ns: "Test.StrPtrLt",
expected: "طول StrPtrLt باید کمتر از 1 کاراکتر باشد",
},
{
ns: "Test.StrPtrLte",
expected: "طول StrPtrLte باید حداکثر 1 کاراکتر باشد",
},
{
ns: "Test.StrPtrGt",
expected: "طول StrPtrGt باید بیشتر از 10 کاراکتر باشد",
},
{
ns: "Test.StrPtrGte",
expected: "طول StrPtrGte باید حداقل 10 کاراکتر باشد",
},
{
ns: "Test.OneOfString",
expected: "OneOfString باید یکی از مقادیر [red green] باشد",
},
{
ns: "Test.OneOfInt",
expected: "OneOfInt باید یکی از مقادیر [5 63] باشد",
},
{
ns: "Test.UniqueSlice",
expected: "UniqueSlice باید شامل مقادیر منحصربفرد باشد",
},
{
ns: "Test.UniqueArray",
expected: "UniqueArray باید شامل مقادیر منحصربفرد باشد",
},
{
ns: "Test.UniqueMap",
expected: "UniqueMap باید شامل مقادیر منحصربفرد باشد",
},
{
ns: "Test.JSONString",
expected: "JSONString باید یک json معتبر باشد",
},
{
ns: "Test.LowercaseString",
expected: "LowercaseString باید یک متن با حروف کوچک باشد",
},
{
ns: "Test.UppercaseString",
expected: "UppercaseString باید یک متن با حروف بزرگ باشد",
},
{
ns: "Test.Datetime",
expected: "فرمت Datetime با 2006-01-02 سازگار نیست",
},
{
ns: "Test.PostCode",
expected: "PostCode یک کدپستی معتبر کشور SG نیست",
},
{
ns: "Test.PostCodeByField",
expected: "PostCodeByField یک کدپستی معتبر کشور فیلد PostCodeCountry نیست",
},
}
for _, tt := range tests {
var fe validator.FieldError
for _, e := range errs {
if tt.ns == e.Namespace() {
fe = e
break
}
}
NotEqual(t, fe, nil)
Equal(t, tt.expected, fe.Translate(trans))
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,639 @@
package fr
import (
"testing"
"time"
. "github.com/go-playground/assert/v2"
french "github.com/go-playground/locales/fr"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
)
func TestTranslations(t *testing.T) {
fre := french.New()
uni := ut.New(fre, fre)
trans, _ := uni.GetTranslator("fr")
validate := validator.New()
err := RegisterDefaultTranslations(validate, trans)
Equal(t, err, nil)
type Inner struct {
EqCSFieldString string
NeCSFieldString string
GtCSFieldString string
GteCSFieldString string
LtCSFieldString string
LteCSFieldString string
}
type Test struct {
Inner Inner
RequiredString string `validate:"required"`
RequiredNumber int `validate:"required"`
RequiredMultiple []string `validate:"required"`
LenString string `validate:"len=1"`
LenNumber float64 `validate:"len=1113.00"`
LenMultiple []string `validate:"len=7"`
MinString string `validate:"min=1"`
MinNumber float64 `validate:"min=1113.00"`
MinMultiple []string `validate:"min=7"`
MaxString string `validate:"max=3"`
MaxNumber float64 `validate:"max=1113.00"`
MaxMultiple []string `validate:"max=7"`
EqString string `validate:"eq=3"`
EqNumber float64 `validate:"eq=2.33"`
EqMultiple []string `validate:"eq=7"`
NeString string `validate:"ne="`
NeNumber float64 `validate:"ne=0.00"`
NeMultiple []string `validate:"ne=0"`
LtString string `validate:"lt=3"`
LtNumber float64 `validate:"lt=5.56"`
LtMultiple []string `validate:"lt=2"`
LtTime time.Time `validate:"lt"`
LteString string `validate:"lte=3"`
LteNumber float64 `validate:"lte=5.56"`
LteMultiple []string `validate:"lte=2"`
LteTime time.Time `validate:"lte"`
GtString string `validate:"gt=3"`
GtNumber float64 `validate:"gt=5.56"`
GtMultiple []string `validate:"gt=2"`
GtTime time.Time `validate:"gt"`
GteString string `validate:"gte=3"`
GteNumber float64 `validate:"gte=5.56"`
GteMultiple []string `validate:"gte=2"`
GteTime time.Time `validate:"gte"`
EqFieldString string `validate:"eqfield=MaxString"`
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"`
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"`
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"`
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"`
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"`
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"`
NeFieldString string `validate:"nefield=EqFieldString"`
GtFieldString string `validate:"gtfield=MaxString"`
GteFieldString string `validate:"gtefield=MaxString"`
LtFieldString string `validate:"ltfield=MaxString"`
LteFieldString string `validate:"ltefield=MaxString"`
AlphaString string `validate:"alpha"`
AlphanumString string `validate:"alphanum"`
NumericString string `validate:"numeric"`
NumberString string `validate:"number"`
HexadecimalString string `validate:"hexadecimal"`
HexColorString string `validate:"hexcolor"`
RGBColorString string `validate:"rgb"`
RGBAColorString string `validate:"rgba"`
HSLColorString string `validate:"hsl"`
HSLAColorString string `validate:"hsla"`
Email string `validate:"email"`
URL string `validate:"url"`
URI string `validate:"uri"`
Base64 string `validate:"base64"`
Contains string `validate:"contains=purpose"`
ContainsAny string `validate:"containsany=!@#$"`
Excludes string `validate:"excludes=text"`
ExcludesAll string `validate:"excludesall=!@#$"`
ExcludesRune string `validate:"excludesrune=☻"`
ISBN string `validate:"isbn"`
ISBN10 string `validate:"isbn10"`
ISBN13 string `validate:"isbn13"`
UUID string `validate:"uuid"`
UUID3 string `validate:"uuid3"`
UUID4 string `validate:"uuid4"`
UUID5 string `validate:"uuid5"`
ULID string `validate:"ulid"`
ASCII string `validate:"ascii"`
PrintableASCII string `validate:"printascii"`
MultiByte string `validate:"multibyte"`
DataURI string `validate:"datauri"`
Latitude string `validate:"latitude"`
Longitude string `validate:"longitude"`
SSN string `validate:"ssn"`
IP string `validate:"ip"`
IPv4 string `validate:"ipv4"`
IPv6 string `validate:"ipv6"`
CIDR string `validate:"cidr"`
CIDRv4 string `validate:"cidrv4"`
CIDRv6 string `validate:"cidrv6"`
TCPAddr string `validate:"tcp_addr"`
TCPAddrv4 string `validate:"tcp4_addr"`
TCPAddrv6 string `validate:"tcp6_addr"`
UDPAddr string `validate:"udp_addr"`
UDPAddrv4 string `validate:"udp4_addr"`
UDPAddrv6 string `validate:"udp6_addr"`
IPAddr string `validate:"ip_addr"`
IPAddrv4 string `validate:"ip4_addr"`
IPAddrv6 string `validate:"ip6_addr"`
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"`
StrPtrMaxLen *string `validate:"max=1"`
StrPtrLen *string `validate:"len=2"`
StrPtrLt *string `validate:"lt=1"`
StrPtrLte *string `validate:"lte=1"`
StrPtrGt *string `validate:"gt=10"`
StrPtrGte *string `validate:"gte=10"`
OneOfString string `validate:"oneof=red green"`
OneOfInt int `validate:"oneof=5 63"`
}
var test Test
test.Inner.EqCSFieldString = "1234"
test.Inner.GtCSFieldString = "1234"
test.Inner.GteCSFieldString = "1234"
test.MaxString = "1234"
test.MaxNumber = 2000
test.MaxMultiple = make([]string, 9)
test.LtString = "1234"
test.LtNumber = 6
test.LtMultiple = make([]string, 3)
test.LtTime = time.Now().Add(time.Hour * 24)
test.LteString = "1234"
test.LteNumber = 6
test.LteMultiple = make([]string, 3)
test.LteTime = time.Now().Add(time.Hour * 24)
test.LtFieldString = "12345"
test.LteFieldString = "12345"
test.LtCSFieldString = "1234"
test.LteCSFieldString = "1234"
test.AlphaString = "abc3"
test.AlphanumString = "abc3!"
test.NumericString = "12E.00"
test.NumberString = "12E"
test.Excludes = "this is some test text"
test.ExcludesAll = "This is Great!"
test.ExcludesRune = "Love it ☻"
test.ASCII = "カタカナ"
test.PrintableASCII = "カタカナ"
test.MultiByte = "1234feerf"
s := "toolong"
test.StrPtrMaxLen = &s
test.StrPtrLen = &s
err = validate.Struct(test)
NotEqual(t, err, nil)
errs, ok := err.(validator.ValidationErrors)
Equal(t, ok, true)
tests := []struct {
ns string
expected string
}{
{
ns: "Test.IsColor",
expected: "IsColor doit être une couleur valide",
},
{
ns: "Test.MAC",
expected: "MAC doit contenir une adresse MAC valide",
},
{
ns: "Test.IPAddr",
expected: "IPAddr doit être une adresse IP résolvable",
},
{
ns: "Test.IPAddrv4",
expected: "IPAddrv4 doit être une adresse IPv4 résolvable",
},
{
ns: "Test.IPAddrv6",
expected: "IPAddrv6 doit être une adresse IPv6 résolvable",
},
{
ns: "Test.UDPAddr",
expected: "UDPAddr doit être une adressse UDP valide",
},
{
ns: "Test.UDPAddrv4",
expected: "UDPAddrv4 doit être une adressse IPv4 UDP valide",
},
{
ns: "Test.UDPAddrv6",
expected: "UDPAddrv6 doit être une adressse IPv6 UDP valide",
},
{
ns: "Test.TCPAddr",
expected: "TCPAddr doit être une adressse TCP valide",
},
{
ns: "Test.TCPAddrv4",
expected: "TCPAddrv4 doit être une adressse IPv4 TCP valide",
},
{
ns: "Test.TCPAddrv6",
expected: "TCPAddrv6 doit être une adressse IPv6 TCP valide",
},
{
ns: "Test.CIDR",
expected: "CIDR doit contenir une notation CIDR valide",
},
{
ns: "Test.CIDRv4",
expected: "CIDRv4 doit contenir une notation CIDR valide pour une adresse IPv4",
},
{
ns: "Test.CIDRv6",
expected: "CIDRv6 doit contenir une notation CIDR valide pour une adresse IPv6",
},
{
ns: "Test.SSN",
expected: "SSN doit être un numéro SSN valide",
},
{
ns: "Test.IP",
expected: "IP doit être une adressse IP valide",
},
{
ns: "Test.IPv4",
expected: "IPv4 doit être une adressse IPv4 valide",
},
{
ns: "Test.IPv6",
expected: "IPv6 doit être une adressse IPv6 valide",
},
{
ns: "Test.DataURI",
expected: "DataURI doit contenir une URI data valide",
},
{
ns: "Test.Latitude",
expected: "Latitude doit contenir des coordonnées latitude valides",
},
{
ns: "Test.Longitude",
expected: "Longitude doit contenir des coordonnées longitudes valides",
},
{
ns: "Test.MultiByte",
expected: "MultiByte doit contenir des caractères multioctets",
},
{
ns: "Test.ASCII",
expected: "ASCII ne doit contenir que des caractères ascii",
},
{
ns: "Test.PrintableASCII",
expected: "PrintableASCII ne doit contenir que des caractères ascii affichables",
},
{
ns: "Test.UUID",
expected: "UUID doit être un UUID valid",
},
{
ns: "Test.UUID3",
expected: "UUID3 doit être un UUID version 3 valid",
},
{
ns: "Test.UUID4",
expected: "UUID4 doit être un UUID version 4 valid",
},
{
ns: "Test.UUID5",
expected: "UUID5 doit être un UUID version 5 valid",
},
{
ns: "Test.ULID",
expected: "ULID doit être une ULID valide",
},
{
ns: "Test.ISBN",
expected: "ISBN doit être un numéro ISBN valid",
},
{
ns: "Test.ISBN10",
expected: "ISBN10 doit être un numéro ISBN-10 valid",
},
{
ns: "Test.ISBN13",
expected: "ISBN13 doit être un numéro ISBN-13 valid",
},
{
ns: "Test.Excludes",
expected: "Excludes ne doit pas contenir le texte 'text'",
},
{
ns: "Test.ExcludesAll",
expected: "ExcludesAll ne doit pas contenir l'un des caractères suivants '!@#$'",
},
{
ns: "Test.ExcludesRune",
expected: "ExcludesRune ne doit pas contenir ce qui suit '☻'",
},
{
ns: "Test.ContainsAny",
expected: "ContainsAny doit contenir au moins l' un des caractères suivants '!@#$'",
},
{
ns: "Test.Contains",
expected: "Contains doit contenir le texte 'purpose'",
},
{
ns: "Test.Base64",
expected: "Base64 doit être une chaîne de caractères au format Base64 valide",
},
{
ns: "Test.Email",
expected: "Email doit être une adresse email valide",
},
{
ns: "Test.URL",
expected: "URL doit être une URL valide",
},
{
ns: "Test.URI",
expected: "URI doit être une URI valide",
},
{
ns: "Test.RGBColorString",
expected: "RGBColorString doit être une couleur au format RGB valide",
},
{
ns: "Test.RGBAColorString",
expected: "RGBAColorString doit être une couleur au format RGBA valide",
},
{
ns: "Test.HSLColorString",
expected: "HSLColorString doit être une couleur au format HSL valide",
},
{
ns: "Test.HSLAColorString",
expected: "HSLAColorString doit être une couleur au format HSLA valide",
},
{
ns: "Test.HexadecimalString",
expected: "HexadecimalString doit être une chaîne de caractères au format hexadécimal valide",
},
{
ns: "Test.HexColorString",
expected: "HexColorString doit être une couleur au format HEX valide",
},
{
ns: "Test.NumberString",
expected: "NumberString doit être un nombre valid",
},
{
ns: "Test.NumericString",
expected: "NumericString doit être une valeur numérique valide",
},
{
ns: "Test.AlphanumString",
expected: "AlphanumString ne doit contenir que des caractères alphanumériques",
},
{
ns: "Test.AlphaString",
expected: "AlphaString ne doit contenir que des caractères alphabétiques",
},
{
ns: "Test.LtFieldString",
expected: "LtFieldString doit être inférieur à MaxString",
},
{
ns: "Test.LteFieldString",
expected: "LteFieldString doit être inférieur ou égal à MaxString",
},
{
ns: "Test.GtFieldString",
expected: "GtFieldString doit être supérieur à MaxString",
},
{
ns: "Test.GteFieldString",
expected: "GteFieldString doit être supérieur ou égal à MaxString",
},
{
ns: "Test.NeFieldString",
expected: "NeFieldString ne doit pas être égal à EqFieldString",
},
{
ns: "Test.LtCSFieldString",
expected: "LtCSFieldString doit être inférieur à Inner.LtCSFieldString",
},
{
ns: "Test.LteCSFieldString",
expected: "LteCSFieldString doit être inférieur ou égal à Inner.LteCSFieldString",
},
{
ns: "Test.GtCSFieldString",
expected: "GtCSFieldString doit être supérieur à Inner.GtCSFieldString",
},
{
ns: "Test.GteCSFieldString",
expected: "GteCSFieldString doit être supérieur ou égal à Inner.GteCSFieldString",
},
{
ns: "Test.NeCSFieldString",
expected: "NeCSFieldString ne doit pas être égal à Inner.NeCSFieldString",
},
{
ns: "Test.EqCSFieldString",
expected: "EqCSFieldString doit être égal à Inner.EqCSFieldString",
},
{
ns: "Test.EqFieldString",
expected: "EqFieldString doit être égal à MaxString",
},
{
ns: "Test.GteString",
expected: "GteString doit faire une taille d'au moins 3 caractères",
},
{
ns: "Test.GteNumber",
expected: "GteNumber doit être 5,56 ou plus",
},
{
ns: "Test.GteMultiple",
expected: "GteMultiple doit contenir au moins 2 elements",
},
{
ns: "Test.GteTime",
expected: "GteTime doit être après ou pendant la date et l'heure actuelle",
},
{
ns: "Test.GtString",
expected: "GtString doit avoir une taille supérieur à 3 caractères",
},
{
ns: "Test.GtNumber",
expected: "GtNumber doit être supérieur à 5,56",
},
{
ns: "Test.GtMultiple",
expected: "GtMultiple doit contenir plus de 2 elements",
},
{
ns: "Test.GtTime",
expected: "GtTime doit être après la date et l'heure actuelle",
},
{
ns: "Test.LteString",
expected: "LteString doit faire une taille maximum de 3 caractères",
},
{
ns: "Test.LteNumber",
expected: "LteNumber doit faire 5,56 ou moins",
},
{
ns: "Test.LteMultiple",
expected: "LteMultiple doit contenir un maximum de 2 elements",
},
{
ns: "Test.LteTime",
expected: "LteTime doit être avant ou pendant la date et l'heure actuelle",
},
{
ns: "Test.LtString",
expected: "LtString doit avoir une taille inférieure à 3 caractères",
},
{
ns: "Test.LtNumber",
expected: "LtNumber doit être inférieur à 5,56",
},
{
ns: "Test.LtMultiple",
expected: "LtMultiple doit contenir mois de 2 elements",
},
{
ns: "Test.LtTime",
expected: "LtTime doit être avant la date et l'heure actuelle",
},
{
ns: "Test.NeString",
expected: "NeString ne doit pas être égal à ",
},
{
ns: "Test.NeNumber",
expected: "NeNumber ne doit pas être égal à 0.00",
},
{
ns: "Test.NeMultiple",
expected: "NeMultiple ne doit pas être égal à 0",
},
{
ns: "Test.EqString",
expected: "EqString n'est pas égal à 3",
},
{
ns: "Test.EqNumber",
expected: "EqNumber n'est pas égal à 2.33",
},
{
ns: "Test.EqMultiple",
expected: "EqMultiple n'est pas égal à 7",
},
{
ns: "Test.MaxString",
expected: "MaxString doit faire une taille maximum de 3 caractères",
},
{
ns: "Test.MaxNumber",
expected: "MaxNumber doit être égal à 1113,00 ou moins",
},
{
ns: "Test.MaxMultiple",
expected: "MaxMultiple doit contenir au maximum 7 elements",
},
{
ns: "Test.MinString",
expected: "MinString doit faire une taille minimum de 1 caractère",
},
{
ns: "Test.MinNumber",
expected: "MinNumber doit être égal à 1113,00 ou plus",
},
{
ns: "Test.MinMultiple",
expected: "MinMultiple doit contenir au moins 7 elements",
},
{
ns: "Test.LenString",
expected: "LenString doit faire une taille de 1 caractère",
},
{
ns: "Test.LenNumber",
expected: "LenNumber doit être égal à 1113,00",
},
{
ns: "Test.LenMultiple",
expected: "LenMultiple doit contenir 7 elements",
},
{
ns: "Test.RequiredString",
expected: "RequiredString est un champ obligatoire",
},
{
ns: "Test.RequiredNumber",
expected: "RequiredNumber est un champ obligatoire",
},
{
ns: "Test.RequiredMultiple",
expected: "RequiredMultiple est un champ obligatoire",
},
{
ns: "Test.StrPtrMinLen",
expected: "StrPtrMinLen doit faire une taille minimum de 10 caractères",
},
{
ns: "Test.StrPtrMaxLen",
expected: "StrPtrMaxLen doit faire une taille maximum de 1 caractère",
},
{
ns: "Test.StrPtrLen",
expected: "StrPtrLen doit faire une taille de 2 caractères",
},
{
ns: "Test.StrPtrLt",
expected: "StrPtrLt doit avoir une taille inférieure à 1 caractère",
},
{
ns: "Test.StrPtrLte",
expected: "StrPtrLte doit faire une taille maximum de 1 caractère",
},
{
ns: "Test.StrPtrGt",
expected: "StrPtrGt doit avoir une taille supérieur à 10 caractères",
},
{
ns: "Test.StrPtrGte",
expected: "StrPtrGte doit faire une taille d'au moins 10 caractères",
},
{
ns: "Test.OneOfString",
expected: "OneOfString doit être l'un des choix suivants [red green]",
},
{
ns: "Test.OneOfInt",
expected: "OneOfInt doit être l'un des choix suivants [5 63]",
},
}
for _, tt := range tests {
var fe validator.FieldError
for _, e := range errs {
if tt.ns == e.Namespace() {
fe = e
break
}
}
NotEqual(t, fe, nil)
Equal(t, tt.expected, fe.Translate(trans))
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,639 @@
package id
import (
"testing"
"time"
. "github.com/go-playground/assert/v2"
indonesia "github.com/go-playground/locales/id"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
)
func TestTranslations(t *testing.T) {
idn := indonesia.New()
uni := ut.New(idn, idn)
trans, _ := uni.GetTranslator("id")
validate := validator.New()
err := RegisterDefaultTranslations(validate, trans)
Equal(t, err, nil)
type Inner struct {
EqCSFieldString string
NeCSFieldString string
GtCSFieldString string
GteCSFieldString string
LtCSFieldString string
LteCSFieldString string
}
type Test struct {
Inner Inner
RequiredString string `validate:"required"`
RequiredNumber int `validate:"required"`
RequiredMultiple []string `validate:"required"`
LenString string `validate:"len=1"`
LenNumber float64 `validate:"len=1113.00"`
LenMultiple []string `validate:"len=7"`
MinString string `validate:"min=1"`
MinNumber float64 `validate:"min=1113.00"`
MinMultiple []string `validate:"min=7"`
MaxString string `validate:"max=3"`
MaxNumber float64 `validate:"max=1113.00"`
MaxMultiple []string `validate:"max=7"`
EqString string `validate:"eq=3"`
EqNumber float64 `validate:"eq=2.33"`
EqMultiple []string `validate:"eq=7"`
NeString string `validate:"ne="`
NeNumber float64 `validate:"ne=0.00"`
NeMultiple []string `validate:"ne=0"`
LtString string `validate:"lt=3"`
LtNumber float64 `validate:"lt=5.56"`
LtMultiple []string `validate:"lt=2"`
LtTime time.Time `validate:"lt"`
LteString string `validate:"lte=3"`
LteNumber float64 `validate:"lte=5.56"`
LteMultiple []string `validate:"lte=2"`
LteTime time.Time `validate:"lte"`
GtString string `validate:"gt=3"`
GtNumber float64 `validate:"gt=5.56"`
GtMultiple []string `validate:"gt=2"`
GtTime time.Time `validate:"gt"`
GteString string `validate:"gte=3"`
GteNumber float64 `validate:"gte=5.56"`
GteMultiple []string `validate:"gte=2"`
GteTime time.Time `validate:"gte"`
EqFieldString string `validate:"eqfield=MaxString"`
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"`
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"`
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"`
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"`
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"`
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"`
NeFieldString string `validate:"nefield=EqFieldString"`
GtFieldString string `validate:"gtfield=MaxString"`
GteFieldString string `validate:"gtefield=MaxString"`
LtFieldString string `validate:"ltfield=MaxString"`
LteFieldString string `validate:"ltefield=MaxString"`
AlphaString string `validate:"alpha"`
AlphanumString string `validate:"alphanum"`
NumericString string `validate:"numeric"`
NumberString string `validate:"number"`
HexadecimalString string `validate:"hexadecimal"`
HexColorString string `validate:"hexcolor"`
RGBColorString string `validate:"rgb"`
RGBAColorString string `validate:"rgba"`
HSLColorString string `validate:"hsl"`
HSLAColorString string `validate:"hsla"`
Email string `validate:"email"`
URL string `validate:"url"`
URI string `validate:"uri"`
Base64 string `validate:"base64"`
Contains string `validate:"contains=tujuan"`
ContainsAny string `validate:"containsany=!@#$"`
Excludes string `validate:"excludes=text"`
ExcludesAll string `validate:"excludesall=!@#$"`
ExcludesRune string `validate:"excludesrune=☻"`
ISBN string `validate:"isbn"`
ISBN10 string `validate:"isbn10"`
ISBN13 string `validate:"isbn13"`
UUID string `validate:"uuid"`
UUID3 string `validate:"uuid3"`
UUID4 string `validate:"uuid4"`
UUID5 string `validate:"uuid5"`
ULID string `validate:"ulid"`
ASCII string `validate:"ascii"`
PrintableASCII string `validate:"printascii"`
MultiByte string `validate:"multibyte"`
DataURI string `validate:"datauri"`
Latitude string `validate:"latitude"`
Longitude string `validate:"longitude"`
SSN string `validate:"ssn"`
IP string `validate:"ip"`
IPv4 string `validate:"ipv4"`
IPv6 string `validate:"ipv6"`
CIDR string `validate:"cidr"`
CIDRv4 string `validate:"cidrv4"`
CIDRv6 string `validate:"cidrv6"`
TCPAddr string `validate:"tcp_addr"`
TCPAddrv4 string `validate:"tcp4_addr"`
TCPAddrv6 string `validate:"tcp6_addr"`
UDPAddr string `validate:"udp_addr"`
UDPAddrv4 string `validate:"udp4_addr"`
UDPAddrv6 string `validate:"udp6_addr"`
IPAddr string `validate:"ip_addr"`
IPAddrv4 string `validate:"ip4_addr"`
IPAddrv6 string `validate:"ip6_addr"`
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"`
StrPtrMaxLen *string `validate:"max=1"`
StrPtrLen *string `validate:"len=2"`
StrPtrLt *string `validate:"lt=1"`
StrPtrLte *string `validate:"lte=1"`
StrPtrGt *string `validate:"gt=10"`
StrPtrGte *string `validate:"gte=10"`
OneOfString string `validate:"oneof=merah hijau"`
OneOfInt int `validate:"oneof=5 63"`
}
var test Test
test.Inner.EqCSFieldString = "1234"
test.Inner.GtCSFieldString = "1234"
test.Inner.GteCSFieldString = "1234"
test.MaxString = "1234"
test.MaxNumber = 2000
test.MaxMultiple = make([]string, 9)
test.LtString = "1234"
test.LtNumber = 6
test.LtMultiple = make([]string, 3)
test.LtTime = time.Now().Add(time.Hour * 24)
test.LteString = "1234"
test.LteNumber = 6
test.LteMultiple = make([]string, 3)
test.LteTime = time.Now().Add(time.Hour * 24)
test.LtFieldString = "12345"
test.LteFieldString = "12345"
test.LtCSFieldString = "1234"
test.LteCSFieldString = "1234"
test.AlphaString = "abc3"
test.AlphanumString = "abc3!"
test.NumericString = "12E.00"
test.NumberString = "12E"
test.Excludes = "this is some test text"
test.ExcludesAll = "This is Great!"
test.ExcludesRune = "Love it ☻"
test.ASCII = "カタカナ"
test.PrintableASCII = "カタカナ"
test.MultiByte = "1234feerf"
s := "toolong"
test.StrPtrMaxLen = &s
test.StrPtrLen = &s
err = validate.Struct(test)
NotEqual(t, err, nil)
errs, ok := err.(validator.ValidationErrors)
Equal(t, ok, true)
tests := []struct {
ns string
expected string
}{
{
ns: "Test.IsColor",
expected: "IsColor harus berupa warna yang valid",
},
{
ns: "Test.MAC",
expected: "MAC harus berisi alamat MAC yang valid",
},
{
ns: "Test.IPAddr",
expected: "IPAddr harus berupa alamat IP yang dapat dipecahkan",
},
{
ns: "Test.IPAddrv4",
expected: "IPAddrv4 harus berupa alamat IPv4 yang dapat diatasi",
},
{
ns: "Test.IPAddrv6",
expected: "IPAddrv6 harus berupa alamat IPv6 yang dapat diatasi",
},
{
ns: "Test.UDPAddr",
expected: "UDPAddr harus berupa alamat UDP yang valid",
},
{
ns: "Test.UDPAddrv4",
expected: "UDPAddrv4 harus berupa alamat IPv4 UDP yang valid",
},
{
ns: "Test.UDPAddrv6",
expected: "UDPAddrv6 harus berupa alamat IPv6 UDP yang valid",
},
{
ns: "Test.TCPAddr",
expected: "TCPAddr harus berupa alamat TCP yang valid",
},
{
ns: "Test.TCPAddrv4",
expected: "TCPAddrv4 harus berupa alamat TCP IPv4 yang valid",
},
{
ns: "Test.TCPAddrv6",
expected: "TCPAddrv6 harus berupa alamat TCP IPv6 yang valid",
},
{
ns: "Test.CIDR",
expected: "CIDR harus berisi notasi CIDR yang valid",
},
{
ns: "Test.CIDRv4",
expected: "CIDRv4 harus berisi notasi CIDR yang valid untuk alamat IPv4",
},
{
ns: "Test.CIDRv6",
expected: "CIDRv6 harus berisi notasi CIDR yang valid untuk alamat IPv6",
},
{
ns: "Test.SSN",
expected: "SSN harus berupa nomor SSN yang valid",
},
{
ns: "Test.IP",
expected: "IP harus berupa alamat IP yang valid",
},
{
ns: "Test.IPv4",
expected: "IPv4 harus berupa alamat IPv4 yang valid",
},
{
ns: "Test.IPv6",
expected: "IPv6 harus berupa alamat IPv6 yang valid",
},
{
ns: "Test.DataURI",
expected: "DataURI harus berisi URI Data yang valid",
},
{
ns: "Test.Latitude",
expected: "Latitude harus berisi koordinat lintang yang valid",
},
{
ns: "Test.Longitude",
expected: "Longitude harus berisi koordinat bujur yang valid",
},
{
ns: "Test.MultiByte",
expected: "MultiByte harus berisi karakter multibyte",
},
{
ns: "Test.ASCII",
expected: "ASCII hanya boleh berisi karakter ascii",
},
{
ns: "Test.PrintableASCII",
expected: "PrintableASCII hanya boleh berisi karakter ascii yang dapat dicetak",
},
{
ns: "Test.UUID",
expected: "UUID harus berupa UUID yang valid",
},
{
ns: "Test.UUID3",
expected: "UUID3 harus berupa UUID versi 3 yang valid",
},
{
ns: "Test.UUID4",
expected: "UUID4 harus berupa UUID versi 4 yang valid",
},
{
ns: "Test.UUID5",
expected: "UUID5 harus berupa UUID versi 5 yang valid",
},
{
ns: "Test.ULID",
expected: "ULID harus berupa ULID yang valid",
},
{
ns: "Test.ISBN",
expected: "ISBN harus berupa nomor ISBN yang valid",
},
{
ns: "Test.ISBN10",
expected: "ISBN10 harus berupa nomor ISBN-10 yang valid",
},
{
ns: "Test.ISBN13",
expected: "ISBN13 harus berupa nomor ISBN-13 yang valid",
},
{
ns: "Test.Excludes",
expected: "Excludes tidak boleh berisi teks 'text'",
},
{
ns: "Test.ExcludesAll",
expected: "ExcludesAll tidak boleh berisi salah satu karakter berikut '!@#$'",
},
{
ns: "Test.ExcludesRune",
expected: "ExcludesRune tidak boleh berisi '☻'",
},
{
ns: "Test.ContainsAny",
expected: "ContainsAny harus berisi setidaknya salah satu karakter berikut '!@#$'",
},
{
ns: "Test.Contains",
expected: "Contains harus berisi teks 'tujuan'",
},
{
ns: "Test.Base64",
expected: "Base64 harus berupa string Base64 yang valid",
},
{
ns: "Test.Email",
expected: "Email harus berupa alamat email yang valid",
},
{
ns: "Test.URL",
expected: "URL harus berupa URL yang valid",
},
{
ns: "Test.URI",
expected: "URI harus berupa URI yang valid",
},
{
ns: "Test.RGBColorString",
expected: "RGBColorString harus berupa warna RGB yang valid",
},
{
ns: "Test.RGBAColorString",
expected: "RGBAColorString harus berupa warna RGBA yang valid",
},
{
ns: "Test.HSLColorString",
expected: "HSLColorString harus berupa warna HSL yang valid",
},
{
ns: "Test.HSLAColorString",
expected: "HSLAColorString harus berupa warna HSLA yang valid",
},
{
ns: "Test.HexadecimalString",
expected: "HexadecimalString harus berupa heksadesimal yang valid",
},
{
ns: "Test.HexColorString",
expected: "HexColorString harus berupa warna HEX yang valid",
},
{
ns: "Test.NumberString",
expected: "NumberString harus berupa angka yang valid",
},
{
ns: "Test.NumericString",
expected: "NumericString harus berupa nilai numerik yang valid",
},
{
ns: "Test.AlphanumString",
expected: "AlphanumString hanya dapat berisi karakter alfanumerik",
},
{
ns: "Test.AlphaString",
expected: "AlphaString hanya dapat berisi karakter abjad",
},
{
ns: "Test.LtFieldString",
expected: "LtFieldString harus kurang dari MaxString",
},
{
ns: "Test.LteFieldString",
expected: "LteFieldString harus kurang dari atau sama dengan MaxString",
},
{
ns: "Test.GtFieldString",
expected: "GtFieldString harus lebih besar dari MaxString",
},
{
ns: "Test.GteFieldString",
expected: "GteFieldString harus lebih besar dari atau sama dengan MaxString",
},
{
ns: "Test.NeFieldString",
expected: "NeFieldString tidak sama dengan EqFieldString",
},
{
ns: "Test.LtCSFieldString",
expected: "LtCSFieldString harus kurang dari Inner.LtCSFieldString",
},
{
ns: "Test.LteCSFieldString",
expected: "LteCSFieldString harus kurang dari atau sama dengan Inner.LteCSFieldString",
},
{
ns: "Test.GtCSFieldString",
expected: "GtCSFieldString harus lebih besar dari Inner.GtCSFieldString",
},
{
ns: "Test.GteCSFieldString",
expected: "GteCSFieldString harus lebih besar dari atau sama dengan Inner.GteCSFieldString",
},
{
ns: "Test.NeCSFieldString",
expected: "NeCSFieldString tidak sama dengan Inner.NeCSFieldString",
},
{
ns: "Test.EqCSFieldString",
expected: "EqCSFieldString harus sama dengan Inner.EqCSFieldString",
},
{
ns: "Test.EqFieldString",
expected: "EqFieldString harus sama dengan MaxString",
},
{
ns: "Test.GteString",
expected: "panjang minimal GteString adalah 3 karakter",
},
{
ns: "Test.GteNumber",
expected: "GteNumber harus 5,56 atau lebih besar",
},
{
ns: "Test.GteMultiple",
expected: "GteMultiple harus berisi setidaknya 2 item",
},
{
ns: "Test.GteTime",
expected: "GteTime harus lebih besar dari atau sama dengan tanggal & waktu saat ini",
},
{
ns: "Test.GtString",
expected: "panjang GtString harus lebih dari 3 karakter",
},
{
ns: "Test.GtNumber",
expected: "GtNumber harus lebih besar dari 5,56",
},
{
ns: "Test.GtMultiple",
expected: "GtMultiple harus berisi lebih dari 2 item",
},
{
ns: "Test.GtTime",
expected: "GtTime harus lebih besar dari tanggal & waktu saat ini",
},
{
ns: "Test.LteString",
expected: "panjang maksimal LteString adalah 3 karakter",
},
{
ns: "Test.LteNumber",
expected: "LteNumber harus 5,56 atau kurang",
},
{
ns: "Test.LteMultiple",
expected: "LteMultiple harus berisi maksimal 2 item",
},
{
ns: "Test.LteTime",
expected: "LteTime harus kurang dari atau sama dengan tanggal & waktu saat ini",
},
{
ns: "Test.LtString",
expected: "panjang LtString harus kurang dari 3 karakter",
},
{
ns: "Test.LtNumber",
expected: "LtNumber harus kurang dari 5,56",
},
{
ns: "Test.LtMultiple",
expected: "LtMultiple harus berisi kurang dari 2 item",
},
{
ns: "Test.LtTime",
expected: "LtTime harus kurang dari tanggal & waktu saat ini",
},
{
ns: "Test.NeString",
expected: "NeString tidak sama dengan ",
},
{
ns: "Test.NeNumber",
expected: "NeNumber tidak sama dengan 0.00",
},
{
ns: "Test.NeMultiple",
expected: "NeMultiple tidak sama dengan 0",
},
{
ns: "Test.EqString",
expected: "EqString tidak sama dengan 3",
},
{
ns: "Test.EqNumber",
expected: "EqNumber tidak sama dengan 2.33",
},
{
ns: "Test.EqMultiple",
expected: "EqMultiple tidak sama dengan 7",
},
{
ns: "Test.MaxString",
expected: "panjang maksimal MaxString adalah 3 karakter",
},
{
ns: "Test.MaxNumber",
expected: "MaxNumber harus 1.113,00 atau kurang",
},
{
ns: "Test.MaxMultiple",
expected: "MaxMultiple harus berisi maksimal 7 item",
},
{
ns: "Test.MinString",
expected: "panjang minimal MinString adalah 1 karakter",
},
{
ns: "Test.MinNumber",
expected: "MinNumber harus 1.113,00 atau lebih besar",
},
{
ns: "Test.MinMultiple",
expected: "panjang minimal MinMultiple adalah 7 item",
},
{
ns: "Test.LenString",
expected: "panjang LenString harus 1 karakter",
},
{
ns: "Test.LenNumber",
expected: "LenNumber harus sama dengan 1.113,00",
},
{
ns: "Test.LenMultiple",
expected: "LenMultiple harus berisi 7 item",
},
{
ns: "Test.RequiredString",
expected: "RequiredString wajib diisi",
},
{
ns: "Test.RequiredNumber",
expected: "RequiredNumber wajib diisi",
},
{
ns: "Test.RequiredMultiple",
expected: "RequiredMultiple wajib diisi",
},
{
ns: "Test.StrPtrMinLen",
expected: "panjang minimal StrPtrMinLen adalah 10 karakter",
},
{
ns: "Test.StrPtrMaxLen",
expected: "panjang maksimal StrPtrMaxLen adalah 1 karakter",
},
{
ns: "Test.StrPtrLen",
expected: "panjang StrPtrLen harus 2 karakter",
},
{
ns: "Test.StrPtrLt",
expected: "panjang StrPtrLt harus kurang dari 1 karakter",
},
{
ns: "Test.StrPtrLte",
expected: "panjang maksimal StrPtrLte adalah 1 karakter",
},
{
ns: "Test.StrPtrGt",
expected: "panjang StrPtrGt harus lebih dari 10 karakter",
},
{
ns: "Test.StrPtrGte",
expected: "panjang minimal StrPtrGte adalah 10 karakter",
},
{
ns: "Test.OneOfString",
expected: "OneOfString harus berupa salah satu dari [merah hijau]",
},
{
ns: "Test.OneOfInt",
expected: "OneOfInt harus berupa salah satu dari [5 63]",
},
}
for _, tt := range tests {
var fe validator.FieldError
for _, e := range errs {
if tt.ns == e.Namespace() {
fe = e
break
}
}
NotEqual(t, fe, nil)
Equal(t, tt.expected, fe.Translate(trans))
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,725 @@
package it
import (
"testing"
"time"
. "github.com/go-playground/assert/v2"
italian "github.com/go-playground/locales/it"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
)
func TestTranslations(t *testing.T) {
ita := italian.New()
uni := ut.New(ita, ita)
trans, _ := uni.GetTranslator("it")
validate := validator.New()
err := RegisterDefaultTranslations(validate, trans)
Equal(t, err, nil)
type Inner struct {
EqCSFieldString string
NeCSFieldString string
GtCSFieldString string
GteCSFieldString string
LtCSFieldString string
LteCSFieldString string
}
type Test struct {
Inner Inner
RequiredString string `validate:"required"`
RequiredNumber int `validate:"required"`
RequiredMultiple []string `validate:"required"`
LenString string `validate:"len=1"`
LenNumber float64 `validate:"len=1113.00"`
LenMultiple []string `validate:"len=7"`
MinString string `validate:"min=1"`
MinNumber float64 `validate:"min=1113.00"`
MinMultiple []string `validate:"min=7"`
MaxString string `validate:"max=3"`
MaxNumber float64 `validate:"max=1113.00"`
MaxMultiple []string `validate:"max=7"`
EqString string `validate:"eq=3"`
EqNumber float64 `validate:"eq=2.33"`
EqMultiple []string `validate:"eq=7"`
NeString string `validate:"ne="`
NeNumber float64 `validate:"ne=0.00"`
NeMultiple []string `validate:"ne=0"`
LtString string `validate:"lt=3"`
LtNumber float64 `validate:"lt=5.56"`
LtMultiple []string `validate:"lt=2"`
LtTime time.Time `validate:"lt"`
LteString string `validate:"lte=3"`
LteNumber float64 `validate:"lte=5.56"`
LteMultiple []string `validate:"lte=2"`
LteTime time.Time `validate:"lte"`
GtString string `validate:"gt=3"`
GtNumber float64 `validate:"gt=5.56"`
GtMultiple []string `validate:"gt=2"`
GtTime time.Time `validate:"gt"`
GteString string `validate:"gte=3"`
GteNumber float64 `validate:"gte=5.56"`
GteMultiple []string `validate:"gte=2"`
GteTime time.Time `validate:"gte"`
EqFieldString string `validate:"eqfield=MaxString"`
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"`
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"`
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"`
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"`
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"`
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"`
NeFieldString string `validate:"nefield=EqFieldString"`
GtFieldString string `validate:"gtfield=MaxString"`
GteFieldString string `validate:"gtefield=MaxString"`
LtFieldString string `validate:"ltfield=MaxString"`
LteFieldString string `validate:"ltefield=MaxString"`
AlphaString string `validate:"alpha"`
AlphanumString string `validate:"alphanum"`
NumericString string `validate:"numeric"`
NumberString string `validate:"number"`
HexadecimalString string `validate:"hexadecimal"`
HexColorString string `validate:"hexcolor"`
RGBColorString string `validate:"rgb"`
RGBAColorString string `validate:"rgba"`
HSLColorString string `validate:"hsl"`
HSLAColorString string `validate:"hsla"`
Email string `validate:"email"`
URL string `validate:"url"`
URI string `validate:"uri"`
Base64 string `validate:"base64"`
Contains string `validate:"contains=purpose"`
ContainsAny string `validate:"containsany=!@#$"`
Excludes string `validate:"excludes=text"`
ExcludesAll string `validate:"excludesall=!@#$"`
ExcludesRune string `validate:"excludesrune=☻"`
ISBN string `validate:"isbn"`
ISBN10 string `validate:"isbn10"`
ISBN13 string `validate:"isbn13"`
UUID string `validate:"uuid"`
UUID3 string `validate:"uuid3"`
UUID4 string `validate:"uuid4"`
UUID5 string `validate:"uuid5"`
ULID string `validate:"ulid"`
ASCII string `validate:"ascii"`
PrintableASCII string `validate:"printascii"`
MultiByte string `validate:"multibyte"`
DataURI string `validate:"datauri"`
Latitude string `validate:"latitude"`
Longitude string `validate:"longitude"`
SSN string `validate:"ssn"`
IP string `validate:"ip"`
IPv4 string `validate:"ipv4"`
IPv6 string `validate:"ipv6"`
CIDR string `validate:"cidr"`
CIDRv4 string `validate:"cidrv4"`
CIDRv6 string `validate:"cidrv6"`
TCPAddr string `validate:"tcp_addr"`
TCPAddrv4 string `validate:"tcp4_addr"`
TCPAddrv6 string `validate:"tcp6_addr"`
UDPAddr string `validate:"udp_addr"`
UDPAddrv4 string `validate:"udp4_addr"`
UDPAddrv6 string `validate:"udp6_addr"`
IPAddr string `validate:"ip_addr"`
IPAddrv4 string `validate:"ip4_addr"`
IPAddrv6 string `validate:"ip6_addr"`
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"`
StrPtrMaxLen *string `validate:"max=1"`
StrPtrLen *string `validate:"len=2"`
StrPtrLt *string `validate:"lt=1"`
StrPtrLte *string `validate:"lte=1"`
StrPtrGt *string `validate:"gt=10"`
StrPtrGte *string `validate:"gte=10"`
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"`
BooleanString string `validate:"boolean"`
JSONString string `validate:"json"`
JWTString string `validate:"jwt"`
LowercaseString string `validate:"lowercase"`
UppercaseString string `validate:"uppercase"`
StartsWithString string `validate:"startswith=foo"`
StartsNotWithString string `validate:"startsnotwith=foo"`
EndsWithString string `validate:"endswith=foo"`
EndsNotWithString string `validate:"endsnotwith=foo"`
Datetime string `validate:"datetime=2006-01-02"`
PostCode string `validate:"postcode_iso3166_alpha2=SG"`
PostCodeCountry string
PostCodeByField string `validate:"postcode_iso3166_alpha2_field=PostCodeCountry"`
}
var test Test
test.Inner.EqCSFieldString = "1234"
test.Inner.GtCSFieldString = "1234"
test.Inner.GteCSFieldString = "1234"
test.MaxString = "1234"
test.MaxNumber = 2000
test.MaxMultiple = make([]string, 9)
test.LtString = "1234"
test.LtNumber = 6
test.LtMultiple = make([]string, 3)
test.LtTime = time.Now().Add(time.Hour * 24)
test.LteString = "1234"
test.LteNumber = 6
test.LteMultiple = make([]string, 3)
test.LteTime = time.Now().Add(time.Hour * 24)
test.LtFieldString = "12345"
test.LteFieldString = "12345"
test.LtCSFieldString = "1234"
test.LteCSFieldString = "1234"
test.AlphaString = "abc3"
test.AlphanumString = "abc3!"
test.NumericString = "12E.00"
test.NumberString = "12E"
test.Excludes = "this is some test text"
test.ExcludesAll = "This is Great!"
test.ExcludesRune = "Love it ☻"
test.ASCII = "カタカナ"
test.PrintableASCII = "カタカナ"
test.MultiByte = "1234feerf"
test.LowercaseString = "ABCDEFG"
test.UppercaseString = "abcdefg"
test.StartsWithString = "hello"
test.StartsNotWithString = "foo-hello"
test.EndsWithString = "hello"
test.EndsNotWithString = "hello-foo"
s := "toolong"
test.StrPtrMaxLen = &s
test.StrPtrLen = &s
test.UniqueSlice = []string{"1234", "1234"}
test.UniqueMap = map[string]string{"key1": "1234", "key2": "1234"}
test.Datetime = "2008-Feb-01"
err = validate.Struct(test)
NotEqual(t, err, nil)
errs, ok := err.(validator.ValidationErrors)
Equal(t, ok, true)
tests := []struct {
ns string
expected string
}{
{
ns: "Test.IsColor",
expected: "IsColor deve essere un colore valido",
},
{
ns: "Test.MAC",
expected: "MAC deve contenere un indirizzo MAC valido",
},
{
ns: "Test.IPAddr",
expected: "IPAddr deve essere un indirizzo IP risolvibile",
},
{
ns: "Test.IPAddrv4",
expected: "IPAddrv4 deve essere un indirizzo IPv4 risolvibile",
},
{
ns: "Test.IPAddrv6",
expected: "IPAddrv6 deve essere un indirizzo IPv6 risolvibile",
},
{
ns: "Test.UDPAddr",
expected: "UDPAddr deve essere un indirizzo UDP valido",
},
{
ns: "Test.UDPAddrv4",
expected: "UDPAddrv4 deve essere un indirizzo IPv4 UDP valido",
},
{
ns: "Test.UDPAddrv6",
expected: "UDPAddrv6 deve essere un indirizzo IPv6 UDP valido",
},
{
ns: "Test.TCPAddr",
expected: "TCPAddr deve essere un indirizzo TCP valido",
},
{
ns: "Test.TCPAddrv4",
expected: "TCPAddrv4 deve essere un indirizzo IPv4 TCP valido",
},
{
ns: "Test.TCPAddrv6",
expected: "TCPAddrv6 deve essere un indirizzo IPv6 TCP valido",
},
{
ns: "Test.CIDR",
expected: "CIDR deve contenere una notazione CIDR valida",
},
{
ns: "Test.CIDRv4",
expected: "CIDRv4 deve contenere una notazione CIDR per un indirizzo IPv4 valida",
},
{
ns: "Test.CIDRv6",
expected: "CIDRv6 deve contenere una notazione CIDR per un indirizzo IPv6 valida",
},
{
ns: "Test.SSN",
expected: "SSN deve essere un numero SSN valido",
},
{
ns: "Test.IP",
expected: "IP deve essere un indirizzo IP valido",
},
{
ns: "Test.IPv4",
expected: "IPv4 deve essere un indirizzo IPv4 valido",
},
{
ns: "Test.IPv6",
expected: "IPv6 deve essere un indirizzo IPv6 valido",
},
{
ns: "Test.DataURI",
expected: "DataURI deve contenere un Data URI valido",
},
{
ns: "Test.Latitude",
expected: "Latitude deve contenere una latitudine valida",
},
{
ns: "Test.Longitude",
expected: "Longitude deve contenere una longitudine valida",
},
{
ns: "Test.MultiByte",
expected: "MultiByte deve contenere caratteri multibyte",
},
{
ns: "Test.ASCII",
expected: "ASCII deve contenere solo caratteri ascii",
},
{
ns: "Test.PrintableASCII",
expected: "PrintableASCII deve contenere solo caratteri ascii stampabili",
},
{
ns: "Test.UUID",
expected: "UUID deve essere un UUID valido",
},
{
ns: "Test.UUID3",
expected: "UUID3 deve essere un UUID versione 3 valido",
},
{
ns: "Test.UUID4",
expected: "UUID4 deve essere un UUID versione 4 valido",
},
{
ns: "Test.UUID5",
expected: "UUID5 deve essere un UUID versione 5 valido",
},
{
ns: "Test.ULID",
expected: "ULID deve essere un ULID valido",
},
{
ns: "Test.ISBN",
expected: "ISBN deve essere un numero ISBN valido",
},
{
ns: "Test.ISBN10",
expected: "ISBN10 deve essere un numero ISBN-10 valido",
},
{
ns: "Test.ISBN13",
expected: "ISBN13 deve essere un numero ISBN-13 valido",
},
{
ns: "Test.Excludes",
expected: "Excludes non deve contenere il testo 'text'",
},
{
ns: "Test.ExcludesAll",
expected: "ExcludesAll non deve contenere alcuno dei seguenti caratteri '!@#$'",
},
{
ns: "Test.ExcludesRune",
expected: "ExcludesRune non deve contenere '☻'",
},
{
ns: "Test.ContainsAny",
expected: "ContainsAny deve contenere almeno uno dei seguenti caratteri '!@#$'",
},
{
ns: "Test.Contains",
expected: "Contains deve contenere il testo 'purpose'",
},
{
ns: "Test.Base64",
expected: "Base64 deve essere una stringa Base64 valida",
},
{
ns: "Test.Email",
expected: "Email deve essere un indirizzo email valido",
},
{
ns: "Test.URL",
expected: "URL deve essere un URL valido",
},
{
ns: "Test.URI",
expected: "URI deve essere un URI valido",
},
{
ns: "Test.RGBColorString",
expected: "RGBColorString deve essere un colore RGB valido",
},
{
ns: "Test.RGBAColorString",
expected: "RGBAColorString deve essere un colore RGBA valido",
},
{
ns: "Test.HSLColorString",
expected: "HSLColorString deve essere un colore HSL valido",
},
{
ns: "Test.HSLAColorString",
expected: "HSLAColorString deve essere un colore HSLA valido",
},
{
ns: "Test.HexadecimalString",
expected: "HexadecimalString deve essere un esadecimale valido",
},
{
ns: "Test.HexColorString",
expected: "HexColorString deve essere un colore HEX valido",
},
{
ns: "Test.NumberString",
expected: "NumberString deve essere un numero valido",
},
{
ns: "Test.NumericString",
expected: "NumericString deve essere un valore numerico valido",
},
{
ns: "Test.AlphanumString",
expected: "AlphanumString può contenere solo caratteri alfanumerici",
},
{
ns: "Test.AlphaString",
expected: "AlphaString può contenere solo caratteri alfabetici",
},
{
ns: "Test.LtFieldString",
expected: "LtFieldString deve essere minore di MaxString",
},
{
ns: "Test.LteFieldString",
expected: "LteFieldString deve essere minore o uguale a MaxString",
},
{
ns: "Test.GtFieldString",
expected: "GtFieldString deve essere maggiore di MaxString",
},
{
ns: "Test.GteFieldString",
expected: "GteFieldString deve essere maggiore o uguale a MaxString",
},
{
ns: "Test.NeFieldString",
expected: "NeFieldString deve essere diverso da EqFieldString",
},
{
ns: "Test.LtCSFieldString",
expected: "LtCSFieldString deve essere minore di Inner.LtCSFieldString",
},
{
ns: "Test.LteCSFieldString",
expected: "LteCSFieldString deve essere minore o uguale a Inner.LteCSFieldString",
},
{
ns: "Test.GtCSFieldString",
expected: "GtCSFieldString deve essere maggiore di Inner.GtCSFieldString",
},
{
ns: "Test.GteCSFieldString",
expected: "GteCSFieldString deve essere maggiore o uguale a Inner.GteCSFieldString",
},
{
ns: "Test.NeCSFieldString",
expected: "NeCSFieldString deve essere diverso da Inner.NeCSFieldString",
},
{
ns: "Test.EqCSFieldString",
expected: "EqCSFieldString deve essere uguale a Inner.EqCSFieldString",
},
{
ns: "Test.EqFieldString",
expected: "EqFieldString deve essere uguale a MaxString",
},
{
ns: "Test.GteString",
expected: "GteString deve essere lungo almeno 3 caratteri",
},
{
ns: "Test.GteNumber",
expected: "GteNumber deve essere maggiore o uguale a 5,56",
},
{
ns: "Test.GteMultiple",
expected: "GteMultiple deve contenere almeno 2 elementi",
},
{
ns: "Test.GteTime",
expected: "GteTime deve essere uguale o successivo alla Data/Ora corrente",
},
{
ns: "Test.GtString",
expected: "GtString deve essere lungo più di 3 caratteri",
},
{
ns: "Test.GtNumber",
expected: "GtNumber deve essere maggiore di 5,56",
},
{
ns: "Test.GtMultiple",
expected: "GtMultiple deve contenere più di 2 elementi",
},
{
ns: "Test.GtTime",
expected: "GtTime deve essere successivo alla Data/Ora corrente",
},
{
ns: "Test.LteString",
expected: "LteString deve essere lungo al massimo 3 caratteri",
},
{
ns: "Test.LteNumber",
expected: "LteNumber deve essere minore o uguale a 5,56",
},
{
ns: "Test.LteMultiple",
expected: "LteMultiple deve contenere al massimo 2 elementi",
},
{
ns: "Test.LteTime",
expected: "LteTime deve essere uguale o precedente alla Data/Ora corrente",
},
{
ns: "Test.LtString",
expected: "LtString deve essere lungo meno di 3 caratteri",
},
{
ns: "Test.LtNumber",
expected: "LtNumber deve essere minore di 5,56",
},
{
ns: "Test.LtMultiple",
expected: "LtMultiple deve contenere meno di 2 elementi",
},
{
ns: "Test.LtTime",
expected: "LtTime deve essere precedente alla Data/Ora corrente",
},
{
ns: "Test.NeString",
expected: "NeString deve essere diverso da ",
},
{
ns: "Test.NeNumber",
expected: "NeNumber deve essere diverso da 0.00",
},
{
ns: "Test.NeMultiple",
expected: "NeMultiple deve essere diverso da 0",
},
{
ns: "Test.EqString",
expected: "EqString non è uguale a 3",
},
{
ns: "Test.EqNumber",
expected: "EqNumber non è uguale a 2.33",
},
{
ns: "Test.EqMultiple",
expected: "EqMultiple non è uguale a 7",
},
{
ns: "Test.MaxString",
expected: "MaxString deve essere lungo al massimo 3 caratteri",
},
{
ns: "Test.MaxNumber",
expected: "MaxNumber deve essere minore o uguale a 1.113,00",
},
{
ns: "Test.MaxMultiple",
expected: "MaxMultiple deve contenere al massimo 7 elementi",
},
{
ns: "Test.MinString",
expected: "MinString deve essere lungo almeno 1 carattere",
},
{
ns: "Test.MinNumber",
expected: "MinNumber deve essere maggiore o uguale a 1.113,00",
},
{
ns: "Test.MinMultiple",
expected: "MinMultiple deve contenere almeno 7 elementi",
},
{
ns: "Test.LenString",
expected: "LenString deve essere lungo 1 carattere",
},
{
ns: "Test.LenNumber",
expected: "LenNumber deve essere uguale a 1.113,00",
},
{
ns: "Test.LenMultiple",
expected: "LenMultiple deve contenere 7 elementi",
},
{
ns: "Test.RequiredString",
expected: "RequiredString è un campo obbligatorio",
},
{
ns: "Test.RequiredNumber",
expected: "RequiredNumber è un campo obbligatorio",
},
{
ns: "Test.RequiredMultiple",
expected: "RequiredMultiple è un campo obbligatorio",
},
{
ns: "Test.StrPtrMinLen",
expected: "StrPtrMinLen deve essere lungo almeno 10 caratteri",
},
{
ns: "Test.StrPtrMaxLen",
expected: "StrPtrMaxLen deve essere lungo al massimo 1 carattere",
},
{
ns: "Test.StrPtrLen",
expected: "StrPtrLen deve essere lungo 2 caratteri",
},
{
ns: "Test.StrPtrLt",
expected: "StrPtrLt deve essere lungo meno di 1 carattere",
},
{
ns: "Test.StrPtrLte",
expected: "StrPtrLte deve essere lungo al massimo 1 carattere",
},
{
ns: "Test.StrPtrGt",
expected: "StrPtrGt deve essere lungo più di 10 caratteri",
},
{
ns: "Test.StrPtrGte",
expected: "StrPtrGte deve essere lungo almeno 10 caratteri",
},
{
ns: "Test.OneOfString",
expected: "OneOfString deve essere uno di [red green]",
},
{
ns: "Test.OneOfInt",
expected: "OneOfInt deve essere uno di [5 63]",
},
{
ns: "Test.UniqueSlice",
expected: "UniqueSlice deve contenere valori unici",
},
{
ns: "Test.UniqueArray",
expected: "UniqueArray deve contenere valori unici",
},
{
ns: "Test.UniqueMap",
expected: "UniqueMap deve contenere valori unici",
},
{
ns: "Test.BooleanString",
expected: "BooleanString deve rappresentare un valore booleano",
},
{
ns: "Test.JSONString",
expected: "JSONString deve essere una stringa json valida",
},
{
ns: "Test.JWTString",
expected: "JWTString deve essere una stringa jwt valida",
},
{
ns: "Test.LowercaseString",
expected: "LowercaseString deve essere una stringa minuscola",
},
{
ns: "Test.UppercaseString",
expected: "UppercaseString deve essere una stringa maiuscola",
},
{
ns: "Test.StartsWithString",
expected: "StartsWithString deve iniziare con foo",
},
{
ns: "Test.StartsNotWithString",
expected: "StartsNotWithString non deve iniziare con foo",
},
{
ns: "Test.EndsWithString",
expected: "EndsWithString deve terminare con foo",
},
{
ns: "Test.EndsNotWithString",
expected: "EndsNotWithString non deve terminare con foo",
},
{
ns: "Test.Datetime",
expected: "Datetime non corrisponde al formato 2006-01-02",
},
{
ns: "Test.PostCode",
expected: "PostCode non corrisponde al formato del codice postale dello stato SG",
},
{
ns: "Test.PostCodeByField",
expected: "PostCodeByField non corrisponde al formato del codice postale dello stato nel campo PostCodeCountry",
},
}
for _, tt := range tests {
var fe validator.FieldError
for _, e := range errs {
if tt.ns == e.Namespace() {
fe = e
break
}
}
NotEqual(t, fe, nil)
Equal(t, tt.expected, fe.Translate(trans))
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,710 @@
package ja
import (
"testing"
"time"
. "github.com/go-playground/assert/v2"
ja_locale "github.com/go-playground/locales/ja"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
)
func TestTranslations(t *testing.T) {
japanese := ja_locale.New()
uni := ut.New(japanese, japanese)
trans, _ := uni.GetTranslator("ja")
validate := validator.New()
err := RegisterDefaultTranslations(validate, trans)
Equal(t, err, nil)
type Inner struct {
EqCSFieldString string
NeCSFieldString string
GtCSFieldString string
GteCSFieldString string
LtCSFieldString string
LteCSFieldString string
RequiredIf string
}
type Test struct {
Inner Inner
RequiredString string `validate:"required"`
RequiredNumber int `validate:"required"`
RequiredMultiple []string `validate:"required"`
RequiredIf string `validate:"required_if=Inner.RequiredIf abcd"`
LenString string `validate:"len=1"`
LenNumber float64 `validate:"len=1113.00"`
LenMultiple []string `validate:"len=7"`
MinString string `validate:"min=1"`
MinNumber float64 `validate:"min=1113.00"`
MinMultiple []string `validate:"min=7"`
MaxString string `validate:"max=3"`
MaxNumber float64 `validate:"max=1113.00"`
MaxMultiple []string `validate:"max=7"`
EqString string `validate:"eq=3"`
EqNumber float64 `validate:"eq=2.33"`
EqMultiple []string `validate:"eq=7"`
NeString string `validate:"ne="`
NeNumber float64 `validate:"ne=0.00"`
NeMultiple []string `validate:"ne=0"`
LtString string `validate:"lt=3"`
LtNumber float64 `validate:"lt=5.56"`
LtMultiple []string `validate:"lt=2"`
LtTime time.Time `validate:"lt"`
LteString string `validate:"lte=3"`
LteNumber float64 `validate:"lte=5.56"`
LteMultiple []string `validate:"lte=2"`
LteTime time.Time `validate:"lte"`
GtString string `validate:"gt=3"`
GtNumber float64 `validate:"gt=5.56"`
GtMultiple []string `validate:"gt=2"`
GtTime time.Time `validate:"gt"`
GteString string `validate:"gte=3"`
GteNumber float64 `validate:"gte=5.56"`
GteMultiple []string `validate:"gte=2"`
GteTime time.Time `validate:"gte"`
EqFieldString string `validate:"eqfield=MaxString"`
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"`
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"`
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"`
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"`
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"`
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"`
NeFieldString string `validate:"nefield=EqFieldString"`
GtFieldString string `validate:"gtfield=MaxString"`
GteFieldString string `validate:"gtefield=MaxString"`
LtFieldString string `validate:"ltfield=MaxString"`
LteFieldString string `validate:"ltefield=MaxString"`
AlphaString string `validate:"alpha"`
AlphanumString string `validate:"alphanum"`
NumericString string `validate:"numeric"`
NumberString string `validate:"number"`
HexadecimalString string `validate:"hexadecimal"`
HexColorString string `validate:"hexcolor"`
RGBColorString string `validate:"rgb"`
RGBAColorString string `validate:"rgba"`
HSLColorString string `validate:"hsl"`
HSLAColorString string `validate:"hsla"`
Email string `validate:"email"`
URL string `validate:"url"`
URI string `validate:"uri"`
Base64 string `validate:"base64"`
Contains string `validate:"contains=purpose"`
ContainsAny string `validate:"containsany=!@#$"`
Excludes string `validate:"excludes=text"`
ExcludesAll string `validate:"excludesall=!@#$"`
ExcludesRune string `validate:"excludesrune=☻"`
ISBN string `validate:"isbn"`
ISBN10 string `validate:"isbn10"`
ISBN13 string `validate:"isbn13"`
UUID string `validate:"uuid"`
UUID3 string `validate:"uuid3"`
UUID4 string `validate:"uuid4"`
UUID5 string `validate:"uuid5"`
ULID string `validate:"ulid"`
ASCII string `validate:"ascii"`
PrintableASCII string `validate:"printascii"`
MultiByte string `validate:"multibyte"`
DataURI string `validate:"datauri"`
Latitude string `validate:"latitude"`
Longitude string `validate:"longitude"`
SSN string `validate:"ssn"`
IP string `validate:"ip"`
IPv4 string `validate:"ipv4"`
IPv6 string `validate:"ipv6"`
CIDR string `validate:"cidr"`
CIDRv4 string `validate:"cidrv4"`
CIDRv6 string `validate:"cidrv6"`
TCPAddr string `validate:"tcp_addr"`
TCPAddrv4 string `validate:"tcp4_addr"`
TCPAddrv6 string `validate:"tcp6_addr"`
UDPAddr string `validate:"udp_addr"`
UDPAddrv4 string `validate:"udp4_addr"`
UDPAddrv6 string `validate:"udp6_addr"`
IPAddr string `validate:"ip_addr"`
IPAddrv4 string `validate:"ip4_addr"`
IPAddrv6 string `validate:"ip6_addr"`
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"`
StrPtrMaxLen *string `validate:"max=1"`
StrPtrLen *string `validate:"len=2"`
StrPtrLt *string `validate:"lt=1"`
StrPtrLte *string `validate:"lte=1"`
StrPtrGt *string `validate:"gt=10"`
StrPtrGte *string `validate:"gte=10"`
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"`
JSONString string `validate:"json"`
JWTString string `validate:"jwt"`
LowercaseString string `validate:"lowercase"`
UppercaseString string `validate:"uppercase"`
Datetime string `validate:"datetime=2006-01-02"`
PostCode string `validate:"postcode_iso3166_alpha2=SG"`
PostCodeCountry string
PostCodeByField string `validate:"postcode_iso3166_alpha2_field=PostCodeCountry"`
BooleanString string `validate:"boolean"`
}
var test Test
test.Inner.EqCSFieldString = "1234"
test.Inner.GtCSFieldString = "1234"
test.Inner.GteCSFieldString = "1234"
test.MaxString = "1234"
test.MaxNumber = 2000
test.MaxMultiple = make([]string, 9)
test.LtString = "1234"
test.LtNumber = 6
test.LtMultiple = make([]string, 3)
test.LtTime = time.Now().Add(time.Hour * 24)
test.LteString = "1234"
test.LteNumber = 6
test.LteMultiple = make([]string, 3)
test.LteTime = time.Now().Add(time.Hour * 24)
test.LtFieldString = "12345"
test.LteFieldString = "12345"
test.LtCSFieldString = "1234"
test.LteCSFieldString = "1234"
test.AlphaString = "abc3"
test.AlphanumString = "abc3!"
test.NumericString = "12E.00"
test.NumberString = "12E"
test.Excludes = "this is some test text"
test.ExcludesAll = "This is Great!"
test.ExcludesRune = "Love it ☻"
test.ASCII = "カタカナ"
test.PrintableASCII = "カタカナ"
test.MultiByte = "1234feerf"
test.LowercaseString = "ABCDEFG"
test.UppercaseString = "abcdefg"
s := "toolong"
test.StrPtrMaxLen = &s
test.StrPtrLen = &s
test.UniqueSlice = []string{"1234", "1234"}
test.UniqueMap = map[string]string{"key1": "1234", "key2": "1234"}
test.Datetime = "2008-Feb-01"
test.BooleanString = "A"
test.Inner.RequiredIf = "abcd"
err = validate.Struct(test)
NotEqual(t, err, nil)
errs, ok := err.(validator.ValidationErrors)
Equal(t, ok, true)
tests := []struct {
ns string
expected string
}{
{
ns: "Test.IsColor",
expected: "IsColorは正しい色でなければなりません",
},
{
ns: "Test.MAC",
expected: "MACは正しいMACアドレスを含まなければなりません",
},
{
ns: "Test.IPAddr",
expected: "IPAddrは解決可能なIPアドレスでなければなりません",
},
{
ns: "Test.IPAddrv4",
expected: "IPAddrv4は解決可能なIPv4アドレスでなければなりません",
},
{
ns: "Test.IPAddrv6",
expected: "IPAddrv6は解決可能なIPv6アドレスでなければなりません",
},
{
ns: "Test.UDPAddr",
expected: "UDPAddrは正しいUDPアドレスでなければなりません",
},
{
ns: "Test.UDPAddrv4",
expected: "UDPAddrv4は正しいIPv4のUDPアドレスでなければなりません",
},
{
ns: "Test.UDPAddrv6",
expected: "UDPAddrv6は正しいIPv6のUDPアドレスでなければなりません",
},
{
ns: "Test.TCPAddr",
expected: "TCPAddrは正しいTCPアドレスでなければなりません",
},
{
ns: "Test.TCPAddrv4",
expected: "TCPAddrv4は正しいIPv4のTCPアドレスでなければなりません",
},
{
ns: "Test.TCPAddrv6",
expected: "TCPAddrv6は正しいIPv6のTCPアドレスでなければなりません",
},
{
ns: "Test.CIDR",
expected: "CIDRは正しいCIDR表記を含まなければなりません",
},
{
ns: "Test.CIDRv4",
expected: "CIDRv4はIPv4アドレスの正しいCIDR表記を含まなければなりません",
},
{
ns: "Test.CIDRv6",
expected: "CIDRv6はIPv6アドレスの正しいCIDR表記を含まなければなりません",
},
{
ns: "Test.SSN",
expected: "SSNは正しい社会保障番号でなければなりません",
},
{
ns: "Test.IP",
expected: "IPは正しいIPアドレスでなければなりません",
},
{
ns: "Test.IPv4",
expected: "IPv4は正しいIPv4アドレスでなければなりません",
},
{
ns: "Test.IPv6",
expected: "IPv6は正しいIPv6アドレスでなければなりません",
},
{
ns: "Test.DataURI",
expected: "DataURIは正しいデータURIを含まなければなりません",
},
{
ns: "Test.Latitude",
expected: "Latitudeは正しい緯度の座標を含まなければなりません",
},
{
ns: "Test.Longitude",
expected: "Longitudeは正しい経度の座標を含まなければなりません",
},
{
ns: "Test.MultiByte",
expected: "MultiByteはマルチバイト文字を含まなければなりません",
},
{
ns: "Test.ASCII",
expected: "ASCIIはASCII文字のみを含まなければなりません",
},
{
ns: "Test.PrintableASCII",
expected: "PrintableASCIIは印刷可能なASCII文字のみを含まなければなりません",
},
{
ns: "Test.UUID",
expected: "UUIDは正しいUUIDでなければなりません",
},
{
ns: "Test.UUID3",
expected: "UUID3はバージョンが3の正しいUUIDでなければなりません",
},
{
ns: "Test.UUID4",
expected: "UUID4はバージョンが4の正しいUUIDでなければなりません",
},
{
ns: "Test.UUID5",
expected: "UUID5はバージョンが5の正しいUUIDでなければなりません",
},
{
ns: "Test.ULID",
expected: "ULIDは正しいULIDでなければなりません",
},
{
ns: "Test.ISBN",
expected: "ISBNは正しいISBN番号でなければなりません",
},
{
ns: "Test.ISBN10",
expected: "ISBN10は正しいISBN-10番号でなければなりません",
},
{
ns: "Test.ISBN13",
expected: "ISBN13は正しいISBN-13番号でなければなりません",
},
{
ns: "Test.Excludes",
expected: "Excludesには'text'というテキストを含むことはできません",
},
{
ns: "Test.ExcludesAll",
expected: "ExcludesAllには'!@#$'のどれも含めることはできません",
},
{
ns: "Test.ExcludesRune",
expected: "ExcludesRuneには'☻'を含めることはできません",
},
{
ns: "Test.ContainsAny",
expected: "ContainsAnyは'!@#$'の少なくとも1つを含まなければなりません",
},
{
ns: "Test.Contains",
expected: "Containsは'purpose'を含まなければなりません",
},
{
ns: "Test.Base64",
expected: "Base64は正しいBase64文字列でなければなりません",
},
{
ns: "Test.Email",
expected: "Emailは正しいメールアドレスでなければなりません",
},
{
ns: "Test.URL",
expected: "URLは正しいURLでなければなりません",
},
{
ns: "Test.URI",
expected: "URIは正しいURIでなければなりません",
},
{
ns: "Test.RGBColorString",
expected: "RGBColorStringは正しいRGBカラーコードでなければなりません",
},
{
ns: "Test.RGBAColorString",
expected: "RGBAColorStringは正しいRGBAカラーコードでなければなりません",
},
{
ns: "Test.HSLColorString",
expected: "HSLColorStringは正しいHSLカラーコードでなければなりません",
},
{
ns: "Test.HSLAColorString",
expected: "HSLAColorStringは正しいHSLAカラーコードでなければなりません",
},
{
ns: "Test.HexadecimalString",
expected: "HexadecimalStringは正しい16進表記でなければなりません",
},
{
ns: "Test.HexColorString",
expected: "HexColorStringは正しいHEXカラーコードでなければなりません",
},
{
ns: "Test.NumberString",
expected: "NumberStringは正しい数でなければなりません",
},
{
ns: "Test.NumericString",
expected: "NumericStringは正しい数字でなければなりません",
},
{
ns: "Test.AlphanumString",
expected: "AlphanumStringはアルファベットと数字のみを含むことができます",
},
{
ns: "Test.AlphaString",
expected: "AlphaStringはアルファベットのみを含むことができます",
},
{
ns: "Test.LtFieldString",
expected: "LtFieldStringはMaxStringよりも小さくなければなりません",
},
{
ns: "Test.LteFieldString",
expected: "LteFieldStringはMaxString以下でなければなりません",
},
{
ns: "Test.GtFieldString",
expected: "GtFieldStringはMaxStringよりも大きくなければなりません",
},
{
ns: "Test.GteFieldString",
expected: "GteFieldStringはMaxString以上でなければなりません",
},
{
ns: "Test.NeFieldString",
expected: "NeFieldStringはEqFieldStringとは異ならなければなりません",
},
{
ns: "Test.LtCSFieldString",
expected: "LtCSFieldStringはInner.LtCSFieldStringよりも小さくなければなりません",
},
{
ns: "Test.LteCSFieldString",
expected: "LteCSFieldStringはInner.LteCSFieldString以下でなければなりません",
},
{
ns: "Test.GtCSFieldString",
expected: "GtCSFieldStringはInner.GtCSFieldStringよりも大きくなければなりません",
},
{
ns: "Test.GteCSFieldString",
expected: "GteCSFieldStringはInner.GteCSFieldString以上でなければなりません",
},
{
ns: "Test.NeCSFieldString",
expected: "NeCSFieldStringはInner.NeCSFieldStringとは異ならなければなりません",
},
{
ns: "Test.EqCSFieldString",
expected: "EqCSFieldStringはInner.EqCSFieldStringと等しくなければなりません",
},
{
ns: "Test.EqFieldString",
expected: "EqFieldStringはMaxStringと等しくなければなりません",
},
{
ns: "Test.GteString",
expected: "GteStringの長さは少なくとも3文字以上はなければなりません",
},
{
ns: "Test.GteNumber",
expected: "GteNumberは5.56以上でなければなりません",
},
{
ns: "Test.GteMultiple",
expected: "GteMultipleは少なくとも2つの項目を含まなければなりません",
},
{
ns: "Test.GteTime",
expected: "GteTimeは現時刻以降でなければなりません",
},
{
ns: "Test.GtString",
expected: "GtStringの長さは3文字よりも多くなければなりません",
},
{
ns: "Test.GtNumber",
expected: "GtNumberは5.56よりも大きくなければなりません",
},
{
ns: "Test.GtMultiple",
expected: "GtMultipleは2つの項目よりも多い項目を含まなければなりません",
},
{
ns: "Test.GtTime",
expected: "GtTimeは現時刻よりも後でなければなりません",
},
{
ns: "Test.LteString",
expected: "LteStringの長さは最大でも3文字でなければなりません",
},
{
ns: "Test.LteNumber",
expected: "LteNumberは5.56以下でなければなりません",
},
{
ns: "Test.LteMultiple",
expected: "LteMultipleは最大でも2つの項目を含まなければなりません",
},
{
ns: "Test.LteTime",
expected: "LteTimeは現時刻以前でなければなりません",
},
{
ns: "Test.LtString",
expected: "LtStringの長さは3文字よりも少なくなければなりません",
},
{
ns: "Test.LtNumber",
expected: "LtNumberは5.56よりも小さくなければなりません",
},
{
ns: "Test.LtMultiple",
expected: "LtMultipleは2つの項目よりも少ない項目を含まなければなりません",
},
{
ns: "Test.LtTime",
expected: "LtTimeは現時刻よりも前でなければなりません",
},
{
ns: "Test.NeString",
expected: "NeStringはと異ならなければなりません",
},
{
ns: "Test.NeNumber",
expected: "NeNumberは0.00と異ならなければなりません",
},
{
ns: "Test.NeMultiple",
expected: "NeMultipleの項目の数は0個と異ならなければなりません",
},
{
ns: "Test.EqString",
expected: "EqStringは3と等しくありません",
},
{
ns: "Test.EqNumber",
expected: "EqNumberは2.33と等しくありません",
},
{
ns: "Test.EqMultiple",
expected: "EqMultipleは7と等しくありません",
},
{
ns: "Test.MaxString",
expected: "MaxStringの長さは最大でも3文字でなければなりません",
},
{
ns: "Test.MaxNumber",
expected: "MaxNumberは1,113.00以下でなければなりません",
},
{
ns: "Test.MaxMultiple",
expected: "MaxMultipleは最大でも7つの項目を含まなければなりません",
},
{
ns: "Test.MinString",
expected: "MinStringの長さは少なくとも1文字はなければなりません",
},
{
ns: "Test.MinNumber",
expected: "MinNumberは1,113.00以上でなければなりません",
},
{
ns: "Test.MinMultiple",
expected: "MinMultipleは少なくとも7つの項目を含まなければなりません",
},
{
ns: "Test.LenString",
expected: "LenStringの長さは1文字でなければなりません",
},
{
ns: "Test.LenNumber",
expected: "LenNumberは1,113.00と等しくなければなりません",
},
{
ns: "Test.LenMultiple",
expected: "LenMultipleは7つの項目を含まなければなりません",
},
{
ns: "Test.RequiredString",
expected: "RequiredStringは必須フィールドです",
},
{
ns: "Test.RequiredIf",
expected: "RequiredIfは必須フィールドです",
},
{
ns: "Test.RequiredNumber",
expected: "RequiredNumberは必須フィールドです",
},
{
ns: "Test.RequiredMultiple",
expected: "RequiredMultipleは必須フィールドです",
},
{
ns: "Test.StrPtrMinLen",
expected: "StrPtrMinLenの長さは少なくとも10文字はなければなりません",
},
{
ns: "Test.StrPtrMaxLen",
expected: "StrPtrMaxLenの長さは最大でも1文字でなければなりません",
},
{
ns: "Test.StrPtrLen",
expected: "StrPtrLenの長さは2文字でなければなりません",
},
{
ns: "Test.StrPtrLt",
expected: "StrPtrLtの長さは1文字よりも少なくなければなりません",
},
{
ns: "Test.StrPtrLte",
expected: "StrPtrLteの長さは最大でも1文字でなければなりません",
},
{
ns: "Test.StrPtrGt",
expected: "StrPtrGtの長さは10文字よりも多くなければなりません",
},
{
ns: "Test.StrPtrGte",
expected: "StrPtrGteの長さは少なくとも10文字以上はなければなりません",
},
{
ns: "Test.OneOfString",
expected: "OneOfStringは[red green]のうちのいずれかでなければなりません",
},
{
ns: "Test.OneOfInt",
expected: "OneOfIntは[5 63]のうちのいずれかでなければなりません",
},
{
ns: "Test.UniqueSlice",
expected: "UniqueSliceは一意な値のみを含まなければなりません",
},
{
ns: "Test.UniqueArray",
expected: "UniqueArrayは一意な値のみを含まなければなりません",
},
{
ns: "Test.UniqueMap",
expected: "UniqueMapは一意な値のみを含まなければなりません",
},
{
ns: "Test.JSONString",
expected: "JSONStringは正しいJSON文字列でなければなりません",
},
{
ns: "Test.JWTString",
expected: "JWTStringは正しいJWT文字列でなければなりません",
},
{
ns: "Test.LowercaseString",
expected: "LowercaseStringは小文字でなければなりません",
},
{
ns: "Test.UppercaseString",
expected: "UppercaseStringは大文字でなければなりません",
},
{
ns: "Test.Datetime",
expected: "Datetimeは2006-01-02の書式と一致しません",
},
{
ns: "Test.PostCode",
expected: "PostCodeは国名コードSGの郵便番号形式と一致しません",
},
{
ns: "Test.PostCodeByField",
expected: "PostCodeByFieldはPostCodeCountryフィールドで指定された国名コードの郵便番号形式と一致しません",
},
{
ns: "Test.BooleanString",
expected: "BooleanStringは正しいブール値でなければなりません",
},
}
for _, tt := range tests {
var fe validator.FieldError
for _, e := range errs {
if tt.ns == e.Namespace() {
fe = e
break
}
}
NotEqual(t, fe, nil)
Equal(t, tt.expected, fe.Translate(trans))
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,709 @@
package lv
import (
"testing"
"time"
. "github.com/go-playground/assert/v2"
english "github.com/go-playground/locales/en"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
)
func TestTranslations(t *testing.T) {
eng := english.New()
uni := ut.New(eng, eng)
trans, _ := uni.GetTranslator("en")
validate := validator.New()
err := RegisterDefaultTranslations(validate, trans)
Equal(t, err, nil)
type Inner struct {
EqCSFieldString string
NeCSFieldString string
GtCSFieldString string
GteCSFieldString string
LtCSFieldString string
LteCSFieldString string
RequiredIf string
}
type Test struct {
Inner Inner
RequiredString string `validate:"required"`
RequiredNumber int `validate:"required"`
RequiredMultiple []string `validate:"required"`
RequiredIf string `validate:"required_if=Inner.RequiredIf abcd"`
LenString string `validate:"len=1"`
LenNumber float64 `validate:"len=1113.00"`
LenMultiple []string `validate:"len=7"`
MinString string `validate:"min=1"`
MinNumber float64 `validate:"min=1113.00"`
MinMultiple []string `validate:"min=7"`
MaxString string `validate:"max=3"`
MaxNumber float64 `validate:"max=1113.00"`
MaxMultiple []string `validate:"max=7"`
EqString string `validate:"eq=3"`
EqNumber float64 `validate:"eq=2.33"`
EqMultiple []string `validate:"eq=7"`
NeString string `validate:"ne="`
NeNumber float64 `validate:"ne=0.00"`
NeMultiple []string `validate:"ne=0"`
LtString string `validate:"lt=3"`
LtNumber float64 `validate:"lt=5.56"`
LtMultiple []string `validate:"lt=2"`
LtTime time.Time `validate:"lt"`
LteString string `validate:"lte=3"`
LteNumber float64 `validate:"lte=5.56"`
LteMultiple []string `validate:"lte=2"`
LteTime time.Time `validate:"lte"`
GtString string `validate:"gt=3"`
GtNumber float64 `validate:"gt=5.56"`
GtMultiple []string `validate:"gt=2"`
GtTime time.Time `validate:"gt"`
GteString string `validate:"gte=3"`
GteNumber float64 `validate:"gte=5.56"`
GteMultiple []string `validate:"gte=2"`
GteTime time.Time `validate:"gte"`
EqFieldString string `validate:"eqfield=MaxString"`
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"`
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"`
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"`
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"`
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"`
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"`
NeFieldString string `validate:"nefield=EqFieldString"`
GtFieldString string `validate:"gtfield=MaxString"`
GteFieldString string `validate:"gtefield=MaxString"`
LtFieldString string `validate:"ltfield=MaxString"`
LteFieldString string `validate:"ltefield=MaxString"`
AlphaString string `validate:"alpha"`
AlphanumString string `validate:"alphanum"`
NumericString string `validate:"numeric"`
NumberString string `validate:"number"`
HexadecimalString string `validate:"hexadecimal"`
HexColorString string `validate:"hexcolor"`
RGBColorString string `validate:"rgb"`
RGBAColorString string `validate:"rgba"`
HSLColorString string `validate:"hsl"`
HSLAColorString string `validate:"hsla"`
Email string `validate:"email"`
URL string `validate:"url"`
URI string `validate:"uri"`
Base64 string `validate:"base64"`
Contains string `validate:"contains=purpose"`
ContainsAny string `validate:"containsany=!@#$"`
Excludes string `validate:"excludes=text"`
ExcludesAll string `validate:"excludesall=!@#$"`
ExcludesRune string `validate:"excludesrune=☻"`
ISBN string `validate:"isbn"`
ISBN10 string `validate:"isbn10"`
ISBN13 string `validate:"isbn13"`
UUID string `validate:"uuid"`
UUID3 string `validate:"uuid3"`
UUID4 string `validate:"uuid4"`
UUID5 string `validate:"uuid5"`
ULID string `validate:"ulid"`
ASCII string `validate:"ascii"`
PrintableASCII string `validate:"printascii"`
MultiByte string `validate:"multibyte"`
DataURI string `validate:"datauri"`
Latitude string `validate:"latitude"`
Longitude string `validate:"longitude"`
SSN string `validate:"ssn"`
IP string `validate:"ip"`
IPv4 string `validate:"ipv4"`
IPv6 string `validate:"ipv6"`
CIDR string `validate:"cidr"`
CIDRv4 string `validate:"cidrv4"`
CIDRv6 string `validate:"cidrv6"`
TCPAddr string `validate:"tcp_addr"`
TCPAddrv4 string `validate:"tcp4_addr"`
TCPAddrv6 string `validate:"tcp6_addr"`
UDPAddr string `validate:"udp_addr"`
UDPAddrv4 string `validate:"udp4_addr"`
UDPAddrv6 string `validate:"udp6_addr"`
IPAddr string `validate:"ip_addr"`
IPAddrv4 string `validate:"ip4_addr"`
IPAddrv6 string `validate:"ip6_addr"`
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"`
StrPtrMaxLen *string `validate:"max=1"`
StrPtrLen *string `validate:"len=2"`
StrPtrLt *string `validate:"lt=1"`
StrPtrLte *string `validate:"lte=1"`
StrPtrGt *string `validate:"gt=10"`
StrPtrGte *string `validate:"gte=10"`
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"`
JSONString string `validate:"json"`
JWTString string `validate:"jwt"`
LowercaseString string `validate:"lowercase"`
UppercaseString string `validate:"uppercase"`
Datetime string `validate:"datetime=2006-01-02"`
PostCode string `validate:"postcode_iso3166_alpha2=SG"`
PostCodeCountry string
PostCodeByField string `validate:"postcode_iso3166_alpha2_field=PostCodeCountry"`
BooleanString string `validate:"boolean"`
}
var test Test
test.Inner.EqCSFieldString = "1234"
test.Inner.GtCSFieldString = "1234"
test.Inner.GteCSFieldString = "1234"
test.MaxString = "1234"
test.MaxNumber = 2000
test.MaxMultiple = make([]string, 9)
test.LtString = "1234"
test.LtNumber = 6
test.LtMultiple = make([]string, 3)
test.LtTime = time.Now().Add(time.Hour * 24)
test.LteString = "1234"
test.LteNumber = 6
test.LteMultiple = make([]string, 3)
test.LteTime = time.Now().Add(time.Hour * 24)
test.LtFieldString = "12345"
test.LteFieldString = "12345"
test.LtCSFieldString = "1234"
test.LteCSFieldString = "1234"
test.AlphaString = "abc3"
test.AlphanumString = "abc3!"
test.NumericString = "12E.00"
test.NumberString = "12E"
test.Excludes = "this is some test text"
test.ExcludesAll = "This is Great!"
test.ExcludesRune = "Love it ☻"
test.ASCII = "カタカナ"
test.PrintableASCII = "カタカナ"
test.MultiByte = "1234feerf"
test.LowercaseString = "ABCDEFG"
test.UppercaseString = "abcdefg"
s := "toolong"
test.StrPtrMaxLen = &s
test.StrPtrLen = &s
test.UniqueSlice = []string{"1234", "1234"}
test.UniqueMap = map[string]string{"key1": "1234", "key2": "1234"}
test.Datetime = "2008-Feb-01"
test.BooleanString = "A"
test.Inner.RequiredIf = "abcd"
err = validate.Struct(test)
NotEqual(t, err, nil)
errs, ok := err.(validator.ValidationErrors)
Equal(t, ok, true)
tests := []struct {
ns string
expected string
}{
{
ns: "Test.IsColor",
expected: "IsColor jābūt derīgai krāsai",
},
{
ns: "Test.MAC",
expected: "MAC jābūt derīgai MAC adresei",
},
{
ns: "Test.IPAddr",
expected: "IPAddr jābūt atrisināmai IP adresei",
},
{
ns: "Test.IPAddrv4",
expected: "IPAddrv4 jābūt atrisināmai IPv4 adresei",
},
{
ns: "Test.IPAddrv6",
expected: "IPAddrv6 jābūt atrisināmai IPv6 adresei",
},
{
ns: "Test.UDPAddr",
expected: "UDPAddr jābūt derīgai UDP adresei",
},
{
ns: "Test.UDPAddrv4",
expected: "UDPAddrv4 jābūt derīgai IPv4 UDP adresei",
},
{
ns: "Test.UDPAddrv6",
expected: "UDPAddrv6 jābūt derīgai IPv6 UDP adresei",
},
{
ns: "Test.TCPAddr",
expected: "TCPAddr jābūt derīgai TCP adresei",
},
{
ns: "Test.TCPAddrv4",
expected: "TCPAddrv4 jābūt derīgai IPv4 TCP adresei",
},
{
ns: "Test.TCPAddrv6",
expected: "TCPAddrv6 jābūt derīgai IPv6 TCP adresei",
},
{
ns: "Test.CIDR",
expected: "CIDR jāsatur derīgu CIDR notāciju",
},
{
ns: "Test.CIDRv4",
expected: "CIDRv4 jāsatur derīgu CIDR notāciju IPv4 adresei",
},
{
ns: "Test.CIDRv6",
expected: "CIDRv6 jāsatur derīgu CIDR notāciju IPv6 adresei",
},
{
ns: "Test.SSN",
expected: "SSN jābūt derīgam SSN numuram",
},
{
ns: "Test.IP",
expected: "IP jābūt derīgai IP adresei",
},
{
ns: "Test.IPv4",
expected: "IPv4 jābūt derīgai IPv4 adresei",
},
{
ns: "Test.IPv6",
expected: "IPv6 jābūt derīgai IPv6 adresei",
},
{
ns: "Test.DataURI",
expected: "DataURI jāsatur derīgs Data URI",
},
{
ns: "Test.Latitude",
expected: "Latitude jāsatur derīgus platuma grādus",
},
{
ns: "Test.Longitude",
expected: "Longitude jāsatur derīgus garuma grādus",
},
{
ns: "Test.MultiByte",
expected: "MultiByte jāsatur multibyte rakstu zīmes",
},
{
ns: "Test.ASCII",
expected: "ASCII jāsatur tikai ascii rakstu zīmes",
},
{
ns: "Test.PrintableASCII",
expected: "PrintableASCII jāsatur tikai drukājamas ascii rakstu zīmes",
},
{
ns: "Test.UUID",
expected: "UUID jābūt derīgam UUID",
},
{
ns: "Test.UUID3",
expected: "UUID3 jābūt derīgam 3. versijas UUID",
},
{
ns: "Test.UUID4",
expected: "UUID4 jābūt derīgam 4. versijas UUID",
},
{
ns: "Test.UUID5",
expected: "UUID5 jābūt derīgam 5. versijas UUID",
},
{
ns: "Test.ULID",
expected: "ULID jābūt derīgam ULID",
},
{
ns: "Test.ISBN",
expected: "ISBN jābūt derīgam ISBN numuram",
},
{
ns: "Test.ISBN10",
expected: "ISBN10 jābūt derīgam ISBN-10 numuram",
},
{
ns: "Test.ISBN13",
expected: "ISBN13 jābūt derīgam ISBN-13 numuram",
},
{
ns: "Test.Excludes",
expected: "Excludes nedrīkst saturēt tekstu 'text'",
},
{
ns: "Test.ExcludesAll",
expected: "ExcludesAll nedrīkst saturēt nevienu no sekojošām rakstu zīmēm '!@#$'",
},
{
ns: "Test.ExcludesRune",
expected: "ExcludesRune nedrīkst saturēt sekojošo '☻'",
},
{
ns: "Test.ContainsAny",
expected: "ContainsAny jāsatur minimums 1 no rakstu zīmēm '!@#$'",
},
{
ns: "Test.Contains",
expected: "Contains jāsatur teksts 'purpose'",
},
{
ns: "Test.Base64",
expected: "Base64 jābūt derīgai Base64 virknei",
},
{
ns: "Test.Email",
expected: "Email jābūt derīgai e-pasta adresei",
},
{
ns: "Test.URL",
expected: "URL jābūt derīgam URL",
},
{
ns: "Test.URI",
expected: "URI jābūt derīgam URI",
},
{
ns: "Test.RGBColorString",
expected: "RGBColorString jābūt derīgai RGB krāsai",
},
{
ns: "Test.RGBAColorString",
expected: "RGBAColorString jābūt derīgai RGBA krāsai",
},
{
ns: "Test.HSLColorString",
expected: "HSLColorString jābūt derīgai HSL krāsai",
},
{
ns: "Test.HSLAColorString",
expected: "HSLAColorString jābūt derīgai HSLA krāsai",
},
{
ns: "Test.HexadecimalString",
expected: "HexadecimalString jābūt heksadecimālam skaitlim",
},
{
ns: "Test.HexColorString",
expected: "HexColorString jābūt derīgai HEX krāsai",
},
{
ns: "Test.NumberString",
expected: "NumberString jāsatur derīgs skaitlis",
},
{
ns: "Test.NumericString",
expected: "NumericString jāsatur tikai cipari",
},
{
ns: "Test.AlphanumString",
expected: "AlphanumString jāsatur tikai simboli no alfabēta vai cipari (Alphanumeric)",
},
{
ns: "Test.AlphaString",
expected: "AlphaString jāsatur tikai simboli no alfabēta",
},
{
ns: "Test.LtFieldString",
expected: "LtFieldString jābūt mazākam par MaxString",
},
{
ns: "Test.LteFieldString",
expected: "LteFieldString jābūt mazākam par MaxString vai vienādam",
},
{
ns: "Test.GtFieldString",
expected: "GtFieldString jābūt lielākam par MaxString",
},
{
ns: "Test.GteFieldString",
expected: "GteFieldString jābūt lielākam par MaxString vai vienādam",
},
{
ns: "Test.NeFieldString",
expected: "NeFieldString nedrīkst būt vienāds ar EqFieldString",
},
{
ns: "Test.LtCSFieldString",
expected: "LtCSFieldString jābūt mazākam par Inner.LtCSFieldString",
},
{
ns: "Test.LteCSFieldString",
expected: "LteCSFieldString jābūt mazākam par Inner.LteCSFieldString vai vienādam",
},
{
ns: "Test.GtCSFieldString",
expected: "GtCSFieldString jābūt lielākam par Inner.GtCSFieldString",
},
{
ns: "Test.GteCSFieldString",
expected: "GteCSFieldString jābūt lielākam par Inner.GteCSFieldString vai vienādam",
},
{
ns: "Test.NeCSFieldString",
expected: "NeCSFieldString nedrīkst būt vienāds ar Inner.NeCSFieldString",
},
{
ns: "Test.EqCSFieldString",
expected: "EqCSFieldString jābūt vienādam ar Inner.EqCSFieldString",
},
{
ns: "Test.EqFieldString",
expected: "EqFieldString jābūt vienādam ar MaxString",
},
{
ns: "Test.GteString",
expected: "GteString garumam jābūt minimums 3 rakstu zīmes",
},
{
ns: "Test.GteNumber",
expected: "GteNumber jābūt 5.56 vai lielākam",
},
{
ns: "Test.GteMultiple",
expected: "GteMultiple jāsatur minimums 2 elementi",
},
{
ns: "Test.GteTime",
expected: "GteTime jābūt lielākam par šī brīža Datumu un laiku vai vienādam",
},
{
ns: "Test.GtString",
expected: "GtString ir jābūt garākam par 3 rakstu zīmēm",
},
{
ns: "Test.GtNumber",
expected: "GtNumber jābūt lielākam par 5.56",
},
{
ns: "Test.GtMultiple",
expected: "GtMultiple jāsatur vairāk par 2 elementiem",
},
{
ns: "Test.GtTime",
expected: "GtTime jābūt lielākam par šī brīža Datumu un laiku",
},
{
ns: "Test.LteString",
expected: "LteString garumam jābūt maksimums 3 rakstu zīmes",
},
{
ns: "Test.LteNumber",
expected: "LteNumber jābūt 5.56 vai mazākam",
},
{
ns: "Test.LteMultiple",
expected: "LteMultiple jāsatur maksimums 2 elementi",
},
{
ns: "Test.LteTime",
expected: "LteTime jābūt mazākam par šī brīža Datumu un laiku vai vienādam",
},
{
ns: "Test.LtString",
expected: "LtString garumam jābūt mazākam par 3 rakstu zīmēm",
},
{
ns: "Test.LtNumber",
expected: "LtNumber jābūt mazākam par 5.56",
},
{
ns: "Test.LtMultiple",
expected: "LtMultiple jāsatur mazāk par 2 elementiem",
},
{
ns: "Test.LtTime",
expected: "LtTime jābūt mazākam par šī brīža Datumu un laiku",
},
{
ns: "Test.NeString",
expected: "NeString nedrīkst būt vienāds ar ",
},
{
ns: "Test.NeNumber",
expected: "NeNumber nedrīkst būt vienāds ar 0.00",
},
{
ns: "Test.NeMultiple",
expected: "NeMultiple nedrīkst būt vienāds ar 0",
},
{
ns: "Test.EqString",
expected: "EqString nav vienāds ar 3",
},
{
ns: "Test.EqNumber",
expected: "EqNumber nav vienāds ar 2.33",
},
{
ns: "Test.EqMultiple",
expected: "EqMultiple nav vienāds ar 7",
},
{
ns: "Test.MaxString",
expected: "MaxString vērtība pārsniedz maksimālo garumu 3 rakstu zīmes",
},
{
ns: "Test.MaxNumber",
expected: "MaxNumber vērtībai jābūt 1,113.00 vai mazākai",
},
{
ns: "Test.MaxMultiple",
expected: "MaxMultiple jāsatur maksimums 7 elementi",
},
{
ns: "Test.MinString",
expected: "MinString garumam jābūt minimums 1 rakstu zīme",
},
{
ns: "Test.MinNumber",
expected: "MinNumber vērtībai jābūt 1,113.00 vai lielākai",
},
{
ns: "Test.MinMultiple",
expected: "MinMultiple jāsatur minimums 7 elementi",
},
{
ns: "Test.LenString",
expected: "LenString garumam jābūt 1 rakstu zīme",
},
{
ns: "Test.LenNumber",
expected: "LenNumber vērtībai jābūt 1,113.00",
},
{
ns: "Test.LenMultiple",
expected: "LenMultiple vērtībai jāsatur 7 elementi",
},
{
ns: "Test.RequiredString",
expected: "RequiredString ir obligāts lauks",
},
{
ns: "Test.RequiredIf",
expected: "RequiredIf ir obligāts lauks",
},
{
ns: "Test.RequiredNumber",
expected: "RequiredNumber ir obligāts lauks",
},
{
ns: "Test.RequiredMultiple",
expected: "RequiredMultiple ir obligāts lauks",
},
{
ns: "Test.StrPtrMinLen",
expected: "StrPtrMinLen garumam jābūt minimums 10 rakstu zīmes",
},
{
ns: "Test.StrPtrMaxLen",
expected: "StrPtrMaxLen vērtība pārsniedz maksimālo garumu 1 rakstu zīme",
},
{
ns: "Test.StrPtrLen",
expected: "StrPtrLen garumam jābūt 2 rakstu zīmes",
},
{
ns: "Test.StrPtrLt",
expected: "StrPtrLt garumam jābūt mazākam par 1 rakstu zīmi",
},
{
ns: "Test.StrPtrLte",
expected: "StrPtrLte garumam jābūt maksimums 1 rakstu zīme",
},
{
ns: "Test.StrPtrGt",
expected: "StrPtrGt ir jābūt garākam par 10 rakstu zīmēm",
},
{
ns: "Test.StrPtrGte",
expected: "StrPtrGte garumam jābūt minimums 10 rakstu zīmes",
},
{
ns: "Test.OneOfString",
expected: "OneOfString jābūt vienam no [red green]",
},
{
ns: "Test.OneOfInt",
expected: "OneOfInt jābūt vienam no [5 63]",
},
{
ns: "Test.UniqueSlice",
expected: "UniqueSlice jāsatur unikālas vērtības",
},
{
ns: "Test.UniqueArray",
expected: "UniqueArray jāsatur unikālas vērtības",
},
{
ns: "Test.UniqueMap",
expected: "UniqueMap jāsatur unikālas vērtības",
},
{
ns: "Test.JSONString",
expected: "JSONString jābūt derīgai json virknei",
},
{
ns: "Test.JWTString",
expected: "JWTString jābūt derīgai jwt virknei",
},
{
ns: "Test.LowercaseString",
expected: "LowercaseString jābūt mazo burtu virknei",
},
{
ns: "Test.UppercaseString",
expected: "UppercaseString jābūt lielo burtu virknei",
},
{
ns: "Test.Datetime",
expected: "Datetime neatbilst formātam 2006-01-02",
},
{
ns: "Test.PostCode",
expected: "PostCode neatbilst pasta indeksa formātam valstī SG",
},
{
ns: "Test.PostCodeByField",
expected: "PostCodeByField neatbilst pasta indeksa formātam valstī, kura norādīta laukā PostCodeCountry",
},
{
ns: "Test.BooleanString",
expected: "BooleanString jābūt derīgai boolean vērtībai",
},
}
for _, tt := range tests {
var fe validator.FieldError
for _, e := range errs {
if tt.ns == e.Namespace() {
fe = e
break
}
}
NotEqual(t, fe, nil)
Equal(t, tt.expected, fe.Translate(trans))
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,639 @@
package nl
import (
"testing"
"time"
. "github.com/go-playground/assert/v2"
english "github.com/go-playground/locales/en"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
)
func TestTranslations(t *testing.T) {
eng := english.New()
uni := ut.New(eng, eng)
trans, _ := uni.GetTranslator("en")
validate := validator.New()
err := RegisterDefaultTranslations(validate, trans)
Equal(t, err, nil)
type Inner struct {
EqCSFieldString string
NeCSFieldString string
GtCSFieldString string
GteCSFieldString string
LtCSFieldString string
LteCSFieldString string
}
type Test struct {
Inner Inner
RequiredString string `validate:"required"`
RequiredNumber int `validate:"required"`
RequiredMultiple []string `validate:"required"`
LenString string `validate:"len=1"`
LenNumber float64 `validate:"len=1113.00"`
LenMultiple []string `validate:"len=7"`
MinString string `validate:"min=1"`
MinNumber float64 `validate:"min=1113.00"`
MinMultiple []string `validate:"min=7"`
MaxString string `validate:"max=3"`
MaxNumber float64 `validate:"max=1113.00"`
MaxMultiple []string `validate:"max=7"`
EqString string `validate:"eq=3"`
EqNumber float64 `validate:"eq=2.33"`
EqMultiple []string `validate:"eq=7"`
NeString string `validate:"ne="`
NeNumber float64 `validate:"ne=0.00"`
NeMultiple []string `validate:"ne=0"`
LtString string `validate:"lt=3"`
LtNumber float64 `validate:"lt=5.56"`
LtMultiple []string `validate:"lt=2"`
LtTime time.Time `validate:"lt"`
LteString string `validate:"lte=3"`
LteNumber float64 `validate:"lte=5.56"`
LteMultiple []string `validate:"lte=2"`
LteTime time.Time `validate:"lte"`
GtString string `validate:"gt=3"`
GtNumber float64 `validate:"gt=5.56"`
GtMultiple []string `validate:"gt=2"`
GtTime time.Time `validate:"gt"`
GteString string `validate:"gte=3"`
GteNumber float64 `validate:"gte=5.56"`
GteMultiple []string `validate:"gte=2"`
GteTime time.Time `validate:"gte"`
EqFieldString string `validate:"eqfield=MaxString"`
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"`
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"`
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"`
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"`
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"`
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"`
NeFieldString string `validate:"nefield=EqFieldString"`
GtFieldString string `validate:"gtfield=MaxString"`
GteFieldString string `validate:"gtefield=MaxString"`
LtFieldString string `validate:"ltfield=MaxString"`
LteFieldString string `validate:"ltefield=MaxString"`
AlphaString string `validate:"alpha"`
AlphanumString string `validate:"alphanum"`
NumericString string `validate:"numeric"`
NumberString string `validate:"number"`
HexadecimalString string `validate:"hexadecimal"`
HexColorString string `validate:"hexcolor"`
RGBColorString string `validate:"rgb"`
RGBAColorString string `validate:"rgba"`
HSLColorString string `validate:"hsl"`
HSLAColorString string `validate:"hsla"`
Email string `validate:"email"`
URL string `validate:"url"`
URI string `validate:"uri"`
Base64 string `validate:"base64"`
Contains string `validate:"contains=purpose"`
ContainsAny string `validate:"containsany=!@#$"`
Excludes string `validate:"excludes=text"`
ExcludesAll string `validate:"excludesall=!@#$"`
ExcludesRune string `validate:"excludesrune=☻"`
ISBN string `validate:"isbn"`
ISBN10 string `validate:"isbn10"`
ISBN13 string `validate:"isbn13"`
UUID string `validate:"uuid"`
UUID3 string `validate:"uuid3"`
UUID4 string `validate:"uuid4"`
UUID5 string `validate:"uuid5"`
ULID string `validate:"ulid"`
ASCII string `validate:"ascii"`
PrintableASCII string `validate:"printascii"`
MultiByte string `validate:"multibyte"`
DataURI string `validate:"datauri"`
Latitude string `validate:"latitude"`
Longitude string `validate:"longitude"`
SSN string `validate:"ssn"`
IP string `validate:"ip"`
IPv4 string `validate:"ipv4"`
IPv6 string `validate:"ipv6"`
CIDR string `validate:"cidr"`
CIDRv4 string `validate:"cidrv4"`
CIDRv6 string `validate:"cidrv6"`
TCPAddr string `validate:"tcp_addr"`
TCPAddrv4 string `validate:"tcp4_addr"`
TCPAddrv6 string `validate:"tcp6_addr"`
UDPAddr string `validate:"udp_addr"`
UDPAddrv4 string `validate:"udp4_addr"`
UDPAddrv6 string `validate:"udp6_addr"`
IPAddr string `validate:"ip_addr"`
IPAddrv4 string `validate:"ip4_addr"`
IPAddrv6 string `validate:"ip6_addr"`
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"`
StrPtrMaxLen *string `validate:"max=1"`
StrPtrLen *string `validate:"len=2"`
StrPtrLt *string `validate:"lt=1"`
StrPtrLte *string `validate:"lte=1"`
StrPtrGt *string `validate:"gt=10"`
StrPtrGte *string `validate:"gte=10"`
OneOfString string `validate:"oneof=red green"`
OneOfInt int `validate:"oneof=5 63"`
}
var test Test
test.Inner.EqCSFieldString = "1234"
test.Inner.GtCSFieldString = "1234"
test.Inner.GteCSFieldString = "1234"
test.MaxString = "1234"
test.MaxNumber = 2000
test.MaxMultiple = make([]string, 9)
test.LtString = "1234"
test.LtNumber = 6
test.LtMultiple = make([]string, 3)
test.LtTime = time.Now().Add(time.Hour * 24)
test.LteString = "1234"
test.LteNumber = 6
test.LteMultiple = make([]string, 3)
test.LteTime = time.Now().Add(time.Hour * 24)
test.LtFieldString = "12345"
test.LteFieldString = "12345"
test.LtCSFieldString = "1234"
test.LteCSFieldString = "1234"
test.AlphaString = "abc3"
test.AlphanumString = "abc3!"
test.NumericString = "12E.00"
test.NumberString = "12E"
test.Excludes = "this is some test text"
test.ExcludesAll = "This is Great!"
test.ExcludesRune = "Love it ☻"
test.ASCII = "カタカナ"
test.PrintableASCII = "カタカナ"
test.MultiByte = "1234feerf"
s := "toolong"
test.StrPtrMaxLen = &s
test.StrPtrLen = &s
err = validate.Struct(test)
NotEqual(t, err, nil)
errs, ok := err.(validator.ValidationErrors)
Equal(t, ok, true)
tests := []struct {
ns string
expected string
}{
{
ns: "Test.IsColor",
expected: "IsColor moet een geldige kleur zijn",
},
{
ns: "Test.MAC",
expected: "MAC moet een geldig MAC adres bevatten",
},
{
ns: "Test.IPAddr",
expected: "IPAddr moet een oplosbaar IP adres zijn",
},
{
ns: "Test.IPAddrv4",
expected: "IPAddrv4 moet een oplosbaar IPv4 adres zijn",
},
{
ns: "Test.IPAddrv6",
expected: "IPAddrv6 moet een oplosbaar IPv6 adres zijn",
},
{
ns: "Test.UDPAddr",
expected: "UDPAddr moet een geldig UDP adres zijn",
},
{
ns: "Test.UDPAddrv4",
expected: "UDPAddrv4 moet een geldig IPv4 UDP adres zijn",
},
{
ns: "Test.UDPAddrv6",
expected: "UDPAddrv6 moet een geldig IPv6 UDP adres zijn",
},
{
ns: "Test.TCPAddr",
expected: "TCPAddr moet een geldig TCP adres zijn",
},
{
ns: "Test.TCPAddrv4",
expected: "TCPAddrv4 moet een geldig IPv4 TCP adres zijn",
},
{
ns: "Test.TCPAddrv6",
expected: "TCPAddrv6 moet een geldig IPv6 TCP adres zijn",
},
{
ns: "Test.CIDR",
expected: "CIDR moet een geldige CIDR notatie bevatten",
},
{
ns: "Test.CIDRv4",
expected: "CIDRv4 moet een geldige CIDR notatie voor een IPv4 adres bevatten",
},
{
ns: "Test.CIDRv6",
expected: "CIDRv6 moet een geldige CIDR notatie voor een IPv6 adres bevatten",
},
{
ns: "Test.SSN",
expected: "SSN moet een geldig SSN nummer zijn",
},
{
ns: "Test.IP",
expected: "IP moet een geldig IP adres zijn",
},
{
ns: "Test.IPv4",
expected: "IPv4 moet een geldig IPv4 adres zijn",
},
{
ns: "Test.IPv6",
expected: "IPv6 moet een geldig IPv6 adres zijn",
},
{
ns: "Test.DataURI",
expected: "DataURI moet een geldige Data URI bevatten",
},
{
ns: "Test.Latitude",
expected: "Latitude moet geldige breedtegraadcoördinaten bevatten",
},
{
ns: "Test.Longitude",
expected: "Longitude moet geldige lengtegraadcoördinaten bevatten",
},
{
ns: "Test.MultiByte",
expected: "MultiByte moet multibyte karakters bevatten",
},
{
ns: "Test.ASCII",
expected: "ASCII mag alleen ascii karakters bevatten",
},
{
ns: "Test.PrintableASCII",
expected: "PrintableASCII mag alleen afdrukbare ascii karakters bevatten",
},
{
ns: "Test.UUID",
expected: "UUID moet een geldige UUID zijn",
},
{
ns: "Test.UUID3",
expected: "UUID3 moet een geldige versie 3 UUID zijn",
},
{
ns: "Test.UUID4",
expected: "UUID4 moet een geldige versie 4 UUID zijn",
},
{
ns: "Test.UUID5",
expected: "UUID5 moet een geldige versie 5 UUID zijn",
},
{
ns: "Test.ULID",
expected: "ULID moet een geldige ULID zijn",
},
{
ns: "Test.ISBN",
expected: "ISBN moet een geldig ISBN nummer zijn",
},
{
ns: "Test.ISBN10",
expected: "ISBN10 moet een geldig ISBN-10 nummer zijn",
},
{
ns: "Test.ISBN13",
expected: "ISBN13 moet een geldig ISBN-13 nummer zijn",
},
{
ns: "Test.Excludes",
expected: "Excludes mag niet de tekst 'text' bevatten",
},
{
ns: "Test.ExcludesAll",
expected: "ExcludesAll mag niet een van de volgende karakters bevatten '!@#$'",
},
{
ns: "Test.ExcludesRune",
expected: "ExcludesRune mag niet het volgende bevatten '☻'",
},
{
ns: "Test.ContainsAny",
expected: "ContainsAny moet tenminste een van de volgende karakters bevatten '!@#$'",
},
{
ns: "Test.Contains",
expected: "Contains moet de tekst 'purpose' bevatten",
},
{
ns: "Test.Base64",
expected: "Base64 moet een geldige Base64 string zijn",
},
{
ns: "Test.Email",
expected: "Email moet een geldig email adres zijn",
},
{
ns: "Test.URL",
expected: "URL moet een geldige URL zijn",
},
{
ns: "Test.URI",
expected: "URI moet een geldige URI zijn",
},
{
ns: "Test.RGBColorString",
expected: "RGBColorString moet een geldige RGB kleur zijn",
},
{
ns: "Test.RGBAColorString",
expected: "RGBAColorString moet een geldige RGBA kleur zijn",
},
{
ns: "Test.HSLColorString",
expected: "HSLColorString moet een geldige HSL kleur zijn",
},
{
ns: "Test.HSLAColorString",
expected: "HSLAColorString moet een geldige HSLA kleur zijn",
},
{
ns: "Test.HexadecimalString",
expected: "HexadecimalString moet een geldig hexadecimaal getal zijn",
},
{
ns: "Test.HexColorString",
expected: "HexColorString moet een geldige HEX kleur zijn",
},
{
ns: "Test.NumberString",
expected: "NumberString moet een geldig getal zijn",
},
{
ns: "Test.NumericString",
expected: "NumericString moet een geldige numerieke waarde zijn",
},
{
ns: "Test.AlphanumString",
expected: "AlphanumString mag alleen alfanumerieke karakters bevatten",
},
{
ns: "Test.AlphaString",
expected: "AlphaString mag alleen alfabetische karakters bevatten",
},
{
ns: "Test.LtFieldString",
expected: "LtFieldString moet kleiner zijn dan MaxString",
},
{
ns: "Test.LteFieldString",
expected: "LteFieldString moet kleiner dan of gelijk aan MaxString zijn",
},
{
ns: "Test.GtFieldString",
expected: "GtFieldString moet groter zijn dan MaxString",
},
{
ns: "Test.GteFieldString",
expected: "GteFieldString moet groter dan of gelijk aan MaxString zijn",
},
{
ns: "Test.NeFieldString",
expected: "NeFieldString mag niet gelijk zijn aan EqFieldString",
},
{
ns: "Test.LtCSFieldString",
expected: "LtCSFieldString moet kleiner zijn dan Inner.LtCSFieldString",
},
{
ns: "Test.LteCSFieldString",
expected: "LteCSFieldString moet kleiner dan of gelijk aan Inner.LteCSFieldString zijn",
},
{
ns: "Test.GtCSFieldString",
expected: "GtCSFieldString moet groter zijn dan Inner.GtCSFieldString",
},
{
ns: "Test.GteCSFieldString",
expected: "GteCSFieldString moet groter dan of gelijk aan Inner.GteCSFieldString zijn",
},
{
ns: "Test.NeCSFieldString",
expected: "NeCSFieldString mag niet gelijk zijn aan Inner.NeCSFieldString",
},
{
ns: "Test.EqCSFieldString",
expected: "EqCSFieldString moet gelijk zijn aan Inner.EqCSFieldString",
},
{
ns: "Test.EqFieldString",
expected: "EqFieldString moet gelijk zijn aan MaxString",
},
{
ns: "Test.GteString",
expected: "GteString moet tenminste 3 karakters lang zijn",
},
{
ns: "Test.GteNumber",
expected: "GteNumber moet 5.56 of groter zijn",
},
{
ns: "Test.GteMultiple",
expected: "GteMultiple moet tenminste 2 items bevatten",
},
{
ns: "Test.GteTime",
expected: "GteTime moet groter dan of gelijk zijn aan de huidige datum & tijd",
},
{
ns: "Test.GtString",
expected: "GtString moet langer dan 3 karakters zijn",
},
{
ns: "Test.GtNumber",
expected: "GtNumber moet groter zijn dan 5.56",
},
{
ns: "Test.GtMultiple",
expected: "GtMultiple moet meer dan 2 items bevatten",
},
{
ns: "Test.GtTime",
expected: "GtTime moet groter zijn dan de huidige datum & tijd",
},
{
ns: "Test.LteString",
expected: "LteString mag maximaal 3 karakters lang zijn",
},
{
ns: "Test.LteNumber",
expected: "LteNumber moet 5.56 of minder zijn",
},
{
ns: "Test.LteMultiple",
expected: "LteMultiple mag maximaal 2 items bevatten",
},
{
ns: "Test.LteTime",
expected: "LteTime moet kleiner dan of gelijk aan de huidige datum & tijd zijn",
},
{
ns: "Test.LtString",
expected: "LtString moet minder dan 3 karakters lang zijn",
},
{
ns: "Test.LtNumber",
expected: "LtNumber moet kleiner zijn dan 5.56",
},
{
ns: "Test.LtMultiple",
expected: "LtMultiple moet minder dan 2 items bevatten",
},
{
ns: "Test.LtTime",
expected: "LtTime moet kleiner zijn dan de huidige datum & tijd",
},
{
ns: "Test.NeString",
expected: "NeString mag niet gelijk zijn aan ",
},
{
ns: "Test.NeNumber",
expected: "NeNumber mag niet gelijk zijn aan 0.00",
},
{
ns: "Test.NeMultiple",
expected: "NeMultiple mag niet gelijk zijn aan 0",
},
{
ns: "Test.EqString",
expected: "EqString is niet gelijk aan 3",
},
{
ns: "Test.EqNumber",
expected: "EqNumber is niet gelijk aan 2.33",
},
{
ns: "Test.EqMultiple",
expected: "EqMultiple is niet gelijk aan 7",
},
{
ns: "Test.MaxString",
expected: "MaxString mag maximaal 3 karakters lang zijn",
},
{
ns: "Test.MaxNumber",
expected: "MaxNumber moet 1,113.00 of kleiner zijn",
},
{
ns: "Test.MaxMultiple",
expected: "MaxMultiple mag maximaal 7 items bevatten",
},
{
ns: "Test.MinString",
expected: "MinString moet tenminste 1 karakter lang zijn",
},
{
ns: "Test.MinNumber",
expected: "MinNumber moet 1,113.00 of groter zijn",
},
{
ns: "Test.MinMultiple",
expected: "MinMultiple moet tenminste 7 items bevatten",
},
{
ns: "Test.LenString",
expected: "LenString moet 1 karakter lang zijn",
},
{
ns: "Test.LenNumber",
expected: "LenNumber moet gelijk zijn aan 1,113.00",
},
{
ns: "Test.LenMultiple",
expected: "LenMultiple moet 7 items bevatten",
},
{
ns: "Test.RequiredString",
expected: "RequiredString is een verplicht veld",
},
{
ns: "Test.RequiredNumber",
expected: "RequiredNumber is een verplicht veld",
},
{
ns: "Test.RequiredMultiple",
expected: "RequiredMultiple is een verplicht veld",
},
{
ns: "Test.StrPtrMinLen",
expected: "StrPtrMinLen moet tenminste 10 karakters lang zijn",
},
{
ns: "Test.StrPtrMaxLen",
expected: "StrPtrMaxLen mag maximaal 1 karakter lang zijn",
},
{
ns: "Test.StrPtrLen",
expected: "StrPtrLen moet 2 karakters lang zijn",
},
{
ns: "Test.StrPtrLt",
expected: "StrPtrLt moet minder dan 1 karakter lang zijn",
},
{
ns: "Test.StrPtrLte",
expected: "StrPtrLte mag maximaal 1 karakter lang zijn",
},
{
ns: "Test.StrPtrGt",
expected: "StrPtrGt moet langer dan 10 karakters zijn",
},
{
ns: "Test.StrPtrGte",
expected: "StrPtrGte moet tenminste 10 karakters lang zijn",
},
{
ns: "Test.OneOfString",
expected: "OneOfString moet een van de volgende zijn [red green]",
},
{
ns: "Test.OneOfInt",
expected: "OneOfInt moet een van de volgende zijn [5 63]",
},
}
for _, tt := range tests {
var fe validator.FieldError
for _, e := range errs {
if tt.ns == e.Namespace() {
fe = e
break
}
}
NotEqual(t, fe, nil)
Equal(t, tt.expected, fe.Translate(trans))
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,682 @@
package pt
import (
"testing"
"time"
. "github.com/go-playground/assert/v2"
"github.com/go-playground/locales/pt"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
)
func TestTranslations(t *testing.T) {
pt := pt.New()
uni := ut.New(pt, pt)
trans, _ := uni.GetTranslator("pt")
validate := validator.New()
err := RegisterDefaultTranslations(validate, trans)
Equal(t, err, nil)
type Inner struct {
EqCSFieldString string
NeCSFieldString string
GtCSFieldString string
GteCSFieldString string
LtCSFieldString string
LteCSFieldString string
}
type Test struct {
Inner Inner
RequiredString string `validate:"required"`
RequiredNumber int `validate:"required"`
RequiredMultiple []string `validate:"required"`
LenString string `validate:"len=1"`
LenNumber float64 `validate:"len=1113.00"`
LenMultiple []string `validate:"len=7"`
MinString string `validate:"min=1"`
MinNumber float64 `validate:"min=1113.00"`
MinMultiple []string `validate:"min=7"`
MaxString string `validate:"max=3"`
MaxNumber float64 `validate:"max=1113.00"`
MaxMultiple []string `validate:"max=7"`
EqString string `validate:"eq=3"`
EqNumber float64 `validate:"eq=2.33"`
EqMultiple []string `validate:"eq=7"`
NeString string `validate:"ne="`
NeNumber float64 `validate:"ne=0.00"`
NeMultiple []string `validate:"ne=0"`
LtString string `validate:"lt=3"`
LtNumber float64 `validate:"lt=5.56"`
LtMultiple []string `validate:"lt=2"`
LtTime time.Time `validate:"lt"`
LteString string `validate:"lte=3"`
LteNumber float64 `validate:"lte=5.56"`
LteMultiple []string `validate:"lte=2"`
LteTime time.Time `validate:"lte"`
GtString string `validate:"gt=3"`
GtNumber float64 `validate:"gt=5.56"`
GtMultiple []string `validate:"gt=2"`
GtTime time.Time `validate:"gt"`
GteString string `validate:"gte=3"`
GteNumber float64 `validate:"gte=5.56"`
GteMultiple []string `validate:"gte=2"`
GteTime time.Time `validate:"gte"`
EqFieldString string `validate:"eqfield=MaxString"`
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"`
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"`
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"`
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"`
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"`
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"`
NeFieldString string `validate:"nefield=EqFieldString"`
GtFieldString string `validate:"gtfield=MaxString"`
GteFieldString string `validate:"gtefield=MaxString"`
LtFieldString string `validate:"ltfield=MaxString"`
LteFieldString string `validate:"ltefield=MaxString"`
AlphaString string `validate:"alpha"`
AlphanumString string `validate:"alphanum"`
NumericString string `validate:"numeric"`
NumberString string `validate:"number"`
HexadecimalString string `validate:"hexadecimal"`
HexColorString string `validate:"hexcolor"`
RGBColorString string `validate:"rgb"`
RGBAColorString string `validate:"rgba"`
HSLColorString string `validate:"hsl"`
HSLAColorString string `validate:"hsla"`
Email string `validate:"email"`
URL string `validate:"url"`
URI string `validate:"uri"`
Base64 string `validate:"base64"`
Contains string `validate:"contains=purpose"`
ContainsAny string `validate:"containsany=!@#$"`
Excludes string `validate:"excludes=text"`
ExcludesAll string `validate:"excludesall=!@#$"`
ExcludesRune string `validate:"excludesrune=☻"`
ISBN string `validate:"isbn"`
ISBN10 string `validate:"isbn10"`
ISBN13 string `validate:"isbn13"`
UUID string `validate:"uuid"`
UUID3 string `validate:"uuid3"`
UUID4 string `validate:"uuid4"`
UUID5 string `validate:"uuid5"`
ULID string `validate:"ulid"`
ASCII string `validate:"ascii"`
PrintableASCII string `validate:"printascii"`
MultiByte string `validate:"multibyte"`
DataURI string `validate:"datauri"`
Latitude string `validate:"latitude"`
Longitude string `validate:"longitude"`
SSN string `validate:"ssn"`
IP string `validate:"ip"`
IPv4 string `validate:"ipv4"`
IPv6 string `validate:"ipv6"`
CIDR string `validate:"cidr"`
CIDRv4 string `validate:"cidrv4"`
CIDRv6 string `validate:"cidrv6"`
TCPAddr string `validate:"tcp_addr"`
TCPAddrv4 string `validate:"tcp4_addr"`
TCPAddrv6 string `validate:"tcp6_addr"`
UDPAddr string `validate:"udp_addr"`
UDPAddrv4 string `validate:"udp4_addr"`
UDPAddrv6 string `validate:"udp6_addr"`
IPAddr string `validate:"ip_addr"`
IPAddrv4 string `validate:"ip4_addr"`
IPAddrv6 string `validate:"ip6_addr"`
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"`
StrPtrMaxLen *string `validate:"max=1"`
StrPtrLen *string `validate:"len=2"`
StrPtrLt *string `validate:"lt=1"`
StrPtrLte *string `validate:"lte=1"`
StrPtrGt *string `validate:"gt=10"`
StrPtrGte *string `validate:"gte=10"`
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"`
JSONString string `validate:"json"`
LowercaseString string `validate:"lowercase"`
UppercaseString string `validate:"uppercase"`
Datetime string `validate:"datetime=2006-01-02"`
}
var test Test
test.Inner.EqCSFieldString = "1234"
test.Inner.GtCSFieldString = "1234"
test.Inner.GteCSFieldString = "1234"
test.MaxString = "1234"
test.MaxNumber = 2000
test.MaxMultiple = make([]string, 9)
test.LtString = "1234"
test.LtNumber = 6
test.LtMultiple = make([]string, 3)
test.LtTime = time.Now().Add(time.Hour * 24)
test.LteString = "1234"
test.LteNumber = 6
test.LteMultiple = make([]string, 3)
test.LteTime = time.Now().Add(time.Hour * 24)
test.LtFieldString = "12345"
test.LteFieldString = "12345"
test.LtCSFieldString = "1234"
test.LteCSFieldString = "1234"
test.AlphaString = "abc3"
test.AlphanumString = "abc3!"
test.NumericString = "12E.00"
test.NumberString = "12E"
test.Excludes = "this is some test text"
test.ExcludesAll = "This is Great!"
test.ExcludesRune = "Love it ☻"
test.ASCII = "カタカナ"
test.PrintableASCII = "カタカナ"
test.MultiByte = "1234feerf"
test.LowercaseString = "ABCDEFG"
test.UppercaseString = "abcdefg"
s := "toolong"
test.StrPtrMaxLen = &s
test.StrPtrLen = &s
test.UniqueSlice = []string{"1234", "1234"}
test.UniqueMap = map[string]string{"key1": "1234", "key2": "1234"}
test.Datetime = "2008-Feb-01"
err = validate.Struct(test)
NotEqual(t, err, nil)
errs, ok := err.(validator.ValidationErrors)
Equal(t, ok, true)
tests := []struct {
ns string
expected string
}{
{
ns: "Test.IsColor",
expected: "IsColor deve ser uma cor válida",
},
{
ns: "Test.MAC",
expected: "MAC deve conter um endereço MAC válido",
},
{
ns: "Test.IPAddr",
expected: "IPAddr deve ser um endereço IP resolvível",
},
{
ns: "Test.IPAddrv4",
expected: "IPAddrv4 deve ser um endereço IPv4 resolvível",
},
{
ns: "Test.IPAddrv6",
expected: "IPAddrv6 deve ser um endereço IPv6 resolvível",
},
{
ns: "Test.UDPAddr",
expected: "UDPAddr deve ser um endereço UDP válido",
},
{
ns: "Test.UDPAddrv4",
expected: "UDPAddrv4 deve ser um endereço UDP IPv4 válido",
},
{
ns: "Test.UDPAddrv6",
expected: "UDPAddrv6 deve ser um endereço UDP IPv6 válido",
},
{
ns: "Test.TCPAddr",
expected: "TCPAddr deve ser um endereço TCP válido",
},
{
ns: "Test.TCPAddrv4",
expected: "TCPAddrv4 deve ser um endereço TCP IPv4 válido",
},
{
ns: "Test.TCPAddrv6",
expected: "TCPAddrv6 deve ser um endereço TCP IPv6 válido",
},
{
ns: "Test.CIDR",
expected: "CIDR não respeita a notação CIDR",
},
{
ns: "Test.CIDRv4",
expected: "CIDRv4 não respeita a notação CIDR para um endereço IPv4",
},
{
ns: "Test.CIDRv6",
expected: "CIDRv6 não respeita a notação CIDR para um endereço IPv6",
},
{
ns: "Test.SSN",
expected: "SSN deve ser um número SSN válido",
},
{
ns: "Test.IP",
expected: "IP deve ser um endereço IP válido",
},
{
ns: "Test.IPv4",
expected: "IPv4 deve ser um endereço IPv4 válido",
},
{
ns: "Test.IPv6",
expected: "IPv6 deve ser um endereço IPv6 válido",
},
{
ns: "Test.DataURI",
expected: "DataURI deve conter um Data URI válido",
},
{
ns: "Test.Latitude",
expected: "Latitude deve conter uma coordenada de latitude válida",
},
{
ns: "Test.Longitude",
expected: "Longitude deve conter uma coordenada de longitude válida",
},
{
ns: "Test.MultiByte",
expected: "MultiByte deve conter caracteres multibyte",
},
{
ns: "Test.ASCII",
expected: "ASCII deve conter apenas caracteres ascii",
},
{
ns: "Test.PrintableASCII",
expected: "PrintableASCII deve conter apenas caracteres ascii imprimíveis",
},
{
ns: "Test.UUID",
expected: "UUID deve ser um UUID válido",
},
{
ns: "Test.UUID3",
expected: "UUID3 deve ser um UUID versão 3 válido",
},
{
ns: "Test.UUID4",
expected: "UUID4 deve ser um UUID versão 4 válido",
},
{
ns: "Test.UUID5",
expected: "UUID5 deve ser um UUID versão 5 válido",
},
{
ns: "Test.ULID",
expected: "ULID deve ser um ULID válido",
},
{
ns: "Test.ISBN",
expected: "ISBN deve ser um número de ISBN válido",
},
{
ns: "Test.ISBN10",
expected: "ISBN10 deve ser um número ISBN-10 válido",
},
{
ns: "Test.ISBN13",
expected: "ISBN13 deve ser um número ISBN-13 válido",
},
{
ns: "Test.Excludes",
expected: "Excludes não deve conter o texto 'text'",
},
{
ns: "Test.ExcludesAll",
expected: "ExcludesAll não deve conter os seguintes caracteres '!@#$'",
},
{
ns: "Test.ExcludesRune",
expected: "ExcludesRune não pode conter o seguinte '☻'",
},
{
ns: "Test.ContainsAny",
expected: "ContainsAny deve conter pelo menos um dos seguintes caracteres '!@#$'",
},
{
ns: "Test.Contains",
expected: "Contains deve conter o texto 'purpose'",
},
{
ns: "Test.Base64",
expected: "Base64 deve ser uma string Base64 válida",
},
{
ns: "Test.Email",
expected: "Email deve ser um endereço de e-mail válido",
},
{
ns: "Test.URL",
expected: "URL deve ser um URL válido",
},
{
ns: "Test.URI",
expected: "URI deve ser um URI válido",
},
{
ns: "Test.RGBColorString",
expected: "RGBColorString deve ser uma cor RGB válida",
},
{
ns: "Test.RGBAColorString",
expected: "RGBAColorString deve ser uma cor RGBA válida",
},
{
ns: "Test.HSLColorString",
expected: "HSLColorString deve ser uma cor HSL válida",
},
{
ns: "Test.HSLAColorString",
expected: "HSLAColorString deve ser uma cor HSLA válida",
},
{
ns: "Test.HexadecimalString",
expected: "HexadecimalString deve ser um hexadecimal válido",
},
{
ns: "Test.HexColorString",
expected: "HexColorString deve ser uma cor HEX válida",
},
{
ns: "Test.NumberString",
expected: "NumberString deve ser um número válido",
},
{
ns: "Test.NumericString",
expected: "NumericString deve ser um valor numérico válido",
},
{
ns: "Test.AlphanumString",
expected: "AlphanumString deve conter apenas caracteres alfanuméricos",
},
{
ns: "Test.AlphaString",
expected: "AlphaString deve conter apenas caracteres alfabéticos",
},
{
ns: "Test.LtFieldString",
expected: "LtFieldString deve ser menor que MaxString",
},
{
ns: "Test.LteFieldString",
expected: "LteFieldString deve ser menor ou igual que MaxString",
},
{
ns: "Test.GtFieldString",
expected: "GtFieldString deve ser maior que MaxString",
},
{
ns: "Test.GteFieldString",
expected: "GteFieldString deve ser maior ou igual que MaxString",
},
{
ns: "Test.NeFieldString",
expected: "NeFieldString não deve ser igual a EqFieldString",
},
{
ns: "Test.LtCSFieldString",
expected: "LtCSFieldString deve ser menor que Inner.LtCSFieldString",
},
{
ns: "Test.LteCSFieldString",
expected: "LteCSFieldString deve ser menor ou igual que Inner.LteCSFieldString",
},
{
ns: "Test.GtCSFieldString",
expected: "GtCSFieldString deve ser maior que Inner.GtCSFieldString",
},
{
ns: "Test.GteCSFieldString",
expected: "GteCSFieldString deve ser maior ou igual que Inner.GteCSFieldString",
},
{
ns: "Test.NeCSFieldString",
expected: "NeCSFieldString não deve ser igual a Inner.NeCSFieldString",
},
{
ns: "Test.EqCSFieldString",
expected: "EqCSFieldString deve ser igual a Inner.EqCSFieldString",
},
{
ns: "Test.EqFieldString",
expected: "EqFieldString deve ser igual a MaxString",
},
{
ns: "Test.GteString",
expected: "GteString deve ter pelo menos 3 caracteres",
},
{
ns: "Test.GteNumber",
expected: "GteNumber deve ser maior ou igual a 5,56",
},
{
ns: "Test.GteMultiple",
expected: "GteMultiple deve conter pelo menos 2 items",
},
{
ns: "Test.GteTime",
expected: "GteTime deve ser posterior ou igual à data/hora atual",
},
{
ns: "Test.GtString",
expected: "GtString deve conter mais de 3 caracteres",
},
{
ns: "Test.GtNumber",
expected: "GtNumber deve ser maior que 5,56",
},
{
ns: "Test.GtMultiple",
expected: "GtMultiple deve conter mais de 2 items",
},
{
ns: "Test.GtTime",
expected: "GtTime deve ser posterior à data/hora atual",
},
{
ns: "Test.LteString",
expected: "LteString deve ter no máximo 3 caracteres",
},
{
ns: "Test.LteNumber",
expected: "LteNumber deve ser menor ou igual a 5,56",
},
{
ns: "Test.LteMultiple",
expected: "LteMultiple deve conter no máximo 2 items",
},
{
ns: "Test.LteTime",
expected: "LteTime deve ser anterior ou igual à data/hora atual",
},
{
ns: "Test.LtString",
expected: "LtString deve ter menos de 3 caracteres",
},
{
ns: "Test.LtNumber",
expected: "LtNumber deve ser menor que 5,56",
},
{
ns: "Test.LtMultiple",
expected: "LtMultiple deve conter menos de 2 items",
},
{
ns: "Test.LtTime",
expected: "LtTime deve ser anterior à data / hora atual",
},
{
ns: "Test.NeString",
expected: "NeString não deve ser igual a ",
},
{
ns: "Test.NeNumber",
expected: "NeNumber não deve ser igual a 0.00",
},
{
ns: "Test.NeMultiple",
expected: "NeMultiple não deve ser igual a 0",
},
{
ns: "Test.EqString",
expected: "EqString não é igual a 3",
},
{
ns: "Test.EqNumber",
expected: "EqNumber não é igual a 2.33",
},
{
ns: "Test.EqMultiple",
expected: "EqMultiple não é igual a 7",
},
{
ns: "Test.MaxString",
expected: "MaxString deve ter no máximo 3 caracteres",
},
{
ns: "Test.MaxNumber",
expected: "MaxNumber deve ser 1.113,00 ou menos",
},
{
ns: "Test.MaxMultiple",
expected: "MaxMultiple deve conter no máximo 7 items",
},
{
ns: "Test.MinString",
expected: "MinString deve ter pelo menos 1 caractere",
},
{
ns: "Test.MinNumber",
expected: "MinNumber deve ser 1.113,00 ou superior",
},
{
ns: "Test.MinMultiple",
expected: "MinMultiple deve conter pelo menos 7 items",
},
{
ns: "Test.LenString",
expected: "LenString deve ter 1 caractere",
},
{
ns: "Test.LenNumber",
expected: "LenNumber deve ser igual a 1.113,00",
},
{
ns: "Test.LenMultiple",
expected: "LenMultiple deve conter 7 items",
},
{
ns: "Test.RequiredString",
expected: "RequiredString é obrigatório",
},
{
ns: "Test.RequiredNumber",
expected: "RequiredNumber é obrigatório",
},
{
ns: "Test.RequiredMultiple",
expected: "RequiredMultiple é obrigatório",
},
{
ns: "Test.StrPtrMinLen",
expected: "StrPtrMinLen deve ter pelo menos 10 caracteres",
},
{
ns: "Test.StrPtrMaxLen",
expected: "StrPtrMaxLen deve ter no máximo 1 caractere",
},
{
ns: "Test.StrPtrLen",
expected: "StrPtrLen deve ter 2 caracteres",
},
{
ns: "Test.StrPtrLt",
expected: "StrPtrLt deve ter menos de 1 caractere",
},
{
ns: "Test.StrPtrLte",
expected: "StrPtrLte deve ter no máximo 1 caractere",
},
{
ns: "Test.StrPtrGt",
expected: "StrPtrGt deve conter mais de 10 caracteres",
},
{
ns: "Test.StrPtrGte",
expected: "StrPtrGte deve ter pelo menos 10 caracteres",
},
{
ns: "Test.OneOfString",
expected: "OneOfString deve ser um de [red green]",
},
{
ns: "Test.OneOfInt",
expected: "OneOfInt deve ser um de [5 63]",
},
{
ns: "Test.UniqueSlice",
expected: "UniqueSlice deve conter valores únicos",
},
{
ns: "Test.UniqueArray",
expected: "UniqueArray deve conter valores únicos",
},
{
ns: "Test.UniqueMap",
expected: "UniqueMap deve conter valores únicos",
},
{
ns: "Test.JSONString",
expected: "JSONString deve ser uma string json válida",
},
{
ns: "Test.LowercaseString",
expected: "LowercaseString deve estar em minuscúlas",
},
{
ns: "Test.UppercaseString",
expected: "UppercaseString deve estar em maiúsculas",
},
{
ns: "Test.Datetime",
expected: "Datetime não está no formato 2006-01-02",
},
}
for _, tt := range tests {
var fe validator.FieldError
for _, e := range errs {
if tt.ns == e.Namespace() {
fe = e
break
}
}
NotEqual(t, fe, nil)
Equal(t, tt.expected, fe.Translate(trans))
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,651 @@
package pt_BR
import (
"testing"
"time"
. "github.com/go-playground/assert/v2"
brazilian_portuguese "github.com/go-playground/locales/pt_BR"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
)
func TestTranslations(t *testing.T) {
ptbr := brazilian_portuguese.New()
uni := ut.New(ptbr, ptbr)
trans, _ := uni.GetTranslator("pt_BR")
validate := validator.New()
err := RegisterDefaultTranslations(validate, trans)
Equal(t, err, nil)
type Inner struct {
EqCSFieldString string
NeCSFieldString string
GtCSFieldString string
GteCSFieldString string
LtCSFieldString string
LteCSFieldString string
}
type Test struct {
Inner Inner
RequiredString string `validate:"required"`
RequiredNumber int `validate:"required"`
RequiredMultiple []string `validate:"required"`
LenString string `validate:"len=1"`
LenNumber float64 `validate:"len=1113.00"`
LenMultiple []string `validate:"len=7"`
MinString string `validate:"min=1"`
MinNumber float64 `validate:"min=1113.00"`
MinMultiple []string `validate:"min=7"`
MaxString string `validate:"max=3"`
MaxNumber float64 `validate:"max=1113.00"`
MaxMultiple []string `validate:"max=7"`
EqString string `validate:"eq=3"`
EqNumber float64 `validate:"eq=2.33"`
EqMultiple []string `validate:"eq=7"`
NeString string `validate:"ne="`
NeNumber float64 `validate:"ne=0.00"`
NeMultiple []string `validate:"ne=0"`
LtString string `validate:"lt=3"`
LtNumber float64 `validate:"lt=5.56"`
LtMultiple []string `validate:"lt=2"`
LtTime time.Time `validate:"lt"`
LteString string `validate:"lte=3"`
LteNumber float64 `validate:"lte=5.56"`
LteMultiple []string `validate:"lte=2"`
LteTime time.Time `validate:"lte"`
GtString string `validate:"gt=3"`
GtNumber float64 `validate:"gt=5.56"`
GtMultiple []string `validate:"gt=2"`
GtTime time.Time `validate:"gt"`
GteString string `validate:"gte=3"`
GteNumber float64 `validate:"gte=5.56"`
GteMultiple []string `validate:"gte=2"`
GteTime time.Time `validate:"gte"`
EqFieldString string `validate:"eqfield=MaxString"`
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"`
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"`
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"`
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"`
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"`
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"`
NeFieldString string `validate:"nefield=EqFieldString"`
GtFieldString string `validate:"gtfield=MaxString"`
GteFieldString string `validate:"gtefield=MaxString"`
LtFieldString string `validate:"ltfield=MaxString"`
LteFieldString string `validate:"ltefield=MaxString"`
AlphaString string `validate:"alpha"`
AlphanumString string `validate:"alphanum"`
NumericString string `validate:"numeric"`
NumberString string `validate:"number"`
HexadecimalString string `validate:"hexadecimal"`
HexColorString string `validate:"hexcolor"`
RGBColorString string `validate:"rgb"`
RGBAColorString string `validate:"rgba"`
HSLColorString string `validate:"hsl"`
HSLAColorString string `validate:"hsla"`
Email string `validate:"email"`
URL string `validate:"url"`
URI string `validate:"uri"`
Base64 string `validate:"base64"`
Contains string `validate:"contains=purpose"`
ContainsAny string `validate:"containsany=!@#$"`
Excludes string `validate:"excludes=text"`
ExcludesAll string `validate:"excludesall=!@#$"`
ExcludesRune string `validate:"excludesrune=☻"`
ISBN string `validate:"isbn"`
ISBN10 string `validate:"isbn10"`
ISBN13 string `validate:"isbn13"`
UUID string `validate:"uuid"`
UUID3 string `validate:"uuid3"`
UUID4 string `validate:"uuid4"`
UUID5 string `validate:"uuid5"`
ULID string `validate:"ulid"`
ASCII string `validate:"ascii"`
PrintableASCII string `validate:"printascii"`
MultiByte string `validate:"multibyte"`
DataURI string `validate:"datauri"`
Latitude string `validate:"latitude"`
Longitude string `validate:"longitude"`
SSN string `validate:"ssn"`
IP string `validate:"ip"`
IPv4 string `validate:"ipv4"`
IPv6 string `validate:"ipv6"`
CIDR string `validate:"cidr"`
CIDRv4 string `validate:"cidrv4"`
CIDRv6 string `validate:"cidrv6"`
TCPAddr string `validate:"tcp_addr"`
TCPAddrv4 string `validate:"tcp4_addr"`
TCPAddrv6 string `validate:"tcp6_addr"`
UDPAddr string `validate:"udp_addr"`
UDPAddrv4 string `validate:"udp4_addr"`
UDPAddrv6 string `validate:"udp6_addr"`
IPAddr string `validate:"ip_addr"`
IPAddrv4 string `validate:"ip4_addr"`
IPAddrv6 string `validate:"ip6_addr"`
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"`
StrPtrMaxLen *string `validate:"max=1"`
StrPtrLen *string `validate:"len=2"`
StrPtrLt *string `validate:"lt=1"`
StrPtrLte *string `validate:"lte=1"`
StrPtrGt *string `validate:"gt=10"`
StrPtrGte *string `validate:"gte=10"`
OneOfString string `validate:"oneof=red green"`
OneOfInt int `validate:"oneof=5 63"`
BooleanString string `validate:"boolean"`
CveString string `validate:"cve"`
}
var test Test
test.Inner.EqCSFieldString = "1234"
test.Inner.GtCSFieldString = "1234"
test.Inner.GteCSFieldString = "1234"
test.MaxString = "1234"
test.MaxNumber = 2000
test.MaxMultiple = make([]string, 9)
test.LtString = "1234"
test.LtNumber = 6
test.LtMultiple = make([]string, 3)
test.LtTime = time.Now().Add(time.Hour * 24)
test.LteString = "1234"
test.LteNumber = 6
test.LteMultiple = make([]string, 3)
test.LteTime = time.Now().Add(time.Hour * 24)
test.LtFieldString = "12345"
test.LteFieldString = "12345"
test.LtCSFieldString = "1234"
test.LteCSFieldString = "1234"
test.AlphaString = "abc3"
test.AlphanumString = "abc3!"
test.NumericString = "12E.00"
test.NumberString = "12E"
test.BooleanString = "A"
test.CveString = "A"
test.Excludes = "este é um texto de teste"
test.ExcludesAll = "Isso é Ótimo!"
test.ExcludesRune = "Amo isso ☻"
test.ASCII = "カタカナ"
test.PrintableASCII = "カタカナ"
test.MultiByte = "1234feerf"
s := "toolong"
test.StrPtrMaxLen = &s
test.StrPtrLen = &s
err = validate.Struct(test)
NotEqual(t, err, nil)
errs, ok := err.(validator.ValidationErrors)
Equal(t, ok, true)
tests := []struct {
ns string
expected string
}{
{
ns: "Test.IsColor",
expected: "IsColor deve ser uma cor válida",
},
{
ns: "Test.MAC",
expected: "MAC deve conter um endereço MAC válido",
},
{
ns: "Test.IPAddr",
expected: "IPAddr deve ser um endereço IP resolvível",
},
{
ns: "Test.IPAddrv4",
expected: "IPAddrv4 deve ser um endereço IPv4 resolvível",
},
{
ns: "Test.IPAddrv6",
expected: "IPAddrv6 deve ser um endereço IPv6 resolvível",
},
{
ns: "Test.UDPAddr",
expected: "UDPAddr deve ser um endereço UDP válido",
},
{
ns: "Test.UDPAddrv4",
expected: "UDPAddrv4 deve ser um endereço IPv4 UDP válido",
},
{
ns: "Test.UDPAddrv6",
expected: "UDPAddrv6 deve ser um endereço IPv6 UDP válido",
},
{
ns: "Test.TCPAddr",
expected: "TCPAddr deve ser um endereço TCP válido",
},
{
ns: "Test.TCPAddrv4",
expected: "TCPAddrv4 deve ser um endereço IPv4 TCP válido",
},
{
ns: "Test.TCPAddrv6",
expected: "TCPAddrv6 deve ser um endereço IPv6 TCP válido",
},
{
ns: "Test.CIDR",
expected: "CIDR deve conter uma notação CIDR válida",
},
{
ns: "Test.CIDRv4",
expected: "CIDRv4 deve conter uma notação CIDR válida para um endereço IPv4",
},
{
ns: "Test.CIDRv6",
expected: "CIDRv6 deve conter uma notação CIDR válida para um endereço IPv6",
},
{
ns: "Test.SSN",
expected: "SSN deve ser um número SSN válido",
},
{
ns: "Test.IP",
expected: "IP deve ser um endereço de IP válido",
},
{
ns: "Test.IPv4",
expected: "IPv4 deve ser um endereço IPv4 válido",
},
{
ns: "Test.IPv6",
expected: "IPv6 deve ser um endereço IPv6 válido",
},
{
ns: "Test.DataURI",
expected: "DataURI deve conter um URI data válido",
},
{
ns: "Test.Latitude",
expected: "Latitude deve conter uma coordenada de latitude válida",
},
{
ns: "Test.Longitude",
expected: "Longitude deve conter uma coordenada de longitude válida",
},
{
ns: "Test.MultiByte",
expected: "MultiByte deve conter caracteres multibyte",
},
{
ns: "Test.ASCII",
expected: "ASCII deve conter apenas caracteres ascii",
},
{
ns: "Test.PrintableASCII",
expected: "PrintableASCII deve conter apenas caracteres ascii imprimíveis",
},
{
ns: "Test.UUID",
expected: "UUID deve ser um UUID válido",
},
{
ns: "Test.UUID3",
expected: "UUID3 deve ser um UUID versão 3 válido",
},
{
ns: "Test.UUID4",
expected: "UUID4 deve ser um UUID versão 4 válido",
},
{
ns: "Test.UUID5",
expected: "UUID5 deve ser um UUID versão 5 válido",
},
{
ns: "Test.ULID",
expected: "ULID deve ser uma ULID válida",
},
{
ns: "Test.ISBN",
expected: "ISBN deve ser um número ISBN válido",
},
{
ns: "Test.ISBN10",
expected: "ISBN10 deve ser um número ISBN-10 válido",
},
{
ns: "Test.ISBN13",
expected: "ISBN13 deve ser um número ISBN-13 válido",
},
{
ns: "Test.Excludes",
expected: "Excludes não deve conter o texto 'text'",
},
{
ns: "Test.ExcludesAll",
expected: "ExcludesAll não deve conter nenhum dos caracteres '!@#$'",
},
{
ns: "Test.ExcludesRune",
expected: "ExcludesRune não deve conter '☻'",
},
{
ns: "Test.ContainsAny",
expected: "ContainsAny deve conter pelo menos um dos caracteres '!@#$'",
},
{
ns: "Test.Contains",
expected: "Contains deve conter o texto 'purpose'",
},
{
ns: "Test.Base64",
expected: "Base64 deve ser uma string Base64 válida",
},
{
ns: "Test.Email",
expected: "Email deve ser um endereço de e-mail válido",
},
{
ns: "Test.URL",
expected: "URL deve ser uma URL válida",
},
{
ns: "Test.URI",
expected: "URI deve ser uma URI válida",
},
{
ns: "Test.RGBColorString",
expected: "RGBColorString deve ser uma cor RGB válida",
},
{
ns: "Test.RGBAColorString",
expected: "RGBAColorString deve ser uma cor RGBA válida",
},
{
ns: "Test.HSLColorString",
expected: "HSLColorString deve ser uma cor HSL válida",
},
{
ns: "Test.HSLAColorString",
expected: "HSLAColorString deve ser uma cor HSLA válida",
},
{
ns: "Test.HexadecimalString",
expected: "HexadecimalString deve ser um hexadecimal válido",
},
{
ns: "Test.HexColorString",
expected: "HexColorString deve ser uma cor HEX válida",
},
{
ns: "Test.NumberString",
expected: "NumberString deve ser um número válido",
},
{
ns: "Test.NumericString",
expected: "NumericString deve ser um valor numérico válido",
},
{
ns: "Test.AlphanumString",
expected: "AlphanumString deve conter caracteres alfanuméricos",
},
{
ns: "Test.AlphaString",
expected: "AlphaString deve conter caracteres alfabéticos",
},
{
ns: "Test.LtFieldString",
expected: "LtFieldString deve ser menor que MaxString",
},
{
ns: "Test.LteFieldString",
expected: "LteFieldString deve ser menor ou igual a MaxString",
},
{
ns: "Test.GtFieldString",
expected: "GtFieldString deve ser maior do que MaxString",
},
{
ns: "Test.GteFieldString",
expected: "GteFieldString deve ser maior ou igual a MaxString",
},
{
ns: "Test.NeFieldString",
expected: "NeFieldString não deve ser igual a EqFieldString",
},
{
ns: "Test.LtCSFieldString",
expected: "LtCSFieldString deve ser menor que Inner.LtCSFieldString",
},
{
ns: "Test.LteCSFieldString",
expected: "LteCSFieldString deve ser menor ou igual a Inner.LteCSFieldString",
},
{
ns: "Test.GtCSFieldString",
expected: "GtCSFieldString deve ser maior do que Inner.GtCSFieldString",
},
{
ns: "Test.GteCSFieldString",
expected: "GteCSFieldString deve ser maior ou igual a Inner.GteCSFieldString",
},
{
ns: "Test.NeCSFieldString",
expected: "NeCSFieldString não deve ser igual a Inner.NeCSFieldString",
},
{
ns: "Test.EqCSFieldString",
expected: "EqCSFieldString deve ser igual a Inner.EqCSFieldString",
},
{
ns: "Test.EqFieldString",
expected: "EqFieldString deve ser igual a MaxString",
},
{
ns: "Test.GteString",
expected: "GteString deve ter pelo menos 3 caracteres",
},
{
ns: "Test.GteNumber",
expected: "GteNumber deve ser 5,56 ou superior",
},
{
ns: "Test.GteMultiple",
expected: "GteMultiple deve conter pelo menos 2 itens",
},
{
ns: "Test.GteTime",
expected: "GteTime deve ser maior ou igual à Data e Hora atual",
},
{
ns: "Test.GtString",
expected: "GtString deve ter mais de 3 caracteres",
},
{
ns: "Test.GtNumber",
expected: "GtNumber deve ser maior do que 5,56",
},
{
ns: "Test.GtMultiple",
expected: "GtMultiple deve conter mais de 2 itens",
},
{
ns: "Test.GtTime",
expected: "GtTime deve ser maior que a Data e Hora atual",
},
{
ns: "Test.LteString",
expected: "LteString deve ter no máximo 3 caracteres",
},
{
ns: "Test.LteNumber",
expected: "LteNumber deve ser 5,56 ou menor",
},
{
ns: "Test.LteMultiple",
expected: "LteMultiple deve conter no máximo 2 itens",
},
{
ns: "Test.LteTime",
expected: "LteTime deve ser menor ou igual à Data e Hora atual",
},
{
ns: "Test.LtString",
expected: "LtString deve ter menos de 3 caracteres",
},
{
ns: "Test.LtNumber",
expected: "LtNumber deve ser menor que 5,56",
},
{
ns: "Test.LtMultiple",
expected: "LtMultiple deve conter menos de 2 itens",
},
{
ns: "Test.LtTime",
expected: "LtTime deve ser inferior à Data e Hora atual",
},
{
ns: "Test.NeString",
expected: "NeString não deve ser igual a ",
},
{
ns: "Test.NeNumber",
expected: "NeNumber não deve ser igual a 0.00",
},
{
ns: "Test.NeMultiple",
expected: "NeMultiple não deve ser igual a 0",
},
{
ns: "Test.EqString",
expected: "EqString não é igual a 3",
},
{
ns: "Test.EqNumber",
expected: "EqNumber não é igual a 2.33",
},
{
ns: "Test.EqMultiple",
expected: "EqMultiple não é igual a 7",
},
{
ns: "Test.MaxString",
expected: "MaxString deve ter no máximo 3 caracteres",
},
{
ns: "Test.MaxNumber",
expected: "MaxNumber deve ser 1.113,00 ou menor",
},
{
ns: "Test.MaxMultiple",
expected: "MaxMultiple deve conter no máximo 7 itens",
},
{
ns: "Test.MinString",
expected: "MinString deve ter pelo menos 1 caractere",
},
{
ns: "Test.MinNumber",
expected: "MinNumber deve ser 1.113,00 ou superior",
},
{
ns: "Test.MinMultiple",
expected: "MinMultiple deve conter pelo menos 7 itens",
},
{
ns: "Test.LenString",
expected: "LenString deve ter 1 caractere",
},
{
ns: "Test.LenNumber",
expected: "LenNumber deve ser igual a 1.113,00",
},
{
ns: "Test.LenMultiple",
expected: "LenMultiple deve conter 7 itens",
},
{
ns: "Test.RequiredString",
expected: "RequiredString é um campo obrigatório",
},
{
ns: "Test.RequiredNumber",
expected: "RequiredNumber é um campo obrigatório",
},
{
ns: "Test.RequiredMultiple",
expected: "RequiredMultiple é um campo obrigatório",
},
{
ns: "Test.StrPtrMinLen",
expected: "StrPtrMinLen deve ter pelo menos 10 caracteres",
},
{
ns: "Test.StrPtrMaxLen",
expected: "StrPtrMaxLen deve ter no máximo 1 caractere",
},
{
ns: "Test.StrPtrLen",
expected: "StrPtrLen deve ter 2 caracteres",
},
{
ns: "Test.StrPtrLt",
expected: "StrPtrLt deve ter menos de 1 caractere",
},
{
ns: "Test.StrPtrLte",
expected: "StrPtrLte deve ter no máximo 1 caractere",
},
{
ns: "Test.StrPtrGt",
expected: "StrPtrGt deve ter mais de 10 caracteres",
},
{
ns: "Test.StrPtrGte",
expected: "StrPtrGte deve ter pelo menos 10 caracteres",
},
{
ns: "Test.OneOfString",
expected: "OneOfString deve ser um de [red green]",
},
{
ns: "Test.OneOfInt",
expected: "OneOfInt deve ser um de [5 63]",
},
{
ns: "Test.BooleanString",
expected: "BooleanString deve ser um valor booleano válido",
},
{
ns: "Test.CveString",
expected: "CveString deve ser um identificador cve válido",
},
}
for _, tt := range tests {
var fe validator.FieldError
for _, e := range errs {
if tt.ns == e.Namespace() {
fe = e
break
}
}
NotEqual(t, fe, nil)
Equal(t, tt.expected, fe.Translate(trans))
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,767 @@
package ru
import (
"log"
//"github.com/rustery/validator"
"testing"
"time"
. "github.com/go-playground/assert/v2"
russian "github.com/go-playground/locales/ru"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
)
func TestTranslations(t *testing.T) {
ru := russian.New()
uni := ut.New(ru, ru)
trans, _ := uni.GetTranslator("ru")
validate := validator.New()
err := RegisterDefaultTranslations(validate, trans)
Equal(t, err, nil)
type Inner struct {
EqCSFieldString string
NeCSFieldString string
GtCSFieldString string
GteCSFieldString string
LtCSFieldString string
LteCSFieldString string
}
type Test struct {
Inner Inner
RequiredString string `validate:"required"`
RequiredNumber int `validate:"required"`
RequiredMultiple []string `validate:"required"`
LenString string `validate:"len=1"`
LenNumber float64 `validate:"len=1113.00"`
LenMultiple []string `validate:"len=7"`
LenMultipleSecond []string `validate:"len=2"`
MinString string `validate:"min=1"`
MinStringMultiple string `validate:"min=2"`
MinStringMultipleSecond string `validate:"min=7"`
MinNumber float64 `validate:"min=1113.00"`
MinMultiple []string `validate:"min=7"`
MinMultipleSecond []string `validate:"min=2"`
MaxString string `validate:"max=3"`
MaxStringSecond string `validate:"max=7"`
MaxNumber float64 `validate:"max=1113.00"`
MaxMultiple []string `validate:"max=7"`
MaxMultipleSecond []string `validate:"max=2"`
EqString string `validate:"eq=3"`
EqNumber float64 `validate:"eq=2.33"`
EqMultiple []string `validate:"eq=7"`
NeString string `validate:"ne="`
NeNumber float64 `validate:"ne=0.00"`
NeMultiple []string `validate:"ne=0"`
LtString string `validate:"lt=3"`
LtStringSecond string `validate:"lt=7"`
LtNumber float64 `validate:"lt=5.56"`
LtMultiple []string `validate:"lt=2"`
LtMultipleSecond []string `validate:"lt=7"`
LtTime time.Time `validate:"lt"`
LteString string `validate:"lte=3"`
LteStringSecond string `validate:"lte=7"`
LteNumber float64 `validate:"lte=5.56"`
LteMultiple []string `validate:"lte=2"`
LteMultipleSecond []string `validate:"lte=7"`
LteTime time.Time `validate:"lte"`
GtString string `validate:"gt=3"`
GtStringSecond string `validate:"gt=7"`
GtNumber float64 `validate:"gt=5.56"`
GtMultiple []string `validate:"gt=2"`
GtMultipleSecond []string `validate:"gt=7"`
GtTime time.Time `validate:"gt"`
GteString string `validate:"gte=3"`
GteStringSecond string `validate:"gte=7"`
GteNumber float64 `validate:"gte=5.56"`
GteMultiple []string `validate:"gte=2"`
GteMultipleSecond []string `validate:"gte=7"`
GteTime time.Time `validate:"gte"`
EqFieldString string `validate:"eqfield=MaxString"`
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"`
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"`
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"`
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"`
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"`
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"`
NeFieldString string `validate:"nefield=EqFieldString"`
GtFieldString string `validate:"gtfield=MaxString"`
GteFieldString string `validate:"gtefield=MaxString"`
LtFieldString string `validate:"ltfield=MaxString"`
LteFieldString string `validate:"ltefield=MaxString"`
AlphaString string `validate:"alpha"`
AlphanumString string `validate:"alphanum"`
NumericString string `validate:"numeric"`
NumberString string `validate:"number"`
HexadecimalString string `validate:"hexadecimal"`
HexColorString string `validate:"hexcolor"`
RGBColorString string `validate:"rgb"`
RGBAColorString string `validate:"rgba"`
HSLColorString string `validate:"hsl"`
HSLAColorString string `validate:"hsla"`
Email string `validate:"email"`
URL string `validate:"url"`
URI string `validate:"uri"`
Base64 string `validate:"base64"`
Contains string `validate:"contains=purpose"`
ContainsAny string `validate:"containsany=!@#$"`
Excludes string `validate:"excludes=text"`
ExcludesAll string `validate:"excludesall=!@#$"`
ExcludesRune string `validate:"excludesrune=☻"`
ISBN string `validate:"isbn"`
ISBN10 string `validate:"isbn10"`
ISBN13 string `validate:"isbn13"`
UUID string `validate:"uuid"`
UUID3 string `validate:"uuid3"`
UUID4 string `validate:"uuid4"`
UUID5 string `validate:"uuid5"`
ULID string `validate:"ulid"`
ASCII string `validate:"ascii"`
PrintableASCII string `validate:"printascii"`
MultiByte string `validate:"multibyte"`
DataURI string `validate:"datauri"`
Latitude string `validate:"latitude"`
Longitude string `validate:"longitude"`
SSN string `validate:"ssn"`
IP string `validate:"ip"`
IPv4 string `validate:"ipv4"`
IPv6 string `validate:"ipv6"`
CIDR string `validate:"cidr"`
CIDRv4 string `validate:"cidrv4"`
CIDRv6 string `validate:"cidrv6"`
TCPAddr string `validate:"tcp_addr"`
TCPAddrv4 string `validate:"tcp4_addr"`
TCPAddrv6 string `validate:"tcp6_addr"`
UDPAddr string `validate:"udp_addr"`
UDPAddrv4 string `validate:"udp4_addr"`
UDPAddrv6 string `validate:"udp6_addr"`
IPAddr string `validate:"ip_addr"`
IPAddrv4 string `validate:"ip4_addr"`
IPAddrv6 string `validate:"ip6_addr"`
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
test.Inner.EqCSFieldString = "1234"
test.Inner.GtCSFieldString = "1234"
test.Inner.GteCSFieldString = "1234"
test.MaxString = "1234"
test.MaxStringSecond = "12345678"
test.MaxNumber = 2000
test.MaxMultiple = make([]string, 9)
test.MaxMultipleSecond = make([]string, 3)
test.LtString = "1234"
test.LtStringSecond = "12345678"
test.LtNumber = 6
test.LtMultiple = make([]string, 3)
test.LtMultipleSecond = make([]string, 8)
test.LtTime = time.Now().Add(time.Hour * 24)
test.LteString = "1234"
test.LteStringSecond = "12345678"
test.LteNumber = 6
test.LteMultiple = make([]string, 3)
test.LteMultipleSecond = make([]string, 8)
test.LteTime = time.Now().Add(time.Hour * 24)
test.LtFieldString = "12345"
test.LteFieldString = "12345"
test.LtCSFieldString = "1234"
test.LteCSFieldString = "1234"
test.AlphaString = "abc3"
test.AlphanumString = "abc3!"
test.NumericString = "12E.00"
test.NumberString = "12E"
test.Excludes = "this is some test text"
test.ExcludesAll = "This is Great!"
test.ExcludesRune = "Love it ☻"
test.ASCII = "カタカナ"
test.PrintableASCII = "カタカナ"
test.MultiByte = "1234feerf"
s := "toolong"
test.StrPtrMaxLen = &s
test.StrPtrLen = &s
test.UniqueSlice = []string{"1234", "1234"}
test.UniqueMap = map[string]string{"key1": "1234", "key2": "1234"}
err = validate.Struct(test)
NotEqual(t, err, nil)
errs, ok := err.(validator.ValidationErrors)
Equal(t, ok, true)
tests := []struct {
ns string
expected string
}{
{
ns: "Test.IsColor",
expected: "IsColor должен быть цветом",
},
{
ns: "Test.MAC",
expected: "MAC должен содержать MAC адрес",
},
{
ns: "Test.IPAddr",
expected: "IPAddr должен быть распознаваемым IP адресом",
},
{
ns: "Test.IPAddrv4",
expected: "IPAddrv4 должен быть распознаваемым IPv4 адресом",
},
{
ns: "Test.IPAddrv6",
expected: "IPAddrv6 должен быть распознаваемым IPv6 адресом",
},
{
ns: "Test.UDPAddr",
expected: "UDPAddr должен быть UDP адресом",
},
{
ns: "Test.UDPAddrv4",
expected: "UDPAddrv4 должен быть IPv4 UDP адресом",
},
{
ns: "Test.UDPAddrv6",
expected: "UDPAddrv6 должен быть IPv6 UDP адресом",
},
{
ns: "Test.TCPAddr",
expected: "TCPAddr должен быть TCP адресом",
},
{
ns: "Test.TCPAddrv4",
expected: "TCPAddrv4 должен быть IPv4 TCP адресом",
},
{
ns: "Test.TCPAddrv6",
expected: "TCPAddrv6 должен быть IPv6 TCP адресом",
},
{
ns: "Test.CIDR",
expected: "CIDR должен содержать CIDR обозначения",
},
{
ns: "Test.CIDRv4",
expected: "CIDRv4 должен содержать CIDR обозначения для IPv4 адреса",
},
{
ns: "Test.CIDRv6",
expected: "CIDRv6 должен содержать CIDR обозначения для IPv6 адреса",
},
{
ns: "Test.SSN",
expected: "SSN должен быть SSN номером",
},
{
ns: "Test.IP",
expected: "IP должен быть IP адресом",
},
{
ns: "Test.IPv4",
expected: "IPv4 должен быть IPv4 адресом",
},
{
ns: "Test.IPv6",
expected: "IPv6 должен быть IPv6 адресом",
},
{
ns: "Test.DataURI",
expected: "DataURI должен содержать Data URI",
},
{
ns: "Test.Latitude",
expected: "Latitude должен содержать координаты широты",
},
{
ns: "Test.Longitude",
expected: "Longitude должен содержать координаты долготы",
},
{
ns: "Test.MultiByte",
expected: "MultiByte должен содержать мультибайтные символы",
},
{
ns: "Test.ASCII",
expected: "ASCII должен содержать только ascii символы",
},
{
ns: "Test.PrintableASCII",
expected: "PrintableASCII должен содержать только доступные для печати ascii символы",
},
{
ns: "Test.UUID",
expected: "UUID должен быть UUID",
},
{
ns: "Test.UUID3",
expected: "UUID3 должен быть UUID 3 версии",
},
{
ns: "Test.UUID4",
expected: "UUID4 должен быть UUID 4 версии",
},
{
ns: "Test.UUID5",
expected: "UUID5 должен быть UUID 5 версии",
},
{
ns: "Test.ULID",
expected: "ULID должен быть ULID",
},
{
ns: "Test.ISBN",
expected: "ISBN должен быть ISBN номером",
},
{
ns: "Test.ISBN10",
expected: "ISBN10 должен быть ISBN-10 номером",
},
{
ns: "Test.ISBN13",
expected: "ISBN13 должен быть ISBN-13 номером",
},
{
ns: "Test.Excludes",
expected: "Excludes не должен содержать текст 'text'",
},
{
ns: "Test.ExcludesAll",
expected: "ExcludesAll не должен содержать символы '!@#$'",
},
{
ns: "Test.ExcludesRune",
expected: "ExcludesRune не должен содержать '☻'",
},
{
ns: "Test.ContainsAny",
expected: "ContainsAny должен содержать минимум один из символов '!@#$'",
},
{
ns: "Test.Contains",
expected: "Contains должен содержать текст 'purpose'",
},
{
ns: "Test.Base64",
expected: "Base64 должен быть Base64 строкой",
},
{
ns: "Test.Email",
expected: "Email должен быть email адресом",
},
{
ns: "Test.URL",
expected: "URL должен быть URL",
},
{
ns: "Test.URI",
expected: "URI должен быть URI",
},
{
ns: "Test.RGBColorString",
expected: "RGBColorString должен быть RGB цветом",
},
{
ns: "Test.RGBAColorString",
expected: "RGBAColorString должен быть RGBA цветом",
},
{
ns: "Test.HSLColorString",
expected: "HSLColorString должен быть HSL цветом",
},
{
ns: "Test.HSLAColorString",
expected: "HSLAColorString должен быть HSLA цветом",
},
{
ns: "Test.HexadecimalString",
expected: "HexadecimalString должен быть шестнадцатеричной строкой",
},
{
ns: "Test.HexColorString",
expected: "HexColorString должен быть HEX цветом",
},
{
ns: "Test.NumberString",
expected: "NumberString должен быть цифрой",
},
{
ns: "Test.NumericString",
expected: "NumericString должен быть цифровым значением",
},
{
ns: "Test.AlphanumString",
expected: "AlphanumString должен содержать только буквы и цифры",
},
{
ns: "Test.AlphaString",
expected: "AlphaString должен содержать только буквы",
},
{
ns: "Test.LtFieldString",
expected: "LtFieldString должен быть менее MaxString",
},
{
ns: "Test.LteFieldString",
expected: "LteFieldString должен быть менее или равен MaxString",
},
{
ns: "Test.GtFieldString",
expected: "GtFieldString должен быть больше MaxString",
},
{
ns: "Test.GteFieldString",
expected: "GteFieldString должен быть больше или равен MaxString",
},
{
ns: "Test.NeFieldString",
expected: "NeFieldString не должен быть равен EqFieldString",
},
{
ns: "Test.LtCSFieldString",
expected: "LtCSFieldString должен быть менее Inner.LtCSFieldString",
},
{
ns: "Test.LteCSFieldString",
expected: "LteCSFieldString должен быть менее или равен Inner.LteCSFieldString",
},
{
ns: "Test.GtCSFieldString",
expected: "GtCSFieldString должен быть больше Inner.GtCSFieldString",
},
{
ns: "Test.GteCSFieldString",
expected: "GteCSFieldString должен быть больше или равен Inner.GteCSFieldString",
},
{
ns: "Test.NeCSFieldString",
expected: "NeCSFieldString не должен быть равен Inner.NeCSFieldString",
},
{
ns: "Test.EqCSFieldString",
expected: "EqCSFieldString должен быть равен Inner.EqCSFieldString",
},
{
ns: "Test.EqFieldString",
expected: "EqFieldString должен быть равен MaxString",
},
{
ns: "Test.GteString",
expected: "GteString должен содержать минимум 3 символа",
},
{
ns: "Test.GteStringSecond",
expected: "GteStringSecond должен содержать минимум 7 символов",
},
{
ns: "Test.GteNumber",
expected: "GteNumber должен быть больше или равно 5,56",
},
{
ns: "Test.GteMultiple",
expected: "GteMultiple должен содержать минимум 2 элемента",
},
{
ns: "Test.GteMultipleSecond",
expected: "GteMultipleSecond должен содержать минимум 7 элементов",
},
{
ns: "Test.GteTime",
expected: "GteTime должна быть позже или равна текущему моменту",
},
{
ns: "Test.GtString",
expected: "GtString должен быть длиннее 3 символов",
},
{
ns: "Test.GtStringSecond",
expected: "GtStringSecond должен быть длиннее 7 символов",
},
{
ns: "Test.GtNumber",
expected: "GtNumber должен быть больше 5,56",
},
{
ns: "Test.GtMultiple",
expected: "GtMultiple должен содержать более 2 элементов",
},
{
ns: "Test.GtMultipleSecond",
expected: "GtMultipleSecond должен содержать более 7 элементов",
},
{
ns: "Test.GtTime",
expected: "GtTime должна быть позже текущего момента",
},
{
ns: "Test.LteString",
expected: "LteString должен содержать максимум 3 символа",
},
{
ns: "Test.LteStringSecond",
expected: "LteStringSecond должен содержать максимум 7 символов",
},
{
ns: "Test.LteNumber",
expected: "LteNumber должен быть менее или равен 5,56",
},
{
ns: "Test.LteMultiple",
expected: "LteMultiple должен содержать максимум 2 элемента",
},
{
ns: "Test.LteMultipleSecond",
expected: "LteMultipleSecond должен содержать максимум 7 элементов",
},
{
ns: "Test.LteTime",
expected: "LteTime must be less than or equal to the current Date & Time",
},
{
ns: "Test.LtString",
expected: "LtString должен иметь менее 3 символов",
},
{
ns: "Test.LtStringSecond",
expected: "LtStringSecond должен иметь менее 7 символов",
},
{
ns: "Test.LtNumber",
expected: "LtNumber должен быть менее 5,56",
},
{
ns: "Test.LtMultiple",
expected: "LtMultiple должен содержать менее 2 элементов",
},
{
ns: "Test.LtMultipleSecond",
expected: "LtMultipleSecond должен содержать менее 7 элементов",
},
{
ns: "Test.LtTime",
expected: "LtTime must be less than the current Date & Time",
},
{
ns: "Test.NeString",
expected: "NeString должен быть не равен ",
},
{
ns: "Test.NeNumber",
expected: "NeNumber должен быть не равен 0.00",
},
{
ns: "Test.NeMultiple",
expected: "NeMultiple должен быть не равен 0",
},
{
ns: "Test.EqString",
expected: "EqString не равен 3",
},
{
ns: "Test.EqNumber",
expected: "EqNumber не равен 2.33",
},
{
ns: "Test.EqMultiple",
expected: "EqMultiple не равен 7",
},
{
ns: "Test.MaxString",
expected: "MaxString должен содержать максимум 3 символа",
},
{
ns: "Test.MaxStringSecond",
expected: "MaxStringSecond должен содержать максимум 7 символов",
},
{
ns: "Test.MaxNumber",
expected: "MaxNumber должен быть меньше или равно 1 113,00",
},
{
ns: "Test.MaxMultiple",
expected: "MaxMultiple должен содержать максимум 7 элементов",
},
{
ns: "Test.MaxMultipleSecond",
expected: "MaxMultipleSecond должен содержать максимум 2 элемента",
},
{
ns: "Test.MinString",
expected: "MinString должен содержать минимум 1 символ",
},
{
ns: "Test.MinStringMultiple",
expected: "MinStringMultiple должен содержать минимум 2 символа",
},
{
ns: "Test.MinStringMultipleSecond",
expected: "MinStringMultipleSecond должен содержать минимум 7 символов",
},
{
ns: "Test.MinNumber",
expected: "MinNumber должен быть больше или равно 1 113,00",
},
{
ns: "Test.MinMultiple",
expected: "MinMultiple должен содержать минимум 7 элементов",
},
{
ns: "Test.MinMultipleSecond",
expected: "MinMultipleSecond должен содержать минимум 2 элемента",
},
{
ns: "Test.LenString",
expected: "LenString должен быть длиной в 1 символ",
},
{
ns: "Test.LenNumber",
expected: "LenNumber должен быть равен 1 113,00",
},
{
ns: "Test.LenMultiple",
expected: "LenMultiple должен содержать 7 элементов",
},
{
ns: "Test.LenMultipleSecond",
expected: "LenMultipleSecond должен содержать 2 элемента",
},
{
ns: "Test.RequiredString",
expected: "RequiredString обязательное поле",
},
{
ns: "Test.RequiredNumber",
expected: "RequiredNumber обязательное поле",
},
{
ns: "Test.RequiredMultiple",
expected: "RequiredMultiple обязательное поле",
},
{
ns: "Test.StrPtrMinLen",
expected: "StrPtrMinLen должен содержать минимум 10 символов",
},
{
ns: "Test.StrPtrMinLenSecond",
expected: "StrPtrMinLenSecond должен содержать минимум 2 символа",
},
{
ns: "Test.StrPtrMaxLen",
expected: "StrPtrMaxLen должен содержать максимум 1 символ",
},
{
ns: "Test.StrPtrLen",
expected: "StrPtrLen должен быть длиной в 2 символа",
},
{
ns: "Test.StrPtrLenSecond",
expected: "StrPtrLenSecond должен быть длиной в 7 символов",
},
{
ns: "Test.StrPtrLt",
expected: "StrPtrLt должен иметь менее 1 символ",
},
{
ns: "Test.StrPtrLte",
expected: "StrPtrLte должен содержать максимум 1 символ",
},
{
ns: "Test.StrPtrLteMultiple",
expected: "StrPtrLteMultiple должен содержать максимум 2 символа",
},
{
ns: "Test.StrPtrLteMultipleSecond",
expected: "StrPtrLteMultipleSecond должен содержать максимум 7 символов",
},
{
ns: "Test.StrPtrGt",
expected: "StrPtrGt должен быть длиннее 10 символов",
},
{
ns: "Test.StrPtrGtSecond",
expected: "StrPtrGtSecond должен быть длиннее 2 символов",
},
{
ns: "Test.StrPtrGte",
expected: "StrPtrGte должен содержать минимум 10 символов",
},
{
ns: "Test.StrPtrGteSecond",
expected: "StrPtrGteSecond должен содержать минимум 2 символа",
},
{
ns: "Test.OneOfString",
expected: "OneOfString должен быть одним из [red green]",
},
{
ns: "Test.OneOfInt",
expected: "OneOfInt должен быть одним из [5 63]",
},
{
ns: "Test.UniqueSlice",
expected: "UniqueSlice должен содержать уникальные значения",
},
{
ns: "Test.UniqueArray",
expected: "UniqueArray должен содержать уникальные значения",
},
{
ns: "Test.UniqueMap",
expected: "UniqueMap должен содержать уникальные значения",
},
}
for _, tt := range tests {
var fe validator.FieldError
for _, e := range errs {
if tt.ns == e.Namespace() {
fe = e
break
}
}
log.Println(fe)
NotEqual(t, fe, nil)
Equal(t, tt.expected, fe.Translate(trans))
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,657 @@
package tr
import (
"testing"
"time"
. "github.com/go-playground/assert/v2"
turkish "github.com/go-playground/locales/tr"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
)
func TestTranslations(t *testing.T) {
tr := turkish.New()
uni := ut.New(tr, tr)
trans, _ := uni.GetTranslator("tr")
validate := validator.New()
err := RegisterDefaultTranslations(validate, trans)
Equal(t, err, nil)
type Inner struct {
EqCSFieldString string
NeCSFieldString string
GtCSFieldString string
GteCSFieldString string
LtCSFieldString string
LteCSFieldString string
}
type Test struct {
Inner Inner
RequiredString string `validate:"required"`
RequiredNumber int `validate:"required"`
RequiredMultiple []string `validate:"required"`
LenString string `validate:"len=1"`
LenNumber float64 `validate:"len=1113.00"`
LenMultiple []string `validate:"len=7"`
MinString string `validate:"min=1"`
MinNumber float64 `validate:"min=1113.00"`
MinMultiple []string `validate:"min=7"`
MaxString string `validate:"max=3"`
MaxNumber float64 `validate:"max=1113.00"`
MaxMultiple []string `validate:"max=7"`
EqString string `validate:"eq=3"`
EqNumber float64 `validate:"eq=2.33"`
EqMultiple []string `validate:"eq=7"`
NeString string `validate:"ne="`
NeNumber float64 `validate:"ne=0.00"`
NeMultiple []string `validate:"ne=0"`
LtString string `validate:"lt=3"`
LtNumber float64 `validate:"lt=5.56"`
LtMultiple []string `validate:"lt=2"`
LtTime time.Time `validate:"lt"`
LteString string `validate:"lte=3"`
LteNumber float64 `validate:"lte=5.56"`
LteMultiple []string `validate:"lte=2"`
LteTime time.Time `validate:"lte"`
GtString string `validate:"gt=3"`
GtNumber float64 `validate:"gt=5.56"`
GtMultiple []string `validate:"gt=2"`
GtTime time.Time `validate:"gt"`
GteString string `validate:"gte=3"`
GteNumber float64 `validate:"gte=5.56"`
GteMultiple []string `validate:"gte=2"`
GteTime time.Time `validate:"gte"`
EqFieldString string `validate:"eqfield=MaxString"`
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"`
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"`
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"`
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"`
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"`
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"`
NeFieldString string `validate:"nefield=EqFieldString"`
GtFieldString string `validate:"gtfield=MaxString"`
GteFieldString string `validate:"gtefield=MaxString"`
LtFieldString string `validate:"ltfield=MaxString"`
LteFieldString string `validate:"ltefield=MaxString"`
AlphaString string `validate:"alpha"`
AlphanumString string `validate:"alphanum"`
NumericString string `validate:"numeric"`
NumberString string `validate:"number"`
HexadecimalString string `validate:"hexadecimal"`
HexColorString string `validate:"hexcolor"`
RGBColorString string `validate:"rgb"`
RGBAColorString string `validate:"rgba"`
HSLColorString string `validate:"hsl"`
HSLAColorString string `validate:"hsla"`
Email string `validate:"email"`
URL string `validate:"url"`
URI string `validate:"uri"`
Base64 string `validate:"base64"`
Contains string `validate:"contains=purpose"`
ContainsAny string `validate:"containsany=!@#$"`
Excludes string `validate:"excludes=text"`
ExcludesAll string `validate:"excludesall=!@#$"`
ExcludesRune string `validate:"excludesrune=☻"`
ISBN string `validate:"isbn"`
ISBN10 string `validate:"isbn10"`
ISBN13 string `validate:"isbn13"`
UUID string `validate:"uuid"`
UUID3 string `validate:"uuid3"`
UUID4 string `validate:"uuid4"`
UUID5 string `validate:"uuid5"`
ULID string `validate:"ulid"`
ASCII string `validate:"ascii"`
PrintableASCII string `validate:"printascii"`
MultiByte string `validate:"multibyte"`
DataURI string `validate:"datauri"`
Latitude string `validate:"latitude"`
Longitude string `validate:"longitude"`
SSN string `validate:"ssn"`
IP string `validate:"ip"`
IPv4 string `validate:"ipv4"`
IPv6 string `validate:"ipv6"`
CIDR string `validate:"cidr"`
CIDRv4 string `validate:"cidrv4"`
CIDRv6 string `validate:"cidrv6"`
TCPAddr string `validate:"tcp_addr"`
TCPAddrv4 string `validate:"tcp4_addr"`
TCPAddrv6 string `validate:"tcp6_addr"`
UDPAddr string `validate:"udp_addr"`
UDPAddrv4 string `validate:"udp4_addr"`
UDPAddrv6 string `validate:"udp6_addr"`
IPAddr string `validate:"ip_addr"`
IPAddrv4 string `validate:"ip4_addr"`
IPAddrv6 string `validate:"ip6_addr"`
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"`
StrPtrMaxLen *string `validate:"max=1"`
StrPtrLen *string `validate:"len=2"`
StrPtrLt *string `validate:"lt=1"`
StrPtrLte *string `validate:"lte=1"`
StrPtrGt *string `validate:"gt=10"`
StrPtrGte *string `validate:"gte=10"`
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
test.Inner.EqCSFieldString = "1234"
test.Inner.GtCSFieldString = "1234"
test.Inner.GteCSFieldString = "1234"
test.MaxString = "1234"
test.MaxNumber = 2000
test.MaxMultiple = make([]string, 9)
test.LtString = "1234"
test.LtNumber = 6
test.LtMultiple = make([]string, 3)
test.LtTime = time.Now().Add(time.Hour * 24)
test.LteString = "1234"
test.LteNumber = 6
test.LteMultiple = make([]string, 3)
test.LteTime = time.Now().Add(time.Hour * 24)
test.LtFieldString = "12345"
test.LteFieldString = "12345"
test.LtCSFieldString = "1234"
test.LteCSFieldString = "1234"
test.AlphaString = "abc3"
test.AlphanumString = "abc3!"
test.NumericString = "12E.00"
test.NumberString = "12E"
test.Excludes = "this is some test text"
test.ExcludesAll = "This is Great!"
test.ExcludesRune = "Love it ☻"
test.ASCII = "カタカナ"
test.PrintableASCII = "カタカナ"
test.MultiByte = "1234feerf"
s := "toolong"
test.StrPtrMaxLen = &s
test.StrPtrLen = &s
test.UniqueSlice = []string{"1234", "1234"}
test.UniqueMap = map[string]string{"key1": "1234", "key2": "1234"}
err = validate.Struct(test)
NotEqual(t, err, nil)
errs, ok := err.(validator.ValidationErrors)
Equal(t, ok, true)
tests := []struct {
ns string
expected string
}{
{
ns: "Test.IsColor",
expected: "IsColor geçerli bir renk olmalıdır",
},
{
ns: "Test.MAC",
expected: "MAC geçerli bir MAC adresi içermelidir",
},
{
ns: "Test.IPAddr",
expected: "IPAddr çözülebilir bir IP adresi olmalıdır",
},
{
ns: "Test.IPAddrv4",
expected: "IPAddrv4 çözülebilir bir IPv4 adresi olmalıdır",
},
{
ns: "Test.IPAddrv6",
expected: "IPAddrv6 çözülebilir bir IPv6 adresi olmalıdır",
},
{
ns: "Test.UDPAddr",
expected: "UDPAddr geçerli bir UDP adresi olmalıdır",
},
{
ns: "Test.UDPAddrv4",
expected: "UDPAddrv4 geçerli bir IPv4 UDP adresi olmalıdır",
},
{
ns: "Test.UDPAddrv6",
expected: "UDPAddrv6 geçerli bir IPv6 UDP adresi olmalıdır",
},
{
ns: "Test.TCPAddr",
expected: "TCPAddr geçerli bir TCP adresi olmalıdır",
},
{
ns: "Test.TCPAddrv4",
expected: "TCPAddrv4 geçerli bir IPv4 TCP adresi olmalıdır",
},
{
ns: "Test.TCPAddrv6",
expected: "TCPAddrv6 geçerli bir IPv6 TCP adresi olmalıdır",
},
{
ns: "Test.CIDR",
expected: "CIDR geçerli bir CIDR gösterimi içermelidir",
},
{
ns: "Test.CIDRv4",
expected: "CIDRv4 bir IPv4 adresi için geçerli bir CIDR gösterimi içermelidir",
},
{
ns: "Test.CIDRv6",
expected: "CIDRv6 bir IPv6 adresi için geçerli bir CIDR gösterimi içermelidir",
},
{
ns: "Test.SSN",
expected: "SSN geçerli bir SSN numarası olmalıdır",
},
{
ns: "Test.IP",
expected: "IP geçerli bir IP adresi olmalıdır",
},
{
ns: "Test.IPv4",
expected: "IPv4 geçerli bir IPv4 adresi olmalıdır",
},
{
ns: "Test.IPv6",
expected: "IPv6 geçerli bir IPv6 adresi olmalıdır",
},
{
ns: "Test.DataURI",
expected: "DataURI geçerli bir Veri URI içermelidir",
},
{
ns: "Test.Latitude",
expected: "Latitude geçerli bir enlem koordinatı içermelidir",
},
{
ns: "Test.Longitude",
expected: "Longitude geçerli bir boylam koordinatı içermelidir",
},
{
ns: "Test.MultiByte",
expected: "MultiByte çok baytlı karakterler içermelidir",
},
{
ns: "Test.ASCII",
expected: "ASCII yalnızca ascii karakterler içermelidir",
},
{
ns: "Test.PrintableASCII",
expected: "PrintableASCII yalnızca yazdırılabilir ascii karakterleri içermelidir",
},
{
ns: "Test.UUID",
expected: "UUID geçerli bir UUID olmalıdır",
},
{
ns: "Test.UUID3",
expected: "UUID3 geçerli bir sürüm 3 UUID olmalıdır",
},
{
ns: "Test.UUID4",
expected: "UUID4 geçerli bir sürüm 4 UUID olmalıdır",
},
{
ns: "Test.UUID5",
expected: "UUID5 geçerli bir sürüm 5 UUID olmalıdır",
},
{
ns: "Test.ULID",
expected: "ULID geçerli bir ULID olmalıdır",
},
{
ns: "Test.ISBN",
expected: "ISBN geçerli bir ISBN numarası olmalıdır",
},
{
ns: "Test.ISBN10",
expected: "ISBN10 geçerli bir ISBN-10 numarası olmalıdır",
},
{
ns: "Test.ISBN13",
expected: "ISBN13 geçerli bir ISBN-13 numarası olmalıdır",
},
{
ns: "Test.Excludes",
expected: "Excludes, 'text' metnini içeremez",
},
{
ns: "Test.ExcludesAll",
expected: "ExcludesAll, '!@#$' karakterlerinden hiçbirini içeremez",
},
{
ns: "Test.ExcludesRune",
expected: "ExcludesRune, '☻' ifadesini içeremez",
},
{
ns: "Test.ContainsAny",
expected: "ContainsAny, '!@#$' karakterlerinden en az birini içermelidir",
},
{
ns: "Test.Contains",
expected: "Contains, 'purpose' metnini içermelidir",
},
{
ns: "Test.Base64",
expected: "Base64 geçerli bir Base64 karakter dizesi olmalıdır",
},
{
ns: "Test.Email",
expected: "Email geçerli bir e-posta adresi olmalıdır",
},
{
ns: "Test.URL",
expected: "URL geçerli bir URL olmalıdır",
},
{
ns: "Test.URI",
expected: "URI geçerli bir URI olmalıdır",
},
{
ns: "Test.RGBColorString",
expected: "RGBColorString geçerli bir RGB rengi olmalıdır",
},
{
ns: "Test.RGBAColorString",
expected: "RGBAColorString geçerli bir RGBA rengi olmalıdır",
},
{
ns: "Test.HSLColorString",
expected: "HSLColorString geçerli bir HSL rengi olmalıdır",
},
{
ns: "Test.HSLAColorString",
expected: "HSLAColorString geçerli bir HSLA rengi olmalıdır",
},
{
ns: "Test.HexadecimalString",
expected: "HexadecimalString geçerli bir onaltılık olmalıdır",
},
{
ns: "Test.HexColorString",
expected: "HexColorString geçerli bir HEX rengi olmalıdır",
},
{
ns: "Test.NumberString",
expected: "NumberString geçerli bir sayı olmalıdır",
},
{
ns: "Test.NumericString",
expected: "NumericString geçerli bir sayısal değer olmalıdır",
},
{
ns: "Test.AlphanumString",
expected: "AlphanumString yalnızca alfanümerik karakterler içerebilir",
},
{
ns: "Test.AlphaString",
expected: "AlphaString yalnızca alfabetik karakterler içerebilir",
},
{
ns: "Test.LtFieldString",
expected: "LtFieldString, MaxString değerinden küçük olmalıdır",
},
{
ns: "Test.LteFieldString",
expected: "LteFieldString, MaxString değerinden küçük veya ona eşit olmalıdır",
},
{
ns: "Test.GtFieldString",
expected: "GtFieldString, MaxString değerinden büyük olmalıdır",
},
{
ns: "Test.GteFieldString",
expected: "GteFieldString, MaxString değerinden büyük veya ona eşit olmalıdır",
},
{
ns: "Test.NeFieldString",
expected: "NeFieldString, EqFieldString değerine eşit olmamalıdır",
},
{
ns: "Test.LtCSFieldString",
expected: "LtCSFieldString, Inner.LtCSFieldString değerinden küçük olmalıdır",
},
{
ns: "Test.LteCSFieldString",
expected: "LteCSFieldString, Inner.LteCSFieldString değerinden küçük veya ona eşit olmalıdır",
},
{
ns: "Test.GtCSFieldString",
expected: "GtCSFieldString, Inner.GtCSFieldString değerinden büyük olmalıdır",
},
{
ns: "Test.GteCSFieldString",
expected: "GteCSFieldString, Inner.GteCSFieldString değerinden küçük veya ona eşit olmalıdır",
},
{
ns: "Test.NeCSFieldString",
expected: "NeCSFieldString, Inner.NeCSFieldString değerine eşit olmamalıdır",
},
{
ns: "Test.EqCSFieldString",
expected: "EqCSFieldString, Inner.EqCSFieldString değerine eşit olmalıdır",
},
{
ns: "Test.EqFieldString",
expected: "EqFieldString, MaxString değerine eşit olmalıdır",
},
{
ns: "Test.GteString",
expected: "GteString en az 3 karakter uzunluğunda olmalıdır",
},
{
ns: "Test.GteNumber",
expected: "GteNumber, 5,56 veya daha büyük olmalıdır",
},
{
ns: "Test.GteMultiple",
expected: "GteMultiple en az 2 öğe içermelidir",
},
{
ns: "Test.GteTime",
expected: "GteTime geçerli Tarih ve Saatten büyük veya ona eşit olmalıdır",
},
{
ns: "Test.GtString",
expected: "GtString, 3 karakter uzunluğundan fazla olmalıdır",
},
{
ns: "Test.GtNumber",
expected: "GtNumber, 5,56 değerinden büyük olmalıdır",
},
{
ns: "Test.GtMultiple",
expected: "GtMultiple, 2 öğeden daha fazla içermelidir",
},
{
ns: "Test.GtTime",
expected: "GtTime geçerli Tarih ve Saatten büyük olmalıdır",
},
{
ns: "Test.LteString",
expected: "LteString en fazla 3 karakter uzunluğunda olmalıdır",
},
{
ns: "Test.LteNumber",
expected: "LteNumber, 5,56 veya daha az olmalıdır",
},
{
ns: "Test.LteMultiple",
expected: "LteMultiple, maksimum 2 öğe içermelidir",
},
{
ns: "Test.LteTime",
expected: "LteTime geçerli Tarih ve Saate eşit veya daha küçük olmalıdır",
},
{
ns: "Test.LtString",
expected: "LtString, 3 karakter uzunluğundan daha az olmalıdır",
},
{
ns: "Test.LtNumber",
expected: "LtNumber, 5,56 değerinden küçük olmalıdır",
},
{
ns: "Test.LtMultiple",
expected: "LtMultiple, 2 öğeden daha az içermelidir",
},
{
ns: "Test.LtTime",
expected: "LtTime geçerli Tarih ve Saatten daha az olmalıdır",
},
{
ns: "Test.NeString",
expected: "NeString, değerine eşit olmamalıdır",
},
{
ns: "Test.NeNumber",
expected: "NeNumber, 0.00 değerine eşit olmamalıdır",
},
{
ns: "Test.NeMultiple",
expected: "NeMultiple, 0 değerine eşit olmamalıdır",
},
{
ns: "Test.EqString",
expected: "EqString, 3 değerine eşit değil",
},
{
ns: "Test.EqNumber",
expected: "EqNumber, 2.33 değerine eşit değil",
},
{
ns: "Test.EqMultiple",
expected: "EqMultiple, 7 değerine eşit değil",
},
{
ns: "Test.MaxString",
expected: "MaxString uzunluğu en fazla 3 karakter olmalıdır",
},
{
ns: "Test.MaxNumber",
expected: "MaxNumber, 1.113,00 veya daha az olmalıdır",
},
{
ns: "Test.MaxMultiple",
expected: "MaxMultiple maksimum 7 öğe içermelidir",
},
{
ns: "Test.MinString",
expected: "MinString en az 1 karakter uzunluğunda olmalıdır",
},
{
ns: "Test.MinNumber",
expected: "MinNumber, 1.113,00 veya daha büyük olmalıdır",
},
{
ns: "Test.MinMultiple",
expected: "MinMultiple en az 7 öğe içermelidir",
},
{
ns: "Test.LenString",
expected: "LenString uzunluğu 1 karakter olmalıdır",
},
{
ns: "Test.LenNumber",
expected: "LenNumber, 1.113,00 değerine eşit olmalıdır",
},
{
ns: "Test.LenMultiple",
expected: "LenMultiple, 7 öğe içermelidir",
},
{
ns: "Test.RequiredString",
expected: "RequiredString zorunlu bir alandır",
},
{
ns: "Test.RequiredNumber",
expected: "RequiredNumber zorunlu bir alandır",
},
{
ns: "Test.RequiredMultiple",
expected: "RequiredMultiple zorunlu bir alandır",
},
{
ns: "Test.StrPtrMinLen",
expected: "StrPtrMinLen en az 10 karakter uzunluğunda olmalıdır",
},
{
ns: "Test.StrPtrMaxLen",
expected: "StrPtrMaxLen uzunluğu en fazla 1 karakter olmalıdır",
},
{
ns: "Test.StrPtrLen",
expected: "StrPtrLen uzunluğu 2 karakter olmalıdır",
},
{
ns: "Test.StrPtrLt",
expected: "StrPtrLt, 1 karakter uzunluğundan daha az olmalıdır",
},
{
ns: "Test.StrPtrLte",
expected: "StrPtrLte en fazla 1 karakter uzunluğunda olmalıdır",
},
{
ns: "Test.StrPtrGt",
expected: "StrPtrGt, 10 karakter uzunluğundan fazla olmalıdır",
},
{
ns: "Test.StrPtrGte",
expected: "StrPtrGte en az 10 karakter uzunluğunda olmalıdır",
},
{
ns: "Test.OneOfString",
expected: "OneOfString, [red green]'dan biri olmalıdır",
},
{
ns: "Test.OneOfInt",
expected: "OneOfInt, [5 63]'dan biri olmalıdır",
},
{
ns: "Test.UniqueSlice",
expected: "UniqueSlice benzersiz değerler içermelidir",
},
{
ns: "Test.UniqueArray",
expected: "UniqueArray benzersiz değerler içermelidir",
},
{
ns: "Test.UniqueMap",
expected: "UniqueMap benzersiz değerler içermelidir",
},
}
for _, tt := range tests {
var fe validator.FieldError
for _, e := range errs {
if tt.ns == e.Namespace() {
fe = e
break
}
}
NotEqual(t, fe, nil)
Equal(t, tt.expected, fe.Translate(trans))
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,690 @@
package vi
import (
"testing"
"time"
. "github.com/go-playground/assert/v2"
vietnamese "github.com/go-playground/locales/vi"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
)
func TestTranslations(t *testing.T) {
vie := vietnamese.New()
uni := ut.New(vie, vie)
trans, _ := uni.GetTranslator("vi")
validate := validator.New()
err := RegisterDefaultTranslations(validate, trans)
Equal(t, err, nil)
type Inner struct {
EqCSFieldString string
NeCSFieldString string
GtCSFieldString string
GteCSFieldString string
LtCSFieldString string
LteCSFieldString string
}
type Test struct {
Inner Inner
RequiredString string `validate:"required"`
RequiredNumber int `validate:"required"`
RequiredMultiple []string `validate:"required"`
LenString string `validate:"len=1"`
LenNumber float64 `validate:"len=1113.00"`
LenMultiple []string `validate:"len=7"`
MinString string `validate:"min=1"`
MinNumber float64 `validate:"min=1113.00"`
MinMultiple []string `validate:"min=7"`
MaxString string `validate:"max=3"`
MaxNumber float64 `validate:"max=1113.00"`
MaxMultiple []string `validate:"max=7"`
EqString string `validate:"eq=3"`
EqNumber float64 `validate:"eq=2.33"`
EqMultiple []string `validate:"eq=7"`
NeString string `validate:"ne="`
NeNumber float64 `validate:"ne=0.00"`
NeMultiple []string `validate:"ne=0"`
LtString string `validate:"lt=3"`
LtNumber float64 `validate:"lt=5.56"`
LtMultiple []string `validate:"lt=2"`
LtTime time.Time `validate:"lt"`
LteString string `validate:"lte=3"`
LteNumber float64 `validate:"lte=5.56"`
LteMultiple []string `validate:"lte=2"`
LteTime time.Time `validate:"lte"`
GtString string `validate:"gt=3"`
GtNumber float64 `validate:"gt=5.56"`
GtMultiple []string `validate:"gt=2"`
GtTime time.Time `validate:"gt"`
GteString string `validate:"gte=3"`
GteNumber float64 `validate:"gte=5.56"`
GteMultiple []string `validate:"gte=2"`
GteTime time.Time `validate:"gte"`
EqFieldString string `validate:"eqfield=MaxString"`
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"`
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"`
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"`
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"`
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"`
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"`
NeFieldString string `validate:"nefield=EqFieldString"`
GtFieldString string `validate:"gtfield=MaxString"`
GteFieldString string `validate:"gtefield=MaxString"`
LtFieldString string `validate:"ltfield=MaxString"`
LteFieldString string `validate:"ltefield=MaxString"`
AlphaString string `validate:"alpha"`
AlphanumString string `validate:"alphanum"`
NumericString string `validate:"numeric"`
NumberString string `validate:"number"`
HexadecimalString string `validate:"hexadecimal"`
HexColorString string `validate:"hexcolor"`
RGBColorString string `validate:"rgb"`
RGBAColorString string `validate:"rgba"`
HSLColorString string `validate:"hsl"`
HSLAColorString string `validate:"hsla"`
Email string `validate:"email"`
URL string `validate:"url"`
URI string `validate:"uri"`
Base64 string `validate:"base64"`
Contains string `validate:"contains=purpose"`
ContainsAny string `validate:"containsany=!@#$"`
Excludes string `validate:"excludes=text"`
ExcludesAll string `validate:"excludesall=!@#$"`
ExcludesRune string `validate:"excludesrune=☻"`
ISBN string `validate:"isbn"`
ISBN10 string `validate:"isbn10"`
ISBN13 string `validate:"isbn13"`
UUID string `validate:"uuid"`
UUID3 string `validate:"uuid3"`
UUID4 string `validate:"uuid4"`
UUID5 string `validate:"uuid5"`
ASCII string `validate:"ascii"`
PrintableASCII string `validate:"printascii"`
MultiByte string `validate:"multibyte"`
DataURI string `validate:"datauri"`
Latitude string `validate:"latitude"`
Longitude string `validate:"longitude"`
SSN string `validate:"ssn"`
IP string `validate:"ip"`
IPv4 string `validate:"ipv4"`
IPv6 string `validate:"ipv6"`
CIDR string `validate:"cidr"`
CIDRv4 string `validate:"cidrv4"`
CIDRv6 string `validate:"cidrv6"`
TCPAddr string `validate:"tcp_addr"`
TCPAddrv4 string `validate:"tcp4_addr"`
TCPAddrv6 string `validate:"tcp6_addr"`
UDPAddr string `validate:"udp_addr"`
UDPAddrv4 string `validate:"udp4_addr"`
UDPAddrv6 string `validate:"udp6_addr"`
IPAddr string `validate:"ip_addr"`
IPAddrv4 string `validate:"ip4_addr"`
IPAddrv6 string `validate:"ip6_addr"`
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"`
StrPtrMaxLen *string `validate:"max=1"`
StrPtrLen *string `validate:"len=2"`
StrPtrLt *string `validate:"lt=1"`
StrPtrLte *string `validate:"lte=1"`
StrPtrGt *string `validate:"gt=10"`
StrPtrGte *string `validate:"gte=10"`
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"`
JSONString string `validate:"json"`
JWTString string `validate:"jwt"`
LowercaseString string `validate:"lowercase"`
UppercaseString string `validate:"uppercase"`
Datetime string `validate:"datetime=2006-01-02"`
PostCode string `validate:"postcode_iso3166_alpha2=SG"`
PostCodeCountry string
PostCodeByField string `validate:"postcode_iso3166_alpha2_field=PostCodeCountry"`
}
var test Test
test.Inner.EqCSFieldString = "1234"
test.Inner.GtCSFieldString = "1234"
test.Inner.GteCSFieldString = "1234"
test.MaxString = "1234"
test.MaxNumber = 2000
test.MaxMultiple = make([]string, 9)
test.LtString = "1234"
test.LtNumber = 6
test.LtMultiple = make([]string, 3)
test.LtTime = time.Now().Add(time.Hour * 24)
test.LteString = "1234"
test.LteNumber = 6
test.LteMultiple = make([]string, 3)
test.LteTime = time.Now().Add(time.Hour * 24)
test.LtFieldString = "12345"
test.LteFieldString = "12345"
test.LtCSFieldString = "1234"
test.LteCSFieldString = "1234"
test.AlphaString = "abc3"
test.AlphanumString = "abc3!"
test.NumericString = "12E.00"
test.NumberString = "12E"
test.Excludes = "this is some test text"
test.ExcludesAll = "This is Great!"
test.ExcludesRune = "Love it ☻"
test.ASCII = "カタカナ"
test.PrintableASCII = "カタカナ"
test.MultiByte = "1234feerf"
test.LowercaseString = "ABCDEFG"
test.UppercaseString = "abcdefg"
s := "toolong"
test.StrPtrMaxLen = &s
test.StrPtrLen = &s
test.UniqueSlice = []string{"1234", "1234"}
test.UniqueMap = map[string]string{"key1": "1234", "key2": "1234"}
test.Datetime = "2008-Feb-01"
err = validate.Struct(test)
NotEqual(t, err, nil)
errs, ok := err.(validator.ValidationErrors)
Equal(t, ok, true)
tests := []struct {
ns string
expected string
}{
{
ns: "Test.IsColor",
expected: "IsColor phải là màu sắc hợp lệ",
},
{
ns: "Test.MAC",
expected: "MAC chỉ được chứa địa chỉ MAC",
},
{
ns: "Test.IPAddr",
expected: "IPAddr phải là địa chỉ IP có thể phân giải",
},
{
ns: "Test.IPAddrv4",
expected: "IPAddrv4 phải là địa chỉ IPv4 có thể phân giải",
},
{
ns: "Test.IPAddrv6",
expected: "IPAddrv6 phải là địa chỉ IPv6 có thể phân giải",
},
{
ns: "Test.UDPAddr",
expected: "UDPAddr phải là địa chỉ UDP",
},
{
ns: "Test.UDPAddrv4",
expected: "UDPAddrv4 phải là địa chỉ IPv4 UDP",
},
{
ns: "Test.UDPAddrv6",
expected: "UDPAddrv6 phải là địa chỉ IPv6 UDP",
},
{
ns: "Test.TCPAddr",
expected: "TCPAddr phải là địa chỉ TCP",
},
{
ns: "Test.TCPAddrv4",
expected: "TCPAddrv4 phải là địa chỉ IPv4 TCP",
},
{
ns: "Test.TCPAddrv6",
expected: "TCPAddrv6 phải là địa chỉ IPv6 TCP",
},
{
ns: "Test.CIDR",
expected: "CIDR chỉ được chứa CIDR notation",
},
{
ns: "Test.CIDRv4",
expected: "CIDRv4 chỉ được chứa CIDR notation của một địa chỉ IPv4",
},
{
ns: "Test.CIDRv6",
expected: "CIDRv6 chỉ được chứa CIDR notation của một địa chỉ IPv6",
},
{
ns: "Test.SSN",
expected: "SSN phải là SSN number",
},
{
ns: "Test.IP",
expected: "IP phải là địa chỉ IP",
},
{
ns: "Test.IPv4",
expected: "IPv4 phải là địa chỉ IPv4",
},
{
ns: "Test.IPv6",
expected: "IPv6 phải là địa chỉ IPv6",
},
{
ns: "Test.DataURI",
expected: "DataURI chỉ được chứa Data URI",
},
{
ns: "Test.Latitude",
expected: "Latitude chỉ được chứa latitude (vỹ độ)",
},
{
ns: "Test.Longitude",
expected: "Longitude chỉ được chứa longitude (kinh độ)",
},
{
ns: "Test.MultiByte",
expected: "MultiByte chỉ được chứa ký tự multibyte",
},
{
ns: "Test.ASCII",
expected: "ASCII chỉ được chứa ký tự ASCII",
},
{
ns: "Test.PrintableASCII",
expected: "PrintableASCII chỉ được chứa ký tự ASCII có thể in ấn",
},
{
ns: "Test.UUID",
expected: "UUID phải là giá trị UUID",
},
{
ns: "Test.UUID3",
expected: "UUID3 phải là giá trị UUID phiên bản 3",
},
{
ns: "Test.UUID4",
expected: "UUID4 phải là giá trị UUID phiên bản 4",
},
{
ns: "Test.UUID5",
expected: "UUID5 phải là giá trị UUID phiên bản 5",
},
{
ns: "Test.ISBN",
expected: "ISBN phải là số ISBN",
},
{
ns: "Test.ISBN10",
expected: "ISBN10 phải là số ISBN-10",
},
{
ns: "Test.ISBN13",
expected: "ISBN13 phải là số ISBN-13",
},
{
ns: "Test.Excludes",
expected: "Excludes không được chứa chuỗi 'text'",
},
{
ns: "Test.ExcludesAll",
expected: "ExcludesAll không được chứa bất kỳ ký tự nào trong nhóm ký tự '!@#$'",
},
{
ns: "Test.ExcludesRune",
expected: "ExcludesRune không được chứa '☻'",
},
{
ns: "Test.ContainsAny",
expected: "ContainsAny phải chứa ít nhất 1 trong cách ký tự sau '!@#$'",
},
{
ns: "Test.Contains",
expected: "Contains phải chứa chuỗi 'purpose'",
},
{
ns: "Test.Base64",
expected: "Base64 phải là giá trị chuỗi Base64",
},
{
ns: "Test.Email",
expected: "Email phải là giá trị email address",
},
{
ns: "Test.URL",
expected: "URL phải là giá trị URL",
},
{
ns: "Test.URI",
expected: "URI phải là giá trị URI",
},
{
ns: "Test.RGBColorString",
expected: "RGBColorString phải là giá trị RGB color",
},
{
ns: "Test.RGBAColorString",
expected: "RGBAColorString phải là giá trị RGBA color",
},
{
ns: "Test.HSLColorString",
expected: "HSLColorString phải là giá trị HSL color",
},
{
ns: "Test.HSLAColorString",
expected: "HSLAColorString phải là giá trị HSLA color",
},
{
ns: "Test.HexadecimalString",
expected: "HexadecimalString phải là giá trị hexadecimal",
},
{
ns: "Test.HexColorString",
expected: "HexColorString phải là giá trị HEX color",
},
{
ns: "Test.NumberString",
expected: "NumberString chỉ được chứa giá trị số",
},
{
ns: "Test.NumericString",
expected: "NumericString chỉ được chứa giá trị số hoặc số dưới dạng chữ",
},
{
ns: "Test.AlphanumString",
expected: "AlphanumString chỉ được chứa ký tự dạng alphanumeric",
},
{
ns: "Test.AlphaString",
expected: "AlphaString chỉ được chứa ký tự dạng alphabetic",
},
{
ns: "Test.LtFieldString",
expected: "LtFieldString chỉ được nhỏ hơn MaxString",
},
{
ns: "Test.LteFieldString",
expected: "LteFieldString chỉ được nhỏ hơn hoặc bằng MaxString",
},
{
ns: "Test.GtFieldString",
expected: "GtFieldString phải lớn hơn MaxString",
},
{
ns: "Test.GteFieldString",
expected: "GteFieldString phải lớn hơn hoặc bằng MaxString",
},
{
ns: "Test.NeFieldString",
expected: "NeFieldString không được phép bằng EqFieldString",
},
{
ns: "Test.LtCSFieldString",
expected: "LtCSFieldString chỉ được nhỏ hơn Inner.LtCSFieldString",
},
{
ns: "Test.LteCSFieldString",
expected: "LteCSFieldString chỉ được nhỏ hơn hoặc bằng Inner.LteCSFieldString",
},
{
ns: "Test.GtCSFieldString",
expected: "GtCSFieldString phải lớn hơn Inner.GtCSFieldString",
},
{
ns: "Test.GteCSFieldString",
expected: "GteCSFieldString phải lớn hơn hoặc bằng Inner.GteCSFieldString",
},
{
ns: "Test.NeCSFieldString",
expected: "NeCSFieldString không được phép bằng Inner.NeCSFieldString",
},
{
ns: "Test.EqCSFieldString",
expected: "EqCSFieldString phải bằng Inner.EqCSFieldString",
},
{
ns: "Test.EqFieldString",
expected: "EqFieldString phải bằng MaxString",
},
{
ns: "Test.GteString",
expected: "GteString phải có độ dài ít nhất 3 ký tự",
},
{
ns: "Test.GteNumber",
expected: "GteNumber phải là 5,56 hoặc lớn hơn",
},
{
ns: "Test.GteMultiple",
expected: "GteMultiple phải chứa ít nhất 2 phần tử",
},
{
ns: "Test.GteTime",
expected: "GteTime phải lớn hơn hoặc bằng Ngày & Giờ hiện tại",
},
{
ns: "Test.GtString",
expected: "GtString phải có độ dài lớn hơn 3 ký tự",
},
{
ns: "Test.GtNumber",
expected: "GtNumber phải lớn hơn 5,56",
},
{
ns: "Test.GtMultiple",
expected: "GtMultiple phải chứa nhiều hơn 2 phần tử",
},
{
ns: "Test.GtTime",
expected: "GtTime phải lớn hơn Ngày & Giờ hiện tại",
},
{
ns: "Test.LteString",
expected: "LteString chỉ được có độ dài tối đa là 3 ký tự",
},
{
ns: "Test.LteNumber",
expected: "LteNumber phải là 5,56 hoặc nhỏ hơn",
},
{
ns: "Test.LteMultiple",
expected: "LteMultiple chỉ được chứa nhiều nhất 2 phần tử",
},
{
ns: "Test.LteTime",
expected: "LteTime chỉ được nhỏ hơn hoặc bằng Ngày & Giờ hiện tại",
},
{
ns: "Test.LtString",
expected: "LtString phải có độ dài nhỏ hơn 3 ký tự",
},
{
ns: "Test.LtNumber",
expected: "LtNumber phải nhỏ hơn 5,56",
},
{
ns: "Test.LtMultiple",
expected: "LtMultiple chỉ được chứa ít hơn 2 phần tử",
},
{
ns: "Test.LtTime",
expected: "LtTime phải nhỏ hơn Ngày & Giờ hiện tại",
},
{
ns: "Test.NeString",
expected: "NeString không được bằng ",
},
{
ns: "Test.NeNumber",
expected: "NeNumber không được bằng 0.00",
},
{
ns: "Test.NeMultiple",
expected: "NeMultiple không được bằng 0",
},
{
ns: "Test.EqString",
expected: "EqString không bằng 3",
},
{
ns: "Test.EqNumber",
expected: "EqNumber không bằng 2.33",
},
{
ns: "Test.EqMultiple",
expected: "EqMultiple không bằng 7",
},
{
ns: "Test.MaxString",
expected: "MaxString chỉ được chứa tối đa 3 ký tự",
},
{
ns: "Test.MaxNumber",
expected: "MaxNumber phải là 1.113,00 hoặc nhỏ hơn",
},
{
ns: "Test.MaxMultiple",
expected: "MaxMultiple chỉ được chứa tối đa 7 phần tử",
},
{
ns: "Test.MinString",
expected: "MinString phải chứa ít nhất 1 ký tự",
},
{
ns: "Test.MinNumber",
expected: "MinNumber phải bằng 1.113,00 hoặc lớn hơn",
},
{
ns: "Test.MinMultiple",
expected: "MinMultiple phải chứa ít nhất 7 phần tử",
},
{
ns: "Test.LenString",
expected: "LenString phải có độ dài là 1 ký tự",
},
{
ns: "Test.LenNumber",
expected: "LenNumber phải bằng 1.113,00",
},
{
ns: "Test.LenMultiple",
expected: "LenMultiple phải chứa 7 phần tử",
},
{
ns: "Test.RequiredString",
expected: "RequiredString không được bỏ trống",
},
{
ns: "Test.RequiredNumber",
expected: "RequiredNumber không được bỏ trống",
},
{
ns: "Test.RequiredMultiple",
expected: "RequiredMultiple không được bỏ trống",
},
{
ns: "Test.StrPtrMinLen",
expected: "StrPtrMinLen phải chứa ít nhất 10 ký tự",
},
{
ns: "Test.StrPtrMaxLen",
expected: "StrPtrMaxLen chỉ được chứa tối đa 1 ký tự",
},
{
ns: "Test.StrPtrLen",
expected: "StrPtrLen phải có độ dài là 2 ký tự",
},
{
ns: "Test.StrPtrLt",
expected: "StrPtrLt phải có độ dài nhỏ hơn 1 ký tự",
},
{
ns: "Test.StrPtrLte",
expected: "StrPtrLte chỉ được có độ dài tối đa là 1 ký tự",
},
{
ns: "Test.StrPtrGt",
expected: "StrPtrGt phải có độ dài lớn hơn 10 ký tự",
},
{
ns: "Test.StrPtrGte",
expected: "StrPtrGte phải có độ dài ít nhất 10 ký tự",
},
{
ns: "Test.OneOfString",
expected: "OneOfString phải là trong những giá trị [red green]",
},
{
ns: "Test.OneOfInt",
expected: "OneOfInt phải là trong những giá trị [5 63]",
},
{
ns: "Test.UniqueSlice",
expected: "UniqueSlice chỉ được chứa những giá trị không trùng lặp",
},
{
ns: "Test.UniqueArray",
expected: "UniqueArray chỉ được chứa những giá trị không trùng lặp",
},
{
ns: "Test.UniqueMap",
expected: "UniqueMap chỉ được chứa những giá trị không trùng lặp",
},
{
ns: "Test.JSONString",
expected: "JSONString phải là một chuỗi json hợp lệ",
},
{
ns: "Test.JWTString",
expected: "JWTString phải là một chuỗi jwt hợp lệ",
},
{
ns: "Test.LowercaseString",
expected: "LowercaseString phải được viết thường",
},
{
ns: "Test.UppercaseString",
expected: "UppercaseString phải được viết hoa",
},
{
ns: "Test.Datetime",
expected: "Datetime không trùng định dạng ngày tháng 2006-01-02",
},
{
ns: "Test.PostCode",
expected: "PostCode sai định dạng postcode của quốc gia SG",
},
{
ns: "Test.PostCodeByField",
expected: "PostCodeByField sai định dạng postcode của quốc gia tương ứng thuộc trường PostCodeCountry",
},
}
for _, tt := range tests {
var fe validator.FieldError
for _, e := range errs {
if tt.ns == e.Namespace() {
fe = e
break
}
}
NotEqual(t, fe, nil)
Equal(t, tt.expected, fe.Translate(trans))
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,696 @@
package zh
import (
"testing"
"time"
. "github.com/go-playground/assert/v2"
zhongwen "github.com/go-playground/locales/zh"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
)
func TestTranslations(t *testing.T) {
zh := zhongwen.New()
uni := ut.New(zh, zh)
trans, _ := uni.GetTranslator("zh")
validate := validator.New()
err := RegisterDefaultTranslations(validate, trans)
Equal(t, err, nil)
type Inner struct {
EqCSFieldString string
NeCSFieldString string
GtCSFieldString string
GteCSFieldString string
LtCSFieldString string
LteCSFieldString string
}
type Test struct {
Inner Inner
RequiredString string `validate:"required"`
RequiredNumber int `validate:"required"`
RequiredMultiple []string `validate:"required"`
LenString string `validate:"len=1"`
LenNumber float64 `validate:"len=1113.00"`
LenMultiple []string `validate:"len=7"`
MinString string `validate:"min=1"`
MinNumber float64 `validate:"min=1113.00"`
MinMultiple []string `validate:"min=7"`
MaxString string `validate:"max=3"`
MaxNumber float64 `validate:"max=1113.00"`
MaxMultiple []string `validate:"max=7"`
EqString string `validate:"eq=3"`
EqNumber float64 `validate:"eq=2.33"`
EqMultiple []string `validate:"eq=7"`
NeString string `validate:"ne="`
NeNumber float64 `validate:"ne=0.00"`
NeMultiple []string `validate:"ne=0"`
LtString string `validate:"lt=3"`
LtNumber float64 `validate:"lt=5.56"`
LtMultiple []string `validate:"lt=2"`
LtTime time.Time `validate:"lt"`
LteString string `validate:"lte=3"`
LteNumber float64 `validate:"lte=5.56"`
LteMultiple []string `validate:"lte=2"`
LteTime time.Time `validate:"lte"`
GtString string `validate:"gt=3"`
GtNumber float64 `validate:"gt=5.56"`
GtMultiple []string `validate:"gt=2"`
GtTime time.Time `validate:"gt"`
GteString string `validate:"gte=3"`
GteNumber float64 `validate:"gte=5.56"`
GteMultiple []string `validate:"gte=2"`
GteTime time.Time `validate:"gte"`
EqFieldString string `validate:"eqfield=MaxString"`
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"`
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"`
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"`
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"`
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"`
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"`
NeFieldString string `validate:"nefield=EqFieldString"`
GtFieldString string `validate:"gtfield=MaxString"`
GteFieldString string `validate:"gtefield=MaxString"`
LtFieldString string `validate:"ltfield=MaxString"`
LteFieldString string `validate:"ltefield=MaxString"`
AlphaString string `validate:"alpha"`
AlphanumString string `validate:"alphanum"`
AlphanumUnicodeString string `validate:"alphanumunicode"`
AlphaUnicodeString string `validate:"alphaunicode"`
NumericString string `validate:"numeric"`
NumberString string `validate:"number"`
HexadecimalString string `validate:"hexadecimal"`
HexColorString string `validate:"hexcolor"`
RGBColorString string `validate:"rgb"`
RGBAColorString string `validate:"rgba"`
HSLColorString string `validate:"hsl"`
HSLAColorString string `validate:"hsla"`
Email string `validate:"email"`
URL string `validate:"url"`
URI string `validate:"uri"`
Base64 string `validate:"base64"`
Contains string `validate:"contains=purpose"`
ContainsAny string `validate:"containsany=!@#$"`
ContainsRune string `validate:"containsrune=☻"`
Excludes string `validate:"excludes=text"`
ExcludesAll string `validate:"excludesall=!@#$"`
ExcludesRune string `validate:"excludesrune=☻"`
EndsWith string `validate:"endswith=end"`
StartsWith string `validate:"startswith=start"`
ISBN string `validate:"isbn"`
ISBN10 string `validate:"isbn10"`
ISBN13 string `validate:"isbn13"`
UUID string `validate:"uuid"`
UUID3 string `validate:"uuid3"`
UUID4 string `validate:"uuid4"`
UUID5 string `validate:"uuid5"`
ULID string `validate:"ulid"`
ASCII string `validate:"ascii"`
PrintableASCII string `validate:"printascii"`
MultiByte string `validate:"multibyte"`
DataURI string `validate:"datauri"`
Latitude string `validate:"latitude"`
Longitude string `validate:"longitude"`
SSN string `validate:"ssn"`
IP string `validate:"ip"`
IPv4 string `validate:"ipv4"`
IPv6 string `validate:"ipv6"`
CIDR string `validate:"cidr"`
CIDRv4 string `validate:"cidrv4"`
CIDRv6 string `validate:"cidrv6"`
TCPAddr string `validate:"tcp_addr"`
TCPAddrv4 string `validate:"tcp4_addr"`
TCPAddrv6 string `validate:"tcp6_addr"`
UDPAddr string `validate:"udp_addr"`
UDPAddrv4 string `validate:"udp4_addr"`
UDPAddrv6 string `validate:"udp6_addr"`
IPAddr string `validate:"ip_addr"`
IPAddrv4 string `validate:"ip4_addr"`
IPAddrv6 string `validate:"ip6_addr"`
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"`
StrPtrMaxLen *string `validate:"max=1"`
StrPtrLen *string `validate:"len=2"`
StrPtrLt *string `validate:"lt=1"`
StrPtrLte *string `validate:"lte=1"`
StrPtrGt *string `validate:"gt=10"`
StrPtrGte *string `validate:"gte=10"`
OneOfString string `validate:"oneof=red green"`
OneOfInt int `validate:"oneof=5 63"`
JsonString string `validate:"json"`
LowercaseString string `validate:"lowercase"`
UppercaseString string `validate:"uppercase"`
Datetime string `validate:"datetime=2006-01-02"`
}
var test Test
test.Inner.EqCSFieldString = "1234"
test.Inner.GtCSFieldString = "1234"
test.Inner.GteCSFieldString = "1234"
test.MaxString = "1234"
test.MaxNumber = 2000
test.MaxMultiple = make([]string, 9)
test.LtString = "1234"
test.LtNumber = 6
test.LtMultiple = make([]string, 3)
test.LtTime = time.Now().Add(time.Hour * 24)
test.LteString = "1234"
test.LteNumber = 6
test.LteMultiple = make([]string, 3)
test.LteTime = time.Now().Add(time.Hour * 24)
test.LtFieldString = "12345"
test.LteFieldString = "12345"
test.LtCSFieldString = "1234"
test.LteCSFieldString = "1234"
test.AlphaString = "abc3"
test.AlphanumString = "abc3!"
test.AlphanumUnicodeString = "abc3啊!"
test.AlphaUnicodeString = "abc3啊"
test.NumericString = "12E.00"
test.NumberString = "12E"
test.Excludes = "this is some test text"
test.ExcludesAll = "This is Great!"
test.ExcludesRune = "Love it ☻"
test.EndsWith = "this is some test text"
test.StartsWith = "this is some test text"
test.ASCII = "カタカナ"
test.PrintableASCII = "カタカナ"
test.MultiByte = "1234feerf"
s := "toolong"
test.StrPtrMaxLen = &s
test.StrPtrLen = &s
test.JsonString = "{\"foo\":\"bar\",}"
test.LowercaseString = "ABCDEFG"
test.UppercaseString = "abcdefg"
test.Datetime = "20060102"
err = validate.Struct(test)
NotEqual(t, err, nil)
errs, ok := err.(validator.ValidationErrors)
Equal(t, ok, true)
tests := []struct {
ns string
expected string
}{
{
ns: "Test.IsColor",
expected: "IsColor必须是一个有效的颜色",
},
{
ns: "Test.MAC",
expected: "MAC必须是一个有效的MAC地址",
},
{
ns: "Test.IPAddr",
expected: "IPAddr必须是一个有效的IP地址",
},
{
ns: "Test.IPAddrv4",
expected: "IPAddrv4必须是一个有效的IPv4地址",
},
{
ns: "Test.IPAddrv6",
expected: "IPAddrv6必须是一个有效的IPv6地址",
},
{
ns: "Test.UDPAddr",
expected: "UDPAddr必须是一个有效的UDP地址",
},
{
ns: "Test.UDPAddrv4",
expected: "UDPAddrv4必须是一个有效的IPv4 UDP地址",
},
{
ns: "Test.UDPAddrv6",
expected: "UDPAddrv6必须是一个有效的IPv6 UDP地址",
},
{
ns: "Test.TCPAddr",
expected: "TCPAddr必须是一个有效的TCP地址",
},
{
ns: "Test.TCPAddrv4",
expected: "TCPAddrv4必须是一个有效的IPv4 TCP地址",
},
{
ns: "Test.TCPAddrv6",
expected: "TCPAddrv6必须是一个有效的IPv6 TCP地址",
},
{
ns: "Test.CIDR",
expected: "CIDR必须是一个有效的无类别域间路由(CIDR)",
},
{
ns: "Test.CIDRv4",
expected: "CIDRv4必须是一个包含IPv4地址的有效无类别域间路由(CIDR)",
},
{
ns: "Test.CIDRv6",
expected: "CIDRv6必须是一个包含IPv6地址的有效无类别域间路由(CIDR)",
},
{
ns: "Test.SSN",
expected: "SSN必须是一个有效的社会安全号码(SSN)",
},
{
ns: "Test.IP",
expected: "IP必须是一个有效的IP地址",
},
{
ns: "Test.IPv4",
expected: "IPv4必须是一个有效的IPv4地址",
},
{
ns: "Test.IPv6",
expected: "IPv6必须是一个有效的IPv6地址",
},
{
ns: "Test.DataURI",
expected: "DataURI必须包含有效的数据URI",
},
{
ns: "Test.Latitude",
expected: "Latitude必须包含有效的纬度坐标",
},
{
ns: "Test.Longitude",
expected: "Longitude必须包含有效的经度坐标",
},
{
ns: "Test.MultiByte",
expected: "MultiByte必须包含多字节字符",
},
{
ns: "Test.ASCII",
expected: "ASCII必须只包含ascii字符",
},
{
ns: "Test.PrintableASCII",
expected: "PrintableASCII必须只包含可打印的ascii字符",
},
{
ns: "Test.UUID",
expected: "UUID必须是一个有效的UUID",
},
{
ns: "Test.UUID3",
expected: "UUID3必须是一个有效的V3 UUID",
},
{
ns: "Test.UUID4",
expected: "UUID4必须是一个有效的V4 UUID",
},
{
ns: "Test.UUID5",
expected: "UUID5必须是一个有效的V5 UUID",
},
{
ns: "Test.ULID",
expected: "ULID必须是一个有效的ULID",
},
{
ns: "Test.ISBN",
expected: "ISBN必须是一个有效的ISBN编号",
},
{
ns: "Test.ISBN10",
expected: "ISBN10必须是一个有效的ISBN-10编号",
},
{
ns: "Test.ISBN13",
expected: "ISBN13必须是一个有效的ISBN-13编号",
},
{
ns: "Test.EndsWith",
expected: "EndsWith必须以文本'end'结尾",
},
{
ns: "Test.StartsWith",
expected: "StartsWith必须以文本'start'开头",
},
{
ns: "Test.Excludes",
expected: "Excludes不能包含文本'text'",
},
{
ns: "Test.ExcludesAll",
expected: "ExcludesAll不能包含以下任何字符'!@#$'",
},
{
ns: "Test.ExcludesRune",
expected: "ExcludesRune不能包含'☻'",
},
{
ns: "Test.ContainsRune",
expected: "ContainsRune必须包含字符'☻'",
},
{
ns: "Test.ContainsAny",
expected: "ContainsAny必须包含至少一个以下字符'!@#$'",
},
{
ns: "Test.Contains",
expected: "Contains必须包含文本'purpose'",
},
{
ns: "Test.Base64",
expected: "Base64必须是一个有效的Base64字符串",
},
{
ns: "Test.Email",
expected: "Email必须是一个有效的邮箱",
},
{
ns: "Test.URL",
expected: "URL必须是一个有效的URL",
},
{
ns: "Test.URI",
expected: "URI必须是一个有效的URI",
},
{
ns: "Test.RGBColorString",
expected: "RGBColorString必须是一个有效的RGB颜色",
},
{
ns: "Test.RGBAColorString",
expected: "RGBAColorString必须是一个有效的RGBA颜色",
},
{
ns: "Test.HSLColorString",
expected: "HSLColorString必须是一个有效的HSL颜色",
},
{
ns: "Test.HSLAColorString",
expected: "HSLAColorString必须是一个有效的HSLA颜色",
},
{
ns: "Test.HexadecimalString",
expected: "HexadecimalString必须是一个有效的十六进制",
},
{
ns: "Test.HexColorString",
expected: "HexColorString必须是一个有效的十六进制颜色",
},
{
ns: "Test.NumberString",
expected: "NumberString必须是一个有效的数字",
},
{
ns: "Test.NumericString",
expected: "NumericString必须是一个有效的数值",
},
{
ns: "Test.AlphaUnicodeString",
expected: "AlphaUnicodeString只能包含字母和Unicode字符",
},
{
ns: "Test.AlphanumUnicodeString",
expected: "AlphanumUnicodeString只能包含字母数字和Unicode字符",
},
{
ns: "Test.AlphanumString",
expected: "AlphanumString只能包含字母和数字",
},
{
ns: "Test.AlphaString",
expected: "AlphaString只能包含字母",
},
{
ns: "Test.LtFieldString",
expected: "LtFieldString必须小于MaxString",
},
{
ns: "Test.LteFieldString",
expected: "LteFieldString必须小于或等于MaxString",
},
{
ns: "Test.GtFieldString",
expected: "GtFieldString必须大于MaxString",
},
{
ns: "Test.GteFieldString",
expected: "GteFieldString必须大于或等于MaxString",
},
{
ns: "Test.NeFieldString",
expected: "NeFieldString不能等于EqFieldString",
},
{
ns: "Test.LtCSFieldString",
expected: "LtCSFieldString必须小于Inner.LtCSFieldString",
},
{
ns: "Test.LteCSFieldString",
expected: "LteCSFieldString必须小于或等于Inner.LteCSFieldString",
},
{
ns: "Test.GtCSFieldString",
expected: "GtCSFieldString必须大于Inner.GtCSFieldString",
},
{
ns: "Test.GteCSFieldString",
expected: "GteCSFieldString必须大于或等于Inner.GteCSFieldString",
},
{
ns: "Test.NeCSFieldString",
expected: "NeCSFieldString不能等于Inner.NeCSFieldString",
},
{
ns: "Test.EqCSFieldString",
expected: "EqCSFieldString必须等于Inner.EqCSFieldString",
},
{
ns: "Test.EqFieldString",
expected: "EqFieldString必须等于MaxString",
},
{
ns: "Test.GteString",
expected: "GteString长度必须至少为3个字符",
},
{
ns: "Test.GteNumber",
expected: "GteNumber必须大于或等于5.56",
},
{
ns: "Test.GteMultiple",
expected: "GteMultiple必须至少包含2项",
},
{
ns: "Test.GteTime",
expected: "GteTime必须大于或等于当前日期和时间",
},
{
ns: "Test.GtString",
expected: "GtString长度必须大于3个字符",
},
{
ns: "Test.GtNumber",
expected: "GtNumber必须大于5.56",
},
{
ns: "Test.GtMultiple",
expected: "GtMultiple必须大于2项",
},
{
ns: "Test.GtTime",
expected: "GtTime必须大于当前日期和时间",
},
{
ns: "Test.LteString",
expected: "LteString长度不能超过3个字符",
},
{
ns: "Test.LteNumber",
expected: "LteNumber必须小于或等于5.56",
},
{
ns: "Test.LteMultiple",
expected: "LteMultiple最多只能包含2项",
},
{
ns: "Test.LteTime",
expected: "LteTime必须小于或等于当前日期和时间",
},
{
ns: "Test.LtString",
expected: "LtString长度必须小于3个字符",
},
{
ns: "Test.LtNumber",
expected: "LtNumber必须小于5.56",
},
{
ns: "Test.LtMultiple",
expected: "LtMultiple必须包含少于2项",
},
{
ns: "Test.LtTime",
expected: "LtTime必须小于当前日期和时间",
},
{
ns: "Test.NeString",
expected: "NeString不能等于",
},
{
ns: "Test.NeNumber",
expected: "NeNumber不能等于0.00",
},
{
ns: "Test.NeMultiple",
expected: "NeMultiple不能等于0",
},
{
ns: "Test.EqString",
expected: "EqString不等于3",
},
{
ns: "Test.EqNumber",
expected: "EqNumber不等于2.33",
},
{
ns: "Test.EqMultiple",
expected: "EqMultiple不等于7",
},
{
ns: "Test.MaxString",
expected: "MaxString长度不能超过3个字符",
},
{
ns: "Test.MaxNumber",
expected: "MaxNumber必须小于或等于1,113.00",
},
{
ns: "Test.MaxMultiple",
expected: "MaxMultiple最多只能包含7项",
},
{
ns: "Test.MinString",
expected: "MinString长度必须至少为1个字符",
},
{
ns: "Test.MinNumber",
expected: "MinNumber最小只能为1,113.00",
},
{
ns: "Test.MinMultiple",
expected: "MinMultiple必须至少包含7项",
},
{
ns: "Test.LenString",
expected: "LenString长度必须是1个字符",
},
{
ns: "Test.LenNumber",
expected: "LenNumber必须等于1,113.00",
},
{
ns: "Test.LenMultiple",
expected: "LenMultiple必须包含7项",
},
{
ns: "Test.RequiredString",
expected: "RequiredString为必填字段",
},
{
ns: "Test.RequiredNumber",
expected: "RequiredNumber为必填字段",
},
{
ns: "Test.RequiredMultiple",
expected: "RequiredMultiple为必填字段",
},
{
ns: "Test.StrPtrMinLen",
expected: "StrPtrMinLen长度必须至少为10个字符",
},
{
ns: "Test.StrPtrMaxLen",
expected: "StrPtrMaxLen长度不能超过1个字符",
},
{
ns: "Test.StrPtrLen",
expected: "StrPtrLen长度必须是2个字符",
},
{
ns: "Test.StrPtrLt",
expected: "StrPtrLt长度必须小于1个字符",
},
{
ns: "Test.StrPtrLte",
expected: "StrPtrLte长度不能超过1个字符",
},
{
ns: "Test.StrPtrGt",
expected: "StrPtrGt长度必须大于10个字符",
},
{
ns: "Test.StrPtrGte",
expected: "StrPtrGte长度必须至少为10个字符",
},
{
ns: "Test.OneOfString",
expected: "OneOfString必须是[red green]中的一个",
},
{
ns: "Test.OneOfInt",
expected: "OneOfInt必须是[5 63]中的一个",
},
{
ns: "Test.JsonString",
expected: "JsonString必须是一个JSON字符串",
},
{
ns: "Test.LowercaseString",
expected: "LowercaseString必须是小写字母",
},
{
ns: "Test.UppercaseString",
expected: "UppercaseString必须是大写字母",
},
{
ns: "Test.Datetime",
expected: "Datetime的格式必须是2006-01-02",
},
}
for _, tt := range tests {
var fe validator.FieldError
for _, e := range errs {
if tt.ns == e.Namespace() {
fe = e
break
}
}
NotEqual(t, fe, nil)
Equal(t, tt.expected, fe.Translate(trans))
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,646 @@
package zh_tw
import (
"testing"
"time"
. "github.com/go-playground/assert/v2"
zhongwen "github.com/go-playground/locales/zh_Hant_TW"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
)
func TestTranslations(t *testing.T) {
zh := zhongwen.New()
uni := ut.New(zh, zh)
trans, _ := uni.GetTranslator("zh")
validate := validator.New()
err := RegisterDefaultTranslations(validate, trans)
Equal(t, err, nil)
type Inner struct {
EqCSFieldString string
NeCSFieldString string
GtCSFieldString string
GteCSFieldString string
LtCSFieldString string
LteCSFieldString string
}
type Test struct {
Inner Inner
RequiredString string `validate:"required"`
RequiredNumber int `validate:"required"`
RequiredMultiple []string `validate:"required"`
LenString string `validate:"len=1"`
LenNumber float64 `validate:"len=1113.00"`
LenMultiple []string `validate:"len=7"`
MinString string `validate:"min=1"`
MinNumber float64 `validate:"min=1113.00"`
MinMultiple []string `validate:"min=7"`
MaxString string `validate:"max=3"`
MaxNumber float64 `validate:"max=1113.00"`
MaxMultiple []string `validate:"max=7"`
EqString string `validate:"eq=3"`
EqNumber float64 `validate:"eq=2.33"`
EqMultiple []string `validate:"eq=7"`
NeString string `validate:"ne="`
NeNumber float64 `validate:"ne=0.00"`
NeMultiple []string `validate:"ne=0"`
LtString string `validate:"lt=3"`
LtNumber float64 `validate:"lt=5.56"`
LtMultiple []string `validate:"lt=2"`
LtTime time.Time `validate:"lt"`
LteString string `validate:"lte=3"`
LteNumber float64 `validate:"lte=5.56"`
LteMultiple []string `validate:"lte=2"`
LteTime time.Time `validate:"lte"`
GtString string `validate:"gt=3"`
GtNumber float64 `validate:"gt=5.56"`
GtMultiple []string `validate:"gt=2"`
GtTime time.Time `validate:"gt"`
GteString string `validate:"gte=3"`
GteNumber float64 `validate:"gte=5.56"`
GteMultiple []string `validate:"gte=2"`
GteTime time.Time `validate:"gte"`
EqFieldString string `validate:"eqfield=MaxString"`
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"`
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"`
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"`
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"`
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"`
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"`
NeFieldString string `validate:"nefield=EqFieldString"`
GtFieldString string `validate:"gtfield=MaxString"`
GteFieldString string `validate:"gtefield=MaxString"`
LtFieldString string `validate:"ltfield=MaxString"`
LteFieldString string `validate:"ltefield=MaxString"`
AlphaString string `validate:"alpha"`
AlphanumString string `validate:"alphanum"`
NumericString string `validate:"numeric"`
NumberString string `validate:"number"`
HexadecimalString string `validate:"hexadecimal"`
HexColorString string `validate:"hexcolor"`
RGBColorString string `validate:"rgb"`
RGBAColorString string `validate:"rgba"`
HSLColorString string `validate:"hsl"`
HSLAColorString string `validate:"hsla"`
Email string `validate:"email"`
URL string `validate:"url"`
URI string `validate:"uri"`
Base64 string `validate:"base64"`
Contains string `validate:"contains=purpose"`
ContainsAny string `validate:"containsany=!@#$"`
Excludes string `validate:"excludes=text"`
ExcludesAll string `validate:"excludesall=!@#$"`
ExcludesRune string `validate:"excludesrune=☻"`
ISBN string `validate:"isbn"`
ISBN10 string `validate:"isbn10"`
ISBN13 string `validate:"isbn13"`
UUID string `validate:"uuid"`
UUID3 string `validate:"uuid3"`
UUID4 string `validate:"uuid4"`
UUID5 string `validate:"uuid5"`
ULID string `validate:"ulid"`
ASCII string `validate:"ascii"`
PrintableASCII string `validate:"printascii"`
MultiByte string `validate:"multibyte"`
DataURI string `validate:"datauri"`
Latitude string `validate:"latitude"`
Longitude string `validate:"longitude"`
SSN string `validate:"ssn"`
IP string `validate:"ip"`
IPv4 string `validate:"ipv4"`
IPv6 string `validate:"ipv6"`
CIDR string `validate:"cidr"`
CIDRv4 string `validate:"cidrv4"`
CIDRv6 string `validate:"cidrv6"`
TCPAddr string `validate:"tcp_addr"`
TCPAddrv4 string `validate:"tcp4_addr"`
TCPAddrv6 string `validate:"tcp6_addr"`
UDPAddr string `validate:"udp_addr"`
UDPAddrv4 string `validate:"udp4_addr"`
UDPAddrv6 string `validate:"udp6_addr"`
IPAddr string `validate:"ip_addr"`
IPAddrv4 string `validate:"ip4_addr"`
IPAddrv6 string `validate:"ip6_addr"`
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"`
StrPtrMaxLen *string `validate:"max=1"`
StrPtrLen *string `validate:"len=2"`
StrPtrLt *string `validate:"lt=1"`
StrPtrLte *string `validate:"lte=1"`
StrPtrGt *string `validate:"gt=10"`
StrPtrGte *string `validate:"gte=10"`
OneOfString string `validate:"oneof=red green"`
OneOfInt int `validate:"oneof=5 63"`
Datetime string `validate:"datetime=2006-01-02"`
}
var test Test
test.Inner.EqCSFieldString = "1234"
test.Inner.GtCSFieldString = "1234"
test.Inner.GteCSFieldString = "1234"
test.MaxString = "1234"
test.MaxNumber = 2000
test.MaxMultiple = make([]string, 9)
test.LtString = "1234"
test.LtNumber = 6
test.LtMultiple = make([]string, 3)
test.LtTime = time.Now().Add(time.Hour * 24)
test.LteString = "1234"
test.LteNumber = 6
test.LteMultiple = make([]string, 3)
test.LteTime = time.Now().Add(time.Hour * 24)
test.LtFieldString = "12345"
test.LteFieldString = "12345"
test.LtCSFieldString = "1234"
test.LteCSFieldString = "1234"
test.AlphaString = "abc3"
test.AlphanumString = "abc3!"
test.NumericString = "12E.00"
test.NumberString = "12E"
test.Excludes = "this is some test text"
test.ExcludesAll = "This is Great!"
test.ExcludesRune = "Love it ☻"
test.ASCII = "カタカナ"
test.PrintableASCII = "カタカナ"
test.MultiByte = "1234feerf"
s := "toolong"
test.StrPtrMaxLen = &s
test.StrPtrLen = &s
test.Datetime = "2008-Feb-01"
err = validate.Struct(test)
NotEqual(t, err, nil)
errs, ok := err.(validator.ValidationErrors)
Equal(t, ok, true)
tests := []struct {
ns string
expected string
}{
{
ns: "Test.IsColor",
expected: "IsColor必須是一個有效的顏色",
},
{
ns: "Test.MAC",
expected: "MAC必須是一個有效的MAC地址",
},
{
ns: "Test.IPAddr",
expected: "IPAddr必須是一個有效的IP地址",
},
{
ns: "Test.IPAddrv4",
expected: "IPAddrv4必須是一個有效的IPv4地址",
},
{
ns: "Test.IPAddrv6",
expected: "IPAddrv6必須是一個有效的IPv6地址",
},
{
ns: "Test.UDPAddr",
expected: "UDPAddr必須是一個有效的UDP地址",
},
{
ns: "Test.UDPAddrv4",
expected: "UDPAddrv4必須是一個有效的IPv4 UDP地址",
},
{
ns: "Test.UDPAddrv6",
expected: "UDPAddrv6必須是一個有效的IPv6 UDP地址",
},
{
ns: "Test.TCPAddr",
expected: "TCPAddr必須是一個有效的TCP地址",
},
{
ns: "Test.TCPAddrv4",
expected: "TCPAddrv4必須是一個有效的IPv4 TCP地址",
},
{
ns: "Test.TCPAddrv6",
expected: "TCPAddrv6必須是一個有效的IPv6 TCP地址",
},
{
ns: "Test.CIDR",
expected: "CIDR必須是一個有效的無類別域間路由(CIDR)",
},
{
ns: "Test.CIDRv4",
expected: "CIDRv4必須是一个包含IPv4地址的有效無類別域間路由(CIDR)",
},
{
ns: "Test.CIDRv6",
expected: "CIDRv6必須是一个包含IPv6地址的有效無類別域間路由(CIDR)",
},
{
ns: "Test.SSN",
expected: "SSN必須是一個有效的社會安全編號(SSN)",
},
{
ns: "Test.IP",
expected: "IP必須是一個有效的IP地址",
},
{
ns: "Test.IPv4",
expected: "IPv4必須是一個有效的IPv4地址",
},
{
ns: "Test.IPv6",
expected: "IPv6必須是一個有效的IPv6地址",
},
{
ns: "Test.DataURI",
expected: "DataURI必須包含有效的數據URI",
},
{
ns: "Test.Latitude",
expected: "Latitude必須包含有效的緯度座標",
},
{
ns: "Test.Longitude",
expected: "Longitude必須包含有效的經度座標",
},
{
ns: "Test.MultiByte",
expected: "MultiByte必須包含多個字元",
},
{
ns: "Test.ASCII",
expected: "ASCII必須只包含ascii字元",
},
{
ns: "Test.PrintableASCII",
expected: "PrintableASCII必須只包含可輸出的ascii字元",
},
{
ns: "Test.UUID",
expected: "UUID必須是一個有效的UUID",
},
{
ns: "Test.UUID3",
expected: "UUID3必須是一個有效的V3 UUID",
},
{
ns: "Test.UUID4",
expected: "UUID4必須是一個有效的V4 UUID",
},
{
ns: "Test.UUID5",
expected: "UUID5必須是一個有效的V5 UUID",
},
{
ns: "Test.ULID",
expected: "ULID必須是一個有效的ULID",
},
{
ns: "Test.ISBN",
expected: "ISBN必須是一個有效的ISBN編號",
},
{
ns: "Test.ISBN10",
expected: "ISBN10必須是一個有效的ISBN-10編號",
},
{
ns: "Test.ISBN13",
expected: "ISBN13必須是一個有效的ISBN-13編號",
},
{
ns: "Test.Excludes",
expected: "Excludes不能包含文字'text'",
},
{
ns: "Test.ExcludesAll",
expected: "ExcludesAll不能包含以下任何字元'!@#$'",
},
{
ns: "Test.ExcludesRune",
expected: "ExcludesRune不能包含'☻'",
},
{
ns: "Test.ContainsAny",
expected: "ContainsAny必須包含至少一個以下字元'!@#$'",
},
{
ns: "Test.Contains",
expected: "Contains必須包含文字'purpose'",
},
{
ns: "Test.Base64",
expected: "Base64必須是一個有效的Base64字元串",
},
{
ns: "Test.Email",
expected: "Email必須是一個有效的信箱",
},
{
ns: "Test.URL",
expected: "URL必須是一個有效的URL",
},
{
ns: "Test.URI",
expected: "URI必須是一個有效的URI",
},
{
ns: "Test.RGBColorString",
expected: "RGBColorString必須是一個有效的RGB顏色",
},
{
ns: "Test.RGBAColorString",
expected: "RGBAColorString必須是一個有效的RGBA顏色",
},
{
ns: "Test.HSLColorString",
expected: "HSLColorString必須是一個有效的HSL顏色",
},
{
ns: "Test.HSLAColorString",
expected: "HSLAColorString必須是一個有效的HSLA顏色",
},
{
ns: "Test.HexadecimalString",
expected: "HexadecimalString必須是一個有效的十六進制",
},
{
ns: "Test.HexColorString",
expected: "HexColorString必須是一個有效的十六進制顏色",
},
{
ns: "Test.NumberString",
expected: "NumberString必須是一個有效的數字",
},
{
ns: "Test.NumericString",
expected: "NumericString必須是一個有效的數值",
},
{
ns: "Test.AlphanumString",
expected: "AlphanumString只能包含字母和數字",
},
{
ns: "Test.AlphaString",
expected: "AlphaString只能包含字母",
},
{
ns: "Test.LtFieldString",
expected: "LtFieldString必須小於MaxString",
},
{
ns: "Test.LteFieldString",
expected: "LteFieldString必須小於或等於MaxString",
},
{
ns: "Test.GtFieldString",
expected: "GtFieldString必須大於MaxString",
},
{
ns: "Test.GteFieldString",
expected: "GteFieldString必須大於或等於MaxString",
},
{
ns: "Test.NeFieldString",
expected: "NeFieldString不能等於EqFieldString",
},
{
ns: "Test.LtCSFieldString",
expected: "LtCSFieldString必須小於Inner.LtCSFieldString",
},
{
ns: "Test.LteCSFieldString",
expected: "LteCSFieldString必須小於或等於Inner.LteCSFieldString",
},
{
ns: "Test.GtCSFieldString",
expected: "GtCSFieldString必須大於Inner.GtCSFieldString",
},
{
ns: "Test.GteCSFieldString",
expected: "GteCSFieldString必須大於或等於Inner.GteCSFieldString",
},
{
ns: "Test.NeCSFieldString",
expected: "NeCSFieldString不能等於Inner.NeCSFieldString",
},
{
ns: "Test.EqCSFieldString",
expected: "EqCSFieldString必須等於Inner.EqCSFieldString",
},
{
ns: "Test.EqFieldString",
expected: "EqFieldString必須等於MaxString",
},
{
ns: "Test.GteString",
expected: "GteString長度必須至少為3個字元",
},
{
ns: "Test.GteNumber",
expected: "GteNumber必須大於或等於5.56",
},
{
ns: "Test.GteMultiple",
expected: "GteMultiple必須至少包含2項",
},
{
ns: "Test.GteTime",
expected: "GteTime必須大於或等於目前日期和時間",
},
{
ns: "Test.GtString",
expected: "GtString長度必須大於3個字元",
},
{
ns: "Test.GtNumber",
expected: "GtNumber必須大於5.56",
},
{
ns: "Test.GtMultiple",
expected: "GtMultiple必須大於2項",
},
{
ns: "Test.GtTime",
expected: "GtTime必須大於目前日期和時間",
},
{
ns: "Test.LteString",
expected: "LteString長度不能超過3個字元",
},
{
ns: "Test.LteNumber",
expected: "LteNumber必須小於或等於5.56",
},
{
ns: "Test.LteMultiple",
expected: "LteMultiple最多只能包含2項",
},
{
ns: "Test.LteTime",
expected: "LteTime必須小於或等於目前日期和時間",
},
{
ns: "Test.LtString",
expected: "LtString長度必須小於3個字元",
},
{
ns: "Test.LtNumber",
expected: "LtNumber必須小於5.56",
},
{
ns: "Test.LtMultiple",
expected: "LtMultiple必須包含少於2項",
},
{
ns: "Test.LtTime",
expected: "LtTime必須小於目前日期和時間",
},
{
ns: "Test.NeString",
expected: "NeString不能等於",
},
{
ns: "Test.NeNumber",
expected: "NeNumber不能等於0.00",
},
{
ns: "Test.NeMultiple",
expected: "NeMultiple不能等於0",
},
{
ns: "Test.EqString",
expected: "EqString不等於3",
},
{
ns: "Test.EqNumber",
expected: "EqNumber不等於2.33",
},
{
ns: "Test.EqMultiple",
expected: "EqMultiple不等於7",
},
{
ns: "Test.MaxString",
expected: "MaxString長度不能超過3個字元",
},
{
ns: "Test.MaxNumber",
expected: "MaxNumber必須小於或等於1,113.00",
},
{
ns: "Test.MaxMultiple",
expected: "MaxMultiple最多只能包含7項",
},
{
ns: "Test.MinString",
expected: "MinString長度必須至少為1個字元",
},
{
ns: "Test.MinNumber",
expected: "MinNumber最小只能為1,113.00",
},
{
ns: "Test.MinMultiple",
expected: "MinMultiple必須至少包含7項",
},
{
ns: "Test.LenString",
expected: "LenString長度必須為1個字元",
},
{
ns: "Test.LenNumber",
expected: "LenNumber必須等於1,113.00",
},
{
ns: "Test.LenMultiple",
expected: "LenMultiple必須包含7項",
},
{
ns: "Test.RequiredString",
expected: "RequiredString為必填欄位",
},
{
ns: "Test.RequiredNumber",
expected: "RequiredNumber為必填欄位",
},
{
ns: "Test.RequiredMultiple",
expected: "RequiredMultiple為必填欄位",
},
{
ns: "Test.StrPtrMinLen",
expected: "StrPtrMinLen長度必須至少為10個字元",
},
{
ns: "Test.StrPtrMaxLen",
expected: "StrPtrMaxLen長度不能超過1個字元",
},
{
ns: "Test.StrPtrLen",
expected: "StrPtrLen長度必須為2個字元",
},
{
ns: "Test.StrPtrLt",
expected: "StrPtrLt長度必須小於1個字元",
},
{
ns: "Test.StrPtrLte",
expected: "StrPtrLte長度不能超過1個字元",
},
{
ns: "Test.StrPtrGt",
expected: "StrPtrGt長度必須大於10個字元",
},
{
ns: "Test.StrPtrGte",
expected: "StrPtrGte長度必須至少為10個字元",
},
{
ns: "Test.OneOfString",
expected: "OneOfString必須是[red green]中的一個",
},
{
ns: "Test.OneOfInt",
expected: "OneOfInt必須是[5 63]中的一個",
},
{
ns: "Test.Datetime",
expected: "Datetime與2006-01-02格式不匹配",
},
}
for _, tt := range tests {
var fe validator.FieldError
for _, e := range errs {
if tt.ns == e.Namespace() {
fe = e
break
}
}
NotEqual(t, fe, nil)
Equal(t, tt.expected, fe.Translate(trans))
}
}

@ -0,0 +1,288 @@
package validator
import (
"reflect"
"strconv"
"strings"
"time"
)
// extractTypeInternal gets the actual underlying type of field value.
// It will dive into pointers, customTypes and return you the
// underlying value and it's kind.
func (v *validate) extractTypeInternal(current reflect.Value, nullable bool) (reflect.Value, reflect.Kind, bool) {
BEGIN:
switch current.Kind() {
case reflect.Ptr:
nullable = true
if current.IsNil() {
return current, reflect.Ptr, nullable
}
current = current.Elem()
goto BEGIN
case reflect.Interface:
nullable = true
if current.IsNil() {
return current, reflect.Interface, nullable
}
current = current.Elem()
goto BEGIN
case reflect.Invalid:
return current, reflect.Invalid, nullable
default:
if v.v.hasCustomFuncs {
if fn, ok := v.v.customFuncs[current.Type()]; ok {
current = reflect.ValueOf(fn(current))
goto BEGIN
}
}
return current, current.Kind(), nullable
}
}
// getStructFieldOKInternal traverses a struct to retrieve a specific field denoted by the provided namespace and
// returns the field, field kind and whether is was successful in retrieving the field at all.
//
// NOTE: when not successful ok will be false, this can happen when a nested struct is nil and so the field
// could not be retrieved because it didn't exist.
func (v *validate) getStructFieldOKInternal(val reflect.Value, namespace string) (current reflect.Value, kind reflect.Kind, nullable bool, found bool) {
BEGIN:
current, kind, nullable = v.ExtractType(val)
if kind == reflect.Invalid {
return
}
if namespace == "" {
found = true
return
}
switch kind {
case reflect.Ptr, reflect.Interface:
return
case reflect.Struct:
typ := current.Type()
fld := namespace
var ns string
if !typ.ConvertibleTo(timeType) {
idx := strings.Index(namespace, namespaceSeparator)
if idx != -1 {
fld = namespace[:idx]
ns = namespace[idx+1:]
} else {
ns = ""
}
bracketIdx := strings.Index(fld, leftBracket)
if bracketIdx != -1 {
fld = fld[:bracketIdx]
ns = namespace[bracketIdx:]
}
val = current.FieldByName(fld)
namespace = ns
goto BEGIN
}
case reflect.Array, reflect.Slice:
idx := strings.Index(namespace, leftBracket)
idx2 := strings.Index(namespace, rightBracket)
arrIdx, _ := strconv.Atoi(namespace[idx+1 : idx2])
if arrIdx >= current.Len() {
return
}
startIdx := idx2 + 1
if startIdx < len(namespace) {
if namespace[startIdx:startIdx+1] == namespaceSeparator {
startIdx++
}
}
val = current.Index(arrIdx)
namespace = namespace[startIdx:]
goto BEGIN
case reflect.Map:
idx := strings.Index(namespace, leftBracket) + 1
idx2 := strings.Index(namespace, rightBracket)
endIdx := idx2
if endIdx+1 < len(namespace) {
if namespace[endIdx+1:endIdx+2] == namespaceSeparator {
endIdx++
}
}
key := namespace[idx:idx2]
switch current.Type().Key().Kind() {
case reflect.Int:
i, _ := strconv.Atoi(key)
val = current.MapIndex(reflect.ValueOf(i))
namespace = namespace[endIdx+1:]
case reflect.Int8:
i, _ := strconv.ParseInt(key, 10, 8)
val = current.MapIndex(reflect.ValueOf(int8(i)))
namespace = namespace[endIdx+1:]
case reflect.Int16:
i, _ := strconv.ParseInt(key, 10, 16)
val = current.MapIndex(reflect.ValueOf(int16(i)))
namespace = namespace[endIdx+1:]
case reflect.Int32:
i, _ := strconv.ParseInt(key, 10, 32)
val = current.MapIndex(reflect.ValueOf(int32(i)))
namespace = namespace[endIdx+1:]
case reflect.Int64:
i, _ := strconv.ParseInt(key, 10, 64)
val = current.MapIndex(reflect.ValueOf(i))
namespace = namespace[endIdx+1:]
case reflect.Uint:
i, _ := strconv.ParseUint(key, 10, 0)
val = current.MapIndex(reflect.ValueOf(uint(i)))
namespace = namespace[endIdx+1:]
case reflect.Uint8:
i, _ := strconv.ParseUint(key, 10, 8)
val = current.MapIndex(reflect.ValueOf(uint8(i)))
namespace = namespace[endIdx+1:]
case reflect.Uint16:
i, _ := strconv.ParseUint(key, 10, 16)
val = current.MapIndex(reflect.ValueOf(uint16(i)))
namespace = namespace[endIdx+1:]
case reflect.Uint32:
i, _ := strconv.ParseUint(key, 10, 32)
val = current.MapIndex(reflect.ValueOf(uint32(i)))
namespace = namespace[endIdx+1:]
case reflect.Uint64:
i, _ := strconv.ParseUint(key, 10, 64)
val = current.MapIndex(reflect.ValueOf(i))
namespace = namespace[endIdx+1:]
case reflect.Float32:
f, _ := strconv.ParseFloat(key, 32)
val = current.MapIndex(reflect.ValueOf(float32(f)))
namespace = namespace[endIdx+1:]
case reflect.Float64:
f, _ := strconv.ParseFloat(key, 64)
val = current.MapIndex(reflect.ValueOf(f))
namespace = namespace[endIdx+1:]
case reflect.Bool:
b, _ := strconv.ParseBool(key)
val = current.MapIndex(reflect.ValueOf(b))
namespace = namespace[endIdx+1:]
// reflect.Type = string
default:
val = current.MapIndex(reflect.ValueOf(key))
namespace = namespace[endIdx+1:]
}
goto BEGIN
}
// if got here there was more namespace, cannot go any deeper
panic("Invalid field namespace")
}
// asInt returns the parameter as a int64
// or panics if it can't convert
func asInt(param string) int64 {
i, err := strconv.ParseInt(param, 0, 64)
panicIf(err)
return i
}
// asIntFromTimeDuration parses param as time.Duration and returns it as int64
// or panics on error.
func asIntFromTimeDuration(param string) int64 {
d, err := time.ParseDuration(param)
if err != nil {
// attempt parsing as an an integer assuming nanosecond precision
return asInt(param)
}
return int64(d)
}
// asIntFromType calls the proper function to parse param as int64,
// given a field's Type t.
func asIntFromType(t reflect.Type, param string) int64 {
switch t {
case timeDurationType:
return asIntFromTimeDuration(param)
default:
return asInt(param)
}
}
// asUint returns the parameter as a uint64
// or panics if it can't convert
func asUint(param string) uint64 {
i, err := strconv.ParseUint(param, 0, 64)
panicIf(err)
return i
}
// asFloat returns the parameter as a float64
// or panics if it can't convert
func asFloat(param string) float64 {
i, err := strconv.ParseFloat(param, 64)
panicIf(err)
return i
}
// asBool returns the parameter as a bool
// or panics if it can't convert
func asBool(param string) bool {
i, err := strconv.ParseBool(param)
panicIf(err)
return i
}
func panicIf(err error) {
if err != nil {
panic(err.Error())
}
}

@ -1,375 +1,485 @@
/**
* Package validator
*
* MISC:
* - anonymous structs - they don't have names so expect the Struct name within StructValidationErrors to be blank
*
*/
package validator
import (
"bytes"
"errors"
"context"
"fmt"
"reflect"
"strings"
"time"
"unicode"
)
const (
tagSeparator = ","
orSeparator = "|"
noValidationTag = "-"
tagKeySeparator = "="
structOnlyTag = "structonly"
omitempty = "omitempty"
validationFieldErrMsg = "Field validation for \"%s\" failed on the \"%s\" tag\n"
validationStructErrMsg = "Struct:%s\n"
"strconv"
)
// FieldValidationError contains a single field's validation error along
// with other properties that may be needed for error message creation
type FieldValidationError struct {
Field string
ErrorTag string
Kind reflect.Kind
Type reflect.Type
Param string
Value interface{}
// per validate construct
type validate struct {
v *Validate
top reflect.Value
ns []byte
actualNs []byte
errs ValidationErrors
includeExclude map[string]struct{} // reset only if StructPartial or StructExcept are called, no need otherwise
ffn FilterFunc
slflParent reflect.Value // StructLevel & FieldLevel
slCurrent reflect.Value // StructLevel & FieldLevel
flField reflect.Value // StructLevel & FieldLevel
cf *cField // StructLevel & FieldLevel
ct *cTag // StructLevel & FieldLevel
misc []byte // misc reusable
str1 string // misc reusable
str2 string // misc reusable
fldIsPointer bool // StructLevel & FieldLevel
isPartial bool
hasExcludes bool
}
// This is intended for use in development + debugging and not intended to be a production error message.
// it also allows FieldValidationError to be used as an Error interface
func (e *FieldValidationError) Error() string {
return fmt.Sprintf(validationFieldErrMsg, e.Field, e.ErrorTag)
}
// parent and current will be the same the first run of validateStruct
func (v *validate) validateStruct(ctx context.Context, parent reflect.Value, current reflect.Value, typ reflect.Type, ns []byte, structNs []byte, ct *cTag) {
// StructValidationErrors is hierarchical list of field and struct validation errors
// for a non hierarchical representation please see the Flatten method for StructValidationErrors
type StructValidationErrors struct {
// Name of the Struct
Struct string
// Struct Field Errors
Errors map[string]*FieldValidationError
// Struct Fields of type struct and their errors
// key = Field Name of current struct, but internally Struct will be the actual struct name unless anonymous struct, it will be blank
StructErrors map[string]*StructValidationErrors
}
cs, ok := v.v.structCache.Get(typ)
if !ok {
cs = v.v.extractStructCache(current, typ.Name())
}
// This is intended for use in development + debugging and not intended to be a production error message.
// it also allows StructValidationErrors to be used as an Error interface
func (e *StructValidationErrors) Error() string {
buff := bytes.NewBufferString(fmt.Sprintf(validationStructErrMsg, e.Struct))
if len(ns) == 0 && len(cs.name) != 0 {
for _, err := range e.Errors {
buff.WriteString(err.Error())
}
ns = append(ns, cs.name...)
ns = append(ns, '.')
for _, err := range e.StructErrors {
buff.WriteString(err.Error())
structNs = append(structNs, cs.name...)
structNs = append(structNs, '.')
}
buff.WriteString("\n\n")
return buff.String()
}
// Flatten flattens the StructValidationErrors hierarchical structure into a flat namespace style field name
// for those that want/need it
func (e *StructValidationErrors) Flatten() map[string]*FieldValidationError {
// ct is nil on top level struct, and structs as fields that have no tag info
// so if nil or if not nil and the structonly tag isn't present
if ct == nil || ct.typeof != typeStructOnly {
if e == nil {
return nil
}
var f *cField
errs := map[string]*FieldValidationError{}
for i := 0; i < len(cs.fields); i++ {
for _, f := range e.Errors {
f = cs.fields[i]
errs[f.Field] = f
}
if v.isPartial {
for key, val := range e.StructErrors {
if v.ffn != nil {
// used with StructFiltered
if v.ffn(append(structNs, f.name...)) {
continue
}
otherErrs := val.Flatten()
} else {
// used with StructPartial & StructExcept
_, ok = v.includeExclude[string(append(structNs, f.name...))]
for _, f2 := range otherErrs {
if (ok && v.hasExcludes) || (!ok && !v.hasExcludes) {
continue
}
}
}
f2.Field = fmt.Sprintf("%s.%s", key, f2.Field)
errs[f2.Field] = f2
v.traverseField(ctx, current, current.Field(f.idx), ns, structNs, f, f.cTags)
}
}
return errs
}
// check if any struct level validations, after all field validations already checked.
// first iteration will have no info about nostructlevel tag, and is checked prior to
// calling the next iteration of validateStruct called from traverseField.
if cs.fn != nil {
// ValidationFunc accepts all values needed for file and cross field validation
// top = top level struct when validating by struct otherwise nil
// current = current level struct when validating by struct otherwise optional comparison value
// f = field value for validation
// param = parameter used in validation i.e. gt=0 param would be 0
type ValidationFunc func(top interface{}, current interface{}, f interface{}, param string) bool
// Validator implements the Validator Struct
// NOTE: Fields within are not thread safe and that is on purpose
// Functions and Tags should all be predifined before use, so subscribe to the philosiphy
// or make it thread safe on your end
type Validator struct {
// tagName being used.
tagName string
// validationFuncs is a map of validation functions and the tag keys
validationFuncs map[string]ValidationFunc
}
v.slflParent = parent
v.slCurrent = current
v.ns = ns
v.actualNs = structNs
// NewValidator creates a new Validator instance for use.
func NewValidator(tagName string, funcs map[string]ValidationFunc) *Validator {
return &Validator{
tagName: tagName,
validationFuncs: funcs,
cs.fn(ctx, v)
}
}
// SetTag sets tagName of the Validator to one of your choosing after creation
// perhaps to dodge a tag name conflict in a specific section of code
func (v *Validator) SetTag(tagName string) {
v.tagName = tagName
}
// traverseField validates any field, be it a struct or single field, ensures it's validity and passes it along to be validated via it's tag options
func (v *validate) traverseField(ctx context.Context, parent reflect.Value, current reflect.Value, ns []byte, structNs []byte, cf *cField, ct *cTag) {
var typ reflect.Type
var kind reflect.Kind
// AddFunction adds a ValidationFunc to a Validator's map of validators denoted by the key
// NOTE: if the key already exists, it will get replaced.
func (v *Validator) AddFunction(key string, f ValidationFunc) error {
current, kind, v.fldIsPointer = v.extractTypeInternal(current, false)
if len(key) == 0 {
return errors.New("Function Key cannot be empty")
}
switch kind {
case reflect.Ptr, reflect.Interface, reflect.Invalid:
if f == nil {
return errors.New("Function cannot be empty")
}
if ct == nil {
return
}
v.validationFuncs[key] = f
if ct.typeof == typeOmitEmpty || ct.typeof == typeIsDefault {
return
}
return nil
}
if ct.hasTag {
if kind == reflect.Invalid {
v.str1 = string(append(ns, cf.altName...))
if v.v.hasTagNameFunc {
v.str2 = string(append(structNs, cf.name...))
} else {
v.str2 = v.str1
}
v.errs = append(v.errs,
&fieldError{
v: v.v,
tag: ct.aliasTag,
actualTag: ct.tag,
ns: v.str1,
structNs: v.str2,
fieldLen: uint8(len(cf.altName)),
structfieldLen: uint8(len(cf.name)),
param: ct.param,
kind: kind,
},
)
return
}
// ValidateStruct validates a struct, even it's nested structs, and returns a struct containing the errors
// NOTE: Nested Arrays, or Maps of structs do not get validated only the Array or Map itself; the reason is that there is no good
// way to represent or report which struct within the array has the error, besides can validate the struct prior to adding it to
// the Array or Map.
func (v *Validator) ValidateStruct(s interface{}) *StructValidationErrors {
v.str1 = string(append(ns, cf.altName...))
if v.v.hasTagNameFunc {
v.str2 = string(append(structNs, cf.name...))
} else {
v.str2 = v.str1
}
if !ct.runValidationWhenNil {
v.errs = append(v.errs,
&fieldError{
v: v.v,
tag: ct.aliasTag,
actualTag: ct.tag,
ns: v.str1,
structNs: v.str2,
fieldLen: uint8(len(cf.altName)),
structfieldLen: uint8(len(cf.name)),
value: current.Interface(),
param: ct.param,
kind: kind,
typ: current.Type(),
},
)
return
}
}
return v.validateStructRecursive(s, s, s)
}
case reflect.Struct:
typ = current.Type()
if !typ.ConvertibleTo(timeType) {
if ct != nil {
if ct.typeof == typeStructOnly {
goto CONTINUE
} else if ct.typeof == typeIsDefault {
// set Field Level fields
v.slflParent = parent
v.flField = current
v.cf = cf
v.ct = ct
if !ct.fn(ctx, v) {
v.str1 = string(append(ns, cf.altName...))
if v.v.hasTagNameFunc {
v.str2 = string(append(structNs, cf.name...))
} else {
v.str2 = v.str1
}
v.errs = append(v.errs,
&fieldError{
v: v.v,
tag: ct.aliasTag,
actualTag: ct.tag,
ns: v.str1,
structNs: v.str2,
fieldLen: uint8(len(cf.altName)),
structfieldLen: uint8(len(cf.name)),
value: current.Interface(),
param: ct.param,
kind: kind,
typ: typ,
},
)
return
}
}
// validateStructRecursive validates a struct recursivly and passes the top level and current struct around for use in validator functions and returns a struct containing the errors
func (v *Validator) validateStructRecursive(top interface{}, current interface{}, s interface{}) *StructValidationErrors {
ct = ct.next
}
structValue := reflect.ValueOf(s)
structType := reflect.TypeOf(s)
structName := structType.Name()
if ct != nil && ct.typeof == typeNoStructLevel {
return
}
if structValue.Kind() == reflect.Ptr && !structValue.IsNil() {
return v.validateStructRecursive(top, current, structValue.Elem().Interface())
}
CONTINUE:
// if len == 0 then validating using 'Var' or 'VarWithValue'
// Var - doesn't make much sense to do it that way, should call 'Struct', but no harm...
// VarWithField - this allows for validating against each field within the struct against a specific value
// pretty handy in certain situations
if len(cf.name) > 0 {
ns = append(append(ns, cf.altName...), '.')
structNs = append(append(structNs, cf.name...), '.')
}
if structValue.Kind() != reflect.Struct && structValue.Kind() != reflect.Interface {
panic("interface passed for validation is not a struct")
v.validateStruct(ctx, parent, current, typ, ns, structNs, ct)
return
}
}
validationErrors := &StructValidationErrors{
Struct: structName,
Errors: map[string]*FieldValidationError{},
StructErrors: map[string]*StructValidationErrors{},
if ct == nil || !ct.hasTag {
return
}
var numFields = structValue.NumField()
for i := 0; i < numFields; i++ {
valueField := structValue.Field(i)
typeField := structType.Field(i)
typ = current.Type()
if valueField.Kind() == reflect.Ptr && !valueField.IsNil() {
valueField = valueField.Elem()
OUTER:
for {
if ct == nil {
return
}
tag := typeField.Tag.Get(v.tagName)
switch ct.typeof {
if tag == noValidationTag {
continue
}
case typeOmitEmpty:
// if no validation and not a struct (which may containt fields for validation)
if tag == "" && valueField.Kind() != reflect.Struct && valueField.Kind() != reflect.Interface {
continue
}
switch valueField.Kind() {
case reflect.Struct, reflect.Interface:
// set Field Level fields
v.slflParent = parent
v.flField = current
v.cf = cf
v.ct = ct
if !unicode.IsUpper(rune(typeField.Name[0])) {
continue
if !hasValue(v) {
return
}
if valueField.Type() == reflect.TypeOf(time.Time{}) {
if fieldError := v.validateFieldByNameAndTagAndValue(top, current, valueField.Interface(), typeField.Name, tag); fieldError != nil {
validationErrors.Errors[fieldError.Field] = fieldError
// free up memory reference
fieldError = nil
}
} else {
if strings.Contains(tag, structOnlyTag) {
continue
}
if structErrors := v.validateStructRecursive(top, valueField.Interface(), valueField.Interface()); structErrors != nil {
validationErrors.StructErrors[typeField.Name] = structErrors
// free up memory map no longer needed
structErrors = nil
}
}
ct = ct.next
continue
default:
case typeEndKeys:
return
if fieldError := v.validateFieldByNameAndTagAndValue(top, current, valueField.Interface(), typeField.Name, tag); fieldError != nil {
validationErrors.Errors[fieldError.Field] = fieldError
// free up memory reference
fieldError = nil
}
}
}
case typeDive:
if len(validationErrors.Errors) == 0 && len(validationErrors.StructErrors) == 0 {
return nil
}
ct = ct.next
return validationErrors
}
// traverse slice or map here
// or panic ;)
switch kind {
case reflect.Slice, reflect.Array:
// ValidateFieldByTag allows validation of a single field, still using tag style validation to check multiple errors
func (v *Validator) ValidateFieldByTag(f interface{}, tag string) *FieldValidationError {
var i64 int64
reusableCF := &cField{}
return v.ValidateFieldByTagAndValue(nil, f, tag)
}
for i := 0; i < current.Len(); i++ {
// ValidateFieldByTagAndValue allows validation of a single field, possibly even against another fields value, still using tag style validation to check multiple errors
func (v *Validator) ValidateFieldByTagAndValue(val interface{}, f interface{}, tag string) *FieldValidationError {
i64 = int64(i)
return v.validateFieldByNameAndTagAndValue(nil, val, f, "", tag)
}
v.misc = append(v.misc[0:0], cf.name...)
v.misc = append(v.misc, '[')
v.misc = strconv.AppendInt(v.misc, i64, 10)
v.misc = append(v.misc, ']')
func (v *Validator) validateFieldByNameAndTagAndValue(val interface{}, current interface{}, f interface{}, name string, tag string) *FieldValidationError {
reusableCF.name = string(v.misc)
// This is a double check if coming from ValidateStruct but need to be here in case function is called directly
if tag == noValidationTag {
return nil
}
if cf.namesEqual {
reusableCF.altName = reusableCF.name
} else {
if strings.Contains(tag, omitempty) && !hasValue(val, current, f, "") {
return nil
}
v.misc = append(v.misc[0:0], cf.altName...)
v.misc = append(v.misc, '[')
v.misc = strconv.AppendInt(v.misc, i64, 10)
v.misc = append(v.misc, ']')
valueField := reflect.ValueOf(f)
fieldKind := valueField.Kind()
reusableCF.altName = string(v.misc)
}
v.traverseField(ctx, parent, current.Index(i), ns, structNs, reusableCF, ct)
}
if fieldKind == reflect.Ptr && !valueField.IsNil() {
return v.validateFieldByNameAndTagAndValue(val, current, valueField.Elem().Interface(), name, tag)
}
case reflect.Map:
fieldType := valueField.Type()
var pv string
reusableCF := &cField{}
switch fieldKind {
for _, key := range current.MapKeys() {
case reflect.Struct, reflect.Interface, reflect.Invalid:
pv = fmt.Sprintf("%v", key.Interface())
if fieldType != reflect.TypeOf(time.Time{}) {
panic("Invalid field passed to ValidateFieldWithTag")
}
}
v.misc = append(v.misc[0:0], cf.name...)
v.misc = append(v.misc, '[')
v.misc = append(v.misc, pv...)
v.misc = append(v.misc, ']')
var valErr *FieldValidationError
var err error
valTags := strings.Split(tag, tagSeparator)
reusableCF.name = string(v.misc)
for _, valTag := range valTags {
if cf.namesEqual {
reusableCF.altName = reusableCF.name
} else {
v.misc = append(v.misc[0:0], cf.altName...)
v.misc = append(v.misc, '[')
v.misc = append(v.misc, pv...)
v.misc = append(v.misc, ']')
orVals := strings.Split(valTag, orSeparator)
reusableCF.altName = string(v.misc)
}
if len(orVals) > 1 {
if ct != nil && ct.typeof == typeKeys && ct.keys != nil {
v.traverseField(ctx, parent, key, ns, structNs, reusableCF, ct.keys)
// can be nil when just keys being validated
if ct.next != nil {
v.traverseField(ctx, parent, current.MapIndex(key), ns, structNs, reusableCF, ct.next)
}
} else {
v.traverseField(ctx, parent, current.MapIndex(key), ns, structNs, reusableCF, ct)
}
}
errTag := ""
default:
// throw error, if not a slice or map then should not have gotten here
// bad dive tag
panic("dive error! can't dive on a non slice or map")
}
for _, val := range orVals {
return
valErr, err = v.validateFieldByNameAndSingleTag(val, current, f, name, val)
case typeOr:
if err == nil {
return nil
}
v.misc = v.misc[0:0]
errTag += orSeparator + valErr.ErrorTag
for {
}
// set Field Level fields
v.slflParent = parent
v.flField = current
v.cf = cf
v.ct = ct
errTag = strings.TrimLeft(errTag, orSeparator)
if ct.fn(ctx, v) {
if ct.isBlockEnd {
ct = ct.next
continue OUTER
}
valErr.ErrorTag = errTag
valErr.Kind = fieldKind
// drain rest of the 'or' values, then continue or leave
for {
return valErr
}
ct = ct.next
if valErr, err = v.validateFieldByNameAndSingleTag(val, current, f, name, valTag); err != nil {
if ct == nil {
return
}
valErr.Kind = valueField.Kind()
valErr.Type = fieldType
if ct.typeof != typeOr {
continue OUTER
}
return valErr
}
}
if ct.isBlockEnd {
ct = ct.next
continue OUTER
}
}
}
return nil
}
v.misc = append(v.misc, '|')
v.misc = append(v.misc, ct.tag...)
func (v *Validator) validateFieldByNameAndSingleTag(val interface{}, current interface{}, f interface{}, name string, valTag string) (*FieldValidationError, error) {
if ct.hasParam {
v.misc = append(v.misc, '=')
v.misc = append(v.misc, ct.param...)
}
vals := strings.Split(valTag, tagKeySeparator)
key := strings.Trim(vals[0], " ")
if ct.isBlockEnd || ct.next == nil {
// if we get here, no valid 'or' value and no more tags
v.str1 = string(append(ns, cf.altName...))
if v.v.hasTagNameFunc {
v.str2 = string(append(structNs, cf.name...))
} else {
v.str2 = v.str1
}
if ct.hasAlias {
v.errs = append(v.errs,
&fieldError{
v: v.v,
tag: ct.aliasTag,
actualTag: ct.actualAliasTag,
ns: v.str1,
structNs: v.str2,
fieldLen: uint8(len(cf.altName)),
structfieldLen: uint8(len(cf.name)),
value: current.Interface(),
param: ct.param,
kind: kind,
typ: typ,
},
)
} else {
tVal := string(v.misc)[1:]
v.errs = append(v.errs,
&fieldError{
v: v.v,
tag: tVal,
actualTag: tVal,
ns: v.str1,
structNs: v.str2,
fieldLen: uint8(len(cf.altName)),
structfieldLen: uint8(len(cf.name)),
value: current.Interface(),
param: ct.param,
kind: kind,
typ: typ,
},
)
}
return
}
if len(key) == 0 {
panic(fmt.Sprintf("Invalid validation tag on field %s", name))
}
ct = ct.next
}
valErr := &FieldValidationError{
Field: name,
ErrorTag: key,
Value: f,
Param: "",
}
default:
// OK to continue because we checked it's existance before getting into this loop
if key == omitempty {
return valErr, nil
}
// set Field Level fields
v.slflParent = parent
v.flField = current
v.cf = cf
v.ct = ct
valFunc, ok := v.validationFuncs[key]
if !ok {
panic(fmt.Sprintf("Undefined validation function on field %s", name))
}
if !ct.fn(ctx, v) {
v.str1 = string(append(ns, cf.altName...))
param := ""
if len(vals) > 1 {
param = strings.Trim(vals[1], " ")
}
if v.v.hasTagNameFunc {
v.str2 = string(append(structNs, cf.name...))
} else {
v.str2 = v.str1
}
if err := valFunc(val, current, f, param); !err {
valErr.Param = param
return valErr, errors.New(key)
v.errs = append(v.errs,
&fieldError{
v: v.v,
tag: ct.aliasTag,
actualTag: ct.tag,
ns: v.str1,
structNs: v.str2,
fieldLen: uint8(len(cf.altName)),
structfieldLen: uint8(len(cf.name)),
value: current.Interface(),
param: ct.param,
kind: kind,
typ: typ,
},
)
return
}
ct = ct.next
}
}
return valErr, nil
}

@ -0,0 +1,700 @@
package validator
import (
"context"
"errors"
"fmt"
"reflect"
"strings"
"sync"
"time"
ut "github.com/go-playground/universal-translator"
)
const (
defaultTagName = "validate"
utf8HexComma = "0x2C"
utf8Pipe = "0x7C"
tagSeparator = ","
orSeparator = "|"
tagKeySeparator = "="
structOnlyTag = "structonly"
noStructLevelTag = "nostructlevel"
omitempty = "omitempty"
isdefault = "isdefault"
requiredWithoutAllTag = "required_without_all"
requiredWithoutTag = "required_without"
requiredWithTag = "required_with"
requiredWithAllTag = "required_with_all"
requiredIfTag = "required_if"
requiredUnlessTag = "required_unless"
excludedWithoutAllTag = "excluded_without_all"
excludedWithoutTag = "excluded_without"
excludedWithTag = "excluded_with"
excludedWithAllTag = "excluded_with_all"
excludedIfTag = "excluded_if"
excludedUnlessTag = "excluded_unless"
skipValidationTag = "-"
diveTag = "dive"
keysTag = "keys"
endKeysTag = "endkeys"
requiredTag = "required"
namespaceSeparator = "."
leftBracket = "["
rightBracket = "]"
restrictedTagChars = ".[],|=+()`~!@#$%^&*\\\"/?<>{}"
restrictedAliasErr = "Alias '%s' either contains restricted characters or is the same as a restricted tag needed for normal operation"
restrictedTagErr = "Tag '%s' either contains restricted characters or is the same as a restricted tag needed for normal operation"
)
var (
timeDurationType = reflect.TypeOf(time.Duration(0))
timeType = reflect.TypeOf(time.Time{})
defaultCField = &cField{namesEqual: true}
)
// FilterFunc is the type used to filter fields using
// StructFiltered(...) function.
// returning true results in the field being filtered/skiped from
// validation
type FilterFunc func(ns []byte) bool
// CustomTypeFunc allows for overriding or adding custom field type handler functions
// field = field value of the type to return a value to be validated
// example Valuer from sql drive see https://golang.org/src/database/sql/driver/types.go?s=1210:1293#L29
type CustomTypeFunc func(field reflect.Value) interface{}
// TagNameFunc allows for adding of a custom tag name parser
type TagNameFunc func(field reflect.StructField) string
type internalValidationFuncWrapper struct {
fn FuncCtx
runValidatinOnNil bool
}
// Validate contains the validator settings and cache
type Validate struct {
tagName string
pool *sync.Pool
hasCustomFuncs bool
hasTagNameFunc bool
tagNameFunc TagNameFunc
structLevelFuncs map[reflect.Type]StructLevelFuncCtx
customFuncs map[reflect.Type]CustomTypeFunc
aliases map[string]string
validations map[string]internalValidationFuncWrapper
transTagFunc map[ut.Translator]map[string]TranslationFunc // map[<locale>]map[<tag>]TranslationFunc
rules map[reflect.Type]map[string]string
tagCache *tagCache
structCache *structCache
}
// 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 {
tc := new(tagCache)
tc.m.Store(make(map[string]*cTag))
sc := new(structCache)
sc.m.Store(make(map[reflect.Type]*cStruct))
v := &Validate{
tagName: defaultTagName,
aliases: make(map[string]string, len(bakedInAliases)),
validations: make(map[string]internalValidationFuncWrapper, len(bakedInValidators)),
tagCache: tc,
structCache: sc,
}
// must copy alias validators for separate validations to be used in each validator instance
for k, val := range bakedInAliases {
v.RegisterAlias(k, val)
}
// must copy validators for separate validations to be used in each instance
for k, val := range bakedInValidators {
switch k {
// these require that even if the value is nil that the validation should run, omitempty still overrides this behaviour
case requiredIfTag, requiredUnlessTag, requiredWithTag, requiredWithAllTag, requiredWithoutTag, requiredWithoutAllTag,
excludedIfTag, excludedUnlessTag, excludedWithTag, excludedWithAllTag, excludedWithoutTag, excludedWithoutAllTag:
_ = v.registerValidation(k, wrapFunc(val), true, true)
default:
// no need to error check here, baked in will always be valid
_ = v.registerValidation(k, wrapFunc(val), true, false)
}
}
v.pool = &sync.Pool{
New: func() interface{} {
return &validate{
v: v,
ns: make([]byte, 0, 64),
actualNs: make([]byte, 0, 64),
misc: make([]byte, 32),
}
},
}
return v
}
// SetTagName allows for changing of the default tag name of 'validate'
func (v *Validate) SetTagName(name string) {
v.tagName = name
}
// ValidateMapCtx validates a map using a map of validation rules and allows passing of contextual
// validation validation information via context.Context.
func (v Validate) ValidateMapCtx(ctx context.Context, data map[string]interface{}, rules map[string]interface{}) map[string]interface{} {
errs := make(map[string]interface{})
for field, rule := range rules {
if ruleObj, ok := rule.(map[string]interface{}); ok {
if dataObj, ok := data[field].(map[string]interface{}); ok {
err := v.ValidateMapCtx(ctx, dataObj, ruleObj)
if len(err) > 0 {
errs[field] = err
}
} else if dataObjs, ok := data[field].([]map[string]interface{}); ok {
for _, obj := range dataObjs {
err := v.ValidateMapCtx(ctx, obj, ruleObj)
if len(err) > 0 {
errs[field] = err
}
}
} else {
errs[field] = errors.New("The field: '" + field + "' is not a map to dive")
}
} else if ruleStr, ok := rule.(string); ok {
err := v.VarCtx(ctx, data[field], ruleStr)
if err != nil {
errs[field] = err
}
}
}
return errs
}
// ValidateMap validates map data from a map of tags
func (v *Validate) ValidateMap(data map[string]interface{}, rules map[string]interface{}) map[string]interface{} {
return v.ValidateMapCtx(context.Background(), data, rules)
}
// RegisterTagNameFunc registers a function to get alternate names for StructFields.
//
// eg. to use the names which have been specified for JSON representations of structs, rather than normal Go field names:
//
// validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
// name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
// // skip if tag key says it should be ignored
// if name == "-" {
// return ""
// }
// return name
// })
func (v *Validate) RegisterTagNameFunc(fn TagNameFunc) {
v.tagNameFunc = fn
v.hasTagNameFunc = true
}
// RegisterValidation adds a validation with the given tag
//
// NOTES:
// - if the key already exists, the previous validation function will be replaced.
// - this method is not thread-safe it is intended that these all be registered prior to any validation
func (v *Validate) RegisterValidation(tag string, fn Func, callValidationEvenIfNull ...bool) error {
return v.RegisterValidationCtx(tag, wrapFunc(fn), callValidationEvenIfNull...)
}
// RegisterValidationCtx does the same as RegisterValidation on accepts a FuncCtx validation
// allowing context.Context validation support.
func (v *Validate) RegisterValidationCtx(tag string, fn FuncCtx, callValidationEvenIfNull ...bool) error {
var nilCheckable bool
if len(callValidationEvenIfNull) > 0 {
nilCheckable = callValidationEvenIfNull[0]
}
return v.registerValidation(tag, fn, false, nilCheckable)
}
func (v *Validate) registerValidation(tag string, fn FuncCtx, bakedIn bool, nilCheckable bool) error {
if len(tag) == 0 {
return errors.New("function Key cannot be empty")
}
if fn == nil {
return errors.New("function cannot be empty")
}
_, ok := restrictedTags[tag]
if !bakedIn && (ok || strings.ContainsAny(tag, restrictedTagChars)) {
panic(fmt.Sprintf(restrictedTagErr, tag))
}
v.validations[tag] = internalValidationFuncWrapper{fn: fn, runValidatinOnNil: nilCheckable}
return nil
}
// RegisterAlias registers a mapping of a single validation tag that
// defines a common or complex set of validation(s) to simplify adding validation
// to structs.
//
// NOTE: this function is not thread-safe it is intended that these all be registered prior to any validation
func (v *Validate) RegisterAlias(alias, tags string) {
_, ok := restrictedTags[alias]
if ok || strings.ContainsAny(alias, restrictedTagChars) {
panic(fmt.Sprintf(restrictedAliasErr, alias))
}
v.aliases[alias] = tags
}
// RegisterStructValidation registers a StructLevelFunc against a number of types.
//
// NOTE:
// - this method is not thread-safe it is intended that these all be registered prior to any validation
func (v *Validate) RegisterStructValidation(fn StructLevelFunc, types ...interface{}) {
v.RegisterStructValidationCtx(wrapStructLevelFunc(fn), types...)
}
// RegisterStructValidationCtx registers a StructLevelFuncCtx against a number of types and allows passing
// of contextual validation information via context.Context.
//
// NOTE:
// - this method is not thread-safe it is intended that these all be registered prior to any validation
func (v *Validate) RegisterStructValidationCtx(fn StructLevelFuncCtx, types ...interface{}) {
if v.structLevelFuncs == nil {
v.structLevelFuncs = make(map[reflect.Type]StructLevelFuncCtx)
}
for _, t := range types {
tv := reflect.ValueOf(t)
if tv.Kind() == reflect.Ptr {
t = reflect.Indirect(tv).Interface()
}
v.structLevelFuncs[reflect.TypeOf(t)] = fn
}
}
// RegisterStructValidationMapRules registers validate map rules.
// Be aware that map validation rules supersede those defined on a/the struct if present.
//
// NOTE: this method is not thread-safe it is intended that these all be registered prior to any validation
func (v *Validate) RegisterStructValidationMapRules(rules map[string]string, types ...interface{}) {
if v.rules == nil {
v.rules = make(map[reflect.Type]map[string]string)
}
deepCopyRules := make(map[string]string)
for i, rule := range rules {
deepCopyRules[i] = rule
}
for _, t := range types {
typ := reflect.TypeOf(t)
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
}
if typ.Kind() != reflect.Struct {
continue
}
v.rules[typ] = deepCopyRules
}
}
// RegisterCustomTypeFunc registers a CustomTypeFunc against a number of types
//
// NOTE: this method is not thread-safe it is intended that these all be registered prior to any validation
func (v *Validate) RegisterCustomTypeFunc(fn CustomTypeFunc, types ...interface{}) {
if v.customFuncs == nil {
v.customFuncs = make(map[reflect.Type]CustomTypeFunc)
}
for _, t := range types {
v.customFuncs[reflect.TypeOf(t)] = fn
}
v.hasCustomFuncs = true
}
// RegisterTranslation registers translations against the provided tag.
func (v *Validate) RegisterTranslation(tag string, trans ut.Translator, registerFn RegisterTranslationsFunc, translationFn TranslationFunc) (err error) {
if v.transTagFunc == nil {
v.transTagFunc = make(map[ut.Translator]map[string]TranslationFunc)
}
if err = registerFn(trans); err != nil {
return
}
m, ok := v.transTagFunc[trans]
if !ok {
m = make(map[string]TranslationFunc)
v.transTagFunc[trans] = m
}
m[tag] = translationFn
return
}
// 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.
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
func (v *Validate) Struct(s interface{}) error {
return v.StructCtx(context.Background(), s)
}
// StructCtx validates a structs exposed fields, and automatically validates nested structs, unless otherwise specified
// and also allows passing of context.Context for contextual validation information.
//
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
func (v *Validate) StructCtx(ctx context.Context, s interface{}) (err error) {
val := reflect.ValueOf(s)
top := val
if val.Kind() == reflect.Ptr && !val.IsNil() {
val = val.Elem()
}
if val.Kind() != reflect.Struct || val.Type().ConvertibleTo(timeType) {
return &InvalidValidationError{Type: reflect.TypeOf(s)}
}
// good to validate
vd := v.pool.Get().(*validate)
vd.top = top
vd.isPartial = false
// vd.hasExcludes = false // only need to reset in StructPartial and StructExcept
vd.validateStruct(ctx, top, val, val.Type(), vd.ns[0:0], vd.actualNs[0:0], nil)
if len(vd.errs) > 0 {
err = vd.errs
vd.errs = nil
}
v.pool.Put(vd)
return
}
// StructFiltered validates a structs exposed fields, that pass the FilterFunc check and automatically validates
// nested structs, unless otherwise specified.
//
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
func (v *Validate) StructFiltered(s interface{}, fn FilterFunc) error {
return v.StructFilteredCtx(context.Background(), s, fn)
}
// StructFilteredCtx validates a structs exposed fields, that pass the FilterFunc check and automatically validates
// nested structs, unless otherwise specified and also allows passing of contextual validation information via
// context.Context
//
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
func (v *Validate) StructFilteredCtx(ctx context.Context, s interface{}, fn FilterFunc) (err error) {
val := reflect.ValueOf(s)
top := val
if val.Kind() == reflect.Ptr && !val.IsNil() {
val = val.Elem()
}
if val.Kind() != reflect.Struct || val.Type().ConvertibleTo(timeType) {
return &InvalidValidationError{Type: reflect.TypeOf(s)}
}
// good to validate
vd := v.pool.Get().(*validate)
vd.top = top
vd.isPartial = true
vd.ffn = fn
// vd.hasExcludes = false // only need to reset in StructPartial and StructExcept
vd.validateStruct(ctx, top, val, val.Type(), vd.ns[0:0], vd.actualNs[0:0], nil)
if len(vd.errs) > 0 {
err = vd.errs
vd.errs = nil
}
v.pool.Put(vd)
return
}
// StructPartial validates the fields passed in only, ignoring all others.
// Fields may be provided in a namespaced fashion relative to the struct provided
// eg. NestedStruct.Field or NestedArrayField[0].Struct.Name
//
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
func (v *Validate) StructPartial(s interface{}, fields ...string) error {
return v.StructPartialCtx(context.Background(), s, fields...)
}
// StructPartialCtx validates the fields passed in only, ignoring all others and allows passing of contextual
// validation validation information via context.Context
// Fields may be provided in a namespaced fashion relative to the struct provided
// eg. NestedStruct.Field or NestedArrayField[0].Struct.Name
//
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
func (v *Validate) StructPartialCtx(ctx context.Context, s interface{}, fields ...string) (err error) {
val := reflect.ValueOf(s)
top := val
if val.Kind() == reflect.Ptr && !val.IsNil() {
val = val.Elem()
}
if val.Kind() != reflect.Struct || val.Type().ConvertibleTo(timeType) {
return &InvalidValidationError{Type: reflect.TypeOf(s)}
}
// good to validate
vd := v.pool.Get().(*validate)
vd.top = top
vd.isPartial = true
vd.ffn = nil
vd.hasExcludes = false
vd.includeExclude = make(map[string]struct{})
typ := val.Type()
name := typ.Name()
for _, k := range fields {
flds := strings.Split(k, namespaceSeparator)
if len(flds) > 0 {
vd.misc = append(vd.misc[0:0], name...)
// Don't append empty name for unnamed structs
if len(vd.misc) != 0 {
vd.misc = append(vd.misc, '.')
}
for _, s := range flds {
idx := strings.Index(s, leftBracket)
if idx != -1 {
for idx != -1 {
vd.misc = append(vd.misc, s[:idx]...)
vd.includeExclude[string(vd.misc)] = struct{}{}
idx2 := strings.Index(s, rightBracket)
idx2++
vd.misc = append(vd.misc, s[idx:idx2]...)
vd.includeExclude[string(vd.misc)] = struct{}{}
s = s[idx2:]
idx = strings.Index(s, leftBracket)
}
} else {
vd.misc = append(vd.misc, s...)
vd.includeExclude[string(vd.misc)] = struct{}{}
}
vd.misc = append(vd.misc, '.')
}
}
}
vd.validateStruct(ctx, top, val, typ, vd.ns[0:0], vd.actualNs[0:0], nil)
if len(vd.errs) > 0 {
err = vd.errs
vd.errs = nil
}
v.pool.Put(vd)
return
}
// StructExcept validates all fields except the ones passed in.
// Fields may be provided in a namespaced fashion relative to the struct provided
// i.e. NestedStruct.Field or NestedArrayField[0].Struct.Name
//
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
func (v *Validate) StructExcept(s interface{}, fields ...string) error {
return v.StructExceptCtx(context.Background(), s, fields...)
}
// StructExceptCtx validates all fields except the ones passed in and allows passing of contextual
// validation validation information via context.Context
// Fields may be provided in a namespaced fashion relative to the struct provided
// i.e. NestedStruct.Field or NestedArrayField[0].Struct.Name
//
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
func (v *Validate) StructExceptCtx(ctx context.Context, s interface{}, fields ...string) (err error) {
val := reflect.ValueOf(s)
top := val
if val.Kind() == reflect.Ptr && !val.IsNil() {
val = val.Elem()
}
if val.Kind() != reflect.Struct || val.Type().ConvertibleTo(timeType) {
return &InvalidValidationError{Type: reflect.TypeOf(s)}
}
// good to validate
vd := v.pool.Get().(*validate)
vd.top = top
vd.isPartial = true
vd.ffn = nil
vd.hasExcludes = true
vd.includeExclude = make(map[string]struct{})
typ := val.Type()
name := typ.Name()
for _, key := range fields {
vd.misc = vd.misc[0:0]
if len(name) > 0 {
vd.misc = append(vd.misc, name...)
vd.misc = append(vd.misc, '.')
}
vd.misc = append(vd.misc, key...)
vd.includeExclude[string(vd.misc)] = struct{}{}
}
vd.validateStruct(ctx, top, val, typ, vd.ns[0:0], vd.actualNs[0:0], nil)
if len(vd.errs) > 0 {
err = vd.errs
vd.errs = nil
}
v.pool.Put(vd)
return
}
// Var validates a single variable using tag style validation.
// eg.
// var i int
// validate.Var(i, "gt=1,lt=10")
//
// WARNING: a struct can be passed for validation eg. time.Time is a struct or
// if you have a custom type and have registered a custom type handler, so must
// allow it; however unforeseen validations will occur if trying to validate a
// struct that is meant to be passed to 'validate.Struct'
//
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
// validate Array, Slice and maps fields which may contain more than one error
func (v *Validate) Var(field interface{}, tag string) error {
return v.VarCtx(context.Background(), field, tag)
}
// VarCtx validates a single variable using tag style validation and allows passing of contextual
// validation information via context.Context.
// eg.
// var i int
// validate.Var(i, "gt=1,lt=10")
//
// WARNING: a struct can be passed for validation eg. time.Time is a struct or
// if you have a custom type and have registered a custom type handler, so must
// allow it; however unforeseen validations will occur if trying to validate a
// struct that is meant to be passed to 'validate.Struct'
//
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
// validate Array, Slice and maps fields which may contain more than one error
func (v *Validate) VarCtx(ctx context.Context, field interface{}, tag string) (err error) {
if len(tag) == 0 || tag == skipValidationTag {
return nil
}
ctag := v.fetchCacheTag(tag)
val := reflect.ValueOf(field)
vd := v.pool.Get().(*validate)
vd.top = val
vd.isPartial = false
vd.traverseField(ctx, val, val, vd.ns[0:0], vd.actualNs[0:0], defaultCField, ctag)
if len(vd.errs) > 0 {
err = vd.errs
vd.errs = nil
}
v.pool.Put(vd)
return
}
// VarWithValue validates a single variable, against another variable/field's value using tag style validation
// eg.
// s1 := "abcd"
// s2 := "abcd"
// validate.VarWithValue(s1, s2, "eqcsfield") // returns true
//
// WARNING: a struct can be passed for validation eg. time.Time is a struct or
// if you have a custom type and have registered a custom type handler, so must
// allow it; however unforeseen validations will occur if trying to validate a
// struct that is meant to be passed to 'validate.Struct'
//
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
// validate Array, Slice and maps fields which may contain more than one error
func (v *Validate) VarWithValue(field interface{}, other interface{}, tag string) error {
return v.VarWithValueCtx(context.Background(), field, other, tag)
}
// VarWithValueCtx validates a single variable, against another variable/field's value using tag style validation and
// allows passing of contextual validation validation information via context.Context.
// eg.
// s1 := "abcd"
// s2 := "abcd"
// validate.VarWithValue(s1, s2, "eqcsfield") // returns true
//
// WARNING: a struct can be passed for validation eg. time.Time is a struct or
// if you have a custom type and have registered a custom type handler, so must
// allow it; however unforeseen validations will occur if trying to validate a
// struct that is meant to be passed to 'validate.Struct'
//
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
// validate Array, Slice and maps fields which may contain more than one error
func (v *Validate) VarWithValueCtx(ctx context.Context, field interface{}, other interface{}, tag string) (err error) {
if len(tag) == 0 || tag == skipValidationTag {
return nil
}
ctag := v.fetchCacheTag(tag)
otherVal := reflect.ValueOf(other)
vd := v.pool.Get().(*validate)
vd.top = otherVal
vd.isPartial = false
vd.traverseField(ctx, otherVal, reflect.ValueOf(field), vd.ns[0:0], vd.actualNs[0:0], defaultCField, ctag)
if len(vd.errs) > 0 {
err = vd.errs
vd.errs = nil
}
v.pool.Put(vd)
return
}

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save