pax_global_header00006660000000000000000000000064151241007700014507gustar00rootroot0000000000000052 comment=f418fa915fd144ba0d1d7d4f61e6f4882949a2d8 golang-github-go-playground-validator-v10-10.30.1/000077500000000000000000000000001512410077000215545ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/.github/000077500000000000000000000000001512410077000231145ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/.github/CODEOWNERS000066400000000000000000000000461512410077000245070ustar00rootroot00000000000000* @go-playground/validator-maintainersgolang-github-go-playground-validator-v10-10.30.1/.github/CONTRIBUTING.md000066400000000000000000000010331512410077000253420ustar00rootroot00000000000000# 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. golang-github-go-playground-validator-v10-10.30.1/.github/ISSUE_TEMPLATE/000077500000000000000000000000001512410077000252775ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/.github/ISSUE_TEMPLATE/bug_report.yml000066400000000000000000000013761512410077000302010ustar00rootroot00000000000000name: Bug Report description: File a bug report title: "[Bug]: " labels: ["bug"] body: - type: markdown attributes: value: | Thanks for taking the time to fill out this bug report! - type: textarea id: what-happened attributes: label: What happened? description: Also tell us, what did you expect to happen? validations: required: true - type: textarea id: version attributes: label: Version description: What version of validator are you running? validations: required: true - type: textarea id: code attributes: label: Example Code description: Please provide a code example that demonstrates the issue render: go validations: required: true golang-github-go-playground-validator-v10-10.30.1/.github/PULL_REQUEST_TEMPLATE.md000066400000000000000000000003161512410077000267150ustar00rootroot00000000000000## 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-maintainersgolang-github-go-playground-validator-v10-10.30.1/.github/dependabot.yml000066400000000000000000000004051512410077000257430ustar00rootroot00000000000000version: 2 updates: # Maintain dependencies for Golang - package-ecosystem: gomod directory: "/" schedule: interval: weekly # Maintain dependencies for GitHub Actions - package-ecosystem: github-actions directory: "/" schedule: interval: weekly golang-github-go-playground-validator-v10-10.30.1/.github/workflows/000077500000000000000000000000001512410077000251515ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/.github/workflows/go.yml000066400000000000000000000006651512410077000263100ustar00rootroot00000000000000on: push: branches: - master name: Test jobs: test: strategy: matrix: go-version: [1.24.x, 1.25.x] os: [ubuntu-latest] runs-on: ${{ matrix.os }} steps: - name: Checkout code uses: actions/checkout@v6 - name: Install Go uses: actions/setup-go@v6 with: go-version: ${{ matrix.go-version }} - name: Test run: go test -race ./... golang-github-go-playground-validator-v10-10.30.1/.github/workflows/workflow.yml000066400000000000000000000017751512410077000275600ustar00rootroot00000000000000on: push: branches: - master pull_request: name: Test jobs: test: strategy: matrix: go-version: [1.24.x, 1.25.x] os: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.os }} steps: - name: Checkout code uses: actions/checkout@v6 - name: Install Go uses: actions/setup-go@v6 with: go-version: ${{ matrix.go-version }} - name: Test run: go test -race -covermode=atomic -coverprofile="profile.cov" ./... - name: Send Coverage if: matrix.os == 'ubuntu-latest' && matrix.go-version == '1.24.x' uses: shogo82148/actions-goveralls@v1 with: path-to-profile: profile.cov golangci: name: lint runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: actions/setup-go@v6 with: go-version: 1.24.x - name: golangci-lint uses: golangci/golangci-lint-action@v9 with: version: latestgolang-github-go-playground-validator-v10-10.30.1/.gitignore000066400000000000000000000005151512410077000235450ustar00rootroot00000000000000# Compiled Object files, Static and Dynamic libs (Shared Objects) *.o *.a *.so # Folders _obj _test bin # Architecture specific extensions/prefixes *.[568vq] [568vq].out *.cgo1.go *.cgo2.c _cgo_defun.c _cgo_gotypes.go _cgo_export.* _testmain.go *.exe *.test *.prof *.test *.out *.txt /**/*.DS_Store cover.html README.html .idea golang-github-go-playground-validator-v10-10.30.1/.golangci.yaml000066400000000000000000000015001512410077000242750ustar00rootroot00000000000000version: "2" linters: default: all disable: - noinlineerr - wsl_v5 - copyloopvar - cyclop - depguard - dogsled - dupl - dupword - err113 - errorlint - exhaustive - exhaustruct - forbidigo - forcetypeassert - funlen - gochecknoglobals - gocognit - goconst - gocritic - gocyclo - godot - gosec - gosmopolitan - interfacebloat - intrange - ireturn - lll - maintidx - misspell - mnd - modernize - nakedret - nestif - nilnil - nlreturn - nonamedreturns - paralleltest - perfsprint - prealloc - recvcheck - revive - staticcheck - tagalign - tagliatelle - testpackage - thelper - tparallel - unparam - varnamelen - wrapcheck - wsl golang-github-go-playground-validator-v10-10.30.1/LICENSE000066400000000000000000000020651512410077000225640ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2015 Dean Karn Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. golang-github-go-playground-validator-v10-10.30.1/MAINTAINERS.md000066400000000000000000000007021512410077000236470ustar00rootroot00000000000000## 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.golang-github-go-playground-validator-v10-10.30.1/Makefile000066400000000000000000000006171512410077000232200ustar00rootroot00000000000000GOCMD=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 v2.0.2; \ } lint: linters-install golangci-lint run test: $(GOCMD) test -cover -race ./... bench: $(GOCMD) test -run=NONE -bench=. -benchmem ./... .PHONY: test lint linters-install golang-github-go-playground-validator-v10-10.30.1/README.md000066400000000000000000000533001512410077000230340ustar00rootroot00000000000000Package validator ================= [![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/go-playground/validator)](https://github.com/go-playground/validator/releases) [![Build Status](https://github.com/go-playground/validator/actions/workflows/workflow.yml/badge.svg)](https://github.com/go-playground/validator/actions) [![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) A Call for Maintainers ---------------------- Please read the discussiong started [here](https://github.com/go-playground/validator/discussions/1330) if you are interested in contributing/helping maintain this package. 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: ```go err := validate.Struct(mystruct) validationErrors := err.(validator.ValidationErrors) ``` Usage and documentation ------ Please see https://pkg.go.dev/github.com/go-playground/validator/v10 for detailed usage docs. ##### Examples: - [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) Baked-in Validations ------ ### Special Notes: - If new to using validator it is highly recommended to initialize it using the `WithRequiredStructEnabled` option which is opt-in to new behaviour that will become the default behaviour in v11+. See documentation for more details. ```go validate := validator.New(validator.WithRequiredStructEnabled()) ``` ### Fields: | 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 | ### Network: | 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_rfc1123 | Hostname RFC 1123 | | hostname_port | HostPort | | port | Port number | | 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 | | uds_exists | Unix domain socket exists (checks filesystem sockets and Linux abstract sockets) | | uri | URI String | | url | URL String | | http_url | HTTP(s) URL String | | https_url | HTTPS-only URL String | | url_encoded | URL Encoded | | urn_rfc2141 | Urn RFC 2141 String | ### Strings: | Tag | Description | | - | - | | alpha | Alpha Only | | alphaspace | Alpha Space | | alphanum | Alphanumeric | | alphanumspace | Alphanumeric Space | | 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_iso_9362_2014 | Business Identifier Code (ISO 9362:2014) | | bic | Business Identifier Code (ISO 9362:2022) | | 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 | | mongodb_connection_string | MongoDB Connection String | | cron | Cron | | spicedb | SpiceDb ObjectID/Permission/Type | | datetime | Datetime | | e164 | e164 formatted phone number | | ein | U.S. Employeer Identification 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 | | issn | International Standard Serial Number | | 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 | | image | Image | | 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 | | validateFn | Verify if the method `Validate() error` does not return an error (or any specified method) | #### 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 Max M3 ```go go version go1.23.3 darwin/arm64 goos: darwin goarch: arm64 cpu: Apple M3 Max pkg: github.com/go-playground/validator/v10 BenchmarkFieldSuccess-16 42461943 27.88 ns/op 0 B/op 0 allocs/op BenchmarkFieldSuccessParallel-16 486632887 2.289 ns/op 0 B/op 0 allocs/op BenchmarkFieldFailure-16 9566167 121.3 ns/op 200 B/op 4 allocs/op BenchmarkFieldFailureParallel-16 17551471 83.68 ns/op 200 B/op 4 allocs/op BenchmarkFieldArrayDiveSuccess-16 7602306 155.6 ns/op 97 B/op 5 allocs/op BenchmarkFieldArrayDiveSuccessParallel-16 20664610 59.80 ns/op 97 B/op 5 allocs/op BenchmarkFieldArrayDiveFailure-16 4659756 252.9 ns/op 301 B/op 10 allocs/op BenchmarkFieldArrayDiveFailureParallel-16 8010116 152.9 ns/op 301 B/op 10 allocs/op BenchmarkFieldMapDiveSuccess-16 2834575 421.2 ns/op 288 B/op 14 allocs/op BenchmarkFieldMapDiveSuccessParallel-16 7179700 171.8 ns/op 288 B/op 14 allocs/op BenchmarkFieldMapDiveFailure-16 3081728 384.4 ns/op 376 B/op 13 allocs/op BenchmarkFieldMapDiveFailureParallel-16 6058137 204.0 ns/op 377 B/op 13 allocs/op BenchmarkFieldMapDiveWithKeysSuccess-16 2544975 464.8 ns/op 288 B/op 14 allocs/op BenchmarkFieldMapDiveWithKeysSuccessParallel-16 6661954 181.4 ns/op 288 B/op 14 allocs/op BenchmarkFieldMapDiveWithKeysFailure-16 2435484 490.7 ns/op 553 B/op 16 allocs/op BenchmarkFieldMapDiveWithKeysFailureParallel-16 4249617 282.0 ns/op 554 B/op 16 allocs/op BenchmarkFieldCustomTypeSuccess-16 14943525 77.35 ns/op 32 B/op 2 allocs/op BenchmarkFieldCustomTypeSuccessParallel-16 64051954 20.61 ns/op 32 B/op 2 allocs/op BenchmarkFieldCustomTypeFailure-16 10721384 107.1 ns/op 184 B/op 3 allocs/op BenchmarkFieldCustomTypeFailureParallel-16 18714495 69.77 ns/op 184 B/op 3 allocs/op BenchmarkFieldOrTagSuccess-16 4063124 294.3 ns/op 16 B/op 1 allocs/op BenchmarkFieldOrTagSuccessParallel-16 31903756 41.22 ns/op 18 B/op 1 allocs/op BenchmarkFieldOrTagFailure-16 7748558 146.8 ns/op 216 B/op 5 allocs/op BenchmarkFieldOrTagFailureParallel-16 13139854 92.05 ns/op 216 B/op 5 allocs/op BenchmarkStructLevelValidationSuccess-16 16808389 70.25 ns/op 16 B/op 1 allocs/op BenchmarkStructLevelValidationSuccessParallel-16 90686955 14.47 ns/op 16 B/op 1 allocs/op BenchmarkStructLevelValidationFailure-16 5818791 200.2 ns/op 264 B/op 7 allocs/op BenchmarkStructLevelValidationFailureParallel-16 11115874 107.5 ns/op 264 B/op 7 allocs/op BenchmarkStructSimpleCustomTypeSuccess-16 7764956 151.9 ns/op 32 B/op 2 allocs/op BenchmarkStructSimpleCustomTypeSuccessParallel-16 52316265 30.37 ns/op 32 B/op 2 allocs/op BenchmarkStructSimpleCustomTypeFailure-16 4195429 277.2 ns/op 416 B/op 9 allocs/op BenchmarkStructSimpleCustomTypeFailureParallel-16 7305661 164.6 ns/op 432 B/op 10 allocs/op BenchmarkStructFilteredSuccess-16 6312625 186.1 ns/op 216 B/op 5 allocs/op BenchmarkStructFilteredSuccessParallel-16 13684459 93.42 ns/op 216 B/op 5 allocs/op BenchmarkStructFilteredFailure-16 6751482 171.2 ns/op 216 B/op 5 allocs/op BenchmarkStructFilteredFailureParallel-16 14146070 86.93 ns/op 216 B/op 5 allocs/op BenchmarkStructPartialSuccess-16 6544448 177.3 ns/op 224 B/op 4 allocs/op BenchmarkStructPartialSuccessParallel-16 13951946 88.73 ns/op 224 B/op 4 allocs/op BenchmarkStructPartialFailure-16 4075833 287.5 ns/op 440 B/op 9 allocs/op BenchmarkStructPartialFailureParallel-16 7490805 161.3 ns/op 440 B/op 9 allocs/op BenchmarkStructExceptSuccess-16 4107187 281.4 ns/op 424 B/op 8 allocs/op BenchmarkStructExceptSuccessParallel-16 15979173 80.86 ns/op 208 B/op 3 allocs/op BenchmarkStructExceptFailure-16 4434372 264.3 ns/op 424 B/op 8 allocs/op BenchmarkStructExceptFailureParallel-16 8081367 154.1 ns/op 424 B/op 8 allocs/op BenchmarkStructSimpleCrossFieldSuccess-16 6459542 183.4 ns/op 56 B/op 3 allocs/op BenchmarkStructSimpleCrossFieldSuccessParallel-16 41013781 37.95 ns/op 56 B/op 3 allocs/op BenchmarkStructSimpleCrossFieldFailure-16 4034998 292.1 ns/op 272 B/op 8 allocs/op BenchmarkStructSimpleCrossFieldFailureParallel-16 11348446 115.3 ns/op 272 B/op 8 allocs/op BenchmarkStructSimpleCrossStructCrossFieldSuccess-16 4448528 267.7 ns/op 64 B/op 4 allocs/op BenchmarkStructSimpleCrossStructCrossFieldSuccessParallel-16 26813619 48.33 ns/op 64 B/op 4 allocs/op BenchmarkStructSimpleCrossStructCrossFieldFailure-16 3090646 384.5 ns/op 288 B/op 9 allocs/op BenchmarkStructSimpleCrossStructCrossFieldFailureParallel-16 9870906 129.5 ns/op 288 B/op 9 allocs/op BenchmarkStructSimpleSuccess-16 10675562 109.5 ns/op 0 B/op 0 allocs/op BenchmarkStructSimpleSuccessParallel-16 131159784 8.932 ns/op 0 B/op 0 allocs/op BenchmarkStructSimpleFailure-16 4094979 286.6 ns/op 416 B/op 9 allocs/op BenchmarkStructSimpleFailureParallel-16 7606663 157.9 ns/op 416 B/op 9 allocs/op BenchmarkStructComplexSuccess-16 2073470 576.0 ns/op 224 B/op 5 allocs/op BenchmarkStructComplexSuccessParallel-16 7821831 161.3 ns/op 224 B/op 5 allocs/op BenchmarkStructComplexFailure-16 576358 2001 ns/op 3042 B/op 48 allocs/op BenchmarkStructComplexFailureParallel-16 1000000 1171 ns/op 3041 B/op 48 allocs/op BenchmarkOneof-16 22503973 52.82 ns/op 0 B/op 0 allocs/op BenchmarkOneofParallel-16 8538474 140.4 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... Maintenance and support for SDK major versions ---------------------------------------------- See prior discussion [here](https://github.com/go-playground/validator/discussions/1342) for more details. This package is aligned with the [Go release policy](https://go.dev/doc/devel/release) in that support is guaranteed for the two most recent major versions. This does not mean the package will not work with older versions of Go, only that we reserve the right to increase the MSGV(Minimum Supported Go Version) when the need arises to address Security issues/patches, OS issues & support or newly introduced functionality that would greatly benefit the maintenance and/or usage of this package. If and when the MSGV is increased it will be done so in a minimum of a `Minor` release bump. License ------- 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 golang-github-go-playground-validator-v10-10.30.1/_examples/000077500000000000000000000000001512410077000235315ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/_examples/custom-validation/000077500000000000000000000000001512410077000271735ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/_examples/custom-validation/main.go000066400000000000000000000013171512410077000304500ustar00rootroot00000000000000package 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" } golang-github-go-playground-validator-v10-10.30.1/_examples/custom/000077500000000000000000000000001512410077000250435ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/_examples/custom/main.go000066400000000000000000000021371512410077000263210ustar00rootroot00000000000000package 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 } golang-github-go-playground-validator-v10-10.30.1/_examples/dive/000077500000000000000000000000001512410077000244605ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/_examples/dive/main.go000066400000000000000000000014001512410077000257260ustar00rootroot00000000000000package 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) } golang-github-go-playground-validator-v10-10.30.1/_examples/gin-upgrading-overriding/000077500000000000000000000000001512410077000304325ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/_examples/gin-upgrading-overriding/main.go000066400000000000000000000002141512410077000317020ustar00rootroot00000000000000package main import "github.com/gin-gonic/gin/binding" func main() { binding.Validator = new(defaultValidator) // regular gin logic } golang-github-go-playground-validator-v10-10.30.1/_examples/gin-upgrading-overriding/v8_to_v9.go000066400000000000000000000016441512410077000324430ustar00rootroot00000000000000package 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 } golang-github-go-playground-validator-v10-10.30.1/_examples/http-transalations/000077500000000000000000000000001512410077000273705ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/_examples/http-transalations/main.go000066400000000000000000000043721512410077000306510ustar00rootroot00000000000000package main import ( "encoding/json" "errors" "net/http" "strings" "github.com/go-playground/locales/en" "github.com/go-playground/locales/zh" "github.com/go-playground/locales/zh_Hant_TW" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" en_translations "github.com/go-playground/validator/v10/translations/en" zh_translations "github.com/go-playground/validator/v10/translations/zh" zh_tw_translations "github.com/go-playground/validator/v10/translations/zh_tw" ) var uni *ut.UniversalTranslator // This example showcases how to use the Validator and UniversalTranslator with both Simplified and Traditional Chinese languages. // To run the example: // Step 1: go run _examples/http-transalations/main.go // Step 2 - Simplified Chinese: curl -d '{"first_name":"foo"}' -H "Accept-Language: zh" -H "Content-Type: application/json" -X POST http://localhost:8081/users // Step 3 - Traditional Chinese: curl -d '{"first_name":"foo"}' -H "Accept-Language: zh-Hant-TW" -H "Content-Type: application/json" -X POST http://localhost:8081/users func main() { validate := validator.New() en := en.New() uni = ut.New(en, en, zh.New(), zh_Hant_TW.New()) validate = validator.New() enTrans, _ := uni.GetTranslator("en") en_translations.RegisterDefaultTranslations(validate, enTrans) zhTrans, _ := uni.GetTranslator("zh") zh_translations.RegisterDefaultTranslations(validate, zhTrans) zhHantTrans, _ := uni.GetTranslator("zh_Hant_TW") zh_tw_translations.RegisterDefaultTranslations(validate, zhHantTrans) type User struct { FirstName string `json:"first_name" validate:"required"` LastName string `json:"last_name" validate:"required"` } http.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) { // ... fill user value var user User // Header Accept-Language value is en or zh trans, _ := uni.GetTranslator(strings.Replace(r.Header.Get("Accept-Language"), "-", "_", -1)) if err := validate.Struct(&user); err != nil { var errs validator.ValidationErrors var httpErrors []validator.ValidationErrorsTranslations if errors.As(err, &errs) { httpErrors = append(httpErrors, errs.Translate(trans)) } r, _ := json.Marshal(httpErrors) w.Write(r) } }) http.ListenAndServe(":8081", nil) } golang-github-go-playground-validator-v10-10.30.1/_examples/map-validation/000077500000000000000000000000001512410077000264365ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/_examples/map-validation/main.go000066400000000000000000000043101512410077000277070ustar00rootroot00000000000000package 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 } golang-github-go-playground-validator-v10-10.30.1/_examples/simple/000077500000000000000000000000001512410077000250225ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/_examples/simple/main.go000066400000000000000000000051771512410077000263070ustar00rootroot00000000000000package main import ( "errors" "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"` Gender string `validate:"oneof=male female prefer_not_to"` 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(validator.WithRequiredStructEnabled()) validateStruct() validateVariable() } func validateStruct() { address := &Address{ Street: "Eavesdown Docks", Planet: "Persphone", Phone: "none", } user := &User{ FirstName: "Badger", LastName: "Smith", Age: 135, Gender: "male", 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. var invalidValidationError *validator.InvalidValidationError if errors.As(err, &invalidValidationError) { fmt.Println(err) return } var validateErrs validator.ValidationErrors if errors.As(err, &validateErrs) { for _, e := range validateErrs { fmt.Println(e.Namespace()) fmt.Println(e.Field()) fmt.Println(e.StructNamespace()) fmt.Println(e.StructField()) fmt.Println(e.Tag()) fmt.Println(e.ActualTag()) fmt.Println(e.Kind()) fmt.Println(e.Type()) fmt.Println(e.Value()) fmt.Println(e.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 } golang-github-go-playground-validator-v10-10.30.1/_examples/struct-level/000077500000000000000000000000001512410077000261625ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/_examples/struct-level/main.go000066400000000000000000000124031512410077000274350ustar00rootroot00000000000000package main import ( "encoding/json" "errors" "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. var invalidValidationError *validator.InvalidValidationError if errors.As(err, &invalidValidationError) { fmt.Println(err) return } var validateErrs validator.ValidationErrors if errors.As(err, &validateErrs) { for _, err := range validateErrs { 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" } golang-github-go-playground-validator-v10-10.30.1/_examples/struct-map-rules-validation/000077500000000000000000000000001512410077000311105ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/_examples/struct-map-rules-validation/main.go000066400000000000000000000034121512410077000323630ustar00rootroot00000000000000package 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) } golang-github-go-playground-validator-v10-10.30.1/_examples/translations/000077500000000000000000000000001512410077000262525ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/_examples/translations/main.go000066400000000000000000000062041512410077000275270ustar00rootroot00000000000000package 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: omitting 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)) } } } golang-github-go-playground-validator-v10-10.30.1/_examples/validate_fn/000077500000000000000000000000001512410077000260055ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/_examples/validate_fn/enum_enumer.go000066400000000000000000000036201512410077000306540ustar00rootroot00000000000000// Code generated by "enumer -type=Enum"; DO NOT EDIT. package main import ( "fmt" "strings" ) const _EnumName = "ZeroOneTwoThree" var _EnumIndex = [...]uint8{0, 4, 7, 10, 15} const _EnumLowerName = "zeroonetwothree" func (i Enum) String() string { if i >= Enum(len(_EnumIndex)-1) { return fmt.Sprintf("Enum(%d)", i) } return _EnumName[_EnumIndex[i]:_EnumIndex[i+1]] } // An "invalid array index" compiler error signifies that the constant values have changed. // Re-run the stringer command to generate them again. func _EnumNoOp() { var x [1]struct{} _ = x[Zero-(0)] _ = x[One-(1)] _ = x[Two-(2)] _ = x[Three-(3)] } var _EnumValues = []Enum{Zero, One, Two, Three} var _EnumNameToValueMap = map[string]Enum{ _EnumName[0:4]: Zero, _EnumLowerName[0:4]: Zero, _EnumName[4:7]: One, _EnumLowerName[4:7]: One, _EnumName[7:10]: Two, _EnumLowerName[7:10]: Two, _EnumName[10:15]: Three, _EnumLowerName[10:15]: Three, } var _EnumNames = []string{ _EnumName[0:4], _EnumName[4:7], _EnumName[7:10], _EnumName[10:15], } // EnumString retrieves an enum value from the enum constants string name. // Throws an error if the param is not part of the enum. func EnumString(s string) (Enum, error) { if val, ok := _EnumNameToValueMap[s]; ok { return val, nil } if val, ok := _EnumNameToValueMap[strings.ToLower(s)]; ok { return val, nil } return 0, fmt.Errorf("%s does not belong to Enum values", s) } // EnumValues returns all values of the enum func EnumValues() []Enum { return _EnumValues } // EnumStrings returns a slice of all String values of the enum func EnumStrings() []string { strs := make([]string, len(_EnumNames)) copy(strs, _EnumNames) return strs } // IsAEnum returns "true" if the value is listed in the enum definition. "false" otherwise func (i Enum) IsAEnum() bool { for _, v := range _EnumValues { if i == v { return true } } return false } golang-github-go-playground-validator-v10-10.30.1/_examples/validate_fn/go.mod000066400000000000000000000011401512410077000271070ustar00rootroot00000000000000module github.com/peczenyj/validator/_examples/validate_fn go 1.23.0 toolchain go1.24.4 replace github.com/go-playground/validator/v10 => ../../../validator require github.com/go-playground/validator/v10 v10.26.0 require ( github.com/gabriel-vasile/mimetype v1.4.8 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/leodido/go-urn v1.4.0 // indirect golang.org/x/crypto v0.36.0 // indirect golang.org/x/net v0.38.0 // indirect golang.org/x/sys v0.31.0 // indirect golang.org/x/text v0.23.0 // indirect ) golang-github-go-playground-validator-v10-10.30.1/_examples/validate_fn/go.sum000066400000000000000000000050031512410077000271360ustar00rootroot00000000000000github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= 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.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= golang-github-go-playground-validator-v10-10.30.1/_examples/validate_fn/main.go000066400000000000000000000014231512410077000272600ustar00rootroot00000000000000package main import ( "errors" "fmt" "github.com/go-playground/validator/v10" ) //go:generate enumer -type=Enum type Enum uint8 const ( Zero Enum = iota One Two Three ) func (e *Enum) Validate() error { if e == nil { return errors.New("can't be nil") } return nil } type Struct struct { Foo *Enum `validate:"validateFn"` // uses Validate() error by default Bar Enum `validate:"validateFn=IsAEnum"` // uses IsAEnum() bool provided by enumer } func main() { validate := validator.New() var x Struct x.Bar = Enum(64) if err := validate.Struct(x); err != nil { fmt.Printf("Expected Err(s):\n%+v\n", err) } x = Struct{ Foo: new(Enum), Bar: One, } if err := validate.Struct(x); err != nil { fmt.Printf("Unexpected Err(s):\n%+v\n", err) } } golang-github-go-playground-validator-v10-10.30.1/baked_in.go000066400000000000000000002740051512410077000236470ustar00rootroot00000000000000package validator import ( "bufio" "bytes" "cmp" "context" "crypto/sha256" "encoding/hex" "encoding/json" "errors" "fmt" "io/fs" "net" "net/mail" "net/url" "os" "reflect" "runtime" "strconv" "strings" "sync" "syscall" "time" "unicode/utf8" "golang.org/x/crypto/sha3" "golang.org/x/text/language" "github.com/gabriel-vasile/mimetype" urn "github.com/leodido/go-urn" ) // Func accepts a FieldLevel interface for all validation needs. The return // value should be true when validation succeeds. type Func func(fl FieldLevel) bool // FuncCtx accepts a context.Context and FieldLevel interface for all // validation needs. The return value should be true when validation succeeds. type FuncCtx func(ctx context.Context, fl FieldLevel) bool // wrapFunc wraps normal Func makes it compatible with FuncCtx func wrapFunc(fn Func) FuncCtx { if fn == nil { return nil // be sure not to wrap a bad function. } return func(ctx context.Context, fl FieldLevel) bool { return fn(fl) } } var ( restrictedTags = map[string]struct{}{ diveTag: {}, keysTag: {}, endKeysTag: {}, structOnlyTag: {}, omitzero: {}, omitempty: {}, omitnil: {}, skipValidationTag: {}, utf8HexComma: {}, utf8Pipe: {}, noStructLevelTag: {}, requiredTag: {}, isdefault: {}, } // bakedInAliases is a default mapping of a single validation tag that // defines a common or complex set of validation(s) to simplify // adding validation to structs. bakedInAliases = map[string]string{ "iscolor": "hexcolor|rgb|rgba|hsl|hsla", "country_code": "iso3166_1_alpha2|iso3166_1_alpha3|iso3166_1_alpha_numeric", "eu_country_code": "iso3166_1_alpha2_eu|iso3166_1_alpha3_eu|iso3166_1_alpha_numeric_eu", } // bakedInValidators is the default map of ValidationFunc // you can add, remove or even replace items to suite your needs, // or even disregard and use your own map if so desired. bakedInValidators = map[string]Func{ "required": hasValue, "required_if": requiredIf, "required_unless": requiredUnless, "skip_unless": skipUnless, "required_with": requiredWith, "required_with_all": requiredWithAll, "required_without": requiredWithout, "required_without_all": requiredWithoutAll, "excluded_if": excludedIf, "excluded_unless": excludedUnless, "excluded_with": excludedWith, "excluded_with_all": excludedWithAll, "excluded_without": excludedWithout, "excluded_without_all": excludedWithoutAll, "isdefault": isDefault, "len": hasLengthOf, "min": hasMinOf, "max": hasMaxOf, "eq": isEq, "eq_ignore_case": isEqIgnoreCase, "ne": isNe, "ne_ignore_case": isNeIgnoreCase, "lt": isLt, "lte": isLte, "gt": isGt, "gte": isGte, "eqfield": isEqField, "eqcsfield": isEqCrossStructField, "necsfield": isNeCrossStructField, "gtcsfield": isGtCrossStructField, "gtecsfield": isGteCrossStructField, "ltcsfield": isLtCrossStructField, "ltecsfield": isLteCrossStructField, "nefield": isNeField, "gtefield": isGteField, "gtfield": isGtField, "ltefield": isLteField, "ltfield": isLtField, "fieldcontains": fieldContains, "fieldexcludes": fieldExcludes, "alpha": isAlpha, "alphaspace": isAlphaSpace, "alphanum": isAlphanum, "alphanumspace": isAlphaNumericSpace, "alphaunicode": isAlphaUnicode, "alphanumunicode": isAlphanumUnicode, "boolean": isBoolean, "numeric": isNumeric, "number": isNumber, "hexadecimal": isHexadecimal, "hexcolor": isHEXColor, "rgb": isRGB, "rgba": isRGBA, "hsl": isHSL, "hsla": isHSLA, "e164": isE164, "email": isEmail, "url": isURL, "http_url": isHttpURL, "https_url": isHttpsURL, "uri": isURI, "urn_rfc2141": isUrnRFC2141, // RFC 2141 "file": isFile, "filepath": isFilePath, "base32": isBase32, "base64": isBase64, "base64url": isBase64URL, "base64rawurl": isBase64RawURL, "contains": contains, "containsany": containsAny, "containsrune": containsRune, "excludes": excludes, "excludesall": excludesAll, "excludesrune": excludesRune, "startswith": startsWith, "endswith": endsWith, "startsnotwith": startsNotWith, "endsnotwith": endsNotWith, "image": isImage, "isbn": isISBN, "isbn10": isISBN10, "isbn13": isISBN13, "issn": isISSN, "eth_addr": isEthereumAddress, "eth_addr_checksum": isEthereumAddressChecksum, "btc_addr": isBitcoinAddress, "btc_addr_bech32": isBitcoinBech32Address, "uuid": isUUID, "uuid3": isUUID3, "uuid4": isUUID4, "uuid5": isUUID5, "uuid_rfc4122": isUUIDRFC4122, "uuid3_rfc4122": isUUID3RFC4122, "uuid4_rfc4122": isUUID4RFC4122, "uuid5_rfc4122": isUUID5RFC4122, "ulid": isULID, "md4": isMD4, "md5": isMD5, "sha256": isSHA256, "sha384": isSHA384, "sha512": isSHA512, "ripemd128": isRIPEMD128, "ripemd160": isRIPEMD160, "tiger128": isTIGER128, "tiger160": isTIGER160, "tiger192": isTIGER192, "ascii": isASCII, "printascii": isPrintableASCII, "multibyte": hasMultiByteCharacter, "datauri": isDataURI, "latitude": isLatitude, "longitude": isLongitude, "ssn": isSSN, "ipv4": isIPv4, "ipv6": isIPv6, "ip": isIP, "cidrv4": isCIDRv4, "cidrv6": isCIDRv6, "cidr": isCIDR, "tcp4_addr": isTCP4AddrResolvable, "tcp6_addr": isTCP6AddrResolvable, "tcp_addr": isTCPAddrResolvable, "udp4_addr": isUDP4AddrResolvable, "udp6_addr": isUDP6AddrResolvable, "udp_addr": isUDPAddrResolvable, "ip4_addr": isIP4AddrResolvable, "ip6_addr": isIP6AddrResolvable, "ip_addr": isIPAddrResolvable, "unix_addr": isUnixAddrResolvable, "uds_exists": isUnixDomainSocketExists, "mac": isMAC, "hostname": isHostnameRFC952, // RFC 952 "hostname_rfc1123": isHostnameRFC1123, // RFC 1123 "fqdn": isFQDN, "unique": isUnique, "oneof": isOneOf, "oneofci": isOneOfCI, "html": isHTML, "html_encoded": isHTMLEncoded, "url_encoded": isURLEncoded, "dir": isDir, "dirpath": isDirPath, "json": isJSON, "jwt": isJWT, "hostname_port": isHostnamePort, "port": isPort, "lowercase": isLowercase, "uppercase": isUppercase, "datetime": isDatetime, "timezone": isTimeZone, "iso3166_1_alpha2": isIso3166Alpha2, "iso3166_1_alpha2_eu": isIso3166Alpha2EU, "iso3166_1_alpha3": isIso3166Alpha3, "iso3166_1_alpha3_eu": isIso3166Alpha3EU, "iso3166_1_alpha_numeric": isIso3166AlphaNumeric, "iso3166_1_alpha_numeric_eu": isIso3166AlphaNumericEU, "iso3166_2": isIso31662, "iso4217": isIso4217, "iso4217_numeric": isIso4217Numeric, "bcp47_language_tag": isBCP47LanguageTag, "postcode_iso3166_alpha2": isPostcodeByIso3166Alpha2, "postcode_iso3166_alpha2_field": isPostcodeByIso3166Alpha2Field, "bic_iso_9362_2014": isIsoBic2014Format, "bic": isIsoBic2022Format, "semver": isSemverFormat, "dns_rfc1035_label": isDnsRFC1035LabelFormat, "credit_card": isCreditCard, "cve": isCveFormat, "luhn_checksum": hasLuhnChecksum, "mongodb": isMongoDBObjectId, "mongodb_connection_string": isMongoDBConnectionString, "cron": isCron, "spicedb": isSpiceDB, "ein": isEIN, "validateFn": isValidateFn, } ) var ( oneofValsCache = map[string][]string{} oneofValsCacheRWLock = sync.RWMutex{} ) func parseOneOfParam2(s string) []string { oneofValsCacheRWLock.RLock() vals, ok := oneofValsCache[s] oneofValsCacheRWLock.RUnlock() if !ok { oneofValsCacheRWLock.Lock() vals = splitParamsRegex().FindAllString(s, -1) for i := 0; i < len(vals); i++ { vals[i] = strings.ReplaceAll(vals[i], "'", "") } oneofValsCache[s] = vals oneofValsCacheRWLock.Unlock() } return vals } func isURLEncoded(fl FieldLevel) bool { return uRLEncodedRegex().MatchString(fl.Field().String()) } func isHTMLEncoded(fl FieldLevel) bool { return hTMLEncodedRegex().MatchString(fl.Field().String()) } func isHTML(fl FieldLevel) bool { return hTMLRegex().MatchString(fl.Field().String()) } func isOneOf(fl FieldLevel) bool { vals := parseOneOfParam2(fl.Param()) field := fl.Field() var v string switch field.Kind() { case reflect.String: v = field.String() case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: v = strconv.FormatInt(field.Int(), 10) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: v = strconv.FormatUint(field.Uint(), 10) default: panic(fmt.Sprintf("Bad field type %s", field.Type())) } for i := 0; i < len(vals); i++ { if vals[i] == v { return true } } return false } // isOneOfCI is the validation function for validating if the current field's value is one of the provided string values (case insensitive). func isOneOfCI(fl FieldLevel) bool { vals := parseOneOfParam2(fl.Param()) field := fl.Field() if field.Kind() != reflect.String { panic(fmt.Sprintf("Bad field type %s", field.Type())) } v := field.String() for _, val := range vals { if strings.EqualFold(val, v) { return true } } return false } // isUnique is the validation function for validating if each array|slice|map value is unique func isUnique(fl FieldLevel) bool { field := fl.Field() param := fl.Param() v := reflect.ValueOf(struct{}{}) switch field.Kind() { case reflect.Slice, reflect.Array: elem := field.Type().Elem() if elem.Kind() == reflect.Ptr { elem = elem.Elem() } if param == "" { m := reflect.MakeMap(reflect.MapOf(elem, v.Type())) for i := 0; i < field.Len(); i++ { m.SetMapIndex(reflect.Indirect(field.Index(i)), v) } return field.Len() == m.Len() } sf, ok := elem.FieldByName(param) if !ok { panic(fmt.Sprintf("Bad field name %s", param)) } sfTyp := sf.Type if sfTyp.Kind() == reflect.Ptr { sfTyp = sfTyp.Elem() } m := reflect.MakeMap(reflect.MapOf(sfTyp, v.Type())) var fieldlen int for i := 0; i < field.Len(); i++ { key := reflect.Indirect(reflect.Indirect(field.Index(i)).FieldByName(param)) if key.IsValid() { fieldlen++ m.SetMapIndex(key, v) } } return fieldlen == m.Len() case reflect.Map: var m reflect.Value if field.Type().Elem().Kind() == reflect.Ptr { m = reflect.MakeMap(reflect.MapOf(field.Type().Elem().Elem(), v.Type())) } else { m = reflect.MakeMap(reflect.MapOf(field.Type().Elem(), v.Type())) } for _, k := range field.MapKeys() { m.SetMapIndex(reflect.Indirect(field.MapIndex(k)), v) } return field.Len() == m.Len() default: if parent := fl.Parent(); parent.Kind() == reflect.Struct { uniqueField := parent.FieldByName(param) if uniqueField == reflect.ValueOf(nil) { panic(fmt.Sprintf("Bad field name provided %s", param)) } if uniqueField.Kind() != field.Kind() { panic(fmt.Sprintf("Bad field type %s:%s", field.Type(), uniqueField.Type())) } return getValue(field) != getValue(uniqueField) } panic(fmt.Sprintf("Bad field type %s", field.Type())) } } // isMAC is the validation function for validating if the field's value is a valid MAC address. func isMAC(fl FieldLevel) bool { _, err := net.ParseMAC(fl.Field().String()) return err == nil } // isCIDRv4 is the validation function for validating if the field's value is a valid v4 CIDR address. func isCIDRv4(fl FieldLevel) bool { ip, net, err := net.ParseCIDR(fl.Field().String()) return err == nil && ip.To4() != nil && net.IP.Equal(ip) } // isCIDRv6 is the validation function for validating if the field's value is a valid v6 CIDR address. func isCIDRv6(fl FieldLevel) bool { ip, _, err := net.ParseCIDR(fl.Field().String()) return err == nil && ip.To4() == nil } // isCIDR is the validation function for validating if the field's value is a valid v4 or v6 CIDR address. func isCIDR(fl FieldLevel) bool { _, _, err := net.ParseCIDR(fl.Field().String()) return err == nil } // isIPv4 is the validation function for validating if a value is a valid v4 IP address. func isIPv4(fl FieldLevel) bool { ip := net.ParseIP(fl.Field().String()) return ip != nil && ip.To4() != nil } // isIPv6 is the validation function for validating if the field's value is a valid v6 IP address. func isIPv6(fl FieldLevel) bool { ip := net.ParseIP(fl.Field().String()) return ip != nil && ip.To4() == nil } // isIP is the validation function for validating if the field's value is a valid v4 or v6 IP address. func isIP(fl FieldLevel) bool { ip := net.ParseIP(fl.Field().String()) return ip != nil } // isSSN is the validation function for validating if the field's value is a valid SSN. func isSSN(fl FieldLevel) bool { field := fl.Field() if field.Len() != 11 { return false } return sSNRegex().MatchString(field.String()) } // isLongitude is the validation function for validating if the field's value is a valid longitude coordinate. func isLongitude(fl FieldLevel) bool { field := fl.Field() var v string switch field.Kind() { case reflect.String: v = field.String() case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: v = strconv.FormatInt(field.Int(), 10) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: v = strconv.FormatUint(field.Uint(), 10) case reflect.Float32: v = strconv.FormatFloat(field.Float(), 'f', -1, 32) case reflect.Float64: v = strconv.FormatFloat(field.Float(), 'f', -1, 64) default: panic(fmt.Sprintf("Bad field type %s", field.Type())) } return longitudeRegex().MatchString(v) } // isLatitude is the validation function for validating if the field's value is a valid latitude coordinate. func isLatitude(fl FieldLevel) bool { field := fl.Field() var v string switch field.Kind() { case reflect.String: v = field.String() case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: v = strconv.FormatInt(field.Int(), 10) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: v = strconv.FormatUint(field.Uint(), 10) case reflect.Float32: v = strconv.FormatFloat(field.Float(), 'f', -1, 32) case reflect.Float64: v = strconv.FormatFloat(field.Float(), 'f', -1, 64) default: panic(fmt.Sprintf("Bad field type %s", field.Type())) } return latitudeRegex().MatchString(v) } // isDataURI is the validation function for validating if the field's value is a valid data URI. func isDataURI(fl FieldLevel) bool { uri := strings.SplitN(fl.Field().String(), ",", 2) if len(uri) != 2 { return false } if !dataURIRegex().MatchString(uri[0]) { return false } return base64Regex().MatchString(uri[1]) } // hasMultiByteCharacter is the validation function for validating if the field's value has a multi byte character. func hasMultiByteCharacter(fl FieldLevel) bool { field := fl.Field() if field.Len() == 0 { return true } return multibyteRegex().MatchString(field.String()) } // isPrintableASCII is the validation function for validating if the field's value is a valid printable ASCII character. func isPrintableASCII(fl FieldLevel) bool { field := fl.Field() if field.Kind() == reflect.String { return printableASCIIRegex().MatchString(field.String()) } return false } // isASCII is the validation function for validating if the field's value is a valid ASCII character. func isASCII(fl FieldLevel) bool { field := fl.Field() if field.Kind() == reflect.String { return aSCIIRegex().MatchString(field.String()) } return false } // isUUID5 is the validation function for validating if the field's value is a valid v5 UUID. func isUUID5(fl FieldLevel) bool { return fieldMatchesRegexByStringerValOrString(uUID5Regex, fl) } // isUUID4 is the validation function for validating if the field's value is a valid v4 UUID. func isUUID4(fl FieldLevel) bool { return fieldMatchesRegexByStringerValOrString(uUID4Regex, fl) } // isUUID3 is the validation function for validating if the field's value is a valid v3 UUID. func isUUID3(fl FieldLevel) bool { return fieldMatchesRegexByStringerValOrString(uUID3Regex, fl) } // isUUID is the validation function for validating if the field's value is a valid UUID of any version. func isUUID(fl FieldLevel) bool { return fieldMatchesRegexByStringerValOrString(uUIDRegex, fl) } // isUUID5RFC4122 is the validation function for validating if the field's value is a valid RFC4122 v5 UUID. func isUUID5RFC4122(fl FieldLevel) bool { return fieldMatchesRegexByStringerValOrString(uUID5RFC4122Regex, fl) } // isUUID4RFC4122 is the validation function for validating if the field's value is a valid RFC4122 v4 UUID. func isUUID4RFC4122(fl FieldLevel) bool { return fieldMatchesRegexByStringerValOrString(uUID4RFC4122Regex, fl) } // isUUID3RFC4122 is the validation function for validating if the field's value is a valid RFC4122 v3 UUID. func isUUID3RFC4122(fl FieldLevel) bool { return fieldMatchesRegexByStringerValOrString(uUID3RFC4122Regex, fl) } // isUUIDRFC4122 is the validation function for validating if the field's value is a valid RFC4122 UUID of any version. func isUUIDRFC4122(fl FieldLevel) bool { return fieldMatchesRegexByStringerValOrString(uUIDRFC4122Regex, fl) } // isULID is the validation function for validating if the field's value is a valid ULID. func isULID(fl FieldLevel) bool { return fieldMatchesRegexByStringerValOrString(uLIDRegex, fl) } // isMD4 is the validation function for validating if the field's value is a valid MD4. func isMD4(fl FieldLevel) bool { return md4Regex().MatchString(fl.Field().String()) } // isMD5 is the validation function for validating if the field's value is a valid MD5. func isMD5(fl FieldLevel) bool { return md5Regex().MatchString(fl.Field().String()) } // isSHA256 is the validation function for validating if the field's value is a valid SHA256. func isSHA256(fl FieldLevel) bool { return sha256Regex().MatchString(fl.Field().String()) } // isSHA384 is the validation function for validating if the field's value is a valid SHA384. func isSHA384(fl FieldLevel) bool { return sha384Regex().MatchString(fl.Field().String()) } // isSHA512 is the validation function for validating if the field's value is a valid SHA512. func isSHA512(fl FieldLevel) bool { return sha512Regex().MatchString(fl.Field().String()) } // isRIPEMD128 is the validation function for validating if the field's value is a valid PIPEMD128. func isRIPEMD128(fl FieldLevel) bool { return ripemd128Regex().MatchString(fl.Field().String()) } // isRIPEMD160 is the validation function for validating if the field's value is a valid PIPEMD160. func isRIPEMD160(fl FieldLevel) bool { return ripemd160Regex().MatchString(fl.Field().String()) } // isTIGER128 is the validation function for validating if the field's value is a valid TIGER128. func isTIGER128(fl FieldLevel) bool { return tiger128Regex().MatchString(fl.Field().String()) } // isTIGER160 is the validation function for validating if the field's value is a valid TIGER160. func isTIGER160(fl FieldLevel) bool { return tiger160Regex().MatchString(fl.Field().String()) } // isTIGER192 is the validation function for validating if the field's value is a valid isTIGER192. func isTIGER192(fl FieldLevel) bool { return tiger192Regex().MatchString(fl.Field().String()) } // isISBN is the validation function for validating if the field's value is a valid v10 or v13 ISBN. func isISBN(fl FieldLevel) bool { return isISBN10(fl) || isISBN13(fl) } // isISBN13 is the validation function for validating if the field's value is a valid v13 ISBN. func isISBN13(fl FieldLevel) bool { s := strings.Replace(strings.Replace(fl.Field().String(), "-", "", 4), " ", "", 4) if !iSBN13Regex().MatchString(s) { return false } var checksum int32 var i int32 factor := []int32{1, 3} for i = 0; i < 12; i++ { checksum += factor[i%2] * int32(s[i]-'0') } return (int32(s[12]-'0'))-((10-(checksum%10))%10) == 0 } // isISBN10 is the validation function for validating if the field's value is a valid v10 ISBN. func isISBN10(fl FieldLevel) bool { s := strings.Replace(strings.Replace(fl.Field().String(), "-", "", 3), " ", "", 3) if !iSBN10Regex().MatchString(s) { return false } var checksum int32 var i int32 for i = 0; i < 9; i++ { checksum += (i + 1) * int32(s[i]-'0') } if s[9] == 'X' { checksum += 10 * 10 } else { checksum += 10 * int32(s[9]-'0') } return checksum%11 == 0 } // isISSN is the validation function for validating if the field's value is a valid ISSN. func isISSN(fl FieldLevel) bool { s := fl.Field().String() if !iSSNRegex().MatchString(s) { return false } s = strings.ReplaceAll(s, "-", "") pos := 8 checksum := 0 for i := 0; i < 7; i++ { checksum += pos * int(s[i]-'0') pos-- } if s[7] == 'X' { checksum += 10 } else { checksum += int(s[7] - '0') } return checksum%11 == 0 } // isEthereumAddress is the validation function for validating if the field's value is a valid Ethereum address. func isEthereumAddress(fl FieldLevel) bool { address := fl.Field().String() return ethAddressRegex().MatchString(address) } // isEthereumAddressChecksum is the validation function for validating if the field's value is a valid checksummed Ethereum address. func isEthereumAddressChecksum(fl FieldLevel) bool { address := fl.Field().String() if !ethAddressRegex().MatchString(address) { return false } // Checksum validation. Reference: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md address = address[2:] // Skip "0x" prefix. h := sha3.NewLegacyKeccak256() // hash.Hash's io.Writer implementation says it never returns an error. https://golang.org/pkg/hash/#Hash _, _ = h.Write([]byte(strings.ToLower(address))) hash := hex.EncodeToString(h.Sum(nil)) for i := 0; i < len(address); i++ { if address[i] <= '9' { // Skip 0-9 digits: they don't have upper/lower-case. continue } if hash[i] > '7' && address[i] >= 'a' || hash[i] <= '7' && address[i] <= 'F' { return false } } return true } // isBitcoinAddress is the validation function for validating if the field's value is a valid btc address func isBitcoinAddress(fl FieldLevel) bool { address := fl.Field().String() if !btcAddressRegex().MatchString(address) { return false } alphabet := []byte("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz") decode := [25]byte{} for _, n := range []byte(address) { d := bytes.IndexByte(alphabet, n) for i := 24; i >= 0; i-- { d += 58 * int(decode[i]) decode[i] = byte(d % 256) d /= 256 } } h := sha256.New() _, _ = h.Write(decode[:21]) d := h.Sum([]byte{}) h = sha256.New() _, _ = h.Write(d) validchecksum := [4]byte{} computedchecksum := [4]byte{} copy(computedchecksum[:], h.Sum(d[:0])) copy(validchecksum[:], decode[21:]) return validchecksum == computedchecksum } // isBitcoinBech32Address is the validation function for validating if the field's value is a valid bech32 btc address func isBitcoinBech32Address(fl FieldLevel) bool { address := fl.Field().String() if !btcLowerAddressRegexBech32().MatchString(address) && !btcUpperAddressRegexBech32().MatchString(address) { return false } am := len(address) % 8 if am == 0 || am == 3 || am == 5 { return false } address = strings.ToLower(address) alphabet := "qpzry9x8gf2tvdw0s3jn54khce6mua7l" hr := []int{3, 3, 0, 2, 3} // the human readable part will always be bc addr := address[3:] dp := make([]int, 0, len(addr)) for _, c := range addr { dp = append(dp, strings.IndexRune(alphabet, c)) } ver := dp[0] if ver < 0 || ver > 16 { return false } if ver == 0 { if len(address) != 42 && len(address) != 62 { return false } } values := append(hr, dp...) GEN := []int{0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3} p := 1 for _, v := range values { b := p >> 25 p = (p&0x1ffffff)<<5 ^ v for i := 0; i < 5; i++ { if (b>>uint(i))&1 == 1 { p ^= GEN[i] } } } if p != 1 { return false } b := uint(0) acc := 0 mv := (1 << 5) - 1 var sw []int for _, v := range dp[1 : len(dp)-6] { acc = (acc << 5) | v b += 5 for b >= 8 { b -= 8 sw = append(sw, (acc>>b)&mv) } } if len(sw) < 2 || len(sw) > 40 { return false } return true } // excludesRune is the validation function for validating that the field's value does not contain the rune specified within the param. func excludesRune(fl FieldLevel) bool { return !containsRune(fl) } // excludesAll is the validation function for validating that the field's value does not contain any of the characters specified within the param. func excludesAll(fl FieldLevel) bool { return !containsAny(fl) } // excludes is the validation function for validating that the field's value does not contain the text specified within the param. func excludes(fl FieldLevel) bool { return !contains(fl) } // containsRune is the validation function for validating that the field's value contains the rune specified within the param. func containsRune(fl FieldLevel) bool { r, _ := utf8.DecodeRuneInString(fl.Param()) return strings.ContainsRune(fl.Field().String(), r) } // containsAny is the validation function for validating that the field's value contains any of the characters specified within the param. func containsAny(fl FieldLevel) bool { return strings.ContainsAny(fl.Field().String(), fl.Param()) } // contains is the validation function for validating that the field's value contains the text specified within the param. func contains(fl FieldLevel) bool { return strings.Contains(fl.Field().String(), fl.Param()) } // startsWith is the validation function for validating that the field's value starts with the text specified within the param. func startsWith(fl FieldLevel) bool { return strings.HasPrefix(fl.Field().String(), fl.Param()) } // endsWith is the validation function for validating that the field's value ends with the text specified within the param. func endsWith(fl FieldLevel) bool { return strings.HasSuffix(fl.Field().String(), fl.Param()) } // startsNotWith is the validation function for validating that the field's value does not start with the text specified within the param. func startsNotWith(fl FieldLevel) bool { return !startsWith(fl) } // endsNotWith is the validation function for validating that the field's value does not end with the text specified within the param. func endsNotWith(fl FieldLevel) bool { return !endsWith(fl) } // fieldContains is the validation function for validating if the current field's value contains the field specified by the param's value. func fieldContains(fl FieldLevel) bool { field := fl.Field() currentField, _, ok := fl.GetStructFieldOK() if !ok { return false } return strings.Contains(field.String(), currentField.String()) } // fieldExcludes is the validation function for validating if the current field's value excludes the field specified by the param's value. func fieldExcludes(fl FieldLevel) bool { field := fl.Field() currentField, _, ok := fl.GetStructFieldOK() if !ok { return true } return !strings.Contains(field.String(), currentField.String()) } // isNeField is the validation function for validating if the current field's value is not equal to the field specified by the param's value. func isNeField(fl FieldLevel) bool { field := fl.Field() kind := field.Kind() currentField, currentKind, ok := fl.GetStructFieldOK() if !ok || currentKind != kind { return true } switch kind { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return field.Int() != currentField.Int() case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return field.Uint() != currentField.Uint() case reflect.Float32, reflect.Float64: return field.Float() != currentField.Float() case reflect.Slice, reflect.Map, reflect.Array: return int64(field.Len()) != int64(currentField.Len()) case reflect.Bool: return field.Bool() != currentField.Bool() case reflect.Struct: fieldType := field.Type() if fieldType.ConvertibleTo(timeType) && currentField.Type().ConvertibleTo(timeType) { t := getValue(currentField).(time.Time) fieldTime := getValue(field).(time.Time) return !fieldTime.Equal(t) } // Not Same underlying type i.e. struct and time if fieldType != currentField.Type() { return true } } // default reflect.String: return field.String() != currentField.String() } // isNe is the validation function for validating that the field's value does not equal the provided param value. func isNe(fl FieldLevel) bool { return !isEq(fl) } // isNeIgnoreCase is the validation function for validating that the field's string value does not equal the // provided param value. The comparison is case-insensitive func isNeIgnoreCase(fl FieldLevel) bool { return !isEqIgnoreCase(fl) } // isLteCrossStructField is the validation function for validating if the current field's value is less than or equal to the field, within a separate struct, specified by the param's value. func isLteCrossStructField(fl FieldLevel) bool { field := fl.Field() kind := field.Kind() topField, topKind, ok := fl.GetStructFieldOK() if !ok || topKind != kind { return false } switch kind { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return field.Int() <= topField.Int() case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return field.Uint() <= topField.Uint() case reflect.Float32, reflect.Float64: return field.Float() <= topField.Float() case reflect.Slice, reflect.Map, reflect.Array: return int64(field.Len()) <= int64(topField.Len()) case reflect.Struct: fieldType := field.Type() if fieldType.ConvertibleTo(timeType) && topField.Type().ConvertibleTo(timeType) { fieldTime := getValue(field.Convert(timeType)).(time.Time) topTime := getValue(topField.Convert(timeType)).(time.Time) return fieldTime.Before(topTime) || fieldTime.Equal(topTime) } // Not Same underlying type i.e. struct and time if fieldType != topField.Type() { return false } } // default reflect.String: return field.String() <= topField.String() } // isLtCrossStructField is the validation function for validating if the current field's value is less than the field, within a separate struct, specified by the param's value. // NOTE: This is exposed for use within your own custom functions and not intended to be called directly. func isLtCrossStructField(fl FieldLevel) bool { field := fl.Field() kind := field.Kind() topField, topKind, ok := fl.GetStructFieldOK() if !ok || topKind != kind { return false } switch kind { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return field.Int() < topField.Int() case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return field.Uint() < topField.Uint() case reflect.Float32, reflect.Float64: return field.Float() < topField.Float() case reflect.Slice, reflect.Map, reflect.Array: return int64(field.Len()) < int64(topField.Len()) case reflect.Struct: fieldType := field.Type() if fieldType.ConvertibleTo(timeType) && topField.Type().ConvertibleTo(timeType) { fieldTime := getValue(field.Convert(timeType)).(time.Time) topTime := getValue(topField.Convert(timeType)).(time.Time) return fieldTime.Before(topTime) } // Not Same underlying type i.e. struct and time if fieldType != topField.Type() { return false } } // default reflect.String: return field.String() < topField.String() } // isGteCrossStructField is the validation function for validating if the current field's value is greater than or equal to the field, within a separate struct, specified by the param's value. func isGteCrossStructField(fl FieldLevel) bool { field := fl.Field() kind := field.Kind() topField, topKind, ok := fl.GetStructFieldOK() if !ok || topKind != kind { return false } switch kind { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return field.Int() >= topField.Int() case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return field.Uint() >= topField.Uint() case reflect.Float32, reflect.Float64: return field.Float() >= topField.Float() case reflect.Slice, reflect.Map, reflect.Array: return int64(field.Len()) >= int64(topField.Len()) case reflect.Struct: fieldType := field.Type() if fieldType.ConvertibleTo(timeType) && topField.Type().ConvertibleTo(timeType) { fieldTime := getValue(field.Convert(timeType)).(time.Time) topTime := getValue(topField.Convert(timeType)).(time.Time) return fieldTime.After(topTime) || fieldTime.Equal(topTime) } // Not Same underlying type i.e. struct and time if fieldType != topField.Type() { return false } } // default reflect.String: return field.String() >= topField.String() } // isGtCrossStructField is the validation function for validating if the current field's value is greater than the field, within a separate struct, specified by the param's value. func isGtCrossStructField(fl FieldLevel) bool { field := fl.Field() kind := field.Kind() topField, topKind, ok := fl.GetStructFieldOK() if !ok || topKind != kind { return false } switch kind { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return field.Int() > topField.Int() case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return field.Uint() > topField.Uint() case reflect.Float32, reflect.Float64: return field.Float() > topField.Float() case reflect.Slice, reflect.Map, reflect.Array: return int64(field.Len()) > int64(topField.Len()) case reflect.Struct: fieldType := field.Type() if fieldType.ConvertibleTo(timeType) && topField.Type().ConvertibleTo(timeType) { fieldTime := getValue(field.Convert(timeType)).(time.Time) topTime := getValue(topField.Convert(timeType)).(time.Time) return fieldTime.After(topTime) } // Not Same underlying type i.e. struct and time if fieldType != topField.Type() { return false } } // default reflect.String: return field.String() > topField.String() } // isNeCrossStructField is the validation function for validating that the current field's value is not equal to the field, within a separate struct, specified by the param's value. func isNeCrossStructField(fl FieldLevel) bool { field := fl.Field() kind := field.Kind() topField, currentKind, ok := fl.GetStructFieldOK() if !ok || currentKind != kind { return true } switch kind { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return topField.Int() != field.Int() case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return topField.Uint() != field.Uint() case reflect.Float32, reflect.Float64: return topField.Float() != field.Float() case reflect.Slice, reflect.Map, reflect.Array: return int64(topField.Len()) != int64(field.Len()) case reflect.Bool: return topField.Bool() != field.Bool() case reflect.Struct: fieldType := field.Type() if fieldType.ConvertibleTo(timeType) && topField.Type().ConvertibleTo(timeType) { t := getValue(field.Convert(timeType)).(time.Time) fieldTime := getValue(topField.Convert(timeType)).(time.Time) return !fieldTime.Equal(t) } // Not Same underlying type i.e. struct and time if fieldType != topField.Type() { return true } } // default reflect.String: return topField.String() != field.String() } // isEqCrossStructField is the validation function for validating that the current field's value is equal to the field, within a separate struct, specified by the param's value. func isEqCrossStructField(fl FieldLevel) bool { field := fl.Field() kind := field.Kind() topField, topKind, ok := fl.GetStructFieldOK() if !ok || topKind != kind { return false } switch kind { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return topField.Int() == field.Int() case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return topField.Uint() == field.Uint() case reflect.Float32, reflect.Float64: return topField.Float() == field.Float() case reflect.Slice, reflect.Map, reflect.Array: return int64(topField.Len()) == int64(field.Len()) case reflect.Bool: return topField.Bool() == field.Bool() case reflect.Struct: fieldType := field.Type() if fieldType.ConvertibleTo(timeType) && topField.Type().ConvertibleTo(timeType) { t := getValue(field.Convert(timeType)).(time.Time) fieldTime := getValue(topField.Convert(timeType)).(time.Time) return fieldTime.Equal(t) } // Not Same underlying type i.e. struct and time if fieldType != topField.Type() { return false } } // default reflect.String: return topField.String() == field.String() } // isEqField is the validation function for validating if the current field's value is equal to the field specified by the param's value. func isEqField(fl FieldLevel) bool { field := fl.Field() kind := field.Kind() currentField, currentKind, ok := fl.GetStructFieldOK() if !ok || currentKind != kind { return false } switch kind { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return field.Int() == currentField.Int() case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return field.Uint() == currentField.Uint() case reflect.Float32, reflect.Float64: return field.Float() == currentField.Float() case reflect.Slice, reflect.Map, reflect.Array: return int64(field.Len()) == int64(currentField.Len()) case reflect.Bool: return field.Bool() == currentField.Bool() case reflect.Struct: fieldType := field.Type() if fieldType.ConvertibleTo(timeType) && currentField.Type().ConvertibleTo(timeType) { t := getValue(currentField.Convert(timeType)).(time.Time) fieldTime := getValue(field.Convert(timeType)).(time.Time) return fieldTime.Equal(t) } // Not Same underlying type i.e. struct and time if fieldType != currentField.Type() { return false } } // default reflect.String: return field.String() == currentField.String() } // isEq is the validation function for validating if the current field's value is equal to the param's value. func isEq(fl FieldLevel) bool { field := fl.Field() param := fl.Param() switch field.Kind() { case reflect.String: return field.String() == param case reflect.Slice, reflect.Map, reflect.Array: p := asInt(param) return int64(field.Len()) == p case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: p := asIntFromType(field.Type(), param) return field.Int() == p case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: p := asUint(param) return field.Uint() == p case reflect.Float32: p := asFloat32(param) return field.Float() == p case reflect.Float64: p := asFloat64(param) return field.Float() == p case reflect.Bool: p := asBool(param) return field.Bool() == p } panic(fmt.Sprintf("Bad field type %s", field.Type())) } // isEqIgnoreCase is the validation function for validating if the current field's string value is // equal to the param's value. // The comparison is case-insensitive. func isEqIgnoreCase(fl FieldLevel) bool { field := fl.Field() param := fl.Param() switch field.Kind() { case reflect.String: return strings.EqualFold(field.String(), param) } panic(fmt.Sprintf("Bad field type %s", field.Type())) } // isPostcodeByIso3166Alpha2 validates by value which is country code in iso 3166 alpha 2 // example: `postcode_iso3166_alpha2=US` func isPostcodeByIso3166Alpha2(fl FieldLevel) bool { field := fl.Field() param := fl.Param() postcodeRegexInit.Do(initPostcodes) reg, found := postCodeRegexDict[param] if !found { return false } return reg.MatchString(field.String()) } // isPostcodeByIso3166Alpha2Field validates by field which represents for a value of country code in iso 3166 alpha 2 // example: `postcode_iso3166_alpha2_field=CountryCode` func isPostcodeByIso3166Alpha2Field(fl FieldLevel) bool { field := fl.Field() params := parseOneOfParam2(fl.Param()) if len(params) != 1 { return false } currentField, kind, _, found := fl.GetStructFieldOKAdvanced2(fl.Parent(), params[0]) if !found { return false } if kind != reflect.String { panic(fmt.Sprintf("Bad field type %s", currentField.Type())) } postcodeRegexInit.Do(initPostcodes) reg, found := postCodeRegexDict[currentField.String()] if !found { return false } return reg.MatchString(field.String()) } // isBase32 is the validation function for validating if the current field's value is a valid base 32. func isBase32(fl FieldLevel) bool { return base32Regex().MatchString(fl.Field().String()) } // isBase64 is the validation function for validating if the current field's value is a valid base 64. func isBase64(fl FieldLevel) bool { return base64Regex().MatchString(fl.Field().String()) } // isBase64URL is the validation function for validating if the current field's value is a valid base64 URL safe string. func isBase64URL(fl FieldLevel) bool { return base64URLRegex().MatchString(fl.Field().String()) } // isBase64RawURL is the validation function for validating if the current field's value is a valid base64 URL safe string without '=' padding. func isBase64RawURL(fl FieldLevel) bool { return base64RawURLRegex().MatchString(fl.Field().String()) } // isURI is the validation function for validating if the current field's value is a valid URI. func isURI(fl FieldLevel) bool { field := fl.Field() switch field.Kind() { case reflect.String: s := field.String() // checks needed as of Go 1.6 because of change https://github.com/golang/go/commit/617c93ce740c3c3cc28cdd1a0d712be183d0b328#diff-6c2d018290e298803c0c9419d8739885L195 // emulate browser and strip the '#' suffix prior to validation. see issue-#237 if i := strings.Index(s, "#"); i > -1 { s = s[:i] } if len(s) == 0 { return false } _, err := url.ParseRequestURI(s) return err == nil } panic(fmt.Sprintf("Bad field type %s", field.Type())) } // isURL is the validation function for validating if the current field's value is a valid URL. func isURL(fl FieldLevel) bool { field := fl.Field() switch field.Kind() { case reflect.String: s := strings.ToLower(field.String()) if len(s) == 0 { return false } url, err := url.Parse(s) if err != nil || url.Scheme == "" { return false } isFileScheme := url.Scheme == "file" if (isFileScheme && (len(url.Path) == 0 || url.Path == "/")) || (!isFileScheme && len(url.Host) == 0 && len(url.Fragment) == 0 && len(url.Opaque) == 0) { return false } return true } panic(fmt.Sprintf("Bad field type %s", field.Type())) } // isHttpURL is the validation function for validating if the current field's value is a valid HTTP(s) URL. func isHttpURL(fl FieldLevel) bool { if !isURL(fl) { return false } field := fl.Field() switch field.Kind() { case reflect.String: s := strings.ToLower(field.String()) url, err := url.Parse(s) if err != nil || url.Host == "" { return false } return url.Scheme == "http" || url.Scheme == "https" } panic(fmt.Sprintf("Bad field type %s", field.Type())) } // isHttpsURL is the validation function for validating if the current field's value is a valid HTTPS-only URL. func isHttpsURL(fl FieldLevel) bool { if !isURL(fl) { return false } field := fl.Field() switch field.Kind() { case reflect.String: s := strings.ToLower(field.String()) url, err := url.Parse(s) if err != nil || url.Host == "" { return false } return url.Scheme == "https" } panic(fmt.Sprintf("Bad field type %s", field.Type())) } // isUrnRFC2141 is the validation function for validating if the current field's value is a valid URN as per RFC 2141. func isUrnRFC2141(fl FieldLevel) bool { field := fl.Field() switch field.Kind() { case reflect.String: str := field.String() _, match := urn.Parse([]byte(str)) return match } panic(fmt.Sprintf("Bad field type %s", field.Type())) } // isFile is the validation function for validating if the current field's value is a valid existing file path. func isFile(fl FieldLevel) bool { field := fl.Field() switch field.Kind() { case reflect.String: fileInfo, err := os.Stat(field.String()) if err != nil { return false } return !fileInfo.IsDir() } panic(fmt.Sprintf("Bad field type %s", field.Type())) } // isImage is the validation function for validating if the current field's value contains the path to a valid image file func isImage(fl FieldLevel) bool { mimetypes := map[string]bool{ "image/bmp": true, "image/cis-cod": true, "image/gif": true, "image/ief": true, "image/jpeg": true, "image/jp2": true, "image/jpx": true, "image/jpm": true, "image/pipeg": true, "image/png": true, "image/svg+xml": true, "image/tiff": true, "image/webp": true, "image/x-cmu-raster": true, "image/x-cmx": true, "image/x-icon": true, "image/x-portable-anymap": true, "image/x-portable-bitmap": true, "image/x-portable-graymap": true, "image/x-portable-pixmap": true, "image/x-rgb": true, "image/x-xbitmap": true, "image/x-xpixmap": true, "image/x-xwindowdump": true, } field := fl.Field() switch field.Kind() { case reflect.String: filePath := field.String() fileInfo, err := os.Stat(filePath) if err != nil { return false } if fileInfo.IsDir() { return false } file, err := os.Open(filePath) if err != nil { return false } defer func() { _ = file.Close() }() mime, err := mimetype.DetectReader(file) if err != nil { return false } if _, ok := mimetypes[mime.String()]; ok { return true } } panic(fmt.Sprintf("Bad field type %s", field.Type())) } // isFilePath is the validation function for validating if the current field's value is a valid file path. func isFilePath(fl FieldLevel) bool { var exists bool var err error field := fl.Field() // Not valid if it is a directory. if isDir(fl) { return false } // If it exists, it obviously is valid. // This is done first to avoid code duplication and unnecessary additional logic. if exists = isFile(fl); exists { return true } // It does not exist but may still be a valid filepath. switch field.Kind() { case reflect.String: // Every OS allows for whitespace, but none // let you use a file with no filename (to my knowledge). // Unless you're dealing with raw inodes, but I digress. if strings.TrimSpace(field.String()) == "" { return false } // We make sure it isn't a directory. if strings.HasSuffix(field.String(), string(os.PathSeparator)) { return false } if _, err = os.Stat(field.String()); err != nil { switch t := err.(type) { case *fs.PathError: if t.Err == syscall.EINVAL { // It's definitely an invalid character in the filepath. return false } // It could be a permission error, a does-not-exist error, etc. // Out-of-scope for this validation, though. return true default: // Something went *seriously* wrong. /* Per https://pkg.go.dev/os#Stat: "If there is an error, it will be of type *PathError." */ panic(err) } } } panic(fmt.Sprintf("Bad field type %s", field.Type())) } // isE164 is the validation function for validating if the current field's value is a valid e.164 formatted phone number. func isE164(fl FieldLevel) bool { return e164Regex().MatchString(fl.Field().String()) } // isEmail is the validation function for validating if the current field's value is a valid email address. func isEmail(fl FieldLevel) bool { _, err := mail.ParseAddress(fl.Field().String()) if err != nil { return false } return emailRegex().MatchString(fl.Field().String()) } // isHSLA is the validation function for validating if the current field's value is a valid HSLA color. func isHSLA(fl FieldLevel) bool { return hslaRegex().MatchString(fl.Field().String()) } // isHSL is the validation function for validating if the current field's value is a valid HSL color. func isHSL(fl FieldLevel) bool { return hslRegex().MatchString(fl.Field().String()) } // isRGBA is the validation function for validating if the current field's value is a valid RGBA color. func isRGBA(fl FieldLevel) bool { return rgbaRegex().MatchString(fl.Field().String()) } // isRGB is the validation function for validating if the current field's value is a valid RGB color. func isRGB(fl FieldLevel) bool { return rgbRegex().MatchString(fl.Field().String()) } // isHEXColor is the validation function for validating if the current field's value is a valid HEX color. func isHEXColor(fl FieldLevel) bool { return hexColorRegex().MatchString(fl.Field().String()) } // isHexadecimal is the validation function for validating if the current field's value is a valid hexadecimal. func isHexadecimal(fl FieldLevel) bool { return hexadecimalRegex().MatchString(fl.Field().String()) } // isNumber is the validation function for validating if the current field's value is a valid number. func isNumber(fl FieldLevel) bool { switch fl.Field().Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, reflect.Float32, reflect.Float64: return true default: return numberRegex().MatchString(fl.Field().String()) } } // isNumeric is the validation function for validating if the current field's value is a valid numeric value. func isNumeric(fl FieldLevel) bool { switch fl.Field().Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, reflect.Float32, reflect.Float64: return true default: return numericRegex().MatchString(fl.Field().String()) } } // isAlphanum is the validation function for validating if the current field's value is a valid alphanumeric value. func isAlphanum(fl FieldLevel) bool { return alphaNumericRegex().MatchString(fl.Field().String()) } // isAlpha is the validation function for validating if the current field's value is a valid alpha value. func isAlpha(fl FieldLevel) bool { return alphaRegex().MatchString(fl.Field().String()) } // isAlphanumUnicode is the validation function for validating if the current field's value is a valid alphanumeric unicode value. func isAlphanumUnicode(fl FieldLevel) bool { return alphaUnicodeNumericRegex().MatchString(fl.Field().String()) } // isAlphaSpace is the validation function for validating if the current field's value is a valid alpha value with spaces. func isAlphaSpace(fl FieldLevel) bool { return alphaSpaceRegex().MatchString(fl.Field().String()) } // isAlphaNumericSpace is the validation function for validating if the current field's value is a valid alphanumeric value with spaces. func isAlphaNumericSpace(fl FieldLevel) bool { return alphanNumericSpaceRegex().MatchString(fl.Field().String()) } // isAlphaUnicode is the validation function for validating if the current field's value is a valid alpha unicode value. func isAlphaUnicode(fl FieldLevel) bool { return alphaUnicodeRegex().MatchString(fl.Field().String()) } // isBoolean is the validation function for validating if the current field's value is a valid boolean value or can be safely converted to a boolean value. func isBoolean(fl FieldLevel) bool { switch fl.Field().Kind() { case reflect.Bool: return true default: _, err := strconv.ParseBool(fl.Field().String()) return err == nil } } // isDefault is the opposite of required aka hasValue func isDefault(fl FieldLevel) bool { return !hasValue(fl) } // hasValue is the validation function for validating if the current field's value is not the default static value. func hasValue(fl FieldLevel) bool { field := fl.Field() switch field.Kind() { case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func: return !field.IsNil() default: if fl.(*validate).fldIsPointer && getValue(field) != nil { return true } return field.IsValid() && !field.IsZero() } } // hasNotZeroValue is the validation function for validating if the current field's value is not the zero value for its type. func hasNotZeroValue(fl FieldLevel) bool { field := fl.Field() switch field.Kind() { case reflect.Slice, reflect.Map: // For slices and maps, consider them "not zero" only if they're both non-nil AND have elements return !field.IsNil() && field.Len() > 0 case reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func: return !field.IsNil() default: if fl.(*validate).fldIsPointer && getValue(field) != nil { return !field.IsZero() } return field.IsValid() && !field.IsZero() } } // requireCheckFieldKind is a func for check field kind func requireCheckFieldKind(fl FieldLevel, param string, defaultNotFoundValue bool) bool { field := fl.Field() kind := field.Kind() var nullable, found bool if len(param) > 0 { field, kind, nullable, found = fl.GetStructFieldOKAdvanced2(fl.Parent(), param) if !found { return defaultNotFoundValue } } switch kind { case reflect.Invalid: return defaultNotFoundValue case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func: return field.IsNil() default: if nullable && getValue(field) != nil { return false } return field.IsValid() && field.IsZero() } } // requireCheckFieldValue is a func for check field value func requireCheckFieldValue( fl FieldLevel, param string, value string, defaultNotFoundValue bool, ) bool { field, kind, _, found := fl.GetStructFieldOKAdvanced2(fl.Parent(), param) if !found { return defaultNotFoundValue } switch kind { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return field.Int() == asInt(value) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return field.Uint() == asUint(value) case reflect.Float32: return field.Float() == asFloat32(value) case reflect.Float64: return field.Float() == asFloat64(value) case reflect.Slice, reflect.Map: if value == "nil" { return field.IsNil() } return int64(field.Len()) == asInt(value) case reflect.Array: // Arrays can't be nil, so only compare lengths return int64(field.Len()) == asInt(value) case reflect.Bool: return field.Bool() == (value == "true") case reflect.Ptr: if field.IsNil() { return value == "nil" } // Handle non-nil pointers return requireCheckFieldValue(fl, param, value, defaultNotFoundValue) } // default reflect.String: return field.String() == value } // requiredIf is the validation function // The field under validation must be present and not empty only if all the other specified fields are equal to the value following with the specified field. func requiredIf(fl FieldLevel) bool { params := parseOneOfParam2(fl.Param()) if len(params)%2 != 0 { panic(fmt.Sprintf("Bad param number for required_if %s", fl.FieldName())) } seen := make(map[string]struct{}) for i := 0; i < len(params); i += 2 { if _, ok := seen[params[i]]; ok { panic(fmt.Sprintf("Duplicate param %s for required_if %s", params[i], fl.FieldName())) } seen[params[i]] = struct{}{} } for i := 0; i < len(params); i += 2 { if !requireCheckFieldValue(fl, params[i], params[i+1], false) { return true } } return hasValue(fl) } // excludedIf is the validation function // The field under validation must not be present or is empty only if all the other specified fields are equal to the value following with the specified field. func excludedIf(fl FieldLevel) bool { params := parseOneOfParam2(fl.Param()) if len(params)%2 != 0 { panic(fmt.Sprintf("Bad param number for excluded_if %s", fl.FieldName())) } for i := 0; i < len(params); i += 2 { if !requireCheckFieldValue(fl, params[i], params[i+1], false) { return true } } return !hasValue(fl) } // requiredUnless is the validation function // The field under validation must be present and not empty only unless all the other specified fields are equal to the value following with the specified field. func requiredUnless(fl FieldLevel) bool { params := parseOneOfParam2(fl.Param()) if len(params)%2 != 0 { panic(fmt.Sprintf("Bad param number for required_unless %s", fl.FieldName())) } for i := 0; i < len(params); i += 2 { if requireCheckFieldValue(fl, params[i], params[i+1], false) { return true } } return hasValue(fl) } // skipUnless is the validation function // The field under validation must be present and not empty only unless all the other specified fields are equal to the value following with the specified field. func skipUnless(fl FieldLevel) bool { params := parseOneOfParam2(fl.Param()) if len(params)%2 != 0 { panic(fmt.Sprintf("Bad param number for skip_unless %s", fl.FieldName())) } for i := 0; i < len(params); i += 2 { if !requireCheckFieldValue(fl, params[i], params[i+1], false) { return true } } return hasValue(fl) } // excludedUnless is the validation function // The field under validation must not be present or is empty unless all the other specified fields are equal to the value following with the specified field. func excludedUnless(fl FieldLevel) bool { params := parseOneOfParam2(fl.Param()) if len(params)%2 != 0 { panic(fmt.Sprintf("Bad param number for excluded_unless %s", fl.FieldName())) } for i := 0; i < len(params); i += 2 { if requireCheckFieldValue(fl, params[i], params[i+1], false) { return true } } return !hasValue(fl) } // excludedWith is the validation function // The field under validation must not be present or is empty if any of the other specified fields are present. func excludedWith(fl FieldLevel) bool { params := parseOneOfParam2(fl.Param()) for _, param := range params { if !requireCheckFieldKind(fl, param, true) { return !hasValue(fl) } } return true } // requiredWith is the validation function // The field under validation must be present and not empty only if any of the other specified fields are present. func requiredWith(fl FieldLevel) bool { params := parseOneOfParam2(fl.Param()) for _, param := range params { if !requireCheckFieldKind(fl, param, true) { return hasValue(fl) } } return true } // excludedWithAll is the validation function // The field under validation must not be present or is empty if all of the other specified fields are present. func excludedWithAll(fl FieldLevel) bool { params := parseOneOfParam2(fl.Param()) for _, param := range params { if requireCheckFieldKind(fl, param, true) { return true } } return !hasValue(fl) } // requiredWithAll is the validation function // The field under validation must be present and not empty only if all of the other specified fields are present. func requiredWithAll(fl FieldLevel) bool { params := parseOneOfParam2(fl.Param()) for _, param := range params { if requireCheckFieldKind(fl, param, true) { return true } } return hasValue(fl) } // excludedWithout is the validation function // The field under validation must not be present or is empty when any of the other specified fields are not present. func excludedWithout(fl FieldLevel) bool { if requireCheckFieldKind(fl, strings.TrimSpace(fl.Param()), true) { return !hasValue(fl) } return true } // requiredWithout is the validation function // The field under validation must be present and not empty only when any of the other specified fields are not present. func requiredWithout(fl FieldLevel) bool { params := parseOneOfParam2(fl.Param()) for _, param := range params { if requireCheckFieldKind(fl, param, true) { return hasValue(fl) } } return true } // excludedWithoutAll is the validation function // The field under validation must not be present or is empty when all of the other specified fields are not present. func excludedWithoutAll(fl FieldLevel) bool { params := parseOneOfParam2(fl.Param()) for _, param := range params { if !requireCheckFieldKind(fl, param, true) { return true } } return !hasValue(fl) } // requiredWithoutAll is the validation function // The field under validation must be present and not empty only when all of the other specified fields are not present. func requiredWithoutAll(fl FieldLevel) bool { params := parseOneOfParam2(fl.Param()) for _, param := range params { if !requireCheckFieldKind(fl, param, true) { return true } } return hasValue(fl) } // isGteField is the validation function for validating if the current field's value is greater than or equal to the field specified by the param's value. func isGteField(fl FieldLevel) bool { field := fl.Field() kind := field.Kind() currentField, currentKind, ok := fl.GetStructFieldOK() if !ok || currentKind != kind { return false } switch kind { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return field.Int() >= currentField.Int() case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return field.Uint() >= currentField.Uint() case reflect.Float32, reflect.Float64: return field.Float() >= currentField.Float() case reflect.Struct: fieldType := field.Type() if fieldType.ConvertibleTo(timeType) && currentField.Type().ConvertibleTo(timeType) { t := getValue(currentField.Convert(timeType)).(time.Time) fieldTime := getValue(field.Convert(timeType)).(time.Time) return fieldTime.After(t) || fieldTime.Equal(t) } // Not Same underlying type i.e. struct and time if fieldType != currentField.Type() { return false } } // default reflect.String return len(field.String()) >= len(currentField.String()) } // isGtField is the validation function for validating if the current field's value is greater than the field specified by the param's value. func isGtField(fl FieldLevel) bool { field := fl.Field() kind := field.Kind() currentField, currentKind, ok := fl.GetStructFieldOK() if !ok || currentKind != kind { return false } switch kind { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return field.Int() > currentField.Int() case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return field.Uint() > currentField.Uint() case reflect.Float32, reflect.Float64: return field.Float() > currentField.Float() case reflect.Struct: fieldType := field.Type() if fieldType.ConvertibleTo(timeType) && currentField.Type().ConvertibleTo(timeType) { t := getValue(currentField.Convert(timeType)).(time.Time) fieldTime := getValue(field.Convert(timeType)).(time.Time) return fieldTime.After(t) } // Not Same underlying type i.e. struct and time if fieldType != currentField.Type() { return false } } // default reflect.String return len(field.String()) > len(currentField.String()) } // isGte is the validation function for validating if the current field's value is greater than or equal to the param's value. func isGte(fl FieldLevel) bool { field := fl.Field() param := fl.Param() switch field.Kind() { case reflect.String: p := asInt(param) return int64(utf8.RuneCountInString(field.String())) >= p case reflect.Slice, reflect.Map, reflect.Array: p := asInt(param) return int64(field.Len()) >= p case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: p := asIntFromType(field.Type(), param) return field.Int() >= p case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: p := asUint(param) return field.Uint() >= p case reflect.Float32: p := asFloat32(param) return field.Float() >= p case reflect.Float64: p := asFloat64(param) return field.Float() >= p case reflect.Struct: if field.Type().ConvertibleTo(timeType) { now := time.Now().UTC() t := getValue(field.Convert(timeType)).(time.Time) return t.After(now) || t.Equal(now) } } panic(fmt.Sprintf("Bad field type %s", field.Type())) } // isGt is the validation function for validating if the current field's value is greater than the param's value. func isGt(fl FieldLevel) bool { field := fl.Field() param := fl.Param() switch field.Kind() { case reflect.String: p := asInt(param) return int64(utf8.RuneCountInString(field.String())) > p case reflect.Slice, reflect.Map, reflect.Array: p := asInt(param) return int64(field.Len()) > p case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: p := asIntFromType(field.Type(), param) return field.Int() > p case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: p := asUint(param) return field.Uint() > p case reflect.Float32: p := asFloat32(param) return field.Float() > p case reflect.Float64: p := asFloat64(param) return field.Float() > p case reflect.Struct: if field.Type().ConvertibleTo(timeType) { return getValue(field.Convert(timeType)).(time.Time).After(time.Now().UTC()) } } panic(fmt.Sprintf("Bad field type %s", field.Type())) } // hasLengthOf is the validation function for validating if the current field's value is equal to the param's value. func hasLengthOf(fl FieldLevel) bool { field := fl.Field() param := fl.Param() switch field.Kind() { case reflect.String: p := asInt(param) return int64(utf8.RuneCountInString(field.String())) == p case reflect.Slice, reflect.Map, reflect.Array: p := asInt(param) return int64(field.Len()) == p case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: p := asIntFromType(field.Type(), param) return field.Int() == p case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: p := asUint(param) return field.Uint() == p case reflect.Float32: p := asFloat32(param) return field.Float() == p case reflect.Float64: p := asFloat64(param) return field.Float() == p } panic(fmt.Sprintf("Bad field type %s", field.Type())) } // hasMinOf is the validation function for validating if the current field's value is greater than or equal to the param's value. func hasMinOf(fl FieldLevel) bool { return isGte(fl) } // isLteField is the validation function for validating if the current field's value is less than or equal to the field specified by the param's value. func isLteField(fl FieldLevel) bool { field := fl.Field() kind := field.Kind() currentField, currentKind, ok := fl.GetStructFieldOK() if !ok || currentKind != kind { return false } switch kind { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return field.Int() <= currentField.Int() case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return field.Uint() <= currentField.Uint() case reflect.Float32, reflect.Float64: return field.Float() <= currentField.Float() case reflect.Struct: fieldType := field.Type() if fieldType.ConvertibleTo(timeType) && currentField.Type().ConvertibleTo(timeType) { t := getValue(currentField.Convert(timeType)).(time.Time) fieldTime := getValue(field.Convert(timeType)).(time.Time) return fieldTime.Before(t) || fieldTime.Equal(t) } // Not Same underlying type i.e. struct and time if fieldType != currentField.Type() { return false } } // default reflect.String return len(field.String()) <= len(currentField.String()) } // isLtField is the validation function for validating if the current field's value is less than the field specified by the param's value. func isLtField(fl FieldLevel) bool { field := fl.Field() kind := field.Kind() currentField, currentKind, ok := fl.GetStructFieldOK() if !ok || currentKind != kind { return false } switch kind { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return field.Int() < currentField.Int() case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return field.Uint() < currentField.Uint() case reflect.Float32, reflect.Float64: return field.Float() < currentField.Float() case reflect.Struct: fieldType := field.Type() if fieldType.ConvertibleTo(timeType) && currentField.Type().ConvertibleTo(timeType) { t := getValue(currentField.Convert(timeType)).(time.Time) fieldTime := getValue(field.Convert(timeType)).(time.Time) return fieldTime.Before(t) } // Not Same underlying type i.e. struct and time if fieldType != currentField.Type() { return false } } // default reflect.String return len(field.String()) < len(currentField.String()) } // isLte is the validation function for validating if the current field's value is less than or equal to the param's value. func isLte(fl FieldLevel) bool { field := fl.Field() param := fl.Param() switch field.Kind() { case reflect.String: p := asInt(param) return int64(utf8.RuneCountInString(field.String())) <= p case reflect.Slice, reflect.Map, reflect.Array: p := asInt(param) return int64(field.Len()) <= p case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: p := asIntFromType(field.Type(), param) return field.Int() <= p case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: p := asUint(param) return field.Uint() <= p case reflect.Float32: p := asFloat32(param) return field.Float() <= p case reflect.Float64: p := asFloat64(param) return field.Float() <= p case reflect.Struct: if field.Type().ConvertibleTo(timeType) { now := time.Now().UTC() t := getValue(field.Convert(timeType)).(time.Time) return t.Before(now) || t.Equal(now) } } panic(fmt.Sprintf("Bad field type %s", field.Type())) } // isLt is the validation function for validating if the current field's value is less than the param's value. func isLt(fl FieldLevel) bool { field := fl.Field() param := fl.Param() switch field.Kind() { case reflect.String: p := asInt(param) return int64(utf8.RuneCountInString(field.String())) < p case reflect.Slice, reflect.Map, reflect.Array: p := asInt(param) return int64(field.Len()) < p case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: p := asIntFromType(field.Type(), param) return field.Int() < p case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: p := asUint(param) return field.Uint() < p case reflect.Float32: p := asFloat32(param) return field.Float() < p case reflect.Float64: p := asFloat64(param) return field.Float() < p case reflect.Struct: if field.Type().ConvertibleTo(timeType) { return getValue(field.Convert(timeType)).(time.Time).Before(time.Now().UTC()) } } panic(fmt.Sprintf("Bad field type %s", field.Type())) } // hasMaxOf is the validation function for validating if the current field's value is less than or equal to the param's value. func hasMaxOf(fl FieldLevel) bool { return isLte(fl) } // isTCP4AddrResolvable is the validation function for validating if the field's value is a resolvable tcp4 address. func isTCP4AddrResolvable(fl FieldLevel) bool { if !isIP4Addr(fl) { return false } _, err := net.ResolveTCPAddr("tcp4", fl.Field().String()) return err == nil } // isTCP6AddrResolvable is the validation function for validating if the field's value is a resolvable tcp6 address. func isTCP6AddrResolvable(fl FieldLevel) bool { if !isIP6Addr(fl) { return false } _, err := net.ResolveTCPAddr("tcp6", fl.Field().String()) return err == nil } // isTCPAddrResolvable is the validation function for validating if the field's value is a resolvable tcp address. func isTCPAddrResolvable(fl FieldLevel) bool { if !isIP4Addr(fl) && !isIP6Addr(fl) { return false } _, err := net.ResolveTCPAddr("tcp", fl.Field().String()) return err == nil } // isUDP4AddrResolvable is the validation function for validating if the field's value is a resolvable udp4 address. func isUDP4AddrResolvable(fl FieldLevel) bool { if !isIP4Addr(fl) { return false } _, err := net.ResolveUDPAddr("udp4", fl.Field().String()) return err == nil } // isUDP6AddrResolvable is the validation function for validating if the field's value is a resolvable udp6 address. func isUDP6AddrResolvable(fl FieldLevel) bool { if !isIP6Addr(fl) { return false } _, err := net.ResolveUDPAddr("udp6", fl.Field().String()) return err == nil } // isUDPAddrResolvable is the validation function for validating if the field's value is a resolvable udp address. func isUDPAddrResolvable(fl FieldLevel) bool { if !isIP4Addr(fl) && !isIP6Addr(fl) { return false } _, err := net.ResolveUDPAddr("udp", fl.Field().String()) return err == nil } // isIP4AddrResolvable is the validation function for validating if the field's value is a resolvable ip4 address. func isIP4AddrResolvable(fl FieldLevel) bool { if !isIPv4(fl) { return false } _, err := net.ResolveIPAddr("ip4", fl.Field().String()) return err == nil } // isIP6AddrResolvable is the validation function for validating if the field's value is a resolvable ip6 address. func isIP6AddrResolvable(fl FieldLevel) bool { if !isIPv6(fl) { return false } _, err := net.ResolveIPAddr("ip6", fl.Field().String()) return err == nil } // isIPAddrResolvable is the validation function for validating if the field's value is a resolvable ip address. func isIPAddrResolvable(fl FieldLevel) bool { if !isIP(fl) { return false } _, err := net.ResolveIPAddr("ip", fl.Field().String()) return err == nil } // isUnixAddrResolvable is the validation function for validating if the field's value is a resolvable unix address. func isUnixAddrResolvable(fl FieldLevel) bool { _, err := net.ResolveUnixAddr("unix", fl.Field().String()) return err == nil } // isUnixDomainSocketExists is the validation function for validating if the field's value is an existing Unix domain socket. // It handles both filesystem-based sockets and Linux abstract sockets. // It always returns false for Windows. func isUnixDomainSocketExists(fl FieldLevel) bool { if runtime.GOOS == "windows" { return false } sockpath := fl.Field().String() if sockpath == "" { return false } // On Linux, check for abstract sockets (prefixed with @) if runtime.GOOS == "linux" && strings.HasPrefix(sockpath, "@") { return isAbstractSocketExists(sockpath) } // For filesystem-based sockets, check if the path exists and is a socket stats, err := os.Stat(sockpath) if err != nil { return false } return stats.Mode().Type() == fs.ModeSocket } // isAbstractSocketExists checks if a Linux abstract socket exists by reading /proc/net/unix. // Abstract sockets are identified by an @ prefix in human-readable form. func isAbstractSocketExists(sockpath string) bool { file, err := os.Open("/proc/net/unix") if err != nil { return false } defer func() { _ = file.Close() }() scanner := bufio.NewScanner(file) // Skip the header line if !scanner.Scan() { return false } // Abstract sockets in /proc/net/unix are represented with @ prefix // The socket path is the last field in each line for scanner.Scan() { line := scanner.Text() fields := strings.Fields(line) // The path is the last field (8th field typically) if len(fields) >= 8 { path := fields[len(fields)-1] if path == sockpath { return true } } } return false } func isIP4Addr(fl FieldLevel) bool { val := fl.Field().String() if idx := strings.LastIndex(val, ":"); idx != -1 { val = val[0:idx] } ip := net.ParseIP(val) return ip != nil && ip.To4() != nil } func isIP6Addr(fl FieldLevel) bool { val := fl.Field().String() if idx := strings.LastIndex(val, ":"); idx != -1 { if idx != 0 && val[idx-1:idx] == "]" { val = val[1 : idx-1] } } ip := net.ParseIP(val) return ip != nil && ip.To4() == nil } func isHostnameRFC952(fl FieldLevel) bool { return hostnameRegexRFC952().MatchString(fl.Field().String()) } func isHostnameRFC1123(fl FieldLevel) bool { return hostnameRegexRFC1123().MatchString(fl.Field().String()) } func isFQDN(fl FieldLevel) bool { val := fl.Field().String() if val == "" { return false } return fqdnRegexRFC1123().MatchString(val) } // isDir is the validation function for validating if the current field's value is a valid existing directory. func isDir(fl FieldLevel) bool { field := fl.Field() if field.Kind() == reflect.String { fileInfo, err := os.Stat(field.String()) if err != nil { return false } return fileInfo.IsDir() } panic(fmt.Sprintf("Bad field type %s", field.Type())) } // isDirPath is the validation function for validating if the current field's value is a valid directory. func isDirPath(fl FieldLevel) bool { var exists bool var err error field := fl.Field() // If it exists, it obviously is valid. // This is done first to avoid code duplication and unnecessary additional logic. if exists = isDir(fl); exists { return true } // It does not exist but may still be a valid path. switch field.Kind() { case reflect.String: // Every OS allows for whitespace, but none // let you use a dir with no name (to my knowledge). // Unless you're dealing with raw inodes, but I digress. if strings.TrimSpace(field.String()) == "" { return false } if _, err = os.Stat(field.String()); err != nil { switch t := err.(type) { case *fs.PathError: if t.Err == syscall.EINVAL { // It's definitely an invalid character in the path. return false } // It could be a permission error, a does-not-exist error, etc. // Out-of-scope for this validation, though. // Lastly, we make sure it is a directory. if strings.HasSuffix(field.String(), string(os.PathSeparator)) { return true } else { return false } default: // Something went *seriously* wrong. /* Per https://pkg.go.dev/os#Stat: "If there is an error, it will be of type *PathError." */ panic(err) } } // We repeat the check here to make sure it is an explicit directory in case the above os.Stat didn't trigger an error. if strings.HasSuffix(field.String(), string(os.PathSeparator)) { return true } else { return false } } panic(fmt.Sprintf("Bad field type %s", field.Type())) } // isJSON is the validation function for validating if the current field's value is a valid json string. func isJSON(fl FieldLevel) bool { field := fl.Field() switch field.Kind() { case reflect.String: val := field.String() return json.Valid([]byte(val)) case reflect.Slice: fieldType := field.Type() if fieldType.ConvertibleTo(byteSliceType) { b := getValue(field.Convert(byteSliceType)).([]byte) return json.Valid(b) } } panic(fmt.Sprintf("Bad field type %s", field.Type())) } // isJWT is the validation function for validating if the current field's value is a valid JWT string. func isJWT(fl FieldLevel) bool { return jWTRegex().MatchString(fl.Field().String()) } // isHostnamePort validates a : combination for fields typically used for socket address. func isHostnamePort(fl FieldLevel) bool { val := fl.Field().String() host, port, err := net.SplitHostPort(val) if err != nil { return false } // Port must be a iny <= 65535. if portNum, err := strconv.ParseInt( port, 10, 32, ); err != nil || portNum > 65535 || portNum < 1 { return false } // If host is specified, it should match a DNS name if host != "" { return hostnameRegexRFC1123().MatchString(host) } return true } // IsPort validates if the current field's value represents a valid port func isPort(fl FieldLevel) bool { val := fl.Field().Uint() return val >= 1 && val <= 65535 } // isLowercase is the validation function for validating if the current field's value is a lowercase string. func isLowercase(fl FieldLevel) bool { field := fl.Field() if field.Kind() == reflect.String { if field.String() == "" { return false } return field.String() == strings.ToLower(field.String()) } panic(fmt.Sprintf("Bad field type %s", field.Type())) } // isUppercase is the validation function for validating if the current field's value is an uppercase string. func isUppercase(fl FieldLevel) bool { field := fl.Field() if field.Kind() == reflect.String { if field.String() == "" { return false } return field.String() == strings.ToUpper(field.String()) } panic(fmt.Sprintf("Bad field type %s", field.Type())) } // isDatetime is the validation function for validating if the current field's value is a valid datetime string. func isDatetime(fl FieldLevel) bool { field := fl.Field() param := fl.Param() if field.Kind() == reflect.String { _, err := time.Parse(param, field.String()) return err == nil } panic(fmt.Sprintf("Bad field type %s", field.Type())) } // isTimeZone is the validation function for validating if the current field's value is a valid time zone string. func isTimeZone(fl FieldLevel) bool { field := fl.Field() if field.Kind() == reflect.String { // empty value is converted to UTC by time.LoadLocation but disallow it as it is not a valid time zone name if field.String() == "" { return false } // Local value is converted to the current system time zone by time.LoadLocation but disallow it as it is not a valid time zone name if strings.ToLower(field.String()) == "local" { return false } _, err := time.LoadLocation(field.String()) return err == nil } panic(fmt.Sprintf("Bad field type %s", field.Type())) } // isIso3166Alpha2 is the validation function for validating if the current field's value is a valid iso3166-1 alpha-2 country code. func isIso3166Alpha2(fl FieldLevel) bool { _, ok := iso3166_1_alpha2[fl.Field().String()] return ok } // isIso3166Alpha2EU is the validation function for validating if the current field's value is a valid iso3166-1 alpha-2 European Union country code. func isIso3166Alpha2EU(fl FieldLevel) bool { _, ok := iso3166_1_alpha2_eu[fl.Field().String()] return ok } // isIso3166Alpha3 is the validation function for validating if the current field's value is a valid iso3166-1 alpha-3 country code. func isIso3166Alpha3(fl FieldLevel) bool { _, ok := iso3166_1_alpha3[fl.Field().String()] return ok } // isIso3166Alpha3EU is the validation function for validating if the current field's value is a valid iso3166-1 alpha-3 European Union country code. func isIso3166Alpha3EU(fl FieldLevel) bool { _, ok := iso3166_1_alpha3_eu[fl.Field().String()] return ok } // isIso3166AlphaNumeric is the validation function for validating if the current field's value is a valid iso3166-1 alpha-numeric country code. func isIso3166AlphaNumeric(fl FieldLevel) bool { field := fl.Field() var code int switch field.Kind() { case reflect.String: i, err := strconv.Atoi(field.String()) if err != nil { return false } code = i % 1000 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: code = int(field.Int() % 1000) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: code = int(field.Uint() % 1000) default: panic(fmt.Sprintf("Bad field type %s", field.Type())) } _, ok := iso3166_1_alpha_numeric[code] return ok } // isIso3166AlphaNumericEU is the validation function for validating if the current field's value is a valid iso3166-1 alpha-numeric European Union country code. func isIso3166AlphaNumericEU(fl FieldLevel) bool { field := fl.Field() var code int switch field.Kind() { case reflect.String: i, err := strconv.Atoi(field.String()) if err != nil { return false } code = i % 1000 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: code = int(field.Int() % 1000) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: code = int(field.Uint() % 1000) default: panic(fmt.Sprintf("Bad field type %s", field.Type())) } _, ok := iso3166_1_alpha_numeric_eu[code] return ok } // isIso31662 is the validation function for validating if the current field's value is a valid iso3166-2 code. func isIso31662(fl FieldLevel) bool { _, ok := iso3166_2[fl.Field().String()] return ok } // isIso4217 is the validation function for validating if the current field's value is a valid iso4217 currency code. func isIso4217(fl FieldLevel) bool { _, ok := iso4217[fl.Field().String()] return ok } // isIso4217Numeric is the validation function for validating if the current field's value is a valid iso4217 numeric currency code. func isIso4217Numeric(fl FieldLevel) bool { field := fl.Field() var code int switch field.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: code = int(field.Int()) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: code = int(field.Uint()) default: panic(fmt.Sprintf("Bad field type %s", field.Type())) } _, ok := iso4217_numeric[code] return ok } // isBCP47LanguageTag is the validation function for validating if the current field's value is a valid BCP 47 language tag, as parsed by language.Parse func isBCP47LanguageTag(fl FieldLevel) bool { field := fl.Field() if field.Kind() == reflect.String { _, err := language.Parse(field.String()) return err == nil } panic(fmt.Sprintf("Bad field type %s", field.Type())) } // isIsoBic2014Format is the validation function for validating if the current field's value is a valid Business Identifier Code (SWIFT code), defined in ISO 9362 2014 func isIsoBic2014Format(fl FieldLevel) bool { bicString := fl.Field().String() return bic2014Regex().MatchString(bicString) } // isIsoBic2022Format is the validation function for validating if the current field's value is a valid Business Identifier Code (SWIFT code), defined in ISO 9362 2022 func isIsoBic2022Format(fl FieldLevel) bool { bicString := fl.Field().String() return bic2022Regex().MatchString(bicString) } // isSemverFormat is the validation function for validating if the current field's value is a valid semver version, defined in Semantic Versioning 2.0.0 func isSemverFormat(fl FieldLevel) bool { semverString := fl.Field().String() return semverRegex().MatchString(semverString) } // isCveFormat is the validation function for validating if the current field's value is a valid cve id, defined in CVE mitre org func isCveFormat(fl FieldLevel) bool { cveString := fl.Field().String() return cveRegex().MatchString(cveString) } // isDnsRFC1035LabelFormat is the validation function // for validating if the current field's value is // a valid dns RFC 1035 label, defined in RFC 1035. func isDnsRFC1035LabelFormat(fl FieldLevel) bool { val := fl.Field().String() size := len(val) if size > 63 { return false } return dnsRegexRFC1035Label().MatchString(val) } // digitsHaveLuhnChecksum returns true if and only if the last element of the given digits slice is the Luhn checksum of the previous elements func digitsHaveLuhnChecksum(digits []string) bool { size := len(digits) sum := 0 for i, digit := range digits { value, err := strconv.Atoi(digit) if err != nil { return false } if size%2 == 0 && i%2 == 0 || size%2 == 1 && i%2 == 1 { v := value * 2 if v >= 10 { sum += 1 + (v % 10) } else { sum += v } } else { sum += value } } return (sum % 10) == 0 } // isMongoDBObjectId is the validation function for validating if the current field's value is valid MongoDB ObjectID func isMongoDBObjectId(fl FieldLevel) bool { val := fl.Field().String() return mongodbIdRegex().MatchString(val) } // isMongoDBConnectionString is the validation function for validating if the current field's value is valid MongoDB Connection String func isMongoDBConnectionString(fl FieldLevel) bool { val := fl.Field().String() return mongodbConnectionRegex().MatchString(val) } // isSpiceDB is the validation function for validating if the current field's value is valid for use with Authzed SpiceDB in the indicated way func isSpiceDB(fl FieldLevel) bool { val := fl.Field().String() param := fl.Param() switch param { case "permission": return spicedbPermissionRegex().MatchString(val) case "type": return spicedbTypeRegex().MatchString(val) case "id", "": return spicedbIDRegex().MatchString(val) } panic("Unrecognized parameter: " + param) } // isCreditCard is the validation function for validating if the current field's value is a valid credit card number func isCreditCard(fl FieldLevel) bool { val := fl.Field().String() var creditCard bytes.Buffer segments := strings.Split(val, " ") for _, segment := range segments { if len(segment) < 3 { return false } creditCard.WriteString(segment) } ccDigits := strings.Split(creditCard.String(), "") size := len(ccDigits) if size < 12 || size > 19 { return false } return digitsHaveLuhnChecksum(ccDigits) } // hasLuhnChecksum is the validation for validating if the current field's value has a valid Luhn checksum func hasLuhnChecksum(fl FieldLevel) bool { field := fl.Field() var str string // convert to a string which will then be split into single digits; easier and more readable than shifting/extracting single digits from a number switch field.Kind() { case reflect.String: str = field.String() case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: str = strconv.FormatInt(field.Int(), 10) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: str = strconv.FormatUint(field.Uint(), 10) default: panic(fmt.Sprintf("Bad field type %s", field.Type())) } size := len(str) if size < 2 { // there has to be at least one digit that carries a meaning + the checksum return false } digits := strings.Split(str, "") return digitsHaveLuhnChecksum(digits) } // isCron is the validation function for validating if the current field's value is a valid cron expression func isCron(fl FieldLevel) bool { cronString := fl.Field().String() return cronRegex().MatchString(cronString) } // isEIN is the validation function for validating if the current field's value is a valid U.S. Employer Identification Number (EIN) func isEIN(fl FieldLevel) bool { field := fl.Field() if field.Len() != 10 { return false } return einRegex().MatchString(field.String()) } func isValidateFn(fl FieldLevel) bool { const defaultParam = `Validate` field := fl.Field() validateFn := cmp.Or(fl.Param(), defaultParam) ok, err := tryCallValidateFn(field, validateFn) if err != nil { return false } return ok } var ( errMethodNotFound = errors.New(`method not found`) errMethodReturnNoValues = errors.New(`method return o values (void)`) errMethodReturnInvalidType = errors.New(`method should return invalid type`) ) func tryCallValidateFn(field reflect.Value, validateFn string) (bool, error) { method := field.MethodByName(validateFn) if field.CanAddr() && !method.IsValid() { method = field.Addr().MethodByName(validateFn) } if !method.IsValid() { return false, fmt.Errorf("unable to call %q on type %q: %w", validateFn, field.Type().String(), errMethodNotFound) } returnValues := method.Call([]reflect.Value{}) if len(returnValues) == 0 { return false, fmt.Errorf("unable to use result of method %q on type %q: %w", validateFn, field.Type().String(), errMethodReturnNoValues) } firstReturnValue := returnValues[0] switch firstReturnValue.Kind() { case reflect.Bool: return firstReturnValue.Bool(), nil case reflect.Interface: errorType := reflect.TypeOf((*error)(nil)).Elem() if firstReturnValue.Type().Implements(errorType) { return firstReturnValue.IsNil(), nil } return false, fmt.Errorf("unable to use result of method %q on type %q: %w (got interface %v expect error)", validateFn, field.Type().String(), errMethodReturnInvalidType, firstReturnValue.Type().String()) default: return false, fmt.Errorf("unable to use result of method %q on type %q: %w (got %v expect error or bool)", validateFn, field.Type().String(), errMethodReturnInvalidType, firstReturnValue.Type().String()) } } golang-github-go-playground-validator-v10-10.30.1/benchmarks_test.go000066400000000000000000000513021512410077000252600ustar00rootroot00000000000000package validator import ( "bytes" sql "database/sql/driver" "errors" "testing" "time" ) func BenchmarkFieldSuccess(b *testing.B) { validate := New() s := "1" b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.Var(&s, "len=1") } } func BenchmarkFieldSuccessParallel(b *testing.B) { validate := New() s := "1" b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.Var(&s, "len=1") } }) } func BenchmarkFieldFailure(b *testing.B) { validate := New() s := "12" b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.Var(&s, "len=1") } } func BenchmarkFieldFailureParallel(b *testing.B) { validate := New() s := "12" b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.Var(&s, "len=1") } }) } func BenchmarkFieldArrayDiveSuccess(b *testing.B) { validate := New() m := []string{"val1", "val2", "val3"} b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.Var(m, "required,dive,required") } } func BenchmarkFieldArrayDiveSuccessParallel(b *testing.B) { validate := New() m := []string{"val1", "val2", "val3"} b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.Var(m, "required,dive,required") } }) } func BenchmarkFieldArrayDiveFailure(b *testing.B) { validate := New() m := []string{"val1", "", "val3"} b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.Var(m, "required,dive,required") } } func BenchmarkFieldArrayDiveFailureParallel(b *testing.B) { validate := New() m := []string{"val1", "", "val3"} b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.Var(m, "required,dive,required") } }) } func BenchmarkFieldMapDiveSuccess(b *testing.B) { validate := New() m := map[string]string{"val1": "val1", "val2": "val2", "val3": "val3"} b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.Var(m, "required,dive,required") } } func BenchmarkFieldMapDiveSuccessParallel(b *testing.B) { validate := New() m := map[string]string{"val1": "val1", "val2": "val2", "val3": "val3"} b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.Var(m, "required,dive,required") } }) } func BenchmarkFieldMapDiveFailure(b *testing.B) { validate := New() m := map[string]string{"": "", "val3": "val3"} b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.Var(m, "required,dive,required") } } func BenchmarkFieldMapDiveFailureParallel(b *testing.B) { validate := New() m := map[string]string{"": "", "val3": "val3"} b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.Var(m, "required,dive,required") } }) } func BenchmarkFieldMapDiveWithKeysSuccess(b *testing.B) { validate := New() m := map[string]string{"val1": "val1", "val2": "val2", "val3": "val3"} b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.Var(m, "required,dive,keys,required,endkeys,required") } } func BenchmarkFieldMapDiveWithKeysSuccessParallel(b *testing.B) { validate := New() m := map[string]string{"val1": "val1", "val2": "val2", "val3": "val3"} b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.Var(m, "required,dive,keys,required,endkeys,required") } }) } func BenchmarkFieldMapDiveWithKeysFailure(b *testing.B) { validate := New() m := map[string]string{"": "", "val3": "val3"} b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.Var(m, "required,dive,keys,required,endkeys,required") } } func BenchmarkFieldMapDiveWithKeysFailureParallel(b *testing.B) { validate := New() m := map[string]string{"": "", "val3": "val3"} b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.Var(m, "required,dive,keys,required,endkeys,required") } }) } func BenchmarkFieldCustomTypeSuccess(b *testing.B) { validate := New() validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{}) val := valuer{ Name: "1", } b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.Var(val, "len=1") } } func BenchmarkFieldCustomTypeSuccessParallel(b *testing.B) { validate := New() validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{}) val := valuer{ Name: "1", } b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.Var(val, "len=1") } }) } func BenchmarkFieldCustomTypeFailure(b *testing.B) { validate := New() validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{}) val := valuer{} b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.Var(val, "len=1") } } func BenchmarkFieldCustomTypeFailureParallel(b *testing.B) { validate := New() validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{}) val := valuer{} b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.Var(val, "len=1") } }) } func BenchmarkFieldOrTagSuccess(b *testing.B) { validate := New() s := "rgba(0,0,0,1)" b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.Var(s, "rgb|rgba") } } func BenchmarkFieldOrTagSuccessParallel(b *testing.B) { validate := New() s := "rgba(0,0,0,1)" b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.Var(s, "rgb|rgba") } }) } func BenchmarkFieldOrTagFailure(b *testing.B) { validate := New() s := "#000" b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.Var(s, "rgb|rgba") } } func BenchmarkFieldOrTagFailureParallel(b *testing.B) { validate := New() s := "#000" b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.Var(s, "rgb|rgba") } }) } func BenchmarkStructLevelValidationSuccess(b *testing.B) { validate := New() validate.RegisterStructValidation(StructValidationTestStructSuccess, TestStruct{}) tst := TestStruct{ String: "good value", } b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.Struct(tst) } } func BenchmarkStructLevelValidationSuccessParallel(b *testing.B) { validate := New() validate.RegisterStructValidation(StructValidationTestStructSuccess, TestStruct{}) tst := TestStruct{ String: "good value", } b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.Struct(tst) } }) } func BenchmarkStructLevelValidationFailure(b *testing.B) { validate := New() validate.RegisterStructValidation(StructValidationTestStruct, TestStruct{}) tst := TestStruct{ String: "good value", } b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.Struct(tst) } } func BenchmarkStructLevelValidationFailureParallel(b *testing.B) { validate := New() validate.RegisterStructValidation(StructValidationTestStruct, TestStruct{}) tst := TestStruct{ String: "good value", } b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.Struct(tst) } }) } func BenchmarkStructSimpleCustomTypeSuccess(b *testing.B) { validate := New() validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{}) val := valuer{ Name: "1", } type Foo struct { Valuer valuer `validate:"len=1"` IntValue int `validate:"min=5,max=10"` } validFoo := &Foo{Valuer: val, IntValue: 7} b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.Struct(validFoo) } } func BenchmarkStructSimpleCustomTypeSuccessParallel(b *testing.B) { validate := New() validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{}) val := valuer{ Name: "1", } type Foo struct { Valuer valuer `validate:"len=1"` IntValue int `validate:"min=5,max=10"` } validFoo := &Foo{Valuer: val, IntValue: 7} b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.Struct(validFoo) } }) } func BenchmarkStructSimpleCustomTypeFailure(b *testing.B) { validate := New() validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{}) val := valuer{} type Foo struct { Valuer valuer `validate:"len=1"` IntValue int `validate:"min=5,max=10"` } validFoo := &Foo{Valuer: val, IntValue: 3} b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.Struct(validFoo) } } func BenchmarkStructSimpleCustomTypeFailureParallel(b *testing.B) { validate := New() validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{}) val := valuer{} type Foo struct { Valuer valuer `validate:"len=1"` IntValue int `validate:"min=5,max=10"` } validFoo := &Foo{Valuer: val, IntValue: 3} b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.Struct(validate.Struct(validFoo)) } }) } func BenchmarkStructFilteredSuccess(b *testing.B) { validate := New() type Test struct { Name string `validate:"required"` NickName string `validate:"required"` } test := &Test{ Name: "Joey Bloggs", } byts := []byte("Name") fn := func(ns []byte) bool { return !bytes.HasSuffix(ns, byts) } b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.StructFiltered(test, fn) } } func BenchmarkStructFilteredSuccessParallel(b *testing.B) { validate := New() type Test struct { Name string `validate:"required"` NickName string `validate:"required"` } test := &Test{ Name: "Joey Bloggs", } byts := []byte("Name") fn := func(ns []byte) bool { return !bytes.HasSuffix(ns, byts) } b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.StructFiltered(test, fn) } }) } func BenchmarkStructFilteredFailure(b *testing.B) { validate := New() type Test struct { Name string `validate:"required"` NickName string `validate:"required"` } test := &Test{ Name: "Joey Bloggs", } byts := []byte("NickName") fn := func(ns []byte) bool { return !bytes.HasSuffix(ns, byts) } b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.StructFiltered(test, fn) } } func BenchmarkStructFilteredFailureParallel(b *testing.B) { validate := New() type Test struct { Name string `validate:"required"` NickName string `validate:"required"` } test := &Test{ Name: "Joey Bloggs", } byts := []byte("NickName") fn := func(ns []byte) bool { return !bytes.HasSuffix(ns, byts) } b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.StructFiltered(test, fn) } }) } func BenchmarkStructPartialSuccess(b *testing.B) { validate := New() type Test struct { Name string `validate:"required"` NickName string `validate:"required"` } test := &Test{ Name: "Joey Bloggs", } b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.StructPartial(test, "Name") } } func BenchmarkStructPartialSuccessParallel(b *testing.B) { validate := New() type Test struct { Name string `validate:"required"` NickName string `validate:"required"` } test := &Test{ Name: "Joey Bloggs", } b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.StructPartial(test, "Name") } }) } func BenchmarkStructPartialFailure(b *testing.B) { validate := New() type Test struct { Name string `validate:"required"` NickName string `validate:"required"` } test := &Test{ Name: "Joey Bloggs", } b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.StructPartial(test, "NickName") } } func BenchmarkStructPartialFailureParallel(b *testing.B) { validate := New() type Test struct { Name string `validate:"required"` NickName string `validate:"required"` } test := &Test{ Name: "Joey Bloggs", } b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.StructPartial(test, "NickName") } }) } func BenchmarkStructExceptSuccess(b *testing.B) { validate := New() type Test struct { Name string `validate:"required"` NickName string `validate:"required"` } test := &Test{ Name: "Joey Bloggs", } b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.StructExcept(test, "Nickname") } } func BenchmarkStructExceptSuccessParallel(b *testing.B) { validate := New() type Test struct { Name string `validate:"required"` NickName string `validate:"required"` } test := &Test{ Name: "Joey Bloggs", } b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.StructExcept(test, "NickName") } }) } func BenchmarkStructExceptFailure(b *testing.B) { validate := New() type Test struct { Name string `validate:"required"` NickName string `validate:"required"` } test := &Test{ Name: "Joey Bloggs", } b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.StructExcept(test, "Name") } } func BenchmarkStructExceptFailureParallel(b *testing.B) { validate := New() type Test struct { Name string `validate:"required"` NickName string `validate:"required"` } test := &Test{ Name: "Joey Bloggs", } b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.StructExcept(test, "Name") } }) } func BenchmarkStructSimpleCrossFieldSuccess(b *testing.B) { validate := New() type Test struct { Start time.Time End time.Time `validate:"gtfield=Start"` } now := time.Now().UTC() then := now.Add(time.Hour * 5) test := &Test{ Start: now, End: then, } b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.Struct(test) } } func BenchmarkStructSimpleCrossFieldSuccessParallel(b *testing.B) { validate := New() type Test struct { Start time.Time End time.Time `validate:"gtfield=Start"` } now := time.Now().UTC() then := now.Add(time.Hour * 5) test := &Test{ Start: now, End: then, } b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.Struct(test) } }) } func BenchmarkStructSimpleCrossFieldFailure(b *testing.B) { validate := New() type Test struct { Start time.Time End time.Time `validate:"gtfield=Start"` } now := time.Now().UTC() then := now.Add(time.Hour * -5) test := &Test{ Start: now, End: then, } b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.Struct(test) } } func BenchmarkStructSimpleCrossFieldFailureParallel(b *testing.B) { validate := New() type Test struct { Start time.Time End time.Time `validate:"gtfield=Start"` } now := time.Now().UTC() then := now.Add(time.Hour * -5) test := &Test{ Start: now, End: then, } b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.Struct(test) } }) } func BenchmarkStructSimpleCrossStructCrossFieldSuccess(b *testing.B) { validate := New() type Inner struct { Start time.Time } type Outer struct { Inner *Inner CreatedAt time.Time `validate:"eqcsfield=Inner.Start"` } now := time.Now().UTC() inner := &Inner{ Start: now, } outer := &Outer{ Inner: inner, CreatedAt: now, } b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.Struct(outer) } } func BenchmarkStructSimpleCrossStructCrossFieldSuccessParallel(b *testing.B) { validate := New() type Inner struct { Start time.Time } type Outer struct { Inner *Inner CreatedAt time.Time `validate:"eqcsfield=Inner.Start"` } now := time.Now().UTC() inner := &Inner{ Start: now, } outer := &Outer{ Inner: inner, CreatedAt: now, } b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.Struct(outer) } }) } func BenchmarkStructSimpleCrossStructCrossFieldFailure(b *testing.B) { validate := New() type Inner struct { Start time.Time } type Outer struct { Inner *Inner CreatedAt time.Time `validate:"eqcsfield=Inner.Start"` } now := time.Now().UTC() then := now.Add(time.Hour * 5) inner := &Inner{ Start: then, } outer := &Outer{ Inner: inner, CreatedAt: now, } b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.Struct(outer) } } func BenchmarkStructSimpleCrossStructCrossFieldFailureParallel(b *testing.B) { validate := New() type Inner struct { Start time.Time } type Outer struct { Inner *Inner CreatedAt time.Time `validate:"eqcsfield=Inner.Start"` } now := time.Now().UTC() then := now.Add(time.Hour * 5) inner := &Inner{ Start: then, } outer := &Outer{ Inner: inner, CreatedAt: now, } b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.Struct(outer) } }) } func BenchmarkStructSimpleSuccess(b *testing.B) { validate := New() type Foo struct { StringValue string `validate:"min=5,max=10"` IntValue int `validate:"min=5,max=10"` } validFoo := &Foo{StringValue: "Foobar", IntValue: 7} b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.Struct(validFoo) } } func BenchmarkStructSimpleSuccessParallel(b *testing.B) { validate := New() type Foo struct { StringValue string `validate:"min=5,max=10"` IntValue int `validate:"min=5,max=10"` } validFoo := &Foo{StringValue: "Foobar", IntValue: 7} b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.Struct(validFoo) } }) } func BenchmarkStructSimpleFailure(b *testing.B) { validate := New() type Foo struct { StringValue string `validate:"min=5,max=10"` IntValue int `validate:"min=5,max=10"` } invalidFoo := &Foo{StringValue: "Fo", IntValue: 3} b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.Struct(invalidFoo) } } func BenchmarkStructSimpleFailureParallel(b *testing.B) { validate := New() type Foo struct { StringValue string `validate:"min=5,max=10"` IntValue int `validate:"min=5,max=10"` } invalidFoo := &Foo{StringValue: "Fo", IntValue: 3} b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.Struct(invalidFoo) } }) } func BenchmarkStructComplexSuccess(b *testing.B) { validate := New() tSuccess := &TestString{ Required: "Required", Len: "length==10", Min: "min=1", Max: "1234567890", MinMax: "12345", Lt: "012345678", Lte: "0123456789", Gt: "01234567890", Gte: "0123456789", OmitEmpty: "", Sub: &SubTest{ Test: "1", }, SubIgnore: &SubTest{ Test: "", }, Anonymous: struct { A string `validate:"required"` }{ A: "1", }, Iface: &Impl{ F: "123", }, } b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.Struct(tSuccess) } } func BenchmarkStructComplexSuccessParallel(b *testing.B) { validate := New() tSuccess := &TestString{ Required: "Required", Len: "length==10", Min: "min=1", Max: "1234567890", MinMax: "12345", Lt: "012345678", Lte: "0123456789", Gt: "01234567890", Gte: "0123456789", OmitEmpty: "", Sub: &SubTest{ Test: "1", }, SubIgnore: &SubTest{ Test: "", }, Anonymous: struct { A string `validate:"required"` }{ A: "1", }, Iface: &Impl{ F: "123", }, } b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.Struct(tSuccess) } }) } func BenchmarkStructComplexFailure(b *testing.B) { validate := New() tFail := &TestString{ Required: "", Len: "", Min: "", Max: "12345678901", MinMax: "", Lt: "0123456789", Lte: "01234567890", Gt: "1", Gte: "1", OmitEmpty: "12345678901", Sub: &SubTest{ Test: "", }, Anonymous: struct { A string `validate:"required"` }{ A: "", }, Iface: &Impl{ F: "12", }, } b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.Struct(tFail) } } func BenchmarkStructComplexFailureParallel(b *testing.B) { validate := New() tFail := &TestString{ Required: "", Len: "", Min: "", Max: "12345678901", MinMax: "", Lt: "0123456789", Lte: "01234567890", Gt: "1", Gte: "1", OmitEmpty: "12345678901", Sub: &SubTest{ Test: "", }, Anonymous: struct { A string `validate:"required"` }{ A: "", }, Iface: &Impl{ F: "12", }, } b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.Struct(tFail) } }) } type TestOneof struct { Color string `validate:"oneof=red green"` } func BenchmarkOneof(b *testing.B) { w := &TestOneof{Color: "green"} val := New() for i := 0; i < b.N; i++ { _ = val.Struct(w) } } func BenchmarkOneofParallel(b *testing.B) { w := &TestOneof{Color: "green"} val := New() b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = val.Struct(w) } }) } type T struct{} func (*T) Validate() error { return errors.New("ops") } func BenchmarkValidateFnSequencial(b *testing.B) { validate := New() type Test struct { T T `validate:"validateFn"` } test := &Test{} b.ResetTimer() for n := 0; n < b.N; n++ { _ = validate.Struct(test) } } func BenchmarkValidateFnParallel(b *testing.B) { validate := New() type Test struct { T T `validate:"validateFn"` } test := &Test{} b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = validate.Struct(test) } }) } golang-github-go-playground-validator-v10-10.30.1/cache.go000066400000000000000000000203511512410077000231470ustar00rootroot00000000000000package validator import ( "fmt" "reflect" "strings" "sync" "sync/atomic" ) type tagType uint8 const ( typeDefault tagType = iota typeOmitEmpty typeIsDefault typeNoStructLevel typeStructOnly typeDive typeOr typeKeys typeEndKeys typeOmitNil typeOmitZero ) 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 !v.privateFieldValidation && !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 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)) } // 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) 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 omitzero: current.typeof = typeOmitZero continue case omitempty: current.typeof = typeOmitEmpty case omitnil: current.typeof = typeOmitNil case structOnlyTag: current.typeof = typeStructOnly case noStructLevelTag: current.typeof = typeNoStructLevel 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.runValidationOnNil } else if aliasTag, isAlias := v.aliases[current.tag]; isAlias { aliasFirst, aliasLast := v.parseFieldTagsRecursive(aliasTag, fieldName, current.tag, true) current.tag = aliasFirst.tag current.fn = aliasFirst.fn current.runValidationWhenNil = aliasFirst.runValidationWhenNil current.hasParam = aliasFirst.hasParam current.param = aliasFirst.param current.typeof = aliasFirst.typeof current.hasAlias = true if aliasFirst.next != nil { nextInChain := current.next current.next = aliasFirst.next aliasLast.next = nextInChain aliasLast.isBlockEnd = false current = aliasLast } } else { panic(strings.TrimSpace(fmt.Sprintf(undefinedValidation, current.tag, fieldName))) } if len(orVals) > 1 { current.typeof = typeOr } if len(vals) > 1 { current.param = strings.ReplaceAll(strings.ReplaceAll(vals[1], utf8HexComma, ","), utf8Pipe, "|") } } 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 } golang-github-go-playground-validator-v10-10.30.1/country_codes.go000066400000000000000000002246001512410077000247670ustar00rootroot00000000000000package validator var iso3166_1_alpha2 = map[string]struct{}{ // see: https://www.iso.org/iso-3166-country-codes.html "AF": {}, "AX": {}, "AL": {}, "DZ": {}, "AS": {}, "AD": {}, "AO": {}, "AI": {}, "AQ": {}, "AG": {}, "AR": {}, "AM": {}, "AW": {}, "AU": {}, "AT": {}, "AZ": {}, "BS": {}, "BH": {}, "BD": {}, "BB": {}, "BY": {}, "BE": {}, "BZ": {}, "BJ": {}, "BM": {}, "BT": {}, "BO": {}, "BQ": {}, "BA": {}, "BW": {}, "BV": {}, "BR": {}, "IO": {}, "BN": {}, "BG": {}, "BF": {}, "BI": {}, "KH": {}, "CM": {}, "CA": {}, "CV": {}, "KY": {}, "CF": {}, "TD": {}, "CL": {}, "CN": {}, "CX": {}, "CC": {}, "CO": {}, "KM": {}, "CG": {}, "CD": {}, "CK": {}, "CR": {}, "CI": {}, "HR": {}, "CU": {}, "CW": {}, "CY": {}, "CZ": {}, "DK": {}, "DJ": {}, "DM": {}, "DO": {}, "EC": {}, "EG": {}, "SV": {}, "GQ": {}, "ER": {}, "EE": {}, "ET": {}, "FK": {}, "FO": {}, "FJ": {}, "FI": {}, "FR": {}, "GF": {}, "PF": {}, "TF": {}, "GA": {}, "GM": {}, "GE": {}, "DE": {}, "GH": {}, "GI": {}, "GR": {}, "GL": {}, "GD": {}, "GP": {}, "GU": {}, "GT": {}, "GG": {}, "GN": {}, "GW": {}, "GY": {}, "HT": {}, "HM": {}, "VA": {}, "HN": {}, "HK": {}, "HU": {}, "IS": {}, "IN": {}, "ID": {}, "IR": {}, "IQ": {}, "IE": {}, "IM": {}, "IL": {}, "IT": {}, "JM": {}, "JP": {}, "JE": {}, "JO": {}, "KZ": {}, "KE": {}, "KI": {}, "KP": {}, "KR": {}, "KW": {}, "KG": {}, "LA": {}, "LV": {}, "LB": {}, "LS": {}, "LR": {}, "LY": {}, "LI": {}, "LT": {}, "LU": {}, "MO": {}, "MK": {}, "MG": {}, "MW": {}, "MY": {}, "MV": {}, "ML": {}, "MT": {}, "MH": {}, "MQ": {}, "MR": {}, "MU": {}, "YT": {}, "MX": {}, "FM": {}, "MD": {}, "MC": {}, "MN": {}, "ME": {}, "MS": {}, "MA": {}, "MZ": {}, "MM": {}, "NA": {}, "NR": {}, "NP": {}, "NL": {}, "NC": {}, "NZ": {}, "NI": {}, "NE": {}, "NG": {}, "NU": {}, "NF": {}, "MP": {}, "NO": {}, "OM": {}, "PK": {}, "PW": {}, "PS": {}, "PA": {}, "PG": {}, "PY": {}, "PE": {}, "PH": {}, "PN": {}, "PL": {}, "PT": {}, "PR": {}, "QA": {}, "RE": {}, "RO": {}, "RU": {}, "RW": {}, "BL": {}, "SH": {}, "KN": {}, "LC": {}, "MF": {}, "PM": {}, "VC": {}, "WS": {}, "SM": {}, "ST": {}, "SA": {}, "SN": {}, "RS": {}, "SC": {}, "SL": {}, "SG": {}, "SX": {}, "SK": {}, "SI": {}, "SB": {}, "SO": {}, "ZA": {}, "GS": {}, "SS": {}, "ES": {}, "LK": {}, "SD": {}, "SR": {}, "SJ": {}, "SZ": {}, "SE": {}, "CH": {}, "SY": {}, "TW": {}, "TJ": {}, "TZ": {}, "TH": {}, "TL": {}, "TG": {}, "TK": {}, "TO": {}, "TT": {}, "TN": {}, "TR": {}, "TM": {}, "TC": {}, "TV": {}, "UG": {}, "UA": {}, "AE": {}, "GB": {}, "US": {}, "UM": {}, "UY": {}, "UZ": {}, "VU": {}, "VE": {}, "VN": {}, "VG": {}, "VI": {}, "WF": {}, "EH": {}, "YE": {}, "ZM": {}, "ZW": {}, "XK": {}, } var iso3166_1_alpha2_eu = map[string]struct{}{ "AT": {}, "BE": {}, "BG": {}, "HR": {}, "CY": {}, "CZ": {}, "DK": {}, "EE": {}, "FI": {}, "FR": {}, "DE": {}, "GR": {}, "HU": {}, "IE": {}, "IT": {}, "LV": {}, "LT": {}, "LU": {}, "MT": {}, "NL": {}, "PL": {}, "PT": {}, "RO": {}, "SK": {}, "SI": {}, "ES": {}, "SE": {}, } var iso3166_1_alpha3 = map[string]struct{}{ // see: https://www.iso.org/iso-3166-country-codes.html "AFG": {}, "ALB": {}, "DZA": {}, "ASM": {}, "AND": {}, "AGO": {}, "AIA": {}, "ATA": {}, "ATG": {}, "ARG": {}, "ARM": {}, "ABW": {}, "AUS": {}, "AUT": {}, "AZE": {}, "BHS": {}, "BHR": {}, "BGD": {}, "BRB": {}, "BLR": {}, "BEL": {}, "BLZ": {}, "BEN": {}, "BMU": {}, "BTN": {}, "BOL": {}, "BES": {}, "BIH": {}, "BWA": {}, "BVT": {}, "BRA": {}, "IOT": {}, "BRN": {}, "BGR": {}, "BFA": {}, "BDI": {}, "CPV": {}, "KHM": {}, "CMR": {}, "CAN": {}, "CYM": {}, "CAF": {}, "TCD": {}, "CHL": {}, "CHN": {}, "CXR": {}, "CCK": {}, "COL": {}, "COM": {}, "COD": {}, "COG": {}, "COK": {}, "CRI": {}, "HRV": {}, "CUB": {}, "CUW": {}, "CYP": {}, "CZE": {}, "CIV": {}, "DNK": {}, "DJI": {}, "DMA": {}, "DOM": {}, "ECU": {}, "EGY": {}, "SLV": {}, "GNQ": {}, "ERI": {}, "EST": {}, "SWZ": {}, "ETH": {}, "FLK": {}, "FRO": {}, "FJI": {}, "FIN": {}, "FRA": {}, "GUF": {}, "PYF": {}, "ATF": {}, "GAB": {}, "GMB": {}, "GEO": {}, "DEU": {}, "GHA": {}, "GIB": {}, "GRC": {}, "GRL": {}, "GRD": {}, "GLP": {}, "GUM": {}, "GTM": {}, "GGY": {}, "GIN": {}, "GNB": {}, "GUY": {}, "HTI": {}, "HMD": {}, "VAT": {}, "HND": {}, "HKG": {}, "HUN": {}, "ISL": {}, "IND": {}, "IDN": {}, "IRN": {}, "IRQ": {}, "IRL": {}, "IMN": {}, "ISR": {}, "ITA": {}, "JAM": {}, "JPN": {}, "JEY": {}, "JOR": {}, "KAZ": {}, "KEN": {}, "KIR": {}, "PRK": {}, "KOR": {}, "KWT": {}, "KGZ": {}, "LAO": {}, "LVA": {}, "LBN": {}, "LSO": {}, "LBR": {}, "LBY": {}, "LIE": {}, "LTU": {}, "LUX": {}, "MAC": {}, "MDG": {}, "MWI": {}, "MYS": {}, "MDV": {}, "MLI": {}, "MLT": {}, "MHL": {}, "MTQ": {}, "MRT": {}, "MUS": {}, "MYT": {}, "MEX": {}, "FSM": {}, "MDA": {}, "MCO": {}, "MNG": {}, "MNE": {}, "MSR": {}, "MAR": {}, "MOZ": {}, "MMR": {}, "NAM": {}, "NRU": {}, "NPL": {}, "NLD": {}, "NCL": {}, "NZL": {}, "NIC": {}, "NER": {}, "NGA": {}, "NIU": {}, "NFK": {}, "MKD": {}, "MNP": {}, "NOR": {}, "OMN": {}, "PAK": {}, "PLW": {}, "PSE": {}, "PAN": {}, "PNG": {}, "PRY": {}, "PER": {}, "PHL": {}, "PCN": {}, "POL": {}, "PRT": {}, "PRI": {}, "QAT": {}, "ROU": {}, "RUS": {}, "RWA": {}, "REU": {}, "BLM": {}, "SHN": {}, "KNA": {}, "LCA": {}, "MAF": {}, "SPM": {}, "VCT": {}, "WSM": {}, "SMR": {}, "STP": {}, "SAU": {}, "SEN": {}, "SRB": {}, "SYC": {}, "SLE": {}, "SGP": {}, "SXM": {}, "SVK": {}, "SVN": {}, "SLB": {}, "SOM": {}, "ZAF": {}, "SGS": {}, "SSD": {}, "ESP": {}, "LKA": {}, "SDN": {}, "SUR": {}, "SJM": {}, "SWE": {}, "CHE": {}, "SYR": {}, "TWN": {}, "TJK": {}, "TZA": {}, "THA": {}, "TLS": {}, "TGO": {}, "TKL": {}, "TON": {}, "TTO": {}, "TUN": {}, "TUR": {}, "TKM": {}, "TCA": {}, "TUV": {}, "UGA": {}, "UKR": {}, "ARE": {}, "GBR": {}, "UMI": {}, "USA": {}, "URY": {}, "UZB": {}, "VUT": {}, "VEN": {}, "VNM": {}, "VGB": {}, "VIR": {}, "WLF": {}, "ESH": {}, "YEM": {}, "ZMB": {}, "ZWE": {}, "ALA": {}, "UNK": {}, } var iso3166_1_alpha3_eu = map[string]struct{}{ "AUT": {}, "BEL": {}, "BGR": {}, "HRV": {}, "CYP": {}, "CZE": {}, "DNK": {}, "EST": {}, "FIN": {}, "FRA": {}, "DEU": {}, "GRC": {}, "HUN": {}, "IRL": {}, "ITA": {}, "LVA": {}, "LTU": {}, "LUX": {}, "MLT": {}, "NLD": {}, "POL": {}, "PRT": {}, "ROU": {}, "SVK": {}, "SVN": {}, "ESP": {}, "SWE": {}, } var iso3166_1_alpha_numeric = map[int]struct{}{ // see: https://www.iso.org/iso-3166-country-codes.html 4: {}, 8: {}, 12: {}, 16: {}, 20: {}, 24: {}, 660: {}, 10: {}, 28: {}, 32: {}, 51: {}, 533: {}, 36: {}, 40: {}, 31: {}, 44: {}, 48: {}, 50: {}, 52: {}, 112: {}, 56: {}, 84: {}, 204: {}, 60: {}, 64: {}, 68: {}, 535: {}, 70: {}, 72: {}, 74: {}, 76: {}, 86: {}, 96: {}, 100: {}, 854: {}, 108: {}, 132: {}, 116: {}, 120: {}, 124: {}, 136: {}, 140: {}, 148: {}, 152: {}, 156: {}, 162: {}, 166: {}, 170: {}, 174: {}, 180: {}, 178: {}, 184: {}, 188: {}, 191: {}, 192: {}, 531: {}, 196: {}, 203: {}, 384: {}, 208: {}, 262: {}, 212: {}, 214: {}, 218: {}, 818: {}, 222: {}, 226: {}, 232: {}, 233: {}, 748: {}, 231: {}, 238: {}, 234: {}, 242: {}, 246: {}, 250: {}, 254: {}, 258: {}, 260: {}, 266: {}, 270: {}, 268: {}, 276: {}, 288: {}, 292: {}, 300: {}, 304: {}, 308: {}, 312: {}, 316: {}, 320: {}, 831: {}, 324: {}, 624: {}, 328: {}, 332: {}, 334: {}, 336: {}, 340: {}, 344: {}, 348: {}, 352: {}, 356: {}, 360: {}, 364: {}, 368: {}, 372: {}, 833: {}, 376: {}, 380: {}, 388: {}, 392: {}, 832: {}, 400: {}, 398: {}, 404: {}, 296: {}, 408: {}, 410: {}, 414: {}, 417: {}, 418: {}, 428: {}, 422: {}, 426: {}, 430: {}, 434: {}, 438: {}, 440: {}, 442: {}, 446: {}, 450: {}, 454: {}, 458: {}, 462: {}, 466: {}, 470: {}, 584: {}, 474: {}, 478: {}, 480: {}, 175: {}, 484: {}, 583: {}, 498: {}, 492: {}, 496: {}, 499: {}, 500: {}, 504: {}, 508: {}, 104: {}, 516: {}, 520: {}, 524: {}, 528: {}, 540: {}, 554: {}, 558: {}, 562: {}, 566: {}, 570: {}, 574: {}, 807: {}, 580: {}, 578: {}, 512: {}, 586: {}, 585: {}, 275: {}, 591: {}, 598: {}, 600: {}, 604: {}, 608: {}, 612: {}, 616: {}, 620: {}, 630: {}, 634: {}, 642: {}, 643: {}, 646: {}, 638: {}, 652: {}, 654: {}, 659: {}, 662: {}, 663: {}, 666: {}, 670: {}, 882: {}, 674: {}, 678: {}, 682: {}, 686: {}, 688: {}, 690: {}, 694: {}, 702: {}, 534: {}, 703: {}, 705: {}, 90: {}, 706: {}, 710: {}, 239: {}, 728: {}, 724: {}, 144: {}, 729: {}, 740: {}, 744: {}, 752: {}, 756: {}, 760: {}, 158: {}, 762: {}, 834: {}, 764: {}, 626: {}, 768: {}, 772: {}, 776: {}, 780: {}, 788: {}, 792: {}, 795: {}, 796: {}, 798: {}, 800: {}, 804: {}, 784: {}, 826: {}, 581: {}, 840: {}, 858: {}, 860: {}, 548: {}, 862: {}, 704: {}, 92: {}, 850: {}, 876: {}, 732: {}, 887: {}, 894: {}, 716: {}, 248: {}, 153: {}, } var iso3166_1_alpha_numeric_eu = map[int]struct{}{ 40: {}, 56: {}, 100: {}, 191: {}, 196: {}, 200: {}, 208: {}, 233: {}, 246: {}, 250: {}, 276: {}, 300: {}, 348: {}, 372: {}, 380: {}, 428: {}, 440: {}, 442: {}, 470: {}, 528: {}, 616: {}, 620: {}, 642: {}, 703: {}, 705: {}, 724: {}, 752: {}, } var iso3166_2 = map[string]struct{}{ "AD-02": {}, "AD-03": {}, "AD-04": {}, "AD-05": {}, "AD-06": {}, "AD-07": {}, "AD-08": {}, "AE-AJ": {}, "AE-AZ": {}, "AE-DU": {}, "AE-FU": {}, "AE-RK": {}, "AE-SH": {}, "AE-UQ": {}, "AF-BAL": {}, "AF-BAM": {}, "AF-BDG": {}, "AF-BDS": {}, "AF-BGL": {}, "AF-DAY": {}, "AF-FRA": {}, "AF-FYB": {}, "AF-GHA": {}, "AF-GHO": {}, "AF-HEL": {}, "AF-HER": {}, "AF-JOW": {}, "AF-KAB": {}, "AF-KAN": {}, "AF-KAP": {}, "AF-KDZ": {}, "AF-KHO": {}, "AF-KNR": {}, "AF-LAG": {}, "AF-LOG": {}, "AF-NAN": {}, "AF-NIM": {}, "AF-NUR": {}, "AF-PAN": {}, "AF-PAR": {}, "AF-PIA": {}, "AF-PKA": {}, "AF-SAM": {}, "AF-SAR": {}, "AF-TAK": {}, "AF-URU": {}, "AF-WAR": {}, "AF-ZAB": {}, "AG-03": {}, "AG-04": {}, "AG-05": {}, "AG-06": {}, "AG-07": {}, "AG-08": {}, "AG-10": {}, "AG-11": {}, "AL-01": {}, "AL-02": {}, "AL-03": {}, "AL-04": {}, "AL-05": {}, "AL-06": {}, "AL-07": {}, "AL-08": {}, "AL-09": {}, "AL-10": {}, "AL-11": {}, "AL-12": {}, "AL-BR": {}, "AL-BU": {}, "AL-DI": {}, "AL-DL": {}, "AL-DR": {}, "AL-DV": {}, "AL-EL": {}, "AL-ER": {}, "AL-FR": {}, "AL-GJ": {}, "AL-GR": {}, "AL-HA": {}, "AL-KA": {}, "AL-KB": {}, "AL-KC": {}, "AL-KO": {}, "AL-KR": {}, "AL-KU": {}, "AL-LB": {}, "AL-LE": {}, "AL-LU": {}, "AL-MK": {}, "AL-MM": {}, "AL-MR": {}, "AL-MT": {}, "AL-PG": {}, "AL-PQ": {}, "AL-PR": {}, "AL-PU": {}, "AL-SH": {}, "AL-SK": {}, "AL-SR": {}, "AL-TE": {}, "AL-TP": {}, "AL-TR": {}, "AL-VL": {}, "AM-AG": {}, "AM-AR": {}, "AM-AV": {}, "AM-ER": {}, "AM-GR": {}, "AM-KT": {}, "AM-LO": {}, "AM-SH": {}, "AM-SU": {}, "AM-TV": {}, "AM-VD": {}, "AO-BGO": {}, "AO-BGU": {}, "AO-BIE": {}, "AO-CAB": {}, "AO-CCU": {}, "AO-CNN": {}, "AO-CNO": {}, "AO-CUS": {}, "AO-HUA": {}, "AO-HUI": {}, "AO-LNO": {}, "AO-LSU": {}, "AO-LUA": {}, "AO-MAL": {}, "AO-MOX": {}, "AO-NAM": {}, "AO-UIG": {}, "AO-ZAI": {}, "AR-A": {}, "AR-B": {}, "AR-C": {}, "AR-D": {}, "AR-E": {}, "AR-F": {}, "AR-G": {}, "AR-H": {}, "AR-J": {}, "AR-K": {}, "AR-L": {}, "AR-M": {}, "AR-N": {}, "AR-P": {}, "AR-Q": {}, "AR-R": {}, "AR-S": {}, "AR-T": {}, "AR-U": {}, "AR-V": {}, "AR-W": {}, "AR-X": {}, "AR-Y": {}, "AR-Z": {}, "AT-1": {}, "AT-2": {}, "AT-3": {}, "AT-4": {}, "AT-5": {}, "AT-6": {}, "AT-7": {}, "AT-8": {}, "AT-9": {}, "AU-ACT": {}, "AU-NSW": {}, "AU-NT": {}, "AU-QLD": {}, "AU-SA": {}, "AU-TAS": {}, "AU-VIC": {}, "AU-WA": {}, "AZ-ABS": {}, "AZ-AGA": {}, "AZ-AGC": {}, "AZ-AGM": {}, "AZ-AGS": {}, "AZ-AGU": {}, "AZ-AST": {}, "AZ-BA": {}, "AZ-BAB": {}, "AZ-BAL": {}, "AZ-BAR": {}, "AZ-BEY": {}, "AZ-BIL": {}, "AZ-CAB": {}, "AZ-CAL": {}, "AZ-CUL": {}, "AZ-DAS": {}, "AZ-FUZ": {}, "AZ-GA": {}, "AZ-GAD": {}, "AZ-GOR": {}, "AZ-GOY": {}, "AZ-GYG": {}, "AZ-HAC": {}, "AZ-IMI": {}, "AZ-ISM": {}, "AZ-KAL": {}, "AZ-KAN": {}, "AZ-KUR": {}, "AZ-LA": {}, "AZ-LAC": {}, "AZ-LAN": {}, "AZ-LER": {}, "AZ-MAS": {}, "AZ-MI": {}, "AZ-NA": {}, "AZ-NEF": {}, "AZ-NV": {}, "AZ-NX": {}, "AZ-OGU": {}, "AZ-ORD": {}, "AZ-QAB": {}, "AZ-QAX": {}, "AZ-QAZ": {}, "AZ-QBA": {}, "AZ-QBI": {}, "AZ-QOB": {}, "AZ-QUS": {}, "AZ-SA": {}, "AZ-SAB": {}, "AZ-SAD": {}, "AZ-SAH": {}, "AZ-SAK": {}, "AZ-SAL": {}, "AZ-SAR": {}, "AZ-SAT": {}, "AZ-SBN": {}, "AZ-SIY": {}, "AZ-SKR": {}, "AZ-SM": {}, "AZ-SMI": {}, "AZ-SMX": {}, "AZ-SR": {}, "AZ-SUS": {}, "AZ-TAR": {}, "AZ-TOV": {}, "AZ-UCA": {}, "AZ-XA": {}, "AZ-XAC": {}, "AZ-XCI": {}, "AZ-XIZ": {}, "AZ-XVD": {}, "AZ-YAR": {}, "AZ-YE": {}, "AZ-YEV": {}, "AZ-ZAN": {}, "AZ-ZAQ": {}, "AZ-ZAR": {}, "BA-01": {}, "BA-02": {}, "BA-03": {}, "BA-04": {}, "BA-05": {}, "BA-06": {}, "BA-07": {}, "BA-08": {}, "BA-09": {}, "BA-10": {}, "BA-BIH": {}, "BA-BRC": {}, "BA-SRP": {}, "BB-01": {}, "BB-02": {}, "BB-03": {}, "BB-04": {}, "BB-05": {}, "BB-06": {}, "BB-07": {}, "BB-08": {}, "BB-09": {}, "BB-10": {}, "BB-11": {}, "BD-01": {}, "BD-02": {}, "BD-03": {}, "BD-04": {}, "BD-05": {}, "BD-06": {}, "BD-07": {}, "BD-08": {}, "BD-09": {}, "BD-10": {}, "BD-11": {}, "BD-12": {}, "BD-13": {}, "BD-14": {}, "BD-15": {}, "BD-16": {}, "BD-17": {}, "BD-18": {}, "BD-19": {}, "BD-20": {}, "BD-21": {}, "BD-22": {}, "BD-23": {}, "BD-24": {}, "BD-25": {}, "BD-26": {}, "BD-27": {}, "BD-28": {}, "BD-29": {}, "BD-30": {}, "BD-31": {}, "BD-32": {}, "BD-33": {}, "BD-34": {}, "BD-35": {}, "BD-36": {}, "BD-37": {}, "BD-38": {}, "BD-39": {}, "BD-40": {}, "BD-41": {}, "BD-42": {}, "BD-43": {}, "BD-44": {}, "BD-45": {}, "BD-46": {}, "BD-47": {}, "BD-48": {}, "BD-49": {}, "BD-50": {}, "BD-51": {}, "BD-52": {}, "BD-53": {}, "BD-54": {}, "BD-55": {}, "BD-56": {}, "BD-57": {}, "BD-58": {}, "BD-59": {}, "BD-60": {}, "BD-61": {}, "BD-62": {}, "BD-63": {}, "BD-64": {}, "BD-A": {}, "BD-B": {}, "BD-C": {}, "BD-D": {}, "BD-E": {}, "BD-F": {}, "BD-G": {}, "BD-H": {}, "BE-BRU": {}, "BE-VAN": {}, "BE-VBR": {}, "BE-VLG": {}, "BE-VLI": {}, "BE-VOV": {}, "BE-VWV": {}, "BE-WAL": {}, "BE-WBR": {}, "BE-WHT": {}, "BE-WLG": {}, "BE-WLX": {}, "BE-WNA": {}, "BF-01": {}, "BF-02": {}, "BF-03": {}, "BF-04": {}, "BF-05": {}, "BF-06": {}, "BF-07": {}, "BF-08": {}, "BF-09": {}, "BF-10": {}, "BF-11": {}, "BF-12": {}, "BF-13": {}, "BF-BAL": {}, "BF-BAM": {}, "BF-BAN": {}, "BF-BAZ": {}, "BF-BGR": {}, "BF-BLG": {}, "BF-BLK": {}, "BF-COM": {}, "BF-GAN": {}, "BF-GNA": {}, "BF-GOU": {}, "BF-HOU": {}, "BF-IOB": {}, "BF-KAD": {}, "BF-KEN": {}, "BF-KMD": {}, "BF-KMP": {}, "BF-KOP": {}, "BF-KOS": {}, "BF-KOT": {}, "BF-KOW": {}, "BF-LER": {}, "BF-LOR": {}, "BF-MOU": {}, "BF-NAM": {}, "BF-NAO": {}, "BF-NAY": {}, "BF-NOU": {}, "BF-OUB": {}, "BF-OUD": {}, "BF-PAS": {}, "BF-PON": {}, "BF-SEN": {}, "BF-SIS": {}, "BF-SMT": {}, "BF-SNG": {}, "BF-SOM": {}, "BF-SOR": {}, "BF-TAP": {}, "BF-TUI": {}, "BF-YAG": {}, "BF-YAT": {}, "BF-ZIR": {}, "BF-ZON": {}, "BF-ZOU": {}, "BG-01": {}, "BG-02": {}, "BG-03": {}, "BG-04": {}, "BG-05": {}, "BG-06": {}, "BG-07": {}, "BG-08": {}, "BG-09": {}, "BG-10": {}, "BG-11": {}, "BG-12": {}, "BG-13": {}, "BG-14": {}, "BG-15": {}, "BG-16": {}, "BG-17": {}, "BG-18": {}, "BG-19": {}, "BG-20": {}, "BG-21": {}, "BG-22": {}, "BG-23": {}, "BG-24": {}, "BG-25": {}, "BG-26": {}, "BG-27": {}, "BG-28": {}, "BH-13": {}, "BH-14": {}, "BH-15": {}, "BH-16": {}, "BH-17": {}, "BI-BB": {}, "BI-BL": {}, "BI-BM": {}, "BI-BR": {}, "BI-CA": {}, "BI-CI": {}, "BI-GI": {}, "BI-KI": {}, "BI-KR": {}, "BI-KY": {}, "BI-MA": {}, "BI-MU": {}, "BI-MW": {}, "BI-NG": {}, "BI-RM": {}, "BI-RT": {}, "BI-RY": {}, "BJ-AK": {}, "BJ-AL": {}, "BJ-AQ": {}, "BJ-BO": {}, "BJ-CO": {}, "BJ-DO": {}, "BJ-KO": {}, "BJ-LI": {}, "BJ-MO": {}, "BJ-OU": {}, "BJ-PL": {}, "BJ-ZO": {}, "BN-BE": {}, "BN-BM": {}, "BN-TE": {}, "BN-TU": {}, "BO-B": {}, "BO-C": {}, "BO-H": {}, "BO-L": {}, "BO-N": {}, "BO-O": {}, "BO-P": {}, "BO-S": {}, "BO-T": {}, "BQ-BO": {}, "BQ-SA": {}, "BQ-SE": {}, "BR-AC": {}, "BR-AL": {}, "BR-AM": {}, "BR-AP": {}, "BR-BA": {}, "BR-CE": {}, "BR-DF": {}, "BR-ES": {}, "BR-FN": {}, "BR-GO": {}, "BR-MA": {}, "BR-MG": {}, "BR-MS": {}, "BR-MT": {}, "BR-PA": {}, "BR-PB": {}, "BR-PE": {}, "BR-PI": {}, "BR-PR": {}, "BR-RJ": {}, "BR-RN": {}, "BR-RO": {}, "BR-RR": {}, "BR-RS": {}, "BR-SC": {}, "BR-SE": {}, "BR-SP": {}, "BR-TO": {}, "BS-AK": {}, "BS-BI": {}, "BS-BP": {}, "BS-BY": {}, "BS-CE": {}, "BS-CI": {}, "BS-CK": {}, "BS-CO": {}, "BS-CS": {}, "BS-EG": {}, "BS-EX": {}, "BS-FP": {}, "BS-GC": {}, "BS-HI": {}, "BS-HT": {}, "BS-IN": {}, "BS-LI": {}, "BS-MC": {}, "BS-MG": {}, "BS-MI": {}, "BS-NE": {}, "BS-NO": {}, "BS-NP": {}, "BS-NS": {}, "BS-RC": {}, "BS-RI": {}, "BS-SA": {}, "BS-SE": {}, "BS-SO": {}, "BS-SS": {}, "BS-SW": {}, "BS-WG": {}, "BT-11": {}, "BT-12": {}, "BT-13": {}, "BT-14": {}, "BT-15": {}, "BT-21": {}, "BT-22": {}, "BT-23": {}, "BT-24": {}, "BT-31": {}, "BT-32": {}, "BT-33": {}, "BT-34": {}, "BT-41": {}, "BT-42": {}, "BT-43": {}, "BT-44": {}, "BT-45": {}, "BT-GA": {}, "BT-TY": {}, "BW-CE": {}, "BW-CH": {}, "BW-GH": {}, "BW-KG": {}, "BW-KL": {}, "BW-KW": {}, "BW-NE": {}, "BW-NW": {}, "BW-SE": {}, "BW-SO": {}, "BY-BR": {}, "BY-HM": {}, "BY-HO": {}, "BY-HR": {}, "BY-MA": {}, "BY-MI": {}, "BY-VI": {}, "BZ-BZ": {}, "BZ-CY": {}, "BZ-CZL": {}, "BZ-OW": {}, "BZ-SC": {}, "BZ-TOL": {}, "CA-AB": {}, "CA-BC": {}, "CA-MB": {}, "CA-NB": {}, "CA-NL": {}, "CA-NS": {}, "CA-NT": {}, "CA-NU": {}, "CA-ON": {}, "CA-PE": {}, "CA-QC": {}, "CA-SK": {}, "CA-YT": {}, "CD-BC": {}, "CD-BN": {}, "CD-EQ": {}, "CD-HK": {}, "CD-IT": {}, "CD-KA": {}, "CD-KC": {}, "CD-KE": {}, "CD-KG": {}, "CD-KN": {}, "CD-KW": {}, "CD-KS": {}, "CD-LU": {}, "CD-MA": {}, "CD-NK": {}, "CD-OR": {}, "CD-SA": {}, "CD-SK": {}, "CD-TA": {}, "CD-TO": {}, "CF-AC": {}, "CF-BB": {}, "CF-BGF": {}, "CF-BK": {}, "CF-HK": {}, "CF-HM": {}, "CF-HS": {}, "CF-KB": {}, "CF-KG": {}, "CF-LB": {}, "CF-MB": {}, "CF-MP": {}, "CF-NM": {}, "CF-OP": {}, "CF-SE": {}, "CF-UK": {}, "CF-VK": {}, "CG-11": {}, "CG-12": {}, "CG-13": {}, "CG-14": {}, "CG-15": {}, "CG-16": {}, "CG-2": {}, "CG-5": {}, "CG-7": {}, "CG-8": {}, "CG-9": {}, "CG-BZV": {}, "CH-AG": {}, "CH-AI": {}, "CH-AR": {}, "CH-BE": {}, "CH-BL": {}, "CH-BS": {}, "CH-FR": {}, "CH-GE": {}, "CH-GL": {}, "CH-GR": {}, "CH-JU": {}, "CH-LU": {}, "CH-NE": {}, "CH-NW": {}, "CH-OW": {}, "CH-SG": {}, "CH-SH": {}, "CH-SO": {}, "CH-SZ": {}, "CH-TG": {}, "CH-TI": {}, "CH-UR": {}, "CH-VD": {}, "CH-VS": {}, "CH-ZG": {}, "CH-ZH": {}, "CI-AB": {}, "CI-BS": {}, "CI-CM": {}, "CI-DN": {}, "CI-GD": {}, "CI-LC": {}, "CI-LG": {}, "CI-MG": {}, "CI-SM": {}, "CI-SV": {}, "CI-VB": {}, "CI-WR": {}, "CI-YM": {}, "CI-ZZ": {}, "CL-AI": {}, "CL-AN": {}, "CL-AP": {}, "CL-AR": {}, "CL-AT": {}, "CL-BI": {}, "CL-CO": {}, "CL-LI": {}, "CL-LL": {}, "CL-LR": {}, "CL-MA": {}, "CL-ML": {}, "CL-NB": {}, "CL-RM": {}, "CL-TA": {}, "CL-VS": {}, "CM-AD": {}, "CM-CE": {}, "CM-EN": {}, "CM-ES": {}, "CM-LT": {}, "CM-NO": {}, "CM-NW": {}, "CM-OU": {}, "CM-SU": {}, "CM-SW": {}, "CN-AH": {}, "CN-BJ": {}, "CN-CQ": {}, "CN-FJ": {}, "CN-GS": {}, "CN-GD": {}, "CN-GX": {}, "CN-GZ": {}, "CN-HI": {}, "CN-HE": {}, "CN-HL": {}, "CN-HA": {}, "CN-HB": {}, "CN-HN": {}, "CN-JS": {}, "CN-JX": {}, "CN-JL": {}, "CN-LN": {}, "CN-NM": {}, "CN-NX": {}, "CN-QH": {}, "CN-SN": {}, "CN-SD": {}, "CN-SH": {}, "CN-SX": {}, "CN-SC": {}, "CN-TJ": {}, "CN-XJ": {}, "CN-XZ": {}, "CN-YN": {}, "CN-ZJ": {}, "CO-AMA": {}, "CO-ANT": {}, "CO-ARA": {}, "CO-ATL": {}, "CO-BOL": {}, "CO-BOY": {}, "CO-CAL": {}, "CO-CAQ": {}, "CO-CAS": {}, "CO-CAU": {}, "CO-CES": {}, "CO-CHO": {}, "CO-COR": {}, "CO-CUN": {}, "CO-DC": {}, "CO-GUA": {}, "CO-GUV": {}, "CO-HUI": {}, "CO-LAG": {}, "CO-MAG": {}, "CO-MET": {}, "CO-NAR": {}, "CO-NSA": {}, "CO-PUT": {}, "CO-QUI": {}, "CO-RIS": {}, "CO-SAN": {}, "CO-SAP": {}, "CO-SUC": {}, "CO-TOL": {}, "CO-VAC": {}, "CO-VAU": {}, "CO-VID": {}, "CR-A": {}, "CR-C": {}, "CR-G": {}, "CR-H": {}, "CR-L": {}, "CR-P": {}, "CR-SJ": {}, "CU-01": {}, "CU-02": {}, "CU-03": {}, "CU-04": {}, "CU-05": {}, "CU-06": {}, "CU-07": {}, "CU-08": {}, "CU-09": {}, "CU-10": {}, "CU-11": {}, "CU-12": {}, "CU-13": {}, "CU-14": {}, "CU-15": {}, "CU-16": {}, "CU-99": {}, "CV-B": {}, "CV-BR": {}, "CV-BV": {}, "CV-CA": {}, "CV-CF": {}, "CV-CR": {}, "CV-MA": {}, "CV-MO": {}, "CV-PA": {}, "CV-PN": {}, "CV-PR": {}, "CV-RB": {}, "CV-RG": {}, "CV-RS": {}, "CV-S": {}, "CV-SD": {}, "CV-SF": {}, "CV-SL": {}, "CV-SM": {}, "CV-SO": {}, "CV-SS": {}, "CV-SV": {}, "CV-TA": {}, "CV-TS": {}, "CY-01": {}, "CY-02": {}, "CY-03": {}, "CY-04": {}, "CY-05": {}, "CY-06": {}, "CZ-10": {}, "CZ-101": {}, "CZ-102": {}, "CZ-103": {}, "CZ-104": {}, "CZ-105": {}, "CZ-106": {}, "CZ-107": {}, "CZ-108": {}, "CZ-109": {}, "CZ-110": {}, "CZ-111": {}, "CZ-112": {}, "CZ-113": {}, "CZ-114": {}, "CZ-115": {}, "CZ-116": {}, "CZ-117": {}, "CZ-118": {}, "CZ-119": {}, "CZ-120": {}, "CZ-121": {}, "CZ-122": {}, "CZ-20": {}, "CZ-201": {}, "CZ-202": {}, "CZ-203": {}, "CZ-204": {}, "CZ-205": {}, "CZ-206": {}, "CZ-207": {}, "CZ-208": {}, "CZ-209": {}, "CZ-20A": {}, "CZ-20B": {}, "CZ-20C": {}, "CZ-31": {}, "CZ-311": {}, "CZ-312": {}, "CZ-313": {}, "CZ-314": {}, "CZ-315": {}, "CZ-316": {}, "CZ-317": {}, "CZ-32": {}, "CZ-321": {}, "CZ-322": {}, "CZ-323": {}, "CZ-324": {}, "CZ-325": {}, "CZ-326": {}, "CZ-327": {}, "CZ-41": {}, "CZ-411": {}, "CZ-412": {}, "CZ-413": {}, "CZ-42": {}, "CZ-421": {}, "CZ-422": {}, "CZ-423": {}, "CZ-424": {}, "CZ-425": {}, "CZ-426": {}, "CZ-427": {}, "CZ-51": {}, "CZ-511": {}, "CZ-512": {}, "CZ-513": {}, "CZ-514": {}, "CZ-52": {}, "CZ-521": {}, "CZ-522": {}, "CZ-523": {}, "CZ-524": {}, "CZ-525": {}, "CZ-53": {}, "CZ-531": {}, "CZ-532": {}, "CZ-533": {}, "CZ-534": {}, "CZ-63": {}, "CZ-631": {}, "CZ-632": {}, "CZ-633": {}, "CZ-634": {}, "CZ-635": {}, "CZ-64": {}, "CZ-641": {}, "CZ-642": {}, "CZ-643": {}, "CZ-644": {}, "CZ-645": {}, "CZ-646": {}, "CZ-647": {}, "CZ-71": {}, "CZ-711": {}, "CZ-712": {}, "CZ-713": {}, "CZ-714": {}, "CZ-715": {}, "CZ-72": {}, "CZ-721": {}, "CZ-722": {}, "CZ-723": {}, "CZ-724": {}, "CZ-80": {}, "CZ-801": {}, "CZ-802": {}, "CZ-803": {}, "CZ-804": {}, "CZ-805": {}, "CZ-806": {}, "DE-BB": {}, "DE-BE": {}, "DE-BW": {}, "DE-BY": {}, "DE-HB": {}, "DE-HE": {}, "DE-HH": {}, "DE-MV": {}, "DE-NI": {}, "DE-NW": {}, "DE-RP": {}, "DE-SH": {}, "DE-SL": {}, "DE-SN": {}, "DE-ST": {}, "DE-TH": {}, "DJ-AR": {}, "DJ-AS": {}, "DJ-DI": {}, "DJ-DJ": {}, "DJ-OB": {}, "DJ-TA": {}, "DK-81": {}, "DK-82": {}, "DK-83": {}, "DK-84": {}, "DK-85": {}, "DM-01": {}, "DM-02": {}, "DM-03": {}, "DM-04": {}, "DM-05": {}, "DM-06": {}, "DM-07": {}, "DM-08": {}, "DM-09": {}, "DM-10": {}, "DO-01": {}, "DO-02": {}, "DO-03": {}, "DO-04": {}, "DO-05": {}, "DO-06": {}, "DO-07": {}, "DO-08": {}, "DO-09": {}, "DO-10": {}, "DO-11": {}, "DO-12": {}, "DO-13": {}, "DO-14": {}, "DO-15": {}, "DO-16": {}, "DO-17": {}, "DO-18": {}, "DO-19": {}, "DO-20": {}, "DO-21": {}, "DO-22": {}, "DO-23": {}, "DO-24": {}, "DO-25": {}, "DO-26": {}, "DO-27": {}, "DO-28": {}, "DO-29": {}, "DO-30": {}, "DO-31": {}, "DZ-01": {}, "DZ-02": {}, "DZ-03": {}, "DZ-04": {}, "DZ-05": {}, "DZ-06": {}, "DZ-07": {}, "DZ-08": {}, "DZ-09": {}, "DZ-10": {}, "DZ-11": {}, "DZ-12": {}, "DZ-13": {}, "DZ-14": {}, "DZ-15": {}, "DZ-16": {}, "DZ-17": {}, "DZ-18": {}, "DZ-19": {}, "DZ-20": {}, "DZ-21": {}, "DZ-22": {}, "DZ-23": {}, "DZ-24": {}, "DZ-25": {}, "DZ-26": {}, "DZ-27": {}, "DZ-28": {}, "DZ-29": {}, "DZ-30": {}, "DZ-31": {}, "DZ-32": {}, "DZ-33": {}, "DZ-34": {}, "DZ-35": {}, "DZ-36": {}, "DZ-37": {}, "DZ-38": {}, "DZ-39": {}, "DZ-40": {}, "DZ-41": {}, "DZ-42": {}, "DZ-43": {}, "DZ-44": {}, "DZ-45": {}, "DZ-46": {}, "DZ-47": {}, "DZ-48": {}, "DZ-49": {}, "DZ-51": {}, "DZ-53": {}, "DZ-55": {}, "DZ-56": {}, "DZ-57": {}, "EC-A": {}, "EC-B": {}, "EC-C": {}, "EC-D": {}, "EC-E": {}, "EC-F": {}, "EC-G": {}, "EC-H": {}, "EC-I": {}, "EC-L": {}, "EC-M": {}, "EC-N": {}, "EC-O": {}, "EC-P": {}, "EC-R": {}, "EC-S": {}, "EC-SD": {}, "EC-SE": {}, "EC-T": {}, "EC-U": {}, "EC-W": {}, "EC-X": {}, "EC-Y": {}, "EC-Z": {}, "EE-37": {}, "EE-39": {}, "EE-44": {}, "EE-45": {}, "EE-49": {}, "EE-50": {}, "EE-51": {}, "EE-52": {}, "EE-56": {}, "EE-57": {}, "EE-59": {}, "EE-60": {}, "EE-64": {}, "EE-65": {}, "EE-67": {}, "EE-68": {}, "EE-70": {}, "EE-71": {}, "EE-74": {}, "EE-78": {}, "EE-79": {}, "EE-81": {}, "EE-82": {}, "EE-84": {}, "EE-86": {}, "EE-87": {}, "EG-ALX": {}, "EG-ASN": {}, "EG-AST": {}, "EG-BA": {}, "EG-BH": {}, "EG-BNS": {}, "EG-C": {}, "EG-DK": {}, "EG-DT": {}, "EG-FYM": {}, "EG-GH": {}, "EG-GZ": {}, "EG-HU": {}, "EG-IS": {}, "EG-JS": {}, "EG-KB": {}, "EG-KFS": {}, "EG-KN": {}, "EG-LX": {}, "EG-MN": {}, "EG-MNF": {}, "EG-MT": {}, "EG-PTS": {}, "EG-SHG": {}, "EG-SHR": {}, "EG-SIN": {}, "EG-SU": {}, "EG-SUZ": {}, "EG-WAD": {}, "ER-AN": {}, "ER-DK": {}, "ER-DU": {}, "ER-GB": {}, "ER-MA": {}, "ER-SK": {}, "ES-A": {}, "ES-AB": {}, "ES-AL": {}, "ES-AN": {}, "ES-AR": {}, "ES-AS": {}, "ES-AV": {}, "ES-B": {}, "ES-BA": {}, "ES-BI": {}, "ES-BU": {}, "ES-C": {}, "ES-CA": {}, "ES-CB": {}, "ES-CC": {}, "ES-CE": {}, "ES-CL": {}, "ES-CM": {}, "ES-CN": {}, "ES-CO": {}, "ES-CR": {}, "ES-CS": {}, "ES-CT": {}, "ES-CU": {}, "ES-EX": {}, "ES-GA": {}, "ES-GC": {}, "ES-GI": {}, "ES-GR": {}, "ES-GU": {}, "ES-H": {}, "ES-HU": {}, "ES-IB": {}, "ES-J": {}, "ES-L": {}, "ES-LE": {}, "ES-LO": {}, "ES-LU": {}, "ES-M": {}, "ES-MA": {}, "ES-MC": {}, "ES-MD": {}, "ES-ML": {}, "ES-MU": {}, "ES-NA": {}, "ES-NC": {}, "ES-O": {}, "ES-OR": {}, "ES-P": {}, "ES-PM": {}, "ES-PO": {}, "ES-PV": {}, "ES-RI": {}, "ES-S": {}, "ES-SA": {}, "ES-SE": {}, "ES-SG": {}, "ES-SO": {}, "ES-SS": {}, "ES-T": {}, "ES-TE": {}, "ES-TF": {}, "ES-TO": {}, "ES-V": {}, "ES-VA": {}, "ES-VC": {}, "ES-VI": {}, "ES-Z": {}, "ES-ZA": {}, "ET-AA": {}, "ET-AF": {}, "ET-AM": {}, "ET-BE": {}, "ET-DD": {}, "ET-GA": {}, "ET-HA": {}, "ET-OR": {}, "ET-SN": {}, "ET-SO": {}, "ET-TI": {}, "FI-01": {}, "FI-02": {}, "FI-03": {}, "FI-04": {}, "FI-05": {}, "FI-06": {}, "FI-07": {}, "FI-08": {}, "FI-09": {}, "FI-10": {}, "FI-11": {}, "FI-12": {}, "FI-13": {}, "FI-14": {}, "FI-15": {}, "FI-16": {}, "FI-17": {}, "FI-18": {}, "FI-19": {}, "FJ-C": {}, "FJ-E": {}, "FJ-N": {}, "FJ-R": {}, "FJ-W": {}, "FM-KSA": {}, "FM-PNI": {}, "FM-TRK": {}, "FM-YAP": {}, "FR-01": {}, "FR-02": {}, "FR-03": {}, "FR-04": {}, "FR-05": {}, "FR-06": {}, "FR-07": {}, "FR-08": {}, "FR-09": {}, "FR-10": {}, "FR-11": {}, "FR-12": {}, "FR-13": {}, "FR-14": {}, "FR-15": {}, "FR-16": {}, "FR-17": {}, "FR-18": {}, "FR-19": {}, "FR-20R": {}, "FR-21": {}, "FR-22": {}, "FR-23": {}, "FR-24": {}, "FR-25": {}, "FR-26": {}, "FR-27": {}, "FR-28": {}, "FR-29": {}, "FR-2A": {}, "FR-2B": {}, "FR-30": {}, "FR-31": {}, "FR-32": {}, "FR-33": {}, "FR-34": {}, "FR-35": {}, "FR-36": {}, "FR-37": {}, "FR-38": {}, "FR-39": {}, "FR-40": {}, "FR-41": {}, "FR-42": {}, "FR-43": {}, "FR-44": {}, "FR-45": {}, "FR-46": {}, "FR-47": {}, "FR-48": {}, "FR-49": {}, "FR-50": {}, "FR-51": {}, "FR-52": {}, "FR-53": {}, "FR-54": {}, "FR-55": {}, "FR-56": {}, "FR-57": {}, "FR-58": {}, "FR-59": {}, "FR-60": {}, "FR-61": {}, "FR-62": {}, "FR-63": {}, "FR-64": {}, "FR-65": {}, "FR-66": {}, "FR-67": {}, "FR-68": {}, "FR-69": {}, "FR-70": {}, "FR-71": {}, "FR-72": {}, "FR-73": {}, "FR-74": {}, "FR-75": {}, "FR-76": {}, "FR-77": {}, "FR-78": {}, "FR-79": {}, "FR-80": {}, "FR-81": {}, "FR-82": {}, "FR-83": {}, "FR-84": {}, "FR-85": {}, "FR-86": {}, "FR-87": {}, "FR-88": {}, "FR-89": {}, "FR-90": {}, "FR-91": {}, "FR-92": {}, "FR-93": {}, "FR-94": {}, "FR-95": {}, "FR-ARA": {}, "FR-BFC": {}, "FR-BL": {}, "FR-BRE": {}, "FR-COR": {}, "FR-CP": {}, "FR-CVL": {}, "FR-GES": {}, "FR-GF": {}, "FR-GP": {}, "FR-GUA": {}, "FR-HDF": {}, "FR-IDF": {}, "FR-LRE": {}, "FR-MAY": {}, "FR-MF": {}, "FR-MQ": {}, "FR-NAQ": {}, "FR-NC": {}, "FR-NOR": {}, "FR-OCC": {}, "FR-PAC": {}, "FR-PDL": {}, "FR-PF": {}, "FR-PM": {}, "FR-RE": {}, "FR-TF": {}, "FR-WF": {}, "FR-YT": {}, "GA-1": {}, "GA-2": {}, "GA-3": {}, "GA-4": {}, "GA-5": {}, "GA-6": {}, "GA-7": {}, "GA-8": {}, "GA-9": {}, "GB-ABC": {}, "GB-ABD": {}, "GB-ABE": {}, "GB-AGB": {}, "GB-AGY": {}, "GB-AND": {}, "GB-ANN": {}, "GB-ANS": {}, "GB-BAS": {}, "GB-BBD": {}, "GB-BDF": {}, "GB-BDG": {}, "GB-BEN": {}, "GB-BEX": {}, "GB-BFS": {}, "GB-BGE": {}, "GB-BGW": {}, "GB-BIR": {}, "GB-BKM": {}, "GB-BMH": {}, "GB-BNE": {}, "GB-BNH": {}, "GB-BNS": {}, "GB-BOL": {}, "GB-BPL": {}, "GB-BRC": {}, "GB-BRD": {}, "GB-BRY": {}, "GB-BST": {}, "GB-BUR": {}, "GB-CAM": {}, "GB-CAY": {}, "GB-CBF": {}, "GB-CCG": {}, "GB-CGN": {}, "GB-CHE": {}, "GB-CHW": {}, "GB-CLD": {}, "GB-CLK": {}, "GB-CMA": {}, "GB-CMD": {}, "GB-CMN": {}, "GB-CON": {}, "GB-COV": {}, "GB-CRF": {}, "GB-CRY": {}, "GB-CWY": {}, "GB-DAL": {}, "GB-DBY": {}, "GB-DEN": {}, "GB-DER": {}, "GB-DEV": {}, "GB-DGY": {}, "GB-DNC": {}, "GB-DND": {}, "GB-DOR": {}, "GB-DRS": {}, "GB-DUD": {}, "GB-DUR": {}, "GB-EAL": {}, "GB-EAW": {}, "GB-EAY": {}, "GB-EDH": {}, "GB-EDU": {}, "GB-ELN": {}, "GB-ELS": {}, "GB-ENF": {}, "GB-ENG": {}, "GB-ERW": {}, "GB-ERY": {}, "GB-ESS": {}, "GB-ESX": {}, "GB-FAL": {}, "GB-FIF": {}, "GB-FLN": {}, "GB-FMO": {}, "GB-GAT": {}, "GB-GBN": {}, "GB-GLG": {}, "GB-GLS": {}, "GB-GRE": {}, "GB-GWN": {}, "GB-HAL": {}, "GB-HAM": {}, "GB-HAV": {}, "GB-HCK": {}, "GB-HEF": {}, "GB-HIL": {}, "GB-HLD": {}, "GB-HMF": {}, "GB-HNS": {}, "GB-HPL": {}, "GB-HRT": {}, "GB-HRW": {}, "GB-HRY": {}, "GB-IOS": {}, "GB-IOW": {}, "GB-ISL": {}, "GB-IVC": {}, "GB-KEC": {}, "GB-KEN": {}, "GB-KHL": {}, "GB-KIR": {}, "GB-KTT": {}, "GB-KWL": {}, "GB-LAN": {}, "GB-LBC": {}, "GB-LBH": {}, "GB-LCE": {}, "GB-LDS": {}, "GB-LEC": {}, "GB-LEW": {}, "GB-LIN": {}, "GB-LIV": {}, "GB-LND": {}, "GB-LUT": {}, "GB-MAN": {}, "GB-MDB": {}, "GB-MDW": {}, "GB-MEA": {}, "GB-MIK": {}, "GD-01": {}, "GB-MLN": {}, "GB-MON": {}, "GB-MRT": {}, "GB-MRY": {}, "GB-MTY": {}, "GB-MUL": {}, "GB-NAY": {}, "GB-NBL": {}, "GB-NEL": {}, "GB-NET": {}, "GB-NFK": {}, "GB-NGM": {}, "GB-NIR": {}, "GB-NLK": {}, "GB-NLN": {}, "GB-NMD": {}, "GB-NSM": {}, "GB-NTH": {}, "GB-NTL": {}, "GB-NTT": {}, "GB-NTY": {}, "GB-NWM": {}, "GB-NWP": {}, "GB-NYK": {}, "GB-OLD": {}, "GB-ORK": {}, "GB-OXF": {}, "GB-PEM": {}, "GB-PKN": {}, "GB-PLY": {}, "GB-POL": {}, "GB-POR": {}, "GB-POW": {}, "GB-PTE": {}, "GB-RCC": {}, "GB-RCH": {}, "GB-RCT": {}, "GB-RDB": {}, "GB-RDG": {}, "GB-RFW": {}, "GB-RIC": {}, "GB-ROT": {}, "GB-RUT": {}, "GB-SAW": {}, "GB-SAY": {}, "GB-SCB": {}, "GB-SCT": {}, "GB-SFK": {}, "GB-SFT": {}, "GB-SGC": {}, "GB-SHF": {}, "GB-SHN": {}, "GB-SHR": {}, "GB-SKP": {}, "GB-SLF": {}, "GB-SLG": {}, "GB-SLK": {}, "GB-SND": {}, "GB-SOL": {}, "GB-SOM": {}, "GB-SOS": {}, "GB-SRY": {}, "GB-STE": {}, "GB-STG": {}, "GB-STH": {}, "GB-STN": {}, "GB-STS": {}, "GB-STT": {}, "GB-STY": {}, "GB-SWA": {}, "GB-SWD": {}, "GB-SWK": {}, "GB-TAM": {}, "GB-TFW": {}, "GB-THR": {}, "GB-TOB": {}, "GB-TOF": {}, "GB-TRF": {}, "GB-TWH": {}, "GB-UKM": {}, "GB-VGL": {}, "GB-WAR": {}, "GB-WBK": {}, "GB-WDU": {}, "GB-WFT": {}, "GB-WGN": {}, "GB-WIL": {}, "GB-WKF": {}, "GB-WLL": {}, "GB-WLN": {}, "GB-WLS": {}, "GB-WLV": {}, "GB-WND": {}, "GB-WNM": {}, "GB-WOK": {}, "GB-WOR": {}, "GB-WRL": {}, "GB-WRT": {}, "GB-WRX": {}, "GB-WSM": {}, "GB-WSX": {}, "GB-YOR": {}, "GB-ZET": {}, "GD-02": {}, "GD-03": {}, "GD-04": {}, "GD-05": {}, "GD-06": {}, "GD-10": {}, "GE-AB": {}, "GE-AJ": {}, "GE-GU": {}, "GE-IM": {}, "GE-KA": {}, "GE-KK": {}, "GE-MM": {}, "GE-RL": {}, "GE-SJ": {}, "GE-SK": {}, "GE-SZ": {}, "GE-TB": {}, "GH-AA": {}, "GH-AH": {}, "GH-AF": {}, "GH-BA": {}, "GH-BO": {}, "GH-BE": {}, "GH-CP": {}, "GH-EP": {}, "GH-NP": {}, "GH-TV": {}, "GH-UE": {}, "GH-UW": {}, "GH-WP": {}, "GL-AV": {}, "GL-KU": {}, "GL-QA": {}, "GL-QT": {}, "GL-QE": {}, "GL-SM": {}, "GM-B": {}, "GM-L": {}, "GM-M": {}, "GM-N": {}, "GM-U": {}, "GM-W": {}, "GN-B": {}, "GN-BE": {}, "GN-BF": {}, "GN-BK": {}, "GN-C": {}, "GN-CO": {}, "GN-D": {}, "GN-DB": {}, "GN-DI": {}, "GN-DL": {}, "GN-DU": {}, "GN-F": {}, "GN-FA": {}, "GN-FO": {}, "GN-FR": {}, "GN-GA": {}, "GN-GU": {}, "GN-K": {}, "GN-KA": {}, "GN-KB": {}, "GN-KD": {}, "GN-KE": {}, "GN-KN": {}, "GN-KO": {}, "GN-KS": {}, "GN-L": {}, "GN-LA": {}, "GN-LE": {}, "GN-LO": {}, "GN-M": {}, "GN-MC": {}, "GN-MD": {}, "GN-ML": {}, "GN-MM": {}, "GN-N": {}, "GN-NZ": {}, "GN-PI": {}, "GN-SI": {}, "GN-TE": {}, "GN-TO": {}, "GN-YO": {}, "GQ-AN": {}, "GQ-BN": {}, "GQ-BS": {}, "GQ-C": {}, "GQ-CS": {}, "GQ-I": {}, "GQ-KN": {}, "GQ-LI": {}, "GQ-WN": {}, "GR-01": {}, "GR-03": {}, "GR-04": {}, "GR-05": {}, "GR-06": {}, "GR-07": {}, "GR-11": {}, "GR-12": {}, "GR-13": {}, "GR-14": {}, "GR-15": {}, "GR-16": {}, "GR-17": {}, "GR-21": {}, "GR-22": {}, "GR-23": {}, "GR-24": {}, "GR-31": {}, "GR-32": {}, "GR-33": {}, "GR-34": {}, "GR-41": {}, "GR-42": {}, "GR-43": {}, "GR-44": {}, "GR-51": {}, "GR-52": {}, "GR-53": {}, "GR-54": {}, "GR-55": {}, "GR-56": {}, "GR-57": {}, "GR-58": {}, "GR-59": {}, "GR-61": {}, "GR-62": {}, "GR-63": {}, "GR-64": {}, "GR-69": {}, "GR-71": {}, "GR-72": {}, "GR-73": {}, "GR-81": {}, "GR-82": {}, "GR-83": {}, "GR-84": {}, "GR-85": {}, "GR-91": {}, "GR-92": {}, "GR-93": {}, "GR-94": {}, "GR-A": {}, "GR-A1": {}, "GR-B": {}, "GR-C": {}, "GR-D": {}, "GR-E": {}, "GR-F": {}, "GR-G": {}, "GR-H": {}, "GR-I": {}, "GR-J": {}, "GR-K": {}, "GR-L": {}, "GR-M": {}, "GT-01": {}, "GT-02": {}, "GT-03": {}, "GT-04": {}, "GT-05": {}, "GT-06": {}, "GT-07": {}, "GT-08": {}, "GT-09": {}, "GT-10": {}, "GT-11": {}, "GT-12": {}, "GT-13": {}, "GT-14": {}, "GT-15": {}, "GT-16": {}, "GT-17": {}, "GT-18": {}, "GT-19": {}, "GT-20": {}, "GT-21": {}, "GT-22": {}, "GW-BA": {}, "GW-BL": {}, "GW-BM": {}, "GW-BS": {}, "GW-CA": {}, "GW-GA": {}, "GW-L": {}, "GW-N": {}, "GW-OI": {}, "GW-QU": {}, "GW-S": {}, "GW-TO": {}, "GY-BA": {}, "GY-CU": {}, "GY-DE": {}, "GY-EB": {}, "GY-ES": {}, "GY-MA": {}, "GY-PM": {}, "GY-PT": {}, "GY-UD": {}, "GY-UT": {}, "HN-AT": {}, "HN-CH": {}, "HN-CL": {}, "HN-CM": {}, "HN-CP": {}, "HN-CR": {}, "HN-EP": {}, "HN-FM": {}, "HN-GD": {}, "HN-IB": {}, "HN-IN": {}, "HN-LE": {}, "HN-LP": {}, "HN-OC": {}, "HN-OL": {}, "HN-SB": {}, "HN-VA": {}, "HN-YO": {}, "HR-01": {}, "HR-02": {}, "HR-03": {}, "HR-04": {}, "HR-05": {}, "HR-06": {}, "HR-07": {}, "HR-08": {}, "HR-09": {}, "HR-10": {}, "HR-11": {}, "HR-12": {}, "HR-13": {}, "HR-14": {}, "HR-15": {}, "HR-16": {}, "HR-17": {}, "HR-18": {}, "HR-19": {}, "HR-20": {}, "HR-21": {}, "HT-AR": {}, "HT-CE": {}, "HT-GA": {}, "HT-ND": {}, "HT-NE": {}, "HT-NO": {}, "HT-NI": {}, "HT-OU": {}, "HT-SD": {}, "HT-SE": {}, "HU-BA": {}, "HU-BC": {}, "HU-BE": {}, "HU-BK": {}, "HU-BU": {}, "HU-BZ": {}, "HU-CS": {}, "HU-DE": {}, "HU-DU": {}, "HU-EG": {}, "HU-ER": {}, "HU-FE": {}, "HU-GS": {}, "HU-GY": {}, "HU-HB": {}, "HU-HE": {}, "HU-HV": {}, "HU-JN": {}, "HU-KE": {}, "HU-KM": {}, "HU-KV": {}, "HU-MI": {}, "HU-NK": {}, "HU-NO": {}, "HU-NY": {}, "HU-PE": {}, "HU-PS": {}, "HU-SD": {}, "HU-SF": {}, "HU-SH": {}, "HU-SK": {}, "HU-SN": {}, "HU-SO": {}, "HU-SS": {}, "HU-ST": {}, "HU-SZ": {}, "HU-TB": {}, "HU-TO": {}, "HU-VA": {}, "HU-VE": {}, "HU-VM": {}, "HU-ZA": {}, "HU-ZE": {}, "ID-AC": {}, "ID-BA": {}, "ID-BB": {}, "ID-BE": {}, "ID-BT": {}, "ID-GO": {}, "ID-IJ": {}, "ID-JA": {}, "ID-JB": {}, "ID-JI": {}, "ID-JK": {}, "ID-JT": {}, "ID-JW": {}, "ID-KA": {}, "ID-KB": {}, "ID-KI": {}, "ID-KU": {}, "ID-KR": {}, "ID-KS": {}, "ID-KT": {}, "ID-LA": {}, "ID-MA": {}, "ID-ML": {}, "ID-MU": {}, "ID-NB": {}, "ID-NT": {}, "ID-NU": {}, "ID-PA": {}, "ID-PB": {}, "ID-PD": {}, "ID-PE": {}, "ID-PP": {}, "ID-PS": {}, "ID-PT": {}, "ID-RI": {}, "ID-SA": {}, "ID-SB": {}, "ID-SG": {}, "ID-SL": {}, "ID-SM": {}, "ID-SN": {}, "ID-SR": {}, "ID-SS": {}, "ID-ST": {}, "ID-SU": {}, "ID-YO": {}, "IE-C": {}, "IE-CE": {}, "IE-CN": {}, "IE-CO": {}, "IE-CW": {}, "IE-D": {}, "IE-DL": {}, "IE-G": {}, "IE-KE": {}, "IE-KK": {}, "IE-KY": {}, "IE-L": {}, "IE-LD": {}, "IE-LH": {}, "IE-LK": {}, "IE-LM": {}, "IE-LS": {}, "IE-M": {}, "IE-MH": {}, "IE-MN": {}, "IE-MO": {}, "IE-OY": {}, "IE-RN": {}, "IE-SO": {}, "IE-TA": {}, "IE-U": {}, "IE-WD": {}, "IE-WH": {}, "IE-WW": {}, "IE-WX": {}, "IL-D": {}, "IL-HA": {}, "IL-JM": {}, "IL-M": {}, "IL-TA": {}, "IL-Z": {}, "IN-AN": {}, "IN-AP": {}, "IN-AR": {}, "IN-AS": {}, "IN-BR": {}, "IN-CH": {}, "IN-CT": {}, "IN-DH": {}, "IN-DL": {}, "IN-DN": {}, "IN-GA": {}, "IN-GJ": {}, "IN-HP": {}, "IN-HR": {}, "IN-JH": {}, "IN-JK": {}, "IN-KA": {}, "IN-KL": {}, "IN-LA": {}, "IN-LD": {}, "IN-MH": {}, "IN-ML": {}, "IN-MN": {}, "IN-MP": {}, "IN-MZ": {}, "IN-NL": {}, "IN-TG": {}, "IN-OR": {}, "IN-PB": {}, "IN-PY": {}, "IN-RJ": {}, "IN-SK": {}, "IN-TN": {}, "IN-TR": {}, "IN-UP": {}, "IN-UT": {}, "IN-WB": {}, "IQ-AN": {}, "IQ-AR": {}, "IQ-BA": {}, "IQ-BB": {}, "IQ-BG": {}, "IQ-DA": {}, "IQ-DI": {}, "IQ-DQ": {}, "IQ-KA": {}, "IQ-KI": {}, "IQ-MA": {}, "IQ-MU": {}, "IQ-NA": {}, "IQ-NI": {}, "IQ-QA": {}, "IQ-SD": {}, "IQ-SW": {}, "IQ-SU": {}, "IQ-TS": {}, "IQ-WA": {}, "IR-00": {}, "IR-01": {}, "IR-02": {}, "IR-03": {}, "IR-04": {}, "IR-05": {}, "IR-06": {}, "IR-07": {}, "IR-08": {}, "IR-09": {}, "IR-10": {}, "IR-11": {}, "IR-12": {}, "IR-13": {}, "IR-14": {}, "IR-15": {}, "IR-16": {}, "IR-17": {}, "IR-18": {}, "IR-19": {}, "IR-20": {}, "IR-21": {}, "IR-22": {}, "IR-23": {}, "IR-24": {}, "IR-25": {}, "IR-26": {}, "IR-27": {}, "IR-28": {}, "IR-29": {}, "IR-30": {}, "IR-31": {}, "IS-0": {}, "IS-1": {}, "IS-2": {}, "IS-3": {}, "IS-4": {}, "IS-5": {}, "IS-6": {}, "IS-7": {}, "IS-8": {}, "IT-21": {}, "IT-23": {}, "IT-25": {}, "IT-32": {}, "IT-34": {}, "IT-36": {}, "IT-42": {}, "IT-45": {}, "IT-52": {}, "IT-55": {}, "IT-57": {}, "IT-62": {}, "IT-65": {}, "IT-67": {}, "IT-72": {}, "IT-75": {}, "IT-77": {}, "IT-78": {}, "IT-82": {}, "IT-88": {}, "IT-AG": {}, "IT-AL": {}, "IT-AN": {}, "IT-AO": {}, "IT-AP": {}, "IT-AQ": {}, "IT-AR": {}, "IT-AT": {}, "IT-AV": {}, "IT-BA": {}, "IT-BG": {}, "IT-BI": {}, "IT-BL": {}, "IT-BN": {}, "IT-BO": {}, "IT-BR": {}, "IT-BS": {}, "IT-BT": {}, "IT-BZ": {}, "IT-CA": {}, "IT-CB": {}, "IT-CE": {}, "IT-CH": {}, "IT-CI": {}, "IT-CL": {}, "IT-CN": {}, "IT-CO": {}, "IT-CR": {}, "IT-CS": {}, "IT-CT": {}, "IT-CZ": {}, "IT-EN": {}, "IT-FC": {}, "IT-FE": {}, "IT-FG": {}, "IT-FI": {}, "IT-FM": {}, "IT-FR": {}, "IT-GE": {}, "IT-GO": {}, "IT-GR": {}, "IT-IM": {}, "IT-IS": {}, "IT-KR": {}, "IT-LC": {}, "IT-LE": {}, "IT-LI": {}, "IT-LO": {}, "IT-LT": {}, "IT-LU": {}, "IT-MB": {}, "IT-MC": {}, "IT-ME": {}, "IT-MI": {}, "IT-MN": {}, "IT-MO": {}, "IT-MS": {}, "IT-MT": {}, "IT-NA": {}, "IT-NO": {}, "IT-NU": {}, "IT-OG": {}, "IT-OR": {}, "IT-OT": {}, "IT-PA": {}, "IT-PC": {}, "IT-PD": {}, "IT-PE": {}, "IT-PG": {}, "IT-PI": {}, "IT-PN": {}, "IT-PO": {}, "IT-PR": {}, "IT-PT": {}, "IT-PU": {}, "IT-PV": {}, "IT-PZ": {}, "IT-RA": {}, "IT-RC": {}, "IT-RE": {}, "IT-RG": {}, "IT-RI": {}, "IT-RM": {}, "IT-RN": {}, "IT-RO": {}, "IT-SA": {}, "IT-SI": {}, "IT-SO": {}, "IT-SP": {}, "IT-SR": {}, "IT-SS": {}, "IT-SV": {}, "IT-TA": {}, "IT-TE": {}, "IT-TN": {}, "IT-TO": {}, "IT-TP": {}, "IT-TR": {}, "IT-TS": {}, "IT-TV": {}, "IT-UD": {}, "IT-VA": {}, "IT-VB": {}, "IT-VC": {}, "IT-VE": {}, "IT-VI": {}, "IT-VR": {}, "IT-VS": {}, "IT-VT": {}, "IT-VV": {}, "JM-01": {}, "JM-02": {}, "JM-03": {}, "JM-04": {}, "JM-05": {}, "JM-06": {}, "JM-07": {}, "JM-08": {}, "JM-09": {}, "JM-10": {}, "JM-11": {}, "JM-12": {}, "JM-13": {}, "JM-14": {}, "JO-AJ": {}, "JO-AM": {}, "JO-AQ": {}, "JO-AT": {}, "JO-AZ": {}, "JO-BA": {}, "JO-IR": {}, "JO-JA": {}, "JO-KA": {}, "JO-MA": {}, "JO-MD": {}, "JO-MN": {}, "JP-01": {}, "JP-02": {}, "JP-03": {}, "JP-04": {}, "JP-05": {}, "JP-06": {}, "JP-07": {}, "JP-08": {}, "JP-09": {}, "JP-10": {}, "JP-11": {}, "JP-12": {}, "JP-13": {}, "JP-14": {}, "JP-15": {}, "JP-16": {}, "JP-17": {}, "JP-18": {}, "JP-19": {}, "JP-20": {}, "JP-21": {}, "JP-22": {}, "JP-23": {}, "JP-24": {}, "JP-25": {}, "JP-26": {}, "JP-27": {}, "JP-28": {}, "JP-29": {}, "JP-30": {}, "JP-31": {}, "JP-32": {}, "JP-33": {}, "JP-34": {}, "JP-35": {}, "JP-36": {}, "JP-37": {}, "JP-38": {}, "JP-39": {}, "JP-40": {}, "JP-41": {}, "JP-42": {}, "JP-43": {}, "JP-44": {}, "JP-45": {}, "JP-46": {}, "JP-47": {}, "KE-01": {}, "KE-02": {}, "KE-03": {}, "KE-04": {}, "KE-05": {}, "KE-06": {}, "KE-07": {}, "KE-08": {}, "KE-09": {}, "KE-10": {}, "KE-11": {}, "KE-12": {}, "KE-13": {}, "KE-14": {}, "KE-15": {}, "KE-16": {}, "KE-17": {}, "KE-18": {}, "KE-19": {}, "KE-20": {}, "KE-21": {}, "KE-22": {}, "KE-23": {}, "KE-24": {}, "KE-25": {}, "KE-26": {}, "KE-27": {}, "KE-28": {}, "KE-29": {}, "KE-30": {}, "KE-31": {}, "KE-32": {}, "KE-33": {}, "KE-34": {}, "KE-35": {}, "KE-36": {}, "KE-37": {}, "KE-38": {}, "KE-39": {}, "KE-40": {}, "KE-41": {}, "KE-42": {}, "KE-43": {}, "KE-44": {}, "KE-45": {}, "KE-46": {}, "KE-47": {}, "KG-B": {}, "KG-C": {}, "KG-GB": {}, "KG-GO": {}, "KG-J": {}, "KG-N": {}, "KG-O": {}, "KG-T": {}, "KG-Y": {}, "KH-1": {}, "KH-10": {}, "KH-11": {}, "KH-12": {}, "KH-13": {}, "KH-14": {}, "KH-15": {}, "KH-16": {}, "KH-17": {}, "KH-18": {}, "KH-19": {}, "KH-2": {}, "KH-20": {}, "KH-21": {}, "KH-22": {}, "KH-23": {}, "KH-24": {}, "KH-3": {}, "KH-4": {}, "KH-5": {}, "KH-6": {}, "KH-7": {}, "KH-8": {}, "KH-9": {}, "KI-G": {}, "KI-L": {}, "KI-P": {}, "KM-A": {}, "KM-G": {}, "KM-M": {}, "KN-01": {}, "KN-02": {}, "KN-03": {}, "KN-04": {}, "KN-05": {}, "KN-06": {}, "KN-07": {}, "KN-08": {}, "KN-09": {}, "KN-10": {}, "KN-11": {}, "KN-12": {}, "KN-13": {}, "KN-15": {}, "KN-K": {}, "KN-N": {}, "KP-01": {}, "KP-02": {}, "KP-03": {}, "KP-04": {}, "KP-05": {}, "KP-06": {}, "KP-07": {}, "KP-08": {}, "KP-09": {}, "KP-10": {}, "KP-13": {}, "KR-11": {}, "KR-26": {}, "KR-27": {}, "KR-28": {}, "KR-29": {}, "KR-30": {}, "KR-31": {}, "KR-41": {}, "KR-42": {}, "KR-43": {}, "KR-44": {}, "KR-45": {}, "KR-46": {}, "KR-47": {}, "KR-48": {}, "KR-49": {}, "KR-50": {}, "KW-AH": {}, "KW-FA": {}, "KW-HA": {}, "KW-JA": {}, "KW-KU": {}, "KW-MU": {}, "KZ-10": {}, "KZ-75": {}, "KZ-19": {}, "KZ-11": {}, "KZ-15": {}, "KZ-71": {}, "KZ-23": {}, "KZ-27": {}, "KZ-47": {}, "KZ-55": {}, "KZ-35": {}, "KZ-39": {}, "KZ-43": {}, "KZ-63": {}, "KZ-79": {}, "KZ-59": {}, "KZ-61": {}, "KZ-62": {}, "KZ-31": {}, "KZ-33": {}, "LA-AT": {}, "LA-BK": {}, "LA-BL": {}, "LA-CH": {}, "LA-HO": {}, "LA-KH": {}, "LA-LM": {}, "LA-LP": {}, "LA-OU": {}, "LA-PH": {}, "LA-SL": {}, "LA-SV": {}, "LA-VI": {}, "LA-VT": {}, "LA-XA": {}, "LA-XE": {}, "LA-XI": {}, "LA-XS": {}, "LB-AK": {}, "LB-AS": {}, "LB-BA": {}, "LB-BH": {}, "LB-BI": {}, "LB-JA": {}, "LB-JL": {}, "LB-NA": {}, "LC-01": {}, "LC-02": {}, "LC-03": {}, "LC-05": {}, "LC-06": {}, "LC-07": {}, "LC-08": {}, "LC-10": {}, "LC-11": {}, "LI-01": {}, "LI-02": {}, "LI-03": {}, "LI-04": {}, "LI-05": {}, "LI-06": {}, "LI-07": {}, "LI-08": {}, "LI-09": {}, "LI-10": {}, "LI-11": {}, "LK-1": {}, "LK-11": {}, "LK-12": {}, "LK-13": {}, "LK-2": {}, "LK-21": {}, "LK-22": {}, "LK-23": {}, "LK-3": {}, "LK-31": {}, "LK-32": {}, "LK-33": {}, "LK-4": {}, "LK-41": {}, "LK-42": {}, "LK-43": {}, "LK-44": {}, "LK-45": {}, "LK-5": {}, "LK-51": {}, "LK-52": {}, "LK-53": {}, "LK-6": {}, "LK-61": {}, "LK-62": {}, "LK-7": {}, "LK-71": {}, "LK-72": {}, "LK-8": {}, "LK-81": {}, "LK-82": {}, "LK-9": {}, "LK-91": {}, "LK-92": {}, "LR-BG": {}, "LR-BM": {}, "LR-CM": {}, "LR-GB": {}, "LR-GG": {}, "LR-GK": {}, "LR-LO": {}, "LR-MG": {}, "LR-MO": {}, "LR-MY": {}, "LR-NI": {}, "LR-RI": {}, "LR-SI": {}, "LS-A": {}, "LS-B": {}, "LS-C": {}, "LS-D": {}, "LS-E": {}, "LS-F": {}, "LS-G": {}, "LS-H": {}, "LS-J": {}, "LS-K": {}, "LT-AL": {}, "LT-KL": {}, "LT-KU": {}, "LT-MR": {}, "LT-PN": {}, "LT-SA": {}, "LT-TA": {}, "LT-TE": {}, "LT-UT": {}, "LT-VL": {}, "LU-CA": {}, "LU-CL": {}, "LU-DI": {}, "LU-EC": {}, "LU-ES": {}, "LU-GR": {}, "LU-LU": {}, "LU-ME": {}, "LU-RD": {}, "LU-RM": {}, "LU-VD": {}, "LU-WI": {}, "LU-D": {}, "LU-G": {}, "LU-L": {}, "LV-001": {}, "LV-111": {}, "LV-112": {}, "LV-113": {}, "LV-002": {}, "LV-003": {}, "LV-004": {}, "LV-005": {}, "LV-006": {}, "LV-007": {}, "LV-008": {}, "LV-009": {}, "LV-010": {}, "LV-011": {}, "LV-012": {}, "LV-013": {}, "LV-014": {}, "LV-015": {}, "LV-016": {}, "LV-017": {}, "LV-018": {}, "LV-019": {}, "LV-020": {}, "LV-021": {}, "LV-022": {}, "LV-023": {}, "LV-024": {}, "LV-025": {}, "LV-026": {}, "LV-027": {}, "LV-028": {}, "LV-029": {}, "LV-030": {}, "LV-031": {}, "LV-032": {}, "LV-033": {}, "LV-034": {}, "LV-035": {}, "LV-036": {}, "LV-037": {}, "LV-038": {}, "LV-039": {}, "LV-040": {}, "LV-041": {}, "LV-042": {}, "LV-043": {}, "LV-044": {}, "LV-045": {}, "LV-046": {}, "LV-047": {}, "LV-048": {}, "LV-049": {}, "LV-050": {}, "LV-051": {}, "LV-052": {}, "LV-053": {}, "LV-054": {}, "LV-055": {}, "LV-056": {}, "LV-057": {}, "LV-058": {}, "LV-059": {}, "LV-060": {}, "LV-061": {}, "LV-062": {}, "LV-063": {}, "LV-064": {}, "LV-065": {}, "LV-066": {}, "LV-067": {}, "LV-068": {}, "LV-069": {}, "LV-070": {}, "LV-071": {}, "LV-072": {}, "LV-073": {}, "LV-074": {}, "LV-075": {}, "LV-076": {}, "LV-077": {}, "LV-078": {}, "LV-079": {}, "LV-080": {}, "LV-081": {}, "LV-082": {}, "LV-083": {}, "LV-084": {}, "LV-085": {}, "LV-086": {}, "LV-087": {}, "LV-088": {}, "LV-089": {}, "LV-090": {}, "LV-091": {}, "LV-092": {}, "LV-093": {}, "LV-094": {}, "LV-095": {}, "LV-096": {}, "LV-097": {}, "LV-098": {}, "LV-099": {}, "LV-100": {}, "LV-101": {}, "LV-102": {}, "LV-103": {}, "LV-104": {}, "LV-105": {}, "LV-106": {}, "LV-107": {}, "LV-108": {}, "LV-109": {}, "LV-110": {}, "LV-DGV": {}, "LV-JEL": {}, "LV-JKB": {}, "LV-JUR": {}, "LV-LPX": {}, "LV-REZ": {}, "LV-RIX": {}, "LV-VEN": {}, "LV-VMR": {}, "LY-BA": {}, "LY-BU": {}, "LY-DR": {}, "LY-GT": {}, "LY-JA": {}, "LY-JB": {}, "LY-JG": {}, "LY-JI": {}, "LY-JU": {}, "LY-KF": {}, "LY-MB": {}, "LY-MI": {}, "LY-MJ": {}, "LY-MQ": {}, "LY-NL": {}, "LY-NQ": {}, "LY-SB": {}, "LY-SR": {}, "LY-TB": {}, "LY-WA": {}, "LY-WD": {}, "LY-WS": {}, "LY-ZA": {}, "MA-01": {}, "MA-02": {}, "MA-03": {}, "MA-04": {}, "MA-05": {}, "MA-06": {}, "MA-07": {}, "MA-08": {}, "MA-09": {}, "MA-10": {}, "MA-11": {}, "MA-12": {}, "MA-13": {}, "MA-14": {}, "MA-15": {}, "MA-16": {}, "MA-AGD": {}, "MA-AOU": {}, "MA-ASZ": {}, "MA-AZI": {}, "MA-BEM": {}, "MA-BER": {}, "MA-BES": {}, "MA-BOD": {}, "MA-BOM": {}, "MA-CAS": {}, "MA-CHE": {}, "MA-CHI": {}, "MA-CHT": {}, "MA-ERR": {}, "MA-ESI": {}, "MA-ESM": {}, "MA-FAH": {}, "MA-FES": {}, "MA-FIG": {}, "MA-GUE": {}, "MA-HAJ": {}, "MA-HAO": {}, "MA-HOC": {}, "MA-IFR": {}, "MA-INE": {}, "MA-JDI": {}, "MA-JRA": {}, "MA-KEN": {}, "MA-KES": {}, "MA-KHE": {}, "MA-KHN": {}, "MA-KHO": {}, "MA-LAA": {}, "MA-LAR": {}, "MA-MED": {}, "MA-MEK": {}, "MA-MMD": {}, "MA-MMN": {}, "MA-MOH": {}, "MA-MOU": {}, "MA-NAD": {}, "MA-NOU": {}, "MA-OUA": {}, "MA-OUD": {}, "MA-OUJ": {}, "MA-RAB": {}, "MA-SAF": {}, "MA-SAL": {}, "MA-SEF": {}, "MA-SET": {}, "MA-SIK": {}, "MA-SKH": {}, "MA-SYB": {}, "MA-TAI": {}, "MA-TAO": {}, "MA-TAR": {}, "MA-TAT": {}, "MA-TAZ": {}, "MA-TET": {}, "MA-TIZ": {}, "MA-TNG": {}, "MA-TNT": {}, "MA-ZAG": {}, "MC-CL": {}, "MC-CO": {}, "MC-FO": {}, "MC-GA": {}, "MC-JE": {}, "MC-LA": {}, "MC-MA": {}, "MC-MC": {}, "MC-MG": {}, "MC-MO": {}, "MC-MU": {}, "MC-PH": {}, "MC-SD": {}, "MC-SO": {}, "MC-SP": {}, "MC-SR": {}, "MC-VR": {}, "MD-AN": {}, "MD-BA": {}, "MD-BD": {}, "MD-BR": {}, "MD-BS": {}, "MD-CA": {}, "MD-CL": {}, "MD-CM": {}, "MD-CR": {}, "MD-CS": {}, "MD-CT": {}, "MD-CU": {}, "MD-DO": {}, "MD-DR": {}, "MD-DU": {}, "MD-ED": {}, "MD-FA": {}, "MD-FL": {}, "MD-GA": {}, "MD-GL": {}, "MD-HI": {}, "MD-IA": {}, "MD-LE": {}, "MD-NI": {}, "MD-OC": {}, "MD-OR": {}, "MD-RE": {}, "MD-RI": {}, "MD-SD": {}, "MD-SI": {}, "MD-SN": {}, "MD-SO": {}, "MD-ST": {}, "MD-SV": {}, "MD-TA": {}, "MD-TE": {}, "MD-UN": {}, "ME-01": {}, "ME-02": {}, "ME-03": {}, "ME-04": {}, "ME-05": {}, "ME-06": {}, "ME-07": {}, "ME-08": {}, "ME-09": {}, "ME-10": {}, "ME-11": {}, "ME-12": {}, "ME-13": {}, "ME-14": {}, "ME-15": {}, "ME-16": {}, "ME-17": {}, "ME-18": {}, "ME-19": {}, "ME-20": {}, "ME-21": {}, "ME-22": {}, "ME-23": {}, "ME-24": {}, "ME-25": {}, "MG-A": {}, "MG-D": {}, "MG-F": {}, "MG-M": {}, "MG-T": {}, "MG-U": {}, "MH-ALK": {}, "MH-ALL": {}, "MH-ARN": {}, "MH-AUR": {}, "MH-EBO": {}, "MH-ENI": {}, "MH-JAB": {}, "MH-JAL": {}, "MH-KIL": {}, "MH-KWA": {}, "MH-L": {}, "MH-LAE": {}, "MH-LIB": {}, "MH-LIK": {}, "MH-MAJ": {}, "MH-MAL": {}, "MH-MEJ": {}, "MH-MIL": {}, "MH-NMK": {}, "MH-NMU": {}, "MH-RON": {}, "MH-T": {}, "MH-UJA": {}, "MH-UTI": {}, "MH-WTJ": {}, "MH-WTN": {}, "MK-101": {}, "MK-102": {}, "MK-103": {}, "MK-104": {}, "MK-105": {}, "MK-106": {}, "MK-107": {}, "MK-108": {}, "MK-109": {}, "MK-201": {}, "MK-202": {}, "MK-205": {}, "MK-206": {}, "MK-207": {}, "MK-208": {}, "MK-209": {}, "MK-210": {}, "MK-211": {}, "MK-301": {}, "MK-303": {}, "MK-307": {}, "MK-308": {}, "MK-310": {}, "MK-311": {}, "MK-312": {}, "MK-401": {}, "MK-402": {}, "MK-403": {}, "MK-404": {}, "MK-405": {}, "MK-406": {}, "MK-408": {}, "MK-409": {}, "MK-410": {}, "MK-501": {}, "MK-502": {}, "MK-503": {}, "MK-505": {}, "MK-506": {}, "MK-507": {}, "MK-508": {}, "MK-509": {}, "MK-601": {}, "MK-602": {}, "MK-604": {}, "MK-605": {}, "MK-606": {}, "MK-607": {}, "MK-608": {}, "MK-609": {}, "MK-701": {}, "MK-702": {}, "MK-703": {}, "MK-704": {}, "MK-705": {}, "MK-803": {}, "MK-804": {}, "MK-806": {}, "MK-807": {}, "MK-809": {}, "MK-810": {}, "MK-811": {}, "MK-812": {}, "MK-813": {}, "MK-814": {}, "MK-816": {}, "ML-1": {}, "ML-2": {}, "ML-3": {}, "ML-4": {}, "ML-5": {}, "ML-6": {}, "ML-7": {}, "ML-8": {}, "ML-BKO": {}, "MM-01": {}, "MM-02": {}, "MM-03": {}, "MM-04": {}, "MM-05": {}, "MM-06": {}, "MM-07": {}, "MM-11": {}, "MM-12": {}, "MM-13": {}, "MM-14": {}, "MM-15": {}, "MM-16": {}, "MM-17": {}, "MM-18": {}, "MN-035": {}, "MN-037": {}, "MN-039": {}, "MN-041": {}, "MN-043": {}, "MN-046": {}, "MN-047": {}, "MN-049": {}, "MN-051": {}, "MN-053": {}, "MN-055": {}, "MN-057": {}, "MN-059": {}, "MN-061": {}, "MN-063": {}, "MN-064": {}, "MN-065": {}, "MN-067": {}, "MN-069": {}, "MN-071": {}, "MN-073": {}, "MN-1": {}, "MR-01": {}, "MR-02": {}, "MR-03": {}, "MR-04": {}, "MR-05": {}, "MR-06": {}, "MR-07": {}, "MR-08": {}, "MR-09": {}, "MR-10": {}, "MR-11": {}, "MR-12": {}, "MR-13": {}, "MR-NKC": {}, "MT-01": {}, "MT-02": {}, "MT-03": {}, "MT-04": {}, "MT-05": {}, "MT-06": {}, "MT-07": {}, "MT-08": {}, "MT-09": {}, "MT-10": {}, "MT-11": {}, "MT-12": {}, "MT-13": {}, "MT-14": {}, "MT-15": {}, "MT-16": {}, "MT-17": {}, "MT-18": {}, "MT-19": {}, "MT-20": {}, "MT-21": {}, "MT-22": {}, "MT-23": {}, "MT-24": {}, "MT-25": {}, "MT-26": {}, "MT-27": {}, "MT-28": {}, "MT-29": {}, "MT-30": {}, "MT-31": {}, "MT-32": {}, "MT-33": {}, "MT-34": {}, "MT-35": {}, "MT-36": {}, "MT-37": {}, "MT-38": {}, "MT-39": {}, "MT-40": {}, "MT-41": {}, "MT-42": {}, "MT-43": {}, "MT-44": {}, "MT-45": {}, "MT-46": {}, "MT-47": {}, "MT-48": {}, "MT-49": {}, "MT-50": {}, "MT-51": {}, "MT-52": {}, "MT-53": {}, "MT-54": {}, "MT-55": {}, "MT-56": {}, "MT-57": {}, "MT-58": {}, "MT-59": {}, "MT-60": {}, "MT-61": {}, "MT-62": {}, "MT-63": {}, "MT-64": {}, "MT-65": {}, "MT-66": {}, "MT-67": {}, "MT-68": {}, "MU-AG": {}, "MU-BL": {}, "MU-BR": {}, "MU-CC": {}, "MU-CU": {}, "MU-FL": {}, "MU-GP": {}, "MU-MO": {}, "MU-PA": {}, "MU-PL": {}, "MU-PU": {}, "MU-PW": {}, "MU-QB": {}, "MU-RO": {}, "MU-RP": {}, "MU-RR": {}, "MU-SA": {}, "MU-VP": {}, "MV-00": {}, "MV-01": {}, "MV-02": {}, "MV-03": {}, "MV-04": {}, "MV-05": {}, "MV-07": {}, "MV-08": {}, "MV-12": {}, "MV-13": {}, "MV-14": {}, "MV-17": {}, "MV-20": {}, "MV-23": {}, "MV-24": {}, "MV-25": {}, "MV-26": {}, "MV-27": {}, "MV-28": {}, "MV-29": {}, "MV-CE": {}, "MV-MLE": {}, "MV-NC": {}, "MV-NO": {}, "MV-SC": {}, "MV-SU": {}, "MV-UN": {}, "MV-US": {}, "MW-BA": {}, "MW-BL": {}, "MW-C": {}, "MW-CK": {}, "MW-CR": {}, "MW-CT": {}, "MW-DE": {}, "MW-DO": {}, "MW-KR": {}, "MW-KS": {}, "MW-LI": {}, "MW-LK": {}, "MW-MC": {}, "MW-MG": {}, "MW-MH": {}, "MW-MU": {}, "MW-MW": {}, "MW-MZ": {}, "MW-N": {}, "MW-NB": {}, "MW-NE": {}, "MW-NI": {}, "MW-NK": {}, "MW-NS": {}, "MW-NU": {}, "MW-PH": {}, "MW-RU": {}, "MW-S": {}, "MW-SA": {}, "MW-TH": {}, "MW-ZO": {}, "MX-AGU": {}, "MX-BCN": {}, "MX-BCS": {}, "MX-CAM": {}, "MX-CHH": {}, "MX-CHP": {}, "MX-COA": {}, "MX-COL": {}, "MX-CMX": {}, "MX-DIF": {}, "MX-DUR": {}, "MX-GRO": {}, "MX-GUA": {}, "MX-HID": {}, "MX-JAL": {}, "MX-MEX": {}, "MX-MIC": {}, "MX-MOR": {}, "MX-NAY": {}, "MX-NLE": {}, "MX-OAX": {}, "MX-PUE": {}, "MX-QUE": {}, "MX-ROO": {}, "MX-SIN": {}, "MX-SLP": {}, "MX-SON": {}, "MX-TAB": {}, "MX-TAM": {}, "MX-TLA": {}, "MX-VER": {}, "MX-YUC": {}, "MX-ZAC": {}, "MY-01": {}, "MY-02": {}, "MY-03": {}, "MY-04": {}, "MY-05": {}, "MY-06": {}, "MY-07": {}, "MY-08": {}, "MY-09": {}, "MY-10": {}, "MY-11": {}, "MY-12": {}, "MY-13": {}, "MY-14": {}, "MY-15": {}, "MY-16": {}, "MZ-A": {}, "MZ-B": {}, "MZ-G": {}, "MZ-I": {}, "MZ-L": {}, "MZ-MPM": {}, "MZ-N": {}, "MZ-P": {}, "MZ-Q": {}, "MZ-S": {}, "MZ-T": {}, "NA-CA": {}, "NA-ER": {}, "NA-HA": {}, "NA-KA": {}, "NA-KE": {}, "NA-KH": {}, "NA-KU": {}, "NA-KW": {}, "NA-OD": {}, "NA-OH": {}, "NA-OK": {}, "NA-ON": {}, "NA-OS": {}, "NA-OT": {}, "NA-OW": {}, "NE-1": {}, "NE-2": {}, "NE-3": {}, "NE-4": {}, "NE-5": {}, "NE-6": {}, "NE-7": {}, "NE-8": {}, "NG-AB": {}, "NG-AD": {}, "NG-AK": {}, "NG-AN": {}, "NG-BA": {}, "NG-BE": {}, "NG-BO": {}, "NG-BY": {}, "NG-CR": {}, "NG-DE": {}, "NG-EB": {}, "NG-ED": {}, "NG-EK": {}, "NG-EN": {}, "NG-FC": {}, "NG-GO": {}, "NG-IM": {}, "NG-JI": {}, "NG-KD": {}, "NG-KE": {}, "NG-KN": {}, "NG-KO": {}, "NG-KT": {}, "NG-KW": {}, "NG-LA": {}, "NG-NA": {}, "NG-NI": {}, "NG-OG": {}, "NG-ON": {}, "NG-OS": {}, "NG-OY": {}, "NG-PL": {}, "NG-RI": {}, "NG-SO": {}, "NG-TA": {}, "NG-YO": {}, "NG-ZA": {}, "NI-AN": {}, "NI-AS": {}, "NI-BO": {}, "NI-CA": {}, "NI-CI": {}, "NI-CO": {}, "NI-ES": {}, "NI-GR": {}, "NI-JI": {}, "NI-LE": {}, "NI-MD": {}, "NI-MN": {}, "NI-MS": {}, "NI-MT": {}, "NI-NS": {}, "NI-RI": {}, "NI-SJ": {}, "NL-AW": {}, "NL-BQ1": {}, "NL-BQ2": {}, "NL-BQ3": {}, "NL-CW": {}, "NL-DR": {}, "NL-FL": {}, "NL-FR": {}, "NL-GE": {}, "NL-GR": {}, "NL-LI": {}, "NL-NB": {}, "NL-NH": {}, "NL-OV": {}, "NL-SX": {}, "NL-UT": {}, "NL-ZE": {}, "NL-ZH": {}, "NO-03": {}, "NO-11": {}, "NO-15": {}, "NO-16": {}, "NO-17": {}, "NO-18": {}, "NO-21": {}, "NO-30": {}, "NO-34": {}, "NO-38": {}, "NO-42": {}, "NO-46": {}, "NO-50": {}, "NO-54": {}, "NO-22": {}, "NP-1": {}, "NP-2": {}, "NP-3": {}, "NP-4": {}, "NP-5": {}, "NP-BA": {}, "NP-BH": {}, "NP-DH": {}, "NP-GA": {}, "NP-JA": {}, "NP-KA": {}, "NP-KO": {}, "NP-LU": {}, "NP-MA": {}, "NP-ME": {}, "NP-NA": {}, "NP-P1": {}, "NP-P2": {}, "NP-P3": {}, "NP-P4": {}, "NP-P5": {}, "NP-P6": {}, "NP-P7": {}, "NP-RA": {}, "NP-SA": {}, "NP-SE": {}, "NR-01": {}, "NR-02": {}, "NR-03": {}, "NR-04": {}, "NR-05": {}, "NR-06": {}, "NR-07": {}, "NR-08": {}, "NR-09": {}, "NR-10": {}, "NR-11": {}, "NR-12": {}, "NR-13": {}, "NR-14": {}, "NZ-AUK": {}, "NZ-BOP": {}, "NZ-CAN": {}, "NZ-CIT": {}, "NZ-GIS": {}, "NZ-HKB": {}, "NZ-MBH": {}, "NZ-MWT": {}, "NZ-N": {}, "NZ-NSN": {}, "NZ-NTL": {}, "NZ-OTA": {}, "NZ-S": {}, "NZ-STL": {}, "NZ-TAS": {}, "NZ-TKI": {}, "NZ-WGN": {}, "NZ-WKO": {}, "NZ-WTC": {}, "OM-BA": {}, "OM-BS": {}, "OM-BU": {}, "OM-BJ": {}, "OM-DA": {}, "OM-MA": {}, "OM-MU": {}, "OM-SH": {}, "OM-SJ": {}, "OM-SS": {}, "OM-WU": {}, "OM-ZA": {}, "OM-ZU": {}, "PA-1": {}, "PA-2": {}, "PA-3": {}, "PA-4": {}, "PA-5": {}, "PA-6": {}, "PA-7": {}, "PA-8": {}, "PA-9": {}, "PA-EM": {}, "PA-KY": {}, "PA-NB": {}, "PE-AMA": {}, "PE-ANC": {}, "PE-APU": {}, "PE-ARE": {}, "PE-AYA": {}, "PE-CAJ": {}, "PE-CAL": {}, "PE-CUS": {}, "PE-HUC": {}, "PE-HUV": {}, "PE-ICA": {}, "PE-JUN": {}, "PE-LAL": {}, "PE-LAM": {}, "PE-LIM": {}, "PE-LMA": {}, "PE-LOR": {}, "PE-MDD": {}, "PE-MOQ": {}, "PE-PAS": {}, "PE-PIU": {}, "PE-PUN": {}, "PE-SAM": {}, "PE-TAC": {}, "PE-TUM": {}, "PE-UCA": {}, "PG-CPK": {}, "PG-CPM": {}, "PG-EBR": {}, "PG-EHG": {}, "PG-EPW": {}, "PG-ESW": {}, "PG-GPK": {}, "PG-MBA": {}, "PG-MPL": {}, "PG-MPM": {}, "PG-MRL": {}, "PG-NCD": {}, "PG-NIK": {}, "PG-NPP": {}, "PG-NSB": {}, "PG-SAN": {}, "PG-SHM": {}, "PG-WBK": {}, "PG-WHM": {}, "PG-WPD": {}, "PH-00": {}, "PH-01": {}, "PH-02": {}, "PH-03": {}, "PH-05": {}, "PH-06": {}, "PH-07": {}, "PH-08": {}, "PH-09": {}, "PH-10": {}, "PH-11": {}, "PH-12": {}, "PH-13": {}, "PH-14": {}, "PH-15": {}, "PH-40": {}, "PH-41": {}, "PH-ABR": {}, "PH-AGN": {}, "PH-AGS": {}, "PH-AKL": {}, "PH-ALB": {}, "PH-ANT": {}, "PH-APA": {}, "PH-AUR": {}, "PH-BAN": {}, "PH-BAS": {}, "PH-BEN": {}, "PH-BIL": {}, "PH-BOH": {}, "PH-BTG": {}, "PH-BTN": {}, "PH-BUK": {}, "PH-BUL": {}, "PH-CAG": {}, "PH-CAM": {}, "PH-CAN": {}, "PH-CAP": {}, "PH-CAS": {}, "PH-CAT": {}, "PH-CAV": {}, "PH-CEB": {}, "PH-COM": {}, "PH-DAO": {}, "PH-DAS": {}, "PH-DAV": {}, "PH-DIN": {}, "PH-EAS": {}, "PH-GUI": {}, "PH-IFU": {}, "PH-ILI": {}, "PH-ILN": {}, "PH-ILS": {}, "PH-ISA": {}, "PH-KAL": {}, "PH-LAG": {}, "PH-LAN": {}, "PH-LAS": {}, "PH-LEY": {}, "PH-LUN": {}, "PH-MAD": {}, "PH-MAG": {}, "PH-MAS": {}, "PH-MDC": {}, "PH-MDR": {}, "PH-MOU": {}, "PH-MSC": {}, "PH-MSR": {}, "PH-NCO": {}, "PH-NEC": {}, "PH-NER": {}, "PH-NSA": {}, "PH-NUE": {}, "PH-NUV": {}, "PH-PAM": {}, "PH-PAN": {}, "PH-PLW": {}, "PH-QUE": {}, "PH-QUI": {}, "PH-RIZ": {}, "PH-ROM": {}, "PH-SAR": {}, "PH-SCO": {}, "PH-SIG": {}, "PH-SLE": {}, "PH-SLU": {}, "PH-SOR": {}, "PH-SUK": {}, "PH-SUN": {}, "PH-SUR": {}, "PH-TAR": {}, "PH-TAW": {}, "PH-WSA": {}, "PH-ZAN": {}, "PH-ZAS": {}, "PH-ZMB": {}, "PH-ZSI": {}, "PK-BA": {}, "PK-GB": {}, "PK-IS": {}, "PK-JK": {}, "PK-KP": {}, "PK-PB": {}, "PK-SD": {}, "PK-TA": {}, "PL-02": {}, "PL-04": {}, "PL-06": {}, "PL-08": {}, "PL-10": {}, "PL-12": {}, "PL-14": {}, "PL-16": {}, "PL-18": {}, "PL-20": {}, "PL-22": {}, "PL-24": {}, "PL-26": {}, "PL-28": {}, "PL-30": {}, "PL-32": {}, "PS-BTH": {}, "PS-DEB": {}, "PS-GZA": {}, "PS-HBN": {}, "PS-JEM": {}, "PS-JEN": {}, "PS-JRH": {}, "PS-KYS": {}, "PS-NBS": {}, "PS-NGZ": {}, "PS-QQA": {}, "PS-RBH": {}, "PS-RFH": {}, "PS-SLT": {}, "PS-TBS": {}, "PS-TKM": {}, "PT-01": {}, "PT-02": {}, "PT-03": {}, "PT-04": {}, "PT-05": {}, "PT-06": {}, "PT-07": {}, "PT-08": {}, "PT-09": {}, "PT-10": {}, "PT-11": {}, "PT-12": {}, "PT-13": {}, "PT-14": {}, "PT-15": {}, "PT-16": {}, "PT-17": {}, "PT-18": {}, "PT-20": {}, "PT-30": {}, "PW-002": {}, "PW-004": {}, "PW-010": {}, "PW-050": {}, "PW-100": {}, "PW-150": {}, "PW-212": {}, "PW-214": {}, "PW-218": {}, "PW-222": {}, "PW-224": {}, "PW-226": {}, "PW-227": {}, "PW-228": {}, "PW-350": {}, "PW-370": {}, "PY-1": {}, "PY-10": {}, "PY-11": {}, "PY-12": {}, "PY-13": {}, "PY-14": {}, "PY-15": {}, "PY-16": {}, "PY-19": {}, "PY-2": {}, "PY-3": {}, "PY-4": {}, "PY-5": {}, "PY-6": {}, "PY-7": {}, "PY-8": {}, "PY-9": {}, "PY-ASU": {}, "QA-DA": {}, "QA-KH": {}, "QA-MS": {}, "QA-RA": {}, "QA-US": {}, "QA-WA": {}, "QA-ZA": {}, "RO-AB": {}, "RO-AG": {}, "RO-AR": {}, "RO-B": {}, "RO-BC": {}, "RO-BH": {}, "RO-BN": {}, "RO-BR": {}, "RO-BT": {}, "RO-BV": {}, "RO-BZ": {}, "RO-CJ": {}, "RO-CL": {}, "RO-CS": {}, "RO-CT": {}, "RO-CV": {}, "RO-DB": {}, "RO-DJ": {}, "RO-GJ": {}, "RO-GL": {}, "RO-GR": {}, "RO-HD": {}, "RO-HR": {}, "RO-IF": {}, "RO-IL": {}, "RO-IS": {}, "RO-MH": {}, "RO-MM": {}, "RO-MS": {}, "RO-NT": {}, "RO-OT": {}, "RO-PH": {}, "RO-SB": {}, "RO-SJ": {}, "RO-SM": {}, "RO-SV": {}, "RO-TL": {}, "RO-TM": {}, "RO-TR": {}, "RO-VL": {}, "RO-VN": {}, "RO-VS": {}, "RS-00": {}, "RS-01": {}, "RS-02": {}, "RS-03": {}, "RS-04": {}, "RS-05": {}, "RS-06": {}, "RS-07": {}, "RS-08": {}, "RS-09": {}, "RS-10": {}, "RS-11": {}, "RS-12": {}, "RS-13": {}, "RS-14": {}, "RS-15": {}, "RS-16": {}, "RS-17": {}, "RS-18": {}, "RS-19": {}, "RS-20": {}, "RS-21": {}, "RS-22": {}, "RS-23": {}, "RS-24": {}, "RS-25": {}, "RS-26": {}, "RS-27": {}, "RS-28": {}, "RS-29": {}, "RS-KM": {}, "RS-VO": {}, "RU-AD": {}, "RU-AL": {}, "RU-ALT": {}, "RU-AMU": {}, "RU-ARK": {}, "RU-AST": {}, "RU-BA": {}, "RU-BEL": {}, "RU-BRY": {}, "RU-BU": {}, "RU-CE": {}, "RU-CHE": {}, "RU-CHU": {}, "RU-CU": {}, "RU-DA": {}, "RU-IN": {}, "RU-IRK": {}, "RU-IVA": {}, "RU-KAM": {}, "RU-KB": {}, "RU-KC": {}, "RU-KDA": {}, "RU-KEM": {}, "RU-KGD": {}, "RU-KGN": {}, "RU-KHA": {}, "RU-KHM": {}, "RU-KIR": {}, "RU-KK": {}, "RU-KL": {}, "RU-KLU": {}, "RU-KO": {}, "RU-KOS": {}, "RU-KR": {}, "RU-KRS": {}, "RU-KYA": {}, "RU-LEN": {}, "RU-LIP": {}, "RU-MAG": {}, "RU-ME": {}, "RU-MO": {}, "RU-MOS": {}, "RU-MOW": {}, "RU-MUR": {}, "RU-NEN": {}, "RU-NGR": {}, "RU-NIZ": {}, "RU-NVS": {}, "RU-OMS": {}, "RU-ORE": {}, "RU-ORL": {}, "RU-PER": {}, "RU-PNZ": {}, "RU-PRI": {}, "RU-PSK": {}, "RU-ROS": {}, "RU-RYA": {}, "RU-SA": {}, "RU-SAK": {}, "RU-SAM": {}, "RU-SAR": {}, "RU-SE": {}, "RU-SMO": {}, "RU-SPE": {}, "RU-STA": {}, "RU-SVE": {}, "RU-TA": {}, "RU-TAM": {}, "RU-TOM": {}, "RU-TUL": {}, "RU-TVE": {}, "RU-TY": {}, "RU-TYU": {}, "RU-UD": {}, "RU-ULY": {}, "RU-VGG": {}, "RU-VLA": {}, "RU-VLG": {}, "RU-VOR": {}, "RU-YAN": {}, "RU-YAR": {}, "RU-YEV": {}, "RU-ZAB": {}, "RW-01": {}, "RW-02": {}, "RW-03": {}, "RW-04": {}, "RW-05": {}, "SA-01": {}, "SA-02": {}, "SA-03": {}, "SA-04": {}, "SA-05": {}, "SA-06": {}, "SA-07": {}, "SA-08": {}, "SA-09": {}, "SA-10": {}, "SA-11": {}, "SA-12": {}, "SA-14": {}, "SB-CE": {}, "SB-CH": {}, "SB-CT": {}, "SB-GU": {}, "SB-IS": {}, "SB-MK": {}, "SB-ML": {}, "SB-RB": {}, "SB-TE": {}, "SB-WE": {}, "SC-01": {}, "SC-02": {}, "SC-03": {}, "SC-04": {}, "SC-05": {}, "SC-06": {}, "SC-07": {}, "SC-08": {}, "SC-09": {}, "SC-10": {}, "SC-11": {}, "SC-12": {}, "SC-13": {}, "SC-14": {}, "SC-15": {}, "SC-16": {}, "SC-17": {}, "SC-18": {}, "SC-19": {}, "SC-20": {}, "SC-21": {}, "SC-22": {}, "SC-23": {}, "SC-24": {}, "SC-25": {}, "SD-DC": {}, "SD-DE": {}, "SD-DN": {}, "SD-DS": {}, "SD-DW": {}, "SD-GD": {}, "SD-GK": {}, "SD-GZ": {}, "SD-KA": {}, "SD-KH": {}, "SD-KN": {}, "SD-KS": {}, "SD-NB": {}, "SD-NO": {}, "SD-NR": {}, "SD-NW": {}, "SD-RS": {}, "SD-SI": {}, "SE-AB": {}, "SE-AC": {}, "SE-BD": {}, "SE-C": {}, "SE-D": {}, "SE-E": {}, "SE-F": {}, "SE-G": {}, "SE-H": {}, "SE-I": {}, "SE-K": {}, "SE-M": {}, "SE-N": {}, "SE-O": {}, "SE-S": {}, "SE-T": {}, "SE-U": {}, "SE-W": {}, "SE-X": {}, "SE-Y": {}, "SE-Z": {}, "SG-01": {}, "SG-02": {}, "SG-03": {}, "SG-04": {}, "SG-05": {}, "SH-AC": {}, "SH-HL": {}, "SH-TA": {}, "SI-001": {}, "SI-002": {}, "SI-003": {}, "SI-004": {}, "SI-005": {}, "SI-006": {}, "SI-007": {}, "SI-008": {}, "SI-009": {}, "SI-010": {}, "SI-011": {}, "SI-012": {}, "SI-013": {}, "SI-014": {}, "SI-015": {}, "SI-016": {}, "SI-017": {}, "SI-018": {}, "SI-019": {}, "SI-020": {}, "SI-021": {}, "SI-022": {}, "SI-023": {}, "SI-024": {}, "SI-025": {}, "SI-026": {}, "SI-027": {}, "SI-028": {}, "SI-029": {}, "SI-030": {}, "SI-031": {}, "SI-032": {}, "SI-033": {}, "SI-034": {}, "SI-035": {}, "SI-036": {}, "SI-037": {}, "SI-038": {}, "SI-039": {}, "SI-040": {}, "SI-041": {}, "SI-042": {}, "SI-043": {}, "SI-044": {}, "SI-045": {}, "SI-046": {}, "SI-047": {}, "SI-048": {}, "SI-049": {}, "SI-050": {}, "SI-051": {}, "SI-052": {}, "SI-053": {}, "SI-054": {}, "SI-055": {}, "SI-056": {}, "SI-057": {}, "SI-058": {}, "SI-059": {}, "SI-060": {}, "SI-061": {}, "SI-062": {}, "SI-063": {}, "SI-064": {}, "SI-065": {}, "SI-066": {}, "SI-067": {}, "SI-068": {}, "SI-069": {}, "SI-070": {}, "SI-071": {}, "SI-072": {}, "SI-073": {}, "SI-074": {}, "SI-075": {}, "SI-076": {}, "SI-077": {}, "SI-078": {}, "SI-079": {}, "SI-080": {}, "SI-081": {}, "SI-082": {}, "SI-083": {}, "SI-084": {}, "SI-085": {}, "SI-086": {}, "SI-087": {}, "SI-088": {}, "SI-089": {}, "SI-090": {}, "SI-091": {}, "SI-092": {}, "SI-093": {}, "SI-094": {}, "SI-095": {}, "SI-096": {}, "SI-097": {}, "SI-098": {}, "SI-099": {}, "SI-100": {}, "SI-101": {}, "SI-102": {}, "SI-103": {}, "SI-104": {}, "SI-105": {}, "SI-106": {}, "SI-107": {}, "SI-108": {}, "SI-109": {}, "SI-110": {}, "SI-111": {}, "SI-112": {}, "SI-113": {}, "SI-114": {}, "SI-115": {}, "SI-116": {}, "SI-117": {}, "SI-118": {}, "SI-119": {}, "SI-120": {}, "SI-121": {}, "SI-122": {}, "SI-123": {}, "SI-124": {}, "SI-125": {}, "SI-126": {}, "SI-127": {}, "SI-128": {}, "SI-129": {}, "SI-130": {}, "SI-131": {}, "SI-132": {}, "SI-133": {}, "SI-134": {}, "SI-135": {}, "SI-136": {}, "SI-137": {}, "SI-138": {}, "SI-139": {}, "SI-140": {}, "SI-141": {}, "SI-142": {}, "SI-143": {}, "SI-144": {}, "SI-146": {}, "SI-147": {}, "SI-148": {}, "SI-149": {}, "SI-150": {}, "SI-151": {}, "SI-152": {}, "SI-153": {}, "SI-154": {}, "SI-155": {}, "SI-156": {}, "SI-157": {}, "SI-158": {}, "SI-159": {}, "SI-160": {}, "SI-161": {}, "SI-162": {}, "SI-163": {}, "SI-164": {}, "SI-165": {}, "SI-166": {}, "SI-167": {}, "SI-168": {}, "SI-169": {}, "SI-170": {}, "SI-171": {}, "SI-172": {}, "SI-173": {}, "SI-174": {}, "SI-175": {}, "SI-176": {}, "SI-177": {}, "SI-178": {}, "SI-179": {}, "SI-180": {}, "SI-181": {}, "SI-182": {}, "SI-183": {}, "SI-184": {}, "SI-185": {}, "SI-186": {}, "SI-187": {}, "SI-188": {}, "SI-189": {}, "SI-190": {}, "SI-191": {}, "SI-192": {}, "SI-193": {}, "SI-194": {}, "SI-195": {}, "SI-196": {}, "SI-197": {}, "SI-198": {}, "SI-199": {}, "SI-200": {}, "SI-201": {}, "SI-202": {}, "SI-203": {}, "SI-204": {}, "SI-205": {}, "SI-206": {}, "SI-207": {}, "SI-208": {}, "SI-209": {}, "SI-210": {}, "SI-211": {}, "SI-212": {}, "SI-213": {}, "SK-BC": {}, "SK-BL": {}, "SK-KI": {}, "SK-NI": {}, "SK-PV": {}, "SK-TA": {}, "SK-TC": {}, "SK-ZI": {}, "SL-E": {}, "SL-N": {}, "SL-S": {}, "SL-W": {}, "SM-01": {}, "SM-02": {}, "SM-03": {}, "SM-04": {}, "SM-05": {}, "SM-06": {}, "SM-07": {}, "SM-08": {}, "SM-09": {}, "SN-DB": {}, "SN-DK": {}, "SN-FK": {}, "SN-KA": {}, "SN-KD": {}, "SN-KE": {}, "SN-KL": {}, "SN-LG": {}, "SN-MT": {}, "SN-SE": {}, "SN-SL": {}, "SN-TC": {}, "SN-TH": {}, "SN-ZG": {}, "SO-AW": {}, "SO-BK": {}, "SO-BN": {}, "SO-BR": {}, "SO-BY": {}, "SO-GA": {}, "SO-GE": {}, "SO-HI": {}, "SO-JD": {}, "SO-JH": {}, "SO-MU": {}, "SO-NU": {}, "SO-SA": {}, "SO-SD": {}, "SO-SH": {}, "SO-SO": {}, "SO-TO": {}, "SO-WO": {}, "SR-BR": {}, "SR-CM": {}, "SR-CR": {}, "SR-MA": {}, "SR-NI": {}, "SR-PM": {}, "SR-PR": {}, "SR-SA": {}, "SR-SI": {}, "SR-WA": {}, "SS-BN": {}, "SS-BW": {}, "SS-EC": {}, "SS-EE8": {}, "SS-EE": {}, "SS-EW": {}, "SS-JG": {}, "SS-LK": {}, "SS-NU": {}, "SS-UY": {}, "SS-WR": {}, "ST-01": {}, "ST-P": {}, "ST-S": {}, "SV-AH": {}, "SV-CA": {}, "SV-CH": {}, "SV-CU": {}, "SV-LI": {}, "SV-MO": {}, "SV-PA": {}, "SV-SA": {}, "SV-SM": {}, "SV-SO": {}, "SV-SS": {}, "SV-SV": {}, "SV-UN": {}, "SV-US": {}, "SY-DI": {}, "SY-DR": {}, "SY-DY": {}, "SY-HA": {}, "SY-HI": {}, "SY-HL": {}, "SY-HM": {}, "SY-ID": {}, "SY-LA": {}, "SY-QU": {}, "SY-RA": {}, "SY-RD": {}, "SY-SU": {}, "SY-TA": {}, "SZ-HH": {}, "SZ-LU": {}, "SZ-MA": {}, "SZ-SH": {}, "TD-BA": {}, "TD-BG": {}, "TD-BO": {}, "TD-CB": {}, "TD-EN": {}, "TD-GR": {}, "TD-HL": {}, "TD-KA": {}, "TD-LC": {}, "TD-LO": {}, "TD-LR": {}, "TD-MA": {}, "TD-MC": {}, "TD-ME": {}, "TD-MO": {}, "TD-ND": {}, "TD-OD": {}, "TD-SA": {}, "TD-SI": {}, "TD-TA": {}, "TD-TI": {}, "TD-WF": {}, "TG-C": {}, "TG-K": {}, "TG-M": {}, "TG-P": {}, "TG-S": {}, "TH-10": {}, "TH-11": {}, "TH-12": {}, "TH-13": {}, "TH-14": {}, "TH-15": {}, "TH-16": {}, "TH-17": {}, "TH-18": {}, "TH-19": {}, "TH-20": {}, "TH-21": {}, "TH-22": {}, "TH-23": {}, "TH-24": {}, "TH-25": {}, "TH-26": {}, "TH-27": {}, "TH-30": {}, "TH-31": {}, "TH-32": {}, "TH-33": {}, "TH-34": {}, "TH-35": {}, "TH-36": {}, "TH-37": {}, "TH-38": {}, "TH-39": {}, "TH-40": {}, "TH-41": {}, "TH-42": {}, "TH-43": {}, "TH-44": {}, "TH-45": {}, "TH-46": {}, "TH-47": {}, "TH-48": {}, "TH-49": {}, "TH-50": {}, "TH-51": {}, "TH-52": {}, "TH-53": {}, "TH-54": {}, "TH-55": {}, "TH-56": {}, "TH-57": {}, "TH-58": {}, "TH-60": {}, "TH-61": {}, "TH-62": {}, "TH-63": {}, "TH-64": {}, "TH-65": {}, "TH-66": {}, "TH-67": {}, "TH-70": {}, "TH-71": {}, "TH-72": {}, "TH-73": {}, "TH-74": {}, "TH-75": {}, "TH-76": {}, "TH-77": {}, "TH-80": {}, "TH-81": {}, "TH-82": {}, "TH-83": {}, "TH-84": {}, "TH-85": {}, "TH-86": {}, "TH-90": {}, "TH-91": {}, "TH-92": {}, "TH-93": {}, "TH-94": {}, "TH-95": {}, "TH-96": {}, "TH-S": {}, "TJ-GB": {}, "TJ-KT": {}, "TJ-SU": {}, "TJ-DU": {}, "TJ-RA": {}, "TL-AL": {}, "TL-AN": {}, "TL-BA": {}, "TL-BO": {}, "TL-CO": {}, "TL-DI": {}, "TL-ER": {}, "TL-LA": {}, "TL-LI": {}, "TL-MF": {}, "TL-MT": {}, "TL-OE": {}, "TL-VI": {}, "TM-A": {}, "TM-B": {}, "TM-D": {}, "TM-L": {}, "TM-M": {}, "TM-S": {}, "TN-11": {}, "TN-12": {}, "TN-13": {}, "TN-14": {}, "TN-21": {}, "TN-22": {}, "TN-23": {}, "TN-31": {}, "TN-32": {}, "TN-33": {}, "TN-34": {}, "TN-41": {}, "TN-42": {}, "TN-43": {}, "TN-51": {}, "TN-52": {}, "TN-53": {}, "TN-61": {}, "TN-71": {}, "TN-72": {}, "TN-73": {}, "TN-81": {}, "TN-82": {}, "TN-83": {}, "TO-01": {}, "TO-02": {}, "TO-03": {}, "TO-04": {}, "TO-05": {}, "TR-01": {}, "TR-02": {}, "TR-03": {}, "TR-04": {}, "TR-05": {}, "TR-06": {}, "TR-07": {}, "TR-08": {}, "TR-09": {}, "TR-10": {}, "TR-11": {}, "TR-12": {}, "TR-13": {}, "TR-14": {}, "TR-15": {}, "TR-16": {}, "TR-17": {}, "TR-18": {}, "TR-19": {}, "TR-20": {}, "TR-21": {}, "TR-22": {}, "TR-23": {}, "TR-24": {}, "TR-25": {}, "TR-26": {}, "TR-27": {}, "TR-28": {}, "TR-29": {}, "TR-30": {}, "TR-31": {}, "TR-32": {}, "TR-33": {}, "TR-34": {}, "TR-35": {}, "TR-36": {}, "TR-37": {}, "TR-38": {}, "TR-39": {}, "TR-40": {}, "TR-41": {}, "TR-42": {}, "TR-43": {}, "TR-44": {}, "TR-45": {}, "TR-46": {}, "TR-47": {}, "TR-48": {}, "TR-49": {}, "TR-50": {}, "TR-51": {}, "TR-52": {}, "TR-53": {}, "TR-54": {}, "TR-55": {}, "TR-56": {}, "TR-57": {}, "TR-58": {}, "TR-59": {}, "TR-60": {}, "TR-61": {}, "TR-62": {}, "TR-63": {}, "TR-64": {}, "TR-65": {}, "TR-66": {}, "TR-67": {}, "TR-68": {}, "TR-69": {}, "TR-70": {}, "TR-71": {}, "TR-72": {}, "TR-73": {}, "TR-74": {}, "TR-75": {}, "TR-76": {}, "TR-77": {}, "TR-78": {}, "TR-79": {}, "TR-80": {}, "TR-81": {}, "TT-ARI": {}, "TT-CHA": {}, "TT-CTT": {}, "TT-DMN": {}, "TT-ETO": {}, "TT-MRC": {}, "TT-TOB": {}, "TT-PED": {}, "TT-POS": {}, "TT-PRT": {}, "TT-PTF": {}, "TT-RCM": {}, "TT-SFO": {}, "TT-SGE": {}, "TT-SIP": {}, "TT-SJL": {}, "TT-TUP": {}, "TT-WTO": {}, "TV-FUN": {}, "TV-NIT": {}, "TV-NKF": {}, "TV-NKL": {}, "TV-NMA": {}, "TV-NMG": {}, "TV-NUI": {}, "TV-VAI": {}, "TW-CHA": {}, "TW-CYI": {}, "TW-CYQ": {}, "TW-KIN": {}, "TW-HSQ": {}, "TW-HSZ": {}, "TW-HUA": {}, "TW-LIE": {}, "TW-ILA": {}, "TW-KEE": {}, "TW-KHH": {}, "TW-KHQ": {}, "TW-MIA": {}, "TW-NAN": {}, "TW-NWT": {}, "TW-PEN": {}, "TW-PIF": {}, "TW-TAO": {}, "TW-TNN": {}, "TW-TNQ": {}, "TW-TPE": {}, "TW-TPQ": {}, "TW-TTT": {}, "TW-TXG": {}, "TW-TXQ": {}, "TW-YUN": {}, "TZ-01": {}, "TZ-02": {}, "TZ-03": {}, "TZ-04": {}, "TZ-05": {}, "TZ-06": {}, "TZ-07": {}, "TZ-08": {}, "TZ-09": {}, "TZ-10": {}, "TZ-11": {}, "TZ-12": {}, "TZ-13": {}, "TZ-14": {}, "TZ-15": {}, "TZ-16": {}, "TZ-17": {}, "TZ-18": {}, "TZ-19": {}, "TZ-20": {}, "TZ-21": {}, "TZ-22": {}, "TZ-23": {}, "TZ-24": {}, "TZ-25": {}, "TZ-26": {}, "TZ-27": {}, "TZ-28": {}, "TZ-29": {}, "TZ-30": {}, "TZ-31": {}, "UA-05": {}, "UA-07": {}, "UA-09": {}, "UA-12": {}, "UA-14": {}, "UA-18": {}, "UA-21": {}, "UA-23": {}, "UA-26": {}, "UA-30": {}, "UA-32": {}, "UA-35": {}, "UA-40": {}, "UA-43": {}, "UA-46": {}, "UA-48": {}, "UA-51": {}, "UA-53": {}, "UA-56": {}, "UA-59": {}, "UA-61": {}, "UA-63": {}, "UA-65": {}, "UA-68": {}, "UA-71": {}, "UA-74": {}, "UA-77": {}, "UG-101": {}, "UG-102": {}, "UG-103": {}, "UG-104": {}, "UG-105": {}, "UG-106": {}, "UG-107": {}, "UG-108": {}, "UG-109": {}, "UG-110": {}, "UG-111": {}, "UG-112": {}, "UG-113": {}, "UG-114": {}, "UG-115": {}, "UG-116": {}, "UG-201": {}, "UG-202": {}, "UG-203": {}, "UG-204": {}, "UG-205": {}, "UG-206": {}, "UG-207": {}, "UG-208": {}, "UG-209": {}, "UG-210": {}, "UG-211": {}, "UG-212": {}, "UG-213": {}, "UG-214": {}, "UG-215": {}, "UG-216": {}, "UG-217": {}, "UG-218": {}, "UG-219": {}, "UG-220": {}, "UG-221": {}, "UG-222": {}, "UG-223": {}, "UG-224": {}, "UG-301": {}, "UG-302": {}, "UG-303": {}, "UG-304": {}, "UG-305": {}, "UG-306": {}, "UG-307": {}, "UG-308": {}, "UG-309": {}, "UG-310": {}, "UG-311": {}, "UG-312": {}, "UG-313": {}, "UG-314": {}, "UG-315": {}, "UG-316": {}, "UG-317": {}, "UG-318": {}, "UG-319": {}, "UG-320": {}, "UG-321": {}, "UG-401": {}, "UG-402": {}, "UG-403": {}, "UG-404": {}, "UG-405": {}, "UG-406": {}, "UG-407": {}, "UG-408": {}, "UG-409": {}, "UG-410": {}, "UG-411": {}, "UG-412": {}, "UG-413": {}, "UG-414": {}, "UG-415": {}, "UG-416": {}, "UG-417": {}, "UG-418": {}, "UG-419": {}, "UG-C": {}, "UG-E": {}, "UG-N": {}, "UG-W": {}, "UG-322": {}, "UG-323": {}, "UG-420": {}, "UG-117": {}, "UG-118": {}, "UG-225": {}, "UG-120": {}, "UG-226": {}, "UG-121": {}, "UG-122": {}, "UG-227": {}, "UG-421": {}, "UG-325": {}, "UG-228": {}, "UG-123": {}, "UG-422": {}, "UG-326": {}, "UG-229": {}, "UG-124": {}, "UG-423": {}, "UG-230": {}, "UG-327": {}, "UG-424": {}, "UG-328": {}, "UG-425": {}, "UG-426": {}, "UG-330": {}, "UM-67": {}, "UM-71": {}, "UM-76": {}, "UM-79": {}, "UM-81": {}, "UM-84": {}, "UM-86": {}, "UM-89": {}, "UM-95": {}, "US-AK": {}, "US-AL": {}, "US-AR": {}, "US-AS": {}, "US-AZ": {}, "US-CA": {}, "US-CO": {}, "US-CT": {}, "US-DC": {}, "US-DE": {}, "US-FL": {}, "US-GA": {}, "US-GU": {}, "US-HI": {}, "US-IA": {}, "US-ID": {}, "US-IL": {}, "US-IN": {}, "US-KS": {}, "US-KY": {}, "US-LA": {}, "US-MA": {}, "US-MD": {}, "US-ME": {}, "US-MI": {}, "US-MN": {}, "US-MO": {}, "US-MP": {}, "US-MS": {}, "US-MT": {}, "US-NC": {}, "US-ND": {}, "US-NE": {}, "US-NH": {}, "US-NJ": {}, "US-NM": {}, "US-NV": {}, "US-NY": {}, "US-OH": {}, "US-OK": {}, "US-OR": {}, "US-PA": {}, "US-PR": {}, "US-RI": {}, "US-SC": {}, "US-SD": {}, "US-TN": {}, "US-TX": {}, "US-UM": {}, "US-UT": {}, "US-VA": {}, "US-VI": {}, "US-VT": {}, "US-WA": {}, "US-WI": {}, "US-WV": {}, "US-WY": {}, "UY-AR": {}, "UY-CA": {}, "UY-CL": {}, "UY-CO": {}, "UY-DU": {}, "UY-FD": {}, "UY-FS": {}, "UY-LA": {}, "UY-MA": {}, "UY-MO": {}, "UY-PA": {}, "UY-RN": {}, "UY-RO": {}, "UY-RV": {}, "UY-SA": {}, "UY-SJ": {}, "UY-SO": {}, "UY-TA": {}, "UY-TT": {}, "UZ-AN": {}, "UZ-BU": {}, "UZ-FA": {}, "UZ-JI": {}, "UZ-NG": {}, "UZ-NW": {}, "UZ-QA": {}, "UZ-QR": {}, "UZ-SA": {}, "UZ-SI": {}, "UZ-SU": {}, "UZ-TK": {}, "UZ-TO": {}, "UZ-XO": {}, "VC-01": {}, "VC-02": {}, "VC-03": {}, "VC-04": {}, "VC-05": {}, "VC-06": {}, "VE-A": {}, "VE-B": {}, "VE-C": {}, "VE-D": {}, "VE-E": {}, "VE-F": {}, "VE-G": {}, "VE-H": {}, "VE-I": {}, "VE-J": {}, "VE-K": {}, "VE-L": {}, "VE-M": {}, "VE-N": {}, "VE-O": {}, "VE-P": {}, "VE-R": {}, "VE-S": {}, "VE-T": {}, "VE-U": {}, "VE-V": {}, "VE-W": {}, "VE-X": {}, "VE-Y": {}, "VE-Z": {}, "VN-01": {}, "VN-02": {}, "VN-03": {}, "VN-04": {}, "VN-05": {}, "VN-06": {}, "VN-07": {}, "VN-09": {}, "VN-13": {}, "VN-14": {}, "VN-15": {}, "VN-18": {}, "VN-20": {}, "VN-21": {}, "VN-22": {}, "VN-23": {}, "VN-24": {}, "VN-25": {}, "VN-26": {}, "VN-27": {}, "VN-28": {}, "VN-29": {}, "VN-30": {}, "VN-31": {}, "VN-32": {}, "VN-33": {}, "VN-34": {}, "VN-35": {}, "VN-36": {}, "VN-37": {}, "VN-39": {}, "VN-40": {}, "VN-41": {}, "VN-43": {}, "VN-44": {}, "VN-45": {}, "VN-46": {}, "VN-47": {}, "VN-49": {}, "VN-50": {}, "VN-51": {}, "VN-52": {}, "VN-53": {}, "VN-54": {}, "VN-55": {}, "VN-56": {}, "VN-57": {}, "VN-58": {}, "VN-59": {}, "VN-61": {}, "VN-63": {}, "VN-66": {}, "VN-67": {}, "VN-68": {}, "VN-69": {}, "VN-70": {}, "VN-71": {}, "VN-72": {}, "VN-73": {}, "VN-CT": {}, "VN-DN": {}, "VN-HN": {}, "VN-HP": {}, "VN-SG": {}, "VU-MAP": {}, "VU-PAM": {}, "VU-SAM": {}, "VU-SEE": {}, "VU-TAE": {}, "VU-TOB": {}, "WF-SG": {}, "WF-UV": {}, "WS-AA": {}, "WS-AL": {}, "WS-AT": {}, "WS-FA": {}, "WS-GE": {}, "WS-GI": {}, "WS-PA": {}, "WS-SA": {}, "WS-TU": {}, "WS-VF": {}, "WS-VS": {}, "YE-AB": {}, "YE-AD": {}, "YE-AM": {}, "YE-BA": {}, "YE-DA": {}, "YE-DH": {}, "YE-HD": {}, "YE-HJ": {}, "YE-HU": {}, "YE-IB": {}, "YE-JA": {}, "YE-LA": {}, "YE-MA": {}, "YE-MR": {}, "YE-MU": {}, "YE-MW": {}, "YE-RA": {}, "YE-SA": {}, "YE-SD": {}, "YE-SH": {}, "YE-SN": {}, "YE-TA": {}, "ZA-EC": {}, "ZA-FS": {}, "ZA-GP": {}, "ZA-LP": {}, "ZA-MP": {}, "ZA-NC": {}, "ZA-NW": {}, "ZA-WC": {}, "ZA-ZN": {}, "ZA-KZN": {}, "ZM-01": {}, "ZM-02": {}, "ZM-03": {}, "ZM-04": {}, "ZM-05": {}, "ZM-06": {}, "ZM-07": {}, "ZM-08": {}, "ZM-09": {}, "ZM-10": {}, "ZW-BU": {}, "ZW-HA": {}, "ZW-MA": {}, "ZW-MC": {}, "ZW-ME": {}, "ZW-MI": {}, "ZW-MN": {}, "ZW-MS": {}, "ZW-MV": {}, "ZW-MW": {}, } golang-github-go-playground-validator-v10-10.30.1/currency_codes.go000066400000000000000000000072021512410077000251130ustar00rootroot00000000000000package validator var iso4217 = map[string]struct{}{ "AFN": {}, "EUR": {}, "ALL": {}, "DZD": {}, "USD": {}, "AOA": {}, "XCD": {}, "ARS": {}, "AMD": {}, "AWG": {}, "AUD": {}, "AZN": {}, "BSD": {}, "BHD": {}, "BDT": {}, "BBD": {}, "BYN": {}, "BZD": {}, "XOF": {}, "BMD": {}, "INR": {}, "BTN": {}, "BOB": {}, "BOV": {}, "BAM": {}, "BWP": {}, "NOK": {}, "BRL": {}, "BND": {}, "BGN": {}, "BIF": {}, "CVE": {}, "KHR": {}, "XAF": {}, "CAD": {}, "KYD": {}, "CLP": {}, "CLF": {}, "CNY": {}, "COP": {}, "COU": {}, "KMF": {}, "CDF": {}, "NZD": {}, "CRC": {}, "CUP": {}, "CZK": {}, "DKK": {}, "DJF": {}, "DOP": {}, "EGP": {}, "SVC": {}, "ERN": {}, "SZL": {}, "ETB": {}, "FKP": {}, "FJD": {}, "XPF": {}, "GMD": {}, "GEL": {}, "GHS": {}, "GIP": {}, "GTQ": {}, "GBP": {}, "GNF": {}, "GYD": {}, "HTG": {}, "HNL": {}, "HKD": {}, "HUF": {}, "ISK": {}, "IDR": {}, "XDR": {}, "IRR": {}, "IQD": {}, "ILS": {}, "JMD": {}, "JPY": {}, "JOD": {}, "KZT": {}, "KES": {}, "KPW": {}, "KRW": {}, "KWD": {}, "KGS": {}, "LAK": {}, "LBP": {}, "LSL": {}, "ZAR": {}, "LRD": {}, "LYD": {}, "CHF": {}, "MOP": {}, "MKD": {}, "MGA": {}, "MWK": {}, "MYR": {}, "MVR": {}, "MRU": {}, "MUR": {}, "XUA": {}, "MXN": {}, "MXV": {}, "MDL": {}, "MNT": {}, "MAD": {}, "MZN": {}, "MMK": {}, "NAD": {}, "NPR": {}, "NIO": {}, "NGN": {}, "OMR": {}, "PKR": {}, "PAB": {}, "PGK": {}, "PYG": {}, "PEN": {}, "PHP": {}, "PLN": {}, "QAR": {}, "RON": {}, "RUB": {}, "RWF": {}, "SHP": {}, "WST": {}, "STN": {}, "SAR": {}, "RSD": {}, "SCR": {}, "SLE": {}, "SGD": {}, "XSU": {}, "SBD": {}, "SOS": {}, "SSP": {}, "LKR": {}, "SDG": {}, "SRD": {}, "SEK": {}, "CHE": {}, "CHW": {}, "SYP": {}, "TWD": {}, "TJS": {}, "TZS": {}, "THB": {}, "TOP": {}, "TTD": {}, "TND": {}, "TRY": {}, "TMT": {}, "UGX": {}, "UAH": {}, "AED": {}, "USN": {}, "UYU": {}, "UYI": {}, "UYW": {}, "UZS": {}, "VUV": {}, "VES": {}, "VED": {}, "VND": {}, "YER": {}, "ZMW": {}, "ZWG": {}, "XBA": {}, "XBB": {}, "XBC": {}, "XBD": {}, "XCG": {}, "XTS": {}, "XXX": {}, "XAU": {}, "XPD": {}, "XPT": {}, "XAG": {}, } var iso4217_numeric = map[int]struct{}{ 8: {}, 12: {}, 32: {}, 36: {}, 44: {}, 48: {}, 50: {}, 51: {}, 52: {}, 60: {}, 64: {}, 68: {}, 72: {}, 84: {}, 90: {}, 96: {}, 104: {}, 108: {}, 116: {}, 124: {}, 132: {}, 136: {}, 144: {}, 152: {}, 156: {}, 170: {}, 174: {}, 188: {}, 192: {}, 203: {}, 208: {}, 214: {}, 222: {}, 230: {}, 232: {}, 238: {}, 242: {}, 262: {}, 270: {}, 292: {}, 320: {}, 324: {}, 328: {}, 332: {}, 340: {}, 344: {}, 348: {}, 352: {}, 356: {}, 360: {}, 364: {}, 368: {}, 376: {}, 388: {}, 392: {}, 398: {}, 400: {}, 404: {}, 408: {}, 410: {}, 414: {}, 417: {}, 418: {}, 422: {}, 426: {}, 430: {}, 434: {}, 446: {}, 454: {}, 458: {}, 462: {}, 480: {}, 484: {}, 496: {}, 498: {}, 504: {}, 512: {}, 516: {}, 524: {}, 532: {}, 533: {}, 548: {}, 554: {}, 558: {}, 566: {}, 578: {}, 586: {}, 590: {}, 598: {}, 600: {}, 604: {}, 608: {}, 634: {}, 643: {}, 646: {}, 654: {}, 682: {}, 690: {}, 702: {}, 704: {}, 706: {}, 710: {}, 728: {}, 748: {}, 752: {}, 756: {}, 760: {}, 764: {}, 776: {}, 780: {}, 784: {}, 788: {}, 800: {}, 807: {}, 818: {}, 826: {}, 834: {}, 840: {}, 858: {}, 860: {}, 882: {}, 886: {}, 901: {}, 924: {}, 925: {}, 926: {}, 927: {}, 928: {}, 929: {}, 930: {}, 933: {}, 934: {}, 936: {}, 938: {}, 940: {}, 941: {}, 943: {}, 944: {}, 946: {}, 947: {}, 948: {}, 949: {}, 950: {}, 951: {}, 952: {}, 953: {}, 955: {}, 956: {}, 957: {}, 958: {}, 959: {}, 960: {}, 961: {}, 962: {}, 963: {}, 964: {}, 965: {}, 967: {}, 968: {}, 969: {}, 970: {}, 971: {}, 972: {}, 973: {}, 975: {}, 976: {}, 977: {}, 978: {}, 979: {}, 980: {}, 981: {}, 984: {}, 985: {}, 986: {}, 990: {}, 994: {}, 997: {}, 999: {}, } golang-github-go-playground-validator-v10-10.30.1/doc.go000066400000000000000000001215631512410077000226600ustar00rootroot00000000000000/* Package validator implements value validations for structs and individual fields based on tags. It can also handle Cross-Field and Cross-Struct validation for nested structs and has the ability to dive into arrays and maps of any type. see more examples https://github.com/go-playground/validator/tree/master/_examples # Singleton Validator is designed to be thread-safe and used as a singleton instance. It caches information about your struct and validations, in essence only parsing your validation tags once per struct type. Using multiple instances neglects the benefit of caching. The not thread-safe functions are explicitly marked as such in the documentation. # Validation Functions Return Type error Doing things this way is actually the way the standard library does, see the file.Open method here: https://golang.org/pkg/os/#Open. The authors 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 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 err.(validator.ValidationErrors). # Custom Validation Functions Custom Validation functions can be added. Example: // Structure func customFunc(fl validator.FieldLevel) bool { if fl.Field().String() == "invalid" { return false } return true } validate.RegisterValidation("custom tag name", customFunc) // NOTES: using the same tag name as an existing function // will overwrite the existing one # Cross-Field Validation Cross-Field Validation can be done via the following tags: - eqfield - nefield - gtfield - gtefield - ltfield - ltefield - eqcsfield - necsfield - gtcsfield - gtecsfield - ltcsfield - ltecsfield If, however, some custom cross-field validation is required, it can be done using a custom validation. Why not just have cross-fields validation tags (i.e. only eqcsfield and not eqfield)? The reason is efficiency. If you want to check a field within the same struct "eqfield" only has to find the field on the same struct (1 level). But, if we used "eqcsfield" it could be multiple levels down. Example: type Inner struct { StartDate time.Time } type Outer struct { InnerStructField *Inner CreatedAt time.Time `validate:"ltecsfield=InnerStructField.StartDate"` } now := time.Now() inner := &Inner{ StartDate: now, } outer := &Outer{ InnerStructField: inner, CreatedAt: now, } errs := validate.Struct(outer) // NOTE: when calling validate.Struct(val) topStruct will be the top level struct passed // into the function // when calling validate.VarWithValue(val, field, tag) val will be // whatever you pass, struct, field... // when calling validate.Field(field, tag) val will be nil # Multiple Validators Multiple validators on a field will process in the order defined. Example: type Test struct { Field `validate:"max=10,min=1"` } // max will be checked then min Bad Validator definitions are not handled by the library. Example: type Test struct { Field `validate:"min=10,max=0"` } // this definition of min max will never succeed # Using Validator Tags Baked In Cross-Field validation only compares fields on the same struct. If Cross-Field + Cross-Struct validation is needed you should implement your own custom validator. Comma (",") is the default separator of validation tags. If you wish to have a comma included within the parameter (i.e. excludesall=,) you will need to use the UTF-8 hex representation 0x2C, which is replaced in the code as a comma, so the above will become excludesall=0x2C. type Test struct { Field `validate:"excludesall=,"` // BAD! Do not include a comma. Field `validate:"excludesall=0x2C"` // GOOD! Use the UTF-8 hex representation. } Pipe ("|") is the 'or' validation tags deparator. If you wish to have a pipe included within the parameter i.e. excludesall=| you will need to use the UTF-8 hex representation 0x7C, which is replaced in the code as a pipe, so the above will become excludesall=0x7C type Test struct { Field `validate:"excludesall=|"` // BAD! Do not include a pipe! Field `validate:"excludesall=0x7C"` // GOOD! Use the UTF-8 hex representation. } # Baked In Validators and Tags Here is a list of the current built in validators: # Skip Field Tells the validation to skip this struct field; this is particularly handy in ignoring embedded structs from being validated. (Usage: -) Usage: - # Or Operator This is the 'or' operator allowing multiple validators to be used and accepted. (Usage: rgb|rgba) <-- this would allow either rgb or rgba colors to be accepted. This can also be combined with 'and' for example ( Usage: omitempty,rgb|rgba) Usage: | # StructOnly When a field that is a nested struct is encountered, and contains this flag any validation on the nested struct will be run, but none of the nested struct fields will be validated. This is useful if inside of your program you know the struct will be valid, but need to verify it has been assigned. NOTE: only "required" and "omitempty" can be used on a struct itself. Usage: structonly # NoStructLevel Same as structonly tag except that any struct level validations will not run. Usage: nostructlevel # Omit Empty Allows conditional validation, for example, if a field is not set with a value (Determined by the "required" validator) then other validation such as min or max won't run, but if a value is set validation will run. Usage: omitempty # Omit Nil Allows to skip the validation if the value is nil (same as omitempty, but only for the nil-values). Usage: omitnil # Omit Zero Allows to skip the validation if the value is a zero value. For pointers, it checks if the pointer is nil or the underlying value is a zero value. For slices and maps, it checks if the value is nil or empty. Otherwise, behaves the same as omitempty. Usage: omitzero # Dive This tells the validator to dive into a slice, array or map and validate that level of the slice, array or map with the validation tags that follow. Multidimensional nesting is also supported, each level you wish to dive will require another dive tag. dive has some sub-tags, 'keys' & 'endkeys', please see the Keys & EndKeys section just below. Usage: dive Example #1 [][]string with validation tag "gt=0,dive,len=1,dive,required" // gt=0 will be applied to [] // len=1 will be applied to []string // required will be applied to string Example #2 [][]string with validation tag "gt=0,dive,dive,required" // gt=0 will be applied to [] // []string will be spared validation // required will be applied to string Keys & EndKeys These are to be used together directly after the dive tag and tells the validator that anything between 'keys' and 'endkeys' applies to the keys of a map and not the values; think of it like the 'dive' tag, but for map keys instead of values. Multidimensional nesting is also supported, each level you wish to validate will require another 'keys' and 'endkeys' tag. These tags are only valid for maps. Usage: dive,keys,othertagvalidation(s),endkeys,valuevalidationtags Example #1 map[string]string with validation tag "gt=0,dive,keys,eq=1|eq=2,endkeys,required" // gt=0 will be applied to the map itself // eq=1|eq=2 will be applied to the map keys // required will be applied to map values Example #2 map[[2]string]string with validation tag "gt=0,dive,keys,dive,eq=1|eq=2,endkeys,required" // gt=0 will be applied to the map itself // eq=1|eq=2 will be applied to each array element in the map keys // required will be applied to map values # Required This validates that the value is not the data types default zero value. For numbers ensures value is not zero. For strings ensures value is not "". For booleans ensures value is not false. For slices, maps, pointers, interfaces, channels and functions ensures the value is not nil. For structs ensures value is not the zero value when using WithRequiredStructEnabled. Usage: required # Required If The field under validation must be present and not empty only if all the other specified fields are equal to the value following the specified field. For strings ensures value is not "". For slices, maps, pointers, interfaces, channels and functions ensures the value is not nil. For structs ensures value is not the zero value. Using the same field name multiple times in the parameters will result in a panic at runtime. Usage: required_if Examples: // require the field if the Field1 is equal to the parameter given: Usage: required_if=Field1 foobar // require the field if the Field1 and Field2 is equal to the value respectively: Usage: required_if=Field1 foo Field2 bar # Required Unless The field under validation must be present and not empty unless all the other specified fields are equal to the value following the specified field. For strings ensures value is not "". For slices, maps, pointers, interfaces, channels and functions ensures the value is not nil. For structs ensures value is not the zero value. Usage: required_unless Examples: // require the field unless the Field1 is equal to the parameter given: Usage: required_unless=Field1 foobar // require the field unless the Field1 and Field2 is equal to the value respectively: Usage: required_unless=Field1 foo Field2 bar # Required With The field under validation must be present and not empty only if any of the other specified fields are present. For strings ensures value is not "". For slices, maps, pointers, interfaces, channels and functions ensures the value is not nil. For structs ensures value is not the zero value. Usage: required_with Examples: // require the field if the Field1 is present: Usage: required_with=Field1 // require the field if the Field1 or Field2 is present: Usage: required_with=Field1 Field2 # Required With All The field under validation must be present and not empty only if all of the other specified fields are present. For strings ensures value is not "". For slices, maps, pointers, interfaces, channels and functions ensures the value is not nil. For structs ensures value is not the zero value. Usage: required_with_all Example: // require the field if the Field1 and Field2 is present: Usage: required_with_all=Field1 Field2 # Required Without The field under validation must be present and not empty only when any of the other specified fields are not present. For strings ensures value is not "". For slices, maps, pointers, interfaces, channels and functions ensures the value is not nil. For structs ensures value is not the zero value. Usage: required_without Examples: // require the field if the Field1 is not present: Usage: required_without=Field1 // require the field if the Field1 or Field2 is not present: Usage: required_without=Field1 Field2 # Required Without All The field under validation must be present and not empty only when all of the other specified fields are not present. For strings ensures value is not "". For slices, maps, pointers, interfaces, channels and functions ensures the value is not nil. For structs ensures value is not the zero value. Usage: required_without_all Example: // require the field if the Field1 and Field2 is not present: Usage: required_without_all=Field1 Field2 # Excluded If The field under validation must not be present or not empty only if all the other specified fields are equal to the value following the specified field. For strings ensures value is not "". For slices, maps, pointers, interfaces, channels and functions ensures the value is not nil. For structs ensures value is not the zero value. Usage: excluded_if Examples: // exclude the field if the Field1 is equal to the parameter given: Usage: excluded_if=Field1 foobar // exclude the field if the Field1 and Field2 is equal to the value respectively: Usage: excluded_if=Field1 foo Field2 bar # Excluded Unless The field under validation must not be present or empty unless all the other specified fields are equal to the value following the specified field. For strings ensures value is not "". For slices, maps, pointers, interfaces, channels and functions ensures the value is not nil. For structs ensures value is not the zero value. Usage: excluded_unless Examples: // exclude the field unless the Field1 is equal to the parameter given: Usage: excluded_unless=Field1 foobar // exclude the field unless the Field1 and Field2 is equal to the value respectively: Usage: excluded_unless=Field1 foo Field2 bar # Is Default This validates that the value is the default value and is almost the opposite of required. Usage: isdefault # Length For numbers, length will ensure that the value is equal to the parameter given. For strings, it checks that the string length is exactly that number of characters. For slices, arrays, and maps, validates the number of items. Example #1 Usage: len=10 Example #2 (time.Duration) For time.Duration, len will ensure that the value is equal to the duration given in the parameter. Usage: len=1h30m # Maximum For numbers, max will ensure that the value is less than or equal to the parameter given. For strings, it checks that the string length is at most that number of characters. For slices, arrays, and maps, validates the number of items. Example #1 Usage: max=10 Example #2 (time.Duration) For time.Duration, max will ensure that the value is less than or equal to the duration given in the parameter. Usage: max=1h30m # Minimum For numbers, min will ensure that the value is greater or equal to the parameter given. For strings, it checks that the string length is at least that number of characters. For slices, arrays, and maps, validates the number of items. Example #1 Usage: min=10 Example #2 (time.Duration) For time.Duration, min will ensure that the value is greater than or equal to the duration given in the parameter. Usage: min=1h30m # Equals For strings & numbers, eq will ensure that the value is equal to the parameter given. For slices, arrays, and maps, validates the number of items. Example #1 Usage: eq=10 Example #2 (time.Duration) For time.Duration, eq will ensure that the value is equal to the duration given in the parameter. Usage: eq=1h30m # Not Equal For strings & numbers, ne will ensure that the value is not equal to the parameter given. For slices, arrays, and maps, validates the number of items. Example #1 Usage: ne=10 Example #2 (time.Duration) For time.Duration, ne will ensure that the value is not equal to the duration given in the parameter. Usage: ne=1h30m # One Of For strings, ints, and uints, oneof will ensure that the value is one of the values in the parameter. The parameter should be a list of values separated by whitespace. Values may be strings or numbers. To match strings with spaces in them, include the target string between single quotes. Kind of like an 'enum'. Usage: oneof=red green oneof='red green' 'blue yellow' oneof=5 7 9 # One Of Case Insensitive Works the same as oneof but is case insensitive and therefore only accepts strings. Usage: oneofci=red green oneofci='red green' 'blue yellow' # Greater Than For numbers, this will ensure that the value is greater than the parameter given. For strings, it checks that the string length is greater than that number of characters. For slices, arrays and maps it validates the number of items. Example #1 Usage: gt=10 Example #2 (time.Time) For time.Time ensures the time value is greater than time.Now.UTC(). Usage: gt Example #3 (time.Duration) For time.Duration, gt will ensure that the value is greater than the duration given in the parameter. Usage: gt=1h30m # Greater Than or Equal Same as 'min' above. Kept both to make terminology with 'len' easier. Example #1 Usage: gte=10 Example #2 (time.Time) For time.Time ensures the time value is greater than or equal to time.Now.UTC(). Usage: gte Example #3 (time.Duration) For time.Duration, gte will ensure that the value is greater than or equal to the duration given in the parameter. Usage: gte=1h30m # Less Than For numbers, this will ensure that the value is less than the parameter given. For strings, it checks that the string length is less than that number of characters. For slices, arrays, and maps it validates the number of items. Example #1 Usage: lt=10 Example #2 (time.Time) For time.Time ensures the time value is less than time.Now.UTC(). Usage: lt Example #3 (time.Duration) For time.Duration, lt will ensure that the value is less than the duration given in the parameter. Usage: lt=1h30m # Less Than or Equal Same as 'max' above. Kept both to make terminology with 'len' easier. Example #1 Usage: lte=10 Example #2 (time.Time) For time.Time ensures the time value is less than or equal to time.Now.UTC(). Usage: lte Example #3 (time.Duration) For time.Duration, lte will ensure that the value is less than or equal to the duration given in the parameter. Usage: lte=1h30m # Field Equals Another Field This will validate the field value against another fields value either within a struct or passed in field. Example #1: // Validation on Password field using: Usage: eqfield=ConfirmPassword Example #2: // Validating by field: validate.VarWithValue(password, confirmpassword, "eqfield") Field Equals Another Field (relative) This does the same as eqfield except that it validates the field provided relative to the top level struct. Usage: eqcsfield=InnerStructField.Field) # Field Does Not Equal Another Field This will validate the field value against another fields value either within a struct or passed in field. Examples: // Confirm two colors are not the same: // // Validation on Color field: Usage: nefield=Color2 // Validating by field: validate.VarWithValue(color1, color2, "nefield") Field Does Not Equal Another Field (relative) This does the same as nefield except that it validates the field provided relative to the top level struct. Usage: necsfield=InnerStructField.Field # Field Greater Than Another Field Only valid for Numbers, time.Duration and time.Time types, this will validate the field value against another fields value either within a struct or passed in field. usage examples are for validation of a Start and End date: Example #1: // Validation on End field using: validate.Struct Usage(gtfield=Start) Example #2: // Validating by field: validate.VarWithValue(start, end, "gtfield") # Field Greater Than Another Relative Field This does the same as gtfield except that it validates the field provided relative to the top level struct. Usage: gtcsfield=InnerStructField.Field # Field Greater Than or Equal To Another Field Only valid for Numbers, time.Duration and time.Time types, this will validate the field value against another fields value either within a struct or passed in field. usage examples are for validation of a Start and End date: Example #1: // Validation on End field using: validate.Struct Usage(gtefield=Start) Example #2: // Validating by field: validate.VarWithValue(start, end, "gtefield") # Field Greater Than or Equal To Another Relative Field This does the same as gtefield except that it validates the field provided relative to the top level struct. Usage: gtecsfield=InnerStructField.Field # Less Than Another Field Only valid for Numbers, time.Duration and time.Time types, this will validate the field value against another fields value either within a struct or passed in field. usage examples are for validation of a Start and End date: Example #1: // Validation on End field using: validate.Struct Usage(ltfield=Start) Example #2: // Validating by field: validate.VarWithValue(start, end, "ltfield") # Less Than Another Relative Field This does the same as ltfield except that it validates the field provided relative to the top level struct. Usage: ltcsfield=InnerStructField.Field # Less Than or Equal To Another Field Only valid for Numbers, time.Duration and time.Time types, this will validate the field value against another fields value either within a struct or passed in field. usage examples are for validation of a Start and End date: Example #1: // Validation on End field using: validate.Struct Usage(ltefield=Start) Example #2: // Validating by field: validate.VarWithValue(start, end, "ltefield") # Less Than or Equal To Another Relative Field This does the same as ltefield except that it validates the field provided relative to the top level struct. Usage: ltecsfield=InnerStructField.Field # Field Contains Another Field This does the same as contains except for struct fields. It should only be used with string types. See the behavior of reflect.Value.String() for behavior on other types. Usage: containsfield=InnerStructField.Field # Field Excludes Another Field This does the same as excludes except for struct fields. It should only be used with string types. See the behavior of reflect.Value.String() for behavior on other types. Usage: excludesfield=InnerStructField.Field # Unique For arrays & slices, unique will ensure that there are no duplicates. For maps, unique will ensure that there are no duplicate values. For slices of struct, unique will ensure that there are no duplicate values in a field of the struct specified via a parameter. // For arrays, slices, and maps: Usage: unique // For slices of struct: Usage: unique=field # ValidateFn This validates that an object responds to a method that can return error or bool. By default it expects an interface `Validate() error` and check that the method does not return an error. Other methods can be specified using two signatures: If the method returns an error, it check if the return value is nil. If the method returns a boolean, it checks if the value is true. // to use the default method Validate() error Usage: validateFn // to use the custom method IsValid() bool (or error) Usage: validateFn=IsValid # Alpha Only This validates that a string value contains ASCII alpha characters only Usage: alpha # Alpha Space This validates that a string value contains ASCII alpha characters and spaces only Usage: alphaspace # Alphanumeric This validates that a string value contains ASCII alphanumeric characters only Usage: alphanum # Alphanumeric Space This validates that a string value contains ASCII alphanumeric characters and spaces only Usage: alphanumspace # Alpha Unicode This validates that a string value contains unicode alpha characters only Usage: alphaunicode # Alphanumeric Unicode This validates that a string value contains unicode alphanumeric characters only Usage: alphanumunicode # Boolean This validates that a string value can successfully be parsed into a boolean with strconv.ParseBool Usage: boolean # Number This validates that a string value contains number values only. For integers or float it returns true. Usage: number # Numeric This validates that a string value contains a basic numeric value. basic excludes exponents etc... for integers or float it returns true. Usage: numeric # Hexadecimal String This validates that a string value contains a valid hexadecimal. Usage: hexadecimal # Hexcolor String This validates that a string value contains a valid hex color including hashtag (#) Usage: hexcolor # Lowercase String This validates that a string value contains only lowercase characters. An empty string is not a valid lowercase string. Usage: lowercase # Uppercase String This validates that a string value contains only uppercase characters. An empty string is not a valid uppercase string. Usage: uppercase # RGB String This validates that a string value contains a valid rgb color Usage: rgb # RGBA String This validates that a string value contains a valid rgba color Usage: rgba # HSL String This validates that a string value contains a valid hsl color Usage: hsl # HSLA String This validates that a string value contains a valid hsla color Usage: hsla # E.164 Phone Number String This validates that a string value contains a valid E.164 Phone number https://en.wikipedia.org/wiki/E.164 (ex. +1123456789) Usage: e164 # E-mail String This validates that a string value contains a valid email This may not conform to all possibilities of any rfc standard, but neither does any email provider accept all possibilities. Usage: email # JSON String This validates that a string value is valid JSON Usage: json # JWT String This validates that a string value is a valid JWT Usage: jwt # File This validates that a string value contains a valid file path and that the file exists on the machine. This is done using os.Stat, which is a platform independent function. Usage: file # Image path This validates that a string value contains a valid file path and that the file exists on the machine and is an image. This is done using os.Stat and github.com/gabriel-vasile/mimetype Usage: image # File Path This validates that a string value contains a valid file path but does not validate the existence of that file. This is done using os.Stat, which is a platform independent function. Usage: filepath # URL String This validates that a string value contains a valid url This will accept any url the golang request uri accepts but must contain a schema for example http:// or rtmp:// Usage: url # URI String This validates that a string value contains a valid uri This will accept any uri the golang request uri accepts Usage: uri # Urn RFC 2141 String This validates that a string value contains a valid URN according to the RFC 2141 spec. Usage: urn_rfc2141 # Base32 String This validates that a string value contains a valid bas324 value. Although an empty string is valid base32 this will report an empty string as an error, if you wish to accept an empty string as valid you can use this with the omitempty tag. Usage: base32 # Base64 String This validates that a string value contains a valid base64 value. Although an empty string is valid base64 this will report an empty string as an error, if you wish to accept an empty string as valid you can use this with the omitempty tag. Usage: base64 # Base64URL String This validates that a string value contains a valid base64 URL safe value according the RFC4648 spec. Although an empty string is a valid base64 URL safe value, this will report an empty string as an error, if you wish to accept an empty string as valid you can use this with the omitempty tag. Usage: base64url # Base64RawURL String This validates that a string value contains a valid base64 URL safe value, but without = padding, according the RFC4648 spec, section 3.2. Although an empty string is a valid base64 URL safe value, this will report an empty string as an error, if you wish to accept an empty string as valid you can use this with the omitempty tag. Usage: base64rawurl # Bitcoin Address This validates that a string value contains a valid bitcoin address. The format of the string is checked to ensure it matches one of the three formats P2PKH, P2SH and performs checksum validation. Usage: btc_addr Bitcoin Bech32 Address (segwit) This validates that a string value contains a valid bitcoin Bech32 address as defined by bip-0173 (https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki) Special thanks to Pieter Wuille for providing reference implementations. Usage: btc_addr_bech32 # Ethereum Address This validates that a string value contains a valid ethereum address. The format of the string is checked to ensure it matches the standard Ethereum address format. Usage: eth_addr # Contains This validates that a string value contains the substring value. Usage: contains=@ # Contains Any This validates that a string value contains any Unicode code points in the substring value. Usage: containsany=!@#? # Contains Rune This validates that a string value contains the supplied rune value. Usage: containsrune=@ # Excludes This validates that a string value does not contain the substring value. Usage: excludes=@ # Excludes All This validates that a string value does not contain any Unicode code points in the substring value. Usage: excludesall=!@#? # Excludes Rune This validates that a string value does not contain the supplied rune value. Usage: excludesrune=@ # Starts With This validates that a string value starts with the supplied string value Usage: startswith=hello # Ends With This validates that a string value ends with the supplied string value Usage: endswith=goodbye # Does Not Start With This validates that a string value does not start with the supplied string value Usage: startsnotwith=hello # Does Not End With This validates that a string value does not end with the supplied string value Usage: endsnotwith=goodbye # International Standard Book Number This validates that a string value contains a valid isbn10 or isbn13 value. Usage: isbn # International Standard Book Number 10 This validates that a string value contains a valid isbn10 value. Usage: isbn10 # International Standard Book Number 13 This validates that a string value contains a valid isbn13 value. Usage: isbn13 # Universally Unique Identifier UUID This validates that a string value contains a valid UUID. Uppercase UUID values will not pass - use `uuid_rfc4122` instead. Usage: uuid # Universally Unique Identifier UUID v3 This validates that a string value contains a valid version 3 UUID. Uppercase UUID values will not pass - use `uuid3_rfc4122` instead. Usage: uuid3 # Universally Unique Identifier UUID v4 This validates that a string value contains a valid version 4 UUID. Uppercase UUID values will not pass - use `uuid4_rfc4122` instead. Usage: uuid4 # Universally Unique Identifier UUID v5 This validates that a string value contains a valid version 5 UUID. Uppercase UUID values will not pass - use `uuid5_rfc4122` instead. Usage: uuid5 # Universally Unique Lexicographically Sortable Identifier ULID This validates that a string value contains a valid ULID value. Usage: ulid # ASCII This validates that a string value contains only ASCII characters. NOTE: if the string is blank, this validates as true. Usage: ascii # Printable ASCII This validates that a string value contains only printable ASCII characters. NOTE: if the string is blank, this validates as true. Usage: printascii # Multi-Byte Characters This validates that a string value contains one or more multibyte characters. NOTE: if the string is blank, this validates as true. Usage: multibyte # Data URL This validates that a string value contains a valid DataURI. NOTE: this will also validate that the data portion is valid base64 Usage: datauri # Latitude This validates that a string value contains a valid latitude. Usage: latitude # Longitude This validates that a string value contains a valid longitude. Usage: longitude # Employeer Identification Number EIN This validates that a string value contains a valid U.S. Employer Identification Number. Usage: ein # Social Security Number SSN This validates that a string value contains a valid U.S. Social Security Number. Usage: ssn # Internet Protocol Address IP This validates that a string value contains a valid IP Address. Usage: ip # Internet Protocol Address IPv4 This validates that a string value contains a valid v4 IP Address. Usage: ipv4 # Internet Protocol Address IPv6 This validates that a string value contains a valid v6 IP Address. Usage: ipv6 # Classless Inter-Domain Routing CIDR This validates that a string value contains a valid CIDR Address. Usage: cidr # Classless Inter-Domain Routing CIDRv4 This validates that a string value contains a valid v4 CIDR Address. Usage: cidrv4 # Classless Inter-Domain Routing CIDRv6 This validates that a string value contains a valid v6 CIDR Address. Usage: cidrv6 # Transmission Control Protocol Address TCP This validates that a string value contains a valid resolvable TCP Address. Usage: tcp_addr # Transmission Control Protocol Address TCPv4 This validates that a string value contains a valid resolvable v4 TCP Address. Usage: tcp4_addr # Transmission Control Protocol Address TCPv6 This validates that a string value contains a valid resolvable v6 TCP Address. Usage: tcp6_addr # User Datagram Protocol Address UDP This validates that a string value contains a valid resolvable UDP Address. Usage: udp_addr # User Datagram Protocol Address UDPv4 This validates that a string value contains a valid resolvable v4 UDP Address. Usage: udp4_addr # User Datagram Protocol Address UDPv6 This validates that a string value contains a valid resolvable v6 UDP Address. Usage: udp6_addr # Internet Protocol Address IP This validates that a string value contains a valid resolvable IP Address. Usage: ip_addr # Internet Protocol Address IPv4 This validates that a string value contains a valid resolvable v4 IP Address. Usage: ip4_addr # Internet Protocol Address IPv6 This validates that a string value contains a valid resolvable v6 IP Address. Usage: ip6_addr # Unix domain socket end point Address This validates that a string value contains a valid Unix Address. Usage: unix_addr # Unix Domain Socket Exists This validates that a Unix domain socket file exists at the specified path. It checks both filesystem-based sockets and Linux abstract sockets (prefixed with @). For filesystem sockets, it verifies the path exists and is a socket file. For abstract sockets on Linux, it checks /proc/net/unix. Usage: uds_exists # Media Access Control Address MAC This validates that a string value contains a valid MAC Address. Usage: mac Note: See Go's ParseMAC for accepted formats and types: http://golang.org/src/net/mac.go?s=866:918#L29 # Hostname RFC 952 This validates that a string value is a valid Hostname according to RFC 952 https://tools.ietf.org/html/rfc952 Usage: hostname # Hostname RFC 1123 This validates that a string value is a valid Hostname according to RFC 1123 https://tools.ietf.org/html/rfc1123 Usage: hostname_rfc1123 or if you want to continue to use 'hostname' in your tags, create an alias. Full Qualified Domain Name (FQDN) This validates that a string value contains a valid FQDN. Usage: fqdn # HTML Tags This validates that a string value appears to be an HTML element tag including those described at https://developer.mozilla.org/en-US/docs/Web/HTML/Element Usage: html # HTML Encoded This validates that a string value is a proper character reference in decimal or hexadecimal format Usage: html_encoded # URL Encoded This validates that a string value is percent-encoded (URL encoded) according to https://tools.ietf.org/html/rfc3986#section-2.1 Usage: url_encoded # Directory This validates that a string value contains a valid directory and that it exists on the machine. This is done using os.Stat, which is a platform independent function. Usage: dir # Directory Path This validates that a string value contains a valid directory but does not validate the existence of that directory. This is done using os.Stat, which is a platform independent function. It is safest to suffix the string with os.PathSeparator if the directory may not exist at the time of validation. Usage: dirpath # HostPort This validates that a string value contains a valid DNS hostname and port that can be used to validate fields typically passed to sockets and connections. Usage: hostname_port # Port This validates that the value falls within the valid port number range of 1 to 65,535. Usage: port # Datetime This validates that a string value is a valid datetime based on the supplied datetime format. Supplied format must match the official Go time format layout as documented in https://golang.org/pkg/time/ Usage: datetime=2006-01-02 # Iso3166-1 alpha-2 This validates that a string value is a valid country code based on iso3166-1 alpha-2 standard. see: https://www.iso.org/iso-3166-country-codes.html Usage: iso3166_1_alpha2 # Iso3166-1 alpha-3 This validates that a string value is a valid country code based on iso3166-1 alpha-3 standard. see: https://www.iso.org/iso-3166-country-codes.html Usage: iso3166_1_alpha3 # Iso3166-1 alpha-numeric This validates that a string value is a valid country code based on iso3166-1 alpha-numeric standard. see: https://www.iso.org/iso-3166-country-codes.html Usage: iso3166_1_alpha3 # BCP 47 Language Tag This validates that a string value is a valid BCP 47 language tag, as parsed by language.Parse. More information on https://pkg.go.dev/golang.org/x/text/language Usage: bcp47_language_tag BIC (SWIFT code - 2022 standard) This validates that a string value is a valid Business Identifier Code (SWIFT code), defined in ISO 9362:2022. More information on https://www.iso.org/standard/84108.html Usage: bic BIC (SWIFT code - 2014 standard) This validates that a string value is a valid Business Identifier Code (SWIFT code), defined in ISO 9362:2014. More information on https://www.iso.org/standard/60390.html Usage: bic_iso_9362_2014 # RFC 1035 label This validates that a string value is a valid dns RFC 1035 label, defined in RFC 1035. More information on https://datatracker.ietf.org/doc/html/rfc1035 Usage: dns_rfc1035_label # TimeZone This validates that a string value is a valid time zone based on the time zone database present on the system. Although empty value and Local value are allowed by time.LoadLocation golang function, they are not allowed by this validator. More information on https://golang.org/pkg/time/#LoadLocation Usage: timezone # Semantic Version This validates that a string value is a valid semver version, defined in Semantic Versioning 2.0.0. More information on https://semver.org/ Usage: semver # CVE Identifier This validates that a string value is a valid cve id, defined in cve mitre. More information on https://cve.mitre.org/ Usage: cve # Credit Card This validates that a string value contains a valid credit card number using Luhn algorithm. Usage: credit_card # Luhn Checksum Usage: luhn_checksum This validates that a string or (u)int value contains a valid checksum using the Luhn algorithm. # MongoDB This validates that a string is a valid 24 character hexadecimal string or valid connection string. Usage: mongodb mongodb_connection_string Example: type Test struct { ObjectIdField string `validate:"mongodb"` ConnectionStringField string `validate:"mongodb_connection_string"` } # Cron This validates that a string value contains a valid cron expression. Usage: cron # SpiceDb ObjectID/Permission/Object Type This validates that a string is valid for use with SpiceDb for the indicated purpose. If no purpose is given, a purpose of 'id' is assumed. Usage: spicedb=id|permission|type # Alias Validators and Tags Alias Validators and Tags NOTE: When returning an error, the tag returned in "FieldError" will be the alias tag unless the dive tag is part of the alias. Everything after the dive tag is not reported as the alias tag. Also, the "ActualTag" in the before case will be the actual tag within the alias that failed. Here is a list of the current built in alias tags: "iscolor" alias is "hexcolor|rgb|rgba|hsl|hsla" (Usage: iscolor) "country_code" alias is "iso3166_1_alpha2|iso3166_1_alpha3|iso3166_1_alpha_numeric" (Usage: country_code) Validator notes: regex a regex validator won't be added because commas and = signs can be part of a regex which conflict with the validation definitions. Although workarounds can be made, they take away from using pure regex's. Furthermore it's quick and dirty but the regex's become harder to maintain and are not reusable, so it's as much a programming philosophy as anything. In place of this new validator functions should be created; a regex can be used within the validator function and even be precompiled for better efficiency within regexes.go. And the best reason, you can submit a pull request and we can keep on adding to the validation library of this package! # Non standard validators A collection of validation rules that are frequently needed but are more complex than the ones found in the baked in validators. A non standard validator must be registered manually like you would with your own custom validation functions. Example of registration and use: type Test struct { TestField string `validate:"yourtag"` } t := &Test{ TestField: "Test" } validate := validator.New() validate.RegisterValidation("yourtag", validators.NotBlank) Here is a list of the current non standard validators: NotBlank This validates that the value is not blank or with length zero. For strings ensures they do not contain only spaces. For channels, maps, slices and arrays ensures they don't have zero length. For others, a non empty value is required. Usage: notblank # Panics This package panics when bad input is provided, this is by design, bad code like that should not make it to production. type Test struct { TestField string `validate:"nonexistentfunction=1"` } t := &Test{ TestField: "Test" } validate.Struct(t) // this will panic */ package validator golang-github-go-playground-validator-v10-10.30.1/errors.go000066400000000000000000000166121512410077000234250ustar00rootroot00000000000000package 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. // // eg. "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 field's name with the tag name taking precedence over the // field's actual name. // // `RegisterTagNameFunc` must be registered to get tag value. // // eg. JSON name "fname" // see StructField for comparison Field() string // StructField returns the field's actual name from the struct, when able to determine. // // eg. "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 { var fn TranslationFunc m, ok := fe.v.transTagFunc[ut] if !ok { return fe.Error() } fn, ok = m[fe.tag] if !ok { fn, ok = m[fe.actualTag] if !ok { return fe.Error() } } return fn(ut, fe) } golang-github-go-playground-validator-v10-10.30.1/field_level.go000066400000000000000000000114741512410077000243640ustar00rootroot00000000000000package 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) } golang-github-go-playground-validator-v10-10.30.1/go.mod000066400000000000000000000006061512410077000226640ustar00rootroot00000000000000module github.com/go-playground/validator/v10 go 1.24.0 require ( github.com/gabriel-vasile/mimetype v1.4.12 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.4.0 golang.org/x/crypto v0.46.0 golang.org/x/text v0.32.0 ) require golang.org/x/sys v0.39.0 // indirect golang-github-go-playground-validator-v10-10.30.1/go.sum000066400000000000000000000040401512410077000227050ustar00rootroot00000000000000github.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/gabriel-vasile/mimetype v1.4.12 h1:e9hWvmLYvtp846tLHam2o++qitpguFiYCKbn0w9jyqw= github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= 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.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= 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/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= golang-github-go-playground-validator-v10-10.30.1/logo.png000066400000000000000000000322031512410077000232220ustar00rootroot00000000000000PNG  IHDR<qsBIT|d pHYs  ~tEXtSoftwareAdobe Fireworks CS6輲 IDATxwEǿ=yg6/,yQEATD1+S99' ;Sp(&T(y 8?gwfمe}>=5]ݿyz)!hkhcXhtbu]A :ՁvA:. V@Xhtbu]A :Ձvmww Y n H2, g€A_5P߀ŷTⱄ  >ޜSdurgd32]4\TcD0a jk"@xkAMi`;(Rw= Pl gWV~=3x{ڥ+ޜN2px9]GhBD@H R"M#% &PVJu*6t*Y E+~[X?C˒JFGdxul %#/Lt)%f4b&HEZlA4m6R,-b׬w?*PĊ#T8ov)}?!m݆ [wt#" # cICw:9]DA,_ƪ9ۧ.+_F? ,u ٳEtGCNAM 0]4]Chz3 CXlN6 ,}-5Ғ{O1eݓ(")e"v{ k4붤 s~>'N!WoZpȪ{Ӊ.^͵ls:ќ.TQS^:L2:uI! `CeKGg)tB׽'{,ᤦxk`ekW!:RJ+~)BRKȲ0ΙJȈRMB\AG{!Z63 tu5`Mqy}x|>tM#`D#먔\nE \Etrt"AqE[B9]7(zJÈ0|]_:uv76}\4 #BMVV_y~]Y[w\IE,K؀!>H7χSYX?X>}5꼋@$MQ/ث*M'jTv\={`D 4려F,U5|>`:uw 7/͏?SOzNH fqgo9dꍿ$͆ӗJ||ߢ?|{)03ɕ4IJHe&d̛vn5hv;`i*Eddr0cWcw: B,h+1vpƏ9!CpP[QNڵ|?>n<8k*]e;}հ3q/͗_!hލJsO<γ} Sg"?RR2X9S{Q{i2zAFF8>3k . I6?%C: ޟy.н V+_PvG|~߭z@eeX2~gn~G\4&q)qgfGa[01<Y (K35ysy/~:YJYN#XIϾ2@Fw80#ay_u!/ PV+5?cgvϝ3a5{UrF!T] 2t޺'M۩~FM>"P^pjg<ſ^*Rtӗ7{oHt$M/Kq,Ǟx|ozy3DY\.uRgc'd*>Zehv{]@ GdB]Nz TYڔy㜓xC՛@: ?7@׼;Չ=zrEy< vm e,.>s |fwԝReܵݧ?e)\]ןh(HV~x; mҡ6Bo#dÈ(OŦ |vH0KԆ~!3=~|t专N{ͫVl1рfy zÛi72` [ 4: dfsU7xFP&vO N_DM$ uNr:(Y;rl'a:x/f$ ncˏsr mQbyrŌo Ecs5uk  y =ň3ϧD:F$PKd`+flRA4&@<D!hOϘqj`-٦}pԛM? Apf2{>ݺRPIUHD)3N+Y@&IJF2EP{rOȳ/ii'ur\6SnpCsN9saiiDm]B%1l] %ER0 |gLvbYXq᏿Z jO<xJ}G~!ZR-!NIAmO r7Ҍۄ4Q#!GORٸG.7Bdd+/O>Z9/>Hbm OjH-F)Y~MtI*vBXx7;0N>TV\i`&TtaS_ tS/ /Tgz&4W{Ql\# )^4_>|" TjmO$ ~w>ft/HOϋy!hu񛘦'-Zl&>c>Lkw8m%؝FI7o)}?`Mb l4EVZբyM>Ss cTo̊_2?C75 IJ87y9FK)_;#~B}Yl_^{utoj:kW3op.Ezy _.[N0%O9ȣ$UU4K~uay}xDU*+GOt?~G)eeۅH bH)Co7>4;t/n7$NѽnP]X'f͚`|\zM4SI0ԉpALź^r1O@ݑd! FO=C#H?Tu(45T@+2)e4Doʿ΃ ' 3Dm_tT¡ gذa6vl=|`D#N^/T\ }Qx|׌{= ӬP(i ~a@4 w kҠt̺_W8FJٍ$3F 8|'<ψF-}۠`!ۮ#pE,yW0ؼl >(k~I\ AJv#8^' sZ_qÏ3W\&e3 j-U7T3 ޣvcTU RJh 76qM7 FJƌ<οxth Yʬ Nr&4MpZ`P[RO<z<{N0q#/Zu .> t8M Z[aD\dʋ- VKa^i](h F$ag]/pGrĉtֽ6n_|۟~FAj6xNHÌܼ ӝЖjфYxUs뽬]ů#˦f0M*2o4Mf#\ȏe;P!{/BlQHJb=|sUH .µyeg}^UUM Fnq1 E5]V,DH 41~yM~= AC!JK)+0759x^pH0H8;.K 5+B^RJI6M͘2yf/Ēn௭`U[ kA^i]Khe {9k4_}}7D t[ΡH.FhSMSn2> TdXNwjZ[ܔ*lP`D#ՕBйGOS7y+ PKCU]#ߟ{1y ^^ݲ3bǏߏ4GdyT5Q-IMIJvN@e V =TNjrʷr9*CG{;>|ɽut0R߻/fD5px)"P$yx9W(Cy,A4qz}2_AR9HND!ub'Bᵿ1՝ B+k #D p8B`H  ѭ39fo6F!ˍwV-ugP9*s3&ʹ*l;,ƽ!XVmʱø+KϠy{{~u,+Wo%k=` 3Cn;h(=@8.v셸ehcU*ޙs&-XT/oHπzO}ˌum !->ߡiq1sA܌7ToC]5h"v{ 18^PhL, % Mi0׳d3\0(^s CW+W =-G#!C'˿R9u1hiU!ovH$s!yVn'UhͨC>?|ygFZ/).w^^ݱ>NJn^0"D$azT!l*y! :* FF>RG5ꬺw-ȠHm2ڷD[¦bʜ;J^; H؈D$@a'ʒˀfGzRؐ>36 MK|Tv]ǴM^RhJZ2P  Z+ޙ2MW>c>˄TR]Q:[j;l2fl ' J,#FC!* :>Y?pm ? KBGm9K}W3o54X7ILdѰ&ܡ;M 0py<M\S>,NUP$i}yTu$R"Ub+&vv*QϮWqhd )%4?X]4SjSe0 d >S&N]TbS9NEIdHJ$%,k[ D%h*iZ-i IKwj YN;vM#b"OeTv8Ma뷏*v$Dd%N $ XPuU nbyZxU_=[9w7؛.A0wSs6l%V8H:r9`w8}i|0dB:ǹv Gq35?/F{:rbe`Jh8ed.[Ɵʷ𷊍ͥps]FHӄwis$ e-BtGVѝW+=+WCϞٸ "NvnW`ƎLk UŁ5ipbV*;7Oh*2uLjDӣB04ܬt;d vU~z x !H)6}J,kI&p.ӑFOntJoPQ(Ι٪V45?|C&&mh`^|qΦwlXN})bTJMqi5TT NƩS&0i>|!FH)]F,k}xO=3ě@h$næiІ4)^LQ,{CՙwϞXMraj۽`n(ᨁtxyP&3S#ic9l6^{~^@i%`HT%*vhF@'=##dCUQj `2/ǐ60G;S/miDpfyx!c,}.,|;ݰ;UajnNƤ)ǎ_?d=+p8M!# Q%FZ4ӨwoM+ƍPPuDzel8ajP *ۅi,e.ye6́#aHE\̩SQ!ķR%;~Vm)EwCrHOTB?)m 띀4һps{C׮0|M))EꏇW~ѽ'a*fM>5=O}7w-'~IVt<}KۤmXUp t͖*^y ?}Eg{<.+dmT4Mz8~=4y/~>6 >*F-U!]0<)݁ˀǁ')@LwRAM>vn#6UT?~>J=^KV^ <jvկmcmq)֭Kzǟ}78EMfC> !z46n%T EjrCl=XD0`#22s+ϙ?~7ܐy VtƹUFm<*ݶ=xFP;;v@JiJ) wZp^-iIDATx}.ۓhpP ޤqƌIzӝw1Xvr;RTD~l|g"'8!u۩&H b5!Dbw[/(+9>xNnpW#AsԻ"@yޟx"jvB쳝;%בͰ\HPZjEJ0f[_O k ?bY$:D8\jM_}Y&vw@*%xNBoHfbe8}n :js;SU'0-U0dH㗼Dm*w?c=Oƨn)DU.:PZ¨ZJ~NVŽ{Hfb|izEB*FG :?w:/,YAAe2xO1 7q,ԇaRFB*:nIt(֡DQ {\#F҄4TSjk}Y WUD"!R33Y1Xu΢GIz~@gQzݬ\r6ز.'/ک,t&f"6ؖ4/J0bBHJbYdJsz}/ G- Lt~qοpN'+ 4*$atY&A7 Kxóet@a.DNQoo5j / !2*$+$p{6öB,QIJT˨amEE1L]sHVbP( &;TalHag0&dWК|.U,Z&YFH[?*B#! 7nKԊ=20>nR=T԰NG*x71Ӛ'("Ş`̇F__kmx}knq.pF,P? Gu1d(+Y\.LgL±OĿtup8JuuM%J ^E7568v,l4+F,0eߡ}zrѝQ_W.-X./?g<]')6Wr%sO9TXPQ Tpu_sG0OB2 %(mraKK6C~ֳIsS/5 >rH PJ4GŖB4'X*I릠Sfʊ|Ơ@.(?S;;wIA,.,l-&=,[ρh@P9u {%rKYLj3/ǰ0"~n`qmN'vw XӜrpo~B MT_~+7u],~AԢlD9JQp򕝹=X:pǾWB(D[ou'?6xO>#FpmnL$ k>ϢǺ58Yٜua˕•f1`\gHNE&v5<ڟ@lsZJUd);{I52;dNɠ\LtDRtd=f}+ͭڼ,Fw^LvRӐRF4R1T44݆pl"Jlx|~ *t`缴4.OC ݦSVY#3>Wn䘉xOֵ~HRAvd(Ig9Yh RA ܋W^͖JF4V*Emm o͞ ڵ\?Ó2˰}t{ܡ{wܮRvGa" )Mo(хfh]GuCH%E䯥dENmIR| |4C9j&w0j _YHZJ}Ai`l|-|~;U[=AOˣ7Lg¡0t/o랋~1Pqk )!4Eʶ E7W^yYi{Ss;=/ۍfuLJcDD TVP[RLM7m$~-ӣ!aBqP/DGJY`ݧܣkG{oG0"Q,\ɳo͡?Q cP PXwe6f1JFT}KwmcO _^[?0nL(/^¥TbͦGQqkQd̍"Z*JKtB͖tfvGÓ⳻n鰹\sLJS`8 @ Wp!8aJ =ԌK)?hfMgw9b0z,{ *I=L&s5QNT5U)9McO 2'k,㉙/ BOf 퀛sMP? ֹ툢fd7 5e uF\Q_8( ϊmF[<R9}k7KC ]@jǛ+N\KCIN}ڒ|<+AnYo,IjgGHxXS!wCBRmG]GgƢjb+a)8b%3Ĥkdwr_w[8>b sV)O֏b1a-$^cQ")voXh)1A :ՁvA:. V@Xhtbu]A :Ձv0IENDB`golang-github-go-playground-validator-v10-10.30.1/non-standard/000077500000000000000000000000001512410077000241445ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/non-standard/validators/000077500000000000000000000000001512410077000263145ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/non-standard/validators/notblank.go000066400000000000000000000013111512410077000304470ustar00rootroot00000000000000package 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() } } golang-github-go-playground-validator-v10-10.30.1/non-standard/validators/notblank_test.go000066400000000000000000000023401512410077000315110ustar00rootroot00000000000000package 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) } golang-github-go-playground-validator-v10-10.30.1/options.go000066400000000000000000000017631512410077000236050ustar00rootroot00000000000000package validator // Option represents a configurations option to be applied to validator during initialization. type Option func(*Validate) // WithRequiredStructEnabled enables required tag on non-pointer structs to be applied instead of ignored. // // This was made opt-in behaviour in order to maintain backward compatibility with the behaviour previous // to being able to apply struct level validations on struct fields directly. // // It is recommended you enabled this as it will be the default behaviour in v11+ func WithRequiredStructEnabled() Option { return func(v *Validate) { v.requiredStructEnabled = true } } // WithPrivateFieldValidation activates validation for unexported fields via the use of the `unsafe` package. // // By opting into this feature you are acknowledging that you are aware of the risks and accept any current or future // consequences of using this feature. func WithPrivateFieldValidation() Option { return func(v *Validate) { v.privateFieldValidation = true } } golang-github-go-playground-validator-v10-10.30.1/postcode_regexes.go000066400000000000000000000103561512410077000254520ustar00rootroot00000000000000package validator import ( "regexp" "sync" ) 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 ( postcodeRegexInit sync.Once postCodeRegexDict = map[string]*regexp.Regexp{} ) func initPostcodes() { for countryCode, pattern := range postCodePatternDict { postCodeRegexDict[countryCode] = regexp.MustCompile(pattern) } } golang-github-go-playground-validator-v10-10.30.1/regexes.go000066400000000000000000000337451512410077000235610ustar00rootroot00000000000000package validator import ( "regexp" "sync" ) const ( alphaRegexString = "^[a-zA-Z]+$" alphaSpaceRegexString = "^[a-zA-Z ]+$" alphaNumericRegexString = "^[a-zA-Z0-9]+$" alphaNumericSpaceRegexString = "^[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]\\d{7,14}$" base32RegexString = "^(?:[A-Z2-7]{8})*(?:[A-Z2-7]{2}={6}|[A-Z2-7]{4}={4}|[A-Z2-7]{5}={3}|[A-Z2-7]{7}=|[A-Z2-7]{8})$" 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})$" iSSNRegexString = "^(?:[0-9]{4}-[0-9]{3}[0-9X])$" 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 = "^(?i)[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})|(>)|(<)|(")|(&)+[;]?` hTMLRegexString = `<[/]?([a-zA-Z]+).*?>` jWTRegexString = "^[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]*$" splitParamsRegexString = `'[^']*'|\S+` bic2014RegexString = `^[A-Za-z]{6}[A-Za-z0-9]{2}([A-Za-z0-9]{3})?$` bic2022RegexString = `^[A-Z0-9]{4}[A-Z]{2}[A-Z0-9]{2}(?:[A-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])?$" 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 mongodbIdRegexString = "^[a-f\\d]{24}$" mongodbConnStringRegexString = "^mongodb(\\+srv)?:\\/\\/(([a-zA-Z\\d]+):([a-zA-Z\\d$:\\/?#\\[\\]@]+)@)?(([a-z\\d.-]+)(:[\\d]+)?)((,(([a-z\\d.-]+)(:(\\d+))?))*)?(\\/[a-zA-Z-_]{1,64})?(\\?(([a-zA-Z]+)=([a-zA-Z\\d]+))(&(([a-zA-Z\\d]+)=([a-zA-Z\\d]+))?)*)?$" cronRegexString = `(@(annually|yearly|monthly|weekly|daily|hourly|reboot))|(@every (\d+(ns|us|µs|ms|s|m|h))+)|((((\d+,)+\d+|((\*|\d+)(\/|-)\d+)|\d+|\*) ?){5,7})` spicedbIDRegexString = `^(([a-zA-Z0-9/_|\-=+]{1,})|\*)$` spicedbPermissionRegexString = "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$" spicedbTypeRegexString = "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)?[a-z][a-z0-9_]{1,62}[a-z0-9]$" einRegexString = "^(\\d{2}-\\d{7})$" ) func lazyRegexCompile(str string) func() *regexp.Regexp { var regex *regexp.Regexp var once sync.Once return func() *regexp.Regexp { once.Do(func() { regex = regexp.MustCompile(str) }) return regex } } var ( alphaRegex = lazyRegexCompile(alphaRegexString) alphaSpaceRegex = lazyRegexCompile(alphaSpaceRegexString) alphanNumericSpaceRegex = lazyRegexCompile(alphaNumericSpaceRegexString) alphaNumericRegex = lazyRegexCompile(alphaNumericRegexString) alphaUnicodeRegex = lazyRegexCompile(alphaUnicodeRegexString) alphaUnicodeNumericRegex = lazyRegexCompile(alphaUnicodeNumericRegexString) numericRegex = lazyRegexCompile(numericRegexString) numberRegex = lazyRegexCompile(numberRegexString) hexadecimalRegex = lazyRegexCompile(hexadecimalRegexString) hexColorRegex = lazyRegexCompile(hexColorRegexString) rgbRegex = lazyRegexCompile(rgbRegexString) rgbaRegex = lazyRegexCompile(rgbaRegexString) hslRegex = lazyRegexCompile(hslRegexString) hslaRegex = lazyRegexCompile(hslaRegexString) e164Regex = lazyRegexCompile(e164RegexString) emailRegex = lazyRegexCompile(emailRegexString) base32Regex = lazyRegexCompile(base32RegexString) base64Regex = lazyRegexCompile(base64RegexString) base64URLRegex = lazyRegexCompile(base64URLRegexString) base64RawURLRegex = lazyRegexCompile(base64RawURLRegexString) iSBN10Regex = lazyRegexCompile(iSBN10RegexString) iSBN13Regex = lazyRegexCompile(iSBN13RegexString) iSSNRegex = lazyRegexCompile(iSSNRegexString) uUID3Regex = lazyRegexCompile(uUID3RegexString) uUID4Regex = lazyRegexCompile(uUID4RegexString) uUID5Regex = lazyRegexCompile(uUID5RegexString) uUIDRegex = lazyRegexCompile(uUIDRegexString) uUID3RFC4122Regex = lazyRegexCompile(uUID3RFC4122RegexString) uUID4RFC4122Regex = lazyRegexCompile(uUID4RFC4122RegexString) uUID5RFC4122Regex = lazyRegexCompile(uUID5RFC4122RegexString) uUIDRFC4122Regex = lazyRegexCompile(uUIDRFC4122RegexString) uLIDRegex = lazyRegexCompile(uLIDRegexString) md4Regex = lazyRegexCompile(md4RegexString) md5Regex = lazyRegexCompile(md5RegexString) sha256Regex = lazyRegexCompile(sha256RegexString) sha384Regex = lazyRegexCompile(sha384RegexString) sha512Regex = lazyRegexCompile(sha512RegexString) ripemd128Regex = lazyRegexCompile(ripemd128RegexString) ripemd160Regex = lazyRegexCompile(ripemd160RegexString) tiger128Regex = lazyRegexCompile(tiger128RegexString) tiger160Regex = lazyRegexCompile(tiger160RegexString) tiger192Regex = lazyRegexCompile(tiger192RegexString) aSCIIRegex = lazyRegexCompile(aSCIIRegexString) printableASCIIRegex = lazyRegexCompile(printableASCIIRegexString) multibyteRegex = lazyRegexCompile(multibyteRegexString) dataURIRegex = lazyRegexCompile(dataURIRegexString) latitudeRegex = lazyRegexCompile(latitudeRegexString) longitudeRegex = lazyRegexCompile(longitudeRegexString) sSNRegex = lazyRegexCompile(sSNRegexString) hostnameRegexRFC952 = lazyRegexCompile(hostnameRegexStringRFC952) hostnameRegexRFC1123 = lazyRegexCompile(hostnameRegexStringRFC1123) fqdnRegexRFC1123 = lazyRegexCompile(fqdnRegexStringRFC1123) btcAddressRegex = lazyRegexCompile(btcAddressRegexString) btcUpperAddressRegexBech32 = lazyRegexCompile(btcAddressUpperRegexStringBech32) btcLowerAddressRegexBech32 = lazyRegexCompile(btcAddressLowerRegexStringBech32) ethAddressRegex = lazyRegexCompile(ethAddressRegexString) uRLEncodedRegex = lazyRegexCompile(uRLEncodedRegexString) hTMLEncodedRegex = lazyRegexCompile(hTMLEncodedRegexString) hTMLRegex = lazyRegexCompile(hTMLRegexString) jWTRegex = lazyRegexCompile(jWTRegexString) splitParamsRegex = lazyRegexCompile(splitParamsRegexString) bic2014Regex = lazyRegexCompile(bic2014RegexString) bic2022Regex = lazyRegexCompile(bic2022RegexString) semverRegex = lazyRegexCompile(semverRegexString) dnsRegexRFC1035Label = lazyRegexCompile(dnsRegexStringRFC1035Label) cveRegex = lazyRegexCompile(cveRegexString) mongodbIdRegex = lazyRegexCompile(mongodbIdRegexString) mongodbConnectionRegex = lazyRegexCompile(mongodbConnStringRegexString) cronRegex = lazyRegexCompile(cronRegexString) spicedbIDRegex = lazyRegexCompile(spicedbIDRegexString) spicedbPermissionRegex = lazyRegexCompile(spicedbPermissionRegexString) spicedbTypeRegex = lazyRegexCompile(spicedbTypeRegexString) einRegex = lazyRegexCompile(einRegexString) ) golang-github-go-playground-validator-v10-10.30.1/struct_level.go000066400000000000000000000125321512410077000246210ustar00rootroot00000000000000package 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 structFieldName 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 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 accurate 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 accurate 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: getValue(fv), 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) } } golang-github-go-playground-validator-v10-10.30.1/testdata/000077500000000000000000000000001512410077000233655ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/testdata/a.go000066400000000000000000000000211512410077000241250ustar00rootroot00000000000000package testdata golang-github-go-playground-validator-v10-10.30.1/testdata/music.mp3000066400000000000000000000121071512410077000251270ustar00rootroot00000000000000ID3 TCON CinematicTALBYouTube Audio LibraryTIT2Impact ModeratoTPE1Kevin MacLeodTSSELavf58.20.100InfoffffffffffffffffffffffffLAME3.99rB='?clMpq m_& <ħEDz8f˰L#Y$HxY{.a$N(98d.jH(3yjS^w yNT@nm8Z #zۜr#^zzxۣZ} RW5.VV.:* ZxG|$3m/uaʭpacaƘmTl.;z +ٖ6y#Ъr^.N3\coj9)r%ĸqsKH.sSR9{)i|T}:Kk5~Vqe,W[端cOY㏌,8f)s n4пs݇wleXs|lۏ1{=749*W zܪXi+[vOUKPʵ3_VloŐ#Nd[ܭ=BgwV!zmes5&E8-ޝ.^Ǣ:N;dz 1rigq 9Ib̌2|‡Uh&k%48DEX4):S4m/1hlqPq.qE{8g ]oQr Fj(vz Db;aL8wj$nԢ |[*j{Gp1GXBWu%vҖ f4;q9HḞ W@ӏ,dBh( ]vUX6]倆KL7"0Mina#=lCfdzK"% eTܚ.SK4%XI,+&@'rܮ%*4y aW9tƖrm]nmpBx=AS%GT. J.' in0-V5 'ŷof8R7ߩC~z^҂>i?a)h+X=.ΏpC%,M̴ [L3%s R- 6,.#N@-:m4u}-8\Ặ+'1ts]/`Mhf.tU#FBd&&aH]" dD]7P+ܘgJYΣLjm'?#32 D$1UH:F\";v4BuiGꮿGEvVa=cfZ<8.UUw- joQkZ8={sgl9s遽]r:͵_آEm M<1b!6gs9G.3QI"X4G45h @`A@Pb06``fp\Ls1KeIA*F%t:p)(wXTw_&2gcZcLPXq8F A%ZUz }.'1e" BGt! YeENU1S!nٔp\ĀP<A=qOJ)bӪzӗC94Xtm,0lhypfb^˭Z]DiI$ײ'n3!,#9N"tWX߈@p}gSQKKR̢=jtrMD3!@7h(*Uyex׃LG1=,B Bv`RC.zj7ٴA+188cqF0@H`Xa(GVC D9L1kHY ) 5K h!=UHŕ(ثw` ! c+(pu-EKp[Cv_l۝lv%`@1e'q>Ա8t/ E.ހ Vav 0 aa@DFI_Hzq{jwq)m'{T]g!zT MZP΋%SSގ| _YDkљjPR92(~T͂ S W_8K4TR/1]ljY's&*: aֽ1/9&RjG˩?Nci*ZZŀirmFY?  miiEc$p@C H?JZ* HS^,]afYy[:M}БkWm+Ek2R/$B%jtbz))FOLGjSس*@ZKt5=j)]Yd9z^ĭ_ɩT oWk +zfS *bO=$MR7IZJYtb^Amnb,RڑRJ9"ԕex8\֫us.J[5+E%t9V;"Yrg0Ov݋vw Y)){X܎7d*&pre  d8ZL^&LJmB*eT9y @2]$D:Lq}ge>Q(nYGMU1 9ӳY=V-f)U(Pӕ0UdRwpWK7WI]{Xz1f](X\OV?E"1z9t-ܻWuUNYoY֤|D¥dHB^*[ڐ/^~s.dtBP|pʽ[I#Y"bmI_X_\ДYxC`>bE>5X:^Az#<8ћ^ l&kI ;Oc Je92Z, j~xٖ%*z צTy >q۽AVٱ$oHR3C´Hn?t{o2LV sž3 ;43>;uaQf-?]z{Od* wx*CΕ7(6*g jL+CPT8tLIeQ@e(ҪcVSi)`$Y(Q7'_golang-github-go-playground-validator-v10-10.30.1/translations.go000066400000000000000000000006511512410077000246260ustar00rootroot00000000000000package 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 golang-github-go-playground-validator-v10-10.30.1/translations/000077500000000000000000000000001512410077000242755ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/translations/ar/000077500000000000000000000000001512410077000246775ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/translations/ar/ar.go000066400000000000000000001134571512410077000256430ustar00rootroot00000000000000package ar import ( "fmt" "log" "reflect" "strconv" "strings" "time" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" ) // RegisterDefaultTranslations registers a set of default translations // for all built in tag's in validator; you may add your own as desired. func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (err error) { translations := []struct { tag string translation string override bool customRegisFunc validator.RegisterTranslationsFunc customTransFunc validator.TranslationFunc }{ { tag: "required", translation: "حقل {0} مطلوب", override: false, }, { tag: "required_if", translation: "حقل {0} مطلوب", override: false, }, { tag: "required_unless", translation: "حقل {0} مطلوب", override: false, }, { tag: "required_with", translation: "حقل {0} مطلوب", override: false, }, { tag: "required_with_all", translation: "حقل {0} مطلوب", override: false, }, { tag: "required_without", translation: "حقل {0} مطلوب", override: false, }, { tag: "required_without_all", translation: "حقل {0} مطلوب", override: false, }, { tag: "excluded_if", translation: "حقل {0} مستبعد", override: false, }, { tag: "excluded_unless", translation: "حقل {0} مستبعد", override: false, }, { tag: "excluded_with", translation: "حقل {0} مستبعد", override: false, }, { tag: "excluded_with_all", translation: "حقل {0} مستبعد", override: false, }, { tag: "excluded_without", translation: "حقل {0} مستبعد", override: false, }, { tag: "excluded_without_all", translation: "حقل {0} مستبعد", override: false, }, { tag: "isdefault", translation: "حقل {0} يجب أن يكون قيمة إفتراضية", override: false, }, { tag: "len", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("len-string", "يجب أن يكون طول {0} مساويا ل {1}", false); err != nil { return } if err = ut.Add("len-string-character-one", "{0} حرف", false); err != nil { return } if err = ut.Add("len-string-character-other", "{0} أحرف", false); err != nil { return } if err = ut.Add("len-number", "يجب أن يكون {0} مساويا ل {1}", false); err != nil { return } if err = ut.Add("len-items", "يجب أن يحتوي {0} على {1}", false); err != nil { return } if err = ut.Add("len-items-item-one", "{0} عنصر", false); err != nil { return } if err = ut.Add("len-items-item-other", "{0} عناصر", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string if f64 == 1 { c, err = ut.T("len-string-character-one", ut.FmtNumber(f64, digits)) } else { c, err = ut.T("len-string-character-other", ut.FmtNumber(f64, digits)) } if err != nil { goto END } t, err = ut.T("len-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string if f64 == 1 { c, err = ut.T("len-items-item-one", ut.FmtNumber(f64, digits)) } else { c, err = ut.T("len-items-item-other", ut.FmtNumber(f64, digits)) } if err != nil { goto END } t, err = ut.T("len-items", fe.Field(), c) default: t, err = ut.T("len-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "min", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("min-string", "{0} يجب أن يكون {1} على الأقل", false); err != nil { return } if err = ut.Add("min-string-character-one", "{0} حرف", false); err != nil { return } if err = ut.Add("min-string-character-other", "{0} أحرف", false); err != nil { return } if err = ut.Add("min-number", "{0} يجب أن يكون {1} أو أكثر", false); err != nil { return } if err = ut.Add("min-items", "يجب أن يحتوي {0} على {1} على الأقل", false); err != nil { return } if err = ut.Add("min-items-item-one", "{0} عنصر", false); err != nil { return } if err = ut.Add("min-items-item-other", "{0} عناصر", false); err != nil { return } if err = ut.Add("min-duration", "يجب أن تكون مدة {0} {1} أو أكبر", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if fe.Type() != reflect.TypeOf(time.Duration(0)) { return nil } t, err = ut.T("min-duration", fe.Field(), fe.Param()) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } if err = fn(); err != nil || t != "" { goto END } if fe.Type() == reflect.TypeOf(time.Duration(0)) { t, err = ut.T("min-duration", fe.Field(), fe.Param()) goto END } if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } switch kind { case reflect.String: var c string if f64 == 1 { c, err = ut.T("min-string-character-one", ut.FmtNumber(f64, digits)) } else { c, err = ut.T("min-string-character-other", ut.FmtNumber(f64, digits)) } if err != nil { goto END } t, err = ut.T("min-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string if f64 == 1 { c, err = ut.T("min-items-item-one", ut.FmtNumber(f64, digits)) } else { c, err = ut.T("min-items-item-other", ut.FmtNumber(f64, digits)) } if err != nil { goto END } t, err = ut.T("min-items", fe.Field(), c) default: t, err = ut.T("min-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { log.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, override: false, }, { tag: "max", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("max-string", "يجب أن يكون طول {0} بحد أقصى {1}", false); err != nil { return } if err = ut.Add("max-string-character-one", "{0} حرف", false); err != nil { return } if err = ut.Add("max-string-character-other", "{0} أحرف", false); err != nil { return } if err = ut.Add("max-number", "{0} يجب أن يكون {1} أو اقل", false); err != nil { return } if err = ut.Add("max-items", "يجب أن يحتوي {0} على {1} كحد أقصى", false); err != nil { return } if err = ut.Add("max-items-item-one", "{0} عنصر", false); err != nil { return } if err = ut.Add("max-items-item-other", "{0} عناصر", false); err != nil { return } if err = ut.Add("max-duration", "يجب أن تكون مدة {0} {1} أو أقل", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if fe.Type() != reflect.TypeOf(time.Duration(0)) { return nil } t, err = ut.T("max-duration", fe.Field(), fe.Param()) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } if err = fn(); err != nil || t != "" { goto END } if fe.Type() == reflect.TypeOf(time.Duration(0)) { t, err = ut.T("max-duration", fe.Field(), fe.Param()) goto END } if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } switch kind { case reflect.String: var c string if f64 == 1 { c, err = ut.T("max-string-character-one", ut.FmtNumber(f64, digits)) } else { c, err = ut.T("max-string-character-other", ut.FmtNumber(f64, digits)) } if err != nil { goto END } t, err = ut.T("max-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string if f64 == 1 { c, err = ut.T("max-items-item-one", ut.FmtNumber(f64, digits)) } else { c, err = ut.T("max-items-item-other", ut.FmtNumber(f64, digits)) } if err != nil { goto END } t, err = ut.T("max-items", fe.Field(), c) default: t, err = ut.T("max-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { log.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, override: false, }, { tag: "eq", translation: "{0} لا يساوي {1}", override: false, }, { tag: "ne", translation: "{0} يجب ألا يساوي {1}", override: false, }, { tag: "lt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lt-string", "يجب أن يكون طول {0} أقل من {1}", false); err != nil { return } if err = ut.Add("lt-string-character-one", "{0} حرف", false); err != nil { return } if err = ut.Add("lt-string-character-other", "{0} أحرف", false); err != nil { return } if err = ut.Add("lt-number", "يجب أن يكون {0} أقل من {1}", false); err != nil { return } if err = ut.Add("lt-items", "يجب أن يحتوي {0} على أقل من {1}", false); err != nil { return } if err = ut.Add("lt-items-item-one", "{0} عنصر", false); err != nil { return } if err = ut.Add("lt-items-item-other", "{0} عناصر", false); err != nil { return } if err = ut.Add("lt-datetime", "يجب أن يكون {0} أقل من التاريخ والوقت الحاليين", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind var f64 float64 kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } // Special handling for time.Time if fe.Type() == reflect.TypeOf(time.Time{}) { t, err = ut.T("lt-datetime", fe.Field()) goto END } if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } switch kind { case reflect.String: var c string if f64 == 1 { c, err = ut.T("lt-string-character-one", ut.FmtNumber(f64, digits)) } else { c, err = ut.T("lt-string-character-other", ut.FmtNumber(f64, digits)) } if err != nil { goto END } t, err = ut.T("lt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string if f64 == 1 { c, err = ut.T("lt-items-item-one", ut.FmtNumber(f64, digits)) } else { c, err = ut.T("lt-items-item-other", ut.FmtNumber(f64, digits)) } if err != nil { goto END } t, err = ut.T("lt-items", fe.Field(), c) case reflect.Struct: t, err = ut.T("lt-number", fe.Field(), ut.FmtNumber(f64, digits)) default: t, err = ut.T("lt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { log.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, override: false, }, { tag: "lte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lte-string", "يجب أن يكون طول {0} كحد أقصى {1}", false); err != nil { return } if err = ut.Add("lte-string-character-one", "{0} حرف", false); err != nil { return } if err = ut.Add("lte-string-character-other", "{0} أحرف", false); err != nil { return } if err = ut.Add("lte-number", "{0} يجب أن يكون {1} أو اقل", false); err != nil { return } if err = ut.Add("lte-items", "يجب أن يحتوي {0} على {1} كحد أقصى", false); err != nil { return } if err = ut.Add("lte-items-item-one", "{0} عنصر", false); err != nil { return } if err = ut.Add("lte-items-item-other", "{0} عناصر", false); err != nil { return } if err = ut.Add("lte-datetime", "يجب أن يكون {0} أقل من أو يساوي التاريخ والوقت الحاليين", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind var f64 float64 kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } // Special handling for time.Time if fe.Type() == reflect.TypeOf(time.Time{}) { t, err = ut.T("lte-datetime", fe.Field()) goto END } if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } switch kind { case reflect.String: var c string if f64 == 1 { c, err = ut.T("lte-string-character-one", ut.FmtNumber(f64, digits)) } else { c, err = ut.T("lte-string-character-other", ut.FmtNumber(f64, digits)) } if err != nil { goto END } t, err = ut.T("lte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string if f64 == 1 { c, err = ut.T("lte-items-item-one", ut.FmtNumber(f64, digits)) } else { c, err = ut.T("lte-items-item-other", ut.FmtNumber(f64, digits)) } if err != nil { goto END } t, err = ut.T("lte-items", fe.Field(), c) case reflect.Struct: t, err = ut.T("lte-number", fe.Field(), ut.FmtNumber(f64, digits)) default: t, err = ut.T("lte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { log.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, override: false, }, { tag: "eqfield", translation: "يجب أن يكون {0} مساويا ل {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "eqcsfield", translation: "يجب أن يكون {0} مساويا ل {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "necsfield", translation: "{0} لا يمكن أن يساوي {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtcsfield", translation: "يجب أن يكون {0} أكبر من {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtecsfield", translation: "يجب أن يكون {0} أكبر من أو يساوي {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltcsfield", translation: "يجب أن يكون {0} أصغر من {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltecsfield", translation: "يجب أن يكون {0} أصغر من أو يساوي {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "nefield", translation: "{0} لا يمكن أن يساوي {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gt-string", "يجب أن يكون طول {0} أكبر من {1}", false); err != nil { return } if err = ut.Add("gt-string-character-one", "{0} حرف", false); err != nil { return } if err = ut.Add("gt-string-character-other", "{0} أحرف", false); err != nil { return } if err = ut.Add("gt-number", "يجب أن يكون {0} أكبر من {1}", false); err != nil { return } if err = ut.Add("gt-items", "يجب أن يحتوي {0} على أكثر من {1}", false); err != nil { return } if err = ut.Add("gt-items-item-one", "{0} عنصر", false); err != nil { return } if err = ut.Add("gt-items-item-other", "{0} عناصر", false); err != nil { return } if err = ut.Add("gt-datetime", "يجب أن يكون {0} أكبر من التاريخ والوقت الحاليين", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind var f64 float64 kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } // Special handling for time.Time if fe.Type() == reflect.TypeOf(time.Time{}) { t, err = ut.T("gt-datetime", fe.Field()) goto END } if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } switch kind { case reflect.String: var c string if f64 == 1 { c, err = ut.T("gt-string-character-one", ut.FmtNumber(f64, digits)) } else { c, err = ut.T("gt-string-character-other", ut.FmtNumber(f64, digits)) } if err != nil { goto END } t, err = ut.T("gt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string if f64 == 1 { c, err = ut.T("gt-items-item-one", ut.FmtNumber(f64, digits)) } else { c, err = ut.T("gt-items-item-other", ut.FmtNumber(f64, digits)) } if err != nil { goto END } t, err = ut.T("gt-items", fe.Field(), c) case reflect.Struct: t, err = ut.T("gt-number", fe.Field(), ut.FmtNumber(f64, digits)) default: t, err = ut.T("gt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { log.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, override: false, }, { tag: "alpha", translation: "يمكن أن يحتوي {0} على أحرف أبجدية فقط", override: false, }, { tag: "alphanum", translation: "يمكن أن يحتوي {0} على أحرف أبجدية رقمية فقط", override: false, }, { tag: "numeric", translation: "يجب أن يكون {0} قيمة رقمية صالحة", override: false, }, { tag: "number", translation: "يجب أن يكون {0} رقم صالح", override: false, }, { tag: "hexadecimal", translation: "يجب أن يكون {0} عددًا سداسيًا عشريًا صالحاً", override: false, }, { tag: "hexcolor", translation: "يجب أن يكون {0} لون HEX صالح", override: false, }, { tag: "rgb", translation: "يجب أن يكون {0} لون RGB صالح", override: false, }, { tag: "rgba", translation: "يجب أن يكون {0} لون RGBA صالح", override: false, }, { tag: "hsl", translation: "يجب أن يكون {0} لون HSL صالح", override: false, }, { tag: "hsla", translation: "يجب أن يكون {0} لون HSLA صالح", override: false, }, { tag: "e164", translation: "يجب أن يكون {0} رقم هاتف صالح بتنسيق E.164", override: false, }, { tag: "email", translation: "يجب أن يكون {0} عنوان بريد إلكتروني صالح", override: false, }, { tag: "url", translation: "يجب أن يكون {0} رابط إنترنت صالح", override: false, }, { tag: "uri", translation: "يجب أن يكون {0} URI صالح", override: false, }, { tag: "base64", translation: "يجب أن يكون {0} سلسلة Base64 صالحة", override: false, }, { tag: "contains", translation: "يجب أن يحتوي {0} على النص '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "containsany", translation: "يجب أن يحتوي {0} على حرف واحد على الأقل من الأحرف التالية '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludes", translation: "لا يمكن أن يحتوي {0} على النص '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesall", translation: "لا يمكن أن يحتوي {0} على أي من الأحرف التالية '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesrune", translation: "لا يمكن أن يحتوي {0} على التالي '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "isbn", translation: "يجب أن يكون {0} رقم ISBN صالح", override: false, }, { tag: "isbn10", translation: "يجب أن يكون {0} رقم ISBN-10 صالح", override: false, }, { tag: "isbn13", translation: "يجب أن يكون {0} رقم ISBN-13 صالح", override: false, }, { tag: "issn", translation: "يجب أن يكون {0} رقم ISSN صالح", override: false, }, { tag: "uuid", translation: "يجب أن يكون {0} UUID صالح", override: false, }, { tag: "uuid3", translation: "يجب أن يكون {0} UUID صالح من النسخة 3", override: false, }, { tag: "uuid4", translation: "يجب أن يكون {0} UUID صالح من النسخة 4", override: false, }, { tag: "uuid5", translation: "يجب أن يكون {0} UUID صالح من النسخة 5", override: false, }, { tag: "ulid", translation: "يجب أن يكون {0} ULID صالح من نسخة", override: false, }, { tag: "ascii", translation: "يجب أن يحتوي {0} على أحرف ascii فقط", override: false, }, { tag: "printascii", translation: "يجب أن يحتوي {0} على أحرف ascii قابلة للطباعة فقط", override: false, }, { tag: "multibyte", translation: "يجب أن يحتوي {0} على أحرف متعددة البايت", override: false, }, { tag: "datauri", translation: "يجب أن يحتوي {0} على URI صالح للبيانات", override: false, }, { tag: "latitude", translation: "يجب أن يحتوي {0} على إحداثيات خط عرض صالحة", override: false, }, { tag: "longitude", translation: "يجب أن يحتوي {0} على إحداثيات خط طول صالحة", override: false, }, { tag: "ssn", translation: "يجب أن يكون {0} رقم SSN صالح", override: false, }, { tag: "ipv4", translation: "يجب أن يكون {0} عنوان IPv4 صالح", override: false, }, { tag: "ipv6", translation: "يجب أن يكون {0} عنوان IPv6 صالح", override: false, }, { tag: "ip", translation: "يجب أن يكون {0} عنوان IP صالح", override: false, }, { tag: "cidr", translation: "يجب أن يحتوي {0} على علامة CIDR صالحة", override: false, }, { tag: "cidrv4", translation: "يجب أن يحتوي {0} على علامة CIDR صالحة لعنوان IPv4", override: false, }, { tag: "cidrv6", translation: "يجب أن يحتوي {0} على علامة CIDR صالحة لعنوان IPv6", override: false, }, { tag: "tcp_addr", translation: "يجب أن يكون {0} عنوان TCP صالح", override: false, }, { tag: "tcp4_addr", translation: "يجب أن يكون {0} عنوان IPv4 TCP صالح", override: false, }, { tag: "tcp6_addr", translation: "يجب أن يكون {0} عنوان IPv6 TCP صالح", override: false, }, { tag: "udp_addr", translation: "يجب أن يكون {0} عنوان UDP صالح", override: false, }, { tag: "udp4_addr", translation: "يجب أن يكون {0} عنوان IPv4 UDP صالح", override: false, }, { tag: "udp6_addr", translation: "يجب أن يكون {0} عنوان IPv6 UDP صالح", override: false, }, { tag: "ip_addr", translation: "يجب أن يكون {0} عنوان IP قابل للحل", override: false, }, { tag: "ip4_addr", translation: "يجب أن يكون {0} عنوان IP قابل للحل", override: false, }, { tag: "ip6_addr", translation: "يجب أن يكون {0} عنوان IPv6 قابل للحل", override: false, }, { tag: "unix_addr", translation: "يجب أن يكون {0} عنوان UNIX قابل للحل", override: false, }, { tag: "mac", translation: "يجب أن يحتوي {0} على عنوان MAC صالح", override: false, }, { tag: "unique", translation: "يجب أن يحتوي {0} على قيم فريدة", override: false, }, { tag: "iscolor", translation: "يجب أن يكون {0} لون صالح", override: false, }, { tag: "oneof", translation: "يجب أن يكون {0} واحدا من [{1}]", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { s, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return s }, }, { tag: "json", translation: "يجب أن يكون {0} نص json صالح", override: false, }, { tag: "jwt", translation: "يجب أن يكون {0} نص jwt صالح", override: false, }, { tag: "lowercase", translation: "يجب أن يكون {0} نص حروف صغيرة", override: false, }, { tag: "uppercase", translation: "يجب أن يكون {0} نص حروف كبيرة", override: false, }, { tag: "datetime", translation: "لا يتطابق {0} مع تنسيق {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "postcode_iso3166_alpha2", translation: "لا يتطابق {0} مع تنسيق الرمز البريدي للبلد {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "postcode_iso3166_alpha2_field", translation: "لا يتطابق {0} مع تنسيق الرمز البريدي للبلد في حقل {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "boolean", translation: "يجب أن يكون {0} قيمة منطقية صالحة", override: false, }, { tag: "image", translation: "يجب أن تكون {0} صورة صالحة", override: false, }, { tag: "cve", translation: "يجب أن يكون {0} معرف CVE صالح", override: false, }, { tag: "gte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gte-string", "يجب أن يكون طول {0} على الأقل {1}", false); err != nil { return } if err = ut.Add("gte-string-character-one", "{0} حرف", false); err != nil { return } if err = ut.Add("gte-string-character-other", "{0} أحرف", false); err != nil { return } if err = ut.Add("gte-number", "{0} يجب أن يكون {1} أو أكبر", false); err != nil { return } if err = ut.Add("gte-items", "يجب أن يحتوي {0} على {1} على الأقل", false); err != nil { return } if err = ut.Add("gte-items-item-one", "{0} عنصر", false); err != nil { return } if err = ut.Add("gte-items-item-other", "{0} عناصر", false); err != nil { return } if err = ut.Add("gte-datetime", "يجب أن يكون {0} أكبر من أو يساوي التاريخ والوقت الحاليين", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind var f64 float64 kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } // Special handling for time.Time if fe.Type() == reflect.TypeOf(time.Time{}) { t, err = ut.T("gte-datetime", fe.Field()) goto END } if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } switch kind { case reflect.String: var c string if f64 == 1 { c, err = ut.T("gte-string-character-one", ut.FmtNumber(f64, digits)) } else { c, err = ut.T("gte-string-character-other", ut.FmtNumber(f64, digits)) } if err != nil { goto END } t, err = ut.T("gte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string if f64 == 1 { c, err = ut.T("gte-items-item-one", ut.FmtNumber(f64, digits)) } else { c, err = ut.T("gte-items-item-other", ut.FmtNumber(f64, digits)) } if err != nil { goto END } t, err = ut.T("gte-items", fe.Field(), c) case reflect.Struct: t, err = ut.T("gte-number", fe.Field(), ut.FmtNumber(f64, digits)) default: t, err = ut.T("gte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { log.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, override: false, }, { tag: "gtfield", translation: "يجب أن يكون {0} أكبر من {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtefield", translation: "يجب أن يكون {0} أكبر من أو يساوي {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltfield", translation: "يجب أن يكون {0} أصغر من {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltefield", translation: "يجب أن يكون {0} أصغر من أو يساوي {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "fqdn", translation: "يجب أن يكون {0} اسم نطاق مؤهل بالكامل صالح", override: false, }, { tag: "cron", translation: "يجب أن يكون {0} تعبير cron صالح", override: false, }, { tag: "md5", translation: "يجب أن يكون {0} تجزئة MD5 صالحة", override: false, }, { tag: "sha256", translation: "يجب أن يكون {0} تجزئة SHA256 صالحة", override: false, }, { tag: "semver", translation: "يجب أن يكون {0} إصدار دلالي صالح", override: false, }, } for _, t := range translations { if t.customTransFunc != nil && t.customRegisFunc != nil { if err := v.RegisterTranslation(t.tag, trans, t.customRegisFunc, t.customTransFunc); err != nil { return err } continue } if err := v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), translateFunc); err != nil { return err } } return } func registrationFunc(tag string, translation string, override bool) validator.RegisterTranslationsFunc { return func(ut ut.Translator) error { return ut.Add(tag, translation, override) } } func translateFunc(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { return fe.(error).Error() } return t } golang-github-go-playground-validator-v10-10.30.1/translations/ar/ar_test.go000066400000000000000000000617551512410077000267050ustar00rootroot00000000000000package 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"` ISSN string `validate:"issn"` 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"` Image string `validate:"image"` BooleanString string `validate:"boolean"` CveString string `validate:"cve"` FQDN string `validate:"fqdn"` MinDuration time.Duration `validate:"min=1h30m"` MaxDuration time.Duration `validate:"max=2h"` CronString string `validate:"cron"` MD5String string `validate:"md5"` SHA256String string `validate:"sha256"` Semver string `validate:"semver"` } 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.PostCode = "invalid" test.PostCodeCountry = "SG" test.PostCodeByField = "invalid" test.Image = "not-an-image-data" test.BooleanString = "invalid-boolean" test.CveString = "invalid-cve" test.FQDN = "invalid-fqdn" test.MinDuration = 1 * time.Hour test.MaxDuration = 3 * time.Hour test.CronString = "invalid-cron" test.MD5String = "invalid-md5" test.SHA256String = "invalid-sha256" test.Semver = "invalid-semver" 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.ISSN", expected: "يجب أن يكون ISSN رقم ISSN صالح", }, { 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", }, { ns: "Test.Image", expected: "يجب أن تكون Image صورة صالحة", }, { ns: "Test.BooleanString", expected: "يجب أن يكون BooleanString قيمة منطقية صالحة", }, { ns: "Test.CveString", expected: "يجب أن يكون CveString معرف CVE صالح", }, { ns: "Test.FQDN", expected: "يجب أن يكون FQDN اسم نطاق مؤهل بالكامل صالح", }, { ns: "Test.MinDuration", expected: "يجب أن تكون مدة MinDuration 1h30m أو أكبر", }, { ns: "Test.MaxDuration", expected: "يجب أن تكون مدة MaxDuration 2h أو أقل", }, { ns: "Test.CronString", expected: "يجب أن يكون CronString تعبير cron صالح", }, { ns: "Test.MD5String", expected: "يجب أن يكون MD5String تجزئة MD5 صالحة", }, { ns: "Test.SHA256String", expected: "يجب أن يكون SHA256String تجزئة SHA256 صالحة", }, { ns: "Test.Semver", expected: "يجب أن يكون Semver إصدار دلالي صالح", }, } 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)) } } golang-github-go-playground-validator-v10-10.30.1/translations/de/000077500000000000000000000000001512410077000246655ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/translations/de/de.go000066400000000000000000001072231512410077000256110ustar00rootroot00000000000000package de import ( "fmt" "log" "reflect" "strconv" "strings" "time" "github.com/go-playground/locales" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" ) // RegisterDefaultTranslations registers a set of default translations // for all built in tag's in validator; you may add your own as desired. func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (err error) { translations := []struct { tag string translation string override bool customRegisFunc validator.RegisterTranslationsFunc customTransFunc validator.TranslationFunc }{ { tag: "required", translation: "{0} ist ein Pflichtfeld", override: false, }, { tag: "required_if", translation: "{0} ist ein Pflichtfeld", override: false, }, { tag: "required_unless", translation: "{0} ist ein Pflichtfeld", override: false, }, { tag: "required_with", translation: "{0} ist ein Pflichtfeld", override: false, }, { tag: "required_with_all", translation: "{0} ist ein Pflichtfeld", override: false, }, { tag: "required_without", translation: "{0} ist ein Pflichtfeld", override: false, }, { tag: "required_without_all", translation: "{0} ist ein Pflichtfeld", override: false, }, { tag: "excluded_if", translation: "{0} ist ein ausgeschlossenes Feld", override: false, }, { tag: "excluded_unless", translation: "{0} ist ein ausgeschlossenes Feld", override: false, }, { tag: "excluded_with", translation: "{0} ist ein ausgeschlossenes Feld", override: false, }, { tag: "excluded_with_all", translation: "{0} ist ein ausgeschlossenes Feld", override: false, }, { tag: "excluded_without", translation: "{0} ist ein ausgeschlossenes Feld", override: false, }, { tag: "excluded_without_all", translation: "{0} ist ein ausgeschlossenes Feld", override: false, }, { tag: "isdefault", translation: "{0} muss der Standardwert sein", override: false, }, { tag: "len", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("len-string", "{0} darf nur {1} lang sein", false); err != nil { return } if err = ut.AddCardinal("len-string-character", "{0} Zeichen", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("len-string-character", "{0} Zeichen", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("len-number", "{0} muss gleich {1} sein", false); err != nil { return } if err = ut.Add("len-items", "{0} muss {1} enthalten", false); err != nil { return } if err = ut.AddCardinal("len-items-item", "{0} Element", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("len-items-item", "{0} Elemente", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("len-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("len-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-items", fe.Field(), c) default: t, err = ut.T("len-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "min", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("min-string", "{0} muss mindestens {1} lang sein", false); err != nil { return } if err = ut.AddCardinal("min-string-character", "{0} Zeichen", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("min-string-character", "{0} Zeichen", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("min-number", "{0} muss {1} oder größer sein", false); err != nil { return } if err = ut.Add("min-items", "{0} muss mindestens {1} enthalten", false); err != nil { return } if err = ut.AddCardinal("min-items-item", "{0} Element", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("min-items-item", "{0} Elemente", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("min-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("min-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-items", fe.Field(), c) default: t, err = ut.T("min-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "max", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("max-string", "{0} darf maximal {1} lang sein", false); err != nil { return } if err = ut.AddCardinal("max-string-character", "{0} Zeichen", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("max-string-character", "{0} Zeichen", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("max-number", "{0} darf {1} oder weniger sein", false); err != nil { return } if err = ut.Add("max-items", "{0} darf maximal {1} enthalten", false); err != nil { return } if err = ut.AddCardinal("max-items-item", "{0} Element", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("max-items-item", "{0} Elemente", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("max-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("max-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-items", fe.Field(), c) default: t, err = ut.T("max-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eq", translation: "{0} ist nicht gleich {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ne", translation: "{0} darf nicht gleich {1} sein", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "lt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lt-string", "{0} muss kleiner als {1} sein", false); err != nil { return } if err = ut.AddCardinal("lt-string-character", "{0} Zeichen", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lt-string-character", "{0} Zeichen", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-number", "{0} muss kleiner als {1} sein", false); err != nil { return } if err = ut.Add("lt-items", "{0} muss {1} oder weniger enthalten", false); err != nil { return } if err = ut.AddCardinal("lt-items-item", "{0} Element", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lt-items-item", "{0} Elemente", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-datetime", "{0} muss vor dem aktuellen Datum und Uhrzeit liegen", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "lte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lte-string", "{0} darf maximal {1} lang sein", false); err != nil { return } if err = ut.AddCardinal("lte-string-character", "{0} Zeichen", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lte-string-character", "{0} Zeichen", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-number", "{0} darf {1} oder weniger sein", false); err != nil { return } if err = ut.Add("lte-items", "{0} darf maximal {1} enthalten", false); err != nil { return } if err = ut.AddCardinal("lte-items-item", "{0} Element", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lte-items-item", "{0} Elemente", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-datetime", "{0} muss vor dem aktuellen Datum und Uhrzeit liegen oder gleich sein", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gt-string", "{0} muss größer als {1} sein", false); err != nil { return } if err = ut.AddCardinal("gt-string-character", "{0} Zeichen", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gt-string-character", "{0} Zeichen", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-number", "{0} muss größer als {1} sein", false); err != nil { return } if err = ut.Add("gt-items", "{0} muss {1} oder mehr enthalten", false); err != nil { return } if err = ut.AddCardinal("gt-items-item", "{0} Element", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gt-items-item", "{0} Elemente", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-datetime", "{0} muss vor dem aktuellen Datum und Uhrzeit liegen", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gte-string", "{0} muss mindestens {1} lang sein", false); err != nil { return } if err = ut.AddCardinal("gte-string-character", "{0} Zeichen", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gte-string-character", "{0} Zeichen", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-number", "{0} muss {1} oder größer sein", false); err != nil { return } if err = ut.Add("gte-items", "{0} muss mindestens {1} enthalten", false); err != nil { return } if err = ut.AddCardinal("gte-items-item", "{0} Element", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gte-items-item", "{0} Elemente", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-datetime", "{0} muss vor dem aktuellen Datum und Uhrzeit liegen oder gleich sein", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eqfield", translation: "{0} muss gleich {1} sein", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "eqcsfield", translation: "{0} muss gleich {1} sein", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "necsfield", translation: "{0} darf nicht gleich {1} sein", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtcsfield", translation: "{0} muss größer als {1} sein", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtecsfield", translation: "{0} muss größer als oder gleich {1} sein", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltcsfield", translation: "{0} muss kleiner als {1} sein", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltecsfield", translation: "{0} muss kleiner als oder gleich {1} sein", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "nefield", translation: "{0} darf nicht gleich {1} sein", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtfield", translation: "{0} muss größer als {1} sein", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtefield", translation: "{0} muss größer als oder gleich {1} sein", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltfield", translation: "{0} muss kleiner als {1} sein", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltefield", translation: "{0} muss kleiner als oder gleich {1} sein", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "alpha", translation: "{0} darf nur alphabetische Zeichen enthalten", override: false, }, { tag: "alphanum", translation: "{0} darf nur alphanumerische Zeichen enthalten", override: false, }, { tag: "numeric", translation: "{0} muss eine gültige Zahl sein", override: false, }, { tag: "number", translation: "{0} muss eine gültige Zahl sein", override: false, }, { tag: "hexadecimal", translation: "{0} muss eine gültige hexadezimale Zahl sein", override: false, }, { tag: "hexcolor", translation: "{0} muss eine gültige Hexadezimalfarbe sein", override: false, }, { tag: "rgb", translation: "{0} muss eine gültige RGB-Farbe sein", override: false, }, { tag: "rgba", translation: "{0} muss eine gültige RGBA-Farbe sein", override: false, }, { tag: "hsl", translation: "{0} muss eine gültige HSL-Farbe sein", override: false, }, { tag: "hsla", translation: "{0} muss eine gültige HSLA-Farbe sein", override: false, }, { tag: "e164", translation: "{0} muss eine gültige E.164-Telefonnummer sein", override: false, }, { tag: "email", translation: "{0} muss eine gültige E-Mail-Adresse sein", override: false, }, { tag: "url", translation: "{0} muss eine gültige URL sein", override: false, }, { tag: "uri", translation: "{0} muss eine gültige URI sein", override: false, }, { tag: "base64", translation: "{0} muss eine gültige Base64-Zeichenkette sein", override: false, }, { tag: "contains", translation: "{0} muss den Text '{1}' enthalten", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "containsany", translation: "{0} muss mindestens eines der folgenden Zeichen enthalten: '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludes", translation: "{0} darf den Text '{1}' nicht enthalten", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesall", translation: "{0} darf keines der folgenden Zeichen enthalten: '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesrune", translation: "{0} darf die folgenden Runen nicht enthalten: '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "isbn", translation: "{0} muss eine gültige ISBN-Nummer sein", override: false, }, { tag: "isbn10", translation: "{0} muss eine gültige ISBN-10-Nummer sein", override: false, }, { tag: "isbn13", translation: "{0} muss eine gültige ISBN-13-Nummer sein", override: false, }, { tag: "issn", translation: "{0} muss eine gültige ISSN-Nummer sein", override: false, }, { tag: "uuid", translation: "{0} muss eine gültige UUID sein", override: false, }, { tag: "uuid3", translation: "{0} muss eine gültige Version 3 UUID sein", override: false, }, { tag: "uuid4", translation: "{0} muss eine gültige Version 4 UUID sein", override: false, }, { tag: "uuid5", translation: "{0} muss eine gültige Version 5 UUID sein", override: false, }, { tag: "ulid", translation: "{0} muss eine gültige ULID sein", override: false, }, { tag: "ascii", translation: "{0} darf nur ASCII-Zeichen enthalten", override: false, }, { tag: "printascii", translation: "{0} darf nur druckbare ASCII-Zeichen enthalten", override: false, }, { tag: "multibyte", translation: "{0} darf nur Mehrbyte-Zeichen enthalten", override: false, }, { tag: "datauri", translation: "{0} muss eine gültige Data-URI sein", override: false, }, { tag: "latitude", translation: "{0} muss gültige Breitengradkoordinaten enthalten", override: false, }, { tag: "longitude", translation: "{0} muss gültige Längengradkoordinaten enthalten", override: false, }, { tag: "ssn", translation: "{0} muss eine gültige SSN-Nummer sein", override: false, }, { tag: "ipv4", translation: "{0} muss eine gültige IPv4-Adresse sein", override: false, }, { tag: "ipv6", translation: "{0} muss eine gültige IPv6-Adresse sein", override: false, }, { tag: "ip", translation: "{0} muss eine gültige IP-Adresse sein", override: false, }, { tag: "cidr", translation: "{0} muss eine gültige CIDR-Notation enthalten", override: false, }, { tag: "cidrv4", translation: "{0} muss eine gültige CIDR-Notation für eine IPv4-Adresse enthalten", override: false, }, { tag: "cidrv6", translation: "{0} muss eine gültige CIDR-Notation für eine IPv6-Adresse enthalten", override: false, }, { tag: "tcp_addr", translation: "{0} muss eine gültige TCP-Adresse sein", override: false, }, { tag: "tcp4_addr", translation: "{0} muss eine gültige IPv4-TCP-Adresse sein", override: false, }, { tag: "tcp6_addr", translation: "{0} muss eine gültige IPv6-TCP-Adresse sein", override: false, }, { tag: "udp_addr", translation: "{0} muss eine gültige UDP-Adresse sein", override: false, }, { tag: "udp4_addr", translation: "{0} muss eine gültige IPv4-UDP-Adresse sein", override: false, }, { tag: "udp6_addr", translation: "{0} muss eine gültige IPv6-UDP-Adresse sein", override: false, }, { tag: "ip_addr", translation: "{0} muss eine auflösbare IP-Adresse sein", override: false, }, { tag: "ip4_addr", translation: "{0} muss eine auflösbare IPv4-Adresse sein", override: false, }, { tag: "ip6_addr", translation: "{0} muss eine auflösbare IPv6-Adresse sein", override: false, }, { tag: "unix_addr", translation: "{0} muss eine auflösbare UNIX-Adresse sein", override: false, }, { tag: "mac", translation: "{0} muss eine gültige MAC-Adresse sein", override: false, }, { tag: "fqdn", translation: "{0} muss eine gültige FQDN sein", override: false, }, { tag: "unique", translation: "{0} darf nur einmal vorkommen", override: false, }, { tag: "iscolor", translation: "{0} muss eine gültige Farbe sein", override: false, }, { tag: "cron", translation: "{0} muss eine gültige Cron-Ausdruck sein", override: false, }, { tag: "oneof", translation: "{0} muss einer der folgenden sein: [{1}]", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { s, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return s }, }, { tag: "json", translation: "{0} muss eine gültige JSON-Zeichenkette sein", override: false, }, { tag: "jwt", translation: "{0} muss eine gültige JWT-Zeichenkette sein", override: false, }, { tag: "lowercase", translation: "{0} darf nur Kleinbuchstaben enthalten", override: false, }, { tag: "uppercase", translation: "{0} darf nur Großbuchstaben enthalten", override: false, }, { tag: "datetime", translation: "{0} entspricht nicht dem {1}-Format", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "postcode_iso3166_alpha2", translation: "{0} entspricht nicht dem Postleitzahlformat von {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "postcode_iso3166_alpha2_field", translation: "{0} entspricht nicht dem Postleitzahlformat des Feldes {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "boolean", translation: "{0} muss eine gültige Booleanwert sein", override: false, }, { tag: "image", translation: "{0} muss ein Bild sein", override: false, }, { tag: "cve", translation: "{0} muss eine gültige CVE-Kennung sein", override: false, }, } for _, t := range translations { if t.customTransFunc != nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, t.customTransFunc) } else if t.customTransFunc != nil && t.customRegisFunc == nil { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), t.customTransFunc) } else if t.customTransFunc == nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, translateFunc) } else { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), translateFunc) } if err != nil { return } } return } func registrationFunc(tag string, translation string, override bool) validator.RegisterTranslationsFunc { return func(ut ut.Translator) (err error) { if err = ut.Add(tag, translation, override); err != nil { return } return } } func translateFunc(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t } golang-github-go-playground-validator-v10-10.30.1/translations/de/de_test.go000066400000000000000000000621331512410077000266500ustar00rootroot00000000000000package de import ( "testing" "time" . "github.com/go-playground/assert/v2" german "github.com/go-playground/locales/de" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" ) func TestTranslations(t *testing.T) { ger := german.New() uni := ut.New(ger, ger) trans, _ := uni.GetTranslator("de") 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 RequiredUnless string RequiredWith string RequiredWithAll string RequiredWithout string RequiredWithoutAll string ExcludedIf string ExcludedUnless string ExcludedWith string ExcludedWithAll string ExcludedWithout string ExcludedWithoutAll 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"` RequiredUnless string `validate:"required_unless=Inner.RequiredUnless abcd"` RequiredWith string `validate:"required_with=Inner.RequiredWith"` RequiredWithAll string `validate:"required_with_all=Inner.RequiredWith Inner.RequiredWithAll"` RequiredWithout string `validate:"required_without=Inner.RequiredWithout"` RequiredWithoutAll string `validate:"required_without_all=Inner.RequiredWithout Inner.RequiredWithoutAll"` ExcludedIf string `validate:"excluded_if=Inner.ExcludedIf abcd"` ExcludedUnless string `validate:"excluded_unless=Inner.ExcludedUnless abcd"` ExcludedWith string `validate:"excluded_with=Inner.ExcludedWith"` ExcludedWithout string `validate:"excluded_with_all=Inner.ExcludedWithAll"` ExcludedWithAll string `validate:"excluded_without=Inner.ExcludedWithout"` ExcludedWithoutAll string `validate:"excluded_without_all=Inner.ExcludedWithoutAll"` IsDefault string `validate:"isdefault"` 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"` ISSN string `validate:"issn"` 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"` Image string `validate:"image"` CveString string `validate:"cve"` } var test Test test.Inner.EqCSFieldString = "1234" test.Inner.GtCSFieldString = "1234" test.Inner.GteCSFieldString = "1234" test.Inner.RequiredUnless = "1234" test.Inner.RequiredWith = "1234" test.Inner.RequiredWithAll = "1234" test.Inner.ExcludedIf = "abcd" test.Inner.ExcludedUnless = "1234" test.Inner.ExcludedWith = "1234" test.Inner.ExcludedWithAll = "1234" test.ExcludedIf = "1234" test.ExcludedUnless = "1234" test.ExcludedWith = "1234" test.ExcludedWithAll = "1234" test.ExcludedWithout = "1234" test.ExcludedWithoutAll = "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 muss eine gültige Farbe sein", }, { ns: "Test.MAC", expected: "MAC muss eine gültige MAC-Adresse sein", }, { ns: "Test.FQDN", expected: "FQDN muss eine gültige FQDN sein", }, { ns: "Test.IPAddr", expected: "IPAddr muss eine auflösbare IP-Adresse sein", }, { ns: "Test.IPAddrv4", expected: "IPAddrv4 muss eine auflösbare IPv4-Adresse sein", }, { ns: "Test.IPAddrv6", expected: "IPAddrv6 muss eine auflösbare IPv6-Adresse sein", }, { ns: "Test.UDPAddr", expected: "UDPAddr muss eine gültige UDP-Adresse sein", }, { ns: "Test.UDPAddrv4", expected: "UDPAddrv4 muss eine gültige IPv4-UDP-Adresse sein", }, { ns: "Test.UDPAddrv6", expected: "UDPAddrv6 muss eine gültige IPv6-UDP-Adresse sein", }, { ns: "Test.TCPAddr", expected: "TCPAddr muss eine gültige TCP-Adresse sein", }, { ns: "Test.TCPAddrv4", expected: "TCPAddrv4 muss eine gültige IPv4-TCP-Adresse sein", }, { ns: "Test.TCPAddrv6", expected: "TCPAddrv6 muss eine gültige IPv6-TCP-Adresse sein", }, { ns: "Test.CIDR", expected: "CIDR muss eine gültige CIDR-Notation enthalten", }, { ns: "Test.CIDRv4", expected: "CIDRv4 muss eine gültige CIDR-Notation für eine IPv4-Adresse enthalten", }, { ns: "Test.CIDRv6", expected: "CIDRv6 muss eine gültige CIDR-Notation für eine IPv6-Adresse enthalten", }, { ns: "Test.SSN", expected: "SSN muss eine gültige SSN-Nummer sein", }, { ns: "Test.IP", expected: "IP muss eine gültige IP-Adresse sein", }, { ns: "Test.IPv4", expected: "IPv4 muss eine gültige IPv4-Adresse sein", }, { ns: "Test.IPv6", expected: "IPv6 muss eine gültige IPv6-Adresse sein", }, { ns: "Test.DataURI", expected: "DataURI muss eine gültige Data-URI sein", }, { ns: "Test.Latitude", expected: "Latitude muss gültige Breitengradkoordinaten enthalten", }, { ns: "Test.Longitude", expected: "Longitude muss gültige Längengradkoordinaten enthalten", }, { ns: "Test.MultiByte", expected: "MultiByte darf nur Mehrbyte-Zeichen enthalten", }, { ns: "Test.ASCII", expected: "ASCII darf nur ASCII-Zeichen enthalten", }, { ns: "Test.PrintableASCII", expected: "PrintableASCII darf nur druckbare ASCII-Zeichen enthalten", }, { ns: "Test.UUID", expected: "UUID muss eine gültige UUID sein", }, { ns: "Test.UUID3", expected: "UUID3 muss eine gültige Version 3 UUID sein", }, { ns: "Test.UUID4", expected: "UUID4 muss eine gültige Version 4 UUID sein", }, { ns: "Test.UUID5", expected: "UUID5 muss eine gültige Version 5 UUID sein", }, { ns: "Test.ULID", expected: "ULID muss eine gültige ULID sein", }, { ns: "Test.ISBN", expected: "ISBN muss eine gültige ISBN-Nummer sein", }, { ns: "Test.ISBN10", expected: "ISBN10 muss eine gültige ISBN-10-Nummer sein", }, { ns: "Test.ISBN13", expected: "ISBN13 muss eine gültige ISBN-13-Nummer sein", }, { ns: "Test.ISSN", expected: "ISSN muss eine gültige ISSN-Nummer sein", }, { ns: "Test.Excludes", expected: "Excludes darf den Text 'text' nicht enthalten", }, { ns: "Test.ExcludesAll", expected: "ExcludesAll darf keines der folgenden Zeichen enthalten: '!@#$'", }, { ns: "Test.ExcludesRune", expected: "ExcludesRune darf die folgenden Runen nicht enthalten: '☻'", }, { ns: "Test.ContainsAny", expected: "ContainsAny muss mindestens eines der folgenden Zeichen enthalten: '!@#$'", }, { ns: "Test.Contains", expected: "Contains muss den Text 'purpose' enthalten", }, { ns: "Test.Base64", expected: "Base64 muss eine gültige Base64-Zeichenkette sein", }, { ns: "Test.Email", expected: "Email muss eine gültige E-Mail-Adresse sein", }, { ns: "Test.URL", expected: "URL muss eine gültige URL sein", }, { ns: "Test.URI", expected: "URI muss eine gültige URI sein", }, { ns: "Test.RGBColorString", expected: "RGBColorString muss eine gültige RGB-Farbe sein", }, { ns: "Test.RGBAColorString", expected: "RGBAColorString muss eine gültige RGBA-Farbe sein", }, { ns: "Test.HSLColorString", expected: "HSLColorString muss eine gültige HSL-Farbe sein", }, { ns: "Test.HSLAColorString", expected: "HSLAColorString muss eine gültige HSLA-Farbe sein", }, { ns: "Test.HexadecimalString", expected: "HexadecimalString muss eine gültige hexadezimale Zahl sein", }, { ns: "Test.HexColorString", expected: "HexColorString muss eine gültige Hexadezimalfarbe sein", }, { ns: "Test.NumberString", expected: "NumberString muss eine gültige Zahl sein", }, { ns: "Test.NumericString", expected: "NumericString muss eine gültige Zahl sein", }, { ns: "Test.AlphanumString", expected: "AlphanumString darf nur alphanumerische Zeichen enthalten", }, { ns: "Test.AlphaString", expected: "AlphaString darf nur alphabetische Zeichen enthalten", }, { ns: "Test.LtFieldString", expected: "LtFieldString muss kleiner als MaxString sein", }, { ns: "Test.LteFieldString", expected: "LteFieldString muss kleiner als oder gleich MaxString sein", }, { ns: "Test.GtFieldString", expected: "GtFieldString muss größer als MaxString sein", }, { ns: "Test.GteFieldString", expected: "GteFieldString muss größer als oder gleich MaxString sein", }, { ns: "Test.NeFieldString", expected: "NeFieldString darf nicht gleich EqFieldString sein", }, { ns: "Test.LtCSFieldString", expected: "LtCSFieldString muss kleiner als Inner.LtCSFieldString sein", }, { ns: "Test.LteCSFieldString", expected: "LteCSFieldString muss kleiner als oder gleich Inner.LteCSFieldString sein", }, { ns: "Test.GtCSFieldString", expected: "GtCSFieldString muss größer als Inner.GtCSFieldString sein", }, { ns: "Test.GteCSFieldString", expected: "GteCSFieldString muss größer als oder gleich Inner.GteCSFieldString sein", }, { ns: "Test.NeCSFieldString", expected: "NeCSFieldString darf nicht gleich Inner.NeCSFieldString sein", }, { ns: "Test.EqCSFieldString", expected: "EqCSFieldString muss gleich Inner.EqCSFieldString sein", }, { ns: "Test.EqFieldString", expected: "EqFieldString muss gleich MaxString sein", }, { ns: "Test.GteString", expected: "GteString muss mindestens 3 Zeichen lang sein", }, { ns: "Test.GteNumber", expected: "GteNumber muss 5,56 oder größer sein", }, { ns: "Test.GteMultiple", expected: "GteMultiple muss mindestens 2 Elemente enthalten", }, { ns: "Test.GteTime", expected: "GteTime muss vor dem aktuellen Datum und Uhrzeit liegen oder gleich sein", }, { ns: "Test.GtString", expected: "GtString muss größer als 3 Zeichen sein", }, { ns: "Test.GtNumber", expected: "GtNumber muss größer als 5,56 sein", }, { ns: "Test.GtMultiple", expected: "GtMultiple muss 2 Elemente oder mehr enthalten", }, { ns: "Test.GtTime", expected: "GtTime muss vor dem aktuellen Datum und Uhrzeit liegen", }, { ns: "Test.LteString", expected: "LteString darf maximal 3 Zeichen lang sein", }, { ns: "Test.LteNumber", expected: "LteNumber darf 5,56 oder weniger sein", }, { ns: "Test.LteMultiple", expected: "LteMultiple darf maximal 2 Elemente enthalten", }, { ns: "Test.LteTime", expected: "LteTime muss vor dem aktuellen Datum und Uhrzeit liegen oder gleich sein", }, { ns: "Test.LtString", expected: "LtString muss kleiner als 3 Zeichen sein", }, { ns: "Test.LtNumber", expected: "LtNumber muss kleiner als 5,56 sein", }, { ns: "Test.LtMultiple", expected: "LtMultiple muss 2 Elemente oder weniger enthalten", }, { ns: "Test.LtTime", expected: "LtTime muss vor dem aktuellen Datum und Uhrzeit liegen", }, { ns: "Test.NeString", expected: "NeString darf nicht gleich sein", }, { ns: "Test.NeNumber", expected: "NeNumber darf nicht gleich 0.00 sein", }, { ns: "Test.NeMultiple", expected: "NeMultiple darf nicht gleich 0 sein", }, { ns: "Test.EqString", expected: "EqString ist nicht gleich 3", }, { ns: "Test.EqNumber", expected: "EqNumber ist nicht gleich 2.33", }, { ns: "Test.EqMultiple", expected: "EqMultiple ist nicht gleich 7", }, { ns: "Test.MaxString", expected: "MaxString darf maximal 3 Zeichen lang sein", }, { ns: "Test.MaxNumber", expected: "MaxNumber darf 1.113,00 oder weniger sein", }, { ns: "Test.MaxMultiple", expected: "MaxMultiple darf maximal 7 Elemente enthalten", }, { ns: "Test.MinString", expected: "MinString muss mindestens 1 Zeichen lang sein", }, { ns: "Test.MinNumber", expected: "MinNumber muss 1.113,00 oder größer sein", }, { ns: "Test.MinMultiple", expected: "MinMultiple muss mindestens 7 Elemente enthalten", }, { ns: "Test.LenString", expected: "LenString darf nur 1 Zeichen lang sein", }, { ns: "Test.LenNumber", expected: "LenNumber muss gleich 1.113,00 sein", }, { ns: "Test.LenMultiple", expected: "LenMultiple muss 7 Elemente enthalten", }, { ns: "Test.RequiredString", expected: "RequiredString ist ein Pflichtfeld", }, { ns: "Test.RequiredIf", expected: "RequiredIf ist ein Pflichtfeld", }, { ns: "Test.RequiredNumber", expected: "RequiredNumber ist ein Pflichtfeld", }, { ns: "Test.RequiredMultiple", expected: "RequiredMultiple ist ein Pflichtfeld", }, { ns: "Test.RequiredUnless", expected: "RequiredUnless ist ein Pflichtfeld", }, { ns: "Test.RequiredWith", expected: "RequiredWith ist ein Pflichtfeld", }, { ns: "Test.RequiredWithAll", expected: "RequiredWithAll ist ein Pflichtfeld", }, { ns: "Test.RequiredWithout", expected: "RequiredWithout ist ein Pflichtfeld", }, { ns: "Test.RequiredWithoutAll", expected: "RequiredWithoutAll ist ein Pflichtfeld", }, { ns: "Test.ExcludedIf", expected: "ExcludedIf ist ein ausgeschlossenes Feld", }, { ns: "Test.ExcludedUnless", expected: "ExcludedUnless ist ein ausgeschlossenes Feld", }, { ns: "Test.ExcludedWith", expected: "ExcludedWith ist ein ausgeschlossenes Feld", }, { ns: "Test.ExcludedWithAll", expected: "ExcludedWithAll ist ein ausgeschlossenes Feld", }, { ns: "Test.ExcludedWithout", expected: "ExcludedWithout ist ein ausgeschlossenes Feld", }, { ns: "Test.ExcludedWithoutAll", expected: "ExcludedWithoutAll ist ein ausgeschlossenes Feld", }, { ns: "Test.StrPtrMinLen", expected: "StrPtrMinLen muss mindestens 10 Zeichen lang sein", }, { ns: "Test.StrPtrMaxLen", expected: "StrPtrMaxLen darf maximal 1 Zeichen lang sein", }, { ns: "Test.StrPtrLen", expected: "StrPtrLen darf nur 2 Zeichen lang sein", }, { ns: "Test.StrPtrLt", expected: "StrPtrLt muss kleiner als 1 Zeichen sein", }, { ns: "Test.StrPtrLte", expected: "StrPtrLte darf maximal 1 Zeichen lang sein", }, { ns: "Test.StrPtrGt", expected: "StrPtrGt muss größer als 10 Zeichen sein", }, { ns: "Test.StrPtrGte", expected: "StrPtrGte muss mindestens 10 Zeichen lang sein", }, { ns: "Test.OneOfString", expected: "OneOfString muss einer der folgenden sein: [red green]", }, { ns: "Test.OneOfInt", expected: "OneOfInt muss einer der folgenden sein: [5 63]", }, { ns: "Test.UniqueSlice", expected: "UniqueSlice darf nur einmal vorkommen", }, { ns: "Test.UniqueArray", expected: "UniqueArray darf nur einmal vorkommen", }, { ns: "Test.UniqueMap", expected: "UniqueMap darf nur einmal vorkommen", }, { ns: "Test.JSONString", expected: "JSONString muss eine gültige JSON-Zeichenkette sein", }, { ns: "Test.JWTString", expected: "JWTString muss eine gültige JWT-Zeichenkette sein", }, { ns: "Test.LowercaseString", expected: "LowercaseString darf nur Kleinbuchstaben enthalten", }, { ns: "Test.UppercaseString", expected: "UppercaseString darf nur Großbuchstaben enthalten", }, { ns: "Test.Datetime", expected: "Datetime entspricht nicht dem 2006-01-02-Format", }, { ns: "Test.PostCode", expected: "PostCode entspricht nicht dem Postleitzahlformat von SG", }, { ns: "Test.PostCodeByField", expected: "PostCodeByField entspricht nicht dem Postleitzahlformat des Feldes PostCodeCountry", }, { ns: "Test.BooleanString", expected: "BooleanString muss eine gültige Booleanwert sein", }, { ns: "Test.Image", expected: "Image muss ein Bild sein", }, { ns: "Test.CveString", expected: "CveString muss eine gültige CVE-Kennung sein", }, } 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)) } } golang-github-go-playground-validator-v10-10.30.1/translations/en/000077500000000000000000000000001512410077000246775ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/translations/en/en.go000066400000000000000000001110031512410077000256240ustar00rootroot00000000000000package en import ( "fmt" "log" "reflect" "strconv" "strings" "time" "github.com/go-playground/locales" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" ) // RegisterDefaultTranslations registers a set of default translations // for all built in tag's in validator; you may add your own as desired. func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (err error) { translations := []struct { tag string translation string override bool customRegisFunc validator.RegisterTranslationsFunc customTransFunc validator.TranslationFunc }{ { tag: "required", translation: "{0} is a required field", override: false, }, { tag: "required_if", translation: "{0} is a required field", override: false, }, { tag: "required_unless", translation: "{0} is a required field", override: false, }, { tag: "required_with", translation: "{0} is a required field", override: false, }, { tag: "required_with_all", translation: "{0} is a required field", override: false, }, { tag: "required_without", translation: "{0} is a required field", override: false, }, { tag: "required_without_all", translation: "{0} is a required field", override: false, }, { tag: "excluded_if", translation: "{0} is an excluded field", override: false, }, { tag: "excluded_unless", translation: "{0} is an excluded field", override: false, }, { tag: "excluded_with", translation: "{0} is an excluded field", override: false, }, { tag: "excluded_with_all", translation: "{0} is an excluded field", override: false, }, { tag: "excluded_without", translation: "{0} is an excluded field", override: false, }, { tag: "excluded_without_all", translation: "{0} is an excluded field", override: false, }, { tag: "isdefault", translation: "{0} must be default value", override: false, }, { tag: "len", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("len-string", "{0} must be {1} in length", false); err != nil { return } if err = ut.AddCardinal("len-string-character", "{0} character", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("len-string-character", "{0} characters", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("len-number", "{0} must be equal to {1}", false); err != nil { return } if err = ut.Add("len-items", "{0} must contain {1}", false); err != nil { return } if err = ut.AddCardinal("len-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("len-items-item", "{0} items", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("len-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("len-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-items", fe.Field(), c) default: t, err = ut.T("len-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "min", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("min-string", "{0} must be at least {1} in length", false); err != nil { return } if err = ut.AddCardinal("min-string-character", "{0} character", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("min-string-character", "{0} characters", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("min-number", "{0} must be {1} or greater", false); err != nil { return } if err = ut.Add("min-items", "{0} must contain at least {1}", false); err != nil { return } if err = ut.AddCardinal("min-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("min-items-item", "{0} items", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("min-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("min-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-items", fe.Field(), c) default: if fe.Type() == reflect.TypeOf(time.Duration(0)) { t, err = ut.T("min-number", fe.Field(), fe.Param()) goto END } err = fn() if err != nil { goto END } t, err = ut.T("min-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "max", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("max-string", "{0} must be a maximum of {1} in length", false); err != nil { return } if err = ut.AddCardinal("max-string-character", "{0} character", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("max-string-character", "{0} characters", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("max-number", "{0} must be {1} or less", false); err != nil { return } if err = ut.Add("max-items", "{0} must contain at maximum {1}", false); err != nil { return } if err = ut.AddCardinal("max-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("max-items-item", "{0} items", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("max-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("max-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-items", fe.Field(), c) default: if fe.Type() == reflect.TypeOf(time.Duration(0)) { t, err = ut.T("max-number", fe.Field(), fe.Param()) goto END } err = fn() if err != nil { goto END } t, err = ut.T("max-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eq", translation: "{0} is not equal to {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ne", translation: "{0} should not be equal to {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "lt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lt-string", "{0} must be less than {1} in length", false); err != nil { return } if err = ut.AddCardinal("lt-string-character", "{0} character", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lt-string-character", "{0} characters", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-number", "{0} must be less than {1}", false); err != nil { return } if err = ut.Add("lt-items", "{0} must contain less than {1}", false); err != nil { return } if err = ut.AddCardinal("lt-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lt-items-item", "{0} items", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-datetime", "{0} must be less than the current Date & Time", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "lte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lte-string", "{0} must be at maximum {1} in length", false); err != nil { return } if err = ut.AddCardinal("lte-string-character", "{0} character", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lte-string-character", "{0} characters", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-number", "{0} must be {1} or less", false); err != nil { return } if err = ut.Add("lte-items", "{0} must contain at maximum {1}", false); err != nil { return } if err = ut.AddCardinal("lte-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lte-items-item", "{0} items", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-datetime", "{0} must be less than or equal to the current Date & Time", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gt-string", "{0} must be greater than {1} in length", false); err != nil { return } if err = ut.AddCardinal("gt-string-character", "{0} character", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gt-string-character", "{0} characters", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-number", "{0} must be greater than {1}", false); err != nil { return } if err = ut.Add("gt-items", "{0} must contain more than {1}", false); err != nil { return } if err = ut.AddCardinal("gt-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gt-items-item", "{0} items", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-datetime", "{0} must be greater than the current Date & Time", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gte-string", "{0} must be at least {1} in length", false); err != nil { return } if err = ut.AddCardinal("gte-string-character", "{0} character", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gte-string-character", "{0} characters", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-number", "{0} must be {1} or greater", false); err != nil { return } if err = ut.Add("gte-items", "{0} must contain at least {1}", false); err != nil { return } if err = ut.AddCardinal("gte-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gte-items-item", "{0} items", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-datetime", "{0} must be greater than or equal to the current Date & Time", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eqfield", translation: "{0} must be equal to {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "eqcsfield", translation: "{0} must be equal to {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "necsfield", translation: "{0} cannot be equal to {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtcsfield", translation: "{0} must be greater than {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtecsfield", translation: "{0} must be greater than or equal to {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltcsfield", translation: "{0} must be less than {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltecsfield", translation: "{0} must be less than or equal to {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "nefield", translation: "{0} cannot be equal to {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtfield", translation: "{0} must be greater than {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtefield", translation: "{0} must be greater than or equal to {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltfield", translation: "{0} must be less than {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltefield", translation: "{0} must be less than or equal to {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "alpha", translation: "{0} can only contain alphabetic characters", override: false, }, { tag: "alphanum", translation: "{0} can only contain alphanumeric characters", override: false, }, { tag: "alphaspace", translation: "{0} can only contain alphabetic and space characters", override: false, }, { tag: "alphanumspace", translation: "{0} can only contain alphanumeric and space characters", override: false, }, { tag: "alphaunicode", translation: "{0} can only contain unicode alphabetic characters", override: false, }, { tag: "alphanumunicode", translation: "{0} can only contain unicode alphanumeric characters", override: false, }, { tag: "numeric", translation: "{0} must be a valid numeric value", override: false, }, { tag: "number", translation: "{0} must be a valid number", override: false, }, { tag: "hexadecimal", translation: "{0} must be a valid hexadecimal", override: false, }, { tag: "hexcolor", translation: "{0} must be a valid HEX color", override: false, }, { tag: "rgb", translation: "{0} must be a valid RGB color", override: false, }, { tag: "rgba", translation: "{0} must be a valid RGBA color", override: false, }, { tag: "hsl", translation: "{0} must be a valid HSL color", override: false, }, { tag: "hsla", translation: "{0} must be a valid HSLA color", override: false, }, { tag: "e164", translation: "{0} must be a valid E.164 formatted phone number", override: false, }, { tag: "email", translation: "{0} must be a valid email address", override: false, }, { tag: "url", translation: "{0} must be a valid URL", override: false, }, { tag: "uri", translation: "{0} must be a valid URI", override: false, }, { tag: "base64", translation: "{0} must be a valid Base64 string", override: false, }, { tag: "contains", translation: "{0} must contain the text '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "containsany", translation: "{0} must contain at least one of the following characters '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludes", translation: "{0} cannot contain the text '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesall", translation: "{0} cannot contain any of the following characters '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesrune", translation: "{0} cannot contain the following '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "isbn", translation: "{0} must be a valid ISBN number", override: false, }, { tag: "isbn10", translation: "{0} must be a valid ISBN-10 number", override: false, }, { tag: "isbn13", translation: "{0} must be a valid ISBN-13 number", override: false, }, { tag: "issn", translation: "{0} must be a valid ISSN number", override: false, }, { tag: "urn_rfc2141", translation: "{0} must be a valid RFC 2141 URN", override: false, }, { tag: "uuid", translation: "{0} must be a valid UUID", override: false, }, { tag: "uuid3", translation: "{0} must be a valid version 3 UUID", override: false, }, { tag: "uuid4", translation: "{0} must be a valid version 4 UUID", override: false, }, { tag: "uuid5", translation: "{0} must be a valid version 5 UUID", override: false, }, { tag: "ulid", translation: "{0} must be a valid ULID", override: false, }, { tag: "ascii", translation: "{0} must contain only ascii characters", override: false, }, { tag: "printascii", translation: "{0} must contain only printable ascii characters", override: false, }, { tag: "multibyte", translation: "{0} must contain multibyte characters", override: false, }, { tag: "datauri", translation: "{0} must contain a valid Data URI", override: false, }, { tag: "latitude", translation: "{0} must contain valid latitude coordinates", override: false, }, { tag: "longitude", translation: "{0} must contain a valid longitude coordinates", override: false, }, { tag: "ssn", translation: "{0} must be a valid SSN number", override: false, }, { tag: "ipv4", translation: "{0} must be a valid IPv4 address", override: false, }, { tag: "ipv6", translation: "{0} must be a valid IPv6 address", override: false, }, { tag: "ip", translation: "{0} must be a valid IP address", override: false, }, { tag: "cidr", translation: "{0} must contain a valid CIDR notation", override: false, }, { tag: "cidrv4", translation: "{0} must contain a valid CIDR notation for an IPv4 address", override: false, }, { tag: "cidrv6", translation: "{0} must contain a valid CIDR notation for an IPv6 address", override: false, }, { tag: "tcp_addr", translation: "{0} must be a valid TCP address", override: false, }, { tag: "tcp4_addr", translation: "{0} must be a valid IPv4 TCP address", override: false, }, { tag: "tcp6_addr", translation: "{0} must be a valid IPv6 TCP address", override: false, }, { tag: "udp_addr", translation: "{0} must be a valid UDP address", override: false, }, { tag: "udp4_addr", translation: "{0} must be a valid IPv4 UDP address", override: false, }, { tag: "udp6_addr", translation: "{0} must be a valid IPv6 UDP address", override: false, }, { tag: "ip_addr", translation: "{0} must be a resolvable IP address", override: false, }, { tag: "ip4_addr", translation: "{0} must be a resolvable IPv4 address", override: false, }, { tag: "ip6_addr", translation: "{0} must be a resolvable IPv6 address", override: false, }, { tag: "unix_addr", translation: "{0} must be a resolvable UNIX address", override: false, }, { tag: "mac", translation: "{0} must contain a valid MAC address", override: false, }, { tag: "fqdn", translation: "{0} must be a valid FQDN", override: false, }, { tag: "unique", translation: "{0} must contain unique values", override: false, }, { tag: "iscolor", translation: "{0} must be a valid color", override: false, }, { tag: "cron", translation: "{0} must be a valid cron expression", override: false, }, { tag: "oneof", translation: "{0} must be one of [{1}]", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { s, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return s }, }, { tag: "json", translation: "{0} must be a valid json string", override: false, }, { tag: "jwt", translation: "{0} must be a valid jwt string", override: false, }, { tag: "lowercase", translation: "{0} must be a lowercase string", override: false, }, { tag: "uppercase", translation: "{0} must be an uppercase string", override: false, }, { tag: "datetime", translation: "{0} does not match the {1} format", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "postcode_iso3166_alpha2", translation: "{0} does not match postcode format of {1} country", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "postcode_iso3166_alpha2_field", translation: "{0} does not match postcode format of country in {1} field", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "boolean", translation: "{0} must be a valid boolean value", override: false, }, { tag: "image", translation: "{0} must be a valid image", override: false, }, { tag: "cve", translation: "{0} must be a valid cve identifier", override: false, }, { tag: "validateFn", translation: "{0} must be a valid object", override: false, }, } for _, t := range translations { if t.customTransFunc != nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, t.customTransFunc) } else if t.customTransFunc != nil && t.customRegisFunc == nil { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), t.customTransFunc) } else if t.customTransFunc == nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, translateFunc) } else { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), translateFunc) } if err != nil { return } } return } func registrationFunc(tag string, translation string, override bool) validator.RegisterTranslationsFunc { return func(ut ut.Translator) (err error) { if err = ut.Add(tag, translation, override); err != nil { return } return } } func translateFunc(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t } golang-github-go-playground-validator-v10-10.30.1/translations/en/en_test.go000066400000000000000000000642031512410077000266740ustar00rootroot00000000000000package 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" ) type Foo struct{} func (Foo) IsBar() bool { return false } 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 RequiredUnless string RequiredWith string RequiredWithAll string RequiredWithout string RequiredWithoutAll string ExcludedIf string ExcludedUnless string ExcludedWith string ExcludedWithAll string ExcludedWithout string ExcludedWithoutAll 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"` RequiredUnless string `validate:"required_unless=Inner.RequiredUnless abcd"` RequiredWith string `validate:"required_with=Inner.RequiredWith"` RequiredWithAll string `validate:"required_with_all=Inner.RequiredWith Inner.RequiredWithAll"` RequiredWithout string `validate:"required_without=Inner.RequiredWithout"` RequiredWithoutAll string `validate:"required_without_all=Inner.RequiredWithout Inner.RequiredWithoutAll"` ExcludedIf string `validate:"excluded_if=Inner.ExcludedIf abcd"` ExcludedUnless string `validate:"excluded_unless=Inner.ExcludedUnless abcd"` ExcludedWith string `validate:"excluded_with=Inner.ExcludedWith"` ExcludedWithout string `validate:"excluded_with_all=Inner.ExcludedWithAll"` ExcludedWithAll string `validate:"excluded_without=Inner.ExcludedWithout"` ExcludedWithoutAll string `validate:"excluded_without_all=Inner.ExcludedWithoutAll"` IsDefault string `validate:"isdefault"` 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"` AlphaSpaceString string `validate:"alphaspace"` AlphaNumSpaceString string `validate:"alphanumspace"` AlphaUnicodeString string `validate:"alphaunicode"` AlphaNumUnicodeString string `validate:"alphanumunicode"` 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"` ISSN string `validate:"issn"` URN string `validate:"urn_rfc2141"` 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"` Image string `validate:"image"` CveString string `validate:"cve"` MinDuration time.Duration `validate:"min=1h30m,max=2h"` MaxDuration time.Duration `validate:"min=1h30m,max=2h"` ValidateFn Foo `validate:"validateFn=IsBar"` } var test Test test.Inner.EqCSFieldString = "1234" test.Inner.GtCSFieldString = "1234" test.Inner.GteCSFieldString = "1234" test.Inner.RequiredUnless = "1234" test.Inner.RequiredWith = "1234" test.Inner.RequiredWithAll = "1234" test.Inner.ExcludedIf = "abcd" test.Inner.ExcludedUnless = "1234" test.Inner.ExcludedWith = "1234" test.Inner.ExcludedWithAll = "1234" test.ExcludedIf = "1234" test.ExcludedUnless = "1234" test.ExcludedWith = "1234" test.ExcludedWithAll = "1234" test.ExcludedWithout = "1234" test.ExcludedWithoutAll = "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.MinDuration = 1 * time.Hour test.MaxDuration = 3 * time.Hour 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.ISSN", expected: "ISSN must be a valid ISSN number", }, { ns: "Test.URN", expected: "URN must be a valid RFC 2141 URN", }, { 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.AlphaSpaceString", expected: "AlphaSpaceString can only contain alphabetic and space characters", }, { ns: "Test.AlphaNumSpaceString", expected: "AlphaNumSpaceString can only contain alphanumeric and space characters", }, { ns: "Test.AlphaUnicodeString", expected: "AlphaUnicodeString can only contain unicode alphabetic characters", }, { ns: "Test.AlphaNumUnicodeString", expected: "AlphaNumUnicodeString can only contain unicode alphanumeric 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.RequiredUnless", expected: "RequiredUnless is a required field", }, { ns: "Test.RequiredWith", expected: "RequiredWith is a required field", }, { ns: "Test.RequiredWithAll", expected: "RequiredWithAll is a required field", }, { ns: "Test.RequiredWithout", expected: "RequiredWithout is a required field", }, { ns: "Test.RequiredWithoutAll", expected: "RequiredWithoutAll is a required field", }, { ns: "Test.ExcludedIf", expected: "ExcludedIf is an excluded field", }, { ns: "Test.ExcludedUnless", expected: "ExcludedUnless is an excluded field", }, { ns: "Test.ExcludedWith", expected: "ExcludedWith is an excluded field", }, { ns: "Test.ExcludedWithAll", expected: "ExcludedWithAll is an excluded field", }, { ns: "Test.ExcludedWithout", expected: "ExcludedWithout is an excluded field", }, { ns: "Test.ExcludedWithoutAll", expected: "ExcludedWithoutAll is an excluded 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.Image", expected: "Image must be a valid image", }, { ns: "Test.CveString", expected: "CveString must be a valid cve identifier", }, { ns: "Test.MinDuration", expected: "MinDuration must be 1h30m or greater", }, { ns: "Test.MaxDuration", expected: "MaxDuration must be 2h or less", }, { ns: "Test.ValidateFn", expected: "ValidateFn must be a valid object", }, } 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)) } } golang-github-go-playground-validator-v10-10.30.1/translations/es/000077500000000000000000000000001512410077000247045ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/translations/es/es.go000066400000000000000000001001671512410077000256470ustar00rootroot00000000000000package es import ( "fmt" "log" "reflect" "strconv" "strings" "time" "github.com/go-playground/locales" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" ) // RegisterDefaultTranslations registers a set of default translations // for all built in tag's in validator; you may add your own as desired. func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (err error) { translations := []struct { tag string translation string override bool customRegisFunc validator.RegisterTranslationsFunc customTransFunc validator.TranslationFunc }{ { tag: "required", translation: "{0} es un campo requerido", override: false, }, { tag: "required_if", translation: "{0} es un campo requerido", override: false, }, { tag: "len", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("len-string", "{0} debe tener {1} de longitud", false); err != nil { return } if err = ut.AddCardinal("len-string-character", "{0} carácter", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("len-string-character", "{0} caracteres", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("len-number", "{0} debe ser igual a {1}", false); err != nil { return } if err = ut.Add("len-items", "{0} debe contener {1}", false); err != nil { return } if err = ut.AddCardinal("len-items-item", "{0} elemento", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("len-items-item", "{0} elementos", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("len-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("len-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-items", fe.Field(), c) default: t, err = ut.T("len-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "min", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("min-string", "{0} debe tener al menos {1} de longitud", false); err != nil { return } if err = ut.AddCardinal("min-string-character", "{0} carácter", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("min-string-character", "{0} caracteres", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("min-number", "{0} debe ser {1} o más", false); err != nil { return } if err = ut.Add("min-items", "{0} debe contener al menos {1}", false); err != nil { return } if err = ut.AddCardinal("min-items-item", "{0} elemento", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("min-items-item", "{0} elementos", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("min-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("min-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-items", fe.Field(), c) default: t, err = ut.T("min-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "max", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("max-string", "{0} debe tener un máximo de {1} de longitud", false); err != nil { return } if err = ut.AddCardinal("max-string-character", "{0} carácter", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("max-string-character", "{0} caracteres", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("max-number", "{0} debe ser {1} o menos", false); err != nil { return } if err = ut.Add("max-items", "{0} debe contener como máximo {1}", false); err != nil { return } if err = ut.AddCardinal("max-items-item", "{0} elemento", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("max-items-item", "{0} elementos", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("max-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("max-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-items", fe.Field(), c) default: t, err = ut.T("max-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eq", translation: "{0} no es igual a {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ne", translation: "{0} no debería ser igual a {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "lt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lt-string", "{0} debe tener menos de {1} de longitud", false); err != nil { return } if err = ut.AddCardinal("lt-string-character", "{0} carácter", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lt-string-character", "{0} caracteres", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-number", "{0} debe ser menos de {1}", false); err != nil { return } if err = ut.Add("lt-items", "{0} debe contener menos de {1}", false); err != nil { return } if err = ut.AddCardinal("lt-items-item", "{0} elemento", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lt-items-item", "{0} elementos", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-datetime", "{0} debe ser antes de la fecha y hora actual", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "lte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lte-string", "{0} debe tener un máximo de {1} de longitud", false); err != nil { return } if err = ut.AddCardinal("lte-string-character", "{0} carácter", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lte-string-character", "{0} caracteres", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-number", "{0} debe ser {1} o menos", false); err != nil { return } if err = ut.Add("lte-items", "{0} debe contener como máximo {1}", false); err != nil { return } if err = ut.AddCardinal("lte-items-item", "{0} elemento", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lte-items-item", "{0} elementos", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-datetime", "{0} debe ser antes o durante la fecha y hora actual", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gt-string", "{0} debe ser mayor que {1} en longitud", false); err != nil { return } if err = ut.AddCardinal("gt-string-character", "{0} carácter", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gt-string-character", "{0} caracteres", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-number", "{0} debe ser mayor que {1}", false); err != nil { return } if err = ut.Add("gt-items", "{0} debe contener más de {1}", false); err != nil { return } if err = ut.AddCardinal("gt-items-item", "{0} elemento", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gt-items-item", "{0} elementos", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-datetime", "{0} debe ser después de la fecha y hora actual", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gte-string", "{0} debe tener al menos {1} de longitud", false); err != nil { return } if err = ut.AddCardinal("gte-string-character", "{0} carácter", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gte-string-character", "{0} caracteres", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-number", "{0} debe ser {1} o mayor", false); err != nil { return } if err = ut.Add("gte-items", "{0} debe contener al menos {1}", false); err != nil { return } if err = ut.AddCardinal("gte-items-item", "{0} elemento", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gte-items-item", "{0} elementos", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-datetime", "{0} debe ser después o durante la fecha y hora actuales", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eqfield", translation: "{0} debe ser igual a {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "eqcsfield", translation: "{0} debe ser igual a {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "necsfield", translation: "{0} no puede ser igual a {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtcsfield", translation: "{0} debe ser mayor que {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtecsfield", translation: "{0} debe ser mayor o igual a {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltcsfield", translation: "{0} debe ser menor que {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltecsfield", translation: "{0} debe ser menor o igual a {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "nefield", translation: "{0} no puede ser igual a {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtfield", translation: "{0} debe ser mayor que {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtefield", translation: "{0} debe ser mayor o igual a {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltfield", translation: "{0} debe ser menor que {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltefield", translation: "{0} debe ser menor o igual a {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "alpha", translation: "{0} sólo puede contener caracteres alfabéticos", override: false, }, { tag: "alphanum", translation: "{0} sólo puede contener caracteres alfanuméricos", override: false, }, { tag: "numeric", translation: "{0} debe ser un valor numérico válido", override: false, }, { tag: "number", translation: "{0} debe ser un número válido", override: false, }, { tag: "hexadecimal", translation: "{0} debe ser un hexadecimal válido", override: false, }, { tag: "hexcolor", translation: "{0} debe ser un color HEX válido", override: false, }, { tag: "rgb", translation: "{0} debe ser un color RGB válido", override: false, }, { tag: "rgba", translation: "{0} debe ser un color RGBA válido", override: false, }, { tag: "hsl", translation: "{0} debe ser un color HSL válido", override: false, }, { tag: "hsla", translation: "{0} debe ser un color HSL válido", override: false, }, { tag: "e164", translation: "{0} debe ser un número de teléfono válido con formato E.164", override: false, }, { tag: "email", translation: "{0} debe ser una dirección de correo electrónico válida", override: false, }, { tag: "url", translation: "{0} debe ser un URL válido", override: false, }, { tag: "uri", translation: "{0} debe ser una URI válida", override: false, }, { tag: "base64", translation: "{0} debe ser una cadena de Base64 válida", override: false, }, { tag: "contains", translation: "{0} debe contener el texto '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "containsany", translation: "{0} debe contener al menos uno de los siguientes caracteres '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludes", translation: "{0} no puede contener el texto '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesall", translation: "{0} no puede contener ninguno de los siguientes caracteres '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesrune", translation: "{0} no puede contener lo siguiente '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "isbn", translation: "{0} debe ser un número ISBN válido", override: false, }, { tag: "isbn10", translation: "{0} debe ser un número ISBN-10 válido", override: false, }, { tag: "isbn13", translation: "{0} debe ser un número ISBN-13 válido", override: false, }, { tag: "issn", translation: "{0} debe ser un número ISSN válido", override: false, }, { tag: "uuid", translation: "{0} debe ser un UUID válido", override: false, }, { tag: "uuid3", translation: "{0} debe ser una versión válida 3 UUID", override: false, }, { tag: "uuid4", translation: "{0} debe ser una versión válida 4 UUID", override: false, }, { tag: "uuid5", translation: "{0} debe ser una versión válida 5 UUID", override: false, }, { tag: "ulid", translation: "{0} debe ser un ULID válido", override: false, }, { tag: "ascii", translation: "{0} debe contener sólo caracteres ascii", override: false, }, { tag: "printascii", translation: "{0} debe contener sólo caracteres ASCII imprimibles", override: false, }, { tag: "multibyte", translation: "{0} debe contener caracteres multibyte", override: false, }, { tag: "datauri", translation: "{0} debe contener un URI de datos válido", override: false, }, { tag: "latitude", translation: "{0} debe contener coordenadas de latitud válidas", override: false, }, { tag: "longitude", translation: "{0} debe contener unas coordenadas de longitud válidas", override: false, }, { tag: "ssn", translation: "{0} debe ser un número válido de SSN", override: false, }, { tag: "ipv4", translation: "{0} debe ser una dirección IPv4 válida", override: false, }, { tag: "ipv6", translation: "{0} debe ser una dirección IPv6 válida", override: false, }, { tag: "ip", translation: "{0} debe ser una dirección IP válida", override: false, }, { tag: "cidr", translation: "{0} debe contener una anotación válida del CIDR", override: false, }, { tag: "cidrv4", translation: "{0} debe contener una notación CIDR válida para una dirección IPv4", override: false, }, { tag: "cidrv6", translation: "{0} debe contener una notación CIDR válida para una dirección IPv6", override: false, }, { tag: "tcp_addr", translation: "{0} debe ser una dirección TCP válida", override: false, }, { tag: "tcp4_addr", translation: "{0} debe ser una dirección IPv4 TCP válida", override: false, }, { tag: "tcp6_addr", translation: "{0} debe ser una dirección IPv6 TCP válida", override: false, }, { tag: "udp_addr", translation: "{0} debe ser una dirección UDP válida", override: false, }, { tag: "udp4_addr", translation: "{0} debe ser una dirección IPv4 UDP válida", override: false, }, { tag: "udp6_addr", translation: "{0} debe ser una dirección IPv6 UDP válida", override: false, }, { tag: "ip_addr", translation: "{0} debe ser una dirección IP resoluble", override: false, }, { tag: "ip4_addr", translation: "{0} debe ser una dirección IPv4 resoluble", override: false, }, { tag: "ip6_addr", translation: "{0} debe ser una dirección IPv6 resoluble", override: false, }, { tag: "unix_addr", translation: "{0} debe ser una dirección UNIX resoluble", override: false, }, { tag: "mac", translation: "{0} debe contener una dirección MAC válida", override: false, }, { tag: "unique", translation: "{0} debe contener valores únicos", override: false, }, { tag: "iscolor", translation: "{0} debe ser un color válido", override: false, }, { tag: "oneof", translation: "{0} debe ser uno de [{1}]", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { s, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return s }, }, { tag: "image", translation: "{0} debe ser una imagen válida", override: false, }, } for _, t := range translations { if t.customTransFunc != nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, t.customTransFunc) } else if t.customTransFunc != nil && t.customRegisFunc == nil { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), t.customTransFunc) } else if t.customTransFunc == nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, translateFunc) } else { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), translateFunc) } if err != nil { return } } return } func registrationFunc(tag string, translation string, override bool) validator.RegisterTranslationsFunc { return func(ut ut.Translator) (err error) { if err = ut.Add(tag, translation, override); err != nil { return } return } } func translateFunc(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t } golang-github-go-playground-validator-v10-10.30.1/translations/es/es_test.go000066400000000000000000000501051512410077000267020ustar00rootroot00000000000000package 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"` ISSN string `validate:"issn"` 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"` Image string `validate:"image"` } 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.ISSN", expected: "ISSN debe ser un número ISSN 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", }, { ns: "Test.Image", expected: "Image debe ser una imagen válida", }, } 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)) } } golang-github-go-playground-validator-v10-10.30.1/translations/fa/000077500000000000000000000000001512410077000246635ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/translations/fa/fa.go000066400000000000000000001062471512410077000256120ustar00rootroot00000000000000package fa import ( "fmt" "log" "reflect" "strconv" "strings" "time" "github.com/go-playground/locales" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" ) // RegisterDefaultTranslations registers a set of default translations // for all built in tag's in validator; you may add your own as desired. func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (err error) { translations := []struct { tag string translation string override bool customRegisFunc validator.RegisterTranslationsFunc customTransFunc validator.TranslationFunc }{ { tag: "required", translation: "فیلد {0} اجباری میباشد", override: false, }, { tag: "len", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("len-string", "طول {0} باید {1} باشد", false); err != nil { return } if err = ut.AddCardinal("len-string-character", "{0} کاراکتر", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("len-string-character", "{0} کاراکتر", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("len-number", "طول {0} باید برابر {1} باشد", false); err != nil { return } if err = ut.Add("len-items", "تعداد {0} باید برابر {1} باشد", false); err != nil { return } if err = ut.AddCardinal("len-items-item", "{0} آیتم", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("len-items-item", "{0} آیتم", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("len-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("len-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-items", fe.Field(), c) default: t, err = ut.T("len-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "min", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("min-string", "طول {0} باید حداقل {1} باشد", false); err != nil { return } if err = ut.AddCardinal("min-string-character", "{0} کاراکتر", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("min-string-character", "{0} کاراکتر", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("min-number", "{0} باید بزرگتر یا برابر {1} باشد", false); err != nil { return } if err = ut.Add("min-items", "{0} باید شامل حداقل {1} باشد", false); err != nil { return } if err = ut.AddCardinal("min-items-item", "{0} آیتم", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("min-items-item", "{0} آیتم", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("min-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("min-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-items", fe.Field(), c) default: t, err = ut.T("min-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "max", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("max-string", "طول {0} باید حداکثر {1} باشد", false); err != nil { return } if err = ut.AddCardinal("max-string-character", "{0} کاراکتر", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("max-string-character", "{0} کاراکتر", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("max-number", "{0} باید کمتر یا برابر {1} باشد", false); err != nil { return } if err = ut.Add("max-items", "{0} باید شامل حداکثر {1} باشد", false); err != nil { return } if err = ut.AddCardinal("max-items-item", "{0} آیتم", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("max-items-item", "{0} آیتم", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("max-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("max-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-items", fe.Field(), c) default: t, err = ut.T("max-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eq", translation: "{0} برابر {1} نمیباشد", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ne", translation: "{0} نباید برابر {1} باشد", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "lt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lt-string", "طول {0} باید کمتر از {1} باشد", false); err != nil { return } if err = ut.AddCardinal("lt-string-character", "{0} کاراکتر", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lt-string-character", "{0} کاراکتر", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-number", "{0} باید کمتر از {1} باشد", false); err != nil { return } if err = ut.Add("lt-items", "{0} باید دارای کمتر از {1} باشد", false); err != nil { return } if err = ut.AddCardinal("lt-items-item", "{0} آیتم", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lt-items-item", "{0} آیتم", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-datetime", "{0} باید قبل از تاریخ و زمان کنونی باشد", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "lte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lte-string", "طول {0} باید حداکثر {1} باشد", false); err != nil { return } if err = ut.AddCardinal("lte-string-character", "{0} کاراکتر", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lte-string-character", "{0} کاراکتر", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-number", "{0} باید کمتر یا برابر {1} باشد", false); err != nil { return } if err = ut.Add("lte-items", "{0} باید حداکثر شامل {1} باشد", false); err != nil { return } if err = ut.AddCardinal("lte-items-item", "{0} آیتم", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lte-items-item", "{0} آیتم", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-datetime", "{0} باید قبل یا برابر تاریخ و زمان کنونی باشد", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gt-string", "طول {0} باید بیشتر از {1} باشد", false); err != nil { return } if err = ut.AddCardinal("gt-string-character", "{0} کاراکتر", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gt-string-character", "{0} کاراکتر", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-number", "{0} باید بیشتر از {1} باشد", false); err != nil { return } if err = ut.Add("gt-items", "{0} باید دارای بیشتر از {1} باشد", false); err != nil { return } if err = ut.AddCardinal("gt-items-item", "{0} آیتم", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gt-items-item", "{0} آیتم", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-datetime", "{0} باید بعد از تاریخ و زمان کنونی باشد", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gte-string", "طول {0} باید حداقل {1} باشد", false); err != nil { return } if err = ut.AddCardinal("gte-string-character", "{0} کاراکتر", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gte-string-character", "{0} کاراکتر", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-number", "{0} باید بیشتر یا برابر {1} باشد", false); err != nil { return } if err = ut.Add("gte-items", "{0} باید شامل حداقل {1} باشد", false); err != nil { return } if err = ut.AddCardinal("gte-items-item", "{0} آیتم", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gte-items-item", "{0} آیتم", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-datetime", "{0} باید بعد یا برابر تاریخ و زمان کنونی باشد", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eqfield", translation: "{0} باید برابر {1} باشد", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "eqcsfield", translation: "{0} باید برابر {1} باشد", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "necsfield", translation: "{0} نمیتواند برابر {1} باشد", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtcsfield", translation: "طول {0} باید بیشتر از {1} باشد", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtecsfield", translation: "طول {0} باید بیشتر یا برابر {1} باشد", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltcsfield", translation: "طول {0} باید کمتر از {1} باشد", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltecsfield", translation: "طول {0} باید کمتر یا برابر {1} باشد", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "nefield", translation: "{0} نمیتواند برابر {1} باشد", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtfield", translation: "طول {0} باید بیشتر از {1} باشد", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtefield", translation: "طول {0} باید بیشتر یا برابر {1} باشد", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltfield", translation: "طول {0} باید کمتر از {1} باشد", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltefield", translation: "طول {0} باید کمتر یا برابر {1} باشد", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "alpha", translation: "{0} میتواند فقط شامل حروف باشد", override: false, }, { tag: "alphanum", translation: "{0} میتواند فقط شامل حروف و اعداد باشد", override: false, }, { tag: "numeric", translation: "{0} باید یک عدد معتبر باشد", override: false, }, { tag: "number", translation: "{0} باید یک عدد معتبر باشد", override: false, }, { tag: "hexadecimal", translation: "{0} باید یک عدد درمبنای16 باشد", override: false, }, { tag: "hexcolor", translation: "{0} باید یک کد رنگ HEX باشد", override: false, }, { tag: "rgb", translation: "{0} باید یک کد رنگ RGB باشد", override: false, }, { tag: "rgba", translation: "{0} باید یک کد رنگ RGBA باشد", override: false, }, { tag: "hsl", translation: "{0} باید یک کد رنگ HSL باشد", override: false, }, { tag: "hsla", translation: "{0} باید یک کد رنگ HSLA باشد", override: false, }, { tag: "e164", translation: "{0} باید یک شماره‌تلفن معتبر با فرمت E.164 باشد", override: false, }, { tag: "email", translation: "{0} باید یک ایمیل معتبر باشد", override: false, }, { tag: "url", translation: "{0} باید یک آدرس اینترنتی معتبر باشد", override: false, }, { tag: "uri", translation: "{0} باید یک URI معتبر باشد", override: false, }, { tag: "base64", translation: "{0} باید یک متن درمبنای64 معتبر باشد", override: false, }, { tag: "contains", translation: "{0} باید شامل '{1}' باشد", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "containsany", translation: "{0} باید شامل کاراکترهای '{1}' باشد", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludes", translation: "{0} نمیتواند شامل '{1}' باشد", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesall", translation: "{0} نمیتواند شامل کاراکترهای '{1}' باشد", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesrune", translation: "{0} نمیتواند شامل '{1}' باشد", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "isbn", translation: "{0} باید یک شابک معتبر باشد", override: false, }, { tag: "isbn10", translation: "{0} باید یک شابک(ISBN-10) معتبر باشد", override: false, }, { tag: "isbn13", translation: "{0} باید یک شابک(ISBN-13) معتبر باشد", override: false, }, { tag: "issn", translation: "{0} باید یک شابک(ISSN) معتبر باشد", override: false, }, { tag: "uuid", translation: "{0} باید یک UUID معتبر باشد", override: false, }, { tag: "uuid3", translation: "{0} باید یک UUID نسخه 3 معتبر باشد", override: false, }, { tag: "uuid4", translation: "{0} باید یک UUID نسخه 4 معتبر باشد", override: false, }, { tag: "uuid5", translation: "{0} باید یک UUID نسخه 5 معتبر باشد", override: false, }, { tag: "ulid", translation: "{0} باید یک ULID معتبر باشد", override: false, }, { tag: "ascii", translation: "{0} باید فقط شامل کاراکترهای اسکی باشد", override: false, }, { tag: "printascii", translation: "{0} باید فقط شامل کاراکترهای اسکی قابل چاپ باشد", override: false, }, { tag: "multibyte", translation: "{0} باید شامل کاراکترهای چندبایته باشد", override: false, }, { tag: "datauri", translation: "{0} باید یک Data URI معتبر باشد", override: false, }, { tag: "latitude", translation: "{0} باید یک عرض جغرافیایی معتبر باشد", override: false, }, { tag: "longitude", translation: "{0} باید یک طول جغرافیایی معتبر باشد", override: false, }, { tag: "ssn", translation: "{0} باید یک شماره SSN معتبر باشد", override: false, }, { tag: "ipv4", translation: "{0} باید یک آدرس آی‌پی IPv4 معتبر باشد", override: false, }, { tag: "ipv6", translation: "{0} باید یک آدرس آی‌پی IPv6 معتبر باشد", override: false, }, { tag: "ip", translation: "{0} باید یک آدرس آی‌پی معتبر باشد", override: false, }, { tag: "cidr", translation: "{0} باید یک نشانه‌گذاری CIDR معتبر باشد", override: false, }, { tag: "cidrv4", translation: "{0} باید یک نشانه‌گذاری CIDR معتبر برای آدرس آی‌پی IPv4 باشد", override: false, }, { tag: "cidrv6", translation: "{0} باید یک نشانه‌گذاری CIDR معتبر برای آدرس آی‌پی IPv6 باشد", override: false, }, { tag: "tcp_addr", translation: "{0} باید یک آدرس TCP معتبر باشد", override: false, }, { tag: "tcp4_addr", translation: "{0} باید یک آدرس TCP IPv4 معتبر باشد", override: false, }, { tag: "tcp6_addr", translation: "{0} باید یک آدرس TCP IPv6 معتبر باشد", override: false, }, { tag: "udp_addr", translation: "{0} باید یک آدرس UDP معتبر باشد", override: false, }, { tag: "udp4_addr", translation: "{0} باید یک آدرس UDP IPv4 معتبر باشد", override: false, }, { tag: "udp6_addr", translation: "{0} باید یک آدرس UDP IPv6 معتبر باشد", override: false, }, { tag: "ip_addr", translation: "{0} باید یک آدرس آی‌پی قابل دسترس باشد", override: false, }, { tag: "ip4_addr", translation: "{0} باید یک آدرس آی‌پی IPv4 قابل دسترس باشد", override: false, }, { tag: "ip6_addr", translation: "{0} باید یک آدرس آی‌پی IPv6 قابل دسترس باشد", override: false, }, { tag: "unix_addr", translation: "{0} باید یک آدرس UNIX معتبر باشد", override: false, }, { tag: "mac", translation: "{0} باید یک مک‌آدرس معتبر باشد", override: false, }, { tag: "unique", translation: "{0} باید شامل مقادیر منحصربفرد باشد", override: false, }, { tag: "iscolor", translation: "{0} باید یک رنگ معتبر باشد", override: false, }, { tag: "oneof", translation: "{0} باید یکی از مقادیر [{1}] باشد", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { s, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return s }, }, { tag: "json", translation: "{0} باید یک json معتبر باشد", override: false, }, { tag: "lowercase", translation: "{0} باید یک متن با حروف کوچک باشد", override: false, }, { tag: "uppercase", translation: "{0} باید یک متن با حروف بزرگ باشد", override: false, }, { tag: "datetime", translation: "فرمت {0} با {1} سازگار نیست", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "postcode_iso3166_alpha2", translation: "{0} یک کدپستی معتبر کشور {1} نیست", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "postcode_iso3166_alpha2_field", translation: "{0} یک کدپستی معتبر کشور فیلد {1} نیست", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "image", translation: "{0} باید یک تصویر معتبر باشد", override: false, }, } for _, t := range translations { if t.customTransFunc != nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, t.customTransFunc) } else if t.customTransFunc != nil && t.customRegisFunc == nil { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), t.customTransFunc) } else if t.customTransFunc == nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, translateFunc) } else { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), translateFunc) } if err != nil { return } } return } func registrationFunc(tag string, translation string, override bool) validator.RegisterTranslationsFunc { return func(ut ut.Translator) (err error) { if err = ut.Add(tag, translation, override); err != nil { return } return } } func translateFunc(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t } golang-github-go-playground-validator-v10-10.30.1/translations/fa/fa_test.go000066400000000000000000000556541512410077000266560ustar00rootroot00000000000000package 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"` ISSN string `validate:"issn"` 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"` Image string `validate:"image"` } 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.ISSN", expected: "ISSN باید یک شابک(ISSN) معتبر باشد", }, { 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 نیست", }, { ns: "Test.Image", expected: "Image باید یک تصویر معتبر باشد", }, } 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)) } } golang-github-go-playground-validator-v10-10.30.1/translations/fr/000077500000000000000000000000001512410077000247045ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/translations/fr/fr.go000066400000000000000000001003371512410077000256460ustar00rootroot00000000000000package fr import ( "fmt" "log" "reflect" "strconv" "strings" "time" "github.com/go-playground/locales" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" ) // RegisterDefaultTranslations registers a set of default translations // for all built in tag's in validator; you may add your own as desired. func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (err error) { translations := []struct { tag string translation string override bool customRegisFunc validator.RegisterTranslationsFunc customTransFunc validator.TranslationFunc }{ { tag: "required", translation: "{0} est un champ obligatoire", override: false, }, { tag: "len", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("len-string", "{0} doit faire une taille de {1}", false); err != nil { return } if err = ut.AddCardinal("len-string-character", "{0} caractère", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("len-string-character", "{0} caractères", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("len-number", "{0} doit être égal à {1}", false); err != nil { return } if err = ut.Add("len-elements", "{0} doit contenir {1}", false); err != nil { return } if err = ut.AddCardinal("len-elements-element", "{0} element", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("len-elements-element", "{0} elements", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("len-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("len-elements-element", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-elements", fe.Field(), c) default: t, err = ut.T("len-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "min", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("min-string", "{0} doit faire une taille minimum de {1}", false); err != nil { return } if err = ut.AddCardinal("min-string-character", "{0} caractère", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("min-string-character", "{0} caractères", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("min-number", "{0} doit être égal à {1} ou plus", false); err != nil { return } if err = ut.Add("min-elements", "{0} doit contenir au moins {1}", false); err != nil { return } if err = ut.AddCardinal("min-elements-element", "{0} element", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("min-elements-element", "{0} elements", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("min-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("min-elements-element", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-elements", fe.Field(), c) default: t, err = ut.T("min-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "max", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("max-string", "{0} doit faire une taille maximum de {1}", false); err != nil { return } if err = ut.AddCardinal("max-string-character", "{0} caractère", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("max-string-character", "{0} caractères", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("max-number", "{0} doit être égal à {1} ou moins", false); err != nil { return } if err = ut.Add("max-elements", "{0} doit contenir au maximum {1}", false); err != nil { return } if err = ut.AddCardinal("max-elements-element", "{0} element", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("max-elements-element", "{0} elements", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("max-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("max-elements-element", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-elements", fe.Field(), c) default: t, err = ut.T("max-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eq", translation: "{0} n'est pas égal à {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ne", translation: "{0} ne doit pas être égal à {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "lt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lt-string", "{0} doit avoir une taille inférieure à {1}", false); err != nil { return } if err = ut.AddCardinal("lt-string-character", "{0} caractère", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lt-string-character", "{0} caractères", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-number", "{0} doit être inférieur à {1}", false); err != nil { return } if err = ut.Add("lt-elements", "{0} doit contenir mois de {1}", false); err != nil { return } if err = ut.AddCardinal("lt-elements-element", "{0} element", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lt-elements-element", "{0} elements", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-datetime", "{0} doit être avant la date et l'heure actuelle", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-elements-element", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-elements", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "lte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lte-string", "{0} doit faire une taille maximum de {1}", false); err != nil { return } if err = ut.AddCardinal("lte-string-character", "{0} caractère", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lte-string-character", "{0} caractères", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-number", "{0} doit faire {1} ou moins", false); err != nil { return } if err = ut.Add("lte-elements", "{0} doit contenir un maximum de {1}", false); err != nil { return } if err = ut.AddCardinal("lte-elements-element", "{0} element", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lte-elements-element", "{0} elements", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-datetime", "{0} doit être avant ou pendant la date et l'heure actuelle", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-elements-element", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-elements", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gt-string", "{0} doit avoir une taille supérieur à {1}", false); err != nil { return } if err = ut.AddCardinal("gt-string-character", "{0} caractère", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gt-string-character", "{0} caractères", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-number", "{0} doit être supérieur à {1}", false); err != nil { return } if err = ut.Add("gt-elements", "{0} doit contenir plus de {1}", false); err != nil { return } if err = ut.AddCardinal("gt-elements-element", "{0} element", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gt-elements-element", "{0} elements", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-datetime", "{0} doit être après la date et l'heure actuelle", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-elements-element", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-elements", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gte-string", "{0} doit faire une taille d'au moins {1}", false); err != nil { return } if err = ut.AddCardinal("gte-string-character", "{0} caractère", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gte-string-character", "{0} caractères", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-number", "{0} doit être {1} ou plus", false); err != nil { return } if err = ut.Add("gte-elements", "{0} doit contenir au moins {1}", false); err != nil { return } if err = ut.AddCardinal("gte-elements-element", "{0} element", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gte-elements-element", "{0} elements", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-datetime", "{0} doit être après ou pendant la date et l'heure actuelle", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-elements-element", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-elements", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eqfield", translation: "{0} doit être égal à {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "eqcsfield", translation: "{0} doit être égal à {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "necsfield", translation: "{0} ne doit pas être égal à {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtcsfield", translation: "{0} doit être supérieur à {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtecsfield", translation: "{0} doit être supérieur ou égal à {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltcsfield", translation: "{0} doit être inférieur à {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltecsfield", translation: "{0} doit être inférieur ou égal à {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "nefield", translation: "{0} ne doit pas être égal à {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtfield", translation: "{0} doit être supérieur à {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtefield", translation: "{0} doit être supérieur ou égal à {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltfield", translation: "{0} doit être inférieur à {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltefield", translation: "{0} doit être inférieur ou égal à {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "alpha", translation: "{0} ne doit contenir que des caractères alphabétiques", override: false, }, { tag: "alphanum", translation: "{0} ne doit contenir que des caractères alphanumériques", override: false, }, { tag: "numeric", translation: "{0} doit être une valeur numérique valide", override: false, }, { tag: "number", translation: "{0} doit être un nombre valid", override: false, }, { tag: "hexadecimal", translation: "{0} doit être une chaîne de caractères au format hexadécimal valide", override: false, }, { tag: "hexcolor", translation: "{0} doit être une couleur au format HEX valide", override: false, }, { tag: "rgb", translation: "{0} doit être une couleur au format RGB valide", override: false, }, { tag: "rgba", translation: "{0} doit être une couleur au format RGBA valide", override: false, }, { tag: "hsl", translation: "{0} doit être une couleur au format HSL valide", override: false, }, { tag: "hsla", translation: "{0} doit être une couleur au format HSLA valide", override: false, }, { tag: "email", translation: "{0} doit être une adresse email valide", override: false, }, { tag: "url", translation: "{0} doit être une URL valide", override: false, }, { tag: "uri", translation: "{0} doit être une URI valide", override: false, }, { tag: "base64", translation: "{0} doit être une chaîne de caractères au format Base64 valide", override: false, }, { tag: "contains", translation: "{0} doit contenir le texte '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "containsany", translation: "{0} doit contenir au moins l' un des caractères suivants '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludes", translation: "{0} ne doit pas contenir le texte '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesall", translation: "{0} ne doit pas contenir l'un des caractères suivants '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesrune", translation: "{0} ne doit pas contenir ce qui suit '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "isbn", translation: "{0} doit être un numéro ISBN valid", override: false, }, { tag: "isbn10", translation: "{0} doit être un numéro ISBN-10 valid", override: false, }, { tag: "isbn13", translation: "{0} doit être un numéro ISBN-13 valid", override: false, }, { tag: "issn", translation: "{0} doit être un numéro ISSN valid", override: false, }, { tag: "uuid", translation: "{0} doit être un UUID valid", override: false, }, { tag: "uuid3", translation: "{0} doit être un UUID version 3 valid", override: false, }, { tag: "uuid4", translation: "{0} doit être un UUID version 4 valid", override: false, }, { tag: "uuid5", translation: "{0} doit être un UUID version 5 valid", override: false, }, { tag: "ulid", translation: "{0} doit être une ULID valide", override: false, }, { tag: "ascii", translation: "{0} ne doit contenir que des caractères ascii", override: false, }, { tag: "printascii", translation: "{0} ne doit contenir que des caractères ascii affichables", override: false, }, { tag: "multibyte", translation: "{0} doit contenir des caractères multioctets", override: false, }, { tag: "datauri", translation: "{0} doit contenir une URI data valide", override: false, }, { tag: "latitude", translation: "{0} doit contenir des coordonnées latitude valides", override: false, }, { tag: "longitude", translation: "{0} doit contenir des coordonnées longitudes valides", override: false, }, { tag: "ssn", translation: "{0} doit être un numéro SSN valide", override: false, }, { tag: "ipv4", translation: "{0} doit être une adressse IPv4 valide", override: false, }, { tag: "ipv6", translation: "{0} doit être une adressse IPv6 valide", override: false, }, { tag: "ip", translation: "{0} doit être une adressse IP valide", override: false, }, { tag: "cidr", translation: "{0} doit contenir une notation CIDR valide", override: false, }, { tag: "cidrv4", translation: "{0} doit contenir une notation CIDR valide pour une adresse IPv4", override: false, }, { tag: "cidrv6", translation: "{0} doit contenir une notation CIDR valide pour une adresse IPv6", override: false, }, { tag: "tcp_addr", translation: "{0} doit être une adressse TCP valide", override: false, }, { tag: "tcp4_addr", translation: "{0} doit être une adressse IPv4 TCP valide", override: false, }, { tag: "tcp6_addr", translation: "{0} doit être une adressse IPv6 TCP valide", override: false, }, { tag: "udp_addr", translation: "{0} doit être une adressse UDP valide", override: false, }, { tag: "udp4_addr", translation: "{0} doit être une adressse IPv4 UDP valide", override: false, }, { tag: "udp6_addr", translation: "{0} doit être une adressse IPv6 UDP valide", override: false, }, { tag: "ip_addr", translation: "{0} doit être une adresse IP résolvable", override: false, }, { tag: "ip4_addr", translation: "{0} doit être une adresse IPv4 résolvable", override: false, }, { tag: "ip6_addr", translation: "{0} doit être une adresse IPv6 résolvable", override: false, }, { tag: "unix_addr", translation: "{0} doit être une adresse UNIX résolvable", override: false, }, { tag: "mac", translation: "{0} doit contenir une adresse MAC valide", override: false, }, { tag: "iscolor", translation: "{0} doit être une couleur valide", override: false, }, { tag: "oneof", translation: "{0} doit être l'un des choix suivants [{1}]", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { s, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return s }, }, { tag: "image", translation: "{0} doit être une image valide", override: false, }, } for _, t := range translations { if t.customTransFunc != nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, t.customTransFunc) } else if t.customTransFunc != nil && t.customRegisFunc == nil { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), t.customTransFunc) } else if t.customTransFunc == nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, translateFunc) } else { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), translateFunc) } if err != nil { return } } return } func registrationFunc(tag string, translation string, override bool) validator.RegisterTranslationsFunc { return func(ut ut.Translator) (err error) { if err = ut.Add(tag, translation, override); err != nil { return } return } } func translateFunc(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t } golang-github-go-playground-validator-v10-10.30.1/translations/fr/fr_test.go000066400000000000000000000456361512410077000267170ustar00rootroot00000000000000package 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"` ISSN string `validate:"issn"` 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"` Image string `validate:"image"` } 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.ISSN", expected: "ISSN doit être un numéro ISSN 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 à 1 113,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 à 1 113,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 à 1 113,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]", }, { ns: "Test.Image", expected: "Image doit être une image valide", }, } 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)) } } golang-github-go-playground-validator-v10-10.30.1/translations/id/000077500000000000000000000000001512410077000246715ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/translations/id/id.go000066400000000000000000001133651512410077000256250ustar00rootroot00000000000000package id import ( "fmt" "log" "reflect" "strconv" "strings" "time" "github.com/go-playground/locales" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" ) // RegisterDefaultTranslations registers a set of default translations // for all built in tag's in validator; you may add your own as desired. func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (err error) { translations := []struct { tag string translation string override bool customRegisFunc validator.RegisterTranslationsFunc customTransFunc validator.TranslationFunc }{ // Field Tags { tag: "eqcsfield", translation: "{0} harus sama dengan {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "eqfield", translation: "{0} harus sama dengan {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "fieldcontains", translation: "{0} harus berisi nilai dari field {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "fieldexcludes", translation: "{0} tidak boleh berisi nilai dari field {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "gtcsfield", translation: "{0} harus lebih besar dari {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "gtecsfield", translation: "{0} harus lebih besar dari atau sama dengan {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "gtefield", translation: "{0} harus lebih besar dari atau sama dengan {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "gtfield", translation: "{0} harus lebih besar dari {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "ltcsfield", translation: "{0} harus kurang dari {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "ltecsfield", translation: "{0} harus kurang dari atau sama dengan {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "ltefield", translation: "{0} harus kurang dari atau sama dengan {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "ltfield", translation: "{0} harus kurang dari {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "necsfield", translation: "{0} tidak sama dengan {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "nefield", translation: "{0} tidak sama dengan {1}", override: false, customTransFunc: translateFuncWithParam, }, // Network Tags { tag: "cidr", translation: "{0} harus berupa notasi CIDR yang valid", override: false, }, { tag: "cidrv4", translation: "{0} harus berupa notasi CIDR IPv4 yang valid", override: false, }, { tag: "cidrv6", translation: "{0} harus berupa notasi CIDR IPv6 yang valid", override: false, }, { tag: "datauri", translation: "{0} harus berisi URI Data yang valid", override: false, }, { tag: "fqdn", translation: "{0} harus berupa FQDN yang valid", override: false, }, { tag: "hostname", translation: "{0} harus berupa hostname sesuai RFC 952 yang valid", override: false, }, { tag: "hostname_port", translation: "{0} harus berupa hostname dan port yang valid", override: false, }, { tag: "hostname_rfc1123", translation: "{0} harus berupa hostname sesuai RFC 1123 yang valid", override: false, }, { tag: "ip", translation: "{0} harus berupa alamat IP yang valid", override: false, }, { tag: "ip4_addr", translation: "{0} harus berupa alamat IPv4 yang valid", override: false, }, { tag: "ip6_addr", translation: "{0} harus berupa alamat IPv6 yang valid", override: false, }, { tag: "ip_addr", translation: "{0} harus berupa alamat IP yang valid", override: false, }, { tag: "ipv4", translation: "{0} harus berupa alamat IPv4 yang valid", override: false, }, { tag: "ipv6", translation: "{0} harus berupa alamat IPv6 yang valid", override: false, }, { tag: "mac", translation: "{0} harus berisi alamat MAC yang valid", override: false, }, { tag: "tcp4_addr", translation: "{0} harus berupa alamat TCP IPv4 yang valid", override: false, }, { tag: "tcp6_addr", translation: "{0} harus berupa alamat TCP IPv6 yang valid", override: false, }, { tag: "tcp_addr", translation: "{0} harus berupa alamat TCP yang valid", override: false, }, { tag: "udp4_addr", translation: "{0} harus berupa alamat IPv4 UDP yang valid", override: false, }, { tag: "udp6_addr", translation: "{0} harus berupa alamat IPv6 UDP yang valid", override: false, }, { tag: "udp_addr", translation: "{0} harus berupa alamat UDP yang valid", override: false, }, { tag: "unix_addr", translation: "{0} harus berupa alamat UNIX yang valid", override: false, }, { tag: "uri", translation: "{0} harus berupa URI yang valid", override: false, }, { tag: "url", translation: "{0} harus berupa URL yang valid", override: false, }, { tag: "http_url", translation: "{0} harus berupa URL HTTP/HTTPS yang valid", override: false, }, { tag: "url_encoded", translation: "{0} harus berupa string URL yang terenkode", override: false, }, { tag: "urn_rfc2141", translation: "{0} harus berupa URN sesuai RFC 2141 yang valid", override: false, }, // Strings Tags { tag: "alpha", translation: "{0} hanya dapat berisi karakter alfanumerik", override: false, }, { tag: "alphanum", translation: "{0} hanya dapat berisi karakter alfanumerik", override: false, }, { tag: "alphanumunicode", translation: "{0} hanya boleh berisi karakter alfanumerik unicode", override: false, }, { tag: "alphaunicode", translation: "{0} hanya boleh berisi karakter alfanumerik unicode", override: false, }, { tag: "ascii", translation: "{0} hanya boleh berisi karakter ASCII", override: false, }, { tag: "boolean", translation: "{0} harus berupa nilai boolean yang valid", override: false, }, { tag: "contains", translation: "{0} harus berisi teks '{1}'", override: false, customTransFunc: translateFuncWithParam, }, { tag: "containsany", translation: "{0} harus berisi setidaknya salah satu karakter berikut '{1}'", override: false, customTransFunc: translateFuncWithParam, }, { tag: "containsrune", translation: "{0} harus berisi setidaknya salah satu karakter berikut '{1}'", override: false, customTransFunc: translateFuncWithParam, }, { tag: "endsnotwith", translation: "{0} tidak boleh diakhiri dengan '{1}'", override: false, customTransFunc: translateFuncWithParam, }, { tag: "endswith", translation: "{0} harus diakhiri dengan '{1}'", override: false, customTransFunc: translateFuncWithParam, }, { tag: "excludes", translation: "{0} tidak boleh berisi teks '{1}'", override: false, customTransFunc: translateFuncWithParam, }, { tag: "excludesall", translation: "{0} tidak boleh berisi salah satu karakter berikut '{1}'", override: false, customTransFunc: translateFuncWithParam, }, { tag: "excludesrune", translation: "{0} tidak boleh berisi '{1}'", override: false, customTransFunc: translateFuncWithParam, }, { tag: "lowercase", translation: "{0} harus berupa string huruf kecil", override: false, }, { tag: "multibyte", translation: "{0} harus berisi karakter multibyte", override: false, }, { tag: "number", translation: "{0} harus berupa angka yang valid", override: false, }, { tag: "numeric", translation: "{0} harus berupa nilai numerik yang valid", override: false, }, { tag: "printascii", translation: "{0} hanya boleh berisi karakter ASCII yang dapat dicetak", override: false, }, { tag: "startsnotwith", translation: "{0} tidak boleh diawali dengan '{1}'", override: false, customTransFunc: translateFuncWithParam, }, { tag: "startswith", translation: "{0} harus diawali dengan '{1}'", override: false, customTransFunc: translateFuncWithParam, }, { tag: "uppercase", translation: "{0} harus berupa string huruf besar", override: false, }, // Format Tags { tag: "hexadecimal", translation: "{0} harus berupa heksadesimal yang valid", override: false, }, { tag: "base64", translation: "{0} harus berupa string Base64 yang valid", override: false, }, { tag: "base64url", translation: "{0} harus berupa string Base64 URL yang valid", override: false, }, { tag: "base64rawurl", translation: "{0} harus berupa string Base64 Raw URL yang valid", override: false, }, { tag: "bic", translation: "{0} harus berupa kode BIC (SWIFT) yang valid sesuai ISO 9362", override: false, }, { tag: "bcp47_language_tag", translation: "{0} harus berupa tag bahasa BCP 47 yang valid", override: false, }, { tag: "btc_addr", translation: "{0} harus berupa alamat Bitcoin yang valid", override: false, }, { tag: "btc_addr_bech32", translation: "{0} harus berupa alamat Bitcoin Bech32 yang valid", override: false, }, { tag: "credit_card", translation: "{0} harus berupa nomor kartu kredit yang valid", override: false, }, { tag: "mongodb", translation: "{0} harus berupa ObjectID MongoDB yang valid", override: false, }, { tag: "mongodb_connection_string", translation: "{0} harus berupa string koneksi MongoDB yang valid", override: false, }, { tag: "cron", translation: "{0} harus berupa ekspresi cron yang valid", override: false, }, { tag: "spicedb", translation: "{0} harus berupa format SpiceDB yang valid", override: false, }, { tag: "datetime", translation: "{0} tidak sesuai dengan format {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "e164", translation: "{0} harus berupa nomor telepon format E.164 yang valid", override: false, }, { tag: "email", translation: "{0} harus berupa alamat email yang valid", override: false, }, { tag: "eth_addr", translation: "{0} harus berupa alamat Ethereum yang valid", override: false, }, { tag: "hexcolor", translation: "{0} harus berupa warna HEX yang valid", override: false, }, { tag: "hsl", translation: "{0} harus berupa warna HSL yang valid", override: false, }, { tag: "hsla", translation: "{0} harus berupa warna HSLA yang valid", override: false, }, { tag: "html", translation: "{0} harus berupa HTML yang valid", override: false, }, { tag: "html_encoded", translation: "{0} harus berupa HTML terenkode yang valid", override: false, }, { tag: "isbn", translation: "{0} harus berupa nomor ISBN yang valid", override: false, }, { tag: "isbn10", translation: "{0} harus berupa nomor ISBN-10 yang valid", override: false, }, { tag: "isbn13", translation: "{0} harus berupa nomor ISBN-13 yang valid", override: false, }, { tag: "issn", translation: "{0} harus berupa nomor ISSN yang valid", override: false, }, { tag: "iso3166_1_alpha2", translation: "{0} harus berupa kode negara ISO 3166-1 alpha-2 yang valid", override: false, }, { tag: "iso3166_1_alpha3", translation: "{0} harus berupa kode negara ISO 3166-1 alpha-3 yang valid", override: false, }, { tag: "iso3166_1_alpha_numeric", translation: "{0} harus berupa kode negara numerik ISO 3166-1 yang valid", override: false, }, { tag: "iso3166_2", translation: "{0} harus berupa kode subdivisi negara ISO 3166-2 yang valid", override: false, }, { tag: "iso4217", translation: "{0} harus berupa kode mata uang ISO 4217 yang valid", override: false, }, { tag: "json", translation: "{0} harus berupa string JSON yang valid", override: false, }, { tag: "jwt", translation: "{0} harus berupa JSON Web Token (JWT) yang valid", override: false, }, { tag: "latitude", translation: "{0} harus berisi koordinat lintang yang valid", override: false, }, { tag: "longitude", translation: "{0} harus berisi koordinat bujur yang valid", override: false, }, { tag: "luhn_checksum", translation: "{0} harus memiliki checksum Luhn yang valid", override: false, }, { tag: "postcode_iso3166_alpha2", translation: "{0} tidak sesuai dengan format kode pos negara {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "postcode_iso3166_alpha2_field", translation: "{0} tidak sesuai dengan format kode pos negara dalam field {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "rgb", translation: "{0} harus berupa warna RGB yang valid", override: false, }, { tag: "rgba", translation: "{0} harus berupa warna RGBA yang valid", override: false, }, { tag: "ssn", translation: "{0} harus berupa nomor SSN (Social Security Number) yang valid", override: false, }, { tag: "timezone", translation: "{0} harus berupa zona waktu yang valid", override: false, }, { tag: "uuid", translation: "{0} harus berupa UUID yang valid", override: false, }, { tag: "uuid3", translation: "{0} harus berupa UUID versi 3 yang valid", override: false, }, { tag: "uuid3_rfc4122", translation: "{0} harus berupa UUID versi 3 RFC4122 yang valid", override: false, }, { tag: "uuid4", translation: "{0} harus berupa UUID versi 4 yang valid", override: false, }, { tag: "uuid4_rfc4122", translation: "{0} harus berupa UUID versi 4 RFC4122 yang valid", override: false, }, { tag: "uuid5", translation: "{0} harus berupa UUID versi 5 yang valid", override: false, }, { tag: "uuid5_rfc4122", translation: "{0} harus berupa UUID versi 5 RFC4122 yang valid", override: false, }, { tag: "uuid_rfc4122", translation: "{0} harus berupa UUID RFC4122 yang valid", override: false, }, { tag: "md4", translation: "{0} harus berupa hash MD4 yang valid", override: false, }, { tag: "md5", translation: "{0} harus berupa hash MD5 yang valid", override: false, }, { tag: "sha256", translation: "{0} harus berupa hash SHA256 yang valid", override: false, }, { tag: "sha384", translation: "{0} harus berupa hash SHA384 yang valid", override: false, }, { tag: "sha512", translation: "{0} harus berupa hash SHA512 yang valid", override: false, }, { tag: "ripemd128", translation: "{0} harus berupa hash RIPEMD128 yang valid", override: false, }, { tag: "ripemd160", translation: "{0} harus berupa hash RIPEMD160 yang valid", override: false, }, { tag: "tiger128", translation: "{0} harus berupa hash TIGER128 yang valid", override: false, }, { tag: "tiger160", translation: "{0} harus berupa hash TIGER160 yang valid", override: false, }, { tag: "tiger192", translation: "{0} harus berupa hash TIGER192 yang valid", override: false, }, { tag: "semver", translation: "{0} harus berupa nomor versi semantik yang valid", override: false, }, { tag: "ulid", translation: "{0} harus berupa ULID yang valid", override: false, }, { tag: "cve", translation: "{0} harus berupa identifikasi CVE yang valid", override: false, }, // Comparisons Tags { tag: "eq", translation: "{0} tidak sama dengan {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "eq_ignore_case", translation: "{0} harus sama dengan {1} (tidak case-sensitive)", override: false, customTransFunc: translateFuncWithParam, }, { tag: "gt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gt-string", "panjang {0} harus lebih dari {1}", false); err != nil { return } if err = ut.AddCardinal("gt-string-character", "{0} karakter", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-number", "{0} harus lebih besar dari {1}", false); err != nil { return } if err = ut.Add("gt-items", "{0} harus berisi lebih dari {1}", false); err != nil { return } if err = ut.AddCardinal("gt-items-item", "{0} item", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-datetime", "{0} harus lebih besar dari tanggal & waktu saat ini", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gte-string", "panjang minimal {0} adalah {1}", false); err != nil { return } if err = ut.AddCardinal("gte-string-character", "{0} karakter", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-number", "{0} harus {1} atau lebih besar", false); err != nil { return } if err = ut.Add("gte-items", "{0} harus berisi setidaknya {1}", false); err != nil { return } if err = ut.AddCardinal("gte-items-item", "{0} item", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-datetime", "{0} harus lebih besar dari atau sama dengan tanggal & waktu saat ini", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "lt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lt-string", "panjang {0} harus kurang dari {1}", false); err != nil { return } if err = ut.AddCardinal("lt-string-character", "{0} karakter", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-number", "{0} harus kurang dari {1}", false); err != nil { return } if err = ut.Add("lt-items", "{0} harus berisi kurang dari {1}", false); err != nil { return } if err = ut.AddCardinal("lt-items-item", "{0} item", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-datetime", "{0} harus kurang dari tanggal & waktu saat ini", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "lte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lte-string", "panjang maksimal {0} adalah {1}", false); err != nil { return } if err = ut.AddCardinal("lte-string-character", "{0} karakter", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-number", "{0} harus {1} atau kurang", false); err != nil { return } if err = ut.Add("lte-items", "{0} harus berisi maksimal {1}", false); err != nil { return } if err = ut.AddCardinal("lte-items-item", "{0} item", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-datetime", "{0} harus kurang dari atau sama dengan tanggal & waktu saat ini", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "ne", translation: "{0} tidak sama dengan {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "ne_ignore_case", translation: "{0} tidak sama dengan {1} (tidak case-sensitive)", override: false, customTransFunc: translateFuncWithParam, }, // Other Tags { tag: "dir", translation: "{0} harus berupa direktori yang ada", override: false, }, { tag: "dirpath", translation: "{0} harus berupa path direktori yang valid", override: false, }, { tag: "file", translation: "{0} harus berupa file yang valid", override: false, }, { tag: "filepath", translation: "{0} harus berupa path file yang valid", override: false, }, { tag: "image", translation: "{0} harus berupa gambar yang valid", override: false, }, { tag: "isdefault", translation: "{0} harus berupa nilai default", override: false, }, { tag: "len", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("len-string", "panjang {0} harus {1}", false); err != nil { return } if err = ut.AddCardinal("len-string-character", "{0} karakter", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("len-number", "{0} harus sama dengan {1}", false); err != nil { return } if err = ut.Add("len-items", "{0} harus berisi {1}", false); err != nil { return } if err = ut.AddCardinal("len-items-item", "{0} item", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("len-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("len-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-items", fe.Field(), c) default: t, err = ut.T("len-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "max", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("max-string", "panjang maksimal {0} adalah {1}", false); err != nil { return } if err = ut.AddCardinal("max-string-character", "{0} karakter", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("max-number", "{0} harus {1} atau kurang", false); err != nil { return } if err = ut.Add("max-items", "{0} harus berisi maksimal {1}", false); err != nil { return } if err = ut.AddCardinal("max-items-item", "{0} item", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("max-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("max-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-items", fe.Field(), c) default: t, err = ut.T("max-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "min", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("min-string", "panjang minimal {0} adalah {1}", false); err != nil { return } if err = ut.AddCardinal("min-string-character", "{0} karakter", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("min-number", "{0} harus {1} atau lebih besar", false); err != nil { return } if err = ut.Add("min-items", "{0} harus berisi minimal {1}", false); err != nil { return } if err = ut.AddCardinal("min-items-item", "{0} item", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("min-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("min-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-items", fe.Field(), c) default: t, err = ut.T("min-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "oneof", translation: "{0} harus berupa salah satu dari [{1}]", override: false, customTransFunc: translateFuncWithParam, }, { tag: "required", translation: "{0} wajib diisi", override: false, }, { tag: "required_if", translation: "{0} wajib diisi jika {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "required_unless", translation: "{0} wajib diisi kecuali {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "required_with", translation: "{0} wajib diisi jika {1} telah diisi", override: false, customTransFunc: translateFuncWithParam, }, { tag: "required_with_all", translation: "{0} wajib diisi jika {1} telah diisi", override: false, customTransFunc: translateFuncWithParam, }, { tag: "required_without", translation: "{0} wajib diisi jika {1} tidak diisi", override: false, customTransFunc: translateFuncWithParam, }, { tag: "required_without_all", translation: "{0} wajib diisi jika {1} tidak diisi", override: false, customTransFunc: translateFuncWithParam, }, { tag: "excluded_if", translation: "{0} tidak boleh diisi jika {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "excluded_unless", translation: "{0} tidak boleh diisi kecuali {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "excluded_with", translation: "{0} tidak boleh diisi jika {1} telah diisi", override: false, customTransFunc: translateFuncWithParam, }, { tag: "excluded_with_all", translation: "{0} tidak boleh diisi jika semua {1} telah diisi", override: false, customTransFunc: translateFuncWithParam, }, { tag: "excluded_without", translation: "{0} tidak boleh diisi jika {1} tidak diisi", override: false, customTransFunc: translateFuncWithParam, }, { tag: "excluded_without_all", translation: "{0} tidak boleh diisi jika {1} tidak diisi", override: false, customTransFunc: translateFuncWithParam, }, { tag: "unique", translation: "{0} harus berisi nilai yang unik", override: false, }, // Aliases Tags { tag: "iscolor", translation: "{0} harus berupa warna yang valid", override: false, }, { tag: "country_code", translation: "{0} harus berupa kode negara yang valid", override: false, }, } // register translations for _, t := range translations { if t.customTransFunc != nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, t.customTransFunc) } else if t.customTransFunc != nil && t.customRegisFunc == nil { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), t.customTransFunc) } else if t.customTransFunc == nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, translateFunc) } else { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), translateFunc) } if err != nil { return } } return } // registrationFunc returns a function that can be used for registering translations func registrationFunc(tag string, translation string, override bool) validator.RegisterTranslationsFunc { return func(ut ut.Translator) (err error) { if err = ut.Add(tag, translation, override); err != nil { return } return } } // translateFunc is the default translation function func translateFunc(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t } // translateFuncWithParam is the default translation function with parameter func translateFuncWithParam(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t } golang-github-go-playground-validator-v10-10.30.1/translations/id/id_test.go000066400000000000000000001301451512410077000266570ustar00rootroot00000000000000package 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" ) // InitValidator initializes a new validator with Indonesian translations func InitValidator() (*validator.Validate, ut.Translator, error) { // setup translator idn := indonesia.New() uni := ut.New(idn, idn) trans, _ := uni.GetTranslator("id") // initialize validator validate := validator.New(validator.WithRequiredStructEnabled()) // register translations err := RegisterDefaultTranslations(validate, trans) if err != nil { return nil, nil, err } return validate, trans, nil } // TestFieldTagsTranslations tests all field tags registered translations for Indonesian language func TestFieldTagsTranslations(t *testing.T) { // init validator with Indonesian translations validate, trans, err := InitValidator() Equal(t, err, nil) // Inner struct for cross-field validations type Inner struct { EqCSFieldString string NeCSFieldString string GtCSFieldString string GteCSFieldString string LtCSFieldString string LteCSFieldString string FieldContains string FieldExcludes string } // TestFieldTags for field validations type TestFieldTags struct { Inner Inner // Equal field validations EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"` EqFieldString string `validate:"eqfield=EqString"` EqString string // Not equal field validations NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"` NeFieldString string `validate:"nefield=NeString"` NeString string // Greater than field validations GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"` GtFieldString string `validate:"gtfield=GtString"` GtString string // Greater than or equal field validations GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"` GteFieldString string `validate:"gtefield=GteString"` GteString string // Less than field validations LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"` LtFieldString string `validate:"ltfield=LtString"` LtString string // Less than or equal field validations LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"` LteFieldString string `validate:"ltefield=LteString"` LteString string // Field contains/excludes validations ContainsField string `validate:"fieldcontains=Inner.FieldContains"` ExcludesField string `validate:"fieldexcludes=Inner.FieldExcludes"` } // init test struct with values test := TestFieldTags{ Inner: Inner{ EqCSFieldString: "equal", NeCSFieldString: "not-equal", GtCSFieldString: "zzz", GteCSFieldString: "zzz", LtCSFieldString: "aaa", LteCSFieldString: "aaa", FieldContains: "contains", FieldExcludes: "excludes", }, EqCSFieldString: "not-equal", // should equal Inner.EqCSFieldString EqFieldString: "not-equal", // should equal EqString EqString: "equal", NeCSFieldString: "not-equal", // should not equal Inner.NeCSFieldString NeFieldString: "same", // should not equal NeString NeString: "same", GtCSFieldString: "aaa", // should be greater than Inner.GtCSFieldString GtFieldString: "aaa", // should be greater than GtString GtString: "zzz", GteCSFieldString: "aaa", // should be greater than or equal to Inner.GteCSFieldString GteFieldString: "aaa", // should be greater than or equal to GteString GteString: "bbbb", // reference value for GteFieldString LtCSFieldString: "zzz", // should be less than Inner.LtCSFieldString LtFieldString: "zzz", // should be less than LtString LtString: "aaa", LteCSFieldString: "zzzzz", // should be less than or equal to Inner.LteCSFieldString LteFieldString: "zzzz", // should be less than or equal to LteString LteString: "yyy", // reference value for LteFieldString ContainsField: "xyz", // should contain Inner.FieldContains ExcludesField: "has-excludes", // should not contain Inner.FieldExcludes } // validate struct err = validate.Struct(test) NotEqual(t, err, nil) // get validation errors errs := err.(validator.ValidationErrors) // verify each expected error message tests := []struct { ns string expected string }{ { ns: "TestFieldTags.EqCSFieldString", expected: "EqCSFieldString harus sama dengan Inner.EqCSFieldString", }, { ns: "TestFieldTags.EqFieldString", expected: "EqFieldString harus sama dengan EqString", }, { ns: "TestFieldTags.NeCSFieldString", expected: "NeCSFieldString tidak sama dengan Inner.NeCSFieldString", }, { ns: "TestFieldTags.NeFieldString", expected: "NeFieldString tidak sama dengan NeString", }, { ns: "TestFieldTags.GtCSFieldString", expected: "GtCSFieldString harus lebih besar dari Inner.GtCSFieldString", }, { ns: "TestFieldTags.GtFieldString", expected: "GtFieldString harus lebih besar dari GtString", }, { ns: "TestFieldTags.GteCSFieldString", expected: "GteCSFieldString harus lebih besar dari atau sama dengan Inner.GteCSFieldString", }, { ns: "TestFieldTags.GteFieldString", expected: "GteFieldString harus lebih besar dari atau sama dengan GteString", }, { ns: "TestFieldTags.LtCSFieldString", expected: "LtCSFieldString harus kurang dari Inner.LtCSFieldString", }, { ns: "TestFieldTags.LtFieldString", expected: "LtFieldString harus kurang dari LtString", }, { ns: "TestFieldTags.LteCSFieldString", expected: "LteCSFieldString harus kurang dari atau sama dengan Inner.LteCSFieldString", }, { ns: "TestFieldTags.LteFieldString", expected: "LteFieldString harus kurang dari atau sama dengan LteString", }, { ns: "TestFieldTags.ContainsField", expected: "ContainsField harus berisi nilai dari field Inner.FieldContains", }, { ns: "TestFieldTags.ExcludesField", expected: "ExcludesField tidak boleh berisi nilai dari field Inner.FieldExcludes", }, } // verify each expected error message for _, tt := range tests { var fe validator.FieldError // find matching field error for _, e := range errs { if tt.ns == e.Namespace() { fe = e break } } NotEqual(t, fe, nil) Equal(t, tt.expected, fe.Translate(trans)) } } // TestNetworkTagsTranslations tests all network tags registered translations for Indonesian language func TestNetworkTagsTranslations(t *testing.T) { // init validator with Indonesian translations validate, trans, err := InitValidator() Equal(t, err, nil) // TestNetworkTags for network validations type TestNetworkTags struct { CIDR string `validate:"cidr"` CIDRv4 string `validate:"cidrv4"` CIDRv6 string `validate:"cidrv6"` DataURI string `validate:"datauri"` FQDN string `validate:"fqdn"` Hostname string `validate:"hostname"` HostnamePort string `validate:"hostname_port"` HostnameRFC1123 string `validate:"hostname_rfc1123"` IP string `validate:"ip"` IP4Addr string `validate:"ip4_addr"` IP6Addr string `validate:"ip6_addr"` IPAddr string `validate:"ip_addr"` IPv4 string `validate:"ipv4"` IPv6 string `validate:"ipv6"` MAC string `validate:"mac"` TCP4Addr string `validate:"tcp4_addr"` TCP6Addr string `validate:"tcp6_addr"` TCPAddr string `validate:"tcp_addr"` UDP4Addr string `validate:"udp4_addr"` UDP6Addr string `validate:"udp6_addr"` UDPAddr string `validate:"udp_addr"` UnixAddr string `validate:"unix_addr"` // can't fail from within Go's net package currently, but maybe in the future URI string `validate:"uri"` URL string `validate:"url"` HTTPURL string `validate:"http_url"` URLEncoded string `validate:"url_encoded"` URN string `validate:"urn_rfc2141"` } // init test struct test := TestNetworkTags{ URLEncoded: "<%az", // invalid URL encoded string } // validate struct err = validate.Struct(test) NotEqual(t, err, nil) // get validation errors errs := err.(validator.ValidationErrors) // verify each expected error message tests := []struct { ns string expected string }{ { ns: "TestNetworkTags.CIDR", expected: "CIDR harus berupa notasi CIDR yang valid", }, { ns: "TestNetworkTags.CIDRv4", expected: "CIDRv4 harus berupa notasi CIDR IPv4 yang valid", }, { ns: "TestNetworkTags.CIDRv6", expected: "CIDRv6 harus berupa notasi CIDR IPv6 yang valid", }, { ns: "TestNetworkTags.DataURI", expected: "DataURI harus berisi URI Data yang valid", }, { ns: "TestNetworkTags.FQDN", expected: "FQDN harus berupa FQDN yang valid", }, { ns: "TestNetworkTags.Hostname", expected: "Hostname harus berupa hostname sesuai RFC 952 yang valid", }, { ns: "TestNetworkTags.HostnamePort", expected: "HostnamePort harus berupa hostname dan port yang valid", }, { ns: "TestNetworkTags.HostnameRFC1123", expected: "HostnameRFC1123 harus berupa hostname sesuai RFC 1123 yang valid", }, { ns: "TestNetworkTags.IP", expected: "IP harus berupa alamat IP yang valid", }, { ns: "TestNetworkTags.IP4Addr", expected: "IP4Addr harus berupa alamat IPv4 yang valid", }, { ns: "TestNetworkTags.IP6Addr", expected: "IP6Addr harus berupa alamat IPv6 yang valid", }, { ns: "TestNetworkTags.IPAddr", expected: "IPAddr harus berupa alamat IP yang valid", }, { ns: "TestNetworkTags.IPv4", expected: "IPv4 harus berupa alamat IPv4 yang valid", }, { ns: "TestNetworkTags.IPv6", expected: "IPv6 harus berupa alamat IPv6 yang valid", }, { ns: "TestNetworkTags.MAC", expected: "MAC harus berisi alamat MAC yang valid", }, { ns: "TestNetworkTags.TCP4Addr", expected: "TCP4Addr harus berupa alamat TCP IPv4 yang valid", }, { ns: "TestNetworkTags.TCP6Addr", expected: "TCP6Addr harus berupa alamat TCP IPv6 yang valid", }, { ns: "TestNetworkTags.TCPAddr", expected: "TCPAddr harus berupa alamat TCP yang valid", }, { ns: "TestNetworkTags.UDP4Addr", expected: "UDP4Addr harus berupa alamat IPv4 UDP yang valid", }, { ns: "TestNetworkTags.UDP6Addr", expected: "UDP6Addr harus berupa alamat IPv6 UDP yang valid", }, { ns: "TestNetworkTags.UDPAddr", expected: "UDPAddr harus berupa alamat UDP yang valid", }, { ns: "TestNetworkTags.URI", expected: "URI harus berupa URI yang valid", }, { ns: "TestNetworkTags.URL", expected: "URL harus berupa URL yang valid", }, { ns: "TestNetworkTags.HTTPURL", expected: "HTTPURL harus berupa URL HTTP/HTTPS yang valid", }, { ns: "TestNetworkTags.URLEncoded", expected: "URLEncoded harus berupa string URL yang terenkode", }, { ns: "TestNetworkTags.URN", expected: "URN harus berupa URN sesuai RFC 2141 yang valid", }, } // verify each expected error message for _, tt := range tests { var fe validator.FieldError // find matching field error for _, e := range errs { if tt.ns == e.Namespace() { fe = e break } } NotEqual(t, fe, nil) Equal(t, tt.expected, fe.Translate(trans)) } } // TestStringTagsTranslations tests all string tags registered translations for Indonesian language func TestStringTagsTranslations(t *testing.T) { // init validator with Indonesian translations validate, trans, err := InitValidator() Equal(t, err, nil) // TestStringTags for string validations type TestStringTags struct { Alpha string `validate:"alpha"` Alphanum string `validate:"alphanum"` AlphanumUni string `validate:"alphanumunicode"` AlphaUni string `validate:"alphaunicode"` ASCII string `validate:"ascii"` Boolean string `validate:"boolean"` Contains string `validate:"contains=test"` ContainsAny string `validate:"containsany=!@#"` ContainsRune string `validate:"containsrune=☺"` EndsNotWith string `validate:"endsnotwith=end"` EndsWith string `validate:"endswith=end"` Excludes string `validate:"excludes=exclude"` ExcludesAll string `validate:"excludesall=!@#"` ExcludesRune string `validate:"excludesrune=☺"` Lowercase string `validate:"lowercase"` Multibyte string `validate:"multibyte"` Number string `validate:"number"` Numeric string `validate:"numeric"` PrintASCII string `validate:"printascii"` StartsNotWith string `validate:"startsnotwith=start"` StartsWith string `validate:"startswith=start"` Uppercase string `validate:"uppercase"` } // init test struct with invalid values test := TestStringTags{ Alpha: "123", // should only contain letters Alphanum: "!@#", // should only contain letters and numbers AlphanumUni: "!@#", // should only contain unicode letters and numbers AlphaUni: "123", // should only contain unicode letters ASCII: "ñ", // should only contain ASCII characters Boolean: "invalid", // should be a valid boolean Contains: "invalid", // should contain "test" ContainsAny: "abc", // should contain any of "!@#" ContainsRune: "abc", // should contain "☺" EndsNotWith: "test-end", // should not end with "end" EndsWith: "test-no-start", // should end with "end" Excludes: "has-exclude-here", // should not contain "exclude" ExcludesAll: "test!@#", // should not contain any of "!@#" ExcludesRune: "test☺here", // should not contain "☺" Lowercase: "TEST", // should be lowercase Multibyte: "abc", // should contain multibyte characters Number: "abc", // should be a valid number Numeric: "abc", // should be numeric PrintASCII: string([]byte{0x7f}), // should only contain printable ASCII StartsNotWith: "start-test", // should not start with "start" StartsWith: "test-no-start", // should start with "start" Uppercase: "test", // should be uppercase } // validate struct err = validate.Struct(test) NotEqual(t, err, nil) // get validation errors errs := err.(validator.ValidationErrors) // verify each expected error message tests := []struct { ns string expected string }{ { ns: "TestStringTags.Alpha", expected: "Alpha hanya dapat berisi karakter alfanumerik", }, { ns: "TestStringTags.Alphanum", expected: "Alphanum hanya dapat berisi karakter alfanumerik", }, { ns: "TestStringTags.AlphanumUni", expected: "AlphanumUni hanya boleh berisi karakter alfanumerik unicode", }, { ns: "TestStringTags.AlphaUni", expected: "AlphaUni hanya boleh berisi karakter alfanumerik unicode", }, { ns: "TestStringTags.ASCII", expected: "ASCII hanya boleh berisi karakter ASCII", }, { ns: "TestStringTags.Boolean", expected: "Boolean harus berupa nilai boolean yang valid", }, { ns: "TestStringTags.Contains", expected: "Contains harus berisi teks 'test'", }, { ns: "TestStringTags.ContainsAny", expected: "ContainsAny harus berisi setidaknya salah satu karakter berikut '!@#'", }, { ns: "TestStringTags.ContainsRune", expected: "ContainsRune harus berisi setidaknya salah satu karakter berikut '☺'", }, { ns: "TestStringTags.EndsNotWith", expected: "EndsNotWith tidak boleh diakhiri dengan 'end'", }, { ns: "TestStringTags.EndsWith", expected: "EndsWith harus diakhiri dengan 'end'", }, { ns: "TestStringTags.Excludes", expected: "Excludes tidak boleh berisi teks 'exclude'", }, { ns: "TestStringTags.ExcludesAll", expected: "ExcludesAll tidak boleh berisi salah satu karakter berikut '!@#'", }, { ns: "TestStringTags.ExcludesRune", expected: "ExcludesRune tidak boleh berisi '☺'", }, { ns: "TestStringTags.Lowercase", expected: "Lowercase harus berupa string huruf kecil", }, { ns: "TestStringTags.Multibyte", expected: "Multibyte harus berisi karakter multibyte", }, { ns: "TestStringTags.Number", expected: "Number harus berupa angka yang valid", }, { ns: "TestStringTags.Numeric", expected: "Numeric harus berupa nilai numerik yang valid", }, { ns: "TestStringTags.PrintASCII", expected: "PrintASCII hanya boleh berisi karakter ASCII yang dapat dicetak", }, { ns: "TestStringTags.StartsNotWith", expected: "StartsNotWith tidak boleh diawali dengan 'start'", }, { ns: "TestStringTags.StartsWith", expected: "StartsWith harus diawali dengan 'start'", }, { ns: "TestStringTags.Uppercase", expected: "Uppercase harus berupa string huruf besar", }, } // verify each expected error message for _, tt := range tests { var fe validator.FieldError // find matching field error for _, e := range errs { if tt.ns == e.Namespace() { fe = e break } } NotEqual(t, fe, nil) Equal(t, tt.expected, fe.Translate(trans)) } } // TestFormatTagsTranslations tests all format tags registered translations for Indonesian language func TestFormatTagsTranslations(t *testing.T) { // init validator with Indonesian translations validate, trans, err := InitValidator() Equal(t, err, nil) // TestFormatTags for format validations type TestFormatTags struct { Hexadecimal string `validate:"hexadecimal"` Base64 string `validate:"base64"` Base64URL string `validate:"base64url"` Base64RawURL string `validate:"base64rawurl"` BIC string `validate:"bic"` BCP47Lang string `validate:"bcp47_language_tag"` BTCAddr string `validate:"btc_addr"` BTCAddrBech32 string `validate:"btc_addr_bech32"` CreditCard string `validate:"credit_card"` MongoDB string `validate:"mongodb"` MongoDBConn string `validate:"mongodb_connection_string"` Cron string `validate:"cron"` SpiceDB string `validate:"spicedb"` DateTime string `validate:"datetime=2006-01-02"` E164 string `validate:"e164"` Email string `validate:"email"` EthAddr string `validate:"eth_addr"` HexColor string `validate:"hexcolor"` HSL string `validate:"hsl"` HSLA string `validate:"hsla"` HTML string `validate:"html"` HTMLEncoded string `validate:"html_encoded"` ISBN string `validate:"isbn"` ISBN10 string `validate:"isbn10"` ISBN13 string `validate:"isbn13"` ISSN string `validate:"issn"` ISO3166Alpha2 string `validate:"iso3166_1_alpha2"` ISO3166Alpha3 string `validate:"iso3166_1_alpha3"` ISO3166AlphaNumeric string `validate:"iso3166_1_alpha_numeric"` ISO31662 string `validate:"iso3166_2"` ISO4217 string `validate:"iso4217"` JSON string `validate:"json"` JWT string `validate:"jwt"` Latitude string `validate:"latitude"` Longitude string `validate:"longitude"` LuhnChecksum string `validate:"luhn_checksum"` PostcodeISO3166Alpha2 string `validate:"postcode_iso3166_alpha2"` PostcodeISO3166Alpha2Field string `validate:"postcode_iso3166_alpha2_field"` RGB string `validate:"rgb"` RGBA string `validate:"rgba"` SSN string `validate:"ssn"` Timezone string `validate:"timezone"` UUID string `validate:"uuid"` UUID3 string `validate:"uuid3"` UUID3RFC4122 string `validate:"uuid3_rfc4122"` UUID4 string `validate:"uuid4"` UUID4RFC4122 string `validate:"uuid4_rfc4122"` UUID5 string `validate:"uuid5"` UUID5RFC4122 string `validate:"uuid5_rfc4122"` UUIDRFC4122 string `validate:"uuid_rfc4122"` MD4 string `validate:"md4"` MD5 string `validate:"md5"` SHA256 string `validate:"sha256"` SHA384 string `validate:"sha384"` SHA512 string `validate:"sha512"` RIPEMD128 string `validate:"ripemd128"` RIPEMD160 string `validate:"ripemd160"` Tiger128 string `validate:"tiger128"` Tiger160 string `validate:"tiger160"` Tiger192 string `validate:"tiger192"` Semver string `validate:"semver"` ULID string `validate:"ulid"` CVE string `validate:"cve"` } // init test struct with invalid values test := TestFormatTags{} // validate struct err = validate.Struct(test) NotEqual(t, err, nil) // get validation errors errs := err.(validator.ValidationErrors) // verify each expected error message tests := []struct { ns string expected string }{ { ns: "TestFormatTags.Hexadecimal", expected: "Hexadecimal harus berupa heksadesimal yang valid", }, { ns: "TestFormatTags.Base64", expected: "Base64 harus berupa string Base64 yang valid", }, { ns: "TestFormatTags.Base64URL", expected: "Base64URL harus berupa string Base64 URL yang valid", }, { ns: "TestFormatTags.Base64RawURL", expected: "Base64RawURL harus berupa string Base64 Raw URL yang valid", }, { ns: "TestFormatTags.BIC", expected: "BIC harus berupa kode BIC (SWIFT) yang valid sesuai ISO 9362", }, { ns: "TestFormatTags.BCP47Lang", expected: "BCP47Lang harus berupa tag bahasa BCP 47 yang valid", }, { ns: "TestFormatTags.BTCAddr", expected: "BTCAddr harus berupa alamat Bitcoin yang valid", }, { ns: "TestFormatTags.BTCAddrBech32", expected: "BTCAddrBech32 harus berupa alamat Bitcoin Bech32 yang valid", }, { ns: "TestFormatTags.CreditCard", expected: "CreditCard harus berupa nomor kartu kredit yang valid", }, { ns: "TestFormatTags.MongoDB", expected: "MongoDB harus berupa ObjectID MongoDB yang valid", }, { ns: "TestFormatTags.MongoDBConn", expected: "MongoDBConn harus berupa string koneksi MongoDB yang valid", }, { ns: "TestFormatTags.Cron", expected: "Cron harus berupa ekspresi cron yang valid", }, { ns: "TestFormatTags.SpiceDB", expected: "SpiceDB harus berupa format SpiceDB yang valid", }, { ns: "TestFormatTags.DateTime", expected: "DateTime tidak sesuai dengan format 2006-01-02", }, { ns: "TestFormatTags.E164", expected: "E164 harus berupa nomor telepon format E.164 yang valid", }, { ns: "TestFormatTags.Email", expected: "Email harus berupa alamat email yang valid", }, { ns: "TestFormatTags.EthAddr", expected: "EthAddr harus berupa alamat Ethereum yang valid", }, { ns: "TestFormatTags.HexColor", expected: "HexColor harus berupa warna HEX yang valid", }, { ns: "TestFormatTags.HSL", expected: "HSL harus berupa warna HSL yang valid", }, { ns: "TestFormatTags.HSLA", expected: "HSLA harus berupa warna HSLA yang valid", }, { ns: "TestFormatTags.HTML", expected: "HTML harus berupa HTML yang valid", }, { ns: "TestFormatTags.HTMLEncoded", expected: "HTMLEncoded harus berupa HTML terenkode yang valid", }, { ns: "TestFormatTags.ISBN", expected: "ISBN harus berupa nomor ISBN yang valid", }, { ns: "TestFormatTags.ISBN10", expected: "ISBN10 harus berupa nomor ISBN-10 yang valid", }, { ns: "TestFormatTags.ISBN13", expected: "ISBN13 harus berupa nomor ISBN-13 yang valid", }, { ns: "TestFormatTags.ISSN", expected: "ISSN harus berupa nomor ISSN yang valid", }, { ns: "TestFormatTags.ISO3166Alpha2", expected: "ISO3166Alpha2 harus berupa kode negara ISO 3166-1 alpha-2 yang valid", }, { ns: "TestFormatTags.ISO3166Alpha3", expected: "ISO3166Alpha3 harus berupa kode negara ISO 3166-1 alpha-3 yang valid", }, { ns: "TestFormatTags.ISO3166AlphaNumeric", expected: "ISO3166AlphaNumeric harus berupa kode negara numerik ISO 3166-1 yang valid", }, { ns: "TestFormatTags.ISO31662", expected: "ISO31662 harus berupa kode subdivisi negara ISO 3166-2 yang valid", }, { ns: "TestFormatTags.ISO4217", expected: "ISO4217 harus berupa kode mata uang ISO 4217 yang valid", }, { ns: "TestFormatTags.JSON", expected: "JSON harus berupa string JSON yang valid", }, { ns: "TestFormatTags.JWT", expected: "JWT harus berupa JSON Web Token (JWT) yang valid", }, { ns: "TestFormatTags.Latitude", expected: "Latitude harus berisi koordinat lintang yang valid", }, { ns: "TestFormatTags.Longitude", expected: "Longitude harus berisi koordinat bujur yang valid", }, { ns: "TestFormatTags.LuhnChecksum", expected: "LuhnChecksum harus memiliki checksum Luhn yang valid", }, { ns: "TestFormatTags.PostcodeISO3166Alpha2", expected: "PostcodeISO3166Alpha2 tidak sesuai dengan format kode pos negara ", }, { ns: "TestFormatTags.PostcodeISO3166Alpha2Field", expected: "PostcodeISO3166Alpha2Field tidak sesuai dengan format kode pos negara dalam field ", }, { ns: "TestFormatTags.RGB", expected: "RGB harus berupa warna RGB yang valid", }, { ns: "TestFormatTags.RGBA", expected: "RGBA harus berupa warna RGBA yang valid", }, { ns: "TestFormatTags.SSN", expected: "SSN harus berupa nomor SSN (Social Security Number) yang valid", }, { ns: "TestFormatTags.Timezone", expected: "Timezone harus berupa zona waktu yang valid", }, { ns: "TestFormatTags.UUID", expected: "UUID harus berupa UUID yang valid", }, { ns: "TestFormatTags.UUID3", expected: "UUID3 harus berupa UUID versi 3 yang valid", }, { ns: "TestFormatTags.UUID3RFC4122", expected: "UUID3RFC4122 harus berupa UUID versi 3 RFC4122 yang valid", }, { ns: "TestFormatTags.UUID4", expected: "UUID4 harus berupa UUID versi 4 yang valid", }, { ns: "TestFormatTags.UUID4RFC4122", expected: "UUID4RFC4122 harus berupa UUID versi 4 RFC4122 yang valid", }, { ns: "TestFormatTags.UUID5", expected: "UUID5 harus berupa UUID versi 5 yang valid", }, { ns: "TestFormatTags.UUID5RFC4122", expected: "UUID5RFC4122 harus berupa UUID versi 5 RFC4122 yang valid", }, { ns: "TestFormatTags.UUIDRFC4122", expected: "UUIDRFC4122 harus berupa UUID RFC4122 yang valid", }, { ns: "TestFormatTags.MD4", expected: "MD4 harus berupa hash MD4 yang valid", }, { ns: "TestFormatTags.MD5", expected: "MD5 harus berupa hash MD5 yang valid", }, { ns: "TestFormatTags.SHA256", expected: "SHA256 harus berupa hash SHA256 yang valid", }, { ns: "TestFormatTags.SHA384", expected: "SHA384 harus berupa hash SHA384 yang valid", }, { ns: "TestFormatTags.SHA512", expected: "SHA512 harus berupa hash SHA512 yang valid", }, { ns: "TestFormatTags.RIPEMD128", expected: "RIPEMD128 harus berupa hash RIPEMD128 yang valid", }, { ns: "TestFormatTags.RIPEMD160", expected: "RIPEMD160 harus berupa hash RIPEMD160 yang valid", }, { ns: "TestFormatTags.Tiger128", expected: "Tiger128 harus berupa hash TIGER128 yang valid", }, { ns: "TestFormatTags.Tiger160", expected: "Tiger160 harus berupa hash TIGER160 yang valid", }, { ns: "TestFormatTags.Tiger192", expected: "Tiger192 harus berupa hash TIGER192 yang valid", }, { ns: "TestFormatTags.Semver", expected: "Semver harus berupa nomor versi semantik yang valid", }, { ns: "TestFormatTags.ULID", expected: "ULID harus berupa ULID yang valid", }, { ns: "TestFormatTags.CVE", expected: "CVE harus berupa identifikasi CVE yang valid", }, } // verify each expected error message for _, tt := range tests { var fe validator.FieldError // find matching field error for _, e := range errs { if tt.ns == e.Namespace() { fe = e break } } NotEqual(t, fe, nil) Equal(t, tt.expected, fe.Translate(trans)) } } // TestComparisonTagsTranslations tests all comparison tags registered translations for Indonesian language func TestComparisonTagsTranslations(t *testing.T) { // init validator with Indonesian translations validate, trans, err := InitValidator() Equal(t, err, nil) // TestComparisonTags for comparison validations type TestComparisonTags struct { // Equal comparisons EqString string `validate:"eq=test"` EqNumber int `validate:"eq=10"` EqIgnoreCase string `validate:"eq_ignore_case=Test"` // Not equal comparisons NeString string `validate:"ne=test"` NeNumber int `validate:"ne=10"` NeIgnoreCase string `validate:"ne_ignore_case=Test"` // Greater than comparisons GtString string `validate:"gt=5"` // length > 5 GtNumber float64 `validate:"gt=10.5"` GtTime time.Time `validate:"gt"` GtSlice []string `validate:"gt=1"` // length > 1 // Greater than or equal comparisons GteString string `validate:"gte=5"` // length >= 5 GteNumber float64 `validate:"gte=10.5"` GteTime time.Time `validate:"gte"` GteSlice []string `validate:"gte=1"` // length >= 1 // Less than comparisons LtString string `validate:"lt=5"` // length < 5 LtNumber float64 `validate:"lt=10.5"` LtTime time.Time `validate:"lt"` LtSlice []string `validate:"lt=2"` // length < 1 // Less than or equal comparisons LteString string `validate:"lte=5"` // length <= 5 LteNumber float64 `validate:"lte=10.5"` LteTime time.Time `validate:"lte"` LteSlice []string `validate:"lte=1"` // length <= 1 } // init test struct with invalid values now := time.Now() test := TestComparisonTags{ EqString: "not-test", EqNumber: 20, EqIgnoreCase: "not-test", NeString: "test", NeNumber: 10, NeIgnoreCase: "Test", GtString: "abc", // length = 3, should be > 5 GtNumber: 5.5, // should be > 10.5 GtTime: now.Add(-time.Hour), // should be > now GteString: "abc", // length = 3, should be >= 5 GteNumber: 5.5, // should be >= 10.5 GteTime: now.Add(-time.Hour), // should be >= now LtString: "toolong", // length = 7, should be < 5 LtNumber: 15.5, // should be < 10.5 LtTime: now.Add(time.Hour), // should be < now LtSlice: []string{"satu", "dua"}, // should be < 2 LteString: "toolong", // length = 7, should be <= 5 LteNumber: 15.5, // should be <= 10.5 LteTime: now.Add(time.Hour), // should be <= now LteSlice: []string{"satu", "dua"}, // should be <= 1 } // validate struct err = validate.Struct(test) NotEqual(t, err, nil) // get validation errors errs := err.(validator.ValidationErrors) // verify each expected error message tests := []struct { ns string expected string }{ { ns: "TestComparisonTags.EqString", expected: "EqString tidak sama dengan test", }, { ns: "TestComparisonTags.EqNumber", expected: "EqNumber tidak sama dengan 10", }, { ns: "TestComparisonTags.EqIgnoreCase", expected: "EqIgnoreCase harus sama dengan Test (tidak case-sensitive)", }, { ns: "TestComparisonTags.NeString", expected: "NeString tidak sama dengan test", }, { ns: "TestComparisonTags.NeNumber", expected: "NeNumber tidak sama dengan 10", }, { ns: "TestComparisonTags.NeIgnoreCase", expected: "NeIgnoreCase tidak sama dengan Test (tidak case-sensitive)", }, { ns: "TestComparisonTags.GtString", expected: "panjang GtString harus lebih dari 5 karakter", }, { ns: "TestComparisonTags.GtNumber", expected: "GtNumber harus lebih besar dari 10,5", }, { ns: "TestComparisonTags.GtTime", expected: "GtTime harus lebih besar dari tanggal & waktu saat ini", }, { ns: "TestComparisonTags.GtSlice", expected: "GtSlice harus berisi lebih dari 1 item", }, { ns: "TestComparisonTags.GteString", expected: "panjang minimal GteString adalah 5 karakter", }, { ns: "TestComparisonTags.GteNumber", expected: "GteNumber harus 10,5 atau lebih besar", }, { ns: "TestComparisonTags.GteTime", expected: "GteTime harus lebih besar dari atau sama dengan tanggal & waktu saat ini", }, { ns: "TestComparisonTags.GteSlice", expected: "GteSlice harus berisi setidaknya 1 item", }, { ns: "TestComparisonTags.LtString", expected: "panjang LtString harus kurang dari 5 karakter", }, { ns: "TestComparisonTags.LtNumber", expected: "LtNumber harus kurang dari 10,5", }, { ns: "TestComparisonTags.LtTime", expected: "LtTime harus kurang dari tanggal & waktu saat ini", }, { ns: "TestComparisonTags.LtSlice", expected: "LtSlice harus berisi kurang dari 2 item", }, { ns: "TestComparisonTags.LteString", expected: "panjang maksimal LteString adalah 5 karakter", }, { ns: "TestComparisonTags.LteNumber", expected: "LteNumber harus 10,5 atau kurang", }, { ns: "TestComparisonTags.LteTime", expected: "LteTime harus kurang dari atau sama dengan tanggal & waktu saat ini", }, { ns: "TestComparisonTags.LteSlice", expected: "LteSlice harus berisi maksimal 1 item", }, } // verify each expected error message for _, tt := range tests { var fe validator.FieldError // find matching field error for _, e := range errs { if tt.ns == e.Namespace() { fe = e break } } NotEqual(t, fe, nil) Equal(t, tt.expected, fe.Translate(trans)) } } // TestOtherTagsTranslations tests all other tags registered translations for Indonesian language func TestOtherTagsTranslations(t *testing.T) { // init validator with Indonesian translations validate, trans, err := InitValidator() Equal(t, err, nil) // TestOtherTags for other validations type Inner struct { RequiredWith string ExcludedWith string Field string } type TestOtherTags struct { Dir string `validate:"dir"` DirPath string `validate:"dirpath"` File string `validate:"file"` FilePath string `validate:"filepath"` Image string `validate:"image"` LenString string `validate:"len=5"` LenSlice []string `validate:"len=3"` LenNumber int `validate:"len=10"` MinString string `validate:"min=3"` MinSlice []string `validate:"min=1"` MaxString string `validate:"max=5"` MaxSlice []string `validate:"max=1"` IsDefault string `validate:"isdefault"` Required string `validate:"required"` RequiredIf string `validate:"required_if=Inner.RequiredWith value"` RequiredUnless string `validate:"required_unless=Inner.RequiredWith values"` RequiredWith string `validate:"required_with=Inner.RequiredWith"` RequiredWithAll string `validate:"required_with_all=Inner.RequiredWith"` RequiredWithout string `validate:"required_without=Inner.ExcludedWith"` RequiredWithoutAll string `validate:"required_without_all=Inner.ExcludedWith"` ExcludedIf string `validate:"excluded_if=Inner.RequiredWith value"` ExcludedUnless string `validate:"excluded_unless=Inner.ExcludedWith value"` ExcludedWith string `validate:"excluded_with=Inner.RequiredWith"` ExcludedWithAll string `validate:"excluded_with_all=Inner.RequiredWith"` ExcludedWithout string `validate:"excluded_without=Inner.ExcludedWith"` ExcludedWithoutAll string `validate:"excluded_without_all=Inner.ExcludedWith"` OneOf string `validate:"oneof=red green blue"` Unique []string `validate:"unique"` Inner Inner } // init test struct with invalid values test := TestOtherTags{ Dir: "nonexistent", DirPath: "invalid/dir/path", File: "nonexistent.txt", Image: "not-an-image.txt", LenString: "toolong", // should be exactly 5 chars LenSlice: []string{"a", "b"}, // should be exactly 3 items LenNumber: 5, // should be 10 MinString: "ab", // should be min 3 chars MinSlice: []string{}, // should be min 1 item MaxString: "toolong", // should be max 5 chars MaxSlice: []string{"satu", "dua"}, // should be max 1 item IsDefault: "non-default", ExcludedIf: "value", // should fail when Inner.RequiredWith is "value" ExcludedUnless: "value", // should fail unless Inner.ExcludedWith is "value" ExcludedWith: "value", // should fail when Inner.Field is populated ExcludedWithAll: "value", // should fail when both Inner.Field and Inner.ExcludedWith are populated ExcludedWithout: "value", // should fail when Inner.ExcludedWith is not populated ExcludedWithoutAll: "value", // should fail when Inner.ExcludedWithoutAll is not populated OneOf: "yellow", // not in [red green blue] Unique: []string{"a", "a"}, // contains duplicate Inner: Inner{ RequiredWith: "value", // triggers required_if validation ExcludedWith: "", // triggers excluded_unless validation }, } // validate struct err = validate.Struct(test) NotEqual(t, err, nil) // get validation errors errs := err.(validator.ValidationErrors) // verify each expected error message tests := []struct { ns string expected string }{ { ns: "TestOtherTags.Dir", expected: "Dir harus berupa direktori yang ada", }, { ns: "TestOtherTags.DirPath", expected: "DirPath harus berupa path direktori yang valid", }, { ns: "TestOtherTags.File", expected: "File harus berupa file yang valid", }, { ns: "TestOtherTags.FilePath", expected: "FilePath harus berupa path file yang valid", }, { ns: "TestOtherTags.Image", expected: "Image harus berupa gambar yang valid", }, { ns: "TestOtherTags.LenString", expected: "panjang LenString harus 5 karakter", }, { ns: "TestOtherTags.LenSlice", expected: "LenSlice harus berisi 3 item", }, { ns: "TestOtherTags.LenNumber", expected: "LenNumber harus sama dengan 10", }, { ns: "TestOtherTags.MinString", expected: "panjang minimal MinString adalah 3 karakter", }, { ns: "TestOtherTags.MinSlice", expected: "MinSlice harus berisi minimal 1 item", }, { ns: "TestOtherTags.MaxString", expected: "panjang maksimal MaxString adalah 5 karakter", }, { ns: "TestOtherTags.MaxSlice", expected: "MaxSlice harus berisi maksimal 1 item", }, { ns: "TestOtherTags.IsDefault", expected: "IsDefault harus berupa nilai default", }, { ns: "TestOtherTags.Required", expected: "Required wajib diisi", }, { ns: "TestOtherTags.RequiredIf", expected: "RequiredIf wajib diisi jika Inner.RequiredWith value", }, { ns: "TestOtherTags.RequiredUnless", expected: "RequiredUnless wajib diisi kecuali Inner.RequiredWith values", }, { ns: "TestOtherTags.RequiredWith", expected: "RequiredWith wajib diisi jika Inner.RequiredWith telah diisi", }, { ns: "TestOtherTags.RequiredWithAll", expected: "RequiredWithAll wajib diisi jika Inner.RequiredWith telah diisi", }, { ns: "TestOtherTags.RequiredWithout", expected: "RequiredWithout wajib diisi jika Inner.ExcludedWith tidak diisi", }, { ns: "TestOtherTags.RequiredWithoutAll", expected: "RequiredWithoutAll wajib diisi jika Inner.ExcludedWith tidak diisi", }, { ns: "TestOtherTags.ExcludedIf", expected: "ExcludedIf tidak boleh diisi jika Inner.RequiredWith value", }, { ns: "TestOtherTags.ExcludedUnless", expected: "ExcludedUnless tidak boleh diisi kecuali Inner.ExcludedWith value", }, { ns: "TestOtherTags.ExcludedWith", expected: "ExcludedWith tidak boleh diisi jika Inner.RequiredWith telah diisi", }, { ns: "TestOtherTags.ExcludedWithAll", expected: "ExcludedWithAll tidak boleh diisi jika semua Inner.RequiredWith telah diisi", }, { ns: "TestOtherTags.ExcludedWithout", expected: "ExcludedWithout tidak boleh diisi jika Inner.ExcludedWith tidak diisi", }, { ns: "TestOtherTags.ExcludedWithoutAll", expected: "ExcludedWithoutAll tidak boleh diisi jika Inner.ExcludedWith tidak diisi", }, { ns: "TestOtherTags.OneOf", expected: "OneOf harus berupa salah satu dari [red green blue]", }, { ns: "TestOtherTags.Unique", expected: "Unique harus berisi nilai yang unik", }, } // verify each expected error message for _, tt := range tests { var fe validator.FieldError // find matching field error for _, e := range errs { if tt.ns == e.Namespace() { fe = e break } } NotEqual(t, fe, nil) Equal(t, tt.expected, fe.Translate(trans)) } } // TestAliasesTagsTranslations tests all aliases tags registered translations for Indonesian language func TestAliasesTagsTranslations(t *testing.T) { // init validator with Indonesian translations validate, trans, err := InitValidator() Equal(t, err, nil) // TestAliasTags for alias validations type TestAliasTags struct { // Color validations Color string `validate:"iscolor"` HexColor string `validate:"hexcolor"` RGBColor string `validate:"rgb"` RGBAColor string `validate:"rgba"` HSLColor string `validate:"hsl"` HSLAColor string `validate:"hsla"` // Country code validation CountryCode string `validate:"country_code"` ISO2Code string `validate:"iso3166_1_alpha2"` ISO3Code string `validate:"iso3166_1_alpha3"` } // init test struct with invalid values test := TestAliasTags{ Color: "not-a-color", HexColor: "not-hex", RGBColor: "not-rgb", RGBAColor: "not-rgba", HSLColor: "not-hsl", HSLAColor: "not-hsla", CountryCode: "XX", // invalid country code ISO2Code: "XX", // invalid ISO 3166-1 alpha-2 ISO3Code: "XXX", // invalid ISO 3166-1 alpha-3 } // validate struct err = validate.Struct(test) NotEqual(t, err, nil) // get validation errors errs := err.(validator.ValidationErrors) // verify each expected error message tests := []struct { ns string expected string }{ { ns: "TestAliasTags.Color", expected: "Color harus berupa warna yang valid", }, { ns: "TestAliasTags.HexColor", expected: "HexColor harus berupa warna HEX yang valid", }, { ns: "TestAliasTags.RGBColor", expected: "RGBColor harus berupa warna RGB yang valid", }, { ns: "TestAliasTags.RGBAColor", expected: "RGBAColor harus berupa warna RGBA yang valid", }, { ns: "TestAliasTags.HSLColor", expected: "HSLColor harus berupa warna HSL yang valid", }, { ns: "TestAliasTags.HSLAColor", expected: "HSLAColor harus berupa warna HSLA yang valid", }, { ns: "TestAliasTags.CountryCode", expected: "CountryCode harus berupa kode negara yang valid", }, } // verify each expected error message for _, tt := range tests { var fe validator.FieldError // find matching field error for _, e := range errs { if tt.ns == e.Namespace() { fe = e break } } NotEqual(t, fe, nil) Equal(t, tt.expected, fe.Translate(trans)) } } golang-github-go-playground-validator-v10-10.30.1/translations/it/000077500000000000000000000000001512410077000247115ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/translations/it/it.go000066400000000000000000000737431512410077000256720ustar00rootroot00000000000000package it import ( "fmt" "log" "reflect" "strconv" "strings" "time" "github.com/go-playground/locales" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" ) // RegisterDefaultTranslations registers a set of default translations // for all built in tag's in validator; you may add your own as desired. func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (err error) { translations := []struct { tag string translation string override bool customRegisFunc validator.RegisterTranslationsFunc customTransFunc validator.TranslationFunc }{ { tag: "required", translation: "{0} è un campo obbligatorio", override: false, }, { tag: "required_without", translation: "{0} è un campo obbligatorio", override: false, }, { tag: "len", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("len-string", "{0} deve essere lungo {1}", false); err != nil { return } if err = ut.AddCardinal("len-string-character", "{0} carattere", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("len-string-character", "{0} caratteri", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("len-number", "{0} deve essere uguale a {1}", false); err != nil { return } if err = ut.Add("len-items", "{0} deve contenere {1}", false); err != nil { return } if err = ut.AddCardinal("len-items-item", "{0} elemento", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("len-items-item", "{0} elementi", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("len-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("len-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-items", fe.Field(), c) default: t, err = ut.T("len-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "min", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("min-string", "{0} deve essere lungo almeno {1}", false); err != nil { return } if err = ut.AddCardinal("min-string-character", "{0} carattere", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("min-string-character", "{0} caratteri", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("min-number", "{0} deve essere maggiore o uguale a {1}", false); err != nil { return } if err = ut.Add("min-items", "{0} deve contenere almeno {1}", false); err != nil { return } if err = ut.AddCardinal("min-items-item", "{0} elemento", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("min-items-item", "{0} elementi", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("min-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("min-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-items", fe.Field(), c) default: t, err = ut.T("min-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "max", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("max-string", "{0} deve essere lungo al massimo {1}", false); err != nil { return } if err = ut.AddCardinal("max-string-character", "{0} carattere", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("max-string-character", "{0} caratteri", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("max-number", "{0} deve essere minore o uguale a {1}", false); err != nil { return } if err = ut.Add("max-items", "{0} deve contenere al massimo {1}", false); err != nil { return } if err = ut.AddCardinal("max-items-item", "{0} elemento", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("max-items-item", "{0} elementi", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("max-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("max-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-items", fe.Field(), c) default: t, err = ut.T("max-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eq", translation: "{0} non è uguale a {1}", override: false, customTransFunc: customTransFuncV1, }, { tag: "ne", translation: "{0} deve essere diverso da {1}", override: false, customTransFunc: customTransFuncV1, }, { tag: "lt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lt-string", "{0} deve essere lungo meno di {1}", false); err != nil { return } if err = ut.AddCardinal("lt-string-character", "{0} carattere", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lt-string-character", "{0} caratteri", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-number", "{0} deve essere minore di {1}", false); err != nil { return } if err = ut.Add("lt-items", "{0} deve contenere meno di {1}", false); err != nil { return } if err = ut.AddCardinal("lt-items-item", "{0} elemento", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lt-items-item", "{0} elementi", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-datetime", "{0} deve essere precedente alla Data/Ora corrente", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "lte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lte-string", "{0} deve essere lungo al massimo {1}", false); err != nil { return } if err = ut.AddCardinal("lte-string-character", "{0} carattere", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lte-string-character", "{0} caratteri", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-number", "{0} deve essere minore o uguale a {1}", false); err != nil { return } if err = ut.Add("lte-items", "{0} deve contenere al massimo {1}", false); err != nil { return } if err = ut.AddCardinal("lte-items-item", "{0} elemento", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lte-items-item", "{0} elementi", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-datetime", "{0} deve essere uguale o precedente alla Data/Ora corrente", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gt-string", "{0} deve essere lungo più di {1}", false); err != nil { return } if err = ut.AddCardinal("gt-string-character", "{0} carattere", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gt-string-character", "{0} caratteri", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-number", "{0} deve essere maggiore di {1}", false); err != nil { return } if err = ut.Add("gt-items", "{0} deve contenere più di {1}", false); err != nil { return } if err = ut.AddCardinal("gt-items-item", "{0} elemento", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gt-items-item", "{0} elementi", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-datetime", "{0} deve essere successivo alla Data/Ora corrente", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gte-string", "{0} deve essere lungo almeno {1}", false); err != nil { return } if err = ut.AddCardinal("gte-string-character", "{0} carattere", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gte-string-character", "{0} caratteri", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-number", "{0} deve essere maggiore o uguale a {1}", false); err != nil { return } if err = ut.Add("gte-items", "{0} deve contenere almeno {1}", false); err != nil { return } if err = ut.AddCardinal("gte-items-item", "{0} elemento", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gte-items-item", "{0} elementi", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-datetime", "{0} deve essere uguale o successivo alla Data/Ora corrente", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eqfield", translation: "{0} deve essere uguale a {1}", override: false, customTransFunc: customTransFuncV1, }, { tag: "eqcsfield", translation: "{0} deve essere uguale a {1}", override: false, customTransFunc: customTransFuncV1, }, { tag: "necsfield", translation: "{0} deve essere diverso da {1}", override: false, customTransFunc: customTransFuncV1, }, { tag: "gtcsfield", translation: "{0} deve essere maggiore di {1}", override: false, customTransFunc: customTransFuncV1, }, { tag: "gtecsfield", translation: "{0} deve essere maggiore o uguale a {1}", override: false, customTransFunc: customTransFuncV1, }, { tag: "ltcsfield", translation: "{0} deve essere minore di {1}", override: false, customTransFunc: customTransFuncV1, }, { tag: "ltecsfield", translation: "{0} deve essere minore o uguale a {1}", override: false, customTransFunc: customTransFuncV1, }, { tag: "nefield", translation: "{0} deve essere diverso da {1}", override: false, customTransFunc: customTransFuncV1, }, { tag: "gtfield", translation: "{0} deve essere maggiore di {1}", override: false, customTransFunc: customTransFuncV1, }, { tag: "gtefield", translation: "{0} deve essere maggiore o uguale a {1}", override: false, customTransFunc: customTransFuncV1, }, { tag: "ltfield", translation: "{0} deve essere minore di {1}", override: false, customTransFunc: customTransFuncV1, }, { tag: "ltefield", translation: "{0} deve essere minore o uguale a {1}", override: false, customTransFunc: customTransFuncV1, }, { tag: "alpha", translation: "{0} può contenere solo caratteri alfabetici", override: false, }, { tag: "alphanum", translation: "{0} può contenere solo caratteri alfanumerici", override: false, }, { tag: "numeric", translation: "{0} deve essere un valore numerico valido", override: false, }, { tag: "number", translation: "{0} deve essere un numero valido", override: false, }, { tag: "hexadecimal", translation: "{0} deve essere un esadecimale valido", override: false, }, { tag: "hexcolor", translation: "{0} deve essere un colore HEX valido", override: false, }, { tag: "rgb", translation: "{0} deve essere un colore RGB valido", override: false, }, { tag: "rgba", translation: "{0} deve essere un colore RGBA valido", override: false, }, { tag: "hsl", translation: "{0} deve essere un colore HSL valido", override: false, }, { tag: "hsla", translation: "{0} deve essere un colore HSLA valido", override: false, }, { tag: "e164", translation: "{0} deve essere un numero telefonico in formato E.164 valido", override: false, }, { tag: "email", translation: "{0} deve essere un indirizzo email valido", override: false, }, { tag: "url", translation: "{0} deve essere un URL valido", override: false, }, { tag: "uri", translation: "{0} deve essere un URI valido", override: false, }, { tag: "base64", translation: "{0} deve essere una stringa Base64 valida", override: false, }, { tag: "contains", translation: "{0} deve contenere il testo '{1}'", override: false, customTransFunc: customTransFuncV1, }, { tag: "containsany", translation: "{0} deve contenere almeno uno dei seguenti caratteri '{1}'", override: false, customTransFunc: customTransFuncV1, }, { tag: "excludes", translation: "{0} non deve contenere il testo '{1}'", override: false, customTransFunc: customTransFuncV1, }, { tag: "excludesall", translation: "{0} non deve contenere alcuno dei seguenti caratteri '{1}'", override: false, customTransFunc: customTransFuncV1, }, { tag: "excludesrune", translation: "{0} non deve contenere '{1}'", override: false, customTransFunc: customTransFuncV1, }, { tag: "isbn", translation: "{0} deve essere un numero ISBN valido", override: false, }, { tag: "isbn10", translation: "{0} deve essere un numero ISBN-10 valido", override: false, }, { tag: "isbn13", translation: "{0} deve essere un numero ISBN-13 valido", override: false, }, { tag: "issn", translation: "{0} deve essere un numero ISSN valido", override: false, }, { tag: "uuid", translation: "{0} deve essere un UUID valido", override: false, }, { tag: "uuid3", translation: "{0} deve essere un UUID versione 3 valido", override: false, }, { tag: "uuid4", translation: "{0} deve essere un UUID versione 4 valido", override: false, }, { tag: "uuid5", translation: "{0} deve essere un UUID versione 5 valido", override: false, }, { tag: "ulid", translation: "{0} deve essere un ULID valido", override: false, }, { tag: "ascii", translation: "{0} deve contenere solo caratteri ascii", override: false, }, { tag: "printascii", translation: "{0} deve contenere solo caratteri ascii stampabili", override: false, }, { tag: "multibyte", translation: "{0} deve contenere caratteri multibyte", override: false, }, { tag: "datauri", translation: "{0} deve contenere un Data URI valido", override: false, }, { tag: "latitude", translation: "{0} deve contenere una latitudine valida", override: false, }, { tag: "longitude", translation: "{0} deve contenere una longitudine valida", override: false, }, { tag: "ssn", translation: "{0} deve essere un numero SSN valido", override: false, }, { tag: "ipv4", translation: "{0} deve essere un indirizzo IPv4 valido", override: false, }, { tag: "ipv6", translation: "{0} deve essere un indirizzo IPv6 valido", override: false, }, { tag: "ip", translation: "{0} deve essere un indirizzo IP valido", override: false, }, { tag: "cidr", translation: "{0} deve contenere una notazione CIDR valida", override: false, }, { tag: "cidrv4", translation: "{0} deve contenere una notazione CIDR per un indirizzo IPv4 valida", override: false, }, { tag: "cidrv6", translation: "{0} deve contenere una notazione CIDR per un indirizzo IPv6 valida", override: false, }, { tag: "tcp_addr", translation: "{0} deve essere un indirizzo TCP valido", override: false, }, { tag: "tcp4_addr", translation: "{0} deve essere un indirizzo IPv4 TCP valido", override: false, }, { tag: "tcp6_addr", translation: "{0} deve essere un indirizzo IPv6 TCP valido", override: false, }, { tag: "udp_addr", translation: "{0} deve essere un indirizzo UDP valido", override: false, }, { tag: "udp4_addr", translation: "{0} deve essere un indirizzo IPv4 UDP valido", override: false, }, { tag: "udp6_addr", translation: "{0} deve essere un indirizzo IPv6 UDP valido", override: false, }, { tag: "ip_addr", translation: "{0} deve essere un indirizzo IP risolvibile", override: false, }, { tag: "ip4_addr", translation: "{0} deve essere un indirizzo IPv4 risolvibile", override: false, }, { tag: "ip6_addr", translation: "{0} deve essere un indirizzo IPv6 risolvibile", override: false, }, { tag: "unix_addr", translation: "{0} deve essere un indirizzo UNIX risolvibile", override: false, }, { tag: "mac", translation: "{0} deve contenere un indirizzo MAC valido", override: false, }, { tag: "unique", translation: "{0} deve contenere valori unici", override: false, }, { tag: "iscolor", translation: "{0} deve essere un colore valido", override: false, }, { tag: "cron", translation: "{0} deve essere una stringa cron valida", override: false, }, { tag: "oneof", translation: "{0} deve essere uno di [{1}]", override: false, customTransFunc: customTransFuncV1, }, { tag: "json", translation: "{0} deve essere una stringa json valida", override: false, }, { tag: "jwt", translation: "{0} deve essere una stringa jwt valida", override: false, }, { tag: "lowercase", translation: "{0} deve essere una stringa minuscola", override: false, }, { tag: "boolean", translation: "{0} deve rappresentare un valore booleano", override: false, }, { tag: "uppercase", translation: "{0} deve essere una stringa maiuscola", override: false, }, { tag: "startswith", translation: "{0} deve iniziare con {1}", override: false, customTransFunc: customTransFuncV1, }, { tag: "startsnotwith", translation: "{0} non deve iniziare con {1}", override: false, customTransFunc: customTransFuncV1, }, { tag: "endswith", translation: "{0} deve terminare con {1}", override: false, customTransFunc: customTransFuncV1, }, { tag: "endsnotwith", translation: "{0} non deve terminare con {1}", override: false, customTransFunc: customTransFuncV1, }, { tag: "datetime", translation: "{0} non corrisponde al formato {1}", override: false, customTransFunc: customTransFuncV1, }, { tag: "postcode_iso3166_alpha2", translation: "{0} non corrisponde al formato del codice postale dello stato {1}", override: false, customTransFunc: customTransFuncV1, }, { tag: "postcode_iso3166_alpha2_field", translation: "{0} non corrisponde al formato del codice postale dello stato nel campo {1}", override: false, customTransFunc: customTransFuncV1, }, { tag: "image", translation: "{0} deve essere un'immagine valida", override: false, }, } for _, t := range translations { if t.customTransFunc != nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, t.customTransFunc) } else if t.customTransFunc != nil && t.customRegisFunc == nil { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), t.customTransFunc) } else if t.customTransFunc == nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, translateFunc) } else { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), translateFunc) } if err != nil { return } } return } func registrationFunc(tag string, translation string, override bool) validator.RegisterTranslationsFunc { return func(ut ut.Translator) (err error) { if err = ut.Add(tag, translation, override); err != nil { return } return } } func translateFunc(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t } func customTransFuncV1(ut ut.Translator, fe validator.FieldError) string { s, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return s } golang-github-go-playground-validator-v10-10.30.1/translations/it/it_test.go000066400000000000000000000551151512410077000267220ustar00rootroot00000000000000package 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"` ISSN string `validate:"issn"` 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"` Image string `validate:"image"` } 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.ISSN", expected: "ISSN deve essere un numero ISSN 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", }, { ns: "Test.Image", expected: "Image deve essere un'immagine valida", }, } 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)) } } golang-github-go-playground-validator-v10-10.30.1/translations/ja/000077500000000000000000000000001512410077000246675ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/translations/ja/ja.go000066400000000000000000001124131512410077000256120ustar00rootroot00000000000000package ja import ( "fmt" "log" "reflect" "strconv" "strings" "time" "github.com/go-playground/locales" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" ) // RegisterDefaultTranslations registers a set of default translations // for all built in tag's in validator; you may add your own as desired. func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (err error) { translations := []struct { tag string translation string override bool customRegisFunc validator.RegisterTranslationsFunc customTransFunc validator.TranslationFunc }{ { tag: "required", translation: "{0}は必須フィールドです", override: false, }, { tag: "required_if", translation: "{0}は必須フィールドです", override: false, }, { tag: "len", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("len-string", "{0}の長さは{1}でなければなりません", false); err != nil { return } // if err = ut.AddCardinal("len-string-character", "{0}文字", locales.PluralRuleOne, false); err != nil { // return // } if err = ut.AddCardinal("len-string-character", "{0}文字", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("len-number", "{0}は{1}と等しくなければなりません", false); err != nil { return } if err = ut.Add("len-items", "{0}は{1}を含まなければなりません", false); err != nil { return } // if err = ut.AddCardinal("len-items-item", "{0}つの項目", locales.PluralRuleOne, false); err != nil { // return // } if err = ut.AddCardinal("len-items-item", "{0}つの項目", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("len-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("len-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-items", fe.Field(), c) default: t, err = ut.T("len-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "min", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("min-string", "{0}の長さは少なくとも{1}はなければなりません", false); err != nil { return } // if err = ut.AddCardinal("min-string-character", "{0}文字", locales.PluralRuleOne, false); err != nil { // return // } if err = ut.AddCardinal("min-string-character", "{0}文字", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("min-number", "{0}は{1}以上でなければなりません", false); err != nil { return } if err = ut.Add("min-items", "{0}は少なくとも{1}を含まなければなりません", false); err != nil { return } // if err = ut.AddCardinal("min-items-item", "{0}つの項目", locales.PluralRuleOne, false); err != nil { // return // } if err = ut.AddCardinal("min-items-item", "{0}つの項目", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("min-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("min-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-items", fe.Field(), c) default: t, err = ut.T("min-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "max", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("max-string", "{0}の長さは最大でも{1}でなければなりません", false); err != nil { return } // if err = ut.AddCardinal("max-string-character", "{0}文字", locales.PluralRuleOne, false); err != nil { // return // } if err = ut.AddCardinal("max-string-character", "{0}文字", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("max-number", "{0}は{1}以下でなければなりません", false); err != nil { return } if err = ut.Add("max-items", "{0}は最大でも{1}でなければなりません", false); err != nil { return } // if err = ut.AddCardinal("max-items-item", "{0}つの項目", locales.PluralRuleOne, false); err != nil { // return // } if err = ut.AddCardinal("max-items-item", "{0}つの項目", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("max-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("max-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-items", fe.Field(), c) default: t, err = ut.T("max-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eq", translation: "{0}は{1}と等しくありません", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ne", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("ne-items", "{0}の項目の数は{1}と異ならなければなりません", false); err != nil { fmt.Printf("ne customRegisFunc #1 error because of %v\n", err) return } // if err = ut.AddCardinal("ne-items-item", "{0}個", locales.PluralRuleOne, false); err != nil { // return // } if err = ut.AddCardinal("ne-items-item", "{0}個", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("ne", "{0}は{1}と異ならなければなりません", false); err != nil { fmt.Printf("ne customRegisFunc #2 error because of %v\n", err) return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.Slice: var c string err = fn() if err != nil { goto END } c, err = ut.C("ne-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("ne-items", fe.Field(), c) default: t, err = ut.T("ne", fe.Field(), fe.Param()) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "lt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lt-string", "{0}の長さは{1}よりも少なくなければなりません", false); err != nil { return } // if err = ut.AddCardinal("lt-string-character", "{0}文字", locales.PluralRuleOne, false); err != nil { // return // } if err = ut.AddCardinal("lt-string-character", "{0}文字", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-number", "{0}は{1}よりも小さくなければなりません", false); err != nil { return } if err = ut.Add("lt-items", "{0}は{1}よりも少ない項目でなければなりません", false); err != nil { return } // if err = ut.AddCardinal("lt-items-item", "{0}つの項目", locales.PluralRuleOne, false); err != nil { // return // } if err = ut.AddCardinal("lt-items-item", "{0}つの項目", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-datetime", "{0}は現時刻よりも前でなければなりません", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "lte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lte-string", "{0}の長さは最大でも{1}でなければなりません", false); err != nil { return } // if err = ut.AddCardinal("lte-string-character", "{0}文字", locales.PluralRuleOne, false); err != nil { // return // } if err = ut.AddCardinal("lte-string-character", "{0}文字", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-number", "{0}は{1}以下でなければなりません", false); err != nil { return } if err = ut.Add("lte-items", "{0}は最大でも{1}でなければなりません", false); err != nil { return } // if err = ut.AddCardinal("lte-items-item", "{0}つの項目", locales.PluralRuleOne, false); err != nil { // return // } if err = ut.AddCardinal("lte-items-item", "{0}つの項目", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-datetime", "{0}は現時刻以前でなければなりません", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gt-string", "{0}の長さは{1}よりも多くなければなりません", false); err != nil { return } // if err = ut.AddCardinal("gt-string-character", "{0}文字", locales.PluralRuleOne, false); err != nil { // return // } if err = ut.AddCardinal("gt-string-character", "{0}文字", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-number", "{0}は{1}よりも大きくなければなりません", false); err != nil { return } if err = ut.Add("gt-items", "{0}は{1}よりも多い項目を含まなければなりません", false); err != nil { return } // if err = ut.AddCardinal("gt-items-item", "{0}つの項目", locales.PluralRuleOne, false); err != nil { // return // } if err = ut.AddCardinal("gt-items-item", "{0}つの項目", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-datetime", "{0}は現時刻よりも後でなければなりません", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gte-string", "{0}の長さは少なくとも{1}以上はなければなりません", false); err != nil { return } // if err = ut.AddCardinal("gte-string-character", "{0}文字", locales.PluralRuleOne, false); err != nil { // return // } if err = ut.AddCardinal("gte-string-character", "{0}文字", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-number", "{0}は{1}以上でなければなりません", false); err != nil { return } if err = ut.Add("gte-items", "{0}は少なくとも{1}を含まなければなりません", false); err != nil { return } // if err = ut.AddCardinal("gte-items-item", "{0}つの項目", locales.PluralRuleOne, false); err != nil { // return // } if err = ut.AddCardinal("gte-items-item", "{0}つの項目", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-datetime", "{0}は現時刻以降でなければなりません", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eqfield", translation: "{0}は{1}と等しくなければなりません", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "eqcsfield", translation: "{0}は{1}と等しくなければなりません", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "necsfield", translation: "{0}は{1}とは異ならなければなりません", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtcsfield", translation: "{0}は{1}よりも大きくなければなりません", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtecsfield", translation: "{0}は{1}以上でなければなりません", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltcsfield", translation: "{0}は{1}よりも小さくなければなりません", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltecsfield", translation: "{0}は{1}以下でなければなりません", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "nefield", translation: "{0}は{1}とは異ならなければなりません", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtfield", translation: "{0}は{1}よりも大きくなければなりません", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtefield", translation: "{0}は{1}以上でなければなりません", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltfield", translation: "{0}は{1}よりも小さくなければなりません", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltefield", translation: "{0}は{1}以下でなければなりません", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "alpha", translation: "{0}はアルファベットのみを含むことができます", override: false, }, { tag: "alphanum", translation: "{0}はアルファベットと数字のみを含むことができます", override: false, }, { tag: "numeric", translation: "{0}は正しい数字でなければなりません", override: false, }, { tag: "number", translation: "{0}は正しい数でなければなりません", override: false, }, { tag: "hexadecimal", translation: "{0}は正しい16進表記でなければなりません", override: false, }, { tag: "hexcolor", translation: "{0}は正しいHEXカラーコードでなければなりません", override: false, }, { tag: "rgb", translation: "{0}は正しいRGBカラーコードでなければなりません", override: false, }, { tag: "rgba", translation: "{0}は正しいRGBAカラーコードでなければなりません", override: false, }, { tag: "hsl", translation: "{0}は正しいHSLカラーコードでなければなりません", override: false, }, { tag: "hsla", translation: "{0}は正しいHSLAカラーコードでなければなりません", override: false, }, { tag: "email", translation: "{0}は正しいメールアドレスでなければなりません", override: false, }, { tag: "url", translation: "{0}は正しいURLでなければなりません", override: false, }, { tag: "uri", translation: "{0}は正しいURIでなければなりません", override: false, }, { tag: "base64", translation: "{0}は正しいBase64文字列でなければなりません", override: false, }, { tag: "contains", translation: "{0}は'{1}'を含まなければなりません", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "containsany", translation: "{0}は'{1}'の少なくとも1つを含まなければなりません", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludes", translation: "{0}には'{1}'というテキストを含むことはできません", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesall", translation: "{0}には'{1}'のどれも含めることはできません", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesrune", translation: "{0}には'{1}'を含めることはできません", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "isbn", translation: "{0}は正しいISBN番号でなければなりません", override: false, }, { tag: "isbn10", translation: "{0}は正しいISBN-10番号でなければなりません", override: false, }, { tag: "isbn13", translation: "{0}は正しいISBN-13番号でなければなりません", override: false, }, { tag: "issn", translation: "{0}は正しいISSN番号でなければなりません", override: false, }, { tag: "uuid", translation: "{0}は正しいUUIDでなければなりません", override: false, }, { tag: "uuid3", translation: "{0}はバージョンが3の正しいUUIDでなければなりません", override: false, }, { tag: "uuid4", translation: "{0}はバージョンが4の正しいUUIDでなければなりません", override: false, }, { tag: "uuid5", translation: "{0}はバージョンが5の正しいUUIDでなければなりません", override: false, }, { tag: "ulid", translation: "{0}は正しいULIDでなければなりません", override: false, }, { tag: "ascii", translation: "{0}はASCII文字のみを含まなければなりません", override: false, }, { tag: "printascii", translation: "{0}は印刷可能なASCII文字のみを含まなければなりません", override: false, }, { tag: "multibyte", translation: "{0}はマルチバイト文字を含まなければなりません", override: false, }, { tag: "datauri", translation: "{0}は正しいデータURIを含まなければなりません", override: false, }, { tag: "latitude", translation: "{0}は正しい緯度の座標を含まなければなりません", override: false, }, { tag: "longitude", translation: "{0}は正しい経度の座標を含まなければなりません", override: false, }, { tag: "ssn", translation: "{0}は正しい社会保障番号でなければなりません", override: false, }, { tag: "ipv4", translation: "{0}は正しいIPv4アドレスでなければなりません", override: false, }, { tag: "ipv6", translation: "{0}は正しいIPv6アドレスでなければなりません", override: false, }, { tag: "ip", translation: "{0}は正しいIPアドレスでなければなりません", override: false, }, { tag: "cidr", translation: "{0}は正しいCIDR表記を含まなければなりません", override: false, }, { tag: "cidrv4", translation: "{0}はIPv4アドレスの正しいCIDR表記を含まなければなりません", override: false, }, { tag: "cidrv6", translation: "{0}はIPv6アドレスの正しいCIDR表記を含まなければなりません", override: false, }, { tag: "tcp_addr", translation: "{0}は正しいTCPアドレスでなければなりません", override: false, }, { tag: "tcp4_addr", translation: "{0}は正しいIPv4のTCPアドレスでなければなりません", override: false, }, { tag: "tcp6_addr", translation: "{0}は正しいIPv6のTCPアドレスでなければなりません", override: false, }, { tag: "udp_addr", translation: "{0}は正しいUDPアドレスでなければなりません", override: false, }, { tag: "udp4_addr", translation: "{0}は正しいIPv4のUDPアドレスでなければなりません", override: false, }, { tag: "udp6_addr", translation: "{0}は正しいIPv6のUDPアドレスでなければなりません", override: false, }, { tag: "ip_addr", translation: "{0}は解決可能なIPアドレスでなければなりません", override: false, }, { tag: "ip4_addr", translation: "{0}は解決可能なIPv4アドレスでなければなりません", override: false, }, { tag: "ip6_addr", translation: "{0}は解決可能なIPv6アドレスでなければなりません", override: false, }, { tag: "unix_addr", translation: "{0}は解決可能なUNIXアドレスでなければなりません", override: false, }, { tag: "mac", translation: "{0}は正しいMACアドレスを含まなければなりません", override: false, }, { tag: "unique", translation: "{0}は一意な値のみを含まなければなりません", override: false, }, { tag: "iscolor", translation: "{0}は正しい色でなければなりません", override: false, }, { tag: "oneof", translation: "{0}は[{1}]のうちのいずれかでなければなりません", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { s, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return s }, }, { tag: "image", translation: "{0} は有効な画像でなければなりません", override: false, }, { tag: "json", translation: "{0}は正しいJSON文字列でなければなりません", override: false, }, { tag: "jwt", translation: "{0}は正しいJWT文字列でなければなりません", override: false, }, { tag: "lowercase", translation: "{0}は小文字でなければなりません", override: false, }, { tag: "uppercase", translation: "{0}は大文字でなければなりません", override: false, }, { tag: "datetime", translation: "{0}は{1}の書式と一致しません", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "postcode_iso3166_alpha2", translation: "{0}は国名コード{1}の郵便番号形式と一致しません", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "postcode_iso3166_alpha2_field", translation: "{0}は{1}フィールドで指定された国名コードの郵便番号形式と一致しません", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "boolean", translation: "{0}は正しいブール値でなければなりません", override: false, }, } for _, t := range translations { if t.customTransFunc != nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, t.customTransFunc) } else if t.customTransFunc != nil && t.customRegisFunc == nil { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), t.customTransFunc) } else if t.customTransFunc == nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, translateFunc) } else { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), translateFunc) } if err != nil { return } } return } func registrationFunc(tag string, translation string, override bool) validator.RegisterTranslationsFunc { return func(ut ut.Translator) (err error) { if err = ut.Add(tag, translation, override); err != nil { return } return } } func translateFunc(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t } golang-github-go-playground-validator-v10-10.30.1/translations/ja/ja_test.go000066400000000000000000000601631512410077000266550ustar00rootroot00000000000000package 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"` ISSN string `validate:"issn"` 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"` Image string `validate:"image"` } 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.ISSN", expected: "ISSNは正しいISSN番号でなければなりません", }, { 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.Image", expected: "Image は有効な画像でなければなりません", }, { 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)) } } golang-github-go-playground-validator-v10-10.30.1/translations/ko/000077500000000000000000000000001512410077000247065ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/translations/ko/ko.go000066400000000000000000001123211512410077000256460ustar00rootroot00000000000000package ko import ( "fmt" "log" "reflect" "strconv" "strings" "time" "github.com/go-playground/locales" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" ) // RegisterDefaultTranslations registers a set of default translations // for all built in tag's in validator; you may add your own as desired. func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (err error) { translations := []struct { tag string translation string override bool customRegisFunc validator.RegisterTranslationsFunc customTransFunc validator.TranslationFunc }{ { tag: "required", translation: "{0}은(는) 필수 필드입니다.", override: false, }, { tag: "required_if", translation: "{0}은(는) 필수 필드입니다.", override: false, }, { tag: "required_unless", translation: "{0}은(는) 필수 필드입니다.", override: false, }, { tag: "required_with", translation: "{0}은(는) 필수 필드입니다.", override: false, }, { tag: "required_with_all", translation: "{0}은(는) 필수 필드입니다.", override: false, }, { tag: "required_without", translation: "{0}은(는) 필수 필드입니다.", override: false, }, { tag: "required_without_all", translation: "{0}은(는) 필수 필드입니다.", override: false, }, { tag: "excluded_if", translation: "{0}은(는) 제외된 필드입니다.", override: false, }, { tag: "excluded_unless", translation: "{0}은(는) 제외된 필드입니다.", override: false, }, { tag: "excluded_with", translation: "{0}은(는) 제외된 필드입니다.", override: false, }, { tag: "excluded_with_all", translation: "{0}은(는) 제외된 필드입니다.", override: false, }, { tag: "excluded_without", translation: "{0}은(는) 제외된 필드입니다.", override: false, }, { tag: "excluded_without_all", translation: "{0}은(는) 제외된 필드입니다.", override: false, }, { tag: "isdefault", translation: "{0}은(는) 기본값이어야 합니다.", override: false, }, { tag: "len", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("len-string", "{0}의 길이는 {1}여야 합니다.", false); err != nil { return } if err = ut.AddCardinal("len-string-character", "{0}자", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("len-number", "{0}은(는) {1}와(과) 같아야 합니다.", false); err != nil { return } if err = ut.Add("len-items", "{0}은(는) {1}을 포함해야 합니다.", false); err != nil { return } if err = ut.AddCardinal("len-items-item", "{0}개의 항목", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("len-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("len-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-items", fe.Field(), c) default: t, err = ut.T("len-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "min", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("min-string", "{0}의 길이는 최소 {1}여야 합니다.", false); err != nil { return } if err = ut.AddCardinal("min-string-character", "{0}자", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("min-number", "{0}은(는) {1} 이상여야 합니다.", false); err != nil { return } if err = ut.Add("min-items", "{0}은(는) 최소 {1}을 포함해야 합니다.", false); err != nil { return } if err = ut.AddCardinal("min-items-item", "{0}개의 항목", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("min-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("min-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-items", fe.Field(), c) default: t, err = ut.T("min-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "max", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("max-string", "{0}의 길이는 최대 {1}여야 합니다.", false); err != nil { return } if err = ut.AddCardinal("max-string-character", "{0}자", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("max-number", "{0}은(는) {1} 이하여야 합니다.", false); err != nil { return } if err = ut.Add("max-items", "{0}은(는) 최대 {1}여야 합니다.", false); err != nil { return } if err = ut.AddCardinal("max-items-item", "{0}개의 항목", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("max-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("max-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-items", fe.Field(), c) default: t, err = ut.T("max-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eq", translation: "{0}은(는) {1}와(과) 같아야 합니다.", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("경고: FieldError 번역 중 오류 발생: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ne", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("ne-items", "{0}의 항목 수는 {1}와(과) 달라야 합니다.", false); err != nil { fmt.Printf("ne customRegisFunc #1 error because of %v\n", err) return } if err = ut.AddCardinal("ne-items-item", "{0}개", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("ne", "{0}은(는) {1}와(과) 달라야 합니다.", false); err != nil { fmt.Printf("ne customRegisFunc #2 error because of %v\n", err) return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.Slice: var c string err = fn() if err != nil { goto END } c, err = ut.C("ne-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("ne-items", fe.Field(), c) default: t, err = ut.T("ne", fe.Field(), fe.Param()) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "lt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lt-string", "{0}의 길이는 {1}보다 작아야 합니다.", false); err != nil { return } if err = ut.AddCardinal("lt-string-character", "{0}자", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-number", "{0}은(는) {1}보다 작아야 합니다.", false); err != nil { return } if err = ut.Add("lt-items", "{0}은(는) {1}보다 적은 항목여야 합니다.", false); err != nil { return } if err = ut.AddCardinal("lt-items-item", "{0}개의 항목", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-datetime", "{0}은(는) 현재 시간보다 이전이어야 합니다.", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "lte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lte-string", "{0}의 길이는 최대 {1}여야 합니다.", false); err != nil { return } if err = ut.AddCardinal("lte-string-character", "{0}자", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-number", "{0}은(는) {1} 이하여야 합니다.", false); err != nil { return } if err = ut.Add("lte-items", "{0}은(는) 최대 {1}여야 합니다.", false); err != nil { return } if err = ut.AddCardinal("lte-items-item", "{0}개의 항목", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-datetime", "{0}은(는) 현재 시간보다 이전이어야 합니다.", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gt-string", "{0}의 길이는 {1}보다 길어야 합니다.", false); err != nil { return } if err = ut.AddCardinal("gt-string-character", "{0}자", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-number", "{0}은(는) {1}보다 커야 합니다.", false); err != nil { return } if err = ut.Add("gt-items", "{0}은(는) {1}보다 많은 항목을 포함해야 합니다.", false); err != nil { return } if err = ut.AddCardinal("gt-items-item", "{0}개의 항목", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-datetime", "{0}은(는) 현재 시간 이후이어야 합니다.", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gte-string", "{0}의 길이는 최소 {1} 이상여야 합니다.", false); err != nil { return } if err = ut.AddCardinal("gte-string-character", "{0}자", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-number", "{0}은(는) {1} 이상여야 합니다.", false); err != nil { return } if err = ut.Add("gte-items", "{0}은(는) 최소 {1}을 포함해야 합니다.", false); err != nil { return } if err = ut.AddCardinal("gte-items-item", "{0}개의 항목", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-datetime", "{0}은(는) 현재 시간 이후이어야 합니다.", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eqfield", translation: "{0}은(는) {1}와(과) 같아야 합니다.", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("경고: FieldError 번역 중 오류 발생: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "eqcsfield", translation: "{0}은(는) {1}와(과) 같아야 합니다.", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("경고: FieldError 번역 중 오류 발생: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "necsfield", translation: "{0}은(는) {1}와(과) 달라야 합니다.", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("경고: FieldError 번역 중 오류 발생: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtcsfield", translation: "{0}은(는) {1}보다 커야 합니다.", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("경고: FieldError 번역 중 오류 발생: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtecsfield", translation: "{0}은(는) {1} 이상여야 합니다.", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("경고: FieldError 번역 중 오류 발생: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltcsfield", translation: "{0}은(는) {1}보다 작아야 합니다.", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("경고: FieldError 번역 중 오류 발생: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltecsfield", translation: "{0}은(는) {1} 이하여야 합니다.", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("경고: FieldError 번역 중 오류 발생: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "nefield", translation: "{0}은(는) {1}와(과) 달라야 합니다.", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("경고: FieldError 번역 중 오류 발생: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtfield", translation: "{0}은(는) {1}보다 커야 합니다.", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("경고: FieldError 번역 중 오류 발생: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtefield", translation: "{0}은(는) {1} 이상여야 합니다.", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("경고: FieldError 번역 중 오류 발생: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltfield", translation: "{0}은(는) {1}보다 작아야 합니다.", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("경고: FieldError 번역 중 오류 발생: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltefield", translation: "{0}은(는) {1} 이하여야 합니다.", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("경고: FieldError 번역 중 오류 발생: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "alpha", translation: "{0}은(는) 알파벳만 포함할 수 있습니다.", override: false, }, { tag: "alphanum", translation: "{0}은(는) 알파벳과 숫자만 포함할 수 있습니다.", override: false, }, { tag: "alphaspace", translation: "{0}은(는) 알파벳과 공백만 포함할 수 있습니다.", override: false, }, { tag: "alphanumspace", translation: "{0}은(는) 알파벳, 숫자, 공백만 포함할 수 있습니다.", override: false, }, { tag: "alphaunicode", translation: "{0}은(는) 유니코드 문자만 포함할 수 있습니다.", override: false, }, { tag: "alphanumunicode", translation: "{0}은(는) 유니코드 문자와 숫자만 포함할 수 있습니다.", override: false, }, { tag: "numeric", translation: "{0}은(는) 올바른 숫자여야 합니다.", override: false, }, { tag: "number", translation: "{0}은(는) 올바른 수여야 합니다.", override: false, }, { tag: "hexadecimal", translation: "{0}은(는) 올바른 16진수 표기여야 합니다.", override: false, }, { tag: "hexcolor", translation: "{0}은(는) 올바른 HEX 색상 코드여야 합니다.", override: false, }, { tag: "rgb", translation: "{0}은(는) 올바른 RGB 색상 코드여야 합니다.", override: false, }, { tag: "rgba", translation: "{0}은(는) 올바른 RGBA 색상 코드여야 합니다.", override: false, }, { tag: "hsl", translation: "{0}은(는) 올바른 HSL 색상 코드여야 합니다.", override: false, }, { tag: "hsla", translation: "{0}은(는) 올바른 HSLA 색상 코드여야 합니다.", override: false, }, { tag: "e164", translation: "{0}은(는) 유효한 E.164 형식의 전화번호여야 합니다.", override: false, }, { tag: "email", translation: "{0}은(는) 올바른 이메일 주소여야 합니다.", override: false, }, { tag: "url", translation: "{0}은(는) 올바른 URL여야 합니다.", override: false, }, { tag: "uri", translation: "{0}은(는) 올바른 URI여야 합니다.", override: false, }, { tag: "base64", translation: "{0}은(는) 올바른 Base64 문자열여야 합니다.", override: false, }, { tag: "contains", translation: "{0}은(는) '{1}'을(를) 포함해야 합니다.", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("경고: FieldError 번역 중 오류 발생: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "containsany", translation: "{0}은(는) '{1}' 중 최소 하나를 포함해야 합니다.", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("경고: FieldError 번역 중 오류 발생: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludes", translation: "{0}에는 '{1}'라는 텍스트를 포함할 수 없습니다.", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("경고: FieldError 번역 중 오류 발생: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesall", translation: "{0}에는 '{1}' 중 어느 것도 포함할 수 없습니다.", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("경고: FieldError 번역 중 오류 발생: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesrune", translation: "{0}에는 '{1}'을(를) 포함할 수 없습니다.", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("경고: FieldError 번역 중 오류 발생: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "isbn", translation: "{0}은(는) 올바른 ISBN 번호여야 합니다.", override: false, }, { tag: "isbn10", translation: "{0}은(는) 올바른 ISBN-10 번호여야 합니다.", override: false, }, { tag: "isbn13", translation: "{0}은(는) 올바른 ISBN-13 번호여야 합니다.", override: false, }, { tag: "issn", translation: "{0}은(는) 올바른 ISSN 번호여야 합니다.", override: false, }, { tag: "uuid", translation: "{0}은(는) 올바른 UUID여야 합니다.", override: false, }, { tag: "uuid3", translation: "{0}은(는) 버전 3의 올바른 UUID여야 합니다.", override: false, }, { tag: "uuid4", translation: "{0}은(는) 버전 4의 올바른 UUID여야 합니다.", override: false, }, { tag: "uuid5", translation: "{0}은(는) 버전 5의 올바른 UUID여야 합니다.", override: false, }, { tag: "ulid", translation: "{0}은(는) 올바른 ULID여야 합니다.", override: false, }, { tag: "ascii", translation: "{0}은(는) ASCII 문자만 포함해야 합니다.", override: false, }, { tag: "printascii", translation: "{0}은(는) 인쇄 가능한 ASCII 문자만 포함해야 합니다.", override: false, }, { tag: "multibyte", translation: "{0}은(는) 멀티바이트 문자를 포함해야 합니다.", override: false, }, { tag: "datauri", translation: "{0}은(는) 올바른 데이터 URI를 포함해야 합니다.", override: false, }, { tag: "latitude", translation: "{0}은(는) 올바른 위도 좌표를 포함해야 합니다.", override: false, }, { tag: "longitude", translation: "{0}은(는) 올바른 경도 좌표를 포함해야 합니다.", override: false, }, { tag: "ssn", translation: "{0}은(는) 올바른 사회 보장 번호여야 합니다.", override: false, }, { tag: "ipv4", translation: "{0}은(는) 올바른 IPv4 주소여야 합니다.", override: false, }, { tag: "ipv6", translation: "{0}은(는) 올바른 IPv6 주소여야 합니다.", override: false, }, { tag: "ip", translation: "{0}은(는) 올바른 IP 주소여야 합니다.", override: false, }, { tag: "cidr", translation: "{0}은(는) 올바른 CIDR 표기를 포함해야 합니다.", override: false, }, { tag: "cidrv4", translation: "{0}은(는) IPv4 주소의 올바른 CIDR 표기를 포함해야 합니다.", override: false, }, { tag: "cidrv6", translation: "{0}은(는) IPv6 주소의 올바른 CIDR 표기를 포함해야 합니다.", override: false, }, { tag: "tcp_addr", translation: "{0}은(는) 올바른 TCP 주소여야 합니다.", override: false, }, { tag: "tcp4_addr", translation: "{0}은(는) 올바른 IPv4의 TCP 주소여야 합니다.", override: false, }, { tag: "tcp6_addr", translation: "{0}은(는) 올바른 IPv6의 TCP 주소여야 합니다.", override: false, }, { tag: "udp_addr", translation: "{0}은(는) 올바른 UDP 주소여야 합니다.", override: false, }, { tag: "udp4_addr", translation: "{0}은(는) 올바른 IPv4의 UDP 주소여야 합니다.", override: false, }, { tag: "udp6_addr", translation: "{0}은(는) 올바른 IPv6의 UDP 주소여야 합니다.", override: false, }, { tag: "ip_addr", translation: "{0}은(는) 해석 가능한 IP 주소여야 합니다.", override: false, }, { tag: "ip4_addr", translation: "{0}은(는) 해석 가능한 IPv4 주소여야 합니다.", override: false, }, { tag: "ip6_addr", translation: "{0}은(는) 해석 가능한 IPv6 주소여야 합니다.", override: false, }, { tag: "unix_addr", translation: "{0}은(는) 해석 가능한 UNIX 주소여야 합니다.", override: false, }, { tag: "mac", translation: "{0}은(는) 올바른 MAC 주소를 포함해야 합니다.", override: false, }, { tag: "fqdn", translation: "{0}은(는) 유효한 FQDN이어야 합니다.", override: false, }, { tag: "unique", translation: "{0}은(는) 고유한 값만 포함해야 합니다.", override: false, }, { tag: "iscolor", translation: "{0}은(는) 올바른 색이여야 합니다.", override: false, }, { tag: "cron", translation: "{0}은(는) 유효한 cron 표현식이어야 합니다.", override: false, }, { tag: "oneof", translation: "{0}은(는) [{1}] 중 하나여야 합니다.", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { s, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("경고: FieldError 번역 중 오류 발생: %#v", fe) return fe.(error).Error() } return s }, }, { tag: "json", translation: "{0}은(는) 올바른 JSON 문자열여야 합니다.", override: false, }, { tag: "jwt", translation: "{0}은(는) 올바른 JWT 문자열여야 합니다.", override: false, }, { tag: "lowercase", translation: "{0}은(는) 소문자여야 합니다.", override: false, }, { tag: "uppercase", translation: "{0}은(는) 대문자여야 합니다.", override: false, }, { tag: "datetime", translation: "{0}은(는) {1} 형식과 일치해야 합니다.", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("경고: FieldError 번역 중 오류 발생: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "postcode_iso3166_alpha2", translation: "{0}은(는) 국가 코드 {1}의 우편번호 형식과 일치해야 합니다.", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("경고: FieldError 번역 중 오류 발생: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "postcode_iso3166_alpha2_field", translation: "{0}은(는) {1} 필드에 지정된 국가 코드의 우편번호 형식과 일치해야 합니다.", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("경고: FieldError 번역 중 오류 발생: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "boolean", translation: "{0}은(는) 올바른 부울 값여야 합니다.", override: false, }, { tag: "image", translation: "{0}은(는) 유효한 이미지여야 합니다.", override: false, }, { tag: "cve", translation: "{0}은(는) 유효한 CVE 식별자여야 합니다.", override: false, }, } for _, t := range translations { if t.customTransFunc != nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, t.customTransFunc) } else if t.customTransFunc != nil && t.customRegisFunc == nil { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), t.customTransFunc) } else if t.customTransFunc == nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, translateFunc) } else { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), translateFunc) } if err != nil { return } } return } func registrationFunc(tag string, translation string, override bool) validator.RegisterTranslationsFunc { return func(ut ut.Translator) (err error) { if err = ut.Add(tag, translation, override); err != nil { return } return } } func translateFunc(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t } golang-github-go-playground-validator-v10-10.30.1/translations/ko/ko_test.go000066400000000000000000000672411512410077000267170ustar00rootroot00000000000000package ko import ( "testing" "time" . "github.com/go-playground/assert/v2" ko_locale "github.com/go-playground/locales/ko" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" ) func TestTranslations(t *testing.T) { korean := ko_locale.New() uni := ut.New(korean, korean) trans, _ := uni.GetTranslator("ko") 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 RequiredUnless string RequiredWith string RequiredWithAll string RequiredWithout string RequiredWithoutAll string ExcludedIf string ExcludedUnless string ExcludedWith string ExcludedWithAll string ExcludedWithout string ExcludedWithoutAll 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"` RequiredUnless string `validate:"required_unless=Inner.RequiredUnless abcd"` RequiredWith string `validate:"required_with=Inner.RequiredWith"` RequiredWithAll string `validate:"required_with_all=Inner.RequiredWith Inner.RequiredWithAll"` RequiredWithout string `validate:"required_without=Inner.RequiredWithout"` RequiredWithoutAll string `validate:"required_without_all=Inner.RequiredWithout Inner.RequiredWithoutAll"` ExcludedIf string `validate:"excluded_if=Inner.ExcludedIf abcd"` ExcludedUnless string `validate:"excluded_unless=Inner.ExcludedUnless abcd"` ExcludedWith string `validate:"excluded_with=Inner.ExcludedWith"` ExcludedWithout string `validate:"excluded_with_all=Inner.ExcludedWithAll"` ExcludedWithAll string `validate:"excluded_without=Inner.ExcludedWithout"` ExcludedWithoutAll string `validate:"excluded_without_all=Inner.ExcludedWithoutAll"` IsDefault string `validate:"isdefault"` 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"` AlphaSpaceString string `validate:"alphaspace"` AlphaNumSpaceString string `validate:"alphanumspace"` AlphaUnicodeString string `validate:"alphaunicode"` AlphaNumUnicodeString string `validate:"alphanumunicode"` 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"` ISSN string `validate:"issn"` 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"` Image string `validate:"image"` CveString string `validate:"cve"` } var test Test test.Inner.EqCSFieldString = "1234" test.Inner.GtCSFieldString = "1234" test.Inner.GteCSFieldString = "1234" test.Inner.RequiredUnless = "1234" test.Inner.RequiredWith = "1234" test.Inner.RequiredWithAll = "1234" test.Inner.ExcludedIf = "abcd" test.Inner.ExcludedUnless = "1234" test.Inner.ExcludedWith = "1234" test.Inner.ExcludedWithAll = "1234" test.ExcludedIf = "1234" test.ExcludedUnless = "1234" test.ExcludedWith = "1234" test.ExcludedWithAll = "1234" test.ExcludedWithout = "1234" test.ExcludedWithoutAll = "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.AlphaSpaceString = "abc3" test.AlphaNumSpaceString = "abc!" test.AlphaUnicodeString = "abc3" test.AlphaNumUnicodeString = "abc!" 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은(는) 올바른 색이여야 합니다.", }, { ns: "Test.MAC", expected: "MAC은(는) 올바른 MAC 주소를 포함해야 합니다.", }, { ns: "Test.FQDN", expected: "FQDN은(는) 유효한 FQDN이어야 합니다.", }, { 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.ISSN", expected: "ISSN은(는) 올바른 ISSN 번호여야 합니다.", }, { 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은(는) 올바른 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.AlphaSpaceString", expected: "AlphaSpaceString은(는) 알파벳과 공백만 포함할 수 있습니다.", }, { ns: "Test.AlphaNumSpaceString", expected: "AlphaNumSpaceString은(는) 알파벳, 숫자, 공백만 포함할 수 있습니다.", }, { ns: "Test.AlphaUnicodeString", expected: "AlphaUnicodeString은(는) 유니코드 문자만 포함할 수 있습니다.", }, { ns: "Test.AlphaNumUnicodeString", expected: "AlphaNumUnicodeString은(는) 유니코드 문자와 숫자만 포함할 수 있습니다.", }, { 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.RequiredUnless", expected: "RequiredUnless은(는) 필수 필드입니다.", }, { ns: "Test.RequiredWith", expected: "RequiredWith은(는) 필수 필드입니다.", }, { ns: "Test.RequiredWithAll", expected: "RequiredWithAll은(는) 필수 필드입니다.", }, { ns: "Test.RequiredWithout", expected: "RequiredWithout은(는) 필수 필드입니다.", }, { ns: "Test.RequiredWithoutAll", expected: "RequiredWithoutAll은(는) 필수 필드입니다.", }, { ns: "Test.ExcludedIf", expected: "ExcludedIf은(는) 제외된 필드입니다.", }, { ns: "Test.ExcludedUnless", expected: "ExcludedUnless은(는) 제외된 필드입니다.", }, { ns: "Test.ExcludedWith", expected: "ExcludedWith은(는) 제외된 필드입니다.", }, { ns: "Test.ExcludedWithAll", expected: "ExcludedWithAll은(는) 제외된 필드입니다.", }, { ns: "Test.ExcludedWithout", expected: "ExcludedWithout은(는) 제외된 필드입니다.", }, { ns: "Test.ExcludedWithoutAll", expected: "ExcludedWithoutAll은(는) 제외된 필드입니다.", }, { 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은(는) 올바른 부울 값여야 합니다.", }, { ns: "Test.Image", expected: "Image은(는) 유효한 이미지여야 합니다.", }, { ns: "Test.CveString", expected: "CveString은(는) 유효한 CVE 식별자여야 합니다.", }, } 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)) } } golang-github-go-playground-validator-v10-10.30.1/translations/lv/000077500000000000000000000000001512410077000247165ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/translations/lv/lv.go000066400000000000000000001031561512410077000256740ustar00rootroot00000000000000package lv import ( "fmt" "log" "reflect" "strconv" "strings" "time" "github.com/go-playground/locales" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" ) // RegisterDefaultTranslations registers a set of default translations // for all built in tag's in validator; you may add your own as desired. func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (err error) { translations := []struct { tag string translation string override bool customRegisFunc validator.RegisterTranslationsFunc customTransFunc validator.TranslationFunc }{ { tag: "required", translation: "{0} ir obligāts lauks", override: false, }, { tag: "required_if", translation: "{0} ir obligāts lauks", override: false, }, { tag: "len", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("len-string", "{0} garumam jābūt {1}", false); err != nil { return } if err = ut.AddCardinal("len-string-character", "{0} rakstu zīme", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("len-string-character", "{0} rakstu zīmes", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("len-number", "{0} vērtībai jābūt {1}", false); err != nil { return } if err = ut.Add("len-items", "{0} vērtībai jāsatur {1}", false); err != nil { return } if err = ut.AddCardinal("len-items-item", "{0} elements", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("len-items-item", "{0} elementi", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("len-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("len-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-items", fe.Field(), c) default: t, err = ut.T("len-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "min", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("min-string", "{0} garumam jābūt minimums {1}", false); err != nil { return } if err = ut.AddCardinal("min-string-character", "{0} rakstu zīme", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("min-string-character", "{0} rakstu zīmes", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("min-number", "{0} vērtībai jābūt {1} vai lielākai", false); err != nil { return } if err = ut.Add("min-items", "{0} jāsatur minimums {1}", false); err != nil { return } if err = ut.AddCardinal("min-items-item", "{0} elements", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("min-items-item", "{0} elementi", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("min-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("min-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-items", fe.Field(), c) default: t, err = ut.T("min-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "max", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("max-string", "{0} vērtība pārsniedz maksimālo garumu {1}", false); err != nil { return } if err = ut.AddCardinal("max-string-character", "{0} rakstu zīme", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("max-string-character", "{0} rakstu zīmes", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("max-number", "{0} vērtībai jābūt {1} vai mazākai", false); err != nil { return } if err = ut.Add("max-items", "{0} jāsatur maksimums {1}", false); err != nil { return } if err = ut.AddCardinal("max-items-item", "{0} elements", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("max-items-item", "{0} elementi", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("max-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("max-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-items", fe.Field(), c) default: t, err = ut.T("max-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eq", translation: "{0} nav vienāds ar {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ne", translation: "{0} nedrīkst būt vienāds ar {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "lt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lt-string", "{0} garumam jābūt mazākam par {1}", false); err != nil { return } if err = ut.AddCardinal("lt-string-character", "{0} rakstu zīmi", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lt-string-character", "{0} rakstu zīmēm", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-number", "{0} jābūt mazākam par {1}", false); err != nil { return } if err = ut.Add("lt-items", "{0} jāsatur mazāk par {1}", false); err != nil { return } if err = ut.AddCardinal("lt-items-item", "{0} elements", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lt-items-item", "{0} elementiem", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-datetime", "{0} jābūt mazākam par šī brīža Datumu un laiku", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "lte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lte-string", "{0} garumam jābūt maksimums {1}", false); err != nil { return } if err = ut.AddCardinal("lte-string-character", "{0} rakstu zīme", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lte-string-character", "{0} rakstu zīmes", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-number", "{0} jābūt {1} vai mazākam", false); err != nil { return } if err = ut.Add("lte-items", "{0} jāsatur maksimums {1}", false); err != nil { return } if err = ut.AddCardinal("lte-items-item", "{0} elements", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lte-items-item", "{0} elementi", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-datetime", "{0} jābūt mazākam par šī brīža Datumu un laiku vai vienādam", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gt-string", "{0} ir jābūt garākam par {1}", false); err != nil { return } if err = ut.AddCardinal("gt-string-character", "{0} rakstu zīme", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gt-string-character", "{0} rakstu zīmēm", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-number", "{0} jābūt lielākam par {1}", false); err != nil { return } if err = ut.Add("gt-items", "{0} jāsatur vairāk par {1}", false); err != nil { return } if err = ut.AddCardinal("gt-items-item", "{0} elements", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gt-items-item", "{0} elementiem", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-datetime", "{0} jābūt lielākam par šī brīža Datumu un laiku", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gte-string", "{0} garumam jābūt minimums {1}", false); err != nil { return } if err = ut.AddCardinal("gte-string-character", "{0} rakstu zīme", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gte-string-character", "{0} rakstu zīmes", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-number", "{0} jābūt {1} vai lielākam", false); err != nil { return } if err = ut.Add("gte-items", "{0} jāsatur minimums {1}", false); err != nil { return } if err = ut.AddCardinal("gte-items-item", "{0} elements", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gte-items-item", "{0} elementi", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-datetime", "{0} jābūt lielākam par šī brīža Datumu un laiku vai vienādam", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eqfield", translation: "{0} jābūt vienādam ar {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "eqcsfield", translation: "{0} jābūt vienādam ar {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "necsfield", translation: "{0} nedrīkst būt vienāds ar {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtcsfield", translation: "{0} jābūt lielākam par {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtecsfield", translation: "{0} jābūt lielākam par {1} vai vienādam", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltcsfield", translation: "{0} jābūt mazākam par {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltecsfield", translation: "{0} jābūt mazākam par {1} vai vienādam", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "nefield", translation: "{0} nedrīkst būt vienāds ar {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtfield", translation: "{0} jābūt lielākam par {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtefield", translation: "{0} jābūt lielākam par {1} vai vienādam", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltfield", translation: "{0} jābūt mazākam par {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltefield", translation: "{0} jābūt mazākam par {1} vai vienādam", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "alpha", translation: "{0} jāsatur tikai simboli no alfabēta", override: false, }, { tag: "alphanum", translation: "{0} jāsatur tikai simboli no alfabēta vai cipari (Alphanumeric)", override: false, }, { tag: "numeric", translation: "{0} jāsatur tikai cipari", override: false, }, { tag: "number", translation: "{0} jāsatur derīgs skaitlis", override: false, }, { tag: "hexadecimal", translation: "{0} jābūt heksadecimālam skaitlim", override: false, }, { tag: "hexcolor", translation: "{0} jābūt derīgai HEX krāsai", override: false, }, { tag: "rgb", translation: "{0} jābūt derīgai RGB krāsai", override: false, }, { tag: "rgba", translation: "{0} jābūt derīgai RGBA krāsai", override: false, }, { tag: "hsl", translation: "{0} jābūt derīgai HSL krāsai", override: false, }, { tag: "hsla", translation: "{0} jābūt derīgai HSLA krāsai", override: false, }, { tag: "e164", translation: "{0} jābūt derīgam, pēc E.164 formatētam talruņa numuram", override: false, }, { tag: "email", translation: "{0} jābūt derīgai e-pasta adresei", override: false, }, { tag: "url", translation: "{0} jābūt derīgam URL", override: false, }, { tag: "uri", translation: "{0} jābūt derīgam URI", override: false, }, { tag: "base64", translation: "{0} jābūt derīgai Base64 virknei", override: false, }, { tag: "contains", translation: "{0} jāsatur teksts '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "containsany", translation: "{0} jāsatur minimums 1 no rakstu zīmēm '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludes", translation: "{0} nedrīkst saturēt tekstu '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesall", translation: "{0} nedrīkst saturēt nevienu no sekojošām rakstu zīmēm '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesrune", translation: "{0} nedrīkst saturēt sekojošo '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "isbn", translation: "{0} jābūt derīgam ISBN numuram", override: false, }, { tag: "isbn10", translation: "{0} jābūt derīgam ISBN-10 numuram", override: false, }, { tag: "isbn13", translation: "{0} jābūt derīgam ISBN-13 numuram", override: false, }, { tag: "issn", translation: "{0} jābūt derīgam ISSN numuram", override: false, }, { tag: "uuid", translation: "{0} jābūt derīgam UUID", override: false, }, { tag: "uuid3", translation: "{0} jābūt derīgam 3. versijas UUID", override: false, }, { tag: "uuid4", translation: "{0} jābūt derīgam 4. versijas UUID", override: false, }, { tag: "uuid5", translation: "{0} jābūt derīgam 5. versijas UUID", override: false, }, { tag: "ulid", translation: "{0} jābūt derīgam ULID", override: false, }, { tag: "ascii", translation: "{0} jāsatur tikai ascii rakstu zīmes", override: false, }, { tag: "printascii", translation: "{0} jāsatur tikai drukājamas ascii rakstu zīmes", override: false, }, { tag: "multibyte", translation: "{0} jāsatur multibyte rakstu zīmes", override: false, }, { tag: "datauri", translation: "{0} jāsatur derīgs Data URI", override: false, }, { tag: "latitude", translation: "{0} jāsatur derīgus platuma grādus", override: false, }, { tag: "longitude", translation: "{0} jāsatur derīgus garuma grādus", override: false, }, { tag: "ssn", translation: "{0} jābūt derīgam SSN numuram", override: false, }, { tag: "ipv4", translation: "{0} jābūt derīgai IPv4 adresei", override: false, }, { tag: "ipv6", translation: "{0} jābūt derīgai IPv6 adresei", override: false, }, { tag: "ip", translation: "{0} jābūt derīgai IP adresei", override: false, }, { tag: "cidr", translation: "{0} jāsatur derīgu CIDR notāciju", override: false, }, { tag: "cidrv4", translation: "{0} jāsatur derīgu CIDR notāciju IPv4 adresei", override: false, }, { tag: "cidrv6", translation: "{0} jāsatur derīgu CIDR notāciju IPv6 adresei", override: false, }, { tag: "tcp_addr", translation: "{0} jābūt derīgai TCP adresei", override: false, }, { tag: "tcp4_addr", translation: "{0} jābūt derīgai IPv4 TCP adresei", override: false, }, { tag: "tcp6_addr", translation: "{0} jābūt derīgai IPv6 TCP adresei", override: false, }, { tag: "udp_addr", translation: "{0} jābūt derīgai UDP adresei", override: false, }, { tag: "udp4_addr", translation: "{0} jābūt derīgai IPv4 UDP adresei", override: false, }, { tag: "udp6_addr", translation: "{0} jābūt derīgai IPv6 UDP adresei", override: false, }, { tag: "ip_addr", translation: "{0} jābūt atrisināmai IP adresei", override: false, }, { tag: "ip4_addr", translation: "{0} jābūt atrisināmai IPv4 adresei", override: false, }, { tag: "ip6_addr", translation: "{0} jābūt atrisināmai IPv6 adresei", override: false, }, { tag: "unix_addr", translation: "{0} jābūt atrisināmai UNIX adresei", override: false, }, { tag: "mac", translation: "{0} jābūt derīgai MAC adresei", override: false, }, { tag: "unique", translation: "{0} jāsatur unikālas vērtības", override: false, }, { tag: "iscolor", translation: "{0} jābūt derīgai krāsai", override: false, }, { tag: "oneof", translation: "{0} jābūt vienam no [{1}]", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { s, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return s }, }, { tag: "json", translation: "{0} jābūt derīgai json virknei", override: false, }, { tag: "jwt", translation: "{0} jābūt derīgai jwt virknei", override: false, }, { tag: "lowercase", translation: "{0} jābūt mazo burtu virknei", override: false, }, { tag: "uppercase", translation: "{0} jābūt lielo burtu virknei", override: false, }, { tag: "datetime", translation: "{0} neatbilst formātam {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "postcode_iso3166_alpha2", translation: "{0} neatbilst pasta indeksa formātam valstī {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "postcode_iso3166_alpha2_field", translation: "{0} neatbilst pasta indeksa formātam valstī, kura norādīta laukā {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "boolean", translation: "{0} jābūt derīgai boolean vērtībai", override: false, }, } for _, t := range translations { if t.customTransFunc != nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, t.customTransFunc) } else if t.customTransFunc != nil && t.customRegisFunc == nil { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), t.customTransFunc) } else if t.customTransFunc == nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, translateFunc) } else { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), translateFunc) } if err != nil { return } } return } func registrationFunc(tag string, translation string, override bool) validator.RegisterTranslationsFunc { return func(ut ut.Translator) (err error) { if err = ut.Add(tag, translation, override); err != nil { return } return } } func translateFunc(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t } golang-github-go-playground-validator-v10-10.30.1/translations/lv/lv_test.go000066400000000000000000000526251512410077000267370ustar00rootroot00000000000000package 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"` ISSN string `validate:"issn"` 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.ISSN", expected: "ISSN jābūt derīgam ISSN 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)) } } golang-github-go-playground-validator-v10-10.30.1/translations/nl/000077500000000000000000000000001512410077000247065ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/translations/nl/nl.go000066400000000000000000000772401512410077000256600ustar00rootroot00000000000000package nl import ( "fmt" "log" "reflect" "strconv" "strings" "time" "github.com/go-playground/locales" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" ) // RegisterDefaultTranslations registers a set of default translations // for all built in tag's in validator; you may add your own as desired. func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (err error) { translations := []struct { tag string translation string override bool customRegisFunc validator.RegisterTranslationsFunc customTransFunc validator.TranslationFunc }{ { tag: "required", translation: "{0} is een verplicht veld", override: false, }, { tag: "len", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("len-string", "{0} moet {1} lang zijn", false); err != nil { return } if err = ut.AddCardinal("len-string-character", "{0} karakter", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("len-string-character", "{0} karakters", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("len-number", "{0} moet gelijk zijn aan {1}", false); err != nil { return } if err = ut.Add("len-items", "{0} moet {1} bevatten", false); err != nil { return } if err = ut.AddCardinal("len-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("len-items-item", "{0} items", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("len-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("len-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-items", fe.Field(), c) default: t, err = ut.T("len-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "min", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("min-string", "{0} moet tenminste {1} lang zijn", false); err != nil { return } if err = ut.AddCardinal("min-string-character", "{0} karakter", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("min-string-character", "{0} karakters", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("min-number", "{0} moet {1} of groter zijn", false); err != nil { return } if err = ut.Add("min-items", "{0} moet tenminste {1} bevatten", false); err != nil { return } if err = ut.AddCardinal("min-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("min-items-item", "{0} items", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("min-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("min-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-items", fe.Field(), c) default: t, err = ut.T("min-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "max", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("max-string", "{0} mag maximaal {1} lang zijn", false); err != nil { return } if err = ut.AddCardinal("max-string-character", "{0} karakter", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("max-string-character", "{0} karakters", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("max-number", "{0} moet {1} of kleiner zijn", false); err != nil { return } if err = ut.Add("max-items", "{0} mag maximaal {1} bevatten", false); err != nil { return } if err = ut.AddCardinal("max-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("max-items-item", "{0} items", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("max-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("max-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-items", fe.Field(), c) default: t, err = ut.T("max-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eq", translation: "{0} is niet gelijk aan {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ne", translation: "{0} mag niet gelijk zijn aan {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "lt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lt-string", "{0} moet minder dan {1} lang zijn", false); err != nil { return } if err = ut.AddCardinal("lt-string-character", "{0} karakter", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lt-string-character", "{0} karakters", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-number", "{0} moet kleiner zijn dan {1}", false); err != nil { return } if err = ut.Add("lt-items", "{0} moet minder dan {1} bevatten", false); err != nil { return } if err = ut.AddCardinal("lt-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lt-items-item", "{0} items", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-datetime", "{0} moet kleiner zijn dan de huidige datum & tijd", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "lte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lte-string", "{0} mag maximaal {1} lang zijn", false); err != nil { return } if err = ut.AddCardinal("lte-string-character", "{0} karakter", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lte-string-character", "{0} karakters", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-number", "{0} moet {1} of minder zijn", false); err != nil { return } if err = ut.Add("lte-items", "{0} mag maximaal {1} bevatten", false); err != nil { return } if err = ut.AddCardinal("lte-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lte-items-item", "{0} items", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-datetime", "{0} moet kleiner dan of gelijk aan de huidige datum & tijd zijn", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gt-string", "{0} moet langer dan {1} zijn", false); err != nil { return } if err = ut.AddCardinal("gt-string-character", "{0} karakter", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gt-string-character", "{0} karakters", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-number", "{0} moet groter zijn dan {1}", false); err != nil { return } if err = ut.Add("gt-items", "{0} moet meer dan {1} bevatten", false); err != nil { return } if err = ut.AddCardinal("gt-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gt-items-item", "{0} items", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-datetime", "{0} moet groter zijn dan de huidige datum & tijd", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gte-string", "{0} moet tenminste {1} lang zijn", false); err != nil { return } if err = ut.AddCardinal("gte-string-character", "{0} karakter", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gte-string-character", "{0} karakters", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-number", "{0} moet {1} of groter zijn", false); err != nil { return } if err = ut.Add("gte-items", "{0} moet tenminste {1} bevatten", false); err != nil { return } if err = ut.AddCardinal("gte-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gte-items-item", "{0} items", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-datetime", "{0} moet groter dan of gelijk zijn aan de huidige datum & tijd", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eqfield", translation: "{0} moet gelijk zijn aan {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "eqcsfield", translation: "{0} moet gelijk zijn aan {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "necsfield", translation: "{0} mag niet gelijk zijn aan {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtcsfield", translation: "{0} moet groter zijn dan {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtecsfield", translation: "{0} moet groter dan of gelijk aan {1} zijn", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltcsfield", translation: "{0} moet kleiner zijn dan {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltecsfield", translation: "{0} moet kleiner dan of gelijk aan {1} zijn", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "nefield", translation: "{0} mag niet gelijk zijn aan {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtfield", translation: "{0} moet groter zijn dan {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtefield", translation: "{0} moet groter dan of gelijk aan {1} zijn", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltfield", translation: "{0} moet kleiner zijn dan {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltefield", translation: "{0} moet kleiner dan of gelijk aan {1} zijn", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "alpha", translation: "{0} mag alleen alfabetische karakters bevatten", override: false, }, { tag: "alphanum", translation: "{0} mag alleen alfanumerieke karakters bevatten", override: false, }, { tag: "numeric", translation: "{0} moet een geldige numerieke waarde zijn", override: false, }, { tag: "number", translation: "{0} moet een geldig getal zijn", override: false, }, { tag: "hexadecimal", translation: "{0} moet een geldig hexadecimaal getal zijn", override: false, }, { tag: "hexcolor", translation: "{0} moet een geldige HEX kleur zijn", override: false, }, { tag: "rgb", translation: "{0} moet een geldige RGB kleur zijn", override: false, }, { tag: "rgba", translation: "{0} moet een geldige RGBA kleur zijn", override: false, }, { tag: "hsl", translation: "{0} moet een geldige HSL kleur zijn", override: false, }, { tag: "hsla", translation: "{0} moet een geldige HSLA kleur zijn", override: false, }, { tag: "email", translation: "{0} moet een geldig email adres zijn", override: false, }, { tag: "url", translation: "{0} moet een geldige URL zijn", override: false, }, { tag: "uri", translation: "{0} moet een geldige URI zijn", override: false, }, { tag: "base64", translation: "{0} moet een geldige Base64 string zijn", override: false, }, { tag: "contains", translation: "{0} moet de tekst '{1}' bevatten", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "containsany", translation: "{0} moet tenminste een van de volgende karakters bevatten '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludes", translation: "{0} mag niet de tekst '{1}' bevatten", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesall", translation: "{0} mag niet een van de volgende karakters bevatten '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesrune", translation: "{0} mag niet het volgende bevatten '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "isbn", translation: "{0} moet een geldig ISBN nummer zijn", override: false, }, { tag: "isbn10", translation: "{0} moet een geldig ISBN-10 nummer zijn", override: false, }, { tag: "isbn13", translation: "{0} moet een geldig ISBN-13 nummer zijn", override: false, }, { tag: "issn", translation: "{0} moet een geldig ISSN nummer zijn", override: false, }, { tag: "uuid", translation: "{0} moet een geldige UUID zijn", override: false, }, { tag: "uuid3", translation: "{0} moet een geldige versie 3 UUID zijn", override: false, }, { tag: "uuid4", translation: "{0} moet een geldige versie 4 UUID zijn", override: false, }, { tag: "uuid5", translation: "{0} moet een geldige versie 5 UUID zijn", override: false, }, { tag: "ulid", translation: "{0} moet een geldige ULID zijn", override: false, }, { tag: "ascii", translation: "{0} mag alleen ascii karakters bevatten", override: false, }, { tag: "printascii", translation: "{0} mag alleen afdrukbare ascii karakters bevatten", override: false, }, { tag: "multibyte", translation: "{0} moet multibyte karakters bevatten", override: false, }, { tag: "datauri", translation: "{0} moet een geldige Data URI bevatten", override: false, }, { tag: "latitude", translation: "{0} moet geldige breedtegraadcoördinaten bevatten", override: false, }, { tag: "longitude", translation: "{0} moet geldige lengtegraadcoördinaten bevatten", override: false, }, { tag: "ssn", translation: "{0} moet een geldig SSN nummer zijn", override: false, }, { tag: "ipv4", translation: "{0} moet een geldig IPv4 adres zijn", override: false, }, { tag: "ipv6", translation: "{0} moet een geldig IPv6 adres zijn", override: false, }, { tag: "ip", translation: "{0} moet een geldig IP adres zijn", override: false, }, { tag: "cidr", translation: "{0} moet een geldige CIDR notatie bevatten", override: false, }, { tag: "cidrv4", translation: "{0} moet een geldige CIDR notatie voor een IPv4 adres bevatten", override: false, }, { tag: "cidrv6", translation: "{0} moet een geldige CIDR notatie voor een IPv6 adres bevatten", override: false, }, { tag: "tcp_addr", translation: "{0} moet een geldig TCP adres zijn", override: false, }, { tag: "tcp4_addr", translation: "{0} moet een geldig IPv4 TCP adres zijn", override: false, }, { tag: "tcp6_addr", translation: "{0} moet een geldig IPv6 TCP adres zijn", override: false, }, { tag: "udp_addr", translation: "{0} moet een geldig UDP adres zijn", override: false, }, { tag: "udp4_addr", translation: "{0} moet een geldig IPv4 UDP adres zijn", override: false, }, { tag: "udp6_addr", translation: "{0} moet een geldig IPv6 UDP adres zijn", override: false, }, { tag: "ip_addr", translation: "{0} moet een oplosbaar IP adres zijn", override: false, }, { tag: "ip4_addr", translation: "{0} moet een oplosbaar IPv4 adres zijn", override: false, }, { tag: "ip6_addr", translation: "{0} moet een oplosbaar IPv6 adres zijn", override: false, }, { tag: "unix_addr", translation: "{0} moet een oplosbaar UNIX adres zijn", override: false, }, { tag: "mac", translation: "{0} moet een geldig MAC adres bevatten", override: false, }, { tag: "iscolor", translation: "{0} moet een geldige kleur zijn", override: false, }, { tag: "oneof", translation: "{0} moet een van de volgende zijn [{1}]", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { s, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return s }, }, { tag: "image", translation: "{0} moet een geldige afbeelding zijn", override: false, }, } for _, t := range translations { if t.customTransFunc != nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, t.customTransFunc) } else if t.customTransFunc != nil && t.customRegisFunc == nil { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), t.customTransFunc) } else if t.customTransFunc == nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, translateFunc) } else { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), translateFunc) } if err != nil { return } } return } func registrationFunc(tag string, translation string, override bool) validator.RegisterTranslationsFunc { return func(ut ut.Translator) (err error) { if err = ut.Add(tag, translation, override); err != nil { return } return } } func translateFunc(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t } golang-github-go-playground-validator-v10-10.30.1/translations/nl/nl_test.go000066400000000000000000000447061512410077000267200ustar00rootroot00000000000000package 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"` ISSN string `validate:"issn"` 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"` Image string `validate:"image"` } 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.ISSN", expected: "ISSN moet een geldig ISSN 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]", }, { ns: "Test.Image", expected: "Image moet een geldige afbeelding zijn", }, } 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)) } } golang-github-go-playground-validator-v10-10.30.1/translations/pl/000077500000000000000000000000001512410077000247105ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/translations/pl/pl.go000066400000000000000000000725111512410077000256600ustar00rootroot00000000000000package pl import ( "fmt" "log" "reflect" "strconv" "strings" "time" "github.com/go-playground/locales" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" ) // RegisterDefaultTranslations registers a set of default translations // for all built in tag's in validator; you may add your own as desired. func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (err error) { translations := []struct { tag string translation string override bool customRegisFunc validator.RegisterTranslationsFunc customTransFunc validator.TranslationFunc }{ { tag: "required", translation: "{0} jest wymaganym polem", override: false, }, { tag: "required_if", translation: "{0} jest wymaganym polem", override: false, }, { tag: "required_unless", translation: "{0} jest wymaganym polem", override: false, }, { tag: "required_with", translation: "{0} jest wymaganym polem", override: false, }, { tag: "required_with_all", translation: "{0} jest wymaganym polem", override: false, }, { tag: "required_without", translation: "{0} jest wymaganym polem", override: false, }, { tag: "required_without_all", translation: "{0} jest wymaganym polem", override: false, }, { tag: "excluded_if", translation: "{0} jest wykluczonym polem", override: false, }, { tag: "excluded_unless", translation: "{0} jest wykluczonym polem", override: false, }, { tag: "excluded_with", translation: "{0} jest wykluczonym polem", override: false, }, { tag: "excluded_with_all", translation: "{0} jest wykluczonym polem", override: false, }, { tag: "excluded_without", translation: "{0} jest wykluczonym polem", override: false, }, { tag: "excluded_without_all", translation: "{0} jest wykluczonym polem", override: false, }, { tag: "isdefault", translation: "{0} musi być domyślną wartością", override: false, }, { tag: "len", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("len-string", "{0} musi mieć długość na {1}", false); err != nil { return } if err = ut.Add("len-number", "{0} musi być równe {1}", false); err != nil { return } if err = ut.Add("len-items", "{0} musi zawierać {1}", false); err != nil { return } if err = registerCardinals(ut, "len"); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("len-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("len-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-items", fe.Field(), c) default: t, err = ut.T("len-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "min", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("min-string", "{0} musi mieć długość przynajmniej na {1}", false); err != nil { return } if err = ut.Add("min-number", "{0} musi być równe {1} lub więcej", false); err != nil { return } if err = ut.Add("min-items", "{0} musi zawierać przynajmniej {1}", false); err != nil { return } if err = registerCardinals(ut, "min"); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("min-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("min-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-items", fe.Field(), c) default: t, err = ut.T("min-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "max", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("max-string", "{0} musi mieć długość maksymalnie na {1}", false); err != nil { return } if err = ut.Add("max-number", "{0} musi być równe {1} lub mniej", false); err != nil { return } if err = ut.Add("max-items", "{0} musi zawierać maksymalnie {1}", false); err != nil { return } if err = registerCardinals(ut, "max"); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("max-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("max-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-items", fe.Field(), c) default: t, err = ut.T("max-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eq", translation: "{0} nie równa się {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "ne", translation: "{0} nie powinien być równy {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "lt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lt-string", "{0} musi mieć długość mniejszą niż {1}", false); err != nil { return } if err = ut.Add("lt-number", "{0} musi być mniejsze niż {1}", false); err != nil { return } if err = ut.Add("lt-items", "{0} musi zawierać mniej niż {1}", false); err != nil { return } if err = ut.Add("lt-datetime", "{0} musi być mniejsze niż obecny dzień i godzina", false); err != nil { return } if err = registerCardinals(ut, "lt"); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "lte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lte-string", "{0} musi mieć długość maksymalnie na {1}", false); err != nil { return } if err = ut.Add("lte-number", "{0} musi być równe {1} lub mniej", false); err != nil { return } if err = ut.Add("lte-items", "{0} musi zawierać maksymalnie {1}", false); err != nil { return } if err = ut.Add("lte-datetime", "{0} musi być mniejsze lub równe niż obecny dzień i godzina", false); err != nil { return } if err = registerCardinals(ut, "lte"); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gt-string", "{0} musi mieć długość większą niż {1}", false); err != nil { return } if err = ut.Add("gt-number", "{0} musi być większe niż {1}", false); err != nil { return } if err = ut.Add("gt-items", "{0} musi zawierać więcej niż {1}", false); err != nil { return } if err = ut.Add("gt-datetime", "{0} musi być większe niż obecny dzień i godzina", false); err != nil { return } if err = registerCardinals(ut, "gt"); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gte-string", "{0} musi mieć długość przynajmniej na {1}", false); err != nil { return } if err = ut.Add("gte-number", "{0} musi być równe {1} lub większe", false); err != nil { return } if err = ut.Add("gte-items", "{0} musi zawierać co najmniej {1}", false); err != nil { return } if err = ut.Add("gte-datetime", "{0} musi być większe lub równe niż obecny dzień i godzina", false); err != nil { return } if err = registerCardinals(ut, "gte"); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eqfield", translation: "{0} musi być równe {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "eqcsfield", translation: "{0} musi być równe {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "necsfield", translation: "{0} nie może być równe {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "gtcsfield", translation: "{0} musi być większe niż {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "gtecsfield", translation: "{0} musi być większe lub równe niż {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "ltcsfield", translation: "{0} musi być mniejsze niż {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "ltecsfield", translation: "{0} musi być mniejsze lub równe {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "nefield", translation: "{0} nie może być równe {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "gtfield", translation: "{0} musi być większe niż {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "gtefield", translation: "{0} musi być większe lub równe {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "ltfield", translation: "{0} musi być mniejsze niż {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "ltefield", translation: "{0} musi być mniejsze lub równe {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "alpha", translation: "{0} może zawierać wyłącznie znaki alfabetu", override: false, }, { tag: "alphanum", translation: "{0} może zawierać wyłącznie znaki alfanumeryczne", override: false, }, { tag: "numeric", translation: "{0} musi być poprawną wartością numeryczną", override: false, }, { tag: "number", translation: "{0} musi być poprawną liczbą", override: false, }, { tag: "hexadecimal", translation: "{0} musi być poprawną wartością heksadecymalną", override: false, }, { tag: "hexcolor", translation: "{0} musi być poprawnym kolorem w formacie HEX", override: false, }, { tag: "rgb", translation: "{0} musi być poprawnym kolorem w formacie RGB", override: false, }, { tag: "rgba", translation: "{0} musi być poprawnym kolorem w formacie RGBA", override: false, }, { tag: "hsl", translation: "{0} musi być poprawnym kolorem w formacie HSL", override: false, }, { tag: "hsla", translation: "{0} musi być poprawnym kolorem w formacie HSLA", override: false, }, { tag: "e164", translation: "{0} musi być poprawnym numerem telefonu w formacie E.164", override: false, }, { tag: "email", translation: "{0} musi być poprawnym adresem email", override: false, }, { tag: "url", translation: "{0} musi być poprawnym adresem URL", override: false, }, { tag: "uri", translation: "{0} musi być poprawnym adresem URI", override: false, }, { tag: "base64", translation: "{0} musi być ciągiem znaków zakodowanym w formacie Base64", override: false, }, { tag: "contains", translation: "{0} musi zawierać tekst '{1}'", override: false, customTransFunc: translateFuncWithParam, }, { tag: "containsany", translation: "{0} musi zawierać przynajmniej jeden z następujących znaków '{1}'", override: false, customTransFunc: translateFuncWithParam, }, { tag: "excludes", translation: "{0} nie może zawierać tekstu '{1}'", override: false, customTransFunc: translateFuncWithParam, }, { tag: "excludesall", translation: "{0} nie może zawierać żadnych z następujących znaków '{1}'", override: false, customTransFunc: translateFuncWithParam, }, { tag: "excludesrune", translation: "{0} nie może zawierać następujących znaków '{1}'", override: false, customTransFunc: translateFuncWithParam, }, { tag: "isbn", translation: "{0} musi być poprawnym numerem ISBN", override: false, }, { tag: "isbn10", translation: "{0} musi być poprawnym numerem ISBN-10", override: false, }, { tag: "isbn13", translation: "{0} musi być poprawnym numerem ISBN-13", override: false, }, { tag: "issn", translation: "{0} musi być poprawnym numerem ISSN", override: false, }, { tag: "uuid", translation: "{0} musi być poprawnym identyfikatorem UUID", override: false, }, { tag: "uuid3", translation: "{0} musi być poprawnym identyfikatorem UUID w wersji 3", override: false, }, { tag: "uuid4", translation: "{0} musi być poprawnym identyfikatorem UUID w wersji 4", override: false, }, { tag: "uuid5", translation: "{0} musi być poprawnym identyfikatorem UUID w wersji 5", override: false, }, { tag: "ulid", translation: "{0} musi być poprawnym identyfikatorem ULID", override: false, }, { tag: "ascii", translation: "{0} może zawierać wyłącznie znaki ASCII", override: false, }, { tag: "printascii", translation: "{0} może zawierać wyłącznie drukowalne znaki ASCII", override: false, }, { tag: "multibyte", translation: "{0} musi zawierać znaki wielobajtowe", override: false, }, { tag: "datauri", translation: "{0} musi zawierać poprawnie zakodowane dane w formie URI", override: false, }, { tag: "latitude", translation: "{0} musi zawierać poprawną szerokość geograficzną", override: false, }, { tag: "longitude", translation: "{0} musi zawierać poprawną długość geograficzną", override: false, }, { tag: "ssn", translation: "{0} musi zawierać poprawny numer SSN", override: false, }, { tag: "ipv4", translation: "{0} musi zawierać poprawny adres IPv4", override: false, }, { tag: "ipv6", translation: "{0} musi zawierać poprawny adres IPv6", override: false, }, { tag: "ip", translation: "{0} musi zawierać poprawny adres IP", override: false, }, { tag: "cidr", translation: "{0} musi zawierać adres zapisany metodą CIDR", override: false, }, { tag: "cidrv4", translation: "{0} musi zawierać adres IPv4 zapisany metodą CIDR", override: false, }, { tag: "cidrv6", translation: "{0} musi zawierać adres IPv6 zapisany metodą CIDR", override: false, }, { tag: "tcp_addr", translation: "{0} musi być poprawnym adresem TCP", override: false, }, { tag: "tcp4_addr", translation: "{0} musi być poprawnym adresem IPv4 TCP", override: false, }, { tag: "tcp6_addr", translation: "{0} musi być poprawnym adresem IPv6 TCP", override: false, }, { tag: "udp_addr", translation: "{0} musi być poprawnym adresem UDP", override: false, }, { tag: "udp4_addr", translation: "{0} musi być poprawnym adresem IPv4 UDP", override: false, }, { tag: "udp6_addr", translation: "{0} musi być poprawnym adresem IPv6 UDP", override: false, }, { tag: "ip_addr", translation: "{0} musi być rozpoznawalnym adresem IP", override: false, }, { tag: "ip4_addr", translation: "{0} musi być rozpoznawalnym adresem IPv4", override: false, }, { tag: "ip6_addr", translation: "{0} musi być rozpoznawalnym adresem IPv6", override: false, }, { tag: "unix_addr", translation: "{0} musi być rozpoznawalnym adresem UNIX", override: false, }, { tag: "mac", translation: "{0} musi zawierać poprawny MAC adres", override: false, }, { tag: "fqdn", translation: "{0} musi być poprawnym FQDN", override: false, }, { tag: "unique", translation: "{0} musi zawierać unikalne wartości", override: false, }, { tag: "iscolor", translation: "{0} musi być prawdziwym kolorem", override: false, }, { tag: "cron", translation: "{0} musi być prawdziwym wyrażeniem cron", override: false, }, { tag: "oneof", translation: "{0} musi być jednym z [{1}]", override: false, customTransFunc: translateFuncWithParam, }, { tag: "json", translation: "{0} musi być ciągiem znaków w formacie JSON", override: false, }, { tag: "jwt", translation: "{0} musi być ciągiem znaków w formacie JWT", override: false, }, { tag: "lowercase", translation: "{0} musi zawierać wyłącznie małe litery", override: false, }, { tag: "uppercase", translation: "{0} musi zawierać wyłącznie duże litery", override: false, }, { tag: "datetime", translation: "{0} nie spełnia formatu {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "postcode_iso3166_alpha2", translation: "{0} nie spełnia formatu kodu pocztowego kraju {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "postcode_iso3166_alpha2_field", translation: "{0} nie spełnia formatu kodu pocztowego kraju z pola {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "boolean", translation: "{0} musi być wartością logiczną", override: false, }, { tag: "image", translation: "{0} musi być obrazem", override: false, }, { tag: "cve", translation: "{0} musi być poprawnym identyfikatorem CVE", override: false, }, } for _, t := range translations { if t.customTransFunc != nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, t.customTransFunc) } else if t.customTransFunc != nil && t.customRegisFunc == nil { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), t.customTransFunc) } else if t.customTransFunc == nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, translateFunc) } else { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), translateFunc) } if err != nil { return } } return } func registrationFunc(tag string, translation string, override bool) validator.RegisterTranslationsFunc { return func(ut ut.Translator) (err error) { if err = ut.Add(tag, translation, override); err != nil { return } return } } func translateFunc(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t } func translateFuncWithParam(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t } func registerCardinals(ut ut.Translator, prefix string) (err error) { var ( stringCharacterKey = fmt.Sprintf("%s-string-character", prefix) itemsItemKey = fmt.Sprintf("%s-items-item", prefix) ) if err = ut.AddCardinal(stringCharacterKey, "{0} znak", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal(stringCharacterKey, "{0} znaki", locales.PluralRuleFew, false); err != nil { return } if err = ut.AddCardinal(stringCharacterKey, "{0} znaków", locales.PluralRuleMany, false); err != nil { return } if err = ut.AddCardinal(stringCharacterKey, "{0} znaków", locales.PluralRuleOther, false); err != nil { return } if err = ut.AddCardinal(itemsItemKey, "{0} element", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal(itemsItemKey, "{0} elementy", locales.PluralRuleFew, false); err != nil { return } if err = ut.AddCardinal(itemsItemKey, "{0} elementów", locales.PluralRuleMany, false); err != nil { return } if err = ut.AddCardinal(itemsItemKey, "{0} elementów", locales.PluralRuleOther, false); err != nil { return } return } golang-github-go-playground-validator-v10-10.30.1/translations/pl/pl_test.go000066400000000000000000000664411512410077000267240ustar00rootroot00000000000000package pl import ( "testing" "time" . "github.com/go-playground/assert/v2" polish "github.com/go-playground/locales/pl" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" ) func TestTranslations(t *testing.T) { pl := polish.New() uni := ut.New(pl, pl) trans, ok := uni.GetTranslator("pl") if !ok { t.Fatalf("didn't found translator") } 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 RequiredUnless string RequiredWith string RequiredWithAll string RequiredWithout string RequiredWithoutAll string ExcludedIf string ExcludedUnless string ExcludedWith string ExcludedWithAll string ExcludedWithout string ExcludedWithoutAll 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"` RequiredUnless string `validate:"required_unless=Inner.RequiredUnless abcd"` RequiredWith string `validate:"required_with=Inner.RequiredWith"` RequiredWithAll string `validate:"required_with_all=Inner.RequiredWith Inner.RequiredWithAll"` RequiredWithout string `validate:"required_without=Inner.RequiredWithout"` RequiredWithoutAll string `validate:"required_without_all=Inner.RequiredWithout Inner.RequiredWithoutAll"` ExcludedIf string `validate:"excluded_if=Inner.ExcludedIf abcd"` ExcludedUnless string `validate:"excluded_unless=Inner.ExcludedUnless abcd"` ExcludedWith string `validate:"excluded_with=Inner.ExcludedWith"` ExcludedWithout string `validate:"excluded_with_all=Inner.ExcludedWithAll"` ExcludedWithAll string `validate:"excluded_without=Inner.ExcludedWithout"` ExcludedWithoutAll string `validate:"excluded_without_all=Inner.ExcludedWithoutAll"` IsDefault string `validate:"isdefault"` 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"` GteStringSingle string `validate:"gte=1"` GteStringFive string `validate:"gte=5"` GteStringTwentyOne string `validate:"gte=21"` GteStringBigNumber string `validate:"gte=852"` GteStringAnotherBigNumber string `validate:"gte=2137"` 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"` ISSN string `validate:"issn"` 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"` Image string `validate:"image"` CveString string `validate:"cve"` } var test Test test.Inner.EqCSFieldString = "1234" test.Inner.GtCSFieldString = "1234" test.Inner.GteCSFieldString = "1234" test.Inner.RequiredUnless = "1234" test.Inner.RequiredWith = "1234" test.Inner.RequiredWithAll = "1234" test.Inner.ExcludedIf = "abcd" test.Inner.ExcludedUnless = "1234" test.Inner.ExcludedWith = "1234" test.Inner.ExcludedWithAll = "1234" test.ExcludedIf = "1234" test.ExcludedUnless = "1234" test.ExcludedWith = "1234" test.ExcludedWithAll = "1234" test.ExcludedWithout = "1234" test.ExcludedWithoutAll = "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 musi być prawdziwym kolorem", }, { ns: "Test.MAC", expected: "MAC musi zawierać poprawny MAC adres", }, { ns: "Test.FQDN", expected: "FQDN musi być poprawnym FQDN", }, { ns: "Test.IPAddr", expected: "IPAddr musi być rozpoznawalnym adresem IP", }, { ns: "Test.IPAddrv4", expected: "IPAddrv4 musi być rozpoznawalnym adresem IPv4", }, { ns: "Test.IPAddrv6", expected: "IPAddrv6 musi być rozpoznawalnym adresem IPv6", }, { ns: "Test.UDPAddr", expected: "UDPAddr musi być poprawnym adresem UDP", }, { ns: "Test.UDPAddrv4", expected: "UDPAddrv4 musi być poprawnym adresem IPv4 UDP", }, { ns: "Test.UDPAddrv6", expected: "UDPAddrv6 musi być poprawnym adresem IPv6 UDP", }, { ns: "Test.TCPAddr", expected: "TCPAddr musi być poprawnym adresem TCP", }, { ns: "Test.TCPAddrv4", expected: "TCPAddrv4 musi być poprawnym adresem IPv4 TCP", }, { ns: "Test.TCPAddrv6", expected: "TCPAddrv6 musi być poprawnym adresem IPv6 TCP", }, { ns: "Test.CIDR", expected: "CIDR musi zawierać adres zapisany metodą CIDR", }, { ns: "Test.CIDRv4", expected: "CIDRv4 musi zawierać adres IPv4 zapisany metodą CIDR", }, { ns: "Test.CIDRv6", expected: "CIDRv6 musi zawierać adres IPv6 zapisany metodą CIDR", }, { ns: "Test.SSN", expected: "SSN musi zawierać poprawny numer SSN", }, { ns: "Test.IP", expected: "IP musi zawierać poprawny adres IP", }, { ns: "Test.IPv4", expected: "IPv4 musi zawierać poprawny adres IPv4", }, { ns: "Test.IPv6", expected: "IPv6 musi zawierać poprawny adres IPv6", }, { ns: "Test.DataURI", expected: "DataURI musi zawierać poprawnie zakodowane dane w formie URI", }, { ns: "Test.Latitude", expected: "Latitude musi zawierać poprawną szerokość geograficzną", }, { ns: "Test.Longitude", expected: "Longitude musi zawierać poprawną długość geograficzną", }, { ns: "Test.MultiByte", expected: "MultiByte musi zawierać znaki wielobajtowe", }, { ns: "Test.ASCII", expected: "ASCII może zawierać wyłącznie znaki ASCII", }, { ns: "Test.PrintableASCII", expected: "PrintableASCII może zawierać wyłącznie drukowalne znaki ASCII", }, { ns: "Test.UUID", expected: "UUID musi być poprawnym identyfikatorem UUID", }, { ns: "Test.UUID3", expected: "UUID3 musi być poprawnym identyfikatorem UUID w wersji 3", }, { ns: "Test.UUID4", expected: "UUID4 musi być poprawnym identyfikatorem UUID w wersji 4", }, { ns: "Test.UUID5", expected: "UUID5 musi być poprawnym identyfikatorem UUID w wersji 5", }, { ns: "Test.ULID", expected: "ULID musi być poprawnym identyfikatorem ULID", }, { ns: "Test.ISBN", expected: "ISBN musi być poprawnym numerem ISBN", }, { ns: "Test.ISBN10", expected: "ISBN10 musi być poprawnym numerem ISBN-10", }, { ns: "Test.ISBN13", expected: "ISBN13 musi być poprawnym numerem ISBN-13", }, { ns: "Test.ISSN", expected: "ISSN musi być poprawnym numerem ISSN", }, { ns: "Test.Excludes", expected: "Excludes nie może zawierać tekstu 'text'", }, { ns: "Test.ExcludesAll", expected: "ExcludesAll nie może zawierać żadnych z następujących znaków '!@#$'", }, { ns: "Test.ExcludesRune", expected: "ExcludesRune nie może zawierać następujących znaków '☻'", }, { ns: "Test.ContainsAny", expected: "ContainsAny musi zawierać przynajmniej jeden z następujących znaków '!@#$'", }, { ns: "Test.Contains", expected: "Contains musi zawierać tekst 'purpose'", }, { ns: "Test.Base64", expected: "Base64 musi być ciągiem znaków zakodowanym w formacie Base64", }, { ns: "Test.Email", expected: "Email musi być poprawnym adresem email", }, { ns: "Test.URL", expected: "URL musi być poprawnym adresem URL", }, { ns: "Test.URI", expected: "URI musi być poprawnym adresem URI", }, { ns: "Test.RGBColorString", expected: "RGBColorString musi być poprawnym kolorem w formacie RGB", }, { ns: "Test.RGBAColorString", expected: "RGBAColorString musi być poprawnym kolorem w formacie RGBA", }, { ns: "Test.HSLColorString", expected: "HSLColorString musi być poprawnym kolorem w formacie HSL", }, { ns: "Test.HSLAColorString", expected: "HSLAColorString musi być poprawnym kolorem w formacie HSLA", }, { ns: "Test.HexadecimalString", expected: "HexadecimalString musi być poprawną wartością heksadecymalną", }, { ns: "Test.HexColorString", expected: "HexColorString musi być poprawnym kolorem w formacie HEX", }, { ns: "Test.NumberString", expected: "NumberString musi być poprawną liczbą", }, { ns: "Test.NumericString", expected: "NumericString musi być poprawną wartością numeryczną", }, { ns: "Test.AlphanumString", expected: "AlphanumString może zawierać wyłącznie znaki alfanumeryczne", }, { ns: "Test.AlphaString", expected: "AlphaString może zawierać wyłącznie znaki alfabetu", }, { ns: "Test.LtFieldString", expected: "LtFieldString musi być mniejsze niż MaxString", }, { ns: "Test.LteFieldString", expected: "LteFieldString musi być mniejsze lub równe MaxString", }, { ns: "Test.GtFieldString", expected: "GtFieldString musi być większe niż MaxString", }, { ns: "Test.GteFieldString", expected: "GteFieldString musi być większe lub równe MaxString", }, { ns: "Test.NeFieldString", expected: "NeFieldString nie może być równe EqFieldString", }, { ns: "Test.LtCSFieldString", expected: "LtCSFieldString musi być mniejsze niż Inner.LtCSFieldString", }, { ns: "Test.LteCSFieldString", expected: "LteCSFieldString musi być mniejsze lub równe Inner.LteCSFieldString", }, { ns: "Test.GtCSFieldString", expected: "GtCSFieldString musi być większe niż Inner.GtCSFieldString", }, { ns: "Test.GteCSFieldString", expected: "GteCSFieldString musi być większe lub równe niż Inner.GteCSFieldString", }, { ns: "Test.NeCSFieldString", expected: "NeCSFieldString nie może być równe Inner.NeCSFieldString", }, { ns: "Test.EqCSFieldString", expected: "EqCSFieldString musi być równe Inner.EqCSFieldString", }, { ns: "Test.EqFieldString", expected: "EqFieldString musi być równe MaxString", }, { ns: "Test.GteString", expected: "GteString musi mieć długość przynajmniej na 3 znaki", }, { ns: "Test.GteStringSingle", expected: "GteStringSingle musi mieć długość przynajmniej na 1 znak", }, { ns: "Test.GteStringFive", expected: "GteStringFive musi mieć długość przynajmniej na 5 znaków", }, { ns: "Test.GteStringTwentyOne", expected: "GteStringTwentyOne musi mieć długość przynajmniej na 21 znaków", }, { ns: "Test.GteStringBigNumber", expected: "GteStringBigNumber musi mieć długość przynajmniej na 852 znaki", }, { ns: "Test.GteStringAnotherBigNumber", expected: "GteStringAnotherBigNumber musi mieć długość przynajmniej na 2 137 znaków", }, { ns: "Test.GteNumber", expected: "GteNumber musi być równe 5,56 lub większe", }, { ns: "Test.GteMultiple", expected: "GteMultiple musi zawierać co najmniej 2 elementy", }, { ns: "Test.GteTime", expected: "GteTime musi być większe lub równe niż obecny dzień i godzina", }, { ns: "Test.GtString", expected: "GtString musi mieć długość większą niż 3 znaki", }, { ns: "Test.GtNumber", expected: "GtNumber musi być większe niż 5,56", }, { ns: "Test.GtMultiple", expected: "GtMultiple musi zawierać więcej niż 2 elementy", }, { ns: "Test.GtTime", expected: "GtTime musi być większe niż obecny dzień i godzina", }, { ns: "Test.LteString", expected: "LteString musi mieć długość maksymalnie na 3 znaki", }, { ns: "Test.LteNumber", expected: "LteNumber musi być równe 5,56 lub mniej", }, { ns: "Test.LteMultiple", expected: "LteMultiple musi zawierać maksymalnie 2 elementy", }, { ns: "Test.LteTime", expected: "LteTime musi być mniejsze lub równe niż obecny dzień i godzina", }, { ns: "Test.LtString", expected: "LtString musi mieć długość mniejszą niż 3 znaki", }, { ns: "Test.LtNumber", expected: "LtNumber musi być mniejsze niż 5,56", }, { ns: "Test.LtMultiple", expected: "LtMultiple musi zawierać mniej niż 2 elementy", }, { ns: "Test.LtTime", expected: "LtTime musi być mniejsze niż obecny dzień i godzina", }, { ns: "Test.NeString", expected: "NeString nie powinien być równy ", }, { ns: "Test.NeNumber", expected: "NeNumber nie powinien być równy 0.00", }, { ns: "Test.NeMultiple", expected: "NeMultiple nie powinien być równy 0", }, { ns: "Test.EqString", expected: "EqString nie równa się 3", }, { ns: "Test.EqNumber", expected: "EqNumber nie równa się 2.33", }, { ns: "Test.EqMultiple", expected: "EqMultiple nie równa się 7", }, { ns: "Test.MaxString", expected: "MaxString musi mieć długość maksymalnie na 3 znaki", }, { ns: "Test.MaxNumber", expected: "MaxNumber musi być równe 1 113,00 lub mniej", }, { ns: "Test.MaxMultiple", expected: "MaxMultiple musi zawierać maksymalnie 7 elementów", }, { ns: "Test.MinString", expected: "MinString musi mieć długość przynajmniej na 1 znak", }, { ns: "Test.MinNumber", expected: "MinNumber musi być równe 1 113,00 lub więcej", }, { ns: "Test.MinMultiple", expected: "MinMultiple musi zawierać przynajmniej 7 elementów", }, { ns: "Test.LenString", expected: "LenString musi mieć długość na 1 znak", }, { ns: "Test.LenNumber", expected: "LenNumber musi być równe 1 113,00", }, { ns: "Test.LenMultiple", expected: "LenMultiple musi zawierać 7 elementów", }, { ns: "Test.RequiredString", expected: "RequiredString jest wymaganym polem", }, { ns: "Test.RequiredIf", expected: "RequiredIf jest wymaganym polem", }, { ns: "Test.RequiredNumber", expected: "RequiredNumber jest wymaganym polem", }, { ns: "Test.RequiredMultiple", expected: "RequiredMultiple jest wymaganym polem", }, { ns: "Test.RequiredUnless", expected: "RequiredUnless jest wymaganym polem", }, { ns: "Test.RequiredWith", expected: "RequiredWith jest wymaganym polem", }, { ns: "Test.RequiredWithAll", expected: "RequiredWithAll jest wymaganym polem", }, { ns: "Test.RequiredWithout", expected: "RequiredWithout jest wymaganym polem", }, { ns: "Test.RequiredWithoutAll", expected: "RequiredWithoutAll jest wymaganym polem", }, { ns: "Test.ExcludedIf", expected: "ExcludedIf jest wykluczonym polem", }, { ns: "Test.ExcludedUnless", expected: "ExcludedUnless jest wykluczonym polem", }, { ns: "Test.ExcludedWith", expected: "ExcludedWith jest wykluczonym polem", }, { ns: "Test.ExcludedWithAll", expected: "ExcludedWithAll jest wykluczonym polem", }, { ns: "Test.ExcludedWithout", expected: "ExcludedWithout jest wykluczonym polem", }, { ns: "Test.ExcludedWithoutAll", expected: "ExcludedWithoutAll jest wykluczonym polem", }, { ns: "Test.StrPtrMinLen", expected: "StrPtrMinLen musi mieć długość przynajmniej na 10 znaków", }, { ns: "Test.StrPtrMaxLen", expected: "StrPtrMaxLen musi mieć długość maksymalnie na 1 znak", }, { ns: "Test.StrPtrLen", expected: "StrPtrLen musi mieć długość na 2 znaki", }, { ns: "Test.StrPtrLt", expected: "StrPtrLt musi mieć długość mniejszą niż 1 znak", }, { ns: "Test.StrPtrLte", expected: "StrPtrLte musi mieć długość maksymalnie na 1 znak", }, { ns: "Test.StrPtrGt", expected: "StrPtrGt musi mieć długość większą niż 10 znaków", }, { ns: "Test.StrPtrGte", expected: "StrPtrGte musi mieć długość przynajmniej na 10 znaków", }, { ns: "Test.OneOfString", expected: "OneOfString musi być jednym z [red green]", }, { ns: "Test.OneOfInt", expected: "OneOfInt musi być jednym z [5 63]", }, { ns: "Test.UniqueSlice", expected: "UniqueSlice musi zawierać unikalne wartości", }, { ns: "Test.UniqueArray", expected: "UniqueArray musi zawierać unikalne wartości", }, { ns: "Test.UniqueMap", expected: "UniqueMap musi zawierać unikalne wartości", }, { ns: "Test.JSONString", expected: "JSONString musi być ciągiem znaków w formacie JSON", }, { ns: "Test.JWTString", expected: "JWTString musi być ciągiem znaków w formacie JWT", }, { ns: "Test.LowercaseString", expected: "LowercaseString musi zawierać wyłącznie małe litery", }, { ns: "Test.UppercaseString", expected: "UppercaseString musi zawierać wyłącznie duże litery", }, { ns: "Test.Datetime", expected: "Datetime nie spełnia formatu 2006-01-02", }, { ns: "Test.PostCode", expected: "PostCode nie spełnia formatu kodu pocztowego kraju SG", }, { ns: "Test.PostCodeByField", expected: "PostCodeByField nie spełnia formatu kodu pocztowego kraju z pola PostCodeCountry", }, { ns: "Test.BooleanString", expected: "BooleanString musi być wartością logiczną", }, { ns: "Test.Image", expected: "Image musi być obrazem", }, { ns: "Test.CveString", expected: "CveString musi być poprawnym identyfikatorem CVE", }, } 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)) } } golang-github-go-playground-validator-v10-10.30.1/translations/pt/000077500000000000000000000000001512410077000247205ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/translations/pt/pt.go000066400000000000000000001006611512410077000256760ustar00rootroot00000000000000package pt import ( "fmt" "log" "reflect" "strconv" "strings" "time" "github.com/go-playground/locales" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" ) // RegisterDefaultTranslations registers a set of default translations // for all built in tag's in validator; you may add your own as desired. func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (err error) { translations := []struct { tag string translation string override bool customRegisFunc validator.RegisterTranslationsFunc customTransFunc validator.TranslationFunc }{ { tag: "required", translation: "{0} é obrigatório", override: false, }, { tag: "len", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("len-string", "{0} deve ter {1}", false); err != nil { return } if err = ut.AddCardinal("len-string-character", "{0} caractere", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("len-string-character", "{0} caracteres", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("len-number", "{0} deve ser igual a {1}", false); err != nil { return } if err = ut.Add("len-items", "{0} deve conter {1}", false); err != nil { return } if err = ut.AddCardinal("len-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("len-items-item", "{0} items", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("len-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("len-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-items", fe.Field(), c) default: t, err = ut.T("len-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "min", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("min-string", "{0} deve ter pelo menos {1}", false); err != nil { return } if err = ut.AddCardinal("min-string-character", "{0} caractere", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("min-string-character", "{0} caracteres", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("min-number", "{0} deve ser {1} ou superior", false); err != nil { return } if err = ut.Add("min-items", "{0} deve conter pelo menos {1}", false); err != nil { return } if err = ut.AddCardinal("min-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("min-items-item", "{0} items", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("min-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("min-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-items", fe.Field(), c) default: t, err = ut.T("min-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "max", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("max-string", "{0} deve ter no máximo {1}", false); err != nil { return } if err = ut.AddCardinal("max-string-character", "{0} caractere", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("max-string-character", "{0} caracteres", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("max-number", "{0} deve ser {1} ou menos", false); err != nil { return } if err = ut.Add("max-items", "{0} deve conter no máximo {1}", false); err != nil { return } if err = ut.AddCardinal("max-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("max-items-item", "{0} items", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("max-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("max-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-items", fe.Field(), c) default: t, err = ut.T("max-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eq", translation: "{0} não é igual a {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ne", translation: "{0} não deve ser igual a {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "lt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lt-string", "{0} deve ter menos de {1}", false); err != nil { return } if err = ut.AddCardinal("lt-string-character", "{0} caractere", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lt-string-character", "{0} caracteres", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-number", "{0} deve ser menor que {1}", false); err != nil { return } if err = ut.Add("lt-items", "{0} deve conter menos de {1}", false); err != nil { return } if err = ut.AddCardinal("lt-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lt-items-item", "{0} items", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-datetime", "{0} deve ser anterior à data / hora atual", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "lte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lte-string", "{0} deve ter no máximo {1}", false); err != nil { return } if err = ut.AddCardinal("lte-string-character", "{0} caractere", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lte-string-character", "{0} caracteres", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-number", "{0} deve ser menor ou igual a {1}", false); err != nil { return } if err = ut.Add("lte-items", "{0} deve conter no máximo {1}", false); err != nil { return } if err = ut.AddCardinal("lte-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lte-items-item", "{0} items", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-datetime", "{0} deve ser anterior ou igual à data/hora atual", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gt-string", "{0} deve conter mais de {1}", false); err != nil { return } if err = ut.AddCardinal("gt-string-character", "{0} caractere", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gt-string-character", "{0} caracteres", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-number", "{0} deve ser maior que {1}", false); err != nil { return } if err = ut.Add("gt-items", "{0} deve conter mais de {1}", false); err != nil { return } if err = ut.AddCardinal("gt-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gt-items-item", "{0} items", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-datetime", "{0} deve ser posterior à data/hora atual", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gte-string", "{0} deve ter pelo menos {1}", false); err != nil { return } if err = ut.AddCardinal("gte-string-character", "{0} caractere", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gte-string-character", "{0} caracteres", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-number", "{0} deve ser maior ou igual a {1}", false); err != nil { return } if err = ut.Add("gte-items", "{0} deve conter pelo menos {1}", false); err != nil { return } if err = ut.AddCardinal("gte-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gte-items-item", "{0} items", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-datetime", "{0} deve ser posterior ou igual à data/hora atual", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eqfield", translation: "{0} deve ser igual a {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "eqcsfield", translation: "{0} deve ser igual a {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "necsfield", translation: "{0} não deve ser igual a {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtcsfield", translation: "{0} deve ser maior que {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtecsfield", translation: "{0} deve ser maior ou igual que {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltcsfield", translation: "{0} deve ser menor que {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltecsfield", translation: "{0} deve ser menor ou igual que {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "nefield", translation: "{0} não deve ser igual a {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtfield", translation: "{0} deve ser maior que {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtefield", translation: "{0} deve ser maior ou igual que {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltfield", translation: "{0} deve ser menor que {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltefield", translation: "{0} deve ser menor ou igual que {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "alpha", translation: "{0} deve conter apenas caracteres alfabéticos", override: false, }, { tag: "alphanum", translation: "{0} deve conter apenas caracteres alfanuméricos", override: false, }, { tag: "numeric", translation: "{0} deve ser um valor numérico válido", override: false, }, { tag: "number", translation: "{0} deve ser um número válido", override: false, }, { tag: "hexadecimal", translation: "{0} deve ser um hexadecimal válido", override: false, }, { tag: "hexcolor", translation: "{0} deve ser uma cor HEX válida", override: false, }, { tag: "rgb", translation: "{0} deve ser uma cor RGB válida", override: false, }, { tag: "rgba", translation: "{0} deve ser uma cor RGBA válida", override: false, }, { tag: "hsl", translation: "{0} deve ser uma cor HSL válida", override: false, }, { tag: "hsla", translation: "{0} deve ser uma cor HSLA válida", override: false, }, { tag: "e164", translation: "{0} deve ser um número de telefone válido no formato E.164", override: false, }, { tag: "email", translation: "{0} deve ser um endereço de e-mail válido", override: false, }, { tag: "url", translation: "{0} deve ser um URL válido", override: false, }, { tag: "uri", translation: "{0} deve ser um URI válido", override: false, }, { tag: "base64", translation: "{0} deve ser uma string Base64 válida", override: false, }, { tag: "contains", translation: "{0} deve conter o texto '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "containsany", translation: "{0} deve conter pelo menos um dos seguintes caracteres '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludes", translation: "{0} não deve conter o texto '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesall", translation: "{0} não deve conter os seguintes caracteres '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesrune", translation: "{0} não pode conter o seguinte '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "isbn", translation: "{0} deve ser um número de ISBN válido", override: false, }, { tag: "isbn10", translation: "{0} deve ser um número ISBN-10 válido", override: false, }, { tag: "isbn13", translation: "{0} deve ser um número ISBN-13 válido", override: false, }, { tag: "issn", translation: "{0} deve ser um número ISSN válido", override: false, }, { tag: "uuid", translation: "{0} deve ser um UUID válido", override: false, }, { tag: "uuid3", translation: "{0} deve ser um UUID versão 3 válido", override: false, }, { tag: "uuid4", translation: "{0} deve ser um UUID versão 4 válido", override: false, }, { tag: "uuid5", translation: "{0} deve ser um UUID versão 5 válido", override: false, }, { tag: "ulid", translation: "{0} deve ser um ULID válido", override: false, }, { tag: "ascii", translation: "{0} deve conter apenas caracteres ascii", override: false, }, { tag: "printascii", translation: "{0} deve conter apenas caracteres ascii imprimíveis", override: false, }, { tag: "multibyte", translation: "{0} deve conter caracteres multibyte", override: false, }, { tag: "datauri", translation: "{0} deve conter um Data URI válido", override: false, }, { tag: "latitude", translation: "{0} deve conter uma coordenada de latitude válida", override: false, }, { tag: "longitude", translation: "{0} deve conter uma coordenada de longitude válida", override: false, }, { tag: "ssn", translation: "{0} deve ser um número SSN válido", override: false, }, { tag: "ipv4", translation: "{0} deve ser um endereço IPv4 válido", override: false, }, { tag: "ipv6", translation: "{0} deve ser um endereço IPv6 válido", override: false, }, { tag: "ip", translation: "{0} deve ser um endereço IP válido", override: false, }, { tag: "cidr", translation: "{0} não respeita a notação CIDR", override: false, }, { tag: "cidrv4", translation: "{0} não respeita a notação CIDR para um endereço IPv4", override: false, }, { tag: "cidrv6", translation: "{0} não respeita a notação CIDR para um endereço IPv6", override: false, }, { tag: "tcp_addr", translation: "{0} deve ser um endereço TCP válido", override: false, }, { tag: "tcp4_addr", translation: "{0} deve ser um endereço TCP IPv4 válido", override: false, }, { tag: "tcp6_addr", translation: "{0} deve ser um endereço TCP IPv6 válido", override: false, }, { tag: "udp_addr", translation: "{0} deve ser um endereço UDP válido", override: false, }, { tag: "udp4_addr", translation: "{0} deve ser um endereço UDP IPv4 válido", override: false, }, { tag: "udp6_addr", translation: "{0} deve ser um endereço UDP IPv6 válido", override: false, }, { tag: "ip_addr", translation: "{0} deve ser um endereço IP resolvível", override: false, }, { tag: "ip4_addr", translation: "{0} deve ser um endereço IPv4 resolvível", override: false, }, { tag: "ip6_addr", translation: "{0} deve ser um endereço IPv6 resolvível", override: false, }, { tag: "unix_addr", translation: "{0} deve ser um endereço UNIX resolvível", override: false, }, { tag: "mac", translation: "{0} deve conter um endereço MAC válido", override: false, }, { tag: "unique", translation: "{0} deve conter valores únicos", override: false, }, { tag: "iscolor", translation: "{0} deve ser uma cor válida", override: false, }, { tag: "oneof", translation: "{0} deve ser um de [{1}]", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { s, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return s }, }, { tag: "json", translation: "{0} deve ser uma string json válida", override: false, }, { tag: "lowercase", translation: "{0} deve estar em minuscúlas", override: false, }, { tag: "uppercase", translation: "{0} deve estar em maiúsculas", override: false, }, { tag: "datetime", translation: "{0} não está no formato {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "image", translation: "{0} deve ser uma imagem válida", override: false, }, } for _, t := range translations { if t.customTransFunc != nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, t.customTransFunc) } else if t.customTransFunc != nil && t.customRegisFunc == nil { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), t.customTransFunc) } else if t.customTransFunc == nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, translateFunc) } else { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), translateFunc) } if err != nil { return } } return } func registrationFunc(tag string, translation string, override bool) validator.RegisterTranslationsFunc { return func(ut ut.Translator) (err error) { if err = ut.Add(tag, translation, override); err != nil { return } return } } func translateFunc(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t } golang-github-go-playground-validator-v10-10.30.1/translations/pt/pt_test.go000066400000000000000000000505371512410077000267430ustar00rootroot00000000000000package 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"` ISSN string `validate:"issn"` 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"` Image string `validate:"image"` } 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.ISSN", expected: "ISSN deve ser um número ISSN 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", }, { ns: "Test.Image", expected: "Image deve ser uma imagem válida", }, } 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)) } } golang-github-go-playground-validator-v10-10.30.1/translations/pt_BR/000077500000000000000000000000001512410077000253035ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/translations/pt_BR/pt_BR.go000066400000000000000000000775411512410077000266560ustar00rootroot00000000000000package pt_BR import ( "fmt" "log" "reflect" "strconv" "strings" "time" "github.com/go-playground/locales" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" ) // RegisterDefaultTranslations registers a set of default translations // for all built in tag's in validator; you may add your own as desired. func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (err error) { translations := []struct { tag string translation string override bool customRegisFunc validator.RegisterTranslationsFunc customTransFunc validator.TranslationFunc }{ { tag: "required", translation: "{0} é um campo obrigatório", override: false, }, { tag: "len", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("len-string", "{0} deve ter {1}", false); err != nil { return } if err = ut.AddCardinal("len-string-character", "{0} caractere", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("len-string-character", "{0} caracteres", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("len-number", "{0} deve ser igual a {1}", false); err != nil { return } if err = ut.Add("len-items", "{0} deve conter {1}", false); err != nil { return } if err = ut.AddCardinal("len-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("len-items-item", "{0} itens", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("len-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("len-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-items", fe.Field(), c) default: t, err = ut.T("len-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("alerta: erro na tradução FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "min", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("min-string", "{0} deve ter pelo menos {1}", false); err != nil { return } if err = ut.AddCardinal("min-string-character", "{0} caractere", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("min-string-character", "{0} caracteres", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("min-number", "{0} deve ser {1} ou superior", false); err != nil { return } if err = ut.Add("min-items", "{0} deve conter pelo menos {1}", false); err != nil { return } if err = ut.AddCardinal("min-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("min-items-item", "{0} itens", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("min-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("min-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-items", fe.Field(), c) default: t, err = ut.T("min-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("alerta: erro na tradução FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "max", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("max-string", "{0} deve ter no máximo {1}", false); err != nil { return } if err = ut.AddCardinal("max-string-character", "{0} caractere", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("max-string-character", "{0} caracteres", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("max-number", "{0} deve ser {1} ou menor", false); err != nil { return } if err = ut.Add("max-items", "{0} deve conter no máximo {1}", false); err != nil { return } if err = ut.AddCardinal("max-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("max-items-item", "{0} itens", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("max-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("max-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-items", fe.Field(), c) default: t, err = ut.T("max-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("alerta: erro na tradução FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eq", translation: "{0} não é igual a {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("alerta: erro na tradução FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ne", translation: "{0} não deve ser igual a {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("alerta: erro na tradução FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "lt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lt-string", "{0} deve ter menos de {1}", false); err != nil { return } if err = ut.AddCardinal("lt-string-character", "{0} caractere", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lt-string-character", "{0} caracteres", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-number", "{0} deve ser menor que {1}", false); err != nil { return } if err = ut.Add("lt-items", "{0} deve conter menos de {1}", false); err != nil { return } if err = ut.AddCardinal("lt-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lt-items-item", "{0} itens", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-datetime", "{0} deve ser inferior à Data e Hora atual", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("a tag '%s' não pode ser usada em uma struct type", fe.Tag()) goto END } t, err = ut.T("lt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("alerta: erro na tradução FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "lte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lte-string", "{0} deve ter no máximo {1}", false); err != nil { return } if err = ut.AddCardinal("lte-string-character", "{0} caractere", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lte-string-character", "{0} caracteres", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-number", "{0} deve ser {1} ou menor", false); err != nil { return } if err = ut.Add("lte-items", "{0} deve conter no máximo {1}", false); err != nil { return } if err = ut.AddCardinal("lte-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lte-items-item", "{0} itens", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-datetime", "{0} deve ser menor ou igual à Data e Hora atual", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("a tag '%s' não pode ser usado em uma struct type", fe.Tag()) goto END } t, err = ut.T("lte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("alerta: erro na tradução FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gt-string", "{0} deve ter mais de {1}", false); err != nil { return } if err = ut.AddCardinal("gt-string-character", "{0} caractere", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gt-string-character", "{0} caracteres", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-number", "{0} deve ser maior do que {1}", false); err != nil { return } if err = ut.Add("gt-items", "{0} deve conter mais de {1}", false); err != nil { return } if err = ut.AddCardinal("gt-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gt-items-item", "{0} itens", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-datetime", "{0} deve ser maior que a Data e Hora atual", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("a tag '%s' não pode ser usado em uma struct type", fe.Tag()) goto END } t, err = ut.T("gt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("alerta: erro na tradução FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gte-string", "{0} deve ter pelo menos {1}", false); err != nil { return } if err = ut.AddCardinal("gte-string-character", "{0} caractere", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gte-string-character", "{0} caracteres", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-number", "{0} deve ser {1} ou superior", false); err != nil { return } if err = ut.Add("gte-items", "{0} deve conter pelo menos {1}", false); err != nil { return } if err = ut.AddCardinal("gte-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gte-items-item", "{0} itens", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-datetime", "{0} deve ser maior ou igual à Data e Hora atual", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("a tag '%s' não pode ser usado em uma struct type", fe.Tag()) goto END } t, err = ut.T("gte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("alerta: erro na tradução FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eqfield", translation: "{0} deve ser igual a {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("alerta: erro na tradução FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "eqcsfield", translation: "{0} deve ser igual a {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("alerta: erro na tradução FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "necsfield", translation: "{0} não deve ser igual a {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("alerta: erro na tradução FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtcsfield", translation: "{0} deve ser maior do que {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("alerta: erro na tradução FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtecsfield", translation: "{0} deve ser maior ou igual a {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("alerta: erro na tradução FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltcsfield", translation: "{0} deve ser menor que {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("alerta: erro na tradução FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltecsfield", translation: "{0} deve ser menor ou igual a {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("alerta: erro na tradução FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "nefield", translation: "{0} não deve ser igual a {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("alerta: erro na tradução FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtfield", translation: "{0} deve ser maior do que {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("alerta: erro na tradução FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtefield", translation: "{0} deve ser maior ou igual a {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("alerta: erro na tradução FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltfield", translation: "{0} deve ser menor que {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("alerta: erro na tradução FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltefield", translation: "{0} deve ser menor ou igual a {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("alerta: erro na tradução FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "alpha", translation: "{0} deve conter caracteres alfabéticos", override: false, }, { tag: "alphanum", translation: "{0} deve conter caracteres alfanuméricos", override: false, }, { tag: "numeric", translation: "{0} deve ser um valor numérico válido", override: false, }, { tag: "number", translation: "{0} deve ser um número válido", override: false, }, { tag: "hexadecimal", translation: "{0} deve ser um hexadecimal válido", override: false, }, { tag: "hexcolor", translation: "{0} deve ser uma cor HEX válida", override: false, }, { tag: "rgb", translation: "{0} deve ser uma cor RGB válida", override: false, }, { tag: "rgba", translation: "{0} deve ser uma cor RGBA válida", override: false, }, { tag: "hsl", translation: "{0} deve ser uma cor HSL válida", override: false, }, { tag: "hsla", translation: "{0} deve ser uma cor HSLA válida", override: false, }, { tag: "email", translation: "{0} deve ser um endereço de e-mail válido", override: false, }, { tag: "url", translation: "{0} deve ser uma URL válida", override: false, }, { tag: "uri", translation: "{0} deve ser uma URI válida", override: false, }, { tag: "base64", translation: "{0} deve ser uma string Base64 válida", override: false, }, { tag: "contains", translation: "{0} deve conter o texto '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("alerta: erro na tradução FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "containsany", translation: "{0} deve conter pelo menos um dos caracteres '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("alerta: erro na tradução FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludes", translation: "{0} não deve conter o texto '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("alerta: erro na tradução FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesall", translation: "{0} não deve conter nenhum dos caracteres '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("alerta: erro na tradução FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesrune", translation: "{0} não deve conter '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("alerta: erro na tradução FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "isbn", translation: "{0} deve ser um número ISBN válido", override: false, }, { tag: "isbn10", translation: "{0} deve ser um número ISBN-10 válido", override: false, }, { tag: "isbn13", translation: "{0} deve ser um número ISBN-13 válido", override: false, }, { tag: "issn", translation: "{0} deve ser um número ISSN válido", override: false, }, { tag: "uuid", translation: "{0} deve ser um UUID válido", override: false, }, { tag: "uuid3", translation: "{0} deve ser um UUID versão 3 válido", override: false, }, { tag: "uuid4", translation: "{0} deve ser um UUID versão 4 válido", override: false, }, { tag: "uuid5", translation: "{0} deve ser um UUID versão 5 válido", override: false, }, { tag: "ulid", translation: "{0} deve ser uma ULID válida", override: false, }, { tag: "ascii", translation: "{0} deve conter apenas caracteres ascii", override: false, }, { tag: "printascii", translation: "{0} deve conter apenas caracteres ascii imprimíveis", override: false, }, { tag: "multibyte", translation: "{0} deve conter caracteres multibyte", override: false, }, { tag: "datauri", translation: "{0} deve conter um URI data válido", override: false, }, { tag: "latitude", translation: "{0} deve conter uma coordenada de latitude válida", override: false, }, { tag: "longitude", translation: "{0} deve conter uma coordenada de longitude válida", override: false, }, { tag: "ssn", translation: "{0} deve ser um número SSN válido", override: false, }, { tag: "ipv4", translation: "{0} deve ser um endereço IPv4 válido", override: false, }, { tag: "ipv6", translation: "{0} deve ser um endereço IPv6 válido", override: false, }, { tag: "ip", translation: "{0} deve ser um endereço de IP válido", override: false, }, { tag: "cidr", translation: "{0} deve conter uma notação CIDR válida", override: false, }, { tag: "cidrv4", translation: "{0} deve conter uma notação CIDR válida para um endereço IPv4", override: false, }, { tag: "cidrv6", translation: "{0} deve conter uma notação CIDR válida para um endereço IPv6", override: false, }, { tag: "tcp_addr", translation: "{0} deve ser um endereço TCP válido", override: false, }, { tag: "tcp4_addr", translation: "{0} deve ser um endereço IPv4 TCP válido", override: false, }, { tag: "tcp6_addr", translation: "{0} deve ser um endereço IPv6 TCP válido", override: false, }, { tag: "udp_addr", translation: "{0} deve ser um endereço UDP válido", override: false, }, { tag: "udp4_addr", translation: "{0} deve ser um endereço IPv4 UDP válido", override: false, }, { tag: "udp6_addr", translation: "{0} deve ser um endereço IPv6 UDP válido", override: false, }, { tag: "ip_addr", translation: "{0} deve ser um endereço IP resolvível", override: false, }, { tag: "ip4_addr", translation: "{0} deve ser um endereço IPv4 resolvível", override: false, }, { tag: "ip6_addr", translation: "{0} deve ser um endereço IPv6 resolvível", override: false, }, { tag: "unix_addr", translation: "{0} deve ser um endereço UNIX resolvível", override: false, }, { tag: "mac", translation: "{0} deve conter um endereço MAC válido", override: false, }, { tag: "iscolor", translation: "{0} deve ser uma cor válida", override: false, }, { tag: "oneof", translation: "{0} deve ser um de [{1}]", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { s, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("alerta: erro na tradução FieldError: %#v", fe) return fe.(error).Error() } return s }, }, { tag: "boolean", translation: "{0} deve ser um valor booleano válido", override: false, }, { tag: "image", translation: "{0} deve ser uma imagen válido", override: false, }, { tag: "cve", translation: "{0} deve ser um identificador cve válido", override: false, }, { tag: "validateFn", translation: "{0} deve ser um objeto válido", override: false, }, } for _, t := range translations { if t.customTransFunc != nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, t.customTransFunc) } else if t.customTransFunc != nil && t.customRegisFunc == nil { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), t.customTransFunc) } else if t.customTransFunc == nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, translateFunc) } else { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), translateFunc) } if err != nil { return } } return } func registrationFunc(tag string, translation string, override bool) validator.RegisterTranslationsFunc { return func(ut ut.Translator) (err error) { if err = ut.Add(tag, translation, override); err != nil { return } return } } func translateFunc(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field()) if err != nil { log.Printf("alerta: erro na tradução FieldError: %#v", fe) return fe.(error).Error() } return t } golang-github-go-playground-validator-v10-10.30.1/translations/pt_BR/pt_BR_test.go000066400000000000000000000454701512410077000277110ustar00rootroot00000000000000package 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" ) type Foo struct{} func (Foo) IsBar() bool { return false } 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"` ISSN string `validate:"issn"` 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"` Image string `validate:"image"` CveString string `validate:"cve"` ValidateFn Foo `validate:"validateFn=IsBar"` } 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.ISSN", expected: "ISSN deve ser um número ISSN 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.Image", expected: "Image deve ser uma imagen válido", }, { ns: "Test.CveString", expected: "CveString deve ser um identificador cve válido", }, { ns: "Test.ValidateFn", expected: "ValidateFn deve ser um objeto 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)) } } golang-github-go-playground-validator-v10-10.30.1/translations/ru/000077500000000000000000000000001512410077000247235ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/translations/ru/ru.go000066400000000000000000001126431512410077000257070ustar00rootroot00000000000000package ru import ( "fmt" "log" "reflect" "strconv" "strings" "time" "github.com/go-playground/locales" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" ) // RegisterDefaultTranslations registers a set of default translations // for all built in tag's in validator; you may add your own as desired. func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (err error) { translations := []struct { tag string translation string override bool customRegisFunc validator.RegisterTranslationsFunc customTransFunc validator.TranslationFunc }{ { tag: "required", translation: "{0} обязательное поле", override: false, }, { tag: "len", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("len-string", "{0} должен быть длиной в {1}", false); err != nil { return } if err = ut.AddCardinal("len-string-character", "{0} символ", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("len-string-character", "{0} символа", locales.PluralRuleFew, false); err != nil { return } if err = ut.AddCardinal("len-string-character", "{0} символов", locales.PluralRuleMany, false); err != nil { return } if err = ut.AddCardinal("len-string-character", "{0} символы", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("len-number", "{0} должен быть равен {1}", false); err != nil { return } if err = ut.Add("len-items", "{0} должен содержать {1}", false); err != nil { return } if err = ut.AddCardinal("len-items-item", "{0} элемент", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("len-items-item", "{0} элемента", locales.PluralRuleFew, false); err != nil { return } if err = ut.AddCardinal("len-items-item", "{0} элементов", locales.PluralRuleMany, false); err != nil { return } if err = ut.AddCardinal("len-items-item", "{0} элементы", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("len-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("len-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-items", fe.Field(), c) default: t, err = ut.T("len-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "min", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("min-string", "{0} должен содержать минимум {1}", false); err != nil { return } if err = ut.AddCardinal("min-string-character", "{0} символ", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("min-string-character", "{0} символа", locales.PluralRuleFew, false); err != nil { return } if err = ut.AddCardinal("min-string-character", "{0} символов", locales.PluralRuleMany, false); err != nil { return } if err = ut.AddCardinal("min-string-character", "{0} символы", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("min-number", "{0} должен быть больше или равно {1}", false); err != nil { return } if err = ut.Add("min-items", "{0} должен содержать минимум {1}", false); err != nil { return } if err = ut.AddCardinal("min-items-item", "{0} элемент", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("min-items-item", "{0} элемента", locales.PluralRuleFew, false); err != nil { return } if err = ut.AddCardinal("min-items-item", "{0} элементов", locales.PluralRuleMany, false); err != nil { return } if err = ut.AddCardinal("min-items-item", "{0} элементы", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("min-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("min-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-items", fe.Field(), c) default: t, err = ut.T("min-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "max", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("max-string", "{0} должен содержать максимум {1}", false); err != nil { return } if err = ut.AddCardinal("max-string-character", "{0} символ", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("max-string-character", "{0} символа", locales.PluralRuleFew, false); err != nil { return } if err = ut.AddCardinal("max-string-character", "{0} символов", locales.PluralRuleMany, false); err != nil { return } if err = ut.AddCardinal("max-string-character", "{0} символы", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("max-number", "{0} должен быть меньше или равно {1}", false); err != nil { return } if err = ut.Add("max-items", "{0} должен содержать максимум {1}", false); err != nil { return } if err = ut.AddCardinal("max-items-item", "{0} элемент", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("max-items-item", "{0} элемента", locales.PluralRuleFew, false); err != nil { return } if err = ut.AddCardinal("max-items-item", "{0} элементов", locales.PluralRuleMany, false); err != nil { return } if err = ut.AddCardinal("max-items-item", "{0} элементы", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("max-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("max-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-items", fe.Field(), c) default: t, err = ut.T("max-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eq", translation: "{0} не равен {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ne", translation: "{0} должен быть не равен {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "lt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lt-string", "{0} должен иметь менее {1}", false); err != nil { return } if err = ut.AddCardinal("lt-string-character", "{0} символ", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lt-string-character", "{0} символов", locales.PluralRuleFew, false); err != nil { return } if err = ut.AddCardinal("lt-string-character", "{0} символов", locales.PluralRuleMany, false); err != nil { return } if err = ut.AddCardinal("lt-string-character", "{0} символы", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-number", "{0} должен быть менее {1}", false); err != nil { return } if err = ut.Add("lt-items", "{0} должен содержать менее {1}", false); err != nil { return } if err = ut.AddCardinal("lt-items-item", "{0} элемент", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lt-items-item", "{0} элементов", locales.PluralRuleFew, false); err != nil { return } if err = ut.AddCardinal("lt-items-item", "{0} элементов", locales.PluralRuleMany, false); err != nil { return } if err = ut.AddCardinal("lt-items-item", "{0} элементы", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-datetime", "{0} must be less than the current Date & Time", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "lte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lte-string", "{0} должен содержать максимум {1}", false); err != nil { return } if err = ut.AddCardinal("lte-string-character", "{0} символ", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lte-string-character", "{0} символа", locales.PluralRuleFew, false); err != nil { return } if err = ut.AddCardinal("lte-string-character", "{0} символов", locales.PluralRuleMany, false); err != nil { return } if err = ut.AddCardinal("lte-string-character", "{0} символы", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-number", "{0} должен быть менее или равен {1}", false); err != nil { return } if err = ut.Add("lte-items", "{0} должен содержать максимум {1}", false); err != nil { return } if err = ut.AddCardinal("lte-items-item", "{0} элемент", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lte-items-item", "{0} элемента", locales.PluralRuleFew, false); err != nil { return } if err = ut.AddCardinal("lte-items-item", "{0} элементов", locales.PluralRuleMany, false); err != nil { return } if err = ut.AddCardinal("lte-items-item", "{0} элементы", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-datetime", "{0} must be less than or equal to the current Date & Time", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gt-string", "{0} должен быть длиннее {1}", false); err != nil { return } if err = ut.AddCardinal("gt-string-character", "{0} символ", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gt-string-character", "{0} символов", locales.PluralRuleFew, false); err != nil { return } if err = ut.AddCardinal("gt-string-character", "{0} символов", locales.PluralRuleMany, false); err != nil { return } if err = ut.AddCardinal("gt-string-character", "{0} символы", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-number", "{0} должен быть больше {1}", false); err != nil { return } if err = ut.Add("gt-items", "{0} должен содержать более {1}", false); err != nil { return } if err = ut.AddCardinal("gt-items-item", "{0} элемент", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gt-items-item", "{0} элементов", locales.PluralRuleFew, false); err != nil { return } if err = ut.AddCardinal("gt-items-item", "{0} элементов", locales.PluralRuleMany, false); err != nil { return } if err = ut.AddCardinal("gt-items-item", "{0} элементы", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-datetime", "{0} должна быть позже текущего момента", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gte-string", "{0} должен содержать минимум {1}", false); err != nil { return } if err = ut.AddCardinal("gte-string-character", "{0} символ", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gte-string-character", "{0} символа", locales.PluralRuleFew, false); err != nil { return } if err = ut.AddCardinal("gte-string-character", "{0} символов", locales.PluralRuleMany, false); err != nil { return } if err = ut.AddCardinal("gte-string-character", "{0} символы", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-number", "{0} должен быть больше или равно {1}", false); err != nil { return } if err = ut.Add("gte-items", "{0} должен содержать минимум {1}", false); err != nil { return } if err = ut.AddCardinal("gte-items-item", "{0} элемент", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gte-items-item", "{0} элемента", locales.PluralRuleFew, false); err != nil { return } if err = ut.AddCardinal("gte-items-item", "{0} элементов", locales.PluralRuleMany, false); err != nil { return } if err = ut.AddCardinal("gte-items-item", "{0} элементы", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-datetime", "{0} должна быть позже или равна текущему моменту", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eqfield", translation: "{0} должен быть равен {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "eqcsfield", translation: "{0} должен быть равен {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "necsfield", translation: "{0} не должен быть равен {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtcsfield", translation: "{0} должен быть больше {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtecsfield", translation: "{0} должен быть больше или равен {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltcsfield", translation: "{0} должен быть менее {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltecsfield", translation: "{0} должен быть менее или равен {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "nefield", translation: "{0} не должен быть равен {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtfield", translation: "{0} должен быть больше {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtefield", translation: "{0} должен быть больше или равен {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltfield", translation: "{0} должен быть менее {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltefield", translation: "{0} должен быть менее или равен {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "alpha", translation: "{0} должен содержать только буквы", override: false, }, { tag: "alphanum", translation: "{0} должен содержать только буквы и цифры", override: false, }, { tag: "numeric", translation: "{0} должен быть цифровым значением", override: false, }, { tag: "number", translation: "{0} должен быть цифрой", override: false, }, { tag: "hexadecimal", translation: "{0} должен быть шестнадцатеричной строкой", override: false, }, { tag: "hexcolor", translation: "{0} должен быть HEX цветом", override: false, }, { tag: "rgb", translation: "{0} должен быть RGB цветом", override: false, }, { tag: "rgba", translation: "{0} должен быть RGBA цветом", override: false, }, { tag: "hsl", translation: "{0} должен быть HSL цветом", override: false, }, { tag: "hsla", translation: "{0} должен быть HSLA цветом", override: false, }, { tag: "e164", translation: "{0} должен быть действительным номером телефона в формате E.164", override: false, }, { tag: "email", translation: "{0} должен быть email адресом", override: false, }, { tag: "url", translation: "{0} должен быть URL", override: false, }, { tag: "uri", translation: "{0} должен быть URI", override: false, }, { tag: "base64", translation: "{0} должен быть Base64 строкой", override: false, }, { tag: "contains", translation: "{0} должен содержать текст '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "containsany", translation: "{0} должен содержать минимум один из символов '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludes", translation: "{0} не должен содержать текст '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesall", translation: "{0} не должен содержать символы '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesrune", translation: "{0} не должен содержать '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "isbn", translation: "{0} должен быть ISBN номером", override: false, }, { tag: "isbn10", translation: "{0} должен быть ISBN-10 номером", override: false, }, { tag: "isbn13", translation: "{0} должен быть ISBN-13 номером", override: false, }, { tag: "issn", translation: "{0} должен быть ISSN номером", override: false, }, { tag: "uuid", translation: "{0} должен быть UUID", override: false, }, { tag: "uuid3", translation: "{0} должен быть UUID 3 версии", override: false, }, { tag: "uuid4", translation: "{0} должен быть UUID 4 версии", override: false, }, { tag: "uuid5", translation: "{0} должен быть UUID 5 версии", override: false, }, { tag: "ulid", translation: "{0} должен быть ULID", override: false, }, { tag: "ascii", translation: "{0} должен содержать только ascii символы", override: false, }, { tag: "printascii", translation: "{0} должен содержать только доступные для печати ascii символы", override: false, }, { tag: "multibyte", translation: "{0} должен содержать мультибайтные символы", override: false, }, { tag: "datauri", translation: "{0} должен содержать Data URI", override: false, }, { tag: "latitude", translation: "{0} должен содержать координаты широты", override: false, }, { tag: "longitude", translation: "{0} должен содержать координаты долготы", override: false, }, { tag: "ssn", translation: "{0} должен быть SSN номером", override: false, }, { tag: "ipv4", translation: "{0} должен быть IPv4 адресом", override: false, }, { tag: "ipv6", translation: "{0} должен быть IPv6 адресом", override: false, }, { tag: "ip", translation: "{0} должен быть IP адресом", override: false, }, { tag: "cidr", translation: "{0} должен содержать CIDR обозначения", override: false, }, { tag: "cidrv4", translation: "{0} должен содержать CIDR обозначения для IPv4 адреса", override: false, }, { tag: "cidrv6", translation: "{0} должен содержать CIDR обозначения для IPv6 адреса", override: false, }, { tag: "tcp_addr", translation: "{0} должен быть TCP адресом", override: false, }, { tag: "tcp4_addr", translation: "{0} должен быть IPv4 TCP адресом", override: false, }, { tag: "tcp6_addr", translation: "{0} должен быть IPv6 TCP адресом", override: false, }, { tag: "udp_addr", translation: "{0} должен быть UDP адресом", override: false, }, { tag: "udp4_addr", translation: "{0} должен быть IPv4 UDP адресом", override: false, }, { tag: "udp6_addr", translation: "{0} должен быть IPv6 UDP адресом", override: false, }, { tag: "ip_addr", translation: "{0} должен быть распознаваемым IP адресом", override: false, }, { tag: "ip4_addr", translation: "{0} должен быть распознаваемым IPv4 адресом", override: false, }, { tag: "ip6_addr", translation: "{0} должен быть распознаваемым IPv6 адресом", override: false, }, { tag: "unix_addr", translation: "{0} должен быть распознаваемым UNIX адресом", override: false, }, { tag: "mac", translation: "{0} должен содержать MAC адрес", override: false, }, { tag: "unique", translation: "{0} должен содержать уникальные значения", override: false, }, { tag: "iscolor", translation: "{0} должен быть цветом", override: false, }, { tag: "oneof", translation: "{0} должен быть одним из [{1}]", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { s, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return s }, }, { tag: "image", translation: "{0} должно быть допустимым изображением", override: false, }, } for _, t := range translations { if t.customTransFunc != nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, t.customTransFunc) } else if t.customTransFunc != nil && t.customRegisFunc == nil { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), t.customTransFunc) } else if t.customTransFunc == nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, translateFunc) } else { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), translateFunc) } if err != nil { return } } return } func registrationFunc(tag string, translation string, override bool) validator.RegisterTranslationsFunc { return func(ut ut.Translator) (err error) { if err = ut.Add(tag, translation, override); err != nil { return } return } } func translateFunc(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t } golang-github-go-playground-validator-v10-10.30.1/translations/ru/ru_test.go000066400000000000000000000654411512410077000267510ustar00rootroot00000000000000package 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"` ISSN string `validate:"issn"` 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"` Image string `validate:"image"` } 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.ISSN", expected: "ISSN должен быть ISSN номером", }, { 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 должен содержать уникальные значения", }, { ns: "Test.Image", expected: "Image должно быть допустимым изображением", }, } 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)) } } golang-github-go-playground-validator-v10-10.30.1/translations/th/000077500000000000000000000000001512410077000247105ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/translations/th/th.go000066400000000000000000001057571512410077000256710ustar00rootroot00000000000000package th import ( "fmt" "log" "reflect" "strconv" "strings" "time" "github.com/go-playground/locales" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" ) // RegisterDefaultTranslations registers a set of default translations // for all built in tag's in validator; you may add your own as desired. func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (err error) { translations := []struct { tag string translation string override bool customRegisFunc validator.RegisterTranslationsFunc customTransFunc validator.TranslationFunc }{ { tag: "required", translation: "โปรดระบุ {0}", override: false, }, { tag: "required_if", translation: "โปรดระบุ {0}", override: false, }, { tag: "len", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("len-string", "{0} ต้องมีความยาว {1}", false); err != nil { return } if err = ut.AddCardinal("len-string-character", "{0} ตัวอักษร", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("len-number", "{0} ต้องเท่ากับ {1}", false); err != nil { return } if err = ut.Add("len-items", "{0} ต้องประกอบไปด้วย {1}", false); err != nil { return } if err = ut.AddCardinal("len-items-item", "{0} รายการ", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("len-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("len-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-items", fe.Field(), c) default: t, err = ut.T("len-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "min", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("min-string", "{0} ต้องมีความยาวอย่างน้อย {1}", false); err != nil { return } if err = ut.AddCardinal("min-string-character", "{0} ตัวอักษร", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("min-number", "{0} ต้องมีค่ามากกว่า {1}", false); err != nil { return } if err = ut.Add("min-items", "{0} ต้องมีอย่างน้อย {1}", false); err != nil { return } if err = ut.AddCardinal("min-items-item", "{0} รายการ", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("min-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("min-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-items", fe.Field(), c) default: t, err = ut.T("min-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "max", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("max-string", "{0} ต้องมีความยาวไม่เกิน {1}", false); err != nil { return } if err = ut.AddCardinal("max-string-character", "{0} ตัวอักษร", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("max-number", "{0} ต้องมีค่าน้อยกว่าหรือเท่ากับ {1}", false); err != nil { return } if err = ut.Add("max-items", "{0} ต้องมีไม่เกิน {1}", false); err != nil { return } if err = ut.AddCardinal("max-items-item", "{0} รายการ", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("max-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("max-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-items", fe.Field(), c) default: t, err = ut.T("max-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eq", translation: "{0} ไม่เท่ากับ {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ne", translation: "{0} ต้องไม่เท่ากับ {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "lt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lt-string", "{0} ต้องมีความยาวน้อยกว่า {1}", false); err != nil { return } if err = ut.AddCardinal("lt-string-character", "{0} ตัวอักษร", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-number", "{0} ต้องมีค่าน้อยกว่า {1}", false); err != nil { return } if err = ut.Add("lt-items", "{0} ต้องมีน้อยกว่า {1}", false); err != nil { return } if err = ut.AddCardinal("lt-items-item", "{0} รายการ", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-datetime", "{0} ต้องเป็นเวลาก่อนปัจจุบัน", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "lte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lte-string", "{0} ต้องมีความยาวไม่เกิน {1}", false); err != nil { return } if err = ut.AddCardinal("lte-string-character", "{0} ตัวอักษร", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-number", "{0} ต้องมีค่าน้อยกว่าหรือเท่ากับ {1}", false); err != nil { return } if err = ut.Add("lte-items", "{0} ต้องมีไม่เกิน {1}", false); err != nil { return } if err = ut.AddCardinal("lte-items-item", "{0} รายการ", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-datetime", "{0} ต้องเป็นเวลาก่อนหรือเป็นเวลาปัจจุบัน", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gt-string", "{0} ต้องมีความยาวมากกว่า {1}", false); err != nil { return } if err = ut.AddCardinal("gt-string-character", "{0} ตัวอักษร", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-number", "{0} ต้องมีค่ามากกว่า {1}", false); err != nil { return } if err = ut.Add("gt-items", "{0} ต้องมีมากกว่า {1}", false); err != nil { return } if err = ut.AddCardinal("gt-items-item", "{0} รายการ", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-datetime", "{0} ต้องเป็นเวลาหลังจากปัจจุบัน", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gte-string", "{0} ต้องมีความยาวอย่างน้อย {1}", false); err != nil { return } if err = ut.AddCardinal("gte-string-character", "{0} ตัวอักษร", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-number", "{0} ต้องมีค่ามากกว่า {1}", false); err != nil { return } if err = ut.Add("gte-items", "{0} ต้องมีอย่างน้อย {1}", false); err != nil { return } if err = ut.AddCardinal("gte-items-item", "{0} รายการ", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-datetime", "{0} ต้องเป็นเวลาหลังหรือเป็นเวลาปัจจุบัน", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eqfield", translation: "{0} ต้องเท่ากับ {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "eqcsfield", translation: "{0} ต้องเท่ากับ {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "necsfield", translation: "{0} ต้องไม่เท่ากับ {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtcsfield", translation: "{0} ต้องมีค่ามากกว่า {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtecsfield", translation: "{0} ต้องมีค่ามากกว่าหรือเท่ากับ {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltcsfield", translation: "{0} ต้องมีค่าน้อยกว่า {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltecsfield", translation: "{0} ต้องมีค่าน้อยกว่าหรือเท่ากับ {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "nefield", translation: "{0} ต้องไม่เท่ากับ {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtfield", translation: "{0} ต้องมีค่ามากกว่า {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtefield", translation: "{0} ต้องมีค่ามากกว่าหรือเท่ากับ {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltfield", translation: "{0} ต้องมีค่าน้อยกว่า {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltefield", translation: "{0} ต้องมีค่าน้อยกว่าหรือเท่ากับ {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "alpha", translation: "{0} ต้องเป็นตัวอักษรเท่านั้น", override: false, }, { tag: "alphanum", translation: "{0} ต้องเป็นตัวอักษรหรือตัวเลขเท่านั้น", override: false, }, { tag: "numeric", translation: "{0} ต้องเป็นค่าตัวเลขเท่านั้น", override: false, }, { tag: "number", translation: "{0} ต้องเป็นตัวเลขเท่านั้น", override: false, }, { tag: "hexadecimal", translation: "{0} ต้องเป็นค่าตัวเลขฐาน 16 เท่านั้น", override: false, }, { tag: "hexcolor", translation: "{0} ต้องเป็นเลขสีฐาน 16 เท่านั้น", override: false, }, { tag: "rgb", translation: "{0} ต้องเป็นเลขสี RGB เท่านั้น", override: false, }, { tag: "rgba", translation: "{0} ต้องเป็นเลขสี RGBA เท่านั้น", override: false, }, { tag: "hsl", translation: "{0} ต้องเป็นเลขสี HSL เท่านั้น", override: false, }, { tag: "hsla", translation: "{0} ต้องเป็นเลขสี HSLA เท่านั้น", override: false, }, { tag: "e164", translation: "{0} ต้องเป็นเบอร์โทรศัพท์รูปแบบ E.164 เท่านั้น", override: false, }, { tag: "email", translation: "{0} ต้องเป็นอีเมลเท่านั้น", override: false, }, { tag: "url", translation: "{0} ต้องเป็น URL เท่านั้น", override: false, }, { tag: "uri", translation: "{0} ต้องเป็น URI เท่านั้น", override: false, }, { tag: "base64", translation: "{0} ต้องเป็น Base64 เท่านั้น", override: false, }, { tag: "contains", translation: "{0} ต้องมี '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "containsany", translation: "{0} ต้องมีอย่างน้อยอักขระใน '{1}' อย่างน้อย 1 ตัว", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludes", translation: "{0} ต้องไม่มี '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesall", translation: "{0} ต้องไม่มีอักขระ '{1}' ทั้งหมด", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesrune", translation: "{0} ต้องไม่มี '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "isbn", translation: "{0} ต้องเป็นตัวเลข ISBN", override: false, }, { tag: "isbn10", translation: "{0} ต้องเป็นตัวเลข ISBN-10", override: false, }, { tag: "isbn13", translation: "{0} ต้องเป็นตัวเลข ISBN-13", override: false, }, { tag: "issn", translation: "{0} ต้องเป็นตัวเลข ISSN", override: false, }, { tag: "uuid", translation: "{0} ต้องเป็น UUID", override: false, }, { tag: "uuid3", translation: "{0} ต้องเป็น version 3 UUID", override: false, }, { tag: "uuid4", translation: "{0} ต้องเป็น version 4 UUID", override: false, }, { tag: "uuid5", translation: "{0} ต้องเป็น version 5 UUID", override: false, }, { tag: "ulid", translation: "{0} must be a valid ULID", override: false, }, { tag: "ascii", translation: "{0} ต้องมีแค่อักขระ ascii", override: false, }, { tag: "printascii", translation: "{0} ต้องมีแค่อักขระ ascii ที่แสดงผลได้", override: false, }, { tag: "multibyte", translation: "{0} ต้องมี multibyte character", override: false, }, { tag: "datauri", translation: "{0} ต้องประกอบไปด้วย a valid Data URI", override: false, }, { tag: "latitude", translation: "{0} ต้องเป็นละติจูด", override: false, }, { tag: "longitude", translation: "{0} ต้องเป็นลองจิจูด", override: false, }, { tag: "ssn", translation: "{0} ต้องเป็นตัวเลข SSN", override: false, }, { tag: "ipv4", translation: "{0} ต้องเป็น IPv4 address", override: false, }, { tag: "ipv6", translation: "{0} ต้องเป็น IPv6 address", override: false, }, { tag: "ip", translation: "{0} ต้องเป็น IP address", override: false, }, { tag: "cidr", translation: "{0} ต้องเป็น CIDR notation", override: false, }, { tag: "cidrv4", translation: "{0} ต้องเป็น CIDR notation สำหรับ an IPv4 address", override: false, }, { tag: "cidrv6", translation: "{0} ต้องเป็น CIDR notation สำหรับ an IPv6 address", override: false, }, { tag: "tcp_addr", translation: "{0} ต้องเป็น TCP address", override: false, }, { tag: "tcp4_addr", translation: "{0} ต้องเป็น IPv4 TCP address", override: false, }, { tag: "tcp6_addr", translation: "{0} ต้องเป็น IPv6 TCP address", override: false, }, { tag: "udp_addr", translation: "{0} ต้องเป็น UDP address", override: false, }, { tag: "udp4_addr", translation: "{0} ต้องเป็น IPv4 UDP address", override: false, }, { tag: "udp6_addr", translation: "{0} ต้องเป็น IPv6 UDP address", override: false, }, { tag: "ip_addr", translation: "{0} ต้องเป็น IP address ที่เข้าถึงได้", override: false, }, { tag: "ip4_addr", translation: "{0} ต้องเป็น IPv4 address ที่เข้าถึงได้", override: false, }, { tag: "ip6_addr", translation: "{0} ต้องเป็น IPv6 address ที่เข้าถึงได้", override: false, }, { tag: "unix_addr", translation: "{0} ต้องเป็น UNIX address ที่เข้าถึงได้", override: false, }, { tag: "mac", translation: "{0} ต้องเป็น MAC address", override: false, }, { tag: "fqdn", translation: "{0} ต้องเป็น FQDN", override: false, }, { tag: "unique", translation: "{0} ต้องมีข้อมูลไม่ซ้ำ", override: false, }, { tag: "iscolor", translation: "{0} ต้องเป็นเลขสี", override: false, }, { tag: "cron", translation: "{0} ต้องเป็น cron expression", override: false, }, { tag: "oneof", translation: "{0} ต้องอยู่ใน [{1}]", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { s, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return s }, }, { tag: "json", translation: "{0} ต้องเป็น json string", override: false, }, { tag: "jwt", translation: "{0} ต้องเป็น jwt string", override: false, }, { tag: "lowercase", translation: "{0} ต้องเป็นตัวพิมพ์เล็ก", override: false, }, { tag: "uppercase", translation: "{0} ต้องเป็นตัวพิมพ์ใหญ่", override: false, }, { tag: "datetime", translation: "{0} ไม่ตรงกับรูปแบบ {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "postcode_iso3166_alpha2", translation: "{0} does not match postcode format of {1} country", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "postcode_iso3166_alpha2_field", translation: "{0} does not match postcode format of country in {1} field", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "boolean", translation: "{0} ต้องเป็น boolean", override: false, }, { tag: "image", translation: "{0} ต้องเป็นรูปภาพ", override: false, }, { tag: "cve", translation: "{0} ต้องเป็นรูปแบบ cve", override: false, }, } for _, t := range translations { if t.customTransFunc != nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, t.customTransFunc) } else if t.customTransFunc != nil && t.customRegisFunc == nil { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), t.customTransFunc) } else if t.customTransFunc == nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, translateFunc) } else { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), translateFunc) } if err != nil { return } } return } func registrationFunc(tag string, translation string, override bool) validator.RegisterTranslationsFunc { return func(ut ut.Translator) (err error) { if err = ut.Add(tag, translation, override); err != nil { return } return } } func translateFunc(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t } golang-github-go-playground-validator-v10-10.30.1/translations/th/th_test.go000066400000000000000000000573211512410077000267210ustar00rootroot00000000000000package th import ( "testing" "time" . "github.com/go-playground/assert/v2" thai "github.com/go-playground/locales/th" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" ) func TestTranslations(t *testing.T) { th := thai.New() uni := ut.New(th, th) trans, _ := uni.GetTranslator("th") 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"` ISSN string `validate:"issn"` 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"` Image string `validate:"image"` 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 ต้องเป็นเลขสี", }, { ns: "Test.MAC", expected: "MAC ต้องเป็น MAC address", }, { ns: "Test.FQDN", expected: "FQDN ต้องเป็น FQDN", }, { ns: "Test.IPAddr", expected: "IPAddr ต้องเป็น IP address ที่เข้าถึงได้", }, { ns: "Test.IPAddrv4", expected: "IPAddrv4 ต้องเป็น IPv4 address ที่เข้าถึงได้", }, { ns: "Test.IPAddrv6", expected: "IPAddrv6 ต้องเป็น IPv6 address ที่เข้าถึงได้", }, { ns: "Test.UDPAddr", expected: "UDPAddr ต้องเป็น UDP address", }, { ns: "Test.UDPAddrv4", expected: "UDPAddrv4 ต้องเป็น IPv4 UDP address", }, { ns: "Test.UDPAddrv6", expected: "UDPAddrv6 ต้องเป็น IPv6 UDP address", }, { ns: "Test.TCPAddr", expected: "TCPAddr ต้องเป็น TCP address", }, { ns: "Test.TCPAddrv4", expected: "TCPAddrv4 ต้องเป็น IPv4 TCP address", }, { ns: "Test.TCPAddrv6", expected: "TCPAddrv6 ต้องเป็น IPv6 TCP address", }, { ns: "Test.CIDR", expected: "CIDR ต้องเป็น CIDR notation", }, { ns: "Test.CIDRv4", expected: "CIDRv4 ต้องเป็น CIDR notation สำหรับ an IPv4 address", }, { ns: "Test.CIDRv6", expected: "CIDRv6 ต้องเป็น CIDR notation สำหรับ an IPv6 address", }, { ns: "Test.SSN", expected: "SSN ต้องเป็นตัวเลข SSN", }, { ns: "Test.IP", expected: "IP ต้องเป็น IP address", }, { ns: "Test.IPv4", expected: "IPv4 ต้องเป็น IPv4 address", }, { ns: "Test.IPv6", expected: "IPv6 ต้องเป็น IPv6 address", }, { ns: "Test.DataURI", expected: "DataURI ต้องประกอบไปด้วย a valid Data URI", }, { ns: "Test.Latitude", expected: "Latitude ต้องเป็นละติจูด", }, { ns: "Test.Longitude", expected: "Longitude ต้องเป็นลองจิจูด", }, { ns: "Test.UUID", expected: "UUID ต้องเป็น UUID", }, { ns: "Test.UUID3", expected: "UUID3 ต้องเป็น version 3 UUID", }, { ns: "Test.UUID4", expected: "UUID4 ต้องเป็น version 4 UUID", }, { ns: "Test.UUID5", expected: "UUID5 ต้องเป็น version 5 UUID", }, { ns: "Test.ULID", expected: "ULID must be a valid ULID", }, { ns: "Test.ISBN", expected: "ISBN ต้องเป็นตัวเลข ISBN", }, { ns: "Test.ISBN10", expected: "ISBN10 ต้องเป็นตัวเลข ISBN-10", }, { ns: "Test.ISBN13", expected: "ISBN13 ต้องเป็นตัวเลข ISBN-13", }, { ns: "Test.ISSN", expected: "ISSN ต้องเป็นตัวเลข ISSN", }, { ns: "Test.Excludes", expected: "Excludes ต้องไม่มี 'text'", }, { ns: "Test.ExcludesAll", expected: "ExcludesAll ต้องไม่มีอักขระ '!@#$' ทั้งหมด", }, { ns: "Test.ExcludesRune", expected: "ExcludesRune ต้องไม่มี '☻'", }, { 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 ต้องเป็นเลขสีฐาน 16 เท่านั้น", }, { ns: "Test.NumberString", expected: "NumberString ต้องเป็นตัวเลขเท่านั้น", }, { ns: "Test.NumericString", expected: "NumericString ต้องเป็นค่าตัวเลขเท่านั้น", }, { 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.GteNumber", expected: "GteNumber ต้องมีค่ามากกว่า 5.56", }, { ns: "Test.GteMultiple", expected: "GteMultiple ต้องมีอย่างน้อย 2 รายการ", }, { ns: "Test.GteTime", expected: "GteTime ต้องเป็นเวลาหลังหรือเป็นเวลาปัจจุบัน", }, { ns: "Test.GtNumber", expected: "GtNumber ต้องมีค่ามากกว่า 5.56", }, { ns: "Test.GtMultiple", expected: "GtMultiple ต้องมีมากกว่า 2 รายการ", }, { ns: "Test.GtTime", expected: "GtTime ต้องเป็นเวลาหลังจากปัจจุบัน", }, { ns: "Test.LteNumber", expected: "LteNumber ต้องมีค่าน้อยกว่าหรือเท่ากับ 5.56", }, { ns: "Test.LteMultiple", expected: "LteMultiple ต้องมีไม่เกิน 2 รายการ", }, { ns: "Test.LteTime", expected: "LteTime ต้องเป็นเวลาก่อนหรือเป็นเวลาปัจจุบัน", }, { 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.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.StrPtrMaxLen", expected: "StrPtrMaxLen ต้องมีความยาวไม่เกิน 1 ตัวอักษร", }, { ns: "Test.StrPtrLt", expected: "StrPtrLt ต้องมีความยาวน้อยกว่า 1 ตัวอักษร", }, { ns: "Test.StrPtrLte", expected: "StrPtrLte ต้องมีความยาวไม่เกิน 1 ตัวอักษร", }, { 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 string", }, { ns: "Test.JWTString", expected: "JWTString ต้องเป็น jwt string", }, { ns: "Test.LowercaseString", expected: "LowercaseString ต้องเป็นตัวพิมพ์เล็ก", }, { ns: "Test.UppercaseString", expected: "UppercaseString ต้องเป็นตัวพิมพ์ใหญ่", }, { ns: "Test.Datetime", expected: "Datetime ไม่ตรงกับรูปแบบ 2006-01-02", }, { 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 ต้องเป็น boolean", }, { ns: "Test.Image", expected: "Image ต้องเป็นรูปภาพ", }, { ns: "Test.CveString", expected: "CveString ต้องเป็นรูปแบบ cve", }, { 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 ตัวอักษร", }, } 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)) } } golang-github-go-playground-validator-v10-10.30.1/translations/tr/000077500000000000000000000000001512410077000247225ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/translations/tr/tr.go000066400000000000000000001002731512410077000257010ustar00rootroot00000000000000package tr import ( "fmt" "log" "reflect" "strconv" "strings" "time" "github.com/go-playground/locales" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" ) // RegisterDefaultTranslations registers a set of default translations // for all built in tag's in validator; you may add your own as desired. func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (err error) { translations := []struct { tag string translation string override bool customRegisFunc validator.RegisterTranslationsFunc customTransFunc validator.TranslationFunc }{ { tag: "required", translation: "{0} zorunlu bir alandır", override: false, }, { tag: "len", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("len-string", "{0} uzunluğu {1} olmalıdır", false); err != nil { return } if err = ut.AddCardinal("len-string-character", "{0} karakter", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("len-string-character", "{0} karakter", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("len-number", "{0}, {1} değerine eşit olmalıdır", false); err != nil { return } if err = ut.Add("len-items", "{0}, {1} içermelidir", false); err != nil { return } if err = ut.AddCardinal("len-items-item", "{0} öğe", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("len-items-item", "{0} öğe", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("len-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("len-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-items", fe.Field(), c) default: t, err = ut.T("len-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "min", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("min-string", "{0} en az {1} uzunluğunda olmalıdır", false); err != nil { return } if err = ut.AddCardinal("min-string-character", "{0} karakter", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("min-string-character", "{0} karakter", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("min-number", "{0}, {1} veya daha büyük olmalıdır", false); err != nil { return } if err = ut.Add("min-items", "{0} en az {1} içermelidir", false); err != nil { return } if err = ut.AddCardinal("min-items-item", "{0} öğe", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("min-items-item", "{0} öğe", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("min-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("min-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-items", fe.Field(), c) default: t, err = ut.T("min-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "max", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("max-string", "{0} uzunluğu en fazla {1} olmalıdır", false); err != nil { return } if err = ut.AddCardinal("max-string-character", "{0} karakter", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("max-string-character", "{0} karakter", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("max-number", "{0}, {1} veya daha az olmalıdır", false); err != nil { return } if err = ut.Add("max-items", "{0} maksimum {1} içermelidir", false); err != nil { return } if err = ut.AddCardinal("max-items-item", "{0} öğe", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("max-items-item", "{0} öğe", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("max-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("max-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-items", fe.Field(), c) default: t, err = ut.T("max-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eq", translation: "{0}, {1} değerine eşit değil", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ne", translation: "{0}, {1} değerine eşit olmamalıdır", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "lt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lt-string", "{0}, {1} uzunluğundan daha az olmalıdır", false); err != nil { return } if err = ut.AddCardinal("lt-string-character", "{0} karakter", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lt-string-character", "{0} karakter", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-number", "{0}, {1} değerinden küçük olmalıdır", false); err != nil { return } if err = ut.Add("lt-items", "{0}, {1}den daha az içermelidir", false); err != nil { return } if err = ut.AddCardinal("lt-items-item", "{0} öğe", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lt-items-item", "{0} öğe", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-datetime", "{0} geçerli Tarih ve Saatten daha az olmalıdır", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "lte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lte-string", "{0} en fazla {1} uzunluğunda olmalıdır", false); err != nil { return } if err = ut.AddCardinal("lte-string-character", "{0} karakter", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lte-string-character", "{0} karakter", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-number", "{0}, {1} veya daha az olmalıdır", false); err != nil { return } if err = ut.Add("lte-items", "{0}, maksimum {1} içermelidir", false); err != nil { return } if err = ut.AddCardinal("lte-items-item", "{0} öğe", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("lte-items-item", "{0} öğe", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-datetime", "{0} geçerli Tarih ve Saate eşit veya daha küçük olmalıdır", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gt-string", "{0}, {1} uzunluğundan fazla olmalıdır", false); err != nil { return } if err = ut.AddCardinal("gt-string-character", "{0} karakter", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gt-string-character", "{0} karakter", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-number", "{0}, {1} değerinden büyük olmalıdır", false); err != nil { return } if err = ut.Add("gt-items", "{0}, {1}den daha fazla içermelidir", false); err != nil { return } if err = ut.AddCardinal("gt-items-item", "{0} öğe", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gt-items-item", "{0} öğe", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-datetime", "{0} geçerli Tarih ve Saatten büyük olmalıdır", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gte-string", "{0} en az {1} uzunluğunda olmalıdır", false); err != nil { return } if err = ut.AddCardinal("gte-string-character", "{0} karakter", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gte-string-character", "{0} karakter", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-number", "{0}, {1} veya daha büyük olmalıdır", false); err != nil { return } if err = ut.Add("gte-items", "{0} en az {1} içermelidir", false); err != nil { return } if err = ut.AddCardinal("gte-items-item", "{0} öğe", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal("gte-items-item", "{0} öğe", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-datetime", "{0} geçerli Tarih ve Saatten büyük veya ona eşit olmalıdır", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eqfield", translation: "{0}, {1} değerine eşit olmalıdır", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "eqcsfield", translation: "{0}, {1} değerine eşit olmalıdır", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "necsfield", translation: "{0}, {1} değerine eşit olmamalıdır", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtcsfield", translation: "{0}, {1} değerinden büyük olmalıdır", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtecsfield", translation: "{0}, {1} değerinden küçük veya ona eşit olmalıdır", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltcsfield", translation: "{0}, {1} değerinden küçük olmalıdır", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltecsfield", translation: "{0}, {1} değerinden küçük veya ona eşit olmalıdır", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "nefield", translation: "{0}, {1} değerine eşit olmamalıdır", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtfield", translation: "{0}, {1} değerinden büyük olmalıdır", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtefield", translation: "{0}, {1} değerinden büyük veya ona eşit olmalıdır", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltfield", translation: "{0}, {1} değerinden küçük olmalıdır", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltefield", translation: "{0}, {1} değerinden küçük veya ona eşit olmalıdır", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "alpha", translation: "{0} yalnızca alfabetik karakterler içerebilir", override: false, }, { tag: "alphanum", translation: "{0} yalnızca alfanümerik karakterler içerebilir", override: false, }, { tag: "numeric", translation: "{0} geçerli bir sayısal değer olmalıdır", override: false, }, { tag: "number", translation: "{0} geçerli bir sayı olmalıdır", override: false, }, { tag: "hexadecimal", translation: "{0} geçerli bir onaltılık olmalıdır", override: false, }, { tag: "hexcolor", translation: "{0} geçerli bir HEX rengi olmalıdır", override: false, }, { tag: "rgb", translation: "{0} geçerli bir RGB rengi olmalıdır", override: false, }, { tag: "rgba", translation: "{0} geçerli bir RGBA rengi olmalıdır", override: false, }, { tag: "hsl", translation: "{0} geçerli bir HSL rengi olmalıdır", override: false, }, { tag: "hsla", translation: "{0} geçerli bir HSLA rengi olmalıdır", override: false, }, { tag: "email", translation: "{0} geçerli bir e-posta adresi olmalıdır", override: false, }, { tag: "url", translation: "{0} geçerli bir URL olmalıdır", override: false, }, { tag: "uri", translation: "{0} geçerli bir URI olmalıdır", override: false, }, { tag: "base64", translation: "{0} geçerli bir Base64 karakter dizesi olmalıdır", override: false, }, { tag: "contains", translation: "{0}, '{1}' metnini içermelidir", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "containsany", translation: "{0}, '{1}' karakterlerinden en az birini içermelidir", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludes", translation: "{0}, '{1}' metnini içeremez", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesall", translation: "{0}, '{1}' karakterlerinden hiçbirini içeremez", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesrune", translation: "{0}, '{1}' ifadesini içeremez", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "isbn", translation: "{0} geçerli bir ISBN numarası olmalıdır", override: false, }, { tag: "isbn10", translation: "{0} geçerli bir ISBN-10 numarası olmalıdır", override: false, }, { tag: "isbn13", translation: "{0} geçerli bir ISBN-13 numarası olmalıdır", override: false, }, { tag: "issn", translation: "{0} geçerli bir ISSN numarası olmalıdır", override: false, }, { tag: "uuid", translation: "{0} geçerli bir UUID olmalıdır", override: false, }, { tag: "uuid3", translation: "{0} geçerli bir sürüm 3 UUID olmalıdır", override: false, }, { tag: "uuid4", translation: "{0} geçerli bir sürüm 4 UUID olmalıdır", override: false, }, { tag: "uuid5", translation: "{0} geçerli bir sürüm 5 UUID olmalıdır", override: false, }, { tag: "ulid", translation: "{0} geçerli bir ULID olmalıdır", override: false, }, { tag: "ascii", translation: "{0} yalnızca ascii karakterler içermelidir", override: false, }, { tag: "printascii", translation: "{0} yalnızca yazdırılabilir ascii karakterleri içermelidir", override: false, }, { tag: "multibyte", translation: "{0} çok baytlı karakterler içermelidir", override: false, }, { tag: "datauri", translation: "{0} geçerli bir Veri URI içermelidir", override: false, }, { tag: "latitude", translation: "{0} geçerli bir enlem koordinatı içermelidir", override: false, }, { tag: "longitude", translation: "{0} geçerli bir boylam koordinatı içermelidir", override: false, }, { tag: "ssn", translation: "{0} geçerli bir SSN numarası olmalıdır", override: false, }, { tag: "ipv4", translation: "{0} geçerli bir IPv4 adresi olmalıdır", override: false, }, { tag: "ipv6", translation: "{0} geçerli bir IPv6 adresi olmalıdır", override: false, }, { tag: "ip", translation: "{0} geçerli bir IP adresi olmalıdır", override: false, }, { tag: "cidr", translation: "{0} geçerli bir CIDR gösterimi içermelidir", override: false, }, { tag: "cidrv4", translation: "{0} bir IPv4 adresi için geçerli bir CIDR gösterimi içermelidir", override: false, }, { tag: "cidrv6", translation: "{0} bir IPv6 adresi için geçerli bir CIDR gösterimi içermelidir", override: false, }, { tag: "tcp_addr", translation: "{0} geçerli bir TCP adresi olmalıdır", override: false, }, { tag: "tcp4_addr", translation: "{0} geçerli bir IPv4 TCP adresi olmalıdır", override: false, }, { tag: "tcp6_addr", translation: "{0} geçerli bir IPv6 TCP adresi olmalıdır", override: false, }, { tag: "udp_addr", translation: "{0} geçerli bir UDP adresi olmalıdır", override: false, }, { tag: "udp4_addr", translation: "{0} geçerli bir IPv4 UDP adresi olmalıdır", override: false, }, { tag: "udp6_addr", translation: "{0} geçerli bir IPv6 UDP adresi olmalıdır", override: false, }, { tag: "ip_addr", translation: "{0} çözülebilir bir IP adresi olmalıdır", override: false, }, { tag: "ip4_addr", translation: "{0} çözülebilir bir IPv4 adresi olmalıdır", override: false, }, { tag: "ip6_addr", translation: "{0} çözülebilir bir IPv6 adresi olmalıdır", override: false, }, { tag: "unix_addr", translation: "{0} çözülebilir bir UNIX adresi olmalıdır", override: false, }, { tag: "mac", translation: "{0} geçerli bir MAC adresi içermelidir", override: false, }, { tag: "unique", translation: "{0} benzersiz değerler içermelidir", override: false, }, { tag: "iscolor", translation: "{0} geçerli bir renk olmalıdır", override: false, }, { tag: "oneof", translation: "{0}, [{1}]'dan biri olmalıdır", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { s, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return s }, }, { tag: "image", translation: "{0} geçerli bir resim olmalıdır", override: false, }, } for _, t := range translations { if t.customTransFunc != nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, t.customTransFunc) } else if t.customTransFunc != nil && t.customRegisFunc == nil { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), t.customTransFunc) } else if t.customTransFunc == nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, translateFunc) } else { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), translateFunc) } if err != nil { return } } return } func registrationFunc(tag string, translation string, override bool) validator.RegisterTranslationsFunc { return func(ut ut.Translator) (err error) { if err = ut.Add(tag, translation, override); err != nil { return } return } } func translateFunc(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t } golang-github-go-playground-validator-v10-10.30.1/translations/tr/tr_test.go000066400000000000000000000505341512410077000267440ustar00rootroot00000000000000package 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"` ISSN string `validate:"issn"` 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"` Image string `validate:"image"` } 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.ISSN", expected: "ISSN geçerli bir ISSN 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", }, { ns: "Test.Image", expected: "Image geçerli bir resim olmalıdır", }, } 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)) } } golang-github-go-playground-validator-v10-10.30.1/translations/uk/000077500000000000000000000000001512410077000247145ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/translations/uk/uk.go000066400000000000000000000746071512410077000257000ustar00rootroot00000000000000package uk import ( "fmt" "log" "reflect" "strconv" "strings" "time" "github.com/go-playground/locales" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" ) // RegisterDefaultTranslations registers a set of default translations // for all built in tag's in validator; you may add your own as desired. func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (err error) { translations := []struct { tag string translation string override bool customRegisFunc validator.RegisterTranslationsFunc customTransFunc validator.TranslationFunc }{ { tag: "required", translation: "{0} обов'язкове поле", override: false, }, { tag: "required_if", translation: "{0} обов'язкове поле", override: false, }, { tag: "required_unless", translation: "{0} обов'язкове поле", override: false, }, { tag: "required_with", translation: "{0} обов'язкове поле", override: false, }, { tag: "required_with_all", translation: "{0} обов'язкове поле", override: false, }, { tag: "required_without", translation: "{0} обов'язкове поле", override: false, }, { tag: "required_without_all", translation: "{0} обов'язкове поле", override: false, }, { tag: "excluded_if", translation: "{0} є виключеним полем", override: false, }, { tag: "excluded_unless", translation: "{0} є виключеним полем", override: false, }, { tag: "excluded_with", translation: "{0} є виключеним полем", override: false, }, { tag: "excluded_with_all", translation: "{0} є виключеним полем", override: false, }, { tag: "excluded_without", translation: "{0} є виключеним полем", override: false, }, { tag: "excluded_without_all", translation: "{0} є виключеним полем", override: false, }, { tag: "isdefault", translation: "{0} має бути значенням за замовчуванням", override: false, }, { tag: "len", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("len-string", "{0} має бути довжиною в {1}", false); err != nil { return } if err = ut.Add("len-number", "{0} має дорівнювати {1}", false); err != nil { return } if err = ut.Add("len-items", "{0} має містити {1}", false); err != nil { return } if err = registerCardinals(ut, "len"); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("len-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("len-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-items", fe.Field(), c) default: t, err = ut.T("len-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "min", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("min-string", "{0} має містити щонайменше {1}", false); err != nil { return } if err = ut.Add("min-number", "{0} має бути більше чи дорівнювати {1}", false); err != nil { return } if err = ut.Add("min-items", "{0} має містити щонайменше {1}", false); err != nil { return } if err = registerCardinals(ut, "min"); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("min-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("min-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-items", fe.Field(), c) default: t, err = ut.T("min-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "max", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("max-string", "{0} має містити максимум {1}", false); err != nil { return } if err = ut.Add("max-number", "{0} має бути менше чи дорівнювати {1}", false); err != nil { return } if err = ut.Add("max-items", "{0} має містити максимум {1}", false); err != nil { return } if err = registerCardinals(ut, "max"); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("max-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("max-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-items", fe.Field(), c) default: t, err = ut.T("max-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eq", translation: "{0} не дорівнює {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "ne", translation: "{0} має не дорівнювати {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "lt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lt-string", "{0} має мати менше за {1}", false); err != nil { return } if err = ut.Add("lt-number", "{0} має бути менше {1}", false); err != nil { return } if err = ut.Add("lt-items", "{0} має містити менше ніж {1}", false); err != nil { return } if err = ut.Add("lt-datetime", "{0} має бути менше поточної дати й часу", false); err != nil { return } if err = registerCardinals(ut, "lt"); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "lte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lte-string", "{0} має містити максимум {1}", false); err != nil { return } if err = ut.Add("lte-number", "{0} має бути менше чи дорівнювати {1}", false); err != nil { return } if err = ut.Add("lte-items", "{0} має містити максимум {1}", false); err != nil { return } if err = ut.Add("lte-datetime", "{0} має бути менше чи дорівнювати поточній даті та часу", false); err != nil { return } if err = registerCardinals(ut, "lte"); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("lte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gt-string", "{0} має бути довше за {1}", false); err != nil { return } if err = ut.Add("gt-number", "{0} має бути більше {1}", false); err != nil { return } if err = ut.Add("gt-items", "{0} має містити більше ніж {1}", false); err != nil { return } if err = ut.Add("gt-datetime", "{0} має бути пізніше поточного моменту", false); err != nil { return } if err = registerCardinals(ut, "gt"); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gte-string", "{0} має містити щонайменше {1}", false); err != nil { return } if err = ut.Add("gte-number", "{0} має бути більше чи дорівнювати {1}", false); err != nil { return } if err = ut.Add("gte-items", "{0} має містити щонайменше {1}", false); err != nil { return } if err = ut.Add("gte-datetime", "{0} має бути пізніше чи дорівнювати теперішньому моменту", false); err != nil { return } if err = registerCardinals(ut, "gte"); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' cannot be used on a struct type", fe.Tag()) goto END } t, err = ut.T("gte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("warning: error translating FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eqfield", translation: "{0} має дорівнювати {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "eqcsfield", translation: "{0} має дорівнювати {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "necsfield", translation: "{0} не має дорівнювати {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "gtcsfield", translation: "{0} має бути більше {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "gtecsfield", translation: "{0} має бути більше чи дорівнювати {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "ltcsfield", translation: "{0} має бути менше {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "ltecsfield", translation: "{0} має бути менше чи дорівнювати {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "nefield", translation: "{0} не має дорівнювати {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "gtfield", translation: "{0} має бути більше {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "gtefield", translation: "{0} має бути більше чи дорівнювати {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "ltfield", translation: "{0} має бути менше {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "ltefield", translation: "{0} має бути менше чи дорівнювати {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "alpha", translation: "{0} має містити тільки літери", override: false, }, { tag: "alphanum", translation: "{0} має містити тільки літери та цифри", override: false, }, { tag: "numeric", translation: "{0} має бути цифровим значенням", override: false, }, { tag: "number", translation: "{0} має бути цифрою", override: false, }, { tag: "hexadecimal", translation: "{0} має бути шістнадцятковим рядком", override: false, }, { tag: "hexcolor", translation: "{0} має бути HEX кольором", override: false, }, { tag: "rgb", translation: "{0} має бути RGB кольором", override: false, }, { tag: "rgba", translation: "{0} має бути RGBA кольором", override: false, }, { tag: "hsl", translation: "{0} має бути HSL кольором", override: false, }, { tag: "hsla", translation: "{0} має бути HSLA кольором", override: false, }, { tag: "e164", translation: "{0} має бути номером телефону у форматі E.164", override: false, }, { tag: "email", translation: "{0} має бути email адресою", override: false, }, { tag: "url", translation: "{0} має бути URL", override: false, }, { tag: "uri", translation: "{0} має бути URI", override: false, }, { tag: "base64", translation: "{0} має бути Base64 рядком", override: false, }, { tag: "contains", translation: "{0} має містити текст '{1}'", override: false, customTransFunc: translateFuncWithParam, }, { tag: "containsany", translation: "{0} має містити щонайменше один із символів '{1}'", override: false, customTransFunc: translateFuncWithParam, }, { tag: "excludes", translation: "{0} не має містити текст '{1}'", override: false, customTransFunc: translateFuncWithParam, }, { tag: "excludesall", translation: "{0} не має містити символи '{1}'", override: false, customTransFunc: translateFuncWithParam, }, { tag: "excludesrune", translation: "{0} не має містити '{1}'", override: false, customTransFunc: translateFuncWithParam, }, { tag: "isbn", translation: "{0} має бути ISBN номером", override: false, }, { tag: "isbn10", translation: "{0} має бути ISBN-10 номером", override: false, }, { tag: "isbn13", translation: "{0} має бути ISBN-13 номером", override: false, }, { tag: "issn", translation: "{0} має бути ISSN номером", override: false, }, { tag: "uuid", translation: "{0} має бути UUID", override: false, }, { tag: "uuid3", translation: "{0} має бути UUID 3 версії", override: false, }, { tag: "uuid4", translation: "{0} має бути UUID 4 версії", override: false, }, { tag: "uuid5", translation: "{0} має бути UUID 5 версії", override: false, }, { tag: "ulid", translation: "{0} має бути ULID", override: false, }, { tag: "ascii", translation: "{0} має містити тільки ascii символи", override: false, }, { tag: "printascii", translation: "{0} має містити тільки доступні для друку ascii символи", override: false, }, { tag: "multibyte", translation: "{0} має містити мультібайтні символи", override: false, }, { tag: "datauri", translation: "{0} має містити Data URI", override: false, }, { tag: "latitude", translation: "{0} має містити координати широти", override: false, }, { tag: "longitude", translation: "{0} має містити координати довготи", override: false, }, { tag: "ssn", translation: "{0} має бути SSN номером", override: false, }, { tag: "ipv4", translation: "{0} має бути IPv4 адресою", override: false, }, { tag: "ipv6", translation: "{0} має бути IPv6 адресою", override: false, }, { tag: "ip", translation: "{0} має бути IP адресою", override: false, }, { tag: "cidr", translation: "{0} має містити CIDR позначення", override: false, }, { tag: "cidrv4", translation: "{0} має містити CIDR позначення для IPv4 адреси", override: false, }, { tag: "cidrv6", translation: "{0} має містити CIDR позначення для IPv6 адреси", override: false, }, { tag: "tcp_addr", translation: "{0} має бути TCP адресою", override: false, }, { tag: "tcp4_addr", translation: "{0} має бути IPv4 TCP адресою", override: false, }, { tag: "tcp6_addr", translation: "{0} має бути IPv6 TCP адресою", override: false, }, { tag: "udp_addr", translation: "{0} має бути UDP адресою", override: false, }, { tag: "udp4_addr", translation: "{0} має бути IPv4 UDP адресою", override: false, }, { tag: "udp6_addr", translation: "{0} має бути IPv6 UDP адресою", override: false, }, { tag: "ip_addr", translation: "{0} має бути розпізнаваною IP адресою", override: false, }, { tag: "ip4_addr", translation: "{0} має бути розпізнаваною IPv4 адресою", override: false, }, { tag: "ip6_addr", translation: "{0} має бути розпізнаваною IPv6 адресою", override: false, }, { tag: "unix_addr", translation: "{0} має бути розпізнаваною UNIX адресою", override: false, }, { tag: "mac", translation: "{0} має містити MAC адресу", override: false, }, { tag: "fqdn", translation: "{0} має містити FQDN", override: false, }, { tag: "unique", translation: "{0} має містити унікальні значення", override: false, }, { tag: "iscolor", translation: "{0} має бути кольором", override: false, }, { tag: "oneof", translation: "{0} має бути одним з [{1}]", override: false, customTransFunc: translateFuncWithParam, }, { tag: "json", translation: "{0} має бути json рядком", override: false, }, { tag: "jwt", translation: "{0} має бути jwt рядком", override: false, }, { tag: "lowercase", translation: "{0} має бути рядком у нижньому регістрі", override: false, }, { tag: "uppercase", translation: "{0} має бути рядком у верхньому регістрі", override: false, }, { tag: "datetime", translation: "{0} не відповідає {1} формату", override: false, customTransFunc: translateFuncWithParam, }, { tag: "postcode_iso3166_alpha2", translation: "{0} не відповідає формату поштового індексу країни {1}", override: false, customTransFunc: translateFuncWithParam, }, { tag: "postcode_iso3166_alpha2_field", translation: "{0} не відповідає формату поштового індексу країни в {1} полі", override: false, customTransFunc: translateFuncWithParam, }, { tag: "boolean", translation: "{0} має бути булевим значенням", override: false, }, { tag: "image", translation: "{0} має бути допустимим зображенням", override: false, }, { tag: "cve", translation: "{0} має бути cve ідентифікатором", override: false, }, } for _, t := range translations { if t.customTransFunc != nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, t.customTransFunc) } else if t.customTransFunc != nil && t.customRegisFunc == nil { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), t.customTransFunc) } else if t.customTransFunc == nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, translateFunc) } else { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), translateFunc) } if err != nil { return } } return } func registrationFunc(tag string, translation string, override bool) validator.RegisterTranslationsFunc { return func(ut ut.Translator) (err error) { if err = ut.Add(tag, translation, override); err != nil { return } return } } func translateFunc(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t } func translateFuncWithParam(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("warning: error translating FieldError: %#v", fe) return fe.(error).Error() } return t } func registerCardinals(ut ut.Translator, prefix string) (err error) { var ( stringCharacterKey = fmt.Sprintf("%s-string-character", prefix) itemsItemKey = fmt.Sprintf("%s-items-item", prefix) ) if err = ut.AddCardinal(stringCharacterKey, "{0} символ", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal(stringCharacterKey, "{0} символи", locales.PluralRuleFew, false); err != nil { return } if err = ut.AddCardinal(stringCharacterKey, "{0} символів", locales.PluralRuleMany, false); err != nil { return } if err = ut.AddCardinal(stringCharacterKey, "{0} символи", locales.PluralRuleOther, false); err != nil { return } if err = ut.AddCardinal(itemsItemKey, "{0} елемент", locales.PluralRuleOne, false); err != nil { return } if err = ut.AddCardinal(itemsItemKey, "{0} елементи", locales.PluralRuleFew, false); err != nil { return } if err = ut.AddCardinal(itemsItemKey, "{0} елементів", locales.PluralRuleMany, false); err != nil { return } if err = ut.AddCardinal(itemsItemKey, "{0} елементи", locales.PluralRuleOther, false); err != nil { return } return } golang-github-go-playground-validator-v10-10.30.1/translations/uk/uk_test.go000066400000000000000000001035421512410077000267260ustar00rootroot00000000000000package uk import ( "testing" "time" . "github.com/go-playground/assert/v2" ukrainian "github.com/go-playground/locales/uk" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" ) func TestTranslations(t *testing.T) { uk := ukrainian.New() uni := ut.New(uk, uk) trans, ok := uni.GetTranslator("uk") if !ok { t.Fatalf("didn't found translator") } 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 RequiredUnless string RequiredWith string RequiredWithAll string RequiredWithout string RequiredWithoutAll string ExcludedIf string ExcludedUnless string ExcludedWith string ExcludedWithAll string ExcludedWithout string ExcludedWithoutAll 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"` RequiredUnless string `validate:"required_unless=Inner.RequiredUnless abcd"` RequiredWith string `validate:"required_with=Inner.RequiredWith"` RequiredWithAll string `validate:"required_with_all=Inner.RequiredWith Inner.RequiredWithAll"` RequiredWithout string `validate:"required_without=Inner.RequiredWithout"` RequiredWithoutAll string `validate:"required_without_all=Inner.RequiredWithout Inner.RequiredWithoutAll"` ExcludedIf string `validate:"excluded_if=Inner.ExcludedIf abcd"` ExcludedUnless string `validate:"excluded_unless=Inner.ExcludedUnless abcd"` ExcludedWith string `validate:"excluded_with=Inner.ExcludedWith"` ExcludedWithout string `validate:"excluded_with_all=Inner.ExcludedWithAll"` ExcludedWithAll string `validate:"excluded_without=Inner.ExcludedWithout"` ExcludedWithoutAll string `validate:"excluded_without_all=Inner.ExcludedWithoutAll"` IsDefault string `validate:"isdefault"` LenString string `validate:"len=1"` LenNumber float64 `validate:"len=1113.00"` LenMultiple []string `validate:"len=7"` LenMultipleSecond []string `validate:"len=2"` LenMultipleThird []string `validate:"len=1"` MinString string `validate:"min=1"` MinStringMultiple string `validate:"min=2"` MinStringMultipleSecond string `validate:"min=7"` MinStringMultipleThird string `validate:"min=1"` MinNumber float64 `validate:"min=1113.00"` MinMultiple []string `validate:"min=7"` MinMultipleSecond []string `validate:"min=2"` MinMultipleThird []string `validate:"min=1"` MaxString string `validate:"max=3"` MaxStringSecond string `validate:"max=7"` MaxStringThird string `validate:"max=1"` MaxNumber float64 `validate:"max=1113.00"` MaxMultiple []string `validate:"max=7"` MaxMultipleSecond []string `validate:"max=2"` MaxMultipleThird []string `validate:"max=1"` 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"` LtStringThird string `validate:"lt=1"` LtNumber float64 `validate:"lt=5.56"` LtMultiple []string `validate:"lt=2"` LtMultipleSecond []string `validate:"lt=7"` LtMultipleThird []string `validate:"lt=1"` LtTime time.Time `validate:"lt"` LteString string `validate:"lte=3"` LteStringSecond string `validate:"lte=7"` LteStringThird string `validate:"lte=1"` LteNumber float64 `validate:"lte=5.56"` LteMultiple []string `validate:"lte=2"` LteMultipleSecond []string `validate:"lte=7"` LteMultipleThird []string `validate:"lte=1"` LteTime time.Time `validate:"lte"` GtString string `validate:"gt=3"` GtStringSecond string `validate:"gt=7"` GtStringThird string `validate:"gt=1"` GtNumber float64 `validate:"gt=5.56"` GtMultiple []string `validate:"gt=2"` GtMultipleSecond []string `validate:"gt=7"` GtMultipleThird []string `validate:"gt=1"` GtTime time.Time `validate:"gt"` GteString string `validate:"gte=3"` GteStringSecond string `validate:"gte=7"` GteStringThird string `validate:"gte=1"` GteNumber float64 `validate:"gte=5.56"` GteMultiple []string `validate:"gte=2"` GteMultipleSecond []string `validate:"gte=7"` GteMultipleThird []string `validate:"gte=1"` 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"` ISSN string `validate:"issn"` 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"` 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"` 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"` Image string `validate:"image"` CveString string `validate:"cve"` } var test Test test.Inner.EqCSFieldString = "1234" test.Inner.GtCSFieldString = "1234" test.Inner.GteCSFieldString = "1234" test.Inner.RequiredUnless = "1234" test.Inner.RequiredWith = "1234" test.Inner.RequiredWithAll = "1234" test.Inner.ExcludedIf = "abcd" test.Inner.ExcludedUnless = "1234" test.Inner.ExcludedWith = "1234" test.Inner.ExcludedWithAll = "1234" test.ExcludedIf = "1234" test.ExcludedUnless = "1234" test.ExcludedWith = "1234" test.ExcludedWithAll = "1234" test.ExcludedWithout = "1234" test.ExcludedWithoutAll = "1234" test.MaxString = "1234" test.MaxStringSecond = "12345678" test.MaxStringThird = "12" test.MaxNumber = 2000 test.MaxMultiple = make([]string, 9) test.MaxMultipleSecond = make([]string, 3) test.MaxMultipleThird = make([]string, 2) test.LtString = "1234" test.LtStringSecond = "12345678" test.LtStringThird = "12" test.LtNumber = 6 test.LtMultiple = make([]string, 3) test.LtMultipleSecond = make([]string, 8) test.LtMultipleThird = make([]string, 2) test.LtTime = time.Now().Add(time.Hour * 24) test.LteString = "1234" test.LteStringSecond = "12345678" test.LteStringThird = "12" test.LteNumber = 6 test.LteMultiple = make([]string, 3) test.LteMultipleSecond = make([]string, 8) test.LteMultipleThird = make([]string, 2) 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 має бути кольором", }, { ns: "Test.MAC", expected: "MAC має містити MAC адресу", }, { ns: "Test.FQDN", expected: "FQDN має містити FQDN", }, { 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.ISSN", expected: "ISSN має бути ISSN номером", }, { 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.GteStringThird", expected: "GteStringThird має містити щонайменше 1 символ", }, { ns: "Test.GteNumber", expected: "GteNumber має бути більше чи дорівнювати 5,56", }, { ns: "Test.GteMultiple", expected: "GteMultiple має містити щонайменше 2 елементи", }, { ns: "Test.GteMultipleSecond", expected: "GteMultipleSecond має містити щонайменше 7 елементів", }, { ns: "Test.GteMultipleThird", expected: "GteMultipleThird має містити щонайменше 1 елемент", }, { ns: "Test.GteTime", expected: "GteTime має бути пізніше чи дорівнювати теперішньому моменту", }, { ns: "Test.GtString", expected: "GtString має бути довше за 3 символи", }, { ns: "Test.GtStringSecond", expected: "GtStringSecond має бути довше за 7 символів", }, { ns: "Test.GtStringThird", expected: "GtStringThird має бути довше за 1 символ", }, { ns: "Test.GtNumber", expected: "GtNumber має бути більше 5,56", }, { ns: "Test.GtMultiple", expected: "GtMultiple має містити більше ніж 2 елементи", }, { ns: "Test.GtMultipleSecond", expected: "GtMultipleSecond має містити більше ніж 7 елементів", }, { ns: "Test.GtMultipleThird", expected: "GtMultipleThird має містити більше ніж 1 елемент", }, { ns: "Test.GtTime", expected: "GtTime має бути пізніше поточного моменту", }, { ns: "Test.LteString", expected: "LteString має містити максимум 3 символи", }, { ns: "Test.LteStringSecond", expected: "LteStringSecond має містити максимум 7 символів", }, { ns: "Test.LteStringThird", expected: "LteStringThird має містити максимум 1 символ", }, { ns: "Test.LteNumber", expected: "LteNumber має бути менше чи дорівнювати 5,56", }, { ns: "Test.LteMultiple", expected: "LteMultiple має містити максимум 2 елементи", }, { ns: "Test.LteMultipleSecond", expected: "LteMultipleSecond має містити максимум 7 елементів", }, { ns: "Test.LteMultipleThird", expected: "LteMultipleThird має містити максимум 1 елемент", }, { ns: "Test.LteTime", expected: "LteTime має бути менше чи дорівнювати поточній даті та часу", }, { ns: "Test.LtString", expected: "LtString має мати менше за 3 символи", }, { ns: "Test.LtStringSecond", expected: "LtStringSecond має мати менше за 7 символів", }, { ns: "Test.LtStringThird", expected: "LtStringThird має мати менше за 1 символ", }, { ns: "Test.LtNumber", expected: "LtNumber має бути менше 5,56", }, { ns: "Test.LtMultiple", expected: "LtMultiple має містити менше ніж 2 елементи", }, { ns: "Test.LtMultipleSecond", expected: "LtMultipleSecond має містити менше ніж 7 елементів", }, { ns: "Test.LtMultipleThird", expected: "LtMultipleThird має містити менше ніж 1 елемент", }, { 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.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.MinStringMultipleThird", expected: "MinStringMultipleThird має містити щонайменше 1 символ", }, { 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.LenMultipleThird", expected: "LenMultipleThird має містити 1 елемент", }, { ns: "Test.RequiredString", expected: "RequiredString обов'язкове поле", }, { ns: "Test.RequiredIf", expected: "RequiredIf обов'язкове поле", }, { ns: "Test.RequiredNumber", expected: "RequiredNumber обов'язкове поле", }, { ns: "Test.RequiredMultiple", expected: "RequiredMultiple обов'язкове поле", }, { ns: "Test.RequiredUnless", expected: "RequiredUnless обов'язкове поле", }, { ns: "Test.RequiredWith", expected: "RequiredWith обов'язкове поле", }, { ns: "Test.RequiredWithAll", expected: "RequiredWithAll обов'язкове поле", }, { ns: "Test.RequiredWithout", expected: "RequiredWithout обов'язкове поле", }, { ns: "Test.RequiredWithoutAll", expected: "RequiredWithoutAll обов'язкове поле", }, { ns: "Test.ExcludedIf", expected: "ExcludedIf є виключеним полем", }, { ns: "Test.ExcludedUnless", expected: "ExcludedUnless є виключеним полем", }, { ns: "Test.ExcludedWith", expected: "ExcludedWith є виключеним полем", }, { ns: "Test.ExcludedWithAll", expected: "ExcludedWithAll є виключеним полем", }, { ns: "Test.ExcludedWithout", expected: "ExcludedWithout є виключеним полем", }, { ns: "Test.ExcludedWithoutAll", expected: "ExcludedWithoutAll є виключеним полем", }, { 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 має містити унікальні значення", }, { 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 має бути булевим значенням", }, { ns: "Test.Image", expected: "Image має бути допустимим зображенням", }, { ns: "Test.CveString", expected: "CveString має бути cve ідентифікатором", }, } 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)) } } golang-github-go-playground-validator-v10-10.30.1/translations/vi/000077500000000000000000000000001512410077000247135ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/translations/vi/vi.go000066400000000000000000001043441512410077000256660ustar00rootroot00000000000000package vi import ( "fmt" "log" "reflect" "strconv" "strings" "time" "github.com/go-playground/locales" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" ) // RegisterDefaultTranslations registers a set of default translations // for all built in tag's in validator; you may add your own as desired. func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (err error) { translations := []struct { tag string translation string override bool customRegisFunc validator.RegisterTranslationsFunc customTransFunc validator.TranslationFunc }{ { tag: "required", translation: "{0} không được bỏ trống", override: false, }, { tag: "len", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("len-string", "{0} phải có độ dài là {1}", false); err != nil { return } // if err = ut.AddCardinal("len-string-character", "{0} ký tự", locales.PluralRuleOne, false); err != nil { // return // } if err = ut.AddCardinal("len-string-character", "{0} ký tự", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("len-number", "{0} phải bằng {1}", false); err != nil { return } if err = ut.Add("len-items", "{0} phải chứa {1}", false); err != nil { return } // if err = ut.AddCardinal("len-items-item", "{0} phần tử", locales.PluralRuleOne, false); err != nil { // return // } if err = ut.AddCardinal("len-items-item", "{0} phần tử", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("len-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("len-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-items", fe.Field(), c) default: t, err = ut.T("len-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "min", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("min-string", "{0} phải chứa ít nhất {1}", false); err != nil { return } // if err = ut.AddCardinal("min-string-character", "{0} ký tự", locales.PluralRuleOne, false); err != nil { // return // } if err = ut.AddCardinal("min-string-character", "{0} ký tự", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("min-number", "{0} phải bằng {1} hoặc lớn hơn", false); err != nil { return } if err = ut.Add("min-items", "{0} phải chứa ít nhất {1}", false); err != nil { return } // if err = ut.AddCardinal("min-items-item", "{0} phần tử", locales.PluralRuleOne, false); err != nil { // return // } if err = ut.AddCardinal("min-items-item", "{0} phần tử", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("min-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("min-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-items", fe.Field(), c) default: t, err = ut.T("min-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "max", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("max-string", "{0} chỉ được chứa tối đa {1}", false); err != nil { return } // if err = ut.AddCardinal("max-string-character", "{0} ký tự", locales.PluralRuleOne, false); err != nil { // return // } if err = ut.AddCardinal("max-string-character", "{0} ký tự", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("max-number", "{0} phải là {1} hoặc nhỏ hơn", false); err != nil { return } if err = ut.Add("max-items", "{0} chỉ được chứa tối đa {1}", false); err != nil { return } // if err = ut.AddCardinal("max-items-item", "{0} phần tử", locales.PluralRuleOne, false); err != nil { // return // } if err = ut.AddCardinal("max-items-item", "{0} phần tử", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("max-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("max-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-items", fe.Field(), c) default: t, err = ut.T("max-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eq", translation: "{0} không bằng {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ne", translation: "{0} không được bằng {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "lt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lt-string", "{0} phải có độ dài nhỏ hơn {1}", false); err != nil { return } // if err = ut.AddCardinal("lt-string-character", "{0} ký tự", locales.PluralRuleOne, false); err != nil { // return // } if err = ut.AddCardinal("lt-string-character", "{0} ký tự", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-number", "{0} phải nhỏ hơn {1}", false); err != nil { return } if err = ut.Add("lt-items", "{0} chỉ được chứa ít hơn {1}", false); err != nil { return } // if err = ut.AddCardinal("lt-items-item", "{0} phần tử", locales.PluralRuleOne, false); err != nil { // return // } if err = ut.AddCardinal("lt-items-item", "{0} phần tử", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-datetime", "{0} phải nhỏ hơn Ngày & Giờ hiện tại", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' không thể dùng trên kiểu struct", fe.Tag()) goto END } t, err = ut.T("lt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "lte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lte-string", "{0} chỉ được có độ dài tối đa là {1}", false); err != nil { return } // if err = ut.AddCardinal("lte-string-character", "{0} ký tự", locales.PluralRuleOne, false); err != nil { // return // } if err = ut.AddCardinal("lte-string-character", "{0} ký tự", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-number", "{0} phải là {1} hoặc nhỏ hơn", false); err != nil { return } if err = ut.Add("lte-items", "{0} chỉ được chứa nhiều nhất {1}", false); err != nil { return } // if err = ut.AddCardinal("lte-items-item", "{0} phần tử", locales.PluralRuleOne, false); err != nil { // return // } if err = ut.AddCardinal("lte-items-item", "{0} phần tử", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-datetime", "{0} chỉ được nhỏ hơn hoặc bằng Ngày & Giờ hiện tại", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' không thể dùng trên kiểu struct", fe.Tag()) goto END } t, err = ut.T("lte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("lte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gt-string", "{0} phải có độ dài lớn hơn {1}", false); err != nil { return } // if err = ut.AddCardinal("gt-string-character", "{0} ký tự", locales.PluralRuleOne, false); err != nil { // return // } if err = ut.AddCardinal("gt-string-character", "{0} ký tự", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-number", "{0} phải lớn hơn {1}", false); err != nil { return } if err = ut.Add("gt-items", "{0} phải chứa nhiều hơn {1}", false); err != nil { return } // if err = ut.AddCardinal("gt-items-item", "{0} phần tử", locales.PluralRuleOne, false); err != nil { // return // } if err = ut.AddCardinal("gt-items-item", "{0} phần tử", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-datetime", "{0} phải lớn hơn Ngày & Giờ hiện tại", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' không thể dùng trên kiểu struct", fe.Tag()) goto END } t, err = ut.T("gt-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "gte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gte-string", "{0} phải có độ dài ít nhất {1}", false); err != nil { return } // if err = ut.AddCardinal("gte-string-character", "{0} ký tự", locales.PluralRuleOne, false); err != nil { // return // } if err = ut.AddCardinal("gte-string-character", "{0} ký tự", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-number", "{0} phải là {1} hoặc lớn hơn", false); err != nil { return } if err = ut.Add("gte-items", "{0} phải chứa ít nhất {1}", false); err != nil { return } // if err = ut.AddCardinal("gte-items-item", "{0} phần tử", locales.PluralRuleOne, false); err != nil { // return // } if err = ut.AddCardinal("gte-items-item", "{0} phần tử", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-datetime", "{0} phải lớn hơn hoặc bằng Ngày & Giờ hiện tại", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s' không thể dùng trên kiểu struct", fe.Tag()) goto END } t, err = ut.T("gte-datetime", fe.Field()) default: err = fn() if err != nil { goto END } t, err = ut.T("gte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %s", err) return fe.(error).Error() } return t }, }, { tag: "eqfield", translation: "{0} phải bằng {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "eqcsfield", translation: "{0} phải bằng {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "necsfield", translation: "{0} không được phép bằng {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtcsfield", translation: "{0} phải lớn hơn {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtecsfield", translation: "{0} phải lớn hơn hoặc bằng {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltcsfield", translation: "{0} chỉ được nhỏ hơn {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltecsfield", translation: "{0} chỉ được nhỏ hơn hoặc bằng {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "nefield", translation: "{0} không được phép bằng {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtfield", translation: "{0} phải lớn hơn {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtefield", translation: "{0} phải lớn hơn hoặc bằng {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltfield", translation: "{0} chỉ được nhỏ hơn {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltefield", translation: "{0} chỉ được nhỏ hơn hoặc bằng {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "alpha", translation: "{0} chỉ được chứa ký tự dạng alphabetic", override: false, }, { tag: "alphanum", translation: "{0} chỉ được chứa ký tự dạng alphanumeric", override: false, }, { tag: "numeric", translation: "{0} chỉ được chứa giá trị số hoặc số dưới dạng chữ", override: false, }, { tag: "number", translation: "{0} chỉ được chứa giá trị số", override: false, }, { tag: "hexadecimal", translation: "{0} phải là giá trị hexadecimal", override: false, }, { tag: "hexcolor", translation: "{0} phải là giá trị HEX color", override: false, }, { tag: "rgb", translation: "{0} phải là giá trị RGB color", override: false, }, { tag: "rgba", translation: "{0} phải là giá trị RGBA color", override: false, }, { tag: "hsl", translation: "{0} phải là giá trị HSL color", override: false, }, { tag: "hsla", translation: "{0} phải là giá trị HSLA color", override: false, }, { tag: "e164", translation: "{0} phải là giá trị số điện thoại theo định dạng E.164", override: false, }, { tag: "email", translation: "{0} phải là giá trị email address", override: false, }, { tag: "url", translation: "{0} phải là giá trị URL", override: false, }, { tag: "uri", translation: "{0} phải là giá trị URI", override: false, }, { tag: "base64", translation: "{0} phải là giá trị chuỗi Base64", override: false, }, { tag: "contains", translation: "{0} phải chứa chuỗi '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "containsany", translation: "{0} phải chứa ít nhất 1 trong cách ký tự sau '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludes", translation: "{0} không được chứa chuỗi '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesall", translation: "{0} không được chứa bất kỳ ký tự nào trong nhóm ký tự '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesrune", translation: "{0} không được chứa '{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "isbn", translation: "{0} phải là số ISBN", override: false, }, { tag: "isbn10", translation: "{0} phải là số ISBN-10", override: false, }, { tag: "isbn13", translation: "{0} phải là số ISBN-13", override: false, }, { tag: "issn", translation: "{0} phải là số ISSN", override: false, }, { tag: "uuid", translation: "{0} phải là giá trị UUID", override: false, }, { tag: "uuid3", translation: "{0} phải là giá trị UUID phiên bản 3", override: false, }, { tag: "uuid4", translation: "{0} phải là giá trị UUID phiên bản 4", override: false, }, { tag: "uuid5", translation: "{0} phải là giá trị UUID phiên bản 5", override: false, }, { tag: "ascii", translation: "{0} chỉ được chứa ký tự ASCII", override: false, }, { tag: "printascii", translation: "{0} chỉ được chứa ký tự ASCII có thể in ấn", override: false, }, { tag: "multibyte", translation: "{0} chỉ được chứa ký tự multibyte", override: false, }, { tag: "datauri", translation: "{0} chỉ được chứa Data URI", override: false, }, { tag: "latitude", translation: "{0} chỉ được chứa latitude (vỹ độ)", override: false, }, { tag: "longitude", translation: "{0} chỉ được chứa longitude (kinh độ)", override: false, }, { tag: "ssn", translation: "{0} phải là SSN number", override: false, }, { tag: "ipv4", translation: "{0} phải là địa chỉ IPv4", override: false, }, { tag: "ipv6", translation: "{0} phải là địa chỉ IPv6", override: false, }, { tag: "ip", translation: "{0} phải là địa chỉ IP", override: false, }, { tag: "cidr", translation: "{0} chỉ được chứa CIDR notation", override: false, }, { tag: "cidrv4", translation: "{0} chỉ được chứa CIDR notation của một địa chỉ IPv4", override: false, }, { tag: "cidrv6", translation: "{0} chỉ được chứa CIDR notation của một địa chỉ IPv6", override: false, }, { tag: "tcp_addr", translation: "{0} phải là địa chỉ TCP", override: false, }, { tag: "tcp4_addr", translation: "{0} phải là địa chỉ IPv4 TCP", override: false, }, { tag: "tcp6_addr", translation: "{0} phải là địa chỉ IPv6 TCP", override: false, }, { tag: "udp_addr", translation: "{0} phải là địa chỉ UDP", override: false, }, { tag: "udp4_addr", translation: "{0} phải là địa chỉ IPv4 UDP", override: false, }, { tag: "udp6_addr", translation: "{0} phải là địa chỉ IPv6 UDP", override: false, }, { tag: "ip_addr", translation: "{0} phải là địa chỉ IP có thể phân giải", override: false, }, { tag: "ip4_addr", translation: "{0} phải là địa chỉ IPv4 có thể phân giải", override: false, }, { tag: "ip6_addr", translation: "{0} phải là địa chỉ IPv6 có thể phân giải", override: false, }, { tag: "unix_addr", translation: "{0} phải là địa chỉ UNIX có thể phân giải", override: false, }, { tag: "mac", translation: "{0} chỉ được chứa địa chỉ MAC", override: false, }, { tag: "unique", translation: "{0} chỉ được chứa những giá trị không trùng lặp", override: false, }, { tag: "iscolor", translation: "{0} phải là màu sắc hợp lệ", override: false, }, { tag: "oneof", translation: "{0} phải là trong những giá trị [{1}]", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { s, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %#v", fe) return fe.(error).Error() } return s }, }, { tag: "json", translation: "{0} phải là một chuỗi json hợp lệ", override: false, }, { tag: "jwt", translation: "{0} phải là một chuỗi jwt hợp lệ", override: false, }, { tag: "lowercase", translation: "{0} phải được viết thường", override: false, }, { tag: "uppercase", translation: "{0} phải được viết hoa", override: false, }, { tag: "datetime", translation: "{0} không trùng định dạng ngày tháng {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "postcode_iso3166_alpha2", translation: "{0} sai định dạng postcode của quốc gia {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "postcode_iso3166_alpha2_field", translation: "{0} sai định dạng postcode của quốc gia tương ứng thuộc trường {1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "image", translation: "{0} phải là một hình ảnh hợp lệ", override: false, }, } for _, t := range translations { if t.customTransFunc != nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, t.customTransFunc) } else if t.customTransFunc != nil && t.customRegisFunc == nil { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), t.customTransFunc) } else if t.customTransFunc == nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, translateFunc) } else { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), translateFunc) } if err != nil { return } } return } func registrationFunc(tag string, translation string, override bool) validator.RegisterTranslationsFunc { return func(ut ut.Translator) (err error) { if err = ut.Add(tag, translation, override); err != nil { return } return } } func translateFunc(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field()) if err != nil { log.Printf("cảnh báo: lỗi chuyển ngữ FieldError: %#v", fe) return fe.(error).Error() } return t } golang-github-go-playground-validator-v10-10.30.1/translations/vi/vi_test.go000066400000000000000000000530421512410077000267230ustar00rootroot00000000000000package 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"` ISSN string `validate:"issn"` 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"` Image string `validate:"image"` } 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.ISSN", expected: "ISSN phải là số ISSN", }, { 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", }, { ns: "Test.Image", expected: "Image phải là một hình ảnh hợp lệ", }, } 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)) } } golang-github-go-playground-validator-v10-10.30.1/translations/zh/000077500000000000000000000000001512410077000247165ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/translations/zh/zh.go000066400000000000000000001043211512410077000256670ustar00rootroot00000000000000package zh import ( "fmt" "log" "reflect" "strconv" "strings" "time" "github.com/go-playground/locales" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" ) // RegisterDefaultTranslations registers a set of default translations // for all built in tag's in validator; you may add your own as desired. func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (err error) { translations := []struct { tag string translation string override bool customRegisFunc validator.RegisterTranslationsFunc customTransFunc validator.TranslationFunc }{ { tag: "required", translation: "{0}为必填字段", override: false, }, { tag: "required_if", translation: "{0}为必填字段", override: false, }, { tag: "required_unless", translation: "{0}为必填字段", override: false, }, { tag: "required_with", translation: "{0}为必填字段", override: false, }, { tag: "required_with_all", translation: "{0}为必填字段", override: false, }, { tag: "required_without", translation: "{0}为必填字段", override: false, }, { tag: "required_without_all", translation: "{0}为必填字段", override: false, }, { tag: "excluded_if", translation: "{0}为禁填字段", override: false, }, { tag: "excluded_unless", translation: "{0}为禁填字段", override: false, }, { tag: "excluded_with", translation: "{0}为禁填字段", override: false, }, { tag: "excluded_with_all", translation: "{0}为禁填字段", override: false, }, { tag: "excluded_without", translation: "{0}为禁填字段", override: false, }, { tag: "excluded_without_all", translation: "{0}为禁填字段", override: false, }, { tag: "isdefault", translation: "{0}为禁填字段", override: false, }, { tag: "len", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("len-string", "{0}长度必须是{1}", false); err != nil { return } //if err = ut.AddCardinal("len-string-character", "{0}字符", locales.PluralRuleOne, false); err != nil { // return //} if err = ut.AddCardinal("len-string-character", "{0}个字符", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("len-number", "{0}必须等于{1}", false); err != nil { return } if err = ut.Add("len-items", "{0}必须包含{1}", false); err != nil { return } //if err = ut.AddCardinal("len-items-item", "{0}项", locales.PluralRuleOne, false); err != nil { // return //} if err = ut.AddCardinal("len-items-item", "{0}项", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("len-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("len-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-items", fe.Field(), c) default: t, err = ut.T("len-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("警告: 翻译字段错误: %s", err) return fe.(error).Error() } return t }, }, { tag: "min", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("min-string", "{0}长度必须至少为{1}", false); err != nil { return } //if err = ut.AddCardinal("min-string-character", "{0}个字符", locales.PluralRuleOne, false); err != nil { // return //} if err = ut.AddCardinal("min-string-character", "{0}个字符", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("min-number", "{0}最小只能为{1}", false); err != nil { return } if err = ut.Add("min-items", "{0}必须至少包含{1}", false); err != nil { return } //if err = ut.AddCardinal("min-items-item", "{0}项", locales.PluralRuleOne, false); err != nil { // return //} if err = ut.AddCardinal("min-items-item", "{0}项", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("min-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("min-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-items", fe.Field(), c) default: t, err = ut.T("min-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("警告: 翻译字段错误: %s", err) return fe.(error).Error() } return t }, }, { tag: "max", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("max-string", "{0}长度不能超过{1}", false); err != nil { return } //if err = ut.AddCardinal("max-string-character", "{0}个字符", locales.PluralRuleOne, false); err != nil { // return //} if err = ut.AddCardinal("max-string-character", "{0}个字符", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("max-number", "{0}必须小于或等于{1}", false); err != nil { return } if err = ut.Add("max-items", "{0}最多只能包含{1}", false); err != nil { return } //if err = ut.AddCardinal("max-items-item", "{0}项", locales.PluralRuleOne, false); err != nil { // return //} if err = ut.AddCardinal("max-items-item", "{0}项", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("max-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("max-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-items", fe.Field(), c) default: t, err = ut.T("max-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("警告: 翻译字段错误: %s", err) return fe.(error).Error() } return t }, }, { tag: "eq", translation: "{0}不等于{1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("警告: 翻译字段错误: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ne", translation: "{0}不能等于{1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("警告: 翻译字段错误: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "lt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lt-string", "{0}长度必须小于{1}", false); err != nil { return } //if err = ut.AddCardinal("lt-string-character", "{0}个字符", locales.PluralRuleOne, false); err != nil { // return //} if err = ut.AddCardinal("lt-string-character", "{0}个字符", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-number", "{0}必须小于{1}", false); err != nil { return } if err = ut.Add("lt-items", "{0}必须包含少于{1}", false); err != nil { return } //if err = ut.AddCardinal("lt-items-item", "{0}项", locales.PluralRuleOne, false); err != nil { // return //} if err = ut.AddCardinal("lt-items-item", "{0}项", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-datetime", "{0}必须小于当前日期和时间", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s'不能用于struct类型.", fe.Tag()) } else { t, err = ut.T("lt-datetime", fe.Field()) } default: err = fn() if err != nil { goto END } t, err = ut.T("lt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("警告: 翻译字段错误: %s", err) return fe.(error).Error() } return t }, }, { tag: "lte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lte-string", "{0}长度不能超过{1}", false); err != nil { return } //if err = ut.AddCardinal("lte-string-character", "{0} character", locales.PluralRuleOne, false); err != nil { // return //} if err = ut.AddCardinal("lte-string-character", "{0}个字符", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-number", "{0}必须小于或等于{1}", false); err != nil { return } if err = ut.Add("lte-items", "{0}最多只能包含{1}", false); err != nil { return } //if err = ut.AddCardinal("lte-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { // return //} if err = ut.AddCardinal("lte-items-item", "{0}项", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-datetime", "{0}必须小于或等于当前日期和时间", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s'不能用于struct类型.", fe.Tag()) } else { t, err = ut.T("lte-datetime", fe.Field()) } default: err = fn() if err != nil { goto END } t, err = ut.T("lte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("警告: 翻译字段错误: %s", err) return fe.(error).Error() } return t }, }, { tag: "gt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gt-string", "{0}长度必须大于{1}", false); err != nil { return } //if err = ut.AddCardinal("gt-string-character", "{0}个字符", locales.PluralRuleOne, false); err != nil { // return //} if err = ut.AddCardinal("gt-string-character", "{0}个字符", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-number", "{0}必须大于{1}", false); err != nil { return } if err = ut.Add("gt-items", "{0}必须大于{1}", false); err != nil { return } //if err = ut.AddCardinal("gt-items-item", "{0}项", locales.PluralRuleOne, false); err != nil { // return //} if err = ut.AddCardinal("gt-items-item", "{0}项", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-datetime", "{0}必须大于当前日期和时间", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s'不能用于struct类型.", fe.Tag()) } else { t, err = ut.T("gt-datetime", fe.Field()) } default: err = fn() if err != nil { goto END } t, err = ut.T("gt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("警告: 翻译字段错误: %s", err) return fe.(error).Error() } return t }, }, { tag: "gte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gte-string", "{0}长度必须至少为{1}", false); err != nil { return } //if err = ut.AddCardinal("gte-string-character", "{0}个字符", locales.PluralRuleOne, false); err != nil { // return //} if err = ut.AddCardinal("gte-string-character", "{0}个字符", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-number", "{0}必须大于或等于{1}", false); err != nil { return } if err = ut.Add("gte-items", "{0}必须至少包含{1}", false); err != nil { return } //if err = ut.AddCardinal("gte-items-item", "{0}项", locales.PluralRuleOne, false); err != nil { // return //} if err = ut.AddCardinal("gte-items-item", "{0}项", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-datetime", "{0}必须大于或等于当前日期和时间", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s'不能用于struct类型.", fe.Tag()) } else { t, err = ut.T("gte-datetime", fe.Field()) } default: err = fn() if err != nil { goto END } t, err = ut.T("gte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("警告: 翻译字段错误: %s", err) return fe.(error).Error() } return t }, }, { tag: "eqfield", translation: "{0}必须等于{1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻译字段错误: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "eqcsfield", translation: "{0}必须等于{1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻译字段错误: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "necsfield", translation: "{0}不能等于{1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻译字段错误: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtcsfield", translation: "{0}必须大于{1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻译字段错误: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtecsfield", translation: "{0}必须大于或等于{1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻译字段错误: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltcsfield", translation: "{0}必须小于{1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻译字段错误: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltecsfield", translation: "{0}必须小于或等于{1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻译字段错误: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "nefield", translation: "{0}不能等于{1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻译字段错误: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtfield", translation: "{0}必须大于{1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻译字段错误: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtefield", translation: "{0}必须大于或等于{1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻译字段错误: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltfield", translation: "{0}必须小于{1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻译字段错误: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltefield", translation: "{0}必须小于或等于{1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻译字段错误: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "alpha", translation: "{0}只能包含字母", override: false, }, { tag: "alphanum", translation: "{0}只能包含字母和数字", override: false, }, { tag: "alphanumunicode", translation: "{0}只能包含字母数字和Unicode字符", override: false, }, { tag: "alphaunicode", translation: "{0}只能包含字母和Unicode字符", override: false, }, { tag: "numeric", translation: "{0}必须是一个有效的数值", override: false, }, { tag: "number", translation: "{0}必须是一个有效的数字", override: false, }, { tag: "hexadecimal", translation: "{0}必须是一个有效的十六进制", override: false, }, { tag: "hexcolor", translation: "{0}必须是一个有效的十六进制颜色", override: false, }, { tag: "rgb", translation: "{0}必须是一个有效的RGB颜色", override: false, }, { tag: "rgba", translation: "{0}必须是一个有效的RGBA颜色", override: false, }, { tag: "hsl", translation: "{0}必须是一个有效的HSL颜色", override: false, }, { tag: "hsla", translation: "{0}必须是一个有效的HSLA颜色", override: false, }, { tag: "email", translation: "{0}必须是一个有效的邮箱", override: false, }, { tag: "url", translation: "{0}必须是一个有效的URL", override: false, }, { tag: "uri", translation: "{0}必须是一个有效的URI", override: false, }, { tag: "base64", translation: "{0}必须是一个有效的Base64字符串", override: false, }, { tag: "contains", translation: "{0}必须包含文本'{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻译字段错误: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "containsany", translation: "{0}必须包含至少一个以下字符'{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻译字段错误: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "containsrune", translation: "{0}必须包含字符'{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻译字段错误: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludes", translation: "{0}不能包含文本'{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻译字段错误: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesall", translation: "{0}不能包含以下任何字符'{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻译字段错误: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesrune", translation: "{0}不能包含'{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻译字段错误: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "endswith", translation: "{0}必须以文本'{1}'结尾", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻译字段错误: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "startswith", translation: "{0}必须以文本'{1}'开头", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻译字段错误: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "isbn", translation: "{0}必须是一个有效的ISBN编号", override: false, }, { tag: "isbn10", translation: "{0}必须是一个有效的ISBN-10编号", override: false, }, { tag: "isbn13", translation: "{0}必须是一个有效的ISBN-13编号", override: false, }, { tag: "issn", translation: "{0}必须是一个有效的ISSN编号", override: false, }, { tag: "uuid", translation: "{0}必须是一个有效的UUID", override: false, }, { tag: "uuid3", translation: "{0}必须是一个有效的V3 UUID", override: false, }, { tag: "uuid4", translation: "{0}必须是一个有效的V4 UUID", override: false, }, { tag: "uuid5", translation: "{0}必须是一个有效的V5 UUID", override: false, }, { tag: "ulid", translation: "{0}必须是一个有效的ULID", override: false, }, { tag: "ascii", translation: "{0}必须只包含ascii字符", override: false, }, { tag: "printascii", translation: "{0}必须只包含可打印的ascii字符", override: false, }, { tag: "multibyte", translation: "{0}必须包含多字节字符", override: false, }, { tag: "datauri", translation: "{0}必须包含有效的数据URI", override: false, }, { tag: "latitude", translation: "{0}必须包含有效的纬度坐标", override: false, }, { tag: "longitude", translation: "{0}必须包含有效的经度坐标", override: false, }, { tag: "ssn", translation: "{0}必须是一个有效的社会安全号码(SSN)", override: false, }, { tag: "ipv4", translation: "{0}必须是一个有效的IPv4地址", override: false, }, { tag: "ipv6", translation: "{0}必须是一个有效的IPv6地址", override: false, }, { tag: "ip", translation: "{0}必须是一个有效的IP地址", override: false, }, { tag: "cidr", translation: "{0}必须是一个有效的无类别域间路由(CIDR)", override: false, }, { tag: "cidrv4", translation: "{0}必须是一个包含IPv4地址的有效无类别域间路由(CIDR)", override: false, }, { tag: "cidrv6", translation: "{0}必须是一个包含IPv6地址的有效无类别域间路由(CIDR)", override: false, }, { tag: "tcp_addr", translation: "{0}必须是一个有效的TCP地址", override: false, }, { tag: "tcp4_addr", translation: "{0}必须是一个有效的IPv4 TCP地址", override: false, }, { tag: "tcp6_addr", translation: "{0}必须是一个有效的IPv6 TCP地址", override: false, }, { tag: "udp_addr", translation: "{0}必须是一个有效的UDP地址", override: false, }, { tag: "udp4_addr", translation: "{0}必须是一个有效的IPv4 UDP地址", override: false, }, { tag: "udp6_addr", translation: "{0}必须是一个有效的IPv6 UDP地址", override: false, }, { tag: "ip_addr", translation: "{0}必须是一个有效的IP地址", override: false, }, { tag: "ip4_addr", translation: "{0}必须是一个有效的IPv4地址", override: false, }, { tag: "ip6_addr", translation: "{0}必须是一个有效的IPv6地址", override: false, }, { tag: "unix_addr", translation: "{0}必须是一个有效的UNIX地址", override: false, }, { tag: "mac", translation: "{0}必须是一个有效的MAC地址", override: false, }, { tag: "iscolor", translation: "{0}必须是一个有效的颜色", override: false, }, { tag: "oneof", translation: "{0}必须是[{1}]中的一个", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { s, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻译字段错误: %#v", fe) return fe.(error).Error() } return s }, }, { tag: "json", translation: "{0}必须是一个JSON字符串", override: false, }, { tag: "lowercase", translation: "{0}必须是小写字母", override: false, }, { tag: "uppercase", translation: "{0}必须是大写字母", override: false, }, { tag: "datetime", translation: "{0}的格式必须是{1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻译字段错误: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "image", translation: "{0} 必须是有效图像", override: false, }, } for _, t := range translations { if t.customTransFunc != nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, t.customTransFunc) } else if t.customTransFunc != nil && t.customRegisFunc == nil { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), t.customTransFunc) } else if t.customTransFunc == nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, translateFunc) } else { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), translateFunc) } if err != nil { return } } return } func registrationFunc(tag string, translation string, override bool) validator.RegisterTranslationsFunc { return func(ut ut.Translator) (err error) { if err = ut.Add(tag, translation, override); err != nil { return } return } } func translateFunc(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field()) if err != nil { log.Printf("警告: 翻译字段错误: %#v", fe) return fe.(error).Error() } return t } golang-github-go-playground-validator-v10-10.30.1/translations/zh/zh_test.go000066400000000000000000000555351512410077000267420ustar00rootroot00000000000000package 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 RequiredIf string RequiredUnless string RequiredWith string RequiredWithAll string RequiredWithout string RequiredWithoutAll string ExcludedIf string ExcludedUnless string ExcludedWith string ExcludedWithAll string ExcludedWithout string ExcludedWithoutAll 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"` RequiredUnless string `validate:"required_unless=Inner.RequiredUnless abcd"` RequiredWith string `validate:"required_with=Inner.RequiredWith"` RequiredWithAll string `validate:"required_with_all=Inner.RequiredWith Inner.RequiredWithAll"` RequiredWithout string `validate:"required_without=Inner.RequiredWithout"` RequiredWithoutAll string `validate:"required_without_all=Inner.RequiredWithout Inner.RequiredWithoutAll"` ExcludedIf string `validate:"excluded_if=Inner.ExcludedIf abcd"` ExcludedUnless string `validate:"excluded_unless=Inner.ExcludedUnless abcd"` ExcludedWith string `validate:"excluded_with=Inner.ExcludedWith"` ExcludedWithout string `validate:"excluded_with_all=Inner.ExcludedWithAll"` ExcludedWithAll string `validate:"excluded_without=Inner.ExcludedWithout"` ExcludedWithoutAll string `validate:"excluded_without_all=Inner.ExcludedWithoutAll"` IsDefault string `validate:"isdefault"` 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"` ISSN string `validate:"issn"` 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"` Image string `validate:"image"` } var test Test test.Inner.EqCSFieldString = "1234" test.Inner.GtCSFieldString = "1234" test.Inner.GteCSFieldString = "1234" test.Inner.RequiredIf = "abcd" test.Inner.RequiredUnless = "1234" test.Inner.RequiredWith = "1234" test.Inner.RequiredWithAll = "1234" test.Inner.ExcludedIf = "abcd" test.Inner.ExcludedUnless = "1234" test.Inner.ExcludedWith = "1234" test.Inner.ExcludedWithAll = "1234" test.ExcludedIf = "1234" test.ExcludedUnless = "1234" test.ExcludedWith = "1234" test.ExcludedWithAll = "1234" test.ExcludedWithout = "1234" test.ExcludedWithoutAll = "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.ISSN", expected: "ISSN必须是一个有效的ISSN编号", }, { 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.RequiredUnless", expected: "RequiredUnless为必填字段", }, { ns: "Test.RequiredWith", expected: "RequiredWith为必填字段", }, { ns: "Test.RequiredWithAll", expected: "RequiredWithAll为必填字段", }, { ns: "Test.RequiredWithout", expected: "RequiredWithout为必填字段", }, { ns: "Test.RequiredWithoutAll", expected: "RequiredWithoutAll为必填字段", }, { ns: "Test.ExcludedIf", expected: "ExcludedIf为禁填字段", }, { ns: "Test.ExcludedUnless", expected: "ExcludedUnless为禁填字段", }, { ns: "Test.ExcludedWith", expected: "ExcludedWith为禁填字段", }, { ns: "Test.ExcludedWithAll", expected: "ExcludedWithAll为禁填字段", }, { ns: "Test.ExcludedWithout", expected: "ExcludedWithout为禁填字段", }, { ns: "Test.ExcludedWithoutAll", expected: "ExcludedWithoutAll为禁填字段", }, { 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", }, { ns: "Test.Image", expected: "Image 必须是有效图像", }, } 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)) } } golang-github-go-playground-validator-v10-10.30.1/translations/zh_tw/000077500000000000000000000000001512410077000254305ustar00rootroot00000000000000golang-github-go-playground-validator-v10-10.30.1/translations/zh_tw/zh_tw.go000066400000000000000000001010731512410077000271140ustar00rootroot00000000000000package zh_tw import ( "fmt" "log" "reflect" "strconv" "strings" "time" "github.com/go-playground/locales" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" ) // RegisterDefaultTranslations registers a set of default translations // for all built in tag's in validator; you may add your own as desired. func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (err error) { translations := []struct { tag string translation string override bool customRegisFunc validator.RegisterTranslationsFunc customTransFunc validator.TranslationFunc }{ { tag: "required", translation: "{0}為必填欄位", override: false, }, { tag: "required_if", translation: "{0}為必填欄位", override: false, }, { tag: "required_unless", translation: "{0}為必填欄位", override: false, }, { tag: "required_with", translation: "{0}為必填欄位", override: false, }, { tag: "required_with_all", translation: "{0}為必填欄位", override: false, }, { tag: "required_without", translation: "{0}為必填欄位", override: false, }, { tag: "required_without_all", translation: "{0}為必填欄位", override: false, }, { tag: "excluded_if", translation: "{0}為禁填欄位", override: false, }, { tag: "excluded_unless", translation: "{0}為禁填欄位", override: false, }, { tag: "excluded_with", translation: "{0}為禁填欄位", override: false, }, { tag: "excluded_with_all", translation: "{0}為禁填欄位", override: false, }, { tag: "excluded_without", translation: "{0}為禁填欄位", override: false, }, { tag: "excluded_without_all", translation: "{0}為禁填欄位", override: false, }, { tag: "isdefault", translation: "{0}為禁填欄位", override: false, }, { tag: "len", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("len-string", "{0}長度必須為{1}", false); err != nil { return } //if err = ut.AddCardinal("len-string-character", "{0}字元", locales.PluralRuleOne, false); err != nil { // return //} if err = ut.AddCardinal("len-string-character", "{0}個字元", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("len-number", "{0}必須等於{1}", false); err != nil { return } if err = ut.Add("len-items", "{0}必須包含{1}", false); err != nil { return } //if err = ut.AddCardinal("len-items-item", "{0}項", locales.PluralRuleOne, false); err != nil { // return //} if err = ut.AddCardinal("len-items-item", "{0}項", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("len-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("len-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("len-items", fe.Field(), c) default: t, err = ut.T("len-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("警告: 翻譯欄位錯誤: %s", err) return fe.(error).Error() } return t }, }, { tag: "min", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("min-string", "{0}長度必須至少為{1}", false); err != nil { return } //if err = ut.AddCardinal("min-string-character", "{0}個字元", locales.PluralRuleOne, false); err != nil { // return //} if err = ut.AddCardinal("min-string-character", "{0}個字元", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("min-number", "{0}最小只能為{1}", false); err != nil { return } if err = ut.Add("min-items", "{0}必須至少包含{1}", false); err != nil { return } //if err = ut.AddCardinal("min-items-item", "{0}項", locales.PluralRuleOne, false); err != nil { // return //} if err = ut.AddCardinal("min-items-item", "{0}項", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("min-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("min-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("min-items", fe.Field(), c) default: t, err = ut.T("min-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("警告: 翻譯欄位錯誤: %s", err) return fe.(error).Error() } return t }, }, { tag: "max", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("max-string", "{0}長度不能超過{1}", false); err != nil { return } //if err = ut.AddCardinal("max-string-character", "{0}個字元", locales.PluralRuleOne, false); err != nil { // return //} if err = ut.AddCardinal("max-string-character", "{0}個字元", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("max-number", "{0}必須小於或等於{1}", false); err != nil { return } if err = ut.Add("max-items", "{0}最多只能包含{1}", false); err != nil { return } //if err = ut.AddCardinal("max-items-item", "{0}項", locales.PluralRuleOne, false); err != nil { // return //} if err = ut.AddCardinal("max-items-item", "{0}項", locales.PluralRuleOther, false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var digits uint64 var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err := strconv.ParseFloat(fe.Param(), 64) if err != nil { goto END } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string c, err = ut.C("max-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string c, err = ut.C("max-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("max-items", fe.Field(), c) default: t, err = ut.T("max-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("警告: 翻譯欄位錯誤: %s", err) return fe.(error).Error() } return t }, }, { tag: "eq", translation: "{0}不等於{1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("警告: 翻譯欄位錯誤: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ne", translation: "{0}不能等於{1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { fmt.Printf("警告: 翻譯欄位錯誤: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "lt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lt-string", "{0}長度必須小於{1}", false); err != nil { return } //if err = ut.AddCardinal("lt-string-character", "{0}個字元", locales.PluralRuleOne, false); err != nil { // return //} if err = ut.AddCardinal("lt-string-character", "{0}個字元", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-number", "{0}必須小於{1}", false); err != nil { return } if err = ut.Add("lt-items", "{0}必須包含少於{1}", false); err != nil { return } //if err = ut.AddCardinal("lt-items-item", "{0}項", locales.PluralRuleOne, false); err != nil { // return //} if err = ut.AddCardinal("lt-items-item", "{0}項", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lt-datetime", "{0}必須小於目前日期和時間", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s'不能用於struct類型.", fe.Tag()) } else { t, err = ut.T("lt-datetime", fe.Field()) } default: err = fn() if err != nil { goto END } t, err = ut.T("lt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("警告: 翻譯欄位錯誤: %s", err) return fe.(error).Error() } return t }, }, { tag: "lte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("lte-string", "{0}長度不能超過{1}", false); err != nil { return } //if err = ut.AddCardinal("lte-string-character", "{0} character", locales.PluralRuleOne, false); err != nil { // return //} if err = ut.AddCardinal("lte-string-character", "{0}個字元", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-number", "{0}必須小於或等於{1}", false); err != nil { return } if err = ut.Add("lte-items", "{0}最多只能包含{1}", false); err != nil { return } //if err = ut.AddCardinal("lte-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { // return //} if err = ut.AddCardinal("lte-items-item", "{0}項", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("lte-datetime", "{0}必須小於或等於目前日期和時間", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("lte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("lte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s'不能用於struct類型.", fe.Tag()) } else { t, err = ut.T("lte-datetime", fe.Field()) } default: err = fn() if err != nil { goto END } t, err = ut.T("lte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("警告: 翻譯欄位錯誤: %s", err) return fe.(error).Error() } return t }, }, { tag: "gt", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gt-string", "{0}長度必須大於{1}", false); err != nil { return } //if err = ut.AddCardinal("gt-string-character", "{0}個字元", locales.PluralRuleOne, false); err != nil { // return //} if err = ut.AddCardinal("gt-string-character", "{0}個字元", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-number", "{0}必須大於{1}", false); err != nil { return } if err = ut.Add("gt-items", "{0}必須大於{1}", false); err != nil { return } //if err = ut.AddCardinal("gt-items-item", "{0}項", locales.PluralRuleOne, false); err != nil { // return //} if err = ut.AddCardinal("gt-items-item", "{0}項", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gt-datetime", "{0}必須大於目前日期和時間", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gt-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gt-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s'不能用於struct類型.", fe.Tag()) } else { t, err = ut.T("gt-datetime", fe.Field()) } default: err = fn() if err != nil { goto END } t, err = ut.T("gt-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("警告: 翻譯欄位錯誤: %s", err) return fe.(error).Error() } return t }, }, { tag: "gte", customRegisFunc: func(ut ut.Translator) (err error) { if err = ut.Add("gte-string", "{0}長度必須至少為{1}", false); err != nil { return } //if err = ut.AddCardinal("gte-string-character", "{0}個字元", locales.PluralRuleOne, false); err != nil { // return //} if err = ut.AddCardinal("gte-string-character", "{0}個字元", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-number", "{0}必須大於或等於{1}", false); err != nil { return } if err = ut.Add("gte-items", "{0}必須至少包含{1}", false); err != nil { return } //if err = ut.AddCardinal("gte-items-item", "{0}項", locales.PluralRuleOne, false); err != nil { // return //} if err = ut.AddCardinal("gte-items-item", "{0}項", locales.PluralRuleOther, false); err != nil { return } if err = ut.Add("gte-datetime", "{0}必須大於或等於目前日期和時間", false); err != nil { return } return }, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { var err error var t string var f64 float64 var digits uint64 var kind reflect.Kind fn := func() (err error) { if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) } f64, err = strconv.ParseFloat(fe.Param(), 64) return } kind = fe.Kind() if kind == reflect.Ptr { kind = fe.Type().Elem().Kind() } switch kind { case reflect.String: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-string-character", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-string", fe.Field(), c) case reflect.Slice, reflect.Map, reflect.Array: var c string err = fn() if err != nil { goto END } c, err = ut.C("gte-items-item", f64, digits, ut.FmtNumber(f64, digits)) if err != nil { goto END } t, err = ut.T("gte-items", fe.Field(), c) case reflect.Struct: if fe.Type() != reflect.TypeOf(time.Time{}) { err = fmt.Errorf("tag '%s'不能用於struct類型.", fe.Tag()) } else { t, err = ut.T("gte-datetime", fe.Field()) } default: err = fn() if err != nil { goto END } t, err = ut.T("gte-number", fe.Field(), ut.FmtNumber(f64, digits)) } END: if err != nil { fmt.Printf("警告: 翻譯欄位錯誤: %s", err) return fe.(error).Error() } return t }, }, { tag: "eqfield", translation: "{0}必須等於{1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻譯欄位錯誤: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "eqcsfield", translation: "{0}必須等於{1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻譯欄位錯誤: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "necsfield", translation: "{0}不能等於{1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻譯欄位錯誤: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtcsfield", translation: "{0}必須大於{1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻譯欄位錯誤: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtecsfield", translation: "{0}必須大於或等於{1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻譯欄位錯誤: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltcsfield", translation: "{0}必須小於{1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻譯欄位錯誤: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltecsfield", translation: "{0}必須小於或等於{1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻譯欄位錯誤: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "nefield", translation: "{0}不能等於{1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻譯欄位錯誤: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtfield", translation: "{0}必須大於{1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻譯欄位錯誤: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "gtefield", translation: "{0}必須大於或等於{1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻譯欄位錯誤: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltfield", translation: "{0}必須小於{1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻譯欄位錯誤: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "ltefield", translation: "{0}必須小於或等於{1}", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻譯欄位錯誤: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "alpha", translation: "{0}只能包含字母", override: false, }, { tag: "alphanum", translation: "{0}只能包含字母和數字", override: false, }, { tag: "numeric", translation: "{0}必須是一個有效的數值", override: false, }, { tag: "number", translation: "{0}必須是一個有效的數字", override: false, }, { tag: "hexadecimal", translation: "{0}必須是一個有效的十六進制", override: false, }, { tag: "hexcolor", translation: "{0}必須是一個有效的十六進制顏色", override: false, }, { tag: "rgb", translation: "{0}必須是一個有效的RGB顏色", override: false, }, { tag: "rgba", translation: "{0}必須是一個有效的RGBA顏色", override: false, }, { tag: "hsl", translation: "{0}必須是一個有效的HSL顏色", override: false, }, { tag: "hsla", translation: "{0}必須是一個有效的HSLA顏色", override: false, }, { tag: "email", translation: "{0}必須是一個有效的信箱", override: false, }, { tag: "url", translation: "{0}必須是一個有效的URL", override: false, }, { tag: "uri", translation: "{0}必須是一個有效的URI", override: false, }, { tag: "base64", translation: "{0}必須是一個有效的Base64字元串", override: false, }, { tag: "contains", translation: "{0}必須包含文字'{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻譯欄位錯誤: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "containsany", translation: "{0}必須包含至少一個以下字元'{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻譯欄位錯誤: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludes", translation: "{0}不能包含文字'{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻譯欄位錯誤: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesall", translation: "{0}不能包含以下任何字元'{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻譯欄位錯誤: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "excludesrune", translation: "{0}不能包含'{1}'", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻譯欄位錯誤: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "isbn", translation: "{0}必須是一個有效的ISBN編號", override: false, }, { tag: "isbn10", translation: "{0}必須是一個有效的ISBN-10編號", override: false, }, { tag: "isbn13", translation: "{0}必須是一個有效的ISBN-13編號", override: false, }, { tag: "issn", translation: "{0}必須是一個有效的ISSN編號", override: false, }, { tag: "uuid", translation: "{0}必須是一個有效的UUID", override: false, }, { tag: "uuid3", translation: "{0}必須是一個有效的V3 UUID", override: false, }, { tag: "uuid4", translation: "{0}必須是一個有效的V4 UUID", override: false, }, { tag: "uuid5", translation: "{0}必須是一個有效的V5 UUID", override: false, }, { tag: "ulid", translation: "{0}必須是一個有效的ULID", override: false, }, { tag: "ascii", translation: "{0}必須只包含ascii字元", override: false, }, { tag: "printascii", translation: "{0}必須只包含可輸出的ascii字元", override: false, }, { tag: "multibyte", translation: "{0}必須包含多個字元", override: false, }, { tag: "datauri", translation: "{0}必須包含有效的數據URI", override: false, }, { tag: "latitude", translation: "{0}必須包含有效的緯度座標", override: false, }, { tag: "longitude", translation: "{0}必須包含有效的經度座標", override: false, }, { tag: "ssn", translation: "{0}必須是一個有效的社會安全編號(SSN)", override: false, }, { tag: "ipv4", translation: "{0}必須是一個有效的IPv4地址", override: false, }, { tag: "ipv6", translation: "{0}必須是一個有效的IPv6地址", override: false, }, { tag: "ip", translation: "{0}必須是一個有效的IP地址", override: false, }, { tag: "cidr", translation: "{0}必須是一個有效的無類別域間路由(CIDR)", override: false, }, { tag: "cidrv4", translation: "{0}必須是一个包含IPv4地址的有效無類別域間路由(CIDR)", override: false, }, { tag: "cidrv6", translation: "{0}必須是一个包含IPv6地址的有效無類別域間路由(CIDR)", override: false, }, { tag: "tcp_addr", translation: "{0}必須是一個有效的TCP地址", override: false, }, { tag: "tcp4_addr", translation: "{0}必須是一個有效的IPv4 TCP地址", override: false, }, { tag: "tcp6_addr", translation: "{0}必須是一個有效的IPv6 TCP地址", override: false, }, { tag: "udp_addr", translation: "{0}必須是一個有效的UDP地址", override: false, }, { tag: "udp4_addr", translation: "{0}必須是一個有效的IPv4 UDP地址", override: false, }, { tag: "udp6_addr", translation: "{0}必須是一個有效的IPv6 UDP地址", override: false, }, { tag: "ip_addr", translation: "{0}必須是一個有效的IP地址", override: false, }, { tag: "ip4_addr", translation: "{0}必須是一個有效的IPv4地址", override: false, }, { tag: "ip6_addr", translation: "{0}必須是一個有效的IPv6地址", override: false, }, { tag: "unix_addr", translation: "{0}必須是一個有效的UNIX地址", override: false, }, { tag: "mac", translation: "{0}必須是一個有效的MAC地址", override: false, }, { tag: "iscolor", translation: "{0}必須是一個有效的顏色", override: false, }, { tag: "oneof", translation: "{0}必須是[{1}]中的一個", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { s, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻譯欄位錯誤: %#v", fe) return fe.(error).Error() } return s }, }, { tag: "datetime", translation: "{0}與{1}格式不匹配", override: false, customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) if err != nil { log.Printf("警告: 翻譯欄位錯誤: %#v", fe) return fe.(error).Error() } return t }, }, { tag: "image", translation: "{0} 必須是有效圖像", override: false, }, } for _, t := range translations { if t.customTransFunc != nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, t.customTransFunc) } else if t.customTransFunc != nil && t.customRegisFunc == nil { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), t.customTransFunc) } else if t.customTransFunc == nil && t.customRegisFunc != nil { err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, translateFunc) } else { err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), translateFunc) } if err != nil { return } } return } func registrationFunc(tag string, translation string, override bool) validator.RegisterTranslationsFunc { return func(ut ut.Translator) (err error) { if err = ut.Add(tag, translation, override); err != nil { return } return } } func translateFunc(ut ut.Translator, fe validator.FieldError) string { t, err := ut.T(fe.Tag(), fe.Field()) if err != nil { log.Printf("警告: 翻譯欄位錯誤: %#v", fe) return fe.(error).Error() } return t } golang-github-go-playground-validator-v10-10.30.1/translations/zh_tw/zh_tw_test.go000066400000000000000000000517151512410077000301620ustar00rootroot00000000000000package 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 RequiredIf string RequiredUnless string RequiredWith string RequiredWithAll string RequiredWithout string RequiredWithoutAll string ExcludedIf string ExcludedUnless string ExcludedWith string ExcludedWithAll string ExcludedWithout string ExcludedWithoutAll 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"` RequiredUnless string `validate:"required_unless=Inner.RequiredUnless abcd"` RequiredWith string `validate:"required_with=Inner.RequiredWith"` RequiredWithAll string `validate:"required_with_all=Inner.RequiredWith Inner.RequiredWithAll"` RequiredWithout string `validate:"required_without=Inner.RequiredWithout"` RequiredWithoutAll string `validate:"required_without_all=Inner.RequiredWithout Inner.RequiredWithoutAll"` ExcludedIf string `validate:"excluded_if=Inner.ExcludedIf abcd"` ExcludedUnless string `validate:"excluded_unless=Inner.ExcludedUnless abcd"` ExcludedWith string `validate:"excluded_with=Inner.ExcludedWith"` ExcludedWithout string `validate:"excluded_with_all=Inner.ExcludedWithAll"` ExcludedWithAll string `validate:"excluded_without=Inner.ExcludedWithout"` ExcludedWithoutAll string `validate:"excluded_without_all=Inner.ExcludedWithoutAll"` IsDefault string `validate:"isdefault"` 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"` ISSN string `validate:"issn"` 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"` Image string `validate:"image"` } var test Test test.Inner.EqCSFieldString = "1234" test.Inner.GtCSFieldString = "1234" test.Inner.GteCSFieldString = "1234" test.Inner.RequiredIf = "abcd" test.Inner.RequiredUnless = "1234" test.Inner.RequiredWith = "1234" test.Inner.RequiredWithAll = "1234" test.Inner.ExcludedIf = "abcd" test.Inner.ExcludedUnless = "1234" test.Inner.ExcludedWith = "1234" test.Inner.ExcludedWithAll = "1234" test.ExcludedIf = "1234" test.ExcludedUnless = "1234" test.ExcludedWith = "1234" test.ExcludedWithAll = "1234" test.ExcludedWithout = "1234" test.ExcludedWithoutAll = "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.ISSN", expected: "ISSN必須是一個有效的ISSN編號", }, { 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.RequiredUnless", expected: "RequiredUnless為必填欄位", }, { ns: "Test.RequiredWith", expected: "RequiredWith為必填欄位", }, { ns: "Test.RequiredWithAll", expected: "RequiredWithAll為必填欄位", }, { ns: "Test.RequiredWithout", expected: "RequiredWithout為必填欄位", }, { ns: "Test.RequiredWithoutAll", expected: "RequiredWithoutAll為必填欄位", }, { ns: "Test.ExcludedIf", expected: "ExcludedIf為禁填欄位", }, { ns: "Test.ExcludedUnless", expected: "ExcludedUnless為禁填欄位", }, { ns: "Test.ExcludedWith", expected: "ExcludedWith為禁填欄位", }, { ns: "Test.ExcludedWithAll", expected: "ExcludedWithAll為禁填欄位", }, { ns: "Test.ExcludedWithout", expected: "ExcludedWithout為禁填欄位", }, { ns: "Test.ExcludedWithoutAll", expected: "ExcludedWithoutAll為禁填欄位", }, { 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格式不匹配", }, { ns: "Test.Image", expected: "Image 必須是有效圖像", }, } 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)) } } golang-github-go-playground-validator-v10-10.30.1/util.go000066400000000000000000000164321512410077000230660ustar00rootroot00000000000000package validator import ( "fmt" "reflect" "regexp" "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 // return found=false instead of panicking to handle cases like ValidateMap // where cross-field validators (required_if, etc.) can't navigate non-struct parents return } // asInt returns the parameter as an 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 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 } // asFloat64 returns the parameter as a float64 // or panics if it can't convert func asFloat64(param string) float64 { i, err := strconv.ParseFloat(param, 64) panicIf(err) return i } // asFloat32 returns the parameter as a float32 // or panics if it can't convert func asFloat32(param string) float64 { i, err := strconv.ParseFloat(param, 32) 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()) } } // Checks if field value matches regex. If fl.Field can be cast to Stringer, it uses the Stringer interfaces // String() return value. Otherwise, it uses fl.Field's String() value. func fieldMatchesRegexByStringerValOrString(regexFn func() *regexp.Regexp, fl FieldLevel) bool { regex := regexFn() switch fl.Field().Kind() { case reflect.String: return regex.MatchString(fl.Field().String()) default: if stringer, ok := getValue(fl.Field()).(fmt.Stringer); ok { return regex.MatchString(stringer.String()) } else { return regex.MatchString(fl.Field().String()) } } } golang-github-go-playground-validator-v10-10.30.1/validator.go000066400000000000000000000317741512410077000241040ustar00rootroot00000000000000package validator import ( "context" "fmt" "reflect" "strconv" "unsafe" ) // 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 } // 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) { cs, ok := v.v.structCache.Get(typ) if !ok { cs = v.v.extractStructCache(current, typ.Name()) } if len(ns) == 0 && len(cs.name) != 0 { ns = append(ns, cs.name...) ns = append(ns, '.') structNs = append(structNs, cs.name...) structNs = append(structNs, '.') } // 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 { var f *cField for i := 0; i < len(cs.fields); i++ { f = cs.fields[i] if v.isPartial { if v.ffn != nil { // used with StructFiltered if v.ffn(append(structNs, f.name...)) { continue } } else { // used with StructPartial & StructExcept _, ok = v.includeExclude[string(append(structNs, f.name...))] if (ok && v.hasExcludes) || (!ok && !v.hasExcludes) { continue } } } v.traverseField(ctx, current, current.Field(f.idx), ns, structNs, f, f.cTags) } } // 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 { v.slflParent = parent v.slCurrent = current v.ns = ns v.actualNs = structNs cs.fn(ctx, v) } } // 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 current, kind, v.fldIsPointer = v.extractTypeInternal(current, false) var isNestedStruct bool switch kind { case reflect.Ptr, reflect.Interface, reflect.Invalid: if ct == nil { return } if ct.typeof == typeOmitEmpty || ct.typeof == typeIsDefault { return } if ct.typeof == typeOmitNil && (kind != reflect.Invalid && current.IsNil()) { return } if ct.typeof == typeOmitZero { return } 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 } 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: getValue(current), param: ct.param, kind: kind, typ: current.Type(), }, ) return } } if kind == reflect.Invalid { return } case reflect.Struct: isNestedStruct = !current.Type().ConvertibleTo(timeType) // For backward compatibility before struct level validation tags were supported // as there were a number of projects relying on `required` not failing on non-pointer // structs. Since it's basically nonsensical to use `required` with a non-pointer struct // are explicitly skipping the required validation for it. This WILL be removed in the // next major version. if isNestedStruct && !v.v.requiredStructEnabled && ct != nil && ct.tag == requiredTag { ct = ct.next } } typ = current.Type() OUTER: for { if ct == nil || !ct.hasTag || (isNestedStruct && len(cf.name) == 0) { // isNestedStruct check here if isNestedStruct { // 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...), '.') } v.validateStruct(ctx, parent, current, typ, ns, structNs, ct) } return } switch ct.typeof { case typeNoStructLevel: return case typeStructOnly: if isNestedStruct { // 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...), '.') } v.validateStruct(ctx, parent, current, typ, ns, structNs, ct) } return case typeOmitEmpty: // set Field Level fields v.slflParent = parent v.flField = current v.cf = cf v.ct = ct if !hasValue(v) { return } ct = ct.next continue case typeOmitZero: v.slflParent = parent v.flField = current v.cf = cf v.ct = ct if !hasNotZeroValue(v) { return } ct = ct.next continue case typeOmitNil: v.slflParent = parent v.flField = current v.cf = cf v.ct = ct switch field := v.Field(); field.Kind() { case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func: if field.IsNil() { return } default: if v.fldIsPointer && getValue(field) == nil { return } } ct = ct.next continue case typeEndKeys: return case typeDive: ct = ct.next // traverse slice or map here // or panic ;) switch kind { case reflect.Slice, reflect.Array: var i64 int64 reusableCF := &cField{} for i := 0; i < current.Len(); i++ { i64 = int64(i) 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, ']') reusableCF.name = string(v.misc) if cf.namesEqual { reusableCF.altName = reusableCF.name } else { 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, ']') reusableCF.altName = string(v.misc) } v.traverseField(ctx, parent, current.Index(i), ns, structNs, reusableCF, ct) } case reflect.Map: var pv string reusableCF := &cField{} for _, key := range current.MapKeys() { pv = fmt.Sprintf("%v", key) 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, ']') reusableCF.name = string(v.misc) 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, ']') reusableCF.altName = string(v.misc) } 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 { // Struct fallback when map values are structs val := current.MapIndex(key) switch val.Kind() { case reflect.Ptr: if val.Elem().Kind() == reflect.Struct { // Dive into the struct so its own tags run v.traverseField(ctx, parent, val, ns, structNs, reusableCF, nil) } case reflect.Struct: v.traverseField(ctx, parent, val, ns, structNs, reusableCF, nil) } } } else { v.traverseField(ctx, parent, current.MapIndex(key), ns, structNs, reusableCF, ct) } } 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") } return case typeOr: v.misc = v.misc[0:0] for { // set Field Level fields v.slflParent = parent v.flField = current v.cf = cf v.ct = ct if ct.fn(ctx, v) { if ct.isBlockEnd { ct = ct.next continue OUTER } // drain rest of the 'or' values, then continue or leave for { ct = ct.next if ct == nil { continue OUTER } if ct.typeof != typeOr { continue OUTER } if ct.isBlockEnd { ct = ct.next continue OUTER } } } v.misc = append(v.misc, '|') v.misc = append(v.misc, ct.tag...) if ct.hasParam { v.misc = append(v.misc, '=') v.misc = append(v.misc, ct.param...) } 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: getValue(current), 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: getValue(current), param: ct.param, kind: kind, typ: typ, }, ) } return } ct = ct.next } default: // 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: getValue(current), param: ct.param, kind: kind, typ: typ, }, ) return } ct = ct.next } } } func getValue(val reflect.Value) interface{} { if val.CanInterface() { return val.Interface() } if val.CanAddr() { return reflect.NewAt(val.Type(), unsafe.Pointer(val.UnsafeAddr())).Elem().Interface() } switch val.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return val.Int() case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return val.Uint() case reflect.Complex64, reflect.Complex128: return val.Complex() case reflect.Float32, reflect.Float64: return val.Float() default: return val.String() } } golang-github-go-playground-validator-v10-10.30.1/validator_instance.go000066400000000000000000000644301512410077000257630ustar00rootroot00000000000000package 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" omitzero = "omitzero" omitempty = "omitempty" omitnil = "omitnil" isdefault = "isdefault" requiredWithoutAllTag = "required_without_all" requiredWithoutTag = "required_without" requiredWithTag = "required_with" requiredWithAllTag = "required_with_all" requiredIfTag = "required_if" requiredUnlessTag = "required_unless" skipUnlessTag = "skip_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{}) byteSliceType = reflect.TypeOf([]byte{}) defaultCField = &cField{namesEqual: true} ) // FilterFunc is the type used to filter fields using // StructFiltered(...) function. // returning true results in the field being filtered/skipped 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 runValidationOnNil bool } // Validate contains the validator settings and cache type Validate struct { tagName string pool *sync.Pool 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[]map[]TranslationFunc rules map[reflect.Type]map[string]string tagCache *tagCache structCache *structCache hasCustomFuncs bool hasTagNameFunc bool requiredStructEnabled bool privateFieldValidation bool } // 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(options ...Option) *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, skipUnlessTag: _ = 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), } }, } for _, o := range options { o(v) } 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 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.VarWithKeyCtx(ctx, field, 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) } // 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 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 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 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 } // VarWithKey validates a single variable with a key to be included in the returned error using tag style validation // eg. // var s string // validate.VarWithKey("email_address", s, "required,email") // // 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) VarWithKey(key string, field interface{}, tag string) error { return v.VarWithKeyCtx(context.Background(), key, field, tag) } // VarWithKeyCtx validates a single variable with a key to be included in the returned error using tag style validation // and allows passing of contextual validation information via context.Context. // eg. // var s string // validate.VarWithKeyCtx("email_address", s, "required,email") // // 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) VarWithKeyCtx(ctx context.Context, key string, field interface{}, tag string) (err error) { if len(tag) == 0 || tag == skipValidationTag { return nil } ctag := v.fetchCacheTag(tag) cField := &cField{ name: key, altName: key, namesEqual: true, } 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], cField, ctag) if len(vd.errs) > 0 { err = vd.errs vd.errs = nil } v.pool.Put(vd) return } 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, runValidationOnNil: nilCheckable} return nil } golang-github-go-playground-validator-v10-10.30.1/validator_test.go000066400000000000000000014760031512410077000251420ustar00rootroot00000000000000package validator import ( "bytes" "context" "database/sql" "database/sql/driver" "encoding/base64" "encoding/json" "errors" "fmt" "image" "image/jpeg" "image/png" "net" "os" "path/filepath" "reflect" "runtime" "strings" "testing" "time" . "github.com/go-playground/assert/v2" "github.com/go-playground/locales/en" "github.com/go-playground/locales/fr" "github.com/go-playground/locales/nl" ut "github.com/go-playground/universal-translator" ) // NOTES: // - Run "go test" to run tests // - Run "gocov test | gocov report" to report on test coverage by file // - Run "gocov test | gocov annotate -" to report on all code and functions, those, marked with "MISS" were never called // // or // // -- may be a good idea to change to output path to somewherelike /tmp // go test -coverprofile cover.out && go tool cover -html=cover.out -o cover.html // // // go test -cpuprofile cpu.out // ./validator.test -test.bench=. -test.cpuprofile=cpu.prof // go tool pprof validator.test cpu.prof // // // go test -memprofile mem.out type I interface { Foo() string } type Impl struct { F string `validate:"len=3"` } func (i *Impl) Foo() string { return i.F } type SubTest struct { Test string `validate:"required"` } type TestInterface struct { Iface I } type TestString struct { BlankTag string `validate:""` Required string `validate:"required"` Len string `validate:"len=10"` Min string `validate:"min=1"` Max string `validate:"max=10"` MinMax string `validate:"min=1,max=10"` Lt string `validate:"lt=10"` Lte string `validate:"lte=10"` Gt string `validate:"gt=10"` Gte string `validate:"gte=10"` OmitEmpty string `validate:"omitempty,min=1,max=10"` Boolean string `validate:"boolean"` Sub *SubTest SubIgnore *SubTest `validate:"-"` Anonymous struct { A string `validate:"required"` } Iface I } type TestUint64 struct { Required uint64 `validate:"required"` Len uint64 `validate:"len=10"` Min uint64 `validate:"min=1"` Max uint64 `validate:"max=10"` MinMax uint64 `validate:"min=1,max=10"` OmitEmpty uint64 `validate:"omitempty,min=1,max=10"` } type TestFloat64 struct { Required float64 `validate:"required"` Len float64 `validate:"len=10"` Min float64 `validate:"min=1"` Max float64 `validate:"max=10"` MinMax float64 `validate:"min=1,max=10"` Lte float64 `validate:"lte=10"` OmitEmpty float64 `validate:"omitempty,min=1,max=10"` } type TestSlice struct { Required []int `validate:"required"` Len []int `validate:"len=10"` Min []int `validate:"min=1"` Max []int `validate:"max=10"` MinMax []int `validate:"min=1,max=10"` OmitEmpty []int `validate:"omitempty,min=1,max=10"` } func AssertError(t *testing.T, err error, nsKey, structNsKey, field, structField, expectedTag string) { errs := err.(ValidationErrors) found := false var fe FieldError for i := 0; i < len(errs); i++ { if errs[i].Namespace() == nsKey && errs[i].StructNamespace() == structNsKey { found = true fe = errs[i] break } } EqualSkip(t, 2, found, true) NotEqualSkip(t, 2, fe, nil) EqualSkip(t, 2, fe.Field(), field) EqualSkip(t, 2, fe.StructField(), structField) EqualSkip(t, 2, fe.Tag(), expectedTag) } func AssertDeepError(t *testing.T, err error, nsKey, structNsKey, field, structField, expectedTag, actualTag string) { errs := err.(ValidationErrors) found := false var fe FieldError for i := 0; i < len(errs); i++ { if errs[i].Namespace() == nsKey && errs[i].StructNamespace() == structNsKey && errs[i].Tag() == expectedTag && errs[i].ActualTag() == actualTag { found = true fe = errs[i] break } } EqualSkip(t, 2, found, true) NotEqualSkip(t, 2, fe, nil) EqualSkip(t, 2, fe.Field(), field) EqualSkip(t, 2, fe.StructField(), structField) } func getError(err error, nsKey, structNsKey string) FieldError { errs := err.(ValidationErrors) var fe FieldError for i := 0; i < len(errs); i++ { if errs[i].Namespace() == nsKey && errs[i].StructNamespace() == structNsKey { fe = errs[i] break } } return fe } type valuer struct { Name string } func (v valuer) Value() (driver.Value, error) { if v.Name == "errorme" { panic("SQL Driver Valuer error: some kind of error") // return nil, errors.New("some kind of error") } if len(v.Name) == 0 { return nil, nil } return v.Name, nil } type MadeUpCustomType struct { FirstName string LastName string } func ValidateCustomType(field reflect.Value) interface{} { if cust, ok := field.Interface().(MadeUpCustomType); ok { if len(cust.FirstName) == 0 || len(cust.LastName) == 0 { return "" } return cust.FirstName + " " + cust.LastName } return "" } func OverrideIntTypeForSomeReason(field reflect.Value) interface{} { if i, ok := field.Interface().(int); ok { if i == 1 { return "1" } if i == 2 { return "12" } } return "" } type CustomMadeUpStruct struct { MadeUp MadeUpCustomType `validate:"required"` OverriddenInt int `validate:"gt=1"` } func ValidateValuerType(field reflect.Value) interface{} { if valuer, ok := field.Interface().(driver.Valuer); ok { val, err := valuer.Value() if err != nil { // handle the error how you want return nil } return val } return nil } type TestPartial struct { NoTag string BlankTag string `validate:""` Required string `validate:"required"` SubSlice []*SubTest `validate:"required,dive"` Sub *SubTest SubIgnore *SubTest `validate:"-"` Anonymous struct { A string `validate:"required"` ASubSlice []*SubTest `validate:"required,dive"` SubAnonStruct []struct { Test string `validate:"required"` OtherTest string `validate:"required"` } `validate:"required,dive"` } } type TestStruct struct { String string `validate:"required" json:"StringVal"` } func StructValidationTestStructSuccess(sl StructLevel) { st := sl.Current().Interface().(TestStruct) if st.String != "good value" { sl.ReportError(st.String, "StringVal", "String", "badvalueteststruct", "good value") } } func StructValidationTestStruct(sl StructLevel) { st := sl.Current().Interface().(TestStruct) if st.String != "bad value" { sl.ReportError(st.String, "StringVal", "String", "badvalueteststruct", "bad value") } } func StructValidationNoTestStructCustomName(sl StructLevel) { st := sl.Current().Interface().(TestStruct) if st.String != "bad value" { sl.ReportError(st.String, "String", "", "badvalueteststruct", "bad value") } } func StructValidationTestStructInvalid(sl StructLevel) { st := sl.Current().Interface().(TestStruct) if st.String != "bad value" { sl.ReportError(nil, "StringVal", "String", "badvalueteststruct", "bad value") } } func StructValidationTestStructReturnValidationErrors(sl StructLevel) { s := sl.Current().Interface().(TestStructReturnValidationErrors) errs := sl.Validator().Struct(s.Inner1.Inner2) if errs == nil { return } sl.ReportValidationErrors("Inner1.", "Inner1.", errs.(ValidationErrors)) } func StructValidationTestStructReturnValidationErrors2(sl StructLevel) { s := sl.Current().Interface().(TestStructReturnValidationErrors) errs := sl.Validator().Struct(s.Inner1.Inner2) if errs == nil { return } sl.ReportValidationErrors("Inner1JSON.", "Inner1.", errs.(ValidationErrors)) } type TestStructReturnValidationErrorsInner2 struct { String string `validate:"required" json:"JSONString"` } type TestStructReturnValidationErrorsInner1 struct { Inner2 *TestStructReturnValidationErrorsInner2 } type TestStructReturnValidationErrors struct { Inner1 *TestStructReturnValidationErrorsInner1 `json:"Inner1JSON"` } type StructLevelInvalidErr struct { Value string } func StructLevelInvalidError(sl StructLevel) { top := sl.Top().Interface().(StructLevelInvalidErr) s := sl.Current().Interface().(StructLevelInvalidErr) if top.Value == s.Value { sl.ReportError(nil, "Value", "Value", "required", "") } } func stringPtr(v string) *string { return &v } func intPtr(v int) *int { return &v } func float64Ptr(v float64) *float64 { return &v } func TestStructLevelInvalidError(t *testing.T) { validate := New() validate.RegisterStructValidation(StructLevelInvalidError, StructLevelInvalidErr{}) var test StructLevelInvalidErr err := validate.Struct(test) NotEqual(t, err, nil) errs, ok := err.(ValidationErrors) Equal(t, ok, true) fe := errs[0] Equal(t, fe.Field(), "Value") Equal(t, fe.StructField(), "Value") Equal(t, fe.Namespace(), "StructLevelInvalidErr.Value") Equal(t, fe.StructNamespace(), "StructLevelInvalidErr.Value") Equal(t, fe.Tag(), "required") Equal(t, fe.ActualTag(), "required") Equal(t, fe.Kind(), reflect.Invalid) Equal(t, fe.Type(), reflect.TypeOf(nil)) } func TestNameNamespace(t *testing.T) { type Inner2Namespace struct { String []string `validate:"dive,required" json:"JSONString"` } type Inner1Namespace struct { Inner2 *Inner2Namespace `json:"Inner2JSON"` } type Namespace struct { Inner1 *Inner1Namespace `json:"Inner1JSON"` } validate := New() validate.RegisterTagNameFunc(func(fld reflect.StructField) string { name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] if name == "-" { return "" } return name }) i2 := &Inner2Namespace{String: []string{"ok", "ok", "ok"}} i1 := &Inner1Namespace{Inner2: i2} ns := &Namespace{Inner1: i1} errs := validate.Struct(ns) Equal(t, errs, nil) i2.String[1] = "" errs = validate.Struct(ns) NotEqual(t, errs, nil) ve := errs.(ValidationErrors) Equal(t, len(ve), 1) AssertError(t, errs, "Namespace.Inner1JSON.Inner2JSON.JSONString[1]", "Namespace.Inner1.Inner2.String[1]", "JSONString[1]", "String[1]", "required") fe := getError(ve, "Namespace.Inner1JSON.Inner2JSON.JSONString[1]", "Namespace.Inner1.Inner2.String[1]") NotEqual(t, fe, nil) Equal(t, fe.Field(), "JSONString[1]") Equal(t, fe.StructField(), "String[1]") Equal(t, fe.Namespace(), "Namespace.Inner1JSON.Inner2JSON.JSONString[1]") Equal(t, fe.StructNamespace(), "Namespace.Inner1.Inner2.String[1]") } func TestAnonymous(t *testing.T) { validate := New() validate.RegisterTagNameFunc(func(fld reflect.StructField) string { name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] if name == "-" { return "" } return name }) type Test struct { Anonymous struct { A string `validate:"required" json:"EH"` } AnonymousB struct { B string `validate:"required" json:"BEE"` } anonymousC struct { c string `validate:"required"` } } tst := &Test{ Anonymous: struct { A string `validate:"required" json:"EH"` }{ A: "1", }, AnonymousB: struct { B string `validate:"required" json:"BEE"` }{ B: "", }, anonymousC: struct { c string `validate:"required"` }{ c: "", }, } Equal(t, tst.anonymousC.c, "") err := validate.Struct(tst) NotEqual(t, err, nil) errs := err.(ValidationErrors) Equal(t, len(errs), 1) AssertError(t, errs, "Test.AnonymousB.BEE", "Test.AnonymousB.B", "BEE", "B", "required") fe := getError(errs, "Test.AnonymousB.BEE", "Test.AnonymousB.B") NotEqual(t, fe, nil) Equal(t, fe.Field(), "BEE") Equal(t, fe.StructField(), "B") s := struct { c string `validate:"required"` }{ c: "", } err = validate.Struct(s) Equal(t, err, nil) } func TestAnonymousSameStructDifferentTags(t *testing.T) { validate := New() validate.RegisterTagNameFunc(func(fld reflect.StructField) string { name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] if name == "-" { return "" } return name }) type Test struct { A interface{} } tst := &Test{ A: struct { A string `validate:"required"` }{ A: "", }, } err := validate.Struct(tst) NotEqual(t, err, nil) errs := err.(ValidationErrors) Equal(t, len(errs), 1) AssertError(t, errs, "Test.A.A", "Test.A.A", "A", "A", "required") tst = &Test{ A: struct { A string `validate:"omitempty,required"` }{ A: "", }, } err = validate.Struct(tst) Equal(t, err, nil) } func TestStructLevelReturnValidationErrors(t *testing.T) { validate := New() validate.RegisterStructValidation(StructValidationTestStructReturnValidationErrors, TestStructReturnValidationErrors{}) inner2 := &TestStructReturnValidationErrorsInner2{ String: "I'm HERE", } inner1 := &TestStructReturnValidationErrorsInner1{ Inner2: inner2, } val := &TestStructReturnValidationErrors{ Inner1: inner1, } errs := validate.Struct(val) Equal(t, errs, nil) inner2.String = "" errs = validate.Struct(val) NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 2) AssertError(t, errs, "TestStructReturnValidationErrors.Inner1.Inner2.String", "TestStructReturnValidationErrors.Inner1.Inner2.String", "String", "String", "required") // this is an extra error reported from struct validation AssertError(t, errs, "TestStructReturnValidationErrors.Inner1.TestStructReturnValidationErrorsInner2.String", "TestStructReturnValidationErrors.Inner1.TestStructReturnValidationErrorsInner2.String", "String", "String", "required") } func TestStructLevelReturnValidationErrorsWithJSON(t *testing.T) { validate := New() validate.RegisterTagNameFunc(func(fld reflect.StructField) string { name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] if name == "-" { return "" } return name }) validate.RegisterStructValidation(StructValidationTestStructReturnValidationErrors2, TestStructReturnValidationErrors{}) inner2 := &TestStructReturnValidationErrorsInner2{ String: "I'm HERE", } inner1 := &TestStructReturnValidationErrorsInner1{ Inner2: inner2, } val := &TestStructReturnValidationErrors{ Inner1: inner1, } errs := validate.Struct(val) Equal(t, errs, nil) inner2.String = "" errs = validate.Struct(val) NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 2) AssertError(t, errs, "TestStructReturnValidationErrors.Inner1JSON.Inner2.JSONString", "TestStructReturnValidationErrors.Inner1.Inner2.String", "JSONString", "String", "required") // this is an extra error reported from struct validation, it's a badly formatted one, but on purpose AssertError(t, errs, "TestStructReturnValidationErrors.Inner1JSON.TestStructReturnValidationErrorsInner2.JSONString", "TestStructReturnValidationErrors.Inner1.TestStructReturnValidationErrorsInner2.String", "JSONString", "String", "required") fe := getError(errs, "TestStructReturnValidationErrors.Inner1JSON.Inner2.JSONString", "TestStructReturnValidationErrors.Inner1.Inner2.String") NotEqual(t, fe, nil) // check for proper JSON namespace Equal(t, fe.Field(), "JSONString") Equal(t, fe.StructField(), "String") Equal(t, fe.Namespace(), "TestStructReturnValidationErrors.Inner1JSON.Inner2.JSONString") Equal(t, fe.StructNamespace(), "TestStructReturnValidationErrors.Inner1.Inner2.String") fe = getError(errs, "TestStructReturnValidationErrors.Inner1JSON.TestStructReturnValidationErrorsInner2.JSONString", "TestStructReturnValidationErrors.Inner1.TestStructReturnValidationErrorsInner2.String") NotEqual(t, fe, nil) // check for proper JSON namespace Equal(t, fe.Field(), "JSONString") Equal(t, fe.StructField(), "String") Equal(t, fe.Namespace(), "TestStructReturnValidationErrors.Inner1JSON.TestStructReturnValidationErrorsInner2.JSONString") Equal(t, fe.StructNamespace(), "TestStructReturnValidationErrors.Inner1.TestStructReturnValidationErrorsInner2.String") } func TestStructLevelValidations(t *testing.T) { v1 := New() v1.RegisterStructValidation(StructValidationTestStruct, TestStruct{}) tst := &TestStruct{ String: "good value", } errs := v1.Struct(tst) NotEqual(t, errs, nil) AssertError(t, errs, "TestStruct.StringVal", "TestStruct.String", "StringVal", "String", "badvalueteststruct") v2 := New() v2.RegisterStructValidation(StructValidationNoTestStructCustomName, TestStruct{}) errs = v2.Struct(tst) NotEqual(t, errs, nil) AssertError(t, errs, "TestStruct.String", "TestStruct.String", "String", "String", "badvalueteststruct") v3 := New() v3.RegisterStructValidation(StructValidationTestStructInvalid, TestStruct{}) errs = v3.Struct(tst) NotEqual(t, errs, nil) AssertError(t, errs, "TestStruct.StringVal", "TestStruct.String", "StringVal", "String", "badvalueteststruct") v4 := New() v4.RegisterStructValidation(StructValidationTestStructSuccess, TestStruct{}) errs = v4.Struct(tst) Equal(t, errs, nil) } func TestAliasTags(t *testing.T) { validate := New() validate.RegisterAlias("iscoloralias", "hexcolor|rgb|rgba|hsl|hsla") s := "rgb(255,255,255)" errs := validate.Var(s, "iscoloralias") Equal(t, errs, nil) s = "" errs = validate.Var(s, "omitempty,iscoloralias") Equal(t, errs, nil) s = "rgb(255,255,0)" errs = validate.Var(s, "iscoloralias,len=5") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "len") type Test struct { Color string `validate:"iscoloralias"` } tst := &Test{ Color: "#000", } errs = validate.Struct(tst) Equal(t, errs, nil) tst.Color = "cfvre" errs = validate.Struct(tst) NotEqual(t, errs, nil) AssertError(t, errs, "Test.Color", "Test.Color", "Color", "Color", "iscoloralias") fe := getError(errs, "Test.Color", "Test.Color") NotEqual(t, fe, nil) Equal(t, fe.ActualTag(), "hexcolor|rgb|rgba|hsl|hsla") validate.RegisterAlias("req", "required,dive,iscoloralias") arr := []string{"val1", "#fff", "#000"} errs = validate.Var(arr, "req") NotEqual(t, errs, nil) AssertError(t, errs, "[0]", "[0]", "[0]", "[0]", "iscoloralias") PanicMatches(t, func() { validate.RegisterAlias("exists!", "gt=5,lt=10") }, "Alias 'exists!' either contains restricted characters or is the same as a restricted tag needed for normal operation") } func TestAliasWithOrOperator(t *testing.T) { validate := New() validate.RegisterAlias("customnum", "numeric") validate.RegisterAlias("customalpha", "alpha") validate.RegisterAlias("customgt5", "gt=5") t.Run("numeric|iscolor", func(t *testing.T) { type S struct { F string `validate:"numeric|iscolor"` } Equal(t, validate.Struct(S{"#fff"}), nil) Equal(t, validate.Struct(S{"123"}), nil) NotEqual(t, validate.Struct(S{"invalid!"}), nil) }) t.Run("iscolor|numeric", func(t *testing.T) { type S struct { F string `validate:"iscolor|numeric"` } Equal(t, validate.Struct(S{"456"}), nil) Equal(t, validate.Struct(S{"rgb(255,0,0)"}), nil) }) t.Run("alpha|customnum", func(t *testing.T) { type S struct { F string `validate:"alpha|customnum"` } Equal(t, validate.Struct(S{"789"}), nil) Equal(t, validate.Struct(S{"abc"}), nil) }) t.Run("customnum|customalpha", func(t *testing.T) { type S struct { F string `validate:"customnum|customalpha"` } Equal(t, validate.Struct(S{"xyz"}), nil) }) t.Run("alpha|customnum|email", func(t *testing.T) { type S struct { F string `validate:"alpha|customnum|email"` } Equal(t, validate.Struct(S{"test@example.com"}), nil) }) t.Run("eq=0|customgt5", func(t *testing.T) { type S struct { F int `validate:"eq=0|customgt5"` } Equal(t, validate.Struct(S{0}), nil) Equal(t, validate.Struct(S{10}), nil) NotEqual(t, validate.Struct(S{3}), nil) }) t.Run("numeric|country_code", func(t *testing.T) { type S struct { F string `validate:"numeric|country_code"` } Equal(t, validate.Struct(S{"US"}), nil) }) } func TestNilValidator(t *testing.T) { type TestStruct struct { Test string `validate:"required"` } ts := TestStruct{} var val *Validate fn := func(fl FieldLevel) bool { return fl.Parent().String() == fl.Field().String() } PanicMatches(t, func() { val.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{}) }, "runtime error: invalid memory address or nil pointer dereference") PanicMatches(t, func() { _ = val.RegisterValidation("something", fn) }, "runtime error: invalid memory address or nil pointer dereference") PanicMatches(t, func() { _ = val.Var(ts.Test, "required") }, "runtime error: invalid memory address or nil pointer dereference") PanicMatches(t, func() { _ = val.VarWithValue("test", ts.Test, "required") }, "runtime error: invalid memory address or nil pointer dereference") PanicMatches(t, func() { _ = val.Struct(ts) }, "runtime error: invalid memory address or nil pointer dereference") PanicMatches(t, func() { _ = val.StructExcept(ts, "Test") }, "runtime error: invalid memory address or nil pointer dereference") PanicMatches(t, func() { _ = val.StructPartial(ts, "Test") }, "runtime error: invalid memory address or nil pointer dereference") } func TestStructPartial(t *testing.T) { p1 := []string{ "NoTag", "Required", } p2 := []string{ "SubSlice[0].Test", "Sub", "SubIgnore", "Anonymous.A", } p3 := []string{ "SubTest.Test", } p4 := []string{ "A", } tPartial := &TestPartial{ NoTag: "NoTag", Required: "Required", SubSlice: []*SubTest{ { Test: "Required", }, { Test: "Required", }, }, Sub: &SubTest{ Test: "1", }, SubIgnore: &SubTest{ Test: "", }, Anonymous: struct { A string `validate:"required"` ASubSlice []*SubTest `validate:"required,dive"` SubAnonStruct []struct { Test string `validate:"required"` OtherTest string `validate:"required"` } `validate:"required,dive"` }{ A: "1", ASubSlice: []*SubTest{ { Test: "Required", }, { Test: "Required", }, }, SubAnonStruct: []struct { Test string `validate:"required"` OtherTest string `validate:"required"` }{ {"Required", "RequiredOther"}, {"Required", "RequiredOther"}, }, }, } validate := New() // the following should all return no errors as everything is valid in // the default state errs := validate.StructPartialCtx(context.Background(), tPartial, p1...) Equal(t, errs, nil) errs = validate.StructPartial(tPartial, p2...) Equal(t, errs, nil) // this isn't really a robust test, but is meant to illustrate the ANON CASE below errs = validate.StructPartial(tPartial.SubSlice[0], p3...) Equal(t, errs, nil) errs = validate.StructExceptCtx(context.Background(), tPartial, p1...) Equal(t, errs, nil) errs = validate.StructExcept(tPartial, p2...) Equal(t, errs, nil) // mod tPartial for required field and re-test making sure invalid fields are NOT required: tPartial.Required = "" errs = validate.StructExcept(tPartial, p1...) Equal(t, errs, nil) errs = validate.StructPartial(tPartial, p2...) Equal(t, errs, nil) // inversion and retesting Partial to generate failures: errs = validate.StructPartial(tPartial, p1...) NotEqual(t, errs, nil) AssertError(t, errs, "TestPartial.Required", "TestPartial.Required", "Required", "Required", "required") errs = validate.StructExcept(tPartial, p2...) AssertError(t, errs, "TestPartial.Required", "TestPartial.Required", "Required", "Required", "required") // reset Required field, and set nested struct tPartial.Required = "Required" tPartial.Anonymous.A = "" // will pass as unset fields is not going to be tested errs = validate.StructPartial(tPartial, p1...) Equal(t, errs, nil) errs = validate.StructExcept(tPartial, p2...) Equal(t, errs, nil) // ANON CASE the response here is strange, it clearly does what it is being told to errs = validate.StructExcept(tPartial.Anonymous, p4...) Equal(t, errs, nil) // will fail as unset field is tested errs = validate.StructPartial(tPartial, p2...) NotEqual(t, errs, nil) AssertError(t, errs, "TestPartial.Anonymous.A", "TestPartial.Anonymous.A", "A", "A", "required") errs = validate.StructExcept(tPartial, p1...) NotEqual(t, errs, nil) AssertError(t, errs, "TestPartial.Anonymous.A", "TestPartial.Anonymous.A", "A", "A", "required") // reset nested struct and unset struct in slice tPartial.Anonymous.A = "Required" tPartial.SubSlice[0].Test = "" // these will pass as unset item is NOT tested errs = validate.StructPartial(tPartial, p1...) Equal(t, errs, nil) errs = validate.StructExcept(tPartial, p2...) Equal(t, errs, nil) // these will fail as unset item IS tested errs = validate.StructExcept(tPartial, p1...) AssertError(t, errs, "TestPartial.SubSlice[0].Test", "TestPartial.SubSlice[0].Test", "Test", "Test", "required") Equal(t, len(errs.(ValidationErrors)), 1) errs = validate.StructPartial(tPartial, p2...) NotEqual(t, errs, nil) AssertError(t, errs, "TestPartial.SubSlice[0].Test", "TestPartial.SubSlice[0].Test", "Test", "Test", "required") Equal(t, len(errs.(ValidationErrors)), 1) // Unset second slice member concurrently to test dive behavior: tPartial.SubSlice[1].Test = "" errs = validate.StructPartial(tPartial, p1...) Equal(t, errs, nil) // NOTE: When specifying nested items, it is still the users responsibility // to specify the dive tag, the library does not override this. errs = validate.StructExcept(tPartial, p2...) NotEqual(t, errs, nil) AssertError(t, errs, "TestPartial.SubSlice[1].Test", "TestPartial.SubSlice[1].Test", "Test", "Test", "required") errs = validate.StructExcept(tPartial, p1...) Equal(t, len(errs.(ValidationErrors)), 2) AssertError(t, errs, "TestPartial.SubSlice[0].Test", "TestPartial.SubSlice[0].Test", "Test", "Test", "required") AssertError(t, errs, "TestPartial.SubSlice[1].Test", "TestPartial.SubSlice[1].Test", "Test", "Test", "required") errs = validate.StructPartial(tPartial, p2...) NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "TestPartial.SubSlice[0].Test", "TestPartial.SubSlice[0].Test", "Test", "Test", "required") // reset struct in slice, and unset struct in slice in unset position tPartial.SubSlice[0].Test = "Required" // these will pass as the unset item is NOT tested errs = validate.StructPartial(tPartial, p1...) Equal(t, errs, nil) errs = validate.StructPartial(tPartial, p2...) Equal(t, errs, nil) // testing for missing item by exception, yes it dives and fails errs = validate.StructExcept(tPartial, p1...) NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "TestPartial.SubSlice[1].Test", "TestPartial.SubSlice[1].Test", "Test", "Test", "required") errs = validate.StructExcept(tPartial, p2...) NotEqual(t, errs, nil) AssertError(t, errs, "TestPartial.SubSlice[1].Test", "TestPartial.SubSlice[1].Test", "Test", "Test", "required") tPartial.SubSlice[1].Test = "Required" tPartial.Anonymous.SubAnonStruct[0].Test = "" // these will pass as the unset item is NOT tested errs = validate.StructPartial(tPartial, p1...) Equal(t, errs, nil) errs = validate.StructPartial(tPartial, p2...) Equal(t, errs, nil) errs = validate.StructExcept(tPartial, p1...) NotEqual(t, errs, nil) AssertError(t, errs, "TestPartial.Anonymous.SubAnonStruct[0].Test", "TestPartial.Anonymous.SubAnonStruct[0].Test", "Test", "Test", "required") errs = validate.StructExcept(tPartial, p2...) NotEqual(t, errs, nil) AssertError(t, errs, "TestPartial.Anonymous.SubAnonStruct[0].Test", "TestPartial.Anonymous.SubAnonStruct[0].Test", "Test", "Test", "required") // Test for unnamed struct testStruct := &TestStruct{ String: "test", } unnamedStruct := struct { String string `validate:"required" json:"StringVal"` }{String: "test"} composedUnnamedStruct := struct{ *TestStruct }{&TestStruct{String: "test"}} errs = validate.StructPartial(testStruct, "String") Equal(t, errs, nil) errs = validate.StructPartial(unnamedStruct, "String") Equal(t, errs, nil) errs = validate.StructPartial(composedUnnamedStruct, "TestStruct.String") Equal(t, errs, nil) testStruct.String = "" errs = validate.StructPartial(testStruct, "String") NotEqual(t, errs, nil) AssertError(t, errs, "TestStruct.String", "TestStruct.String", "String", "String", "required") unnamedStruct.String = "" errs = validate.StructPartial(unnamedStruct, "String") NotEqual(t, errs, nil) AssertError(t, errs, "String", "String", "String", "String", "required") composedUnnamedStruct.String = "" errs = validate.StructPartial(composedUnnamedStruct, "TestStruct.String") NotEqual(t, errs, nil) AssertError(t, errs, "TestStruct.String", "TestStruct.String", "String", "String", "required") } func TestCrossStructLteFieldValidation(t *testing.T) { var errs error validate := New() type Inner struct { CreatedAt *time.Time String string Int int Uint uint Float float64 Array []string } type Test struct { Inner *Inner CreatedAt *time.Time `validate:"ltecsfield=Inner.CreatedAt"` String string `validate:"ltecsfield=Inner.String"` Int int `validate:"ltecsfield=Inner.Int"` Uint uint `validate:"ltecsfield=Inner.Uint"` Float float64 `validate:"ltecsfield=Inner.Float"` Array []string `validate:"ltecsfield=Inner.Array"` } now := time.Now().UTC() then := now.Add(time.Hour * 5) inner := &Inner{ CreatedAt: &then, String: "abcd", Int: 13, Uint: 13, Float: 1.13, Array: []string{"val1", "val2"}, } test := &Test{ Inner: inner, CreatedAt: &now, String: "abc", Int: 12, Uint: 12, Float: 1.12, Array: []string{"val1"}, } errs = validate.Struct(test) Equal(t, errs, nil) test.CreatedAt = &then test.String = "abcd" test.Int = 13 test.Uint = 13 test.Float = 1.13 test.Array = []string{"val1", "val2"} errs = validate.Struct(test) Equal(t, errs, nil) after := now.Add(time.Hour * 10) test.CreatedAt = &after test.String = "abce" test.Int = 14 test.Uint = 14 test.Float = 1.14 test.Array = []string{"val1", "val2", "val3"} errs = validate.Struct(test) NotEqual(t, errs, nil) AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "ltecsfield") AssertError(t, errs, "Test.String", "Test.String", "String", "String", "ltecsfield") AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "ltecsfield") AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "ltecsfield") AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "ltecsfield") AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "ltecsfield") errs = validate.VarWithValueCtx(context.Background(), 1, "", "ltecsfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "ltecsfield") // this test is for the WARNING about unforeseen validation issues. errs = validate.VarWithValue(test, now, "ltecsfield") NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 6) AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "ltecsfield") AssertError(t, errs, "Test.String", "Test.String", "String", "String", "ltecsfield") AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "ltecsfield") AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "ltecsfield") AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "ltecsfield") AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "ltecsfield") type Other struct { Value string } type Test2 struct { Value Other Time time.Time `validate:"ltecsfield=Value"` } tst := Test2{ Value: Other{Value: "StringVal"}, Time: then, } errs = validate.Struct(tst) NotEqual(t, errs, nil) AssertError(t, errs, "Test2.Time", "Test2.Time", "Time", "Time", "ltecsfield") // Tests for time.Duration type. // -- Validations for variables of time.Duration type. errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "ltecsfield") Equal(t, errs, nil) errs = validate.VarWithValue(time.Hour, time.Hour, "ltecsfield") Equal(t, errs, nil) errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "ltecsfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "ltecsfield") errs = validate.VarWithValue(time.Duration(0), -time.Minute, "omitempty,ltecsfield") Equal(t, errs, nil) // -- Validations for a struct and an inner struct with time.Duration type fields. type TimeDurationInner struct { Duration time.Duration } var timeDurationInner *TimeDurationInner type TimeDurationTest struct { Inner *TimeDurationInner Duration time.Duration `validate:"ltecsfield=Inner.Duration"` } var timeDurationTest *TimeDurationTest timeDurationInner = &TimeDurationInner{time.Hour + time.Minute} timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationInner = &TimeDurationInner{time.Hour} timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationInner = &TimeDurationInner{time.Hour - time.Minute} timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "ltecsfield") type TimeDurationOmitemptyTest struct { Inner *TimeDurationInner Duration time.Duration `validate:"omitempty,ltecsfield=Inner.Duration"` } var timeDurationOmitemptyTest *TimeDurationOmitemptyTest timeDurationInner = &TimeDurationInner{-time.Minute} timeDurationOmitemptyTest = &TimeDurationOmitemptyTest{timeDurationInner, time.Duration(0)} errs = validate.Struct(timeDurationOmitemptyTest) Equal(t, errs, nil) } func TestCrossStructLtFieldValidation(t *testing.T) { var errs error validate := New() type Inner struct { CreatedAt *time.Time String string Int int Uint uint Float float64 Array []string } type Test struct { Inner *Inner CreatedAt *time.Time `validate:"ltcsfield=Inner.CreatedAt"` String string `validate:"ltcsfield=Inner.String"` Int int `validate:"ltcsfield=Inner.Int"` Uint uint `validate:"ltcsfield=Inner.Uint"` Float float64 `validate:"ltcsfield=Inner.Float"` Array []string `validate:"ltcsfield=Inner.Array"` } now := time.Now().UTC() then := now.Add(time.Hour * 5) inner := &Inner{ CreatedAt: &then, String: "abcd", Int: 13, Uint: 13, Float: 1.13, Array: []string{"val1", "val2"}, } test := &Test{ Inner: inner, CreatedAt: &now, String: "abc", Int: 12, Uint: 12, Float: 1.12, Array: []string{"val1"}, } errs = validate.Struct(test) Equal(t, errs, nil) test.CreatedAt = &then test.String = "abcd" test.Int = 13 test.Uint = 13 test.Float = 1.13 test.Array = []string{"val1", "val2"} errs = validate.Struct(test) NotEqual(t, errs, nil) AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "ltcsfield") AssertError(t, errs, "Test.String", "Test.String", "String", "String", "ltcsfield") AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "ltcsfield") AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "ltcsfield") AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "ltcsfield") AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "ltcsfield") errs = validate.VarWithValue(1, "", "ltcsfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "ltcsfield") // this test is for the WARNING about unforeseen validation issues. errs = validate.VarWithValue(test, now, "ltcsfield") NotEqual(t, errs, nil) AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "ltcsfield") AssertError(t, errs, "Test.String", "Test.String", "String", "String", "ltcsfield") AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "ltcsfield") AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "ltcsfield") AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "ltcsfield") AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "ltcsfield") type Other struct { Value string } type Test2 struct { Value Other Time time.Time `validate:"ltcsfield=Value"` } tst := Test2{ Value: Other{Value: "StringVal"}, Time: then, } errs = validate.Struct(tst) NotEqual(t, errs, nil) AssertError(t, errs, "Test2.Time", "Test2.Time", "Time", "Time", "ltcsfield") // Tests for time.Duration type. // -- Validations for variables of time.Duration type. errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "ltcsfield") Equal(t, errs, nil) errs = validate.VarWithValue(time.Hour, time.Hour, "ltcsfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "ltcsfield") errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "ltcsfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "ltcsfield") errs = validate.VarWithValue(time.Duration(0), -time.Minute, "omitempty,ltcsfield") Equal(t, errs, nil) // -- Validations for a struct and an inner struct with time.Duration type fields. type TimeDurationInner struct { Duration time.Duration } var timeDurationInner *TimeDurationInner type TimeDurationTest struct { Inner *TimeDurationInner Duration time.Duration `validate:"ltcsfield=Inner.Duration"` } var timeDurationTest *TimeDurationTest timeDurationInner = &TimeDurationInner{time.Hour + time.Minute} timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationInner = &TimeDurationInner{time.Hour} timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "ltcsfield") timeDurationInner = &TimeDurationInner{time.Hour - time.Minute} timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "ltcsfield") type TimeDurationOmitemptyTest struct { Inner *TimeDurationInner Duration time.Duration `validate:"omitempty,ltcsfield=Inner.Duration"` } var timeDurationOmitemptyTest *TimeDurationOmitemptyTest timeDurationInner = &TimeDurationInner{-time.Minute} timeDurationOmitemptyTest = &TimeDurationOmitemptyTest{timeDurationInner, time.Duration(0)} errs = validate.Struct(timeDurationOmitemptyTest) Equal(t, errs, nil) } func TestCrossStructGteFieldValidation(t *testing.T) { var errs error validate := New() type Inner struct { CreatedAt *time.Time String string Int int Uint uint Float float64 Array []string } type Test struct { Inner *Inner CreatedAt *time.Time `validate:"gtecsfield=Inner.CreatedAt"` String string `validate:"gtecsfield=Inner.String"` Int int `validate:"gtecsfield=Inner.Int"` Uint uint `validate:"gtecsfield=Inner.Uint"` Float float64 `validate:"gtecsfield=Inner.Float"` Array []string `validate:"gtecsfield=Inner.Array"` } now := time.Now().UTC() then := now.Add(time.Hour * -5) inner := &Inner{ CreatedAt: &then, String: "abcd", Int: 13, Uint: 13, Float: 1.13, Array: []string{"val1", "val2"}, } test := &Test{ Inner: inner, CreatedAt: &now, String: "abcde", Int: 14, Uint: 14, Float: 1.14, Array: []string{"val1", "val2", "val3"}, } errs = validate.Struct(test) Equal(t, errs, nil) test.CreatedAt = &then test.String = "abcd" test.Int = 13 test.Uint = 13 test.Float = 1.13 test.Array = []string{"val1", "val2"} errs = validate.Struct(test) Equal(t, errs, nil) before := now.Add(time.Hour * -10) test.CreatedAt = &before test.String = "abc" test.Int = 12 test.Uint = 12 test.Float = 1.12 test.Array = []string{"val1"} errs = validate.Struct(test) NotEqual(t, errs, nil) AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "gtecsfield") AssertError(t, errs, "Test.String", "Test.String", "String", "String", "gtecsfield") AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "gtecsfield") AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "gtecsfield") AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "gtecsfield") AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "gtecsfield") errs = validate.VarWithValue(1, "", "gtecsfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gtecsfield") // this test is for the WARNING about unforeseen validation issues. errs = validate.VarWithValue(test, now, "gtecsfield") NotEqual(t, errs, nil) AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "gtecsfield") AssertError(t, errs, "Test.String", "Test.String", "String", "String", "gtecsfield") AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "gtecsfield") AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "gtecsfield") AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "gtecsfield") AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "gtecsfield") type Other struct { Value string } type Test2 struct { Value Other Time time.Time `validate:"gtecsfield=Value"` } tst := Test2{ Value: Other{Value: "StringVal"}, Time: then, } errs = validate.Struct(tst) NotEqual(t, errs, nil) AssertError(t, errs, "Test2.Time", "Test2.Time", "Time", "Time", "gtecsfield") // Tests for time.Duration type. // -- Validations for variables of time.Duration type. errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "gtecsfield") Equal(t, errs, nil) errs = validate.VarWithValue(time.Hour, time.Hour, "gtecsfield") Equal(t, errs, nil) errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "gtecsfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gtecsfield") errs = validate.VarWithValue(time.Duration(0), time.Hour, "omitempty,gtecsfield") Equal(t, errs, nil) // -- Validations for a struct and an inner struct with time.Duration type fields. type TimeDurationInner struct { Duration time.Duration } var timeDurationInner *TimeDurationInner type TimeDurationTest struct { Inner *TimeDurationInner Duration time.Duration `validate:"gtecsfield=Inner.Duration"` } var timeDurationTest *TimeDurationTest timeDurationInner = &TimeDurationInner{time.Hour - time.Minute} timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationInner = &TimeDurationInner{time.Hour} timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationInner = &TimeDurationInner{time.Hour + time.Minute} timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "gtecsfield") type TimeDurationOmitemptyTest struct { Inner *TimeDurationInner Duration time.Duration `validate:"omitempty,gtecsfield=Inner.Duration"` } var timeDurationOmitemptyTest *TimeDurationOmitemptyTest timeDurationInner = &TimeDurationInner{time.Hour} timeDurationOmitemptyTest = &TimeDurationOmitemptyTest{timeDurationInner, time.Duration(0)} errs = validate.Struct(timeDurationOmitemptyTest) Equal(t, errs, nil) } func TestCrossStructGtFieldValidation(t *testing.T) { var errs error validate := New() type Inner struct { CreatedAt *time.Time String string Int int Uint uint Float float64 Array []string } type Test struct { Inner *Inner CreatedAt *time.Time `validate:"gtcsfield=Inner.CreatedAt"` String string `validate:"gtcsfield=Inner.String"` Int int `validate:"gtcsfield=Inner.Int"` Uint uint `validate:"gtcsfield=Inner.Uint"` Float float64 `validate:"gtcsfield=Inner.Float"` Array []string `validate:"gtcsfield=Inner.Array"` } now := time.Now().UTC() then := now.Add(time.Hour * -5) inner := &Inner{ CreatedAt: &then, String: "abcd", Int: 13, Uint: 13, Float: 1.13, Array: []string{"val1", "val2"}, } test := &Test{ Inner: inner, CreatedAt: &now, String: "abcde", Int: 14, Uint: 14, Float: 1.14, Array: []string{"val1", "val2", "val3"}, } errs = validate.Struct(test) Equal(t, errs, nil) test.CreatedAt = &then test.String = "abcd" test.Int = 13 test.Uint = 13 test.Float = 1.13 test.Array = []string{"val1", "val2"} errs = validate.Struct(test) NotEqual(t, errs, nil) AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "gtcsfield") AssertError(t, errs, "Test.String", "Test.String", "String", "String", "gtcsfield") AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "gtcsfield") AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "gtcsfield") AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "gtcsfield") AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "gtcsfield") errs = validate.VarWithValue(1, "", "gtcsfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gtcsfield") // this test is for the WARNING about unforeseen validation issues. errs = validate.VarWithValue(test, now, "gtcsfield") NotEqual(t, errs, nil) AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "gtcsfield") AssertError(t, errs, "Test.String", "Test.String", "String", "String", "gtcsfield") AssertError(t, errs, "Test.Int", "Test.Int", "Int", "Int", "gtcsfield") AssertError(t, errs, "Test.Uint", "Test.Uint", "Uint", "Uint", "gtcsfield") AssertError(t, errs, "Test.Float", "Test.Float", "Float", "Float", "gtcsfield") AssertError(t, errs, "Test.Array", "Test.Array", "Array", "Array", "gtcsfield") type Other struct { Value string } type Test2 struct { Value Other Time time.Time `validate:"gtcsfield=Value"` } tst := Test2{ Value: Other{Value: "StringVal"}, Time: then, } errs = validate.Struct(tst) NotEqual(t, errs, nil) AssertError(t, errs, "Test2.Time", "Test2.Time", "Time", "Time", "gtcsfield") // Tests for time.Duration type. // -- Validations for variables of time.Duration type. errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "gtcsfield") Equal(t, errs, nil) errs = validate.VarWithValue(time.Hour, time.Hour, "gtcsfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gtcsfield") errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "gtcsfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gtcsfield") errs = validate.VarWithValue(time.Duration(0), time.Hour, "omitempty,gtcsfield") Equal(t, errs, nil) // -- Validations for a struct and an inner struct with time.Duration type fields. type TimeDurationInner struct { Duration time.Duration } var timeDurationInner *TimeDurationInner type TimeDurationTest struct { Inner *TimeDurationInner Duration time.Duration `validate:"gtcsfield=Inner.Duration"` } var timeDurationTest *TimeDurationTest timeDurationInner = &TimeDurationInner{time.Hour - time.Minute} timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationInner = &TimeDurationInner{time.Hour} timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "gtcsfield") timeDurationInner = &TimeDurationInner{time.Hour + time.Minute} timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "gtcsfield") type TimeDurationOmitemptyTest struct { Inner *TimeDurationInner Duration time.Duration `validate:"omitempty,gtcsfield=Inner.Duration"` } var timeDurationOmitemptyTest *TimeDurationOmitemptyTest timeDurationInner = &TimeDurationInner{time.Hour} timeDurationOmitemptyTest = &TimeDurationOmitemptyTest{timeDurationInner, time.Duration(0)} errs = validate.Struct(timeDurationOmitemptyTest) Equal(t, errs, nil) } func TestCrossStructNeFieldValidation(t *testing.T) { var errs error validate := New() type Inner struct { CreatedAt *time.Time } type Test struct { Inner *Inner CreatedAt *time.Time `validate:"necsfield=Inner.CreatedAt"` } now := time.Now().UTC() then := now.Add(time.Hour * 5) inner := &Inner{ CreatedAt: &then, } test := &Test{ Inner: inner, CreatedAt: &now, } errs = validate.Struct(test) Equal(t, errs, nil) test.CreatedAt = &then errs = validate.Struct(test) NotEqual(t, errs, nil) AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "necsfield") var j uint64 var k float64 var j2 uint64 var k2 float64 s := "abcd" i := 1 j = 1 k = 1.543 b := true arr := []string{"test"} s2 := "abcd" i2 := 1 j2 = 1 k2 = 1.543 b2 := true arr2 := []string{"test"} arr3 := []string{"test", "test2"} now2 := now errs = validate.VarWithValue(s, s2, "necsfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "necsfield") errs = validate.VarWithValue(i2, i, "necsfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "necsfield") errs = validate.VarWithValue(j2, j, "necsfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "necsfield") errs = validate.VarWithValue(k2, k, "necsfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "necsfield") errs = validate.VarWithValue(b2, b, "necsfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "necsfield") errs = validate.VarWithValue(arr2, arr, "necsfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "necsfield") errs = validate.VarWithValue(now2, now, "necsfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "necsfield") errs = validate.VarWithValue(arr3, arr, "necsfield") Equal(t, errs, nil) type SInner struct { Name string } type TStruct struct { Inner *SInner CreatedAt *time.Time `validate:"necsfield=Inner"` } sinner := &SInner{ Name: "NAME", } test2 := &TStruct{ Inner: sinner, CreatedAt: &now, } errs = validate.Struct(test2) Equal(t, errs, nil) test2.Inner = nil errs = validate.Struct(test2) Equal(t, errs, nil) errs = validate.VarWithValue(nil, 1, "necsfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "necsfield") // Tests for time.Duration type. // -- Validations for variables of time.Duration type. errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "necsfield") Equal(t, errs, nil) errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "necsfield") Equal(t, errs, nil) errs = validate.VarWithValue(time.Hour, time.Hour, "necsfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "necsfield") errs = validate.VarWithValue(time.Duration(0), time.Duration(0), "omitempty,necsfield") Equal(t, errs, nil) // -- Validations for a struct and an inner struct with time.Duration type fields. type TimeDurationInner struct { Duration time.Duration } var timeDurationInner *TimeDurationInner type TimeDurationTest struct { Inner *TimeDurationInner Duration time.Duration `validate:"necsfield=Inner.Duration"` } var timeDurationTest *TimeDurationTest timeDurationInner = &TimeDurationInner{time.Hour - time.Minute} timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationInner = &TimeDurationInner{time.Hour + time.Minute} timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationInner = &TimeDurationInner{time.Hour} timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "necsfield") type TimeDurationOmitemptyTest struct { Inner *TimeDurationInner Duration time.Duration `validate:"omitempty,necsfield=Inner.Duration"` } var timeDurationOmitemptyTest *TimeDurationOmitemptyTest timeDurationInner = &TimeDurationInner{time.Duration(0)} timeDurationOmitemptyTest = &TimeDurationOmitemptyTest{timeDurationInner, time.Duration(0)} errs = validate.Struct(timeDurationOmitemptyTest) Equal(t, errs, nil) } func TestCrossStructEqFieldValidation(t *testing.T) { var errs error validate := New() type Inner struct { CreatedAt *time.Time } type Test struct { Inner *Inner CreatedAt *time.Time `validate:"eqcsfield=Inner.CreatedAt"` } now := time.Now().UTC() inner := &Inner{ CreatedAt: &now, } test := &Test{ Inner: inner, CreatedAt: &now, } errs = validate.Struct(test) Equal(t, errs, nil) newTime := time.Now().Add(time.Hour).UTC() test.CreatedAt = &newTime errs = validate.Struct(test) NotEqual(t, errs, nil) AssertError(t, errs, "Test.CreatedAt", "Test.CreatedAt", "CreatedAt", "CreatedAt", "eqcsfield") var j uint64 var k float64 s := "abcd" i := 1 j = 1 k = 1.543 b := true arr := []string{"test"} var j2 uint64 var k2 float64 s2 := "abcd" i2 := 1 j2 = 1 k2 = 1.543 b2 := true arr2 := []string{"test"} arr3 := []string{"test", "test2"} now2 := now errs = validate.VarWithValue(s, s2, "eqcsfield") Equal(t, errs, nil) errs = validate.VarWithValue(i2, i, "eqcsfield") Equal(t, errs, nil) errs = validate.VarWithValue(j2, j, "eqcsfield") Equal(t, errs, nil) errs = validate.VarWithValue(k2, k, "eqcsfield") Equal(t, errs, nil) errs = validate.VarWithValue(b2, b, "eqcsfield") Equal(t, errs, nil) errs = validate.VarWithValue(arr2, arr, "eqcsfield") Equal(t, errs, nil) errs = validate.VarWithValue(now2, now, "eqcsfield") Equal(t, errs, nil) errs = validate.VarWithValue(arr3, arr, "eqcsfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "eqcsfield") type SInner struct { Name string } type TStruct struct { Inner *SInner CreatedAt *time.Time `validate:"eqcsfield=Inner"` } sinner := &SInner{ Name: "NAME", } test2 := &TStruct{ Inner: sinner, CreatedAt: &now, } errs = validate.Struct(test2) NotEqual(t, errs, nil) AssertError(t, errs, "TStruct.CreatedAt", "TStruct.CreatedAt", "CreatedAt", "CreatedAt", "eqcsfield") test2.Inner = nil errs = validate.Struct(test2) NotEqual(t, errs, nil) AssertError(t, errs, "TStruct.CreatedAt", "TStruct.CreatedAt", "CreatedAt", "CreatedAt", "eqcsfield") errs = validate.VarWithValue(nil, 1, "eqcsfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "eqcsfield") // Tests for time.Duration type. // -- Validations for variables of time.Duration type. errs = validate.VarWithValue(time.Hour, time.Hour, "eqcsfield") Equal(t, errs, nil) errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "eqcsfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "eqcsfield") errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "eqcsfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "eqcsfield") errs = validate.VarWithValue(time.Duration(0), time.Hour, "omitempty,eqcsfield") Equal(t, errs, nil) // -- Validations for a struct and an inner struct with time.Duration type fields. type TimeDurationInner struct { Duration time.Duration } var timeDurationInner *TimeDurationInner type TimeDurationTest struct { Inner *TimeDurationInner Duration time.Duration `validate:"eqcsfield=Inner.Duration"` } var timeDurationTest *TimeDurationTest timeDurationInner = &TimeDurationInner{time.Hour} timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationInner = &TimeDurationInner{time.Hour - time.Minute} timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "eqcsfield") timeDurationInner = &TimeDurationInner{time.Hour + time.Minute} timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "eqcsfield") type TimeDurationOmitemptyTest struct { Inner *TimeDurationInner Duration time.Duration `validate:"omitempty,eqcsfield=Inner.Duration"` } var timeDurationOmitemptyTest *TimeDurationOmitemptyTest timeDurationInner = &TimeDurationInner{time.Hour} timeDurationOmitemptyTest = &TimeDurationOmitemptyTest{timeDurationInner, time.Duration(0)} errs = validate.Struct(timeDurationOmitemptyTest) Equal(t, errs, nil) } func TestCrossNamespaceFieldValidation(t *testing.T) { type SliceStruct struct { Name string } type Inner struct { CreatedAt *time.Time Slice []string SliceStructs []*SliceStruct SliceSlice [][]string SliceSliceStruct [][]*SliceStruct SliceMap []map[string]string Map map[string]string MapMap map[string]map[string]string MapStructs map[string]*SliceStruct MapMapStruct map[string]map[string]*SliceStruct MapSlice map[string][]string MapInt map[int]string MapInt8 map[int8]string MapInt16 map[int16]string MapInt32 map[int32]string MapInt64 map[int64]string MapUint map[uint]string MapUint8 map[uint8]string MapUint16 map[uint16]string MapUint32 map[uint32]string MapUint64 map[uint64]string MapFloat32 map[float32]string MapFloat64 map[float64]string MapBool map[bool]string } type Test struct { Inner *Inner CreatedAt *time.Time } now := time.Now() inner := &Inner{ CreatedAt: &now, Slice: []string{"val1", "val2", "val3"}, SliceStructs: []*SliceStruct{{Name: "name1"}, {Name: "name2"}, {Name: "name3"}}, SliceSlice: [][]string{{"1", "2", "3"}, {"4", "5", "6"}, {"7", "8", "9"}}, SliceSliceStruct: [][]*SliceStruct{{{Name: "name1"}, {Name: "name2"}, {Name: "name3"}}, {{Name: "name4"}, {Name: "name5"}, {Name: "name6"}}, {{Name: "name7"}, {Name: "name8"}, {Name: "name9"}}}, SliceMap: []map[string]string{{"key1": "val1", "key2": "val2", "key3": "val3"}, {"key4": "val4", "key5": "val5", "key6": "val6"}}, Map: map[string]string{"key1": "val1", "key2": "val2", "key3": "val3"}, MapStructs: map[string]*SliceStruct{"key1": {Name: "name1"}, "key2": {Name: "name2"}, "key3": {Name: "name3"}}, MapMap: map[string]map[string]string{"key1": {"key1-1": "val1"}, "key2": {"key2-1": "val2"}, "key3": {"key3-1": "val3"}}, MapMapStruct: map[string]map[string]*SliceStruct{"key1": {"key1-1": {Name: "name1"}}, "key2": {"key2-1": {Name: "name2"}}, "key3": {"key3-1": {Name: "name3"}}}, MapSlice: map[string][]string{"key1": {"1", "2", "3"}, "key2": {"4", "5", "6"}, "key3": {"7", "8", "9"}}, MapInt: map[int]string{1: "val1", 2: "val2", 3: "val3"}, MapInt8: map[int8]string{1: "val1", 2: "val2", 3: "val3"}, MapInt16: map[int16]string{1: "val1", 2: "val2", 3: "val3"}, MapInt32: map[int32]string{1: "val1", 2: "val2", 3: "val3"}, MapInt64: map[int64]string{1: "val1", 2: "val2", 3: "val3"}, MapUint: map[uint]string{1: "val1", 2: "val2", 3: "val3"}, MapUint8: map[uint8]string{1: "val1", 2: "val2", 3: "val3"}, MapUint16: map[uint16]string{1: "val1", 2: "val2", 3: "val3"}, MapUint32: map[uint32]string{1: "val1", 2: "val2", 3: "val3"}, MapUint64: map[uint64]string{1: "val1", 2: "val2", 3: "val3"}, MapFloat32: map[float32]string{1.01: "val1", 2.02: "val2", 3.03: "val3"}, MapFloat64: map[float64]string{1.01: "val1", 2.02: "val2", 3.03: "val3"}, MapBool: map[bool]string{true: "val1", false: "val2"}, } test := &Test{ Inner: inner, CreatedAt: &now, } val := reflect.ValueOf(test) vd := New() v := &validate{ v: vd, } current, kind, _, ok := v.getStructFieldOKInternal(val, "Inner.CreatedAt") Equal(t, ok, true) Equal(t, kind, reflect.Struct) tm, ok := current.Interface().(time.Time) Equal(t, ok, true) Equal(t, tm, now) current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.Slice[1]") Equal(t, ok, true) Equal(t, kind, reflect.String) Equal(t, current.String(), "val2") _, _, _, ok = v.getStructFieldOKInternal(val, "Inner.CrazyNonExistantField") Equal(t, ok, false) _, _, _, ok = v.getStructFieldOKInternal(val, "Inner.Slice[101]") Equal(t, ok, false) current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.Map[key3]") Equal(t, ok, true) Equal(t, kind, reflect.String) Equal(t, current.String(), "val3") current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapMap[key2][key2-1]") Equal(t, ok, true) Equal(t, kind, reflect.String) Equal(t, current.String(), "val2") current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapStructs[key2].Name") Equal(t, ok, true) Equal(t, kind, reflect.String) Equal(t, current.String(), "name2") current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapMapStruct[key3][key3-1].Name") Equal(t, ok, true) Equal(t, kind, reflect.String) Equal(t, current.String(), "name3") current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.SliceSlice[2][0]") Equal(t, ok, true) Equal(t, kind, reflect.String) Equal(t, current.String(), "7") current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.SliceSliceStruct[2][1].Name") Equal(t, ok, true) Equal(t, kind, reflect.String) Equal(t, current.String(), "name8") current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.SliceMap[1][key5]") Equal(t, ok, true) Equal(t, kind, reflect.String) Equal(t, current.String(), "val5") current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapSlice[key3][2]") Equal(t, ok, true) Equal(t, kind, reflect.String) Equal(t, current.String(), "9") current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapInt[2]") Equal(t, ok, true) Equal(t, kind, reflect.String) Equal(t, current.String(), "val2") current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapInt8[2]") Equal(t, ok, true) Equal(t, kind, reflect.String) Equal(t, current.String(), "val2") current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapInt16[2]") Equal(t, ok, true) Equal(t, kind, reflect.String) Equal(t, current.String(), "val2") current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapInt32[2]") Equal(t, ok, true) Equal(t, kind, reflect.String) Equal(t, current.String(), "val2") current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapInt64[2]") Equal(t, ok, true) Equal(t, kind, reflect.String) Equal(t, current.String(), "val2") current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapUint[2]") Equal(t, ok, true) Equal(t, kind, reflect.String) Equal(t, current.String(), "val2") current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapUint8[2]") Equal(t, ok, true) Equal(t, kind, reflect.String) Equal(t, current.String(), "val2") current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapUint16[2]") Equal(t, ok, true) Equal(t, kind, reflect.String) Equal(t, current.String(), "val2") current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapUint32[2]") Equal(t, ok, true) Equal(t, kind, reflect.String) Equal(t, current.String(), "val2") current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapUint64[2]") Equal(t, ok, true) Equal(t, kind, reflect.String) Equal(t, current.String(), "val2") current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapFloat32[3.03]") Equal(t, ok, true) Equal(t, kind, reflect.String) Equal(t, current.String(), "val3") current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapFloat64[2.02]") Equal(t, ok, true) Equal(t, kind, reflect.String) Equal(t, current.String(), "val2") current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.MapBool[true]") Equal(t, ok, true) Equal(t, kind, reflect.String) Equal(t, current.String(), "val1") inner = &Inner{ CreatedAt: &now, Slice: []string{"val1", "val2", "val3"}, SliceStructs: []*SliceStruct{{Name: "name1"}, {Name: "name2"}, nil}, SliceSlice: [][]string{{"1", "2", "3"}, {"4", "5", "6"}, {"7", "8", "9"}}, SliceSliceStruct: [][]*SliceStruct{{{Name: "name1"}, {Name: "name2"}, {Name: "name3"}}, {{Name: "name4"}, {Name: "name5"}, {Name: "name6"}}, {{Name: "name7"}, {Name: "name8"}, {Name: "name9"}}}, SliceMap: []map[string]string{{"key1": "val1", "key2": "val2", "key3": "val3"}, {"key4": "val4", "key5": "val5", "key6": "val6"}}, Map: map[string]string{"key1": "val1", "key2": "val2", "key3": "val3"}, MapStructs: map[string]*SliceStruct{"key1": {Name: "name1"}, "key2": {Name: "name2"}, "key3": {Name: "name3"}}, MapMap: map[string]map[string]string{"key1": {"key1-1": "val1"}, "key2": {"key2-1": "val2"}, "key3": {"key3-1": "val3"}}, MapMapStruct: map[string]map[string]*SliceStruct{"key1": {"key1-1": {Name: "name1"}}, "key2": {"key2-1": {Name: "name2"}}, "key3": {"key3-1": {Name: "name3"}}}, MapSlice: map[string][]string{"key1": {"1", "2", "3"}, "key2": {"4", "5", "6"}, "key3": {"7", "8", "9"}}, } test = &Test{ Inner: inner, CreatedAt: nil, } val = reflect.ValueOf(test) current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.SliceStructs[2]") Equal(t, ok, true) Equal(t, kind, reflect.Ptr) Equal(t, current.String(), "<*validator.SliceStruct Value>") Equal(t, current.IsNil(), true) current, kind, _, ok = v.getStructFieldOKInternal(val, "Inner.SliceStructs[2].Name") Equal(t, ok, false) Equal(t, kind, reflect.Ptr) Equal(t, current.String(), "<*validator.SliceStruct Value>") Equal(t, current.IsNil(), true) // Test that invalid namespace on primitive type returns found=false instead of panicking // This enables cross-field validators like required_if to work with ValidateMap _, kind, _, ok = v.getStructFieldOKInternal(reflect.ValueOf(1), "crazyinput") Equal(t, ok, false) Equal(t, kind, reflect.Int) } func TestExistsValidation(t *testing.T) { jsonText := "{ \"truthiness2\": true }" type Thing struct { Truthiness *bool `json:"truthiness" validate:"required"` } var ting Thing err := json.Unmarshal([]byte(jsonText), &ting) Equal(t, err, nil) NotEqual(t, ting, nil) Equal(t, ting.Truthiness, nil) validate := New() errs := validate.Struct(ting) NotEqual(t, errs, nil) AssertError(t, errs, "Thing.Truthiness", "Thing.Truthiness", "Truthiness", "Truthiness", "required") jsonText = "{ \"truthiness\": true }" err = json.Unmarshal([]byte(jsonText), &ting) Equal(t, err, nil) NotEqual(t, ting, nil) Equal(t, ting.Truthiness, true) errs = validate.Struct(ting) Equal(t, errs, nil) } func TestSQLValue2Validation(t *testing.T) { validate := New() validate.RegisterCustomTypeFunc(ValidateValuerType, valuer{}, (*driver.Valuer)(nil), sql.NullString{}, sql.NullInt64{}, sql.NullBool{}, sql.NullFloat64{}) validate.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{}) validate.RegisterCustomTypeFunc(OverrideIntTypeForSomeReason, 1) val := valuer{ Name: "", } errs := validate.Var(val, "required") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "required") val.Name = "Valid Name" errs = validate.VarCtx(context.Background(), val, "required") Equal(t, errs, nil) val.Name = "errorme" PanicMatches(t, func() { _ = validate.Var(val, "required") }, "SQL Driver Valuer error: some kind of error") myVal := valuer{ Name: "", } errs = validate.Var(myVal, "required") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "required") cust := MadeUpCustomType{ FirstName: "Joey", LastName: "Bloggs", } c := CustomMadeUpStruct{MadeUp: cust, OverriddenInt: 2} errs = validate.Struct(c) Equal(t, errs, nil) c.MadeUp.FirstName = "" c.OverriddenInt = 1 errs = validate.Struct(c) NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 2) AssertError(t, errs, "CustomMadeUpStruct.MadeUp", "CustomMadeUpStruct.MadeUp", "MadeUp", "MadeUp", "required") AssertError(t, errs, "CustomMadeUpStruct.OverriddenInt", "CustomMadeUpStruct.OverriddenInt", "OverriddenInt", "OverriddenInt", "gt") } func TestSQLValueValidation(t *testing.T) { validate := New() validate.RegisterCustomTypeFunc(ValidateValuerType, (*driver.Valuer)(nil), valuer{}) validate.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{}) validate.RegisterCustomTypeFunc(OverrideIntTypeForSomeReason, 1) val := valuer{ Name: "", } errs := validate.Var(val, "required") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "required") val.Name = "Valid Name" errs = validate.Var(val, "required") Equal(t, errs, nil) val.Name = "errorme" PanicMatches(t, func() { errs = validate.Var(val, "required") }, "SQL Driver Valuer error: some kind of error") myVal := valuer{ Name: "", } errs = validate.Var(myVal, "required") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "required") cust := MadeUpCustomType{ FirstName: "Joey", LastName: "Bloggs", } c := CustomMadeUpStruct{MadeUp: cust, OverriddenInt: 2} errs = validate.Struct(c) Equal(t, errs, nil) c.MadeUp.FirstName = "" c.OverriddenInt = 1 errs = validate.Struct(c) NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 2) AssertError(t, errs, "CustomMadeUpStruct.MadeUp", "CustomMadeUpStruct.MadeUp", "MadeUp", "MadeUp", "required") AssertError(t, errs, "CustomMadeUpStruct.OverriddenInt", "CustomMadeUpStruct.OverriddenInt", "OverriddenInt", "OverriddenInt", "gt") // Test for empty field on structs without tags type InvalidValuePanicSafetyTest struct { V valuer } errs = validate.Struct(InvalidValuePanicSafetyTest{}) Equal(t, errs, nil) } func TestMACValidation(t *testing.T) { tests := []struct { param string expected bool }{ {"3D:F2:C9:A6:B3:4F", true}, {"3D-F2-C9-A6-B3:4F", false}, {"123", false}, {"", false}, {"abacaba", false}, {"00:25:96:FF:FE:12:34:56", true}, {"0025:96FF:FE12:3456", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "mac") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d mac failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d mac failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "mac" { t.Fatalf("Index: %d mac failed Error: %s", i, errs) } } } } } func TestIPValidation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"10.0.0.1", true}, {"172.16.0.1", true}, {"192.168.0.1", true}, {"192.168.255.254", true}, {"192.168.255.256", false}, {"172.16.255.254", true}, {"172.16.256.255", false}, {"2001:cdba:0000:0000:0000:0000:3257:9652", true}, {"2001:cdba:0:0:0:0:3257:9652", true}, {"2001:cdba::3257:9652", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "ip") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d ip failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d ip failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "ip" { t.Fatalf("Index: %d ip failed Error: %s", i, errs) } } } } } func TestIPv6Validation(t *testing.T) { tests := []struct { param string expected bool }{ {"10.0.0.1", false}, {"172.16.0.1", false}, {"192.168.0.1", false}, {"192.168.255.254", false}, {"192.168.255.256", false}, {"172.16.255.254", false}, {"172.16.256.255", false}, {"2001:cdba:0000:0000:0000:0000:3257:9652", true}, {"2001:cdba:0:0:0:0:3257:9652", true}, {"2001:cdba::3257:9652", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "ipv6") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d ipv6 failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d ipv6 failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "ipv6" { t.Fatalf("Index: %d ipv6 failed Error: %s", i, errs) } } } } } func TestIPv4Validation(t *testing.T) { tests := []struct { param string expected bool }{ {"10.0.0.1", true}, {"172.16.0.1", true}, {"192.168.0.1", true}, {"192.168.255.254", true}, {"192.168.255.256", false}, {"172.16.255.254", true}, {"172.16.256.255", false}, {"2001:cdba:0000:0000:0000:0000:3257:9652", false}, {"2001:cdba:0:0:0:0:3257:9652", false}, {"2001:cdba::3257:9652", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "ipv4") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d ipv4 failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d ipv4 failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "ipv4" { t.Fatalf("Index: %d ipv4 failed Error: %s", i, errs) } } } } } func TestCIDRValidation(t *testing.T) { tests := []struct { param string expected bool }{ {"10.0.0.0/0", true}, {"10.0.0.1/8", true}, {"172.16.0.1/16", true}, {"192.168.0.1/24", true}, {"192.168.255.254/24", true}, {"192.168.255.254/48", false}, {"192.168.255.256/24", false}, {"172.16.255.254/16", true}, {"172.16.256.255/16", false}, {"2001:cdba:0000:0000:0000:0000:3257:9652/64", true}, {"2001:cdba:0000:0000:0000:0000:3257:9652/256", false}, {"2001:cdba:0:0:0:0:3257:9652/32", true}, {"2001:cdba::3257:9652/16", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "cidr") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d cidr failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d cidr failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "cidr" { t.Fatalf("Index: %d cidr failed Error: %s", i, errs) } } } } } func TestCIDRv6Validation(t *testing.T) { tests := []struct { param string expected bool }{ {"10.0.0.0/0", false}, {"10.0.0.1/8", false}, {"172.16.0.1/16", false}, {"192.168.0.1/24", false}, {"192.168.255.254/24", false}, {"192.168.255.254/48", false}, {"192.168.255.256/24", false}, {"172.16.255.254/16", false}, {"172.16.256.255/16", false}, {"2001:cdba:0000:0000:0000:0000:3257:9652/64", true}, {"2001:cdba:0000:0000:0000:0000:3257:9652/256", false}, {"2001:cdba:0:0:0:0:3257:9652/32", true}, {"2001:cdba::3257:9652/16", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "cidrv6") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d cidrv6 failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d cidrv6 failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "cidrv6" { t.Fatalf("Index: %d cidrv6 failed Error: %s", i, errs) } } } } } func TestCIDRv4Validation(t *testing.T) { tests := []struct { param string expected bool }{ {"0.0.0.0/0", true}, {"10.0.0.0/0", false}, {"10.0.0.0/8", true}, {"10.0.0.1/8", false}, {"172.16.0.0/16", true}, {"172.16.0.1/16", false}, {"192.168.0.0/24", true}, {"192.168.0.1/24", false}, {"192.168.255.0/24", true}, {"192.168.255.254/24", false}, {"192.168.255.254/48", false}, {"192.168.255.256/24", false}, {"172.16.0.0/16", true}, {"172.16.255.254/16", false}, {"172.16.256.255/16", false}, {"2001:cdba:0000:0000:0000:0000:3257:9652/64", false}, {"2001:cdba:0000:0000:0000:0000:3257:9652/256", false}, {"2001:cdba:0:0:0:0:3257:9652/32", false}, {"2001:cdba::3257:9652/16", false}, {"172.56.1.0/16", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "cidrv4") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d cidrv4 failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d cidrv4 failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "cidrv4" { t.Fatalf("Index: %d cidrv4 failed Error: %s", i, errs) } } } } } func TestTCPAddrValidation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {":80", false}, {"127.0.0.1:80", true}, {"[::1]:80", true}, {"256.0.0.0:1", false}, {"[::1]", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "tcp_addr") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d tcp_addr failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d tcp_addr failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "tcp_addr" { t.Fatalf("Index: %d tcp_addr failed Error: %s", i, errs) } } } } } func TestTCP6AddrValidation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {":80", false}, {"127.0.0.1:80", false}, {"[::1]:80", true}, {"256.0.0.0:1", false}, {"[::1]", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "tcp6_addr") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d tcp6_addr failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d tcp6_addr failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "tcp6_addr" { t.Fatalf("Index: %d tcp6_addr failed Error: %s", i, errs) } } } } } func TestTCP4AddrValidation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {":80", false}, {"127.0.0.1:80", true}, {"[::1]:80", false}, // https://github.com/golang/go/issues/14037 {"256.0.0.0:1", false}, {"[::1]", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "tcp4_addr") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d tcp4_addr failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Log(test.param, IsEqual(errs, nil)) t.Fatalf("Index: %d tcp4_addr failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "tcp4_addr" { t.Fatalf("Index: %d tcp4_addr failed Error: %s", i, errs) } } } } } func TestUDPAddrValidation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {":80", false}, {"127.0.0.1:80", true}, {"[::1]:80", true}, {"256.0.0.0:1", false}, {"[::1]", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "udp_addr") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d udp_addr failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d udp_addr failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "udp_addr" { t.Fatalf("Index: %d udp_addr failed Error: %s", i, errs) } } } } } func TestUDP6AddrValidation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {":80", false}, {"127.0.0.1:80", false}, {"[::1]:80", true}, {"256.0.0.0:1", false}, {"[::1]", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "udp6_addr") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d udp6_addr failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d udp6_addr failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "udp6_addr" { t.Fatalf("Index: %d udp6_addr failed Error: %s", i, errs) } } } } } func TestUDP4AddrValidation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {":80", false}, {"127.0.0.1:80", true}, {"[::1]:80", false}, // https://github.com/golang/go/issues/14037 {"256.0.0.0:1", false}, {"[::1]", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "udp4_addr") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d udp4_addr failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Log(test.param, IsEqual(errs, nil)) t.Fatalf("Index: %d udp4_addr failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "udp4_addr" { t.Fatalf("Index: %d udp4_addr failed Error: %s", i, errs) } } } } } func TestIPAddrValidation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"127.0.0.1", true}, {"127.0.0.1:80", false}, {"::1", true}, {"256.0.0.0", false}, {"localhost", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "ip_addr") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d ip_addr failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d ip_addr failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "ip_addr" { t.Fatalf("Index: %d ip_addr failed Error: %s", i, errs) } } } } } func TestIP6AddrValidation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"127.0.0.1", false}, // https://github.com/golang/go/issues/14037 {"127.0.0.1:80", false}, {"::1", true}, {"0:0:0:0:0:0:0:1", true}, {"256.0.0.0", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "ip6_addr") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d ip6_addr failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d ip6_addr failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "ip6_addr" { t.Fatalf("Index: %d ip6_addr failed Error: %s", i, errs) } } } } } func TestIP4AddrValidation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"127.0.0.1", true}, {"127.0.0.1:80", false}, {"::1", false}, // https://github.com/golang/go/issues/14037 {"256.0.0.0", false}, {"localhost", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "ip4_addr") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d ip4_addr failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Log(test.param, IsEqual(errs, nil)) t.Fatalf("Index: %d ip4_addr failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "ip4_addr" { t.Fatalf("Index: %d ip4_addr failed Error: %s", i, errs) } } } } } func TestUnixAddrValidation(t *testing.T) { tests := []struct { param string expected bool }{ {"", true}, {"v.sock", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "unix_addr") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d unix_addr failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Log(test.param, IsEqual(errs, nil)) t.Fatalf("Index: %d unix_addr failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "unix_addr" { t.Fatalf("Index: %d unix_addr failed Error: %s", i, errs) } } } } } func TestUnixDomainSocketExistsValidation(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("Unix domain sockets are not supported on Windows") } validate := New() t.Run("empty", func(t *testing.T) { errs := validate.Var("", "uds_exists") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "uds_exists") }) t.Run("non_existent", func(t *testing.T) { errs := validate.Var("/tmp/nonexistent.sock", "uds_exists") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "uds_exists") }) t.Run("sock_file", func(t *testing.T) { sockPath := "/tmp/test_validator.sock" var lc net.ListenConfig listener, err := lc.Listen(t.Context(), "unix", sockPath) if err != nil { t.Fatalf("Failed to create test socket: %v", err) } defer func() { _ = os.Remove(sockPath) _ = listener.Close() }() errs := validate.Var(sockPath, "uds_exists") Equal(t, errs, nil) }) t.Run("regular_file", func(t *testing.T) { regularFile := "/tmp/test_validator_regular.txt" if err := os.WriteFile(regularFile, []byte("test"), 0644); err != nil { t.Fatalf("Failed to create regular file: %v", err) } defer func() { _ = os.Remove(regularFile) }() errs := validate.Var(regularFile, "uds_exists") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "uds_exists") }) t.Run("directory", func(t *testing.T) { dirPath := "/tmp/test_validator_dir" if err := os.Mkdir(dirPath, 0755); err != nil && !os.IsExist(err) { t.Fatalf("Failed to create directory: %v", err) } defer func() { _ = os.RemoveAll(dirPath) }() errs := validate.Var(dirPath, "uds_exists") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "uds_exists") }) // only supported on linux t.Run("abstract_sockets", func(t *testing.T) { if runtime.GOOS != "linux" { return } t.Run("non_existent", func(t *testing.T) { errs := validate.Var("@nonexistent_abstract_socket", "uds_exists") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "uds_exists") }) t.Run("existing", func(t *testing.T) { abstractSockName := "@test_abstract_socket_" + fmt.Sprintf("%d", time.Now().UnixNano()) var lc net.ListenConfig abstractListener, err := lc.Listen(t.Context(), "unix", "\x00"+abstractSockName[1:]) if err != nil { t.Fatalf("Failed to create abstract socket: %v", err) } defer func() { _ = abstractListener.Close() }() errs := validate.Var(abstractSockName, "uds_exists") Equal(t, errs, nil) }) }) } func TestSliceMapArrayChanFuncPtrInterfaceRequiredValidation(t *testing.T) { validate := New() var m map[string]string errs := validate.Var(m, "required") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "required") m = map[string]string{} errs = validate.Var(m, "required") Equal(t, errs, nil) var arr [5]string errs = validate.Var(arr, "required") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "required") arr[0] = "ok" errs = validate.Var(arr, "required") Equal(t, errs, nil) var s []string errs = validate.Var(s, "required") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "required") s = []string{} errs = validate.Var(s, "required") Equal(t, errs, nil) var c chan string errs = validate.Var(c, "required") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "required") c = make(chan string) errs = validate.Var(c, "required") Equal(t, errs, nil) var tst *int errs = validate.Var(tst, "required") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "required") one := 1 tst = &one errs = validate.Var(tst, "required") Equal(t, errs, nil) var iface interface{} errs = validate.Var(iface, "required") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "required") errs = validate.Var(iface, "omitempty,required") Equal(t, errs, nil) errs = validate.Var(iface, "") Equal(t, errs, nil) errs = validate.VarWithValue(nil, iface, "") Equal(t, errs, nil) var f func(string) errs = validate.Var(f, "required") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "required") f = func(name string) {} errs = validate.Var(f, "required") Equal(t, errs, nil) } func TestDatePtrValidationIssueValidation(t *testing.T) { type Test struct { LastViewed *time.Time Reminder *time.Time } test := &Test{} validate := New() errs := validate.Struct(test) Equal(t, errs, nil) } func TestCommaAndPipeObfuscationValidation(t *testing.T) { s := "My Name Is, |joeybloggs|" validate := New() errs := validate.Var(s, "excludesall=0x2C") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "excludesall") errs = validate.Var(s, "excludesall=0x7C") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "excludesall") } func TestBadKeyValidation(t *testing.T) { type Test struct { Name string `validate:"required, "` } tst := &Test{ Name: "test", } validate := New() PanicMatches(t, func() { _ = validate.Struct(tst) }, "Undefined validation function ' ' on field 'Name'") type Test2 struct { Name string `validate:"required,,len=2"` } tst2 := &Test2{ Name: "test", } PanicMatches(t, func() { _ = validate.Struct(tst2) }, "Invalid validation tag on field 'Name'") } func TestInterfaceErrValidation(t *testing.T) { var v2 interface{} = 1 var v1 = v2 validate := New() errs := validate.Var(v1, "len=1") Equal(t, errs, nil) errs = validate.Var(v2, "len=1") Equal(t, errs, nil) type ExternalCMD struct { Userid string `json:"userid"` Action uint32 `json:"action"` Data interface{} `json:"data,omitempty" validate:"required"` } s := &ExternalCMD{ Userid: "123456", Action: 10000, // Data: 1, } errs = validate.Struct(s) NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "ExternalCMD.Data", "ExternalCMD.Data", "Data", "Data", "required") type ExternalCMD2 struct { Userid string `json:"userid"` Action uint32 `json:"action"` Data interface{} `json:"data,omitempty" validate:"len=1"` } s2 := &ExternalCMD2{ Userid: "123456", Action: 10000, // Data: 1, } errs = validate.Struct(s2) NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "ExternalCMD2.Data", "ExternalCMD2.Data", "Data", "Data", "len") s3 := &ExternalCMD2{ Userid: "123456", Action: 10000, Data: 2, } errs = validate.Struct(s3) NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "ExternalCMD2.Data", "ExternalCMD2.Data", "Data", "Data", "len") type Inner struct { Name string `validate:"required"` } inner := &Inner{ Name: "", } s4 := &ExternalCMD{ Userid: "123456", Action: 10000, Data: inner, } errs = validate.Struct(s4) NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "ExternalCMD.Data.Name", "ExternalCMD.Data.Name", "Name", "Name", "required") type TestMapStructPtr struct { Errs map[int]interface{} `validate:"gt=0,dive,required"` } mip := map[int]interface{}{0: &Inner{"ok"}, 3: nil, 4: &Inner{"ok"}} msp := &TestMapStructPtr{ Errs: mip, } errs = validate.Struct(msp) NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "TestMapStructPtr.Errs[3]", "TestMapStructPtr.Errs[3]", "Errs[3]", "Errs[3]", "required") type TestMultiDimensionalStructs struct { Errs [][]interface{} `validate:"gt=0,dive,dive"` } var errStructArray [][]interface{} errStructArray = append(errStructArray, []interface{}{&Inner{"ok"}, &Inner{""}, &Inner{""}}) errStructArray = append(errStructArray, []interface{}{&Inner{"ok"}, &Inner{""}, &Inner{""}}) tms := &TestMultiDimensionalStructs{ Errs: errStructArray, } errs = validate.Struct(tms) NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 4) AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][1].Name", "TestMultiDimensionalStructs.Errs[0][1].Name", "Name", "Name", "required") AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][2].Name", "TestMultiDimensionalStructs.Errs[0][2].Name", "Name", "Name", "required") AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][1].Name", "TestMultiDimensionalStructs.Errs[1][1].Name", "Name", "Name", "required") AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][2].Name", "TestMultiDimensionalStructs.Errs[1][2].Name", "Name", "Name", "required") type TestMultiDimensionalStructsPtr2 struct { Errs [][]*Inner `validate:"gt=0,dive,dive,required"` } var errStructPtr2Array [][]*Inner errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}}) errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}}) errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, nil}) tmsp2 := &TestMultiDimensionalStructsPtr2{ Errs: errStructPtr2Array, } errs = validate.Struct(tmsp2) NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 6) AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][1].Name", "TestMultiDimensionalStructsPtr2.Errs[0][1].Name", "Name", "Name", "required") AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][2].Name", "TestMultiDimensionalStructsPtr2.Errs[0][2].Name", "Name", "Name", "required") AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][1].Name", "TestMultiDimensionalStructsPtr2.Errs[1][1].Name", "Name", "Name", "required") AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][2].Name", "TestMultiDimensionalStructsPtr2.Errs[1][2].Name", "Name", "Name", "required") AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][1].Name", "TestMultiDimensionalStructsPtr2.Errs[2][1].Name", "Name", "Name", "required") AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][2]", "TestMultiDimensionalStructsPtr2.Errs[2][2]", "Errs[2][2]", "Errs[2][2]", "required") m := map[int]interface{}{0: "ok", 3: "", 4: "ok"} errs = validate.Var(m, "len=3,dive,len=2") NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "[3]", "[3]", "[3]", "[3]", "len") errs = validate.Var(m, "len=2,dive,required") NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "", "", "", "", "len") arr := []interface{}{"ok", "", "ok"} errs = validate.Var(arr, "len=3,dive,len=2") NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "[1]", "[1]", "[1]", "[1]", "len") errs = validate.Var(arr, "len=2,dive,required") NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "", "", "", "", "len") type MyStruct struct { A, B string C interface{} } var a MyStruct a.A = "value" a.C = "nu" errs = validate.Struct(a) Equal(t, errs, nil) } func TestMapDiveValidation(t *testing.T) { validate := New() n := map[int]interface{}{0: nil} errs := validate.Var(n, "omitempty,required") Equal(t, errs, nil) m := map[int]string{0: "ok", 3: "", 4: "ok"} errs = validate.Var(m, "len=3,dive,required") NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "[3]", "[3]", "[3]", "[3]", "required") errs = validate.Var(m, "len=2,dive,required") NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "", "", "", "", "len") type Inner struct { Name string `validate:"required"` } type TestMapStruct struct { Errs map[int]Inner `validate:"gt=0,dive"` } mi := map[int]Inner{0: {"ok"}, 3: {""}, 4: {"ok"}} ms := &TestMapStruct{ Errs: mi, } errs = validate.Struct(ms) NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "TestMapStruct.Errs[3].Name", "TestMapStruct.Errs[3].Name", "Name", "Name", "required") // for full test coverage s := fmt.Sprint(errs.Error()) NotEqual(t, s, "") type TestMapInterface struct { Errs map[int]interface{} `validate:"dive"` } mit := map[int]interface{}{0: Inner{"ok"}, 1: Inner{""}, 3: nil, 5: "string", 6: 33} msi := &TestMapInterface{ Errs: mit, } errs = validate.Struct(msi) NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "TestMapInterface.Errs[1].Name", "TestMapInterface.Errs[1].Name", "Name", "Name", "required") type TestMapTimeStruct struct { Errs map[int]*time.Time `validate:"gt=0,dive,required"` } t1 := time.Now().UTC() mta := map[int]*time.Time{0: &t1, 3: nil, 4: nil} mt := &TestMapTimeStruct{ Errs: mta, } errs = validate.Struct(mt) NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 2) AssertError(t, errs, "TestMapTimeStruct.Errs[3]", "TestMapTimeStruct.Errs[3]", "Errs[3]", "Errs[3]", "required") AssertError(t, errs, "TestMapTimeStruct.Errs[4]", "TestMapTimeStruct.Errs[4]", "Errs[4]", "Errs[4]", "required") type TestMapStructPtr struct { Errs map[int]*Inner `validate:"gt=0,dive,required"` } mip := map[int]*Inner{0: {"ok"}, 3: nil, 4: {"ok"}} msp := &TestMapStructPtr{ Errs: mip, } errs = validate.Struct(msp) NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "TestMapStructPtr.Errs[3]", "TestMapStructPtr.Errs[3]", "Errs[3]", "Errs[3]", "required") type TestMapStructPtr2 struct { Errs map[int]*Inner `validate:"gt=0,dive,omitempty,required"` } mip2 := map[int]*Inner{0: {"ok"}, 3: nil, 4: {"ok"}} msp2 := &TestMapStructPtr2{ Errs: mip2, } errs = validate.Struct(msp2) Equal(t, errs, nil) v2 := New() v2.RegisterTagNameFunc(func(fld reflect.StructField) string { name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] if name == "-" { return "" } return name }) type MapDiveJSONTest struct { Map map[string]string `validate:"required,gte=1,dive,gte=1" json:"MyName"` } mdjt := &MapDiveJSONTest{ Map: map[string]string{ "Key1": "Value1", "Key2": "", }, } err := v2.Struct(mdjt) NotEqual(t, err, nil) errs = err.(ValidationErrors) fe := getError(errs, "MapDiveJSONTest.MyName[Key2]", "MapDiveJSONTest.Map[Key2]") NotEqual(t, fe, nil) Equal(t, fe.Tag(), "gte") Equal(t, fe.ActualTag(), "gte") Equal(t, fe.Field(), "MyName[Key2]") Equal(t, fe.StructField(), "Map[Key2]") } func TestArrayDiveValidation(t *testing.T) { validate := New() arr := []string{"ok", "", "ok"} errs := validate.Var(arr, "len=3,dive,required") NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "[1]", "[1]", "[1]", "[1]", "required") errs = validate.Var(arr, "len=2,dive,required") NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "", "", "", "", "len") type BadDive struct { Name string `validate:"dive"` } bd := &BadDive{ Name: "TEST", } PanicMatches(t, func() { _ = validate.Struct(bd) }, "dive error! can't dive on a non slice or map") type Test struct { Errs []string `validate:"gt=0,dive,required"` } test := &Test{ Errs: []string{"ok", "", "ok"}, } errs = validate.Struct(test) NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "Test.Errs[1]", "Test.Errs[1]", "Errs[1]", "Errs[1]", "required") test = &Test{ Errs: []string{"ok", "ok", ""}, } errs = validate.Struct(test) NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "Test.Errs[2]", "Test.Errs[2]", "Errs[2]", "Errs[2]", "required") type TestMultiDimensional struct { Errs [][]string `validate:"gt=0,dive,dive,required"` } var errArray [][]string errArray = append(errArray, []string{"ok", "", ""}) errArray = append(errArray, []string{"ok", "", ""}) tm := &TestMultiDimensional{ Errs: errArray, } errs = validate.Struct(tm) NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 4) AssertError(t, errs, "TestMultiDimensional.Errs[0][1]", "TestMultiDimensional.Errs[0][1]", "Errs[0][1]", "Errs[0][1]", "required") AssertError(t, errs, "TestMultiDimensional.Errs[0][2]", "TestMultiDimensional.Errs[0][2]", "Errs[0][2]", "Errs[0][2]", "required") AssertError(t, errs, "TestMultiDimensional.Errs[1][1]", "TestMultiDimensional.Errs[1][1]", "Errs[1][1]", "Errs[1][1]", "required") AssertError(t, errs, "TestMultiDimensional.Errs[1][2]", "TestMultiDimensional.Errs[1][2]", "Errs[1][2]", "Errs[1][2]", "required") type Inner struct { Name string `validate:"required"` } type TestMultiDimensionalStructs struct { Errs [][]Inner `validate:"gt=0,dive,dive"` } var errStructArray [][]Inner errStructArray = append(errStructArray, []Inner{{"ok"}, {""}, {""}}) errStructArray = append(errStructArray, []Inner{{"ok"}, {""}, {""}}) tms := &TestMultiDimensionalStructs{ Errs: errStructArray, } errs = validate.Struct(tms) NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 4) AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][1].Name", "TestMultiDimensionalStructs.Errs[0][1].Name", "Name", "Name", "required") AssertError(t, errs, "TestMultiDimensionalStructs.Errs[0][2].Name", "TestMultiDimensionalStructs.Errs[0][2].Name", "Name", "Name", "required") AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][1].Name", "TestMultiDimensionalStructs.Errs[1][1].Name", "Name", "Name", "required") AssertError(t, errs, "TestMultiDimensionalStructs.Errs[1][2].Name", "TestMultiDimensionalStructs.Errs[1][2].Name", "Name", "Name", "required") type TestMultiDimensionalStructsPtr struct { Errs [][]*Inner `validate:"gt=0,dive,dive"` } var errStructPtrArray [][]*Inner errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, {""}}) errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, {""}}) errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, nil}) tmsp := &TestMultiDimensionalStructsPtr{ Errs: errStructPtrArray, } errs = validate.Struct(tmsp) NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 5) AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[0][1].Name", "TestMultiDimensionalStructsPtr.Errs[0][1].Name", "Name", "Name", "required") AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[0][2].Name", "TestMultiDimensionalStructsPtr.Errs[0][2].Name", "Name", "Name", "required") AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[1][1].Name", "TestMultiDimensionalStructsPtr.Errs[1][1].Name", "Name", "Name", "required") AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[1][2].Name", "TestMultiDimensionalStructsPtr.Errs[1][2].Name", "Name", "Name", "required") AssertError(t, errs, "TestMultiDimensionalStructsPtr.Errs[2][1].Name", "TestMultiDimensionalStructsPtr.Errs[2][1].Name", "Name", "Name", "required") // for full test coverage s := fmt.Sprint(errs.Error()) NotEqual(t, s, "") type TestMultiDimensionalStructsPtr2 struct { Errs [][]*Inner `validate:"gt=0,dive,dive,required"` } var errStructPtr2Array [][]*Inner errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}}) errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}}) errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, nil}) tmsp2 := &TestMultiDimensionalStructsPtr2{ Errs: errStructPtr2Array, } errs = validate.Struct(tmsp2) NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 6) AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][1].Name", "TestMultiDimensionalStructsPtr2.Errs[0][1].Name", "Name", "Name", "required") AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[0][2].Name", "TestMultiDimensionalStructsPtr2.Errs[0][2].Name", "Name", "Name", "required") AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][1].Name", "TestMultiDimensionalStructsPtr2.Errs[1][1].Name", "Name", "Name", "required") AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[1][2].Name", "TestMultiDimensionalStructsPtr2.Errs[1][2].Name", "Name", "Name", "required") AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][1].Name", "TestMultiDimensionalStructsPtr2.Errs[2][1].Name", "Name", "Name", "required") AssertError(t, errs, "TestMultiDimensionalStructsPtr2.Errs[2][2]", "TestMultiDimensionalStructsPtr2.Errs[2][2]", "Errs[2][2]", "Errs[2][2]", "required") type TestMultiDimensionalStructsPtr3 struct { Errs [][]*Inner `validate:"gt=0,dive,dive,omitempty"` } var errStructPtr3Array [][]*Inner errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, {""}}) errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, {""}}) errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, nil}) tmsp3 := &TestMultiDimensionalStructsPtr3{ Errs: errStructPtr3Array, } errs = validate.Struct(tmsp3) NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 5) AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[0][1].Name", "TestMultiDimensionalStructsPtr3.Errs[0][1].Name", "Name", "Name", "required") AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[0][2].Name", "TestMultiDimensionalStructsPtr3.Errs[0][2].Name", "Name", "Name", "required") AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[1][1].Name", "TestMultiDimensionalStructsPtr3.Errs[1][1].Name", "Name", "Name", "required") AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[1][2].Name", "TestMultiDimensionalStructsPtr3.Errs[1][2].Name", "Name", "Name", "required") AssertError(t, errs, "TestMultiDimensionalStructsPtr3.Errs[2][1].Name", "TestMultiDimensionalStructsPtr3.Errs[2][1].Name", "Name", "Name", "required") type TestMultiDimensionalTimeTime struct { Errs [][]*time.Time `validate:"gt=0,dive,dive,required"` } var errTimePtr3Array [][]*time.Time t1 := time.Now().UTC() t2 := time.Now().UTC() t3 := time.Now().UTC().Add(time.Hour * 24) errTimePtr3Array = append(errTimePtr3Array, []*time.Time{&t1, &t2, &t3}) errTimePtr3Array = append(errTimePtr3Array, []*time.Time{&t1, &t2, nil}) errTimePtr3Array = append(errTimePtr3Array, []*time.Time{&t1, nil, nil}) tmtp3 := &TestMultiDimensionalTimeTime{ Errs: errTimePtr3Array, } errs = validate.Struct(tmtp3) NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 3) AssertError(t, errs, "TestMultiDimensionalTimeTime.Errs[1][2]", "TestMultiDimensionalTimeTime.Errs[1][2]", "Errs[1][2]", "Errs[1][2]", "required") AssertError(t, errs, "TestMultiDimensionalTimeTime.Errs[2][1]", "TestMultiDimensionalTimeTime.Errs[2][1]", "Errs[2][1]", "Errs[2][1]", "required") AssertError(t, errs, "TestMultiDimensionalTimeTime.Errs[2][2]", "TestMultiDimensionalTimeTime.Errs[2][2]", "Errs[2][2]", "Errs[2][2]", "required") type TestMultiDimensionalTimeTime2 struct { Errs [][]*time.Time `validate:"gt=0,dive,dive,required"` } var errTimeArray [][]*time.Time t1 = time.Now().UTC() t2 = time.Now().UTC() t3 = time.Now().UTC().Add(time.Hour * 24) errTimeArray = append(errTimeArray, []*time.Time{&t1, &t2, &t3}) errTimeArray = append(errTimeArray, []*time.Time{&t1, &t2, nil}) errTimeArray = append(errTimeArray, []*time.Time{&t1, nil, nil}) tmtp := &TestMultiDimensionalTimeTime2{ Errs: errTimeArray, } errs = validate.Struct(tmtp) NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 3) AssertError(t, errs, "TestMultiDimensionalTimeTime2.Errs[1][2]", "TestMultiDimensionalTimeTime2.Errs[1][2]", "Errs[1][2]", "Errs[1][2]", "required") AssertError(t, errs, "TestMultiDimensionalTimeTime2.Errs[2][1]", "TestMultiDimensionalTimeTime2.Errs[2][1]", "Errs[2][1]", "Errs[2][1]", "required") AssertError(t, errs, "TestMultiDimensionalTimeTime2.Errs[2][2]", "TestMultiDimensionalTimeTime2.Errs[2][2]", "Errs[2][2]", "Errs[2][2]", "required") } func TestNilStructPointerValidation(t *testing.T) { type Inner struct { Data string } type Outer struct { Inner *Inner `validate:"omitempty"` } inner := &Inner{ Data: "test", } outer := &Outer{ Inner: inner, } validate := New() errs := validate.Struct(outer) Equal(t, errs, nil) outer = &Outer{ Inner: nil, } errs = validate.Struct(outer) Equal(t, errs, nil) type Inner2 struct { Data string } type Outer2 struct { Inner2 *Inner2 `validate:"required"` } inner2 := &Inner2{ Data: "test", } outer2 := &Outer2{ Inner2: inner2, } errs = validate.Struct(outer2) Equal(t, errs, nil) outer2 = &Outer2{ Inner2: nil, } errs = validate.Struct(outer2) NotEqual(t, errs, nil) AssertError(t, errs, "Outer2.Inner2", "Outer2.Inner2", "Inner2", "Inner2", "required") type Inner3 struct { Data string } type Outer3 struct { Inner3 *Inner3 } inner3 := &Inner3{ Data: "test", } outer3 := &Outer3{ Inner3: inner3, } errs = validate.Struct(outer3) Equal(t, errs, nil) type Inner4 struct { Data string } type Outer4 struct { Inner4 *Inner4 `validate:"-"` } inner4 := &Inner4{ Data: "test", } outer4 := &Outer4{ Inner4: inner4, } errs = validate.Struct(outer4) Equal(t, errs, nil) } func TestSSNValidation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"00-90-8787", false}, {"66690-76", false}, {"191 60 2869", true}, {"191-60-2869", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "ssn") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d SSN failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d SSN failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "ssn" { t.Fatalf("Index: %d Latitude failed Error: %s", i, errs) } } } } } func TestLongitudeValidation(t *testing.T) { tests := []struct { param interface{} expected bool }{ {"", false}, {"-180.000", true}, {"180.1", false}, {"+73.234", true}, {"+382.3811", false}, {"23.11111111", true}, {uint(180), true}, {float32(-180.0), true}, {-180, true}, {180.1, false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "longitude") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d Longitude failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d Longitude failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "longitude" { t.Fatalf("Index: %d Longitude failed Error: %s", i, errs) } } } } PanicMatches(t, func() { _ = validate.Var(true, "longitude") }, "Bad field type bool") } func TestLatitudeValidation(t *testing.T) { tests := []struct { param interface{} expected bool }{ {"", false}, {"-90.000", true}, {"+90", true}, {"47.1231231", true}, {"+99.9", false}, {"108", false}, {uint(90), true}, {float32(-90.0), true}, {-90, true}, {90.1, false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "latitude") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d Latitude failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d Latitude failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "latitude" { t.Fatalf("Index: %d Latitude failed Error: %s", i, errs) } } } } PanicMatches(t, func() { _ = validate.Var(true, "latitude") }, "Bad field type bool") } func TestDataURIValidation(t *testing.T) { tests := []struct { param string expected bool }{ {"data:image/png;base64,TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4=", true}, {"data:text/plain;base64,Vml2YW11cyBmZXJtZW50dW0gc2VtcGVyIHBvcnRhLg==", true}, {"image/gif;base64,U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==", false}, { "data:image/gif;base64,MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuMPNS1Ufof9EW/M98FNw" + "UAKrwflsqVxaxQjBQnHQmiI7Vac40t8x7pIb8gLGV6wL7sBTJiPovJ0V7y7oc0Ye" + "rhKh0Rm4skP2z/jHwwZICgGzBvA0rH8xlhUiTvcwDCJ0kc+fh35hNt8srZQM4619" + "FTgB66Xmp4EtVyhpQV+t02g6NzK72oZI0vnAvqhpkxLeLiMCyrI416wHm5Tkukhx" + "QmcL2a6hNOyu0ixX/x2kSFXApEnVrJ+/IxGyfyw8kf4N2IZpW5nEP847lpfj0SZZ" + "Fwrd1mnfnDbYohX2zRptLy2ZUn06Qo9pkG5ntvFEPo9bfZeULtjYzIl6K8gJ2uGZ" + "HQIDAQAB", true, }, {"data:image/png;base64,12345", false}, {"", false}, {"data:text,:;base85,U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==", false}, {"data:image/jpeg;key=value;base64,UEsDBBQAAAAI", true}, {"data:image/jpeg;key=value,UEsDBBQAAAAI", true}, {"data:;base64;sdfgsdfgsdfasdfa=s,UEsDBBQAAAAI", true}, {"data:,UEsDBBQAAAAI", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "datauri") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d DataURI failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d DataURI failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "datauri" { t.Fatalf("Index: %d DataURI failed Error: %s", i, errs) } } } } } func TestMultibyteValidation(t *testing.T) { tests := []struct { param string expected bool }{ {"", true}, {"abc", false}, {"123", false}, {"<>@;.-=", false}, {"ひらがな・カタカナ、.漢字", true}, {"あいうえお foobar", true}, {"test@example.com", true}, {"test@example.com", true}, {"1234abcDExyz", true}, {"カタカナ", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "multibyte") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d Multibyte failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d Multibyte failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "multibyte" { t.Fatalf("Index: %d Multibyte failed Error: %s", i, errs) } } } } } func TestPrintableASCIIValidation(t *testing.T) { tests := []struct { param interface{} expected bool }{ {"", true}, {"foobar", false}, {"xyz098", false}, {"123456", false}, {"カタカナ", false}, {"foobar", true}, {"0987654321", true}, {"test@example.com", true}, {"1234abcDEF", true}, {"newline\n", false}, {"\x19test\x7F", false}, {[]int{3000}, false}, {1, false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "printascii") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d Printable ASCII failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d Printable ASCII failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "printascii" { t.Fatalf("Index: %d Printable ASCII failed Error: %s", i, errs) } } } } } func TestASCIIValidation(t *testing.T) { tests := []struct { param interface{} expected bool }{ {"", true}, {"foobar", false}, {"xyz098", false}, {"123456", false}, {"カタカナ", false}, {"foobar", true}, {"0987654321", true}, {"test@example.com", true}, {"1234abcDEF", true}, {"", true}, {[]int{3000}, false}, {1, false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "ascii") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d ASCII failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d ASCII failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "ascii" { t.Fatalf("Index: %d ASCII failed Error: %s", i, errs) } } } } } func TestUUID5Validation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false}, {"9c858901-8a57-4791-81fe-4c455b099bc9", false}, {"a987fbc9-4bed-3078-cf07-9141ba07c9f3", false}, {"987fbc97-4bed-5078-af07-9141ba07c9f3", true}, {"987fbc97-4bed-5078-9f07-9141ba07c9f3", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "uuid5") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d UUID5 failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d UUID5 failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "uuid5" { t.Fatalf("Index: %d UUID5 failed Error: %s", i, errs) } } } } } func TestUUID4Validation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false}, {"a987fbc9-4bed-5078-af07-9141ba07c9f3", false}, {"934859", false}, {"57b73598-8764-4ad0-a76a-679bb6640eb1", true}, {"625e63f3-58f5-40b7-83a1-a72ad31acffb", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "uuid4") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d UUID4 failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d UUID4 failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "uuid4" { t.Fatalf("Index: %d UUID4 failed Error: %s", i, errs) } } } } } func TestUUID3Validation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"412452646", false}, {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false}, {"a987fbc9-4bed-4078-8f07-9141ba07c9f3", false}, {"a987fbc9-4bed-3078-cf07-9141ba07c9f3", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "uuid3") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d UUID3 failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d UUID3 failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "uuid3" { t.Fatalf("Index: %d UUID3 failed Error: %s", i, errs) } } } } } type uuidTestType struct { val string } func (u uuidTestType) String() string { return u.val } type uuidAlias string func (u uuidAlias) String() string { return "This is a UUID " + string(u) } var ( _ fmt.Stringer = uuidTestType{} _ fmt.Stringer = uuidAlias("") ) func TestUUIDValidation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9f3", false}, {"a987fbc9-4bed-3078-cf07-9141ba07c9f3xxx", false}, {"a987fbc94bed3078cf079141ba07c9f3", false}, {"934859", false}, {"987fbc9-4bed-3078-cf07a-9141ba07c9f3", false}, {"aaaaaaaa-1111-1111-aaag-111111111111", false}, {"a987fbc9-4bed-3078-cf07-9141ba07c9f3", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "uuid") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d UUID failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d UUID failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "uuid" { t.Fatalf("Index: %d UUID failed Error: %s", i, errs) } } } } // Test UUID validation on uuid structs type that implements Stringer interface. structWithValidUUID := struct { UUID uuidTestType `validate:"uuid"` }{ UUID: uuidTestType{val: "a987fbc9-4bed-3078-cf07-9141ba07c9f3"}, } structWithInvalidUUID := struct { UUID uuidTestType `validate:"uuid"` }{ UUID: uuidTestType{val: "934859"}, } if err := validate.Struct(structWithValidUUID); err != nil { t.Fatalf("UUID failed Error: %s", err) } if err := validate.Struct(structWithInvalidUUID); err == nil { t.Fatal("UUID failed Error expected but received nil") } // Test on Alias type with Stringer interface. alias := uuidAlias("a987fbc9-4bed-3078-cf07-9141ba07c9f3") if err := validate.Var(alias, "uuid"); err != nil { t.Fatalf("UUID failed Error: %s", err) } } func TestUUID5RFC4122Validation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"xxxa987Fbc9-4bed-3078-cf07-9141ba07c9f3", false}, {"9c858901-8a57-4791-81Fe-4c455b099bc9", false}, {"a987Fbc9-4bed-3078-cf07-9141ba07c9f3", false}, {"987Fbc97-4bed-5078-af07-9141ba07c9f3", true}, {"987Fbc97-4bed-5078-9f07-9141ba07c9f3", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "uuid5_rfc4122") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d UUID5RFC4122 failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d UUID5RFC4122 failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "uuid5_rfc4122" { t.Fatalf("Index: %d UUID5RFC4122 failed Error: %s", i, errs) } } } } } func TestUUID4RFC4122Validation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9F3", false}, {"a987fbc9-4bed-5078-af07-9141ba07c9F3", false}, {"934859", false}, {"57b73598-8764-4ad0-a76A-679bb6640eb1", true}, {"625e63f3-58f5-40b7-83a1-a72ad31acFfb", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "uuid4_rfc4122") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d UUID4RFC4122 failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d UUID4RFC4122 failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "uuid4_rfc4122" { t.Fatalf("Index: %d UUID4RFC4122 failed Error: %s", i, errs) } } } } } func TestUUID3RFC4122Validation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"412452646", false}, {"xxxa987fbc9-4bed-3078-cf07-9141ba07c9F3", false}, {"a987fbc9-4bed-4078-8f07-9141ba07c9F3", false}, {"a987fbc9-4bed-3078-cf07-9141ba07c9F3", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "uuid3_rfc4122") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d UUID3RFC4122 failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d UUID3RFC4122 failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "uuid3_rfc4122" { t.Fatalf("Index: %d UUID3RFC4122 failed Error: %s", i, errs) } } } } } func TestUUIDRFC4122Validation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"xxxa987Fbc9-4bed-3078-cf07-9141ba07c9f3", false}, {"a987Fbc9-4bed-3078-cf07-9141ba07c9f3xxx", false}, {"a987Fbc94bed3078cf079141ba07c9f3", false}, {"934859", false}, {"987fbc9-4bed-3078-cf07a-9141ba07c9F3", false}, {"aaaaaaaa-1111-1111-aaaG-111111111111", false}, {"a987Fbc9-4bed-3078-cf07-9141ba07c9f3", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "uuid_rfc4122") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d UUIDRFC4122 failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d UUIDRFC4122 failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "uuid_rfc4122" { t.Fatalf("Index: %d UUIDRFC4122 failed Error: %s", i, errs) } } } } } func TestULIDValidation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"01BX5ZZKBKACT-V9WEVGEMMVRZ", false}, {"01bx5zzkbkactav9wevgemmvrz", true}, {"a987Fbc9-4bed-3078-cf07-9141ba07c9f3xxx", false}, {"01BX5ZZKBKACTAV9WEVGEMMVRZABC", false}, {"01BX5ZZKBKACTAV9WEVGEMMVRZABC", false}, {"0IBX5ZZKBKACTAV9WEVGEMMVRZ", false}, {"O1BX5ZZKBKACTAV9WEVGEMMVRZ", false}, {"01BX5ZZKBKACTAVLWEVGEMMVRZ", false}, {"01BX5ZZKBKACTAV9WEVGEMMVRZ", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "ulid") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d ULID failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d ULID failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "ulid" { t.Fatalf("Index: %d ULID failed Error: %s", i, errs) } } } } } func TestMD4Validation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"6f5902ac237024bdd0c176cb93063dc4", true}, {"6f5902ac237024bdd0c176cb93063dc-", false}, {"6f5902ac237024bdd0c176cb93063dc41", false}, {"6f5902ac237024bdd0c176cb93063dcC", false}, {"6f5902ac237024bdd0c176cb93063dc", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "md4") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d MD4 failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d MD4 failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "md4" { t.Fatalf("Index: %d MD4 failed Error: %s", i, errs) } } } } } func TestMD5Validation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"6f5902ac237024bdd0c176cb93063dc4", true}, {"6f5902ac237024bdd0c176cb93063dc-", false}, {"6f5902ac237024bdd0c176cb93063dc41", false}, {"6f5902ac237024bdd0c176cb93063dcC", false}, {"6f5902ac237024bdd0c176cb93063dc", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "md5") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d MD5 failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d MD5 failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "md5" { t.Fatalf("Index: %d MD5 failed Error: %s", i, errs) } } } } } func TestSHA256Validation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc4", true}, {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc-", false}, {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc41", false}, {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dcC", false}, {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "sha256") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d SHA256 failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d SHA256 failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "sha256" { t.Fatalf("Index: %d SHA256 failed Error: %s", i, errs) } } } } } func TestSHA384Validation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc4", true}, {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc-", false}, {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc41", false}, {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dcC", false}, {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "sha384") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d SHA384 failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d SHA384 failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "sha384" { t.Fatalf("Index: %d SHA384 failed Error: %s", i, errs) } } } } } func TestSHA512Validation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc4", true}, {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc-", false}, {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc41", false}, {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dcC", false}, {"6f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc46f5902ac237024bdd0c176cb93063dc", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "sha512") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d SHA512 failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d SHA512 failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "sha512" { t.Fatalf("Index: %d SHA512 failed Error: %s", i, errs) } } } } } func TestRIPEMD128Validation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"6f5902ac237024bdd0c176cb93063dc4", true}, {"6f5902ac237024bdd0c176cb93063dc-", false}, {"6f5902ac237024bdd0c176cb93063dc41", false}, {"6f5902ac237024bdd0c176cb93063dcC", false}, {"6f5902ac237024bdd0c176cb93063dc", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "ripemd128") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d RIPEMD128 failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d RIPEMD128 failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "ripemd128" { t.Fatalf("Index: %d RIPEMD128 failed Error: %s", i, errs) } } } } } func TestRIPEMD160Validation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"6f5902ac6f5902ac237024bdd0c176cb93063dc4", true}, {"6f5902ac6f5902ac237024bdd0c176cb93063dc-", false}, {"6f5902ac6f5902ac237024bdd0c176cb93063dc41", false}, {"6f5902ac6f5902ac237024bdd0c176cb93063dcC", false}, {"6f5902ac6f5902ac237024bdd0c176cb93063dc", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "ripemd160") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d RIPEMD160 failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d RIPEMD160 failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "ripemd160" { t.Fatalf("Index: %d RIPEMD160 failed Error: %s", i, errs) } } } } } func TestTIGER128Validation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"6f5902ac237024bdd0c176cb93063dc4", true}, {"6f5902ac237024bdd0c176cb93063dc-", false}, {"6f5902ac237024bdd0c176cb93063dc41", false}, {"6f5902ac237024bdd0c176cb93063dcC", false}, {"6f5902ac237024bdd0c176cb93063dc", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "tiger128") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d TIGER128 failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d TIGER128 failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "tiger128" { t.Fatalf("Index: %d TIGER128 failed Error: %s", i, errs) } } } } } func TestTIGER160Validation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"6f5902ac6f5902ac237024bdd0c176cb93063dc4", true}, {"6f5902ac6f5902ac237024bdd0c176cb93063dc-", false}, {"6f5902ac6f5902ac237024bdd0c176cb93063dc41", false}, {"6f5902ac6f5902ac237024bdd0c176cb93063dcC", false}, {"6f5902ac6f5902ac237024bdd0c176cb93063dc", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "tiger160") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d TIGER160 failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d TIGER160 failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "tiger160" { t.Fatalf("Index: %d TIGER160 failed Error: %s", i, errs) } } } } } func TestTIGER192Validation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"6f5902ac237024bd6f5902ac237024bdd0c176cb93063dc4", true}, {"6f5902ac237024bd6f5902ac237024bdd0c176cb93063dc-", false}, {"6f5902ac237024bd6f5902ac237024bdd0c176cb93063dc41", false}, {"6f5902ac237024bd6f5902ac237024bdd0c176cb93063dcC", false}, {"6f5902ac237024bd6f5902ac237024bdd0c176cb93063dc", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "tiger192") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d TIGER192 failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d TIGER192 failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "tiger192" { t.Fatalf("Index: %d TIGER192 failed Error: %s", i, errs) } } } } } func TestISBNValidation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"foo", false}, {"3836221195", true}, {"1-61729-085-8", true}, {"3 423 21412 0", true}, {"3 401 01319 X", true}, {"9784873113685", true}, {"978-4-87311-368-5", true}, {"978 3401013190", true}, {"978-3-8362-2119-1", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "isbn") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d ISBN failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d ISBN failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "isbn" { t.Fatalf("Index: %d ISBN failed Error: %s", i, errs) } } } } } func TestISBN13Validation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"foo", false}, {"3-8362-2119-5", false}, {"01234567890ab", false}, {"978 3 8362 2119 0", false}, {"9784873113685", true}, {"978-4-87311-368-5", true}, {"978 3401013190", true}, {"978-3-8362-2119-1", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "isbn13") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d ISBN13 failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d ISBN13 failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "isbn13" { t.Fatalf("Index: %d ISBN13 failed Error: %s", i, errs) } } } } } func TestISBN10Validation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"foo", false}, {"3423214121", false}, {"978-3836221191", false}, {"3-423-21412-1", false}, {"3 423 21412 1", false}, {"3836221195", true}, {"1-61729-085-8", true}, {"3 423 21412 0", true}, {"3 401 01319 X", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "isbn10") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d ISBN10 failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d ISBN10 failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "isbn10" { t.Fatalf("Index: %d ISBN10 failed Error: %s", i, errs) } } } } } func TestISSNValidation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"foo", false}, {"20519990", false}, {"2051-9991", false}, {"2051-999X", false}, {"1050-124X", true}, {"0317-8471", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "issn") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d ISSN failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d ISSN failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "issn" { t.Fatalf("Index: %d ISSN failed Error: %s", i, errs) } } } } } func TestExcludesRuneValidation(t *testing.T) { tests := []struct { Value string `validate:"excludesrune=☻"` Tag string ExpectedNil bool }{ {Value: "a☺b☻c☹d", Tag: "excludesrune=☻", ExpectedNil: false}, {Value: "abcd", Tag: "excludesrune=☻", ExpectedNil: true}, } validate := New() for i, s := range tests { errs := validate.Var(s.Value, s.Tag) if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { t.Fatalf("Index: %d failed Error: %s", i, errs) } errs = validate.Struct(s) if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { t.Fatalf("Index: %d failed Error: %s", i, errs) } } } func TestExcludesAllValidation(t *testing.T) { tests := []struct { Value string `validate:"excludesall=@!{}[]"` Tag string ExpectedNil bool }{ {Value: "abcd@!jfk", Tag: "excludesall=@!{}[]", ExpectedNil: false}, {Value: "abcdefg", Tag: "excludesall=@!{}[]", ExpectedNil: true}, } validate := New() for i, s := range tests { errs := validate.Var(s.Value, s.Tag) if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { t.Fatalf("Index: %d failed Error: %s", i, errs) } errs = validate.Struct(s) if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { t.Fatalf("Index: %d failed Error: %s", i, errs) } } username := "joeybloggs " errs := validate.Var(username, "excludesall=@ ") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "excludesall") excluded := "," errs = validate.Var(excluded, "excludesall=!@#$%^&*()_+.0x2C?") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "excludesall") excluded = "=" errs = validate.Var(excluded, "excludesall=!@#$%^&*()_+.0x2C=?") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "excludesall") } func TestExcludesValidation(t *testing.T) { tests := []struct { Value string `validate:"excludes=@"` Tag string ExpectedNil bool }{ {Value: "abcd@!jfk", Tag: "excludes=@", ExpectedNil: false}, {Value: "abcdq!jfk", Tag: "excludes=@", ExpectedNil: true}, } validate := New() for i, s := range tests { errs := validate.Var(s.Value, s.Tag) if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { t.Fatalf("Index: %d failed Error: %s", i, errs) } errs = validate.Struct(s) if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { t.Fatalf("Index: %d failed Error: %s", i, errs) } } } func TestContainsRuneValidation(t *testing.T) { tests := []struct { Value string `validate:"containsrune=☻"` Tag string ExpectedNil bool }{ {Value: "a☺b☻c☹d", Tag: "containsrune=☻", ExpectedNil: true}, {Value: "abcd", Tag: "containsrune=☻", ExpectedNil: false}, } validate := New() for i, s := range tests { errs := validate.Var(s.Value, s.Tag) if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { t.Fatalf("Index: %d failed Error: %s", i, errs) } errs = validate.Struct(s) if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { t.Fatalf("Index: %d failed Error: %s", i, errs) } } } func TestContainsAnyValidation(t *testing.T) { tests := []struct { Value string `validate:"containsany=@!{}[]"` Tag string ExpectedNil bool }{ {Value: "abcd@!jfk", Tag: "containsany=@!{}[]", ExpectedNil: true}, {Value: "abcdefg", Tag: "containsany=@!{}[]", ExpectedNil: false}, } validate := New() for i, s := range tests { errs := validate.Var(s.Value, s.Tag) if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { t.Fatalf("Index: %d failed Error: %s", i, errs) } errs = validate.Struct(s) if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { t.Fatalf("Index: %d failed Error: %s", i, errs) } } } func TestContainsValidation(t *testing.T) { tests := []struct { Value string `validate:"contains=@"` Tag string ExpectedNil bool }{ {Value: "abcd@!jfk", Tag: "contains=@", ExpectedNil: true}, {Value: "abcdq!jfk", Tag: "contains=@", ExpectedNil: false}, } validate := New() for i, s := range tests { errs := validate.Var(s.Value, s.Tag) if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { t.Fatalf("Index: %d failed Error: %s", i, errs) } errs = validate.Struct(s) if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { t.Fatalf("Index: %d failed Error: %s", i, errs) } } } func TestIsNeFieldValidation(t *testing.T) { var errs error validate := New() var j uint64 var k float64 s := "abcd" i := 1 j = 1 k = 1.543 b := true arr := []string{"test"} now := time.Now().UTC() var j2 uint64 var k2 float64 s2 := "abcdef" i2 := 3 j2 = 2 k2 = 1.5434456 b2 := false arr2 := []string{"test", "test2"} arr3 := []string{"test"} now2 := now errs = validate.VarWithValue(s, s2, "nefield") Equal(t, errs, nil) errs = validate.VarWithValue(i2, i, "nefield") Equal(t, errs, nil) errs = validate.VarWithValue(j2, j, "nefield") Equal(t, errs, nil) errs = validate.VarWithValue(k2, k, "nefield") Equal(t, errs, nil) errs = validate.VarWithValue(b2, b, "nefield") Equal(t, errs, nil) errs = validate.VarWithValue(arr2, arr, "nefield") Equal(t, errs, nil) errs = validate.VarWithValue(now2, now, "nefield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "nefield") errs = validate.VarWithValue(arr3, arr, "nefield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "nefield") type Test struct { Start *time.Time `validate:"nefield=End"` End *time.Time } sv := &Test{ Start: &now, End: &now, } errs = validate.Struct(sv) NotEqual(t, errs, nil) AssertError(t, errs, "Test.Start", "Test.Start", "Start", "Start", "nefield") now3 := time.Now().Add(time.Hour).UTC() sv = &Test{ Start: &now, End: &now3, } errs = validate.Struct(sv) Equal(t, errs, nil) errs = validate.VarWithValue(nil, 1, "nefield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "nefield") errs = validate.VarWithValue(sv, now, "nefield") Equal(t, errs, nil) type Test2 struct { Start *time.Time `validate:"nefield=NonExistantField"` End *time.Time } sv2 := &Test2{ Start: &now, End: &now, } errs = validate.Struct(sv2) Equal(t, errs, nil) type Other struct { Value string } type Test3 struct { Value Other Time time.Time `validate:"nefield=Value"` } tst := Test3{ Value: Other{Value: "StringVal"}, Time: now, } errs = validate.Struct(tst) Equal(t, errs, nil) // Tests for time.Duration type. // -- Validations for variables of time.Duration type. errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "nefield") Equal(t, errs, nil) errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "nefield") Equal(t, errs, nil) errs = validate.VarWithValue(time.Hour, time.Hour, "nefield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "nefield") errs = validate.VarWithValue(time.Duration(0), time.Duration(0), "omitempty,nefield") Equal(t, errs, nil) // -- Validations for a struct with time.Duration type fields. type TimeDurationTest struct { First time.Duration `validate:"nefield=Second"` Second time.Duration } var timeDurationTest *TimeDurationTest timeDurationTest = &TimeDurationTest{time.Hour, time.Hour - time.Minute} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationTest = &TimeDurationTest{time.Hour, time.Hour + time.Minute} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationTest = &TimeDurationTest{time.Hour, time.Hour} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "nefield") type TimeDurationOmitemptyTest struct { First time.Duration `validate:"omitempty,nefield=Second"` Second time.Duration } timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0), time.Duration(0)} errs = validate.Struct(timeDurationOmitemptyTest) Equal(t, errs, nil) } func TestIsNeValidation(t *testing.T) { var errs error validate := New() var j uint64 var k float64 s := "abcdef" i := 3 j = 2 k = 1.5434 arr := []string{"test"} now := time.Now().UTC() errs = validate.Var(s, "ne=abcd") Equal(t, errs, nil) errs = validate.Var(i, "ne=1") Equal(t, errs, nil) errs = validate.Var(j, "ne=1") Equal(t, errs, nil) errs = validate.Var(k, "ne=1.543") Equal(t, errs, nil) errs = validate.Var(arr, "ne=2") Equal(t, errs, nil) errs = validate.Var(arr, "ne=1") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "ne") PanicMatches(t, func() { _ = validate.Var(now, "ne=now") }, "Bad field type time.Time") // Tests for time.Duration type. // -- Validations for a variable of time.Duration type. errs = validate.Var(time.Hour-time.Minute, "ne=1h") Equal(t, errs, nil) errs = validate.Var(time.Hour+time.Minute, "ne=1h") Equal(t, errs, nil) errs = validate.Var(time.Hour, "ne=1h") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "ne") errs = validate.Var(time.Duration(0), "omitempty,ne=0") Equal(t, errs, nil) // -- Validations for a struct with a time.Duration type field. type TimeDurationTest struct { Duration time.Duration `validate:"ne=1h"` } var timeDurationTest *TimeDurationTest timeDurationTest = &TimeDurationTest{time.Hour - time.Minute} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationTest = &TimeDurationTest{time.Hour + time.Minute} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationTest = &TimeDurationTest{time.Hour} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "ne") type TimeDurationOmitemptyTest struct { Duration time.Duration `validate:"omitempty,ne=0"` } timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} errs = validate.Struct(timeDurationOmitemptyTest) Equal(t, errs, nil) } func TestIsNeIgnoreCaseValidation(t *testing.T) { var errs error validate := New() s := "abcd" now := time.Now() errs = validate.Var(s, "ne_ignore_case=efgh") Equal(t, errs, nil) errs = validate.Var(s, "ne_ignore_case=AbCd") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "ne_ignore_case") PanicMatches( t, func() { _ = validate.Var(now, "ne_ignore_case=abcd") }, "Bad field type time.Time", ) } func TestIsEqFieldValidation(t *testing.T) { var errs error validate := New() var j uint64 var k float64 s := "abcd" i := 1 j = 1 k = 1.543 b := true arr := []string{"test"} now := time.Now().UTC() var j2 uint64 var k2 float64 s2 := "abcd" i2 := 1 j2 = 1 k2 = 1.543 b2 := true arr2 := []string{"test"} arr3 := []string{"test", "test2"} now2 := now errs = validate.VarWithValue(s, s2, "eqfield") Equal(t, errs, nil) errs = validate.VarWithValue(i2, i, "eqfield") Equal(t, errs, nil) errs = validate.VarWithValue(j2, j, "eqfield") Equal(t, errs, nil) errs = validate.VarWithValue(k2, k, "eqfield") Equal(t, errs, nil) errs = validate.VarWithValue(b2, b, "eqfield") Equal(t, errs, nil) errs = validate.VarWithValue(arr2, arr, "eqfield") Equal(t, errs, nil) errs = validate.VarWithValue(now2, now, "eqfield") Equal(t, errs, nil) errs = validate.VarWithValue(arr3, arr, "eqfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "eqfield") type Test struct { Start *time.Time `validate:"eqfield=End"` End *time.Time } sv := &Test{ Start: &now, End: &now, } errs = validate.Struct(sv) Equal(t, errs, nil) now3 := time.Now().Add(time.Hour).UTC() sv = &Test{ Start: &now, End: &now3, } errs = validate.Struct(sv) NotEqual(t, errs, nil) AssertError(t, errs, "Test.Start", "Test.Start", "Start", "Start", "eqfield") errs = validate.VarWithValue(nil, 1, "eqfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "eqfield") channel := make(chan string) errs = validate.VarWithValue(5, channel, "eqfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "eqfield") errs = validate.VarWithValue(5, now, "eqfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "eqfield") type Test2 struct { Start *time.Time `validate:"eqfield=NonExistantField"` End *time.Time } sv2 := &Test2{ Start: &now, End: &now, } errs = validate.Struct(sv2) NotEqual(t, errs, nil) AssertError(t, errs, "Test2.Start", "Test2.Start", "Start", "Start", "eqfield") type Inner struct { Name string } type TStruct struct { Inner *Inner CreatedAt *time.Time `validate:"eqfield=Inner"` } inner := &Inner{ Name: "NAME", } test := &TStruct{ Inner: inner, CreatedAt: &now, } errs = validate.Struct(test) NotEqual(t, errs, nil) AssertError(t, errs, "TStruct.CreatedAt", "TStruct.CreatedAt", "CreatedAt", "CreatedAt", "eqfield") // Tests for time.Duration type. // -- Validations for variables of time.Duration type. errs = validate.VarWithValue(time.Hour, time.Hour, "eqfield") Equal(t, errs, nil) errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "eqfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "eqfield") errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "eqfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "eqfield") errs = validate.VarWithValue(time.Duration(0), time.Hour, "omitempty,eqfield") Equal(t, errs, nil) // -- Validations for a struct with time.Duration type fields. type TimeDurationTest struct { First time.Duration `validate:"eqfield=Second"` Second time.Duration } var timeDurationTest *TimeDurationTest timeDurationTest = &TimeDurationTest{time.Hour, time.Hour} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationTest = &TimeDurationTest{time.Hour, time.Hour - time.Minute} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "eqfield") timeDurationTest = &TimeDurationTest{time.Hour, time.Hour + time.Minute} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "eqfield") type TimeDurationOmitemptyTest struct { First time.Duration `validate:"omitempty,eqfield=Second"` Second time.Duration } timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0), time.Hour} errs = validate.Struct(timeDurationOmitemptyTest) Equal(t, errs, nil) } func TestIsEqFieldValidationWithAliasTime(t *testing.T) { var errs error validate := New() type CustomTime time.Time type Test struct { Start CustomTime `validate:"eqfield=End"` End *time.Time } now := time.Now().UTC() sv := &Test{ Start: CustomTime(now), End: &now, } errs = validate.Struct(sv) Equal(t, errs, nil) } func TestIsEqValidation(t *testing.T) { var errs error validate := New() var j uint64 var k float64 s := "abcd" i := 1 j = 1 k = 1.543 arr := []string{"test"} now := time.Now().UTC() errs = validate.Var(s, "eq=abcd") Equal(t, errs, nil) errs = validate.Var(i, "eq=1") Equal(t, errs, nil) errs = validate.Var(j, "eq=1") Equal(t, errs, nil) errs = validate.Var(k, "eq=1.543") Equal(t, errs, nil) errs = validate.Var(arr, "eq=1") Equal(t, errs, nil) errs = validate.Var(arr, "eq=2") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "eq") PanicMatches(t, func() { _ = validate.Var(now, "eq=now") }, "Bad field type time.Time") // Tests for time.Duration type. // -- Validations for a variable of time.Duration type. errs = validate.Var(time.Hour, "eq=1h") Equal(t, errs, nil) errs = validate.Var(time.Hour-time.Minute, "eq=1h") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "eq") errs = validate.Var(time.Hour+time.Minute, "eq=1h") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "eq") errs = validate.Var(time.Duration(0), "omitempty,eq=1h") Equal(t, errs, nil) // -- Validations for a struct with a time.Duration type field. type TimeDurationTest struct { Duration time.Duration `validate:"eq=1h"` } var timeDurationTest *TimeDurationTest timeDurationTest = &TimeDurationTest{time.Hour} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationTest = &TimeDurationTest{time.Hour - time.Minute} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "eq") timeDurationTest = &TimeDurationTest{time.Hour + time.Minute} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "eq") type TimeDurationOmitemptyTest struct { Duration time.Duration `validate:"omitempty,eq=1h"` } timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} errs = validate.Struct(timeDurationOmitemptyTest) Equal(t, errs, nil) } func TestIsEqIgnoreCaseValidation(t *testing.T) { var errs error validate := New() s := "abcd" now := time.Now() errs = validate.Var(s, "eq_ignore_case=abcd") Equal(t, errs, nil) errs = validate.Var(s, "eq_ignore_case=AbCd") Equal(t, errs, nil) PanicMatches( t, func() { _ = validate.Var(now, "eq_ignore_case=abcd") }, "Bad field type time.Time", ) } func TestOneOfValidation(t *testing.T) { validate := New() passSpecs := []struct { f interface{} t string }{ {f: "red", t: "oneof=red green"}, {f: "green", t: "oneof=red green"}, {f: "red green", t: "oneof='red green' blue"}, {f: "blue", t: "oneof='red green' blue"}, {f: 5, t: "oneof=5 6"}, {f: 6, t: "oneof=5 6"}, {f: int8(6), t: "oneof=5 6"}, {f: int16(6), t: "oneof=5 6"}, {f: int32(6), t: "oneof=5 6"}, {f: int64(6), t: "oneof=5 6"}, {f: uint(6), t: "oneof=5 6"}, {f: uint8(6), t: "oneof=5 6"}, {f: uint16(6), t: "oneof=5 6"}, {f: uint32(6), t: "oneof=5 6"}, {f: uint64(6), t: "oneof=5 6"}, } for _, spec := range passSpecs { t.Logf("%#v", spec) errs := validate.Var(spec.f, spec.t) Equal(t, errs, nil) } failSpecs := []struct { f interface{} t string }{ {f: "", t: "oneof=red green"}, {f: "yellow", t: "oneof=red green"}, {f: "green", t: "oneof='red green' blue"}, {f: 5, t: "oneof=red green"}, {f: 6, t: "oneof=red green"}, {f: 6, t: "oneof=7"}, {f: uint(6), t: "oneof=7"}, {f: int8(5), t: "oneof=red green"}, {f: int16(5), t: "oneof=red green"}, {f: int32(5), t: "oneof=red green"}, {f: int64(5), t: "oneof=red green"}, {f: uint(5), t: "oneof=red green"}, {f: uint8(5), t: "oneof=red green"}, {f: uint16(5), t: "oneof=red green"}, {f: uint32(5), t: "oneof=red green"}, {f: uint64(5), t: "oneof=red green"}, } for _, spec := range failSpecs { t.Logf("%#v", spec) errs := validate.Var(spec.f, spec.t) AssertError(t, errs, "", "", "", "", "oneof") } PanicMatches(t, func() { _ = validate.Var(3.14, "oneof=red green") }, "Bad field type float64") } func TestOneOfCIValidation(t *testing.T) { validate := New() passSpecs := []struct { f interface{} t string }{ {f: "red", t: "oneofci=RED GREEN"}, {f: "RED", t: "oneofci=red green"}, {f: "red", t: "oneofci=red green"}, {f: "RED", t: "oneofci=RED GREEN"}, {f: "green", t: "oneofci=red green"}, {f: "red green", t: "oneofci='red green' blue"}, {f: "blue", t: "oneofci='red green' blue"}, {f: "GREEN", t: "oneofci=Red Green"}, {f: "ReD", t: "oneofci=RED GREEN"}, {f: "gReEn", t: "oneofci=rEd GrEeN"}, {f: "RED GREEN", t: "oneofci='red green' blue"}, {f: "red Green", t: "oneofci='RED GREEN' Blue"}, {f: "Red green", t: "oneofci='Red Green' BLUE"}, {f: "rEd GrEeN", t: "oneofci='ReD gReEn' BlUe"}, {f: "BLUE", t: "oneofci='Red Green' BLUE"}, {f: "BlUe", t: "oneofci='RED GREEN' Blue"}, {f: "bLuE", t: "oneofci='red green' BLUE"}, } for _, spec := range passSpecs { t.Logf("%#v", spec) errs := validate.Var(spec.f, spec.t) Equal(t, errs, nil) } failSpecs := []struct { f interface{} t string }{ {f: "", t: "oneofci=red green"}, {f: "yellow", t: "oneofci=red green"}, {f: "green", t: "oneofci='red green' blue"}, } for _, spec := range failSpecs { t.Logf("%#v", spec) errs := validate.Var(spec.f, spec.t) AssertError(t, errs, "", "", "", "", "oneofci") } panicSpecs := []struct { f interface{} t string }{ {f: 3.14, t: "oneofci=red green"}, {f: 5, t: "oneofci=red green"}, {f: uint(6), t: "oneofci=7"}, {f: int8(5), t: "oneofci=red green"}, {f: int16(5), t: "oneofci=red green"}, {f: int32(5), t: "oneofci=red green"}, {f: int64(5), t: "oneofci=red green"}, {f: uint(5), t: "oneofci=red green"}, {f: uint8(5), t: "oneofci=red green"}, {f: uint16(5), t: "oneofci=red green"}, {f: uint32(5), t: "oneofci=red green"}, {f: uint64(5), t: "oneofci=red green"}, } panicCount := 0 for _, spec := range panicSpecs { t.Logf("%#v", spec) PanicMatches(t, func() { _ = validate.Var(spec.f, spec.t) }, fmt.Sprintf("Bad field type %T", spec.f)) panicCount++ } Equal(t, panicCount, len(panicSpecs)) } func TestBase32Validation(t *testing.T) { validate := New() s := "ABCD2345" errs := validate.Var(s, "base32") Equal(t, errs, nil) s = "AB======" errs = validate.Var(s, "base32") Equal(t, errs, nil) s = "ABCD2===" errs = validate.Var(s, "base32") Equal(t, errs, nil) s = "ABCD====" errs = validate.Var(s, "base32") Equal(t, errs, nil) s = "ABCD234=" errs = validate.Var(s, "base32") Equal(t, errs, nil) s = "" errs = validate.Var(s, "base32") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "base32") s = "ABCabc1890== foo bar" errs = validate.Var(s, "base32") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "base32") } func TestBase64Validation(t *testing.T) { validate := New() s := "dW5pY29ybg==" errs := validate.Var(s, "base64") Equal(t, errs, nil) s = "dGhpIGlzIGEgdGVzdCBiYXNlNjQ=" errs = validate.Var(s, "base64") Equal(t, errs, nil) s = "" errs = validate.Var(s, "base64") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "base64") s = "dW5pY29ybg== foo bar" errs = validate.Var(s, "base64") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "base64") } func TestBase64URLValidation(t *testing.T) { validate := New() testCases := []struct { decoded, encoded string success bool }{ // empty string, although a valid base64 string, should fail {"", "", false}, // invalid length {"", "a", false}, // base64 with padding {"f", "Zg==", true}, {"fo", "Zm8=", true}, // base64 without padding {"foo", "Zm9v", true}, {"", "Zg", false}, {"", "Zm8", false}, // base64 URL safe encoding with invalid, special characters '+' and '/' {"\x14\xfb\x9c\x03\xd9\x7e", "FPucA9l+", false}, {"\x14\xfb\x9c\x03\xf9\x73", "FPucA/lz", false}, // base64 URL safe encoding with valid, special characters '-' and '_' {"\x14\xfb\x9c\x03\xd9\x7e", "FPucA9l-", true}, {"\x14\xfb\x9c\x03\xf9\x73", "FPucA_lz", true}, // non base64 characters {"", "@mc=", false}, {"", "Zm 9", false}, } for _, tc := range testCases { err := validate.Var(tc.encoded, "base64url") if tc.success { Equal(t, err, nil) // make sure encoded value is decoded back to the expected value d, innerErr := base64.URLEncoding.DecodeString(tc.encoded) Equal(t, innerErr, nil) Equal(t, tc.decoded, string(d)) } else { NotEqual(t, err, nil) if len(tc.encoded) > 0 { // make sure that indeed the encoded value was faulty _, err := base64.URLEncoding.DecodeString(tc.encoded) NotEqual(t, err, nil) } } } } func TestBase64RawURLValidation(t *testing.T) { validate := New() testCases := []struct { decoded, encoded string success bool }{ // empty string, although a valid base64 string, should fail {"", "", false}, // invalid length {"", "a", false}, // base64 with padding should fail {"f", "Zg==", false}, {"fo", "Zm8=", false}, // base64 without padding {"foo", "Zm9v", true}, {"hello", "aGVsbG8", true}, {"", "aGVsb", false}, // // base64 URL safe encoding with invalid, special characters '+' and '/' {"\x14\xfb\x9c\x03\xd9\x7e", "FPucA9l+", false}, {"\x14\xfb\x9c\x03\xf9\x73", "FPucA/lz", false}, // // base64 URL safe encoding with valid, special characters '-' and '_' {"\x14\xfb\x9c\x03\xd9\x7e", "FPucA9l-", true}, {"\x14\xfb\x9c\x03\xf9\x73", "FPucA_lz", true}, // non base64 characters {"", "@mc=", false}, {"", "Zm 9", false}, } for _, tc := range testCases { err := validate.Var(tc.encoded, "base64rawurl") if tc.success { Equal(t, err, nil) // make sure encoded value is decoded back to the expected value d, innerErr := base64.RawURLEncoding.DecodeString(tc.encoded) Equal(t, innerErr, nil) Equal(t, tc.decoded, string(d)) } else { NotEqual(t, err, nil) if len(tc.encoded) > 0 { // make sure that indeed the encoded value was faulty _, err := base64.RawURLEncoding.DecodeString(tc.encoded) NotEqual(t, err, nil) } } } } func TestFileValidation(t *testing.T) { validate := New() tests := []struct { title string param string expected bool }{ {"empty path", "", false}, {"regular file", filepath.Join("testdata", "a.go"), true}, {"missing file", filepath.Join("testdata", "no.go"), false}, {"directory, not a file", "testdata", false}, } for _, test := range tests { errs := validate.Var(test.param, "file") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Test: '%s' failed Error: %s", test.title, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Test: '%s' failed Error: %s", test.title, errs) } } } PanicMatches(t, func() { _ = validate.Var(6, "file") }, "Bad field type int") } func TestImageValidation(t *testing.T) { validate := New() tmpDir := t.TempDir() paths := map[string]string{ "empty": "", "directory": "testdata", "missing": filepath.Join(tmpDir, "none.png"), "png": filepath.Join(tmpDir, "image.png"), "jpeg": filepath.Join(tmpDir, "image.jpg"), "mp3": filepath.Join(tmpDir, "music.mp3"), } tests := []struct { title string param string expected bool createImage func() destroyImage func() }{ { "empty path", paths["empty"], false, func() {}, func() {}, }, { "directory, not a file", paths["directory"], false, func() {}, func() {}, }, { "missing file", paths["missing"], false, func() {}, func() {}, }, { "valid png", paths["png"], true, func() { img := image.NewRGBA(image.Rectangle{image.Point{0, 0}, image.Point{10, 10}}) f, err := os.Create(paths["png"]) Equal(t, err, nil) defer func() { _ = f.Close() }() err = png.Encode(f, img) Equal(t, err, nil) }, func() { err := os.Remove(paths["png"]) Equal(t, err, nil) }, }, { "valid jpeg", paths["jpeg"], true, func() { var opt jpeg.Options img := image.NewGray(image.Rect(0, 0, 10, 10)) f, err := os.Create(paths["jpeg"]) Equal(t, err, nil) defer func() { _ = f.Close() }() err = jpeg.Encode(f, img, &opt) Equal(t, err, nil) }, func() { err := os.Remove(paths["jpeg"]) Equal(t, err, nil) }, }, { "valid mp3", paths["mp3"], false, func() {}, func() {}, }, } for _, test := range tests { test.createImage() errs := validate.Var(test.param, "image") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Test: '%s' failed Error: %s", test.title, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Test: '%s' failed Error: %s", test.title, errs) } } test.destroyImage() } PanicMatches(t, func() { _ = validate.Var(6, "image") }, "Bad field type int") } func TestFilePathValidation(t *testing.T) { validate := New() tests := []struct { title string param string expected bool }{ {"empty filepath", "", false}, {"valid filepath", filepath.Join("testdata", "a.go"), true}, {"invalid filepath", filepath.Join("testdata", "no\000.go"), false}, {"directory, not a filepath", "testdata" + string(os.PathSeparator), false}, {"directory", "testdata", false}, } for _, test := range tests { errs := validate.Var(test.param, "filepath") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Test: '%s' failed Error: %s", test.title, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Test: '%s' failed Error: %s", test.title, errs) } } } PanicMatches(t, func() { _ = validate.Var(6, "filepath") }, "Bad field type int") } func TestEthereumAddressValidation(t *testing.T) { validate := New() tests := []struct { param string expected bool }{ // All caps. {"0x52908400098527886E0F7030069857D2E4169EE7", true}, {"0x8617E340B3D01FA5F11F306F4090FD50E238070D", true}, // All lower. {"0xde709f2102306220921060314715629080e2fb77", true}, {"0x27b1fdb04752bbc536007a920d24acb045561c26", true}, {"0x123f681646d4a755815f9cb19e1acc8565a0c2ac", true}, // Mixed case: runs checksum validation. {"0x02F9AE5f22EA3fA88F05780B30385bECFacbf130", true}, {"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed", true}, {"0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359", true}, {"0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB", true}, {"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb", true}, {"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDB", true}, // Invalid checksum, but valid address. // Other. {"", false}, {"D1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb", false}, // Missing "0x" prefix. {"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDbc", false}, // More than 40 hex digits. {"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aD", false}, // Less than 40 hex digits. {"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDw", false}, // Invalid hex digit "w". } for i, test := range tests { errs := validate.Var(test.param, "eth_addr") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d eth_addr failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d eth_addr failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "eth_addr" { t.Fatalf("Index: %d Latitude failed Error: %s", i, errs) } } } } } func TestEthereumAddressChecksumValidation(t *testing.T) { validate := New() tests := []struct { param string expected bool }{ // All caps. {"0x52908400098527886E0F7030069857D2E4169EE7", true}, {"0x8617E340B3D01FA5F11F306F4090FD50E238070D", true}, // All lower. {"0x27b1fdb04752bbc536007a920d24acb045561c26", true}, {"0x123f681646d4a755815f9cb19e1acc8565a0c2ac", false}, // Mixed case: runs checksum validation. {"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb", true}, {"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDB", false}, // Invalid checksum. {"0x000000000000000000000000000000000000dead", false}, // Invalid checksum. {"0x000000000000000000000000000000000000dEaD", true}, // Valid checksum. // Other. {"", false}, {"D1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb", false}, // Missing "0x" prefix. {"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDbc", false}, // More than 40 hex digits. {"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aD", false}, // Less than 40 hex digits. {"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDw", false}, // Invalid hex digit "w". } for i, test := range tests { errs := validate.Var(test.param, "eth_addr_checksum") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d eth_addr_checksum failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d eth_addr_checksum failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "eth_addr_checksum" { t.Fatalf("Index: %d Latitude failed Error: %s", i, errs) } } } } } func TestBitcoinAddressValidation(t *testing.T) { validate := New() tests := []struct { param string expected bool }{ {"", false}, {"x", false}, {"0x02F9AE5f22EA3fA88F05780B30385bEC", false}, {"1A1zP1ePQGefi2DMPTifTL5SLmv7DivfNa", false}, {"1P9RQEr2XeE3PEb44ZE35sfZRRW1JH8Uqx", false}, {"3P14159I73E4gFr7JterCCQh9QjiTjiZrG", false}, {"3P141597f3E4gFr7JterCCQh9QjiTjiZrG", false}, {"37qgekLpCCHrQuSjvX3fs496FWTGsHFHizjJAs6NPcR47aefnnCWECAhHV6E3g4YN7u7Yuwod5Y", false}, {"dzb7VV1Ui55BARxv7ATxAtCUeJsANKovDGWFVgpTbhq9gvPqP3yv", false}, {"MuNu7ZAEDFiHthiunm7dPjwKqrVNCM3mAz6rP9zFveQu14YA8CxExSJTHcVP9DErn6u84E6Ej7S", false}, {"rPpQpYknyNQ5AEHuY6H8ijJJrYc2nDKKk9jjmKEXsWzyAQcFGpDLU2Zvsmoi8JLR7hAwoy3RQWf", false}, {"4Uc3FmN6NQ6zLBK5QQBXRBUREaaHwCZYsGCueHauuDmJpZKn6jkEskMB2Zi2CNgtb5r6epWEFfUJq", false}, {"7aQgR5DFQ25vyXmqZAWmnVCjL3PkBcdVkBUpjrjMTcghHx3E8wb", false}, {"17QpPprjeg69fW1DV8DcYYCKvWjYhXvWkov6MJ1iTTvMFj6weAqW7wybZeH57WTNxXVCRH4veVs", false}, {"KxuACDviz8Xvpn1xAh9MfopySZNuyajYMZWz16Dv2mHHryznWUp3", false}, {"7nK3GSmqdXJQtdohvGfJ7KsSmn3TmGqExug49583bDAL91pVSGq5xS9SHoAYL3Wv3ijKTit65th", false}, {"cTivdBmq7bay3RFGEBBuNfMh2P1pDCgRYN2Wbxmgwr4ki3jNUL2va", false}, {"gjMV4vjNjyMrna4fsAr8bWxAbwtmMUBXJS3zL4NJt5qjozpbQLmAfK1uA3CquSqsZQMpoD1g2nk", false}, {"emXm1naBMoVzPjbk7xpeTVMFy4oDEe25UmoyGgKEB1gGWsK8kRGs", false}, {"7VThQnNRj1o3Zyvc7XHPRrjDf8j2oivPTeDXnRPYWeYGE4pXeRJDZgf28ppti5hsHWXS2GSobdqyo", false}, {"1G9u6oCVCPh2o8m3t55ACiYvG1y5BHewUkDSdiQarDcYXXhFHYdzMdYfUAhfxn5vNZBwpgUNpso", false}, {"31QQ7ZMLkScDiB4VyZjuptr7AEc9j1SjstF7pRoLhHTGkW4Q2y9XELobQmhhWxeRvqcukGd1XCq", false}, {"DHqKSnpxa8ZdQyH8keAhvLTrfkyBMQxqngcQA5N8LQ9KVt25kmGN", false}, {"2LUHcJPbwLCy9GLH1qXmfmAwvadWw4bp4PCpDfduLqV17s6iDcy1imUwhQJhAoNoN1XNmweiJP4i", false}, {"7USRzBXAnmck8fX9HmW7RAb4qt92VFX6soCnts9s74wxm4gguVhtG5of8fZGbNPJA83irHVY6bCos", false}, {"1DGezo7BfVebZxAbNT3XGujdeHyNNBF3vnficYoTSp4PfK2QaML9bHzAMxke3wdKdHYWmsMTJVu", false}, {"2D12DqDZKwCxxkzs1ZATJWvgJGhQ4cFi3WrizQ5zLAyhN5HxuAJ1yMYaJp8GuYsTLLxTAz6otCfb", false}, {"8AFJzuTujXjw1Z6M3fWhQ1ujDW7zsV4ePeVjVo7D1egERqSW9nZ", false}, {"163Q17qLbTCue8YY3AvjpUhotuaodLm2uqMhpYirsKjVqnxJRWTEoywMVY3NbBAHuhAJ2cF9GAZ", false}, {"2MnmgiRH4eGLyLc9eAqStzk7dFgBjFtUCtu", false}, {"461QQ2sYWxU7H2PV4oBwJGNch8XVTYYbZxU", false}, {"2UCtv53VttmQYkVU4VMtXB31REvQg4ABzs41AEKZ8UcB7DAfVzdkV9JDErwGwyj5AUHLkmgZeobs", false}, {"cSNjAsnhgtiFMi6MtfvgscMB2Cbhn2v1FUYfviJ1CdjfidvmeW6mn", false}, {"gmsow2Y6EWAFDFE1CE4Hd3Tpu2BvfmBfG1SXsuRARbnt1WjkZnFh1qGTiptWWbjsq2Q6qvpgJVj", false}, {"nksUKSkzS76v8EsSgozXGMoQFiCoCHzCVajFKAXqzK5on9ZJYVHMD5CKwgmX3S3c7M1U3xabUny", false}, {"L3favK1UzFGgdzYBF2oBT5tbayCo4vtVBLJhg2iYuMeePxWG8SQc", false}, {"7VxLxGGtYT6N99GdEfi6xz56xdQ8nP2dG1CavuXx7Rf2PrvNMTBNevjkfgs9JmkcGm6EXpj8ipyPZ ", false}, {"2mbZwFXF6cxShaCo2czTRB62WTx9LxhTtpP", false}, {"dB7cwYdcPSgiyAwKWL3JwCVwSk6epU2txw", false}, {"HPhFUhUAh8ZQQisH8QQWafAxtQYju3SFTX", false}, {"4ctAH6AkHzq5ioiM1m9T3E2hiYEev5mTsB", false}, {"31uEbMgunupShBVTewXjtqbBv5MndwfXhb", false}, {"175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W", false}, {"Hn1uFi4dNexWrqARpjMqgT6cX1UsNPuV3cHdGg9ExyXw8HTKadbktRDtdeVmY3M1BxJStiL4vjJ", false}, {"Sq3fDbvutABmnAHHExJDgPLQn44KnNC7UsXuT7KZecpaYDMU9Txs", false}, {"6TqWyrqdgUEYDQU1aChMuFMMEimHX44qHFzCUgGfqxGgZNMUVWJ", false}, {"giqJo7oWqFxNKWyrgcBxAVHXnjJ1t6cGoEffce5Y1y7u649Noj5wJ4mmiUAKEVVrYAGg2KPB3Y4", false}, {"cNzHY5e8vcmM3QVJUcjCyiKMYfeYvyueq5qCMV3kqcySoLyGLYUK", false}, {"37uTe568EYc9WLoHEd9jXEvUiWbq5LFLscNyqvAzLU5vBArUJA6eydkLmnMwJDjkL5kXc2VK7ig", false}, {"EsYbG4tWWWY45G31nox838qNdzksbPySWc", false}, {"nbuzhfwMoNzA3PaFnyLcRxE9bTJPDkjZ6Rf6Y6o2ckXZfzZzXBT", false}, {"cQN9PoxZeCWK1x56xnz6QYAsvR11XAce3Ehp3gMUdfSQ53Y2mPzx", false}, {"1Gm3N3rkef6iMbx4voBzaxtXcmmiMTqZPhcuAepRzYUJQW4qRpEnHvMojzof42hjFRf8PE2jPde", false}, {"2TAq2tuN6x6m233bpT7yqdYQPELdTDJn1eU", false}, {"ntEtnnGhqPii4joABvBtSEJG6BxjT2tUZqE8PcVYgk3RHpgxgHDCQxNbLJf7ardf1dDk2oCQ7Cf", false}, {"Ky1YjoZNgQ196HJV3HpdkecfhRBmRZdMJk89Hi5KGfpfPwS2bUbfd", false}, {"2A1q1YsMZowabbvta7kTy2Fd6qN4r5ZCeG3qLpvZBMzCixMUdkN2Y4dHB1wPsZAeVXUGD83MfRED", false}, {"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i", true}, {"1Ax4gZtb7gAit2TivwejZHYtNNLT18PUXJ", true}, {"1C5bSj1iEGUgSTbziymG7Cn18ENQuT36vv", true}, {"1Gqk4Tv79P91Cc1STQtU3s1W6277M2CVWu", true}, {"1JwMWBVLtiqtscbaRHai4pqHokhFCbtoB4", true}, {"19dcawoKcZdQz365WpXWMhX6QCUpR9SY4r", true}, {"13p1ijLwsnrcuyqcTvJXkq2ASdXqcnEBLE", true}, {"1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2", true}, {"3P14159f73E4gFr7JterCCQh9QjiTjiZrG", true}, {"3CMNFxN1oHBc4R1EpboAL5yzHGgE611Xou", true}, {"3QjYXhTkvuj8qPaXHTTWb5wjXhdsLAAWVy", true}, {"3AnNxabYGoTxYiTEZwFEnerUoeFXK2Zoks", true}, {"33vt8ViH5jsr115AGkW6cEmEz9MpvJSwDk", true}, {"3QCzvfL4ZRvmJFiWWBVwxfdaNBT8EtxB5y", true}, {"37Sp6Rv3y4kVd1nQ1JV5pfqXccHNyZm1x3", true}, {"3ALJH9Y951VCGcVZYAdpA3KchoP9McEj1G", true}, {"12KYrjTdVGjFMtaxERSk3gphreJ5US8aUP", true}, {"12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y", true}, {"1oNLrsHnBcR6dpaBpwz3LSwutbUNkNSjs", true}, {"1SQHtwR5oJRKLfiWQ2APsAd9miUc4k2ez", true}, {"116CGDLddrZhMrTwhCVJXtXQpxygTT1kHd", true}, {"3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt", true}, } for i, test := range tests { errs := validate.Var(test.param, "btc_addr") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d btc_addr failed with Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d btc_addr failed with Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "btc_addr" { t.Fatalf("Index: %d Latitude failed with Error: %s", i, errs) } } } } } func TestBitcoinBech32AddressValidation(t *testing.T) { validate := New() tests := []struct { param string expected bool }{ {"", false}, {"bc1rw5uspcuh", false}, {"bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t5", false}, {"BC13W508D6QEJXTDG4Y5R3ZARVARY0C5XW7KN40WF2", false}, {"qw508d6qejxtdg4y5r3zarvary0c5xw7kg3g4ty", false}, {"bc1rw5uspcuh", false}, {"bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs90", false}, {"BC1QW508d6QEJxTDG4y5R3ZArVARY0C5XW7KV8F3T4", false}, {"BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P", false}, {"bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t5", false}, {"bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs90", false}, {"bc1pw508d6qejxtdg4y5r3zarqfsj6c3", false}, {"bc1zw508d6qejxtdg4y5r3zarvaryvqyzf3du", false}, {"bc1gmk9yu", false}, {"bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv", false}, {"BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4", true}, {"bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7k7grplx", true}, {"bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3", true}, {"BC1SW50QA3JX3S", true}, {"bc1zw508d6qejxtdg4y5r3zarvaryvg6kdaj", true}, } for i, test := range tests { errs := validate.Var(test.param, "btc_addr_bech32") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d btc_addr_bech32 failed with Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d btc_addr_bech32 failed with Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "btc_addr_bech32" { t.Fatalf("Index: %d Latitude failed with Error: %s", i, errs) } } } } } func TestNoStructLevelValidation(t *testing.T) { type Inner struct { Test string `validate:"len=5"` } type Outer struct { InnerStruct Inner `validate:"required,nostructlevel"` InnerStructPtr *Inner `validate:"required,nostructlevel"` } outer := &Outer{ InnerStructPtr: nil, InnerStruct: Inner{}, } // test with struct required failing on validate := New(WithRequiredStructEnabled()) errs := validate.Struct(outer) NotEqual(t, errs, nil) AssertError(t, errs, "Outer.InnerStruct", "Outer.InnerStruct", "InnerStruct", "InnerStruct", "required") AssertError(t, errs, "Outer.InnerStructPtr", "Outer.InnerStructPtr", "InnerStructPtr", "InnerStructPtr", "required") inner := Inner{ Test: "1234", } outer = &Outer{ InnerStruct: inner, InnerStructPtr: &inner, } errs = validate.Struct(outer) Equal(t, errs, nil) // test with struct required failing off outer = &Outer{ InnerStructPtr: nil, InnerStruct: Inner{}, } validate = New() errs = validate.Struct(outer) NotEqual(t, errs, nil) AssertError(t, errs, "Outer.InnerStructPtr", "Outer.InnerStructPtr", "InnerStructPtr", "InnerStructPtr", "required") inner = Inner{ Test: "1234", } outer = &Outer{ InnerStruct: inner, InnerStructPtr: &inner, } errs = validate.Struct(outer) Equal(t, errs, nil) } func TestStructOnlyValidation(t *testing.T) { type Inner struct { Test string `validate:"len=5"` } type Outer struct { InnerStruct Inner `validate:"required,structonly"` InnerStructPtr *Inner `validate:"required,structonly"` } outer := &Outer{ InnerStruct: Inner{}, InnerStructPtr: nil, } // without required struct on validate := New() errs := validate.Struct(outer) NotEqual(t, errs, nil) AssertError(t, errs, "Outer.InnerStructPtr", "Outer.InnerStructPtr", "InnerStructPtr", "InnerStructPtr", "required") // with required struct on validate.requiredStructEnabled = true errs = validate.Struct(outer) NotEqual(t, errs, nil) AssertError(t, errs, "Outer.InnerStruct", "Outer.InnerStruct", "InnerStruct", "InnerStruct", "required") AssertError(t, errs, "Outer.InnerStructPtr", "Outer.InnerStructPtr", "InnerStructPtr", "InnerStructPtr", "required") inner := Inner{ Test: "1234", } outer = &Outer{ InnerStruct: inner, InnerStructPtr: &inner, } errs = validate.Struct(outer) Equal(t, errs, nil) // 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"` } type User struct { FirstName string `json:"fname"` LastName string `json:"lname"` Age uint8 `validate:"gte=0,lte=130"` Number string `validate:"required,e164"` Email string `validate:"required,email"` FavouriteColor string `validate:"hexcolor|rgb|rgba"` Addresses []*Address `validate:"required"` // a person can have a home and cottage... Address Address `validate:"structonly"` // a person can have a home and cottage... } address := &Address{ Street: "Eavesdown Docks", Planet: "Persphone", Phone: "none", City: "Unknown", } user := &User{ FirstName: "", LastName: "", Age: 45, Number: "+1123456789", Email: "Badger.Smith@gmail.com", FavouriteColor: "#000", Addresses: []*Address{address}, Address: Address{ // Street: "Eavesdown Docks", Planet: "Persphone", Phone: "none", City: "Unknown", }, } errs = validate.Struct(user) Equal(t, errs, nil) } func TestGtField(t *testing.T) { var errs error validate := New() type TimeTest struct { Start *time.Time `validate:"required,gt"` End *time.Time `validate:"required,gt,gtfield=Start"` } now := time.Now() start := now.Add(time.Hour * 24) end := start.Add(time.Hour * 24) timeTest := &TimeTest{ Start: &start, End: &end, } errs = validate.Struct(timeTest) Equal(t, errs, nil) timeTest = &TimeTest{ Start: &end, End: &start, } errs = validate.Struct(timeTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeTest.End", "TimeTest.End", "End", "End", "gtfield") errs = validate.VarWithValue(&end, &start, "gtfield") Equal(t, errs, nil) errs = validate.VarWithValue(&start, &end, "gtfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gtfield") errs = validate.VarWithValue(&end, &start, "gtfield") Equal(t, errs, nil) errs = validate.VarWithValue(&timeTest, &end, "gtfield") NotEqual(t, errs, nil) errs = validate.VarWithValue("test bigger", "test", "gtfield") Equal(t, errs, nil) // Tests for time.Duration type. // -- Validations for variables of time.Duration type. errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "gtfield") Equal(t, errs, nil) errs = validate.VarWithValue(time.Hour, time.Hour, "gtfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gtfield") errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "gtfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gtfield") errs = validate.VarWithValue(time.Duration(0), time.Hour, "omitempty,gtfield") Equal(t, errs, nil) // -- Validations for a struct with time.Duration type fields. type TimeDurationTest struct { First time.Duration `validate:"gtfield=Second"` Second time.Duration } var timeDurationTest *TimeDurationTest timeDurationTest = &TimeDurationTest{time.Hour, time.Hour - time.Minute} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationTest = &TimeDurationTest{time.Hour, time.Hour} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "gtfield") timeDurationTest = &TimeDurationTest{time.Hour, time.Hour + time.Minute} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "gtfield") type TimeDurationOmitemptyTest struct { First time.Duration `validate:"omitempty,gtfield=Second"` Second time.Duration } timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0), time.Hour} errs = validate.Struct(timeDurationOmitemptyTest) Equal(t, errs, nil) // Tests for Ints types. type IntTest struct { Val1 int `validate:"required"` Val2 int `validate:"required,gtfield=Val1"` } intTest := &IntTest{ Val1: 1, Val2: 5, } errs = validate.Struct(intTest) Equal(t, errs, nil) intTest = &IntTest{ Val1: 5, Val2: 1, } errs = validate.Struct(intTest) NotEqual(t, errs, nil) AssertError(t, errs, "IntTest.Val2", "IntTest.Val2", "Val2", "Val2", "gtfield") errs = validate.VarWithValue(int(5), int(1), "gtfield") Equal(t, errs, nil) errs = validate.VarWithValue(int(1), int(5), "gtfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gtfield") type UIntTest struct { Val1 uint `validate:"required"` Val2 uint `validate:"required,gtfield=Val1"` } uIntTest := &UIntTest{ Val1: 1, Val2: 5, } errs = validate.Struct(uIntTest) Equal(t, errs, nil) uIntTest = &UIntTest{ Val1: 5, Val2: 1, } errs = validate.Struct(uIntTest) NotEqual(t, errs, nil) AssertError(t, errs, "UIntTest.Val2", "UIntTest.Val2", "Val2", "Val2", "gtfield") errs = validate.VarWithValue(uint(5), uint(1), "gtfield") Equal(t, errs, nil) errs = validate.VarWithValue(uint(1), uint(5), "gtfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gtfield") type FloatTest struct { Val1 float64 `validate:"required"` Val2 float64 `validate:"required,gtfield=Val1"` } floatTest := &FloatTest{ Val1: 1, Val2: 5, } errs = validate.Struct(floatTest) Equal(t, errs, nil) floatTest = &FloatTest{ Val1: 5, Val2: 1, } errs = validate.Struct(floatTest) NotEqual(t, errs, nil) AssertError(t, errs, "FloatTest.Val2", "FloatTest.Val2", "Val2", "Val2", "gtfield") errs = validate.VarWithValue(float32(5), float32(1), "gtfield") Equal(t, errs, nil) errs = validate.VarWithValue(float32(1), float32(5), "gtfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gtfield") errs = validate.VarWithValue(nil, 1, "gtfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gtfield") errs = validate.VarWithValue(5, "T", "gtfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gtfield") errs = validate.VarWithValue(5, start, "gtfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gtfield") type TimeTest2 struct { Start *time.Time `validate:"required"` End *time.Time `validate:"required,gtfield=NonExistantField"` } timeTest2 := &TimeTest2{ Start: &start, End: &end, } errs = validate.Struct(timeTest2) NotEqual(t, errs, nil) AssertError(t, errs, "TimeTest2.End", "TimeTest2.End", "End", "End", "gtfield") type Other struct { Value string } type Test struct { Value Other Time time.Time `validate:"gtfield=Value"` } tst := Test{ Value: Other{Value: "StringVal"}, Time: end, } errs = validate.Struct(tst) NotEqual(t, errs, nil) AssertError(t, errs, "Test.Time", "Test.Time", "Time", "Time", "gtfield") } func TestLtField(t *testing.T) { var errs error validate := New() type TimeTest struct { Start *time.Time `validate:"required,lt,ltfield=End"` End *time.Time `validate:"required,lt"` } now := time.Now() start := now.Add(time.Hour * 24 * -1 * 2) end := start.Add(time.Hour * 24) timeTest := &TimeTest{ Start: &start, End: &end, } errs = validate.Struct(timeTest) Equal(t, errs, nil) timeTest = &TimeTest{ Start: &end, End: &start, } errs = validate.Struct(timeTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeTest.Start", "TimeTest.Start", "Start", "Start", "ltfield") errs = validate.VarWithValue(&start, &end, "ltfield") Equal(t, errs, nil) errs = validate.VarWithValue(&end, &start, "ltfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "ltfield") errs = validate.VarWithValue(&end, timeTest, "ltfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "ltfield") errs = validate.VarWithValue("tes", "test", "ltfield") Equal(t, errs, nil) // Tests for time.Duration type. // -- Validations for variables of time.Duration type. errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "ltfield") Equal(t, errs, nil) errs = validate.VarWithValue(time.Hour, time.Hour, "ltfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "ltfield") errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "ltfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "ltfield") errs = validate.VarWithValue(time.Duration(0), -time.Minute, "omitempty,ltfield") Equal(t, errs, nil) // -- Validations for a struct with time.Duration type fields. type TimeDurationTest struct { First time.Duration `validate:"ltfield=Second"` Second time.Duration } var timeDurationTest *TimeDurationTest timeDurationTest = &TimeDurationTest{time.Hour, time.Hour + time.Minute} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationTest = &TimeDurationTest{time.Hour, time.Hour} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "ltfield") timeDurationTest = &TimeDurationTest{time.Hour, time.Hour - time.Minute} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "ltfield") type TimeDurationOmitemptyTest struct { First time.Duration `validate:"omitempty,ltfield=Second"` Second time.Duration } timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0), -time.Minute} errs = validate.Struct(timeDurationOmitemptyTest) Equal(t, errs, nil) // Tests for Ints types. type IntTest struct { Val1 int `validate:"required"` Val2 int `validate:"required,ltfield=Val1"` } intTest := &IntTest{ Val1: 5, Val2: 1, } errs = validate.Struct(intTest) Equal(t, errs, nil) intTest = &IntTest{ Val1: 1, Val2: 5, } errs = validate.Struct(intTest) NotEqual(t, errs, nil) AssertError(t, errs, "IntTest.Val2", "IntTest.Val2", "Val2", "Val2", "ltfield") errs = validate.VarWithValue(int(1), int(5), "ltfield") Equal(t, errs, nil) errs = validate.VarWithValue(int(5), int(1), "ltfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "ltfield") type UIntTest struct { Val1 uint `validate:"required"` Val2 uint `validate:"required,ltfield=Val1"` } uIntTest := &UIntTest{ Val1: 5, Val2: 1, } errs = validate.Struct(uIntTest) Equal(t, errs, nil) uIntTest = &UIntTest{ Val1: 1, Val2: 5, } errs = validate.Struct(uIntTest) NotEqual(t, errs, nil) AssertError(t, errs, "UIntTest.Val2", "UIntTest.Val2", "Val2", "Val2", "ltfield") errs = validate.VarWithValue(uint(1), uint(5), "ltfield") Equal(t, errs, nil) errs = validate.VarWithValue(uint(5), uint(1), "ltfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "ltfield") type FloatTest struct { Val1 float64 `validate:"required"` Val2 float64 `validate:"required,ltfield=Val1"` } floatTest := &FloatTest{ Val1: 5, Val2: 1, } errs = validate.Struct(floatTest) Equal(t, errs, nil) floatTest = &FloatTest{ Val1: 1, Val2: 5, } errs = validate.Struct(floatTest) NotEqual(t, errs, nil) AssertError(t, errs, "FloatTest.Val2", "FloatTest.Val2", "Val2", "Val2", "ltfield") errs = validate.VarWithValue(float32(1), float32(5), "ltfield") Equal(t, errs, nil) errs = validate.VarWithValue(float32(5), float32(1), "ltfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "ltfield") errs = validate.VarWithValue(nil, 5, "ltfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "ltfield") errs = validate.VarWithValue(1, "T", "ltfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "ltfield") errs = validate.VarWithValue(1, end, "ltfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "ltfield") type TimeTest2 struct { Start *time.Time `validate:"required"` End *time.Time `validate:"required,ltfield=NonExistantField"` } timeTest2 := &TimeTest2{ Start: &end, End: &start, } errs = validate.Struct(timeTest2) NotEqual(t, errs, nil) AssertError(t, errs, "TimeTest2.End", "TimeTest2.End", "End", "End", "ltfield") } func TestFieldContains(t *testing.T) { validate := New() type StringTest struct { Foo string `validate:"fieldcontains=Bar"` Bar string } stringTest := &StringTest{ Foo: "foobar", Bar: "bar", } errs := validate.Struct(stringTest) Equal(t, errs, nil) stringTest = &StringTest{ Foo: "foo", Bar: "bar", } errs = validate.Struct(stringTest) NotEqual(t, errs, nil) AssertError(t, errs, "StringTest.Foo", "StringTest.Foo", "Foo", "Foo", "fieldcontains") errs = validate.VarWithValue("foo", "bar", "fieldcontains") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "fieldcontains") errs = validate.VarWithValue("bar", "foobarfoo", "fieldcontains") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "fieldcontains") errs = validate.VarWithValue("foobarfoo", "bar", "fieldcontains") Equal(t, errs, nil) type StringTestMissingField struct { Foo string `validate:"fieldcontains=Bar"` } stringTestMissingField := &StringTestMissingField{ Foo: "foo", } errs = validate.Struct(stringTestMissingField) NotEqual(t, errs, nil) AssertError(t, errs, "StringTestMissingField.Foo", "StringTestMissingField.Foo", "Foo", "Foo", "fieldcontains") } func TestFieldExcludes(t *testing.T) { validate := New() type StringTest struct { Foo string `validate:"fieldexcludes=Bar"` Bar string } stringTest := &StringTest{ Foo: "foobar", Bar: "bar", } errs := validate.Struct(stringTest) NotEqual(t, errs, nil) AssertError(t, errs, "StringTest.Foo", "StringTest.Foo", "Foo", "Foo", "fieldexcludes") stringTest = &StringTest{ Foo: "foo", Bar: "bar", } errs = validate.Struct(stringTest) Equal(t, errs, nil) errs = validate.VarWithValue("foo", "bar", "fieldexcludes") Equal(t, errs, nil) errs = validate.VarWithValue("bar", "foobarfoo", "fieldexcludes") Equal(t, errs, nil) errs = validate.VarWithValue("foobarfoo", "bar", "fieldexcludes") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "fieldexcludes") type StringTestMissingField struct { Foo string `validate:"fieldexcludes=Bar"` } stringTestMissingField := &StringTestMissingField{ Foo: "foo", } errs = validate.Struct(stringTestMissingField) Equal(t, errs, nil) } func TestContainsAndExcludes(t *testing.T) { validate := New() type ImpossibleStringTest struct { Foo string `validate:"fieldcontains=Bar"` Bar string `validate:"fieldexcludes=Foo"` } impossibleStringTest := &ImpossibleStringTest{ Foo: "foo", Bar: "bar", } errs := validate.Struct(impossibleStringTest) NotEqual(t, errs, nil) AssertError(t, errs, "ImpossibleStringTest.Foo", "ImpossibleStringTest.Foo", "Foo", "Foo", "fieldcontains") impossibleStringTest = &ImpossibleStringTest{ Foo: "bar", Bar: "foo", } errs = validate.Struct(impossibleStringTest) NotEqual(t, errs, nil) AssertError(t, errs, "ImpossibleStringTest.Foo", "ImpossibleStringTest.Foo", "Foo", "Foo", "fieldcontains") } func TestLteField(t *testing.T) { var errs error validate := New() type TimeTest struct { Start *time.Time `validate:"required,lte,ltefield=End"` End *time.Time `validate:"required,lte"` } now := time.Now() start := now.Add(time.Hour * 24 * -1 * 2) end := start.Add(time.Hour * 24) timeTest := &TimeTest{ Start: &start, End: &end, } errs = validate.Struct(timeTest) Equal(t, errs, nil) timeTest = &TimeTest{ Start: &end, End: &start, } errs = validate.Struct(timeTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeTest.Start", "TimeTest.Start", "Start", "Start", "ltefield") errs = validate.VarWithValue(&start, &end, "ltefield") Equal(t, errs, nil) errs = validate.VarWithValue(&end, &start, "ltefield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "ltefield") errs = validate.VarWithValue(&end, timeTest, "ltefield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "ltefield") errs = validate.VarWithValue("tes", "test", "ltefield") Equal(t, errs, nil) errs = validate.VarWithValue("test", "test", "ltefield") Equal(t, errs, nil) // Tests for time.Duration type. // -- Validations for variables of time.Duration type. errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "ltefield") Equal(t, errs, nil) errs = validate.VarWithValue(time.Hour, time.Hour, "ltefield") Equal(t, errs, nil) errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "ltefield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "ltefield") errs = validate.VarWithValue(time.Duration(0), -time.Minute, "omitempty,ltefield") Equal(t, errs, nil) // -- Validations for a struct with time.Duration type fields. type TimeDurationTest struct { First time.Duration `validate:"ltefield=Second"` Second time.Duration } var timeDurationTest *TimeDurationTest timeDurationTest = &TimeDurationTest{time.Hour, time.Hour + time.Minute} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationTest = &TimeDurationTest{time.Hour, time.Hour} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationTest = &TimeDurationTest{time.Hour, time.Hour - time.Minute} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "ltefield") type TimeDurationOmitemptyTest struct { First time.Duration `validate:"omitempty,ltefield=Second"` Second time.Duration } timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0), -time.Minute} errs = validate.Struct(timeDurationOmitemptyTest) Equal(t, errs, nil) // Tests for Ints types. type IntTest struct { Val1 int `validate:"required"` Val2 int `validate:"required,ltefield=Val1"` } intTest := &IntTest{ Val1: 5, Val2: 1, } errs = validate.Struct(intTest) Equal(t, errs, nil) intTest = &IntTest{ Val1: 1, Val2: 5, } errs = validate.Struct(intTest) NotEqual(t, errs, nil) AssertError(t, errs, "IntTest.Val2", "IntTest.Val2", "Val2", "Val2", "ltefield") errs = validate.VarWithValue(int(1), int(5), "ltefield") Equal(t, errs, nil) errs = validate.VarWithValue(int(5), int(1), "ltefield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "ltefield") type UIntTest struct { Val1 uint `validate:"required"` Val2 uint `validate:"required,ltefield=Val1"` } uIntTest := &UIntTest{ Val1: 5, Val2: 1, } errs = validate.Struct(uIntTest) Equal(t, errs, nil) uIntTest = &UIntTest{ Val1: 1, Val2: 5, } errs = validate.Struct(uIntTest) NotEqual(t, errs, nil) AssertError(t, errs, "UIntTest.Val2", "UIntTest.Val2", "Val2", "Val2", "ltefield") errs = validate.VarWithValue(uint(1), uint(5), "ltefield") Equal(t, errs, nil) errs = validate.VarWithValue(uint(5), uint(1), "ltefield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "ltefield") type FloatTest struct { Val1 float64 `validate:"required"` Val2 float64 `validate:"required,ltefield=Val1"` } floatTest := &FloatTest{ Val1: 5, Val2: 1, } errs = validate.Struct(floatTest) Equal(t, errs, nil) floatTest = &FloatTest{ Val1: 1, Val2: 5, } errs = validate.Struct(floatTest) NotEqual(t, errs, nil) AssertError(t, errs, "FloatTest.Val2", "FloatTest.Val2", "Val2", "Val2", "ltefield") errs = validate.VarWithValue(float32(1), float32(5), "ltefield") Equal(t, errs, nil) errs = validate.VarWithValue(float32(5), float32(1), "ltefield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "ltefield") errs = validate.VarWithValue(nil, 5, "ltefield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "ltefield") errs = validate.VarWithValue(1, "T", "ltefield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "ltefield") errs = validate.VarWithValue(1, end, "ltefield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "ltefield") type TimeTest2 struct { Start *time.Time `validate:"required"` End *time.Time `validate:"required,ltefield=NonExistantField"` } timeTest2 := &TimeTest2{ Start: &end, End: &start, } errs = validate.Struct(timeTest2) NotEqual(t, errs, nil) AssertError(t, errs, "TimeTest2.End", "TimeTest2.End", "End", "End", "ltefield") } func TestGteField(t *testing.T) { var errs error validate := New() type TimeTest struct { Start *time.Time `validate:"required,gte"` End *time.Time `validate:"required,gte,gtefield=Start"` } now := time.Now() start := now.Add(time.Hour * 24) end := start.Add(time.Hour * 24) timeTest := &TimeTest{ Start: &start, End: &end, } errs = validate.Struct(timeTest) Equal(t, errs, nil) timeTest = &TimeTest{ Start: &end, End: &start, } errs = validate.Struct(timeTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeTest.End", "TimeTest.End", "End", "End", "gtefield") errs = validate.VarWithValue(&end, &start, "gtefield") Equal(t, errs, nil) errs = validate.VarWithValue(&start, &end, "gtefield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gtefield") errs = validate.VarWithValue(&start, timeTest, "gtefield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gtefield") errs = validate.VarWithValue("test", "test", "gtefield") Equal(t, errs, nil) errs = validate.VarWithValue("test bigger", "test", "gtefield") Equal(t, errs, nil) // Tests for time.Duration type. // -- Validations for variables of time.Duration type. errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "gtefield") Equal(t, errs, nil) errs = validate.VarWithValue(time.Hour, time.Hour, "gtefield") Equal(t, errs, nil) errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "gtefield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gtefield") errs = validate.VarWithValue(time.Duration(0), time.Hour, "omitempty,gtefield") Equal(t, errs, nil) // -- Validations for a struct with time.Duration type fields. type TimeDurationTest struct { First time.Duration `validate:"gtefield=Second"` Second time.Duration } var timeDurationTest *TimeDurationTest timeDurationTest = &TimeDurationTest{time.Hour, time.Hour - time.Minute} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationTest = &TimeDurationTest{time.Hour, time.Hour} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationTest = &TimeDurationTest{time.Hour, time.Hour + time.Minute} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "gtefield") type TimeDurationOmitemptyTest struct { First time.Duration `validate:"omitempty,gtefield=Second"` Second time.Duration } timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0), time.Hour} errs = validate.Struct(timeDurationOmitemptyTest) Equal(t, errs, nil) // Tests for Ints types. type IntTest struct { Val1 int `validate:"required"` Val2 int `validate:"required,gtefield=Val1"` } intTest := &IntTest{ Val1: 1, Val2: 5, } errs = validate.Struct(intTest) Equal(t, errs, nil) intTest = &IntTest{ Val1: 5, Val2: 1, } errs = validate.Struct(intTest) NotEqual(t, errs, nil) AssertError(t, errs, "IntTest.Val2", "IntTest.Val2", "Val2", "Val2", "gtefield") errs = validate.VarWithValue(int(5), int(1), "gtefield") Equal(t, errs, nil) errs = validate.VarWithValue(int(1), int(5), "gtefield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gtefield") type UIntTest struct { Val1 uint `validate:"required"` Val2 uint `validate:"required,gtefield=Val1"` } uIntTest := &UIntTest{ Val1: 1, Val2: 5, } errs = validate.Struct(uIntTest) Equal(t, errs, nil) uIntTest = &UIntTest{ Val1: 5, Val2: 1, } errs = validate.Struct(uIntTest) NotEqual(t, errs, nil) AssertError(t, errs, "UIntTest.Val2", "UIntTest.Val2", "Val2", "Val2", "gtefield") errs = validate.VarWithValue(uint(5), uint(1), "gtefield") Equal(t, errs, nil) errs = validate.VarWithValue(uint(1), uint(5), "gtefield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gtefield") type FloatTest struct { Val1 float64 `validate:"required"` Val2 float64 `validate:"required,gtefield=Val1"` } floatTest := &FloatTest{ Val1: 1, Val2: 5, } errs = validate.Struct(floatTest) Equal(t, errs, nil) floatTest = &FloatTest{ Val1: 5, Val2: 1, } errs = validate.Struct(floatTest) NotEqual(t, errs, nil) AssertError(t, errs, "FloatTest.Val2", "FloatTest.Val2", "Val2", "Val2", "gtefield") errs = validate.VarWithValue(float32(5), float32(1), "gtefield") Equal(t, errs, nil) errs = validate.VarWithValue(float32(1), float32(5), "gtefield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gtefield") errs = validate.VarWithValue(nil, 1, "gtefield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gtefield") errs = validate.VarWithValue(5, "T", "gtefield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gtefield") errs = validate.VarWithValue(5, start, "gtefield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gtefield") type TimeTest2 struct { Start *time.Time `validate:"required"` End *time.Time `validate:"required,gtefield=NonExistantField"` } timeTest2 := &TimeTest2{ Start: &start, End: &end, } errs = validate.Struct(timeTest2) NotEqual(t, errs, nil) AssertError(t, errs, "TimeTest2.End", "TimeTest2.End", "End", "End", "gtefield") } func TestValidateByTagAndValue(t *testing.T) { validate := New() val := "test" field := "test" errs := validate.VarWithValue(val, field, "required") Equal(t, errs, nil) fn := func(fl FieldLevel) bool { return fl.Parent().String() == fl.Field().String() } errs = validate.RegisterValidation("isequaltestfunc", fn) Equal(t, errs, nil) errs = validate.VarWithValue(val, field, "isequaltestfunc") Equal(t, errs, nil) val = "unequal" errs = validate.VarWithValue(val, field, "isequaltestfunc") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "isequaltestfunc") } func TestAddFunctions(t *testing.T) { fn := func(fl FieldLevel) bool { return true } fnCtx := func(ctx context.Context, fl FieldLevel) bool { return true } validate := New() errs := validate.RegisterValidation("new", fn) Equal(t, errs, nil) errs = validate.RegisterValidation("", fn) NotEqual(t, errs, nil) errs = validate.RegisterValidation("new", nil) NotEqual(t, errs, nil) errs = validate.RegisterValidation("new", fn) Equal(t, errs, nil) errs = validate.RegisterValidationCtx("new", fnCtx) Equal(t, errs, nil) PanicMatches(t, func() { _ = validate.RegisterValidation("dive", fn) }, "Tag 'dive' either contains restricted characters or is the same as a restricted tag needed for normal operation") } func TestChangeTag(t *testing.T) { validate := New() validate.SetTagName("val") type Test struct { Name string `val:"len=4"` } s := &Test{ Name: "TEST", } errs := validate.Struct(s) Equal(t, errs, nil) s.Name = "" errs = validate.Struct(s) NotEqual(t, errs, nil) AssertError(t, errs, "Test.Name", "Test.Name", "Name", "Name", "len") } func TestUnexposedStruct(t *testing.T) { validate := New() type Test struct { Name string unexposed struct { A string `validate:"required"` } } s := &Test{ Name: "TEST", } Equal(t, s.unexposed.A, "") errs := validate.Struct(s) Equal(t, errs, nil) } func TestBadParams(t *testing.T) { validate := New() i := 1 errs := validate.Var(i, "-") Equal(t, errs, nil) PanicMatches(t, func() { _ = validate.Var(i, "len=a") }, "strconv.ParseInt: parsing \"a\": invalid syntax") PanicMatches(t, func() { _ = validate.Var(i, "len=a") }, "strconv.ParseInt: parsing \"a\": invalid syntax") var ui uint = 1 PanicMatches(t, func() { _ = validate.Var(ui, "len=a") }, "strconv.ParseUint: parsing \"a\": invalid syntax") f := 1.23 PanicMatches(t, func() { _ = validate.Var(f, "len=a") }, "strconv.ParseFloat: parsing \"a\": invalid syntax") } func TestLength(t *testing.T) { validate := New() i := true PanicMatches(t, func() { _ = validate.Var(i, "len") }, "Bad field type bool") } func TestIsGt(t *testing.T) { var errs error validate := New() myMap := map[string]string{} errs = validate.Var(myMap, "gt=0") NotEqual(t, errs, nil) f := 1.23 errs = validate.Var(f, "gt=5") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gt") var ui uint = 5 errs = validate.Var(ui, "gt=10") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gt") i := true PanicMatches(t, func() { _ = validate.Var(i, "gt") }, "Bad field type bool") tm := time.Now().UTC() tm = tm.Add(time.Hour * 24) errs = validate.Var(tm, "gt") Equal(t, errs, nil) t2 := time.Now().UTC().Add(-time.Hour) errs = validate.Var(t2, "gt") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gt") type Test struct { Now *time.Time `validate:"gt"` } s := &Test{ Now: &tm, } errs = validate.Struct(s) Equal(t, errs, nil) s = &Test{ Now: &t2, } errs = validate.Struct(s) NotEqual(t, errs, nil) AssertError(t, errs, "Test.Now", "Test.Now", "Now", "Now", "gt") // Tests for time.Duration type. // -- Validations for a variable of time.Duration type. errs = validate.Var(time.Hour, "gt=59m") Equal(t, errs, nil) errs = validate.Var(time.Hour-time.Minute, "gt=59m") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gt") errs = validate.Var(time.Hour-2*time.Minute, "gt=59m") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gt") errs = validate.Var(time.Duration(0), "omitempty,gt=59m") Equal(t, errs, nil) // -- Validations for a struct with a time.Duration type field. type TimeDurationTest struct { Duration time.Duration `validate:"gt=59m"` } var timeDurationTest *TimeDurationTest timeDurationTest = &TimeDurationTest{time.Hour} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationTest = &TimeDurationTest{time.Hour - time.Minute} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "gt") timeDurationTest = &TimeDurationTest{time.Hour - 2*time.Minute} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "gt") type TimeDurationOmitemptyTest struct { Duration time.Duration `validate:"omitempty,gt=59m"` } timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} errs = validate.Struct(timeDurationOmitemptyTest) Equal(t, errs, nil) } func TestIsGte(t *testing.T) { var errs error validate := New() i := true PanicMatches(t, func() { _ = validate.Var(i, "gte") }, "Bad field type bool") t1 := time.Now().UTC() t1 = t1.Add(time.Hour * 24) errs = validate.Var(t1, "gte") Equal(t, errs, nil) t2 := time.Now().UTC().Add(-time.Hour) errs = validate.Var(t2, "gte") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gte") type Test struct { Now *time.Time `validate:"gte"` } s := &Test{ Now: &t1, } errs = validate.Struct(s) Equal(t, errs, nil) s = &Test{ Now: &t2, } errs = validate.Struct(s) NotEqual(t, errs, nil) AssertError(t, errs, "Test.Now", "Test.Now", "Now", "Now", "gte") // Tests for time.Duration type. // -- Validations for a variable of time.Duration type. errs = validate.Var(time.Hour, "gte=59m") Equal(t, errs, nil) errs = validate.Var(time.Hour-time.Minute, "gte=59m") Equal(t, errs, nil) errs = validate.Var(time.Hour-2*time.Minute, "gte=59m") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "gte") errs = validate.Var(time.Duration(0), "omitempty,gte=59m") Equal(t, errs, nil) // -- Validations for a struct with a time.Duration type field. type TimeDurationTest struct { Duration time.Duration `validate:"gte=59m"` } var timeDurationTest *TimeDurationTest timeDurationTest = &TimeDurationTest{time.Hour} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationTest = &TimeDurationTest{time.Hour - time.Minute} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationTest = &TimeDurationTest{time.Hour - 2*time.Minute} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "gte") type TimeDurationOmitemptyTest struct { Duration time.Duration `validate:"omitempty,gte=59m"` } timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} errs = validate.Struct(timeDurationOmitemptyTest) Equal(t, errs, nil) } func TestMinValidation(t *testing.T) { var errs error validate := New() // Tests for time.Duration type. // -- Validations for a variable of time.Duration type. errs = validate.Var(time.Hour, "min=59m") Equal(t, errs, nil) errs = validate.Var(time.Hour-time.Minute, "min=59m") Equal(t, errs, nil) errs = validate.Var(time.Hour-2*time.Minute, "min=59m") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "min") errs = validate.Var(time.Duration(0), "omitempty,min=59m") Equal(t, errs, nil) // -- Validations for a struct with a time.Duration type field. type TimeDurationTest struct { Duration time.Duration `validate:"min=59m"` } var timeDurationTest *TimeDurationTest timeDurationTest = &TimeDurationTest{time.Hour} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationTest = &TimeDurationTest{time.Hour - time.Minute} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationTest = &TimeDurationTest{time.Hour - 2*time.Minute} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "min") type TimeDurationOmitemptyTest struct { Duration time.Duration `validate:"omitempty,min=59m"` } timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} errs = validate.Struct(timeDurationOmitemptyTest) Equal(t, errs, nil) } func TestMaxValidation(t *testing.T) { var errs error validate := New() // Tests for time.Duration type. // -- Validations for a variable of time.Duration type. errs = validate.Var(time.Hour, "max=1h1m") Equal(t, errs, nil) errs = validate.Var(time.Hour+time.Minute, "max=1h1m") Equal(t, errs, nil) errs = validate.Var(time.Hour+2*time.Minute, "max=1h1m") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "max") errs = validate.Var(time.Duration(0), "omitempty,max=-1s") Equal(t, errs, nil) // -- Validations for a struct with a time.Duration type field. type TimeDurationTest struct { Duration time.Duration `validate:"max=1h1m"` } var timeDurationTest *TimeDurationTest timeDurationTest = &TimeDurationTest{time.Hour} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationTest = &TimeDurationTest{time.Hour + time.Minute} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationTest = &TimeDurationTest{time.Hour + 2*time.Minute} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "max") type TimeDurationOmitemptyTest struct { Duration time.Duration `validate:"omitempty,max=-1s"` } timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} errs = validate.Struct(timeDurationOmitemptyTest) Equal(t, errs, nil) } func TestMinMaxValidation(t *testing.T) { var errs error validate := New() // Tests for time.Duration type. // -- Validations for a variable of time.Duration type. errs = validate.Var(time.Hour, "min=59m,max=1h1m") Equal(t, errs, nil) errs = validate.Var(time.Hour-time.Minute, "min=59m,max=1h1m") Equal(t, errs, nil) errs = validate.Var(time.Hour+time.Minute, "min=59m,max=1h1m") Equal(t, errs, nil) errs = validate.Var(time.Hour-2*time.Minute, "min=59m,max=1h1m") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "min") errs = validate.Var(time.Hour+2*time.Minute, "min=59m,max=1h1m") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "max") errs = validate.Var(time.Duration(0), "omitempty,min=59m,max=1h1m") Equal(t, errs, nil) // -- Validations for a struct with a time.Duration type field. type TimeDurationTest struct { Duration time.Duration `validate:"min=59m,max=1h1m"` } var timeDurationTest *TimeDurationTest timeDurationTest = &TimeDurationTest{time.Hour} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationTest = &TimeDurationTest{time.Hour - time.Minute} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationTest = &TimeDurationTest{time.Hour + time.Minute} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationTest = &TimeDurationTest{time.Hour - 2*time.Minute} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "min") timeDurationTest = &TimeDurationTest{time.Hour + 2*time.Minute} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "max") type TimeDurationOmitemptyTest struct { Duration time.Duration `validate:"omitempty,min=59m,max=1h1m"` } timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} errs = validate.Struct(timeDurationOmitemptyTest) Equal(t, errs, nil) } func TestLenValidation(t *testing.T) { var errs error validate := New() // Tests for time.Duration type. // -- Validations for a variable of time.Duration type. errs = validate.Var(time.Hour, "len=1h") Equal(t, errs, nil) errs = validate.Var(time.Hour-time.Minute, "len=1h") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "len") errs = validate.Var(time.Hour+time.Minute, "len=1h") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "len") errs = validate.Var(time.Duration(0), "omitempty,len=1h") Equal(t, errs, nil) // -- Validations for a struct with a time.Duration type field. type TimeDurationTest struct { Duration time.Duration `validate:"len=1h"` } var timeDurationTest *TimeDurationTest timeDurationTest = &TimeDurationTest{time.Hour} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationTest = &TimeDurationTest{time.Hour - time.Minute} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "len") timeDurationTest = &TimeDurationTest{time.Hour + time.Minute} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "len") type TimeDurationOmitemptyTest struct { Duration time.Duration `validate:"omitempty,len=1h"` } timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} errs = validate.Struct(timeDurationOmitemptyTest) Equal(t, errs, nil) } func TestIsLt(t *testing.T) { var errs error validate := New() myMap := map[string]string{} errs = validate.Var(myMap, "lt=0") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "lt") f := 1.23 errs = validate.Var(f, "lt=0") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "lt") var ui uint = 5 errs = validate.Var(ui, "lt=0") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "lt") i := true PanicMatches(t, func() { _ = validate.Var(i, "lt") }, "Bad field type bool") t1 := time.Now().UTC().Add(-time.Hour) errs = validate.Var(t1, "lt") Equal(t, errs, nil) t2 := time.Now().UTC() t2 = t2.Add(time.Hour * 24) errs = validate.Var(t2, "lt") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "lt") type Test struct { Now *time.Time `validate:"lt"` } s := &Test{ Now: &t1, } errs = validate.Struct(s) Equal(t, errs, nil) s = &Test{ Now: &t2, } errs = validate.Struct(s) NotEqual(t, errs, nil) AssertError(t, errs, "Test.Now", "Test.Now", "Now", "Now", "lt") // Tests for time.Duration type. // -- Validations for a variable of time.Duration type. errs = validate.Var(time.Hour, "lt=1h1m") Equal(t, errs, nil) errs = validate.Var(time.Hour+time.Minute, "lt=1h1m") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "lt") errs = validate.Var(time.Hour+2*time.Minute, "lt=1h1m") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "lt") errs = validate.Var(time.Duration(0), "omitempty,lt=0") Equal(t, errs, nil) // -- Validations for a struct with a time.Duration type field. type TimeDurationTest struct { Duration time.Duration `validate:"lt=1h1m"` } var timeDurationTest *TimeDurationTest timeDurationTest = &TimeDurationTest{time.Hour} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationTest = &TimeDurationTest{time.Hour + time.Minute} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "lt") timeDurationTest = &TimeDurationTest{time.Hour + 2*time.Minute} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "lt") type TimeDurationOmitemptyTest struct { Duration time.Duration `validate:"omitempty,lt=0"` } timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} errs = validate.Struct(timeDurationOmitemptyTest) Equal(t, errs, nil) } func TestIsLte(t *testing.T) { var errs error validate := New() i := true PanicMatches(t, func() { _ = validate.Var(i, "lte") }, "Bad field type bool") t1 := time.Now().UTC().Add(-time.Hour) errs = validate.Var(t1, "lte") Equal(t, errs, nil) t2 := time.Now().UTC() t2 = t2.Add(time.Hour * 24) errs = validate.Var(t2, "lte") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "lte") type Test struct { Now *time.Time `validate:"lte"` } s := &Test{ Now: &t1, } errs = validate.Struct(s) Equal(t, errs, nil) s = &Test{ Now: &t2, } errs = validate.Struct(s) NotEqual(t, errs, nil) // Tests for time.Duration type. // -- Validations for a variable of time.Duration type. errs = validate.Var(time.Hour, "lte=1h1m") Equal(t, errs, nil) errs = validate.Var(time.Hour+time.Minute, "lte=1h1m") Equal(t, errs, nil) errs = validate.Var(time.Hour+2*time.Minute, "lte=1h1m") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "lte") errs = validate.Var(time.Duration(0), "omitempty,lte=-1s") Equal(t, errs, nil) // -- Validations for a struct with a time.Duration type field. type TimeDurationTest struct { Duration time.Duration `validate:"lte=1h1m"` } var timeDurationTest *TimeDurationTest timeDurationTest = &TimeDurationTest{time.Hour} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationTest = &TimeDurationTest{time.Hour + time.Minute} errs = validate.Struct(timeDurationTest) Equal(t, errs, nil) timeDurationTest = &TimeDurationTest{time.Hour + 2*time.Minute} errs = validate.Struct(timeDurationTest) NotEqual(t, errs, nil) AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "lte") type TimeDurationOmitemptyTest struct { Duration time.Duration `validate:"omitempty,lte=-1s"` } timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} errs = validate.Struct(timeDurationOmitemptyTest) Equal(t, errs, nil) } func TestUrnRFC2141(t *testing.T) { tests := []struct { param string expected bool }{ {"urn:a:b", true}, {"urn:a::", true}, {"urn:a:-", true}, {"URN:simple:simple", true}, {"urn:urna:simple", true}, {"urn:burnout:nss", true}, {"urn:burn:nss", true}, {"urn:urnurnurn:x", true}, {"urn:abcdefghilmnopqrstuvzabcdefghilm:x", true}, {"URN:123:x", true}, {"URN:abcd-:x", true}, {"URN:abcd-abcd:x", true}, {"urn:urnx:urn", true}, {"urn:ciao:a:b:c", true}, {"urn:aaa:x:y:", true}, {"urn:ciao:-", true}, {"urn:colon:::::nss", true}, {"urn:ciao:@!=%2C(xyz)+a,b.*@g=$_'", true}, {"URN:hexes:%25", true}, {"URN:x:abc%1Dz%2F%3az", true}, {"URN:foo:a123,456", true}, {"urn:foo:a123,456", true}, {"urn:FOO:a123,456", true}, {"urn:foo:A123,456", true}, {"urn:foo:a123%2C456", true}, {"URN:FOO:a123%2c456", true}, {"URN:FOO:ABC%FFabc123%2c456", true}, {"URN:FOO:ABC%FFabc123%2C456%9A", true}, {"urn:ietf:params:scim:schemas:core:2.0:User", true}, {"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:meta.lastModified", true}, {"URN:-xxx:x", false}, {"urn::colon:nss", false}, {"urn:abcdefghilmnopqrstuvzabcdefghilmn:specificstring", false}, {"URN:a!?:x", false}, {"URN:#,:x", false}, {"urn:urn:NSS", false}, {"urn:URN:NSS", false}, {"urn:white space:NSS", false}, {"urn:concat:no spaces", false}, {"urn:a:%", false}, {"urn:", false}, } tag := "urn_rfc2141" validate := New() for i, test := range tests { errs := validate.Var(test.param, tag) if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d URN failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d URN failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != tag { t.Fatalf("Index: %d URN failed Error: %s", i, errs) } } } } i := 1 PanicMatches(t, func() { _ = validate.Var(i, tag) }, "Bad field type int") } func TestUrl(t *testing.T) { tests := []struct { param string expected bool }{ {"http://foo.bar#com", true}, {"http://foobar.com", true}, {"https://foobar.com", true}, {"foobar.com", false}, {"http://foobar.coffee/", true}, {"http://foobar.中文网/", true}, {"http://foobar.org/", true}, {"http://foobar.org:8080/", true}, {"ftp://foobar.ru/", true}, {"http://user:pass@www.foobar.com/", true}, {"http://127.0.0.1/", true}, {"http://duckduckgo.com/?q=%2F", true}, {"http://localhost:3000/", true}, {"http://foobar.com/?foo=bar#baz=qux", true}, {"http://foobar.com?foo=bar", true}, {"http://www.xn--froschgrn-x9a.net/", true}, {"", false}, {"xyz://foobar.com", true}, {"invalid.", false}, {".com", false}, {"rtmp://foobar.com", true}, {"http://www.foo_bar.com/", true}, {"http://localhost:3000/", true}, {"http://foobar.com/#baz", true}, {"http://foobar.com#baz=qux", true}, {"http://foobar.com/t$-_.+!*\\'(),", true}, {"http://www.foobar.com/~foobar", true}, {"http://www.-foobar.com/", true}, {"http://www.foo---bar.com/", true}, {"mailto:someone@example.com", true}, {"irc://irc.server.org/channel", true}, {"irc://#channel@network", true}, {"/abs/test/dir", false}, {"./rel/test/dir", false}, {"irc:", false}, {"http://", false}, {"file://path/to/file.txt", true}, {"file:///c:/Windows/file.txt", true}, {"file://localhost/path/to/file.txt", true}, {"file://localhost/c:/WINDOWS/file.txt", true}, {"file:", false}, {"file:/", false}, {"file://", false}, {"file:////remotehost/path/file.txt", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "url") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d URL failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d URL failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "url" { t.Fatalf("Index: %d URL failed Error: %s", i, errs) } } } } i := 1 PanicMatches(t, func() { _ = validate.Var(i, "url") }, "Bad field type int") } func TestHttpUrl(t *testing.T) { tests := []struct { param string expected bool }{ {"http://foo.bar#com", true}, {"http://foobar.com", true}, {"HTTP://foobar.com", true}, {"https://foobar.com", true}, {"foobar.com", false}, {"http://foobar.coffee/", true}, {"http://foobar.中文网/", true}, {"http://foobar.org/", true}, {"http://foobar.org:8080/", true}, {"ftp://foobar.ru/", false}, {"file:///etc/passwd", false}, {"file://C:/windows/win.ini", false}, {"http://user:pass@www.foobar.com/", true}, {"http://127.0.0.1/", true}, {"http://duckduckgo.com/?q=%2F", true}, {"http://localhost:3000/", true}, {"http://foobar.com/?foo=bar#baz=qux", true}, {"http://foobar.com?foo=bar", true}, {"http://www.xn--froschgrn-x9a.net/", true}, {"", false}, {"a://b", false}, {"xyz://foobar.com", false}, {"invalid.", false}, {".com", false}, {"rtmp://foobar.com", false}, {"http://www.foo_bar.com/", true}, {"http://localhost:3000/", true}, {"http://foobar.com/#baz", true}, {"http://foobar.com#baz=qux", true}, {"http://foobar.com/t$-_.+!*\\'(),", true}, {"http://www.foobar.com/~foobar", true}, {"http://www.-foobar.com/", true}, {"http://www.foo---bar.com/", true}, {"mailto:someone@example.com", false}, {"irc://irc.server.org/channel", false}, {"irc://#channel@network", false}, {"/abs/test/dir", false}, {"./rel/test/dir", false}, {"http:", false}, {"http://", false}, {"http://#invalid", false}, {"https://1.1.1.1", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "http_url") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d HTTP URL failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d HTTP URL failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "http_url" { t.Fatalf("Index: %d HTTP URL failed Error: %s", i, errs) } } } } i := 1 PanicMatches(t, func() { _ = validate.Var(i, "http_url") }, "Bad field type int") } func TestHttpsUrl(t *testing.T) { tests := []struct { param string expected bool }{ {"https://foo.bar#com", true}, {"https://foobar.com", true}, {"HTTPS://foobar.com", true}, {"http://foobar.com", false}, {"foobar.com", false}, {"https://foobar.coffee/", true}, {"https://foobar.中文网/", true}, {"https://foobar.org/", true}, {"https://foobar.org:8080/", true}, {"ftp://foobar.ru/", false}, {"file:///etc/passwd", false}, {"file://C:/windows/win.ini", false}, {"https://user:pass@www.foobar.com/", true}, {"https://127.0.0.1/", true}, {"https://duckduckgo.com/?q=%2F", true}, {"https://localhost:3000/", true}, {"https://foobar.com/?foo=bar#baz=qux", true}, {"https://foobar.com?foo=bar", true}, {"https://www.xn--froschgrn-x9a.net/", true}, {"", false}, {"a://b", false}, {"xyz://foobar.com", false}, {"invalid.", false}, {".com", false}, {"rtmp://foobar.com", false}, {"https://www.foo_bar.com/", true}, {"https://localhost:3000/", true}, {"https://foobar.com/#baz", true}, {"https://foobar.com#baz=qux", true}, {"https://foobar.com/t$-_.+!*\\'(),", true}, {"https://www.foobar.com/~foobar", true}, {"https://www.-foobar.com/", true}, {"https://www.foo---bar.com/", true}, {"mailto:someone@example.com", false}, {"irc://irc.server.org/channel", false}, {"irc://#channel@network", false}, {"/abs/test/dir", false}, {"./rel/test/dir", false}, {"https:", false}, {"https://", false}, {"https://#invalid", false}, {"http://1.1.1.1", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "https_url") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d HTTPS URL failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d HTTPS URL failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "https_url" { t.Fatalf("Index: %d HTTPS URL failed Error: %s", i, errs) } } } } i := 1 PanicMatches(t, func() { _ = validate.Var(i, "https_url") }, "Bad field type int") } func TestUri(t *testing.T) { tests := []struct { param string expected bool }{ {"http://foo.bar#com", true}, {"http://foobar.com", true}, {"https://foobar.com", true}, {"foobar.com", false}, {"http://foobar.coffee/", true}, {"http://foobar.中文网/", true}, {"http://foobar.org/", true}, {"http://foobar.org:8080/", true}, {"ftp://foobar.ru/", true}, {"http://user:pass@www.foobar.com/", true}, {"http://127.0.0.1/", true}, {"http://duckduckgo.com/?q=%2F", true}, {"http://localhost:3000/", true}, {"http://foobar.com/?foo=bar#baz=qux", true}, {"http://foobar.com?foo=bar", true}, {"http://www.xn--froschgrn-x9a.net/", true}, {"", false}, {"xyz://foobar.com", true}, {"invalid.", false}, {".com", false}, {"rtmp://foobar.com", true}, {"http://www.foo_bar.com/", true}, {"http://localhost:3000/", true}, {"http://foobar.com#baz=qux", true}, {"http://foobar.com/t$-_.+!*\\'(),", true}, {"http://www.foobar.com/~foobar", true}, {"http://www.-foobar.com/", true}, {"http://www.foo---bar.com/", true}, {"mailto:someone@example.com", true}, {"irc://irc.server.org/channel", true}, {"irc://#channel@network", true}, {"/abs/test/dir", true}, {"./rel/test/dir", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "uri") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d URI failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d URI failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "uri" { t.Fatalf("Index: %d URI failed Error: %s", i, errs) } } } } i := 1 PanicMatches(t, func() { _ = validate.Var(i, "uri") }, "Bad field type int") } func TestOrTag(t *testing.T) { validate := New() s := "rgba(0,31,255,0.5)" errs := validate.Var(s, "rgb|rgba") Equal(t, errs, nil) s = "rgba(0,31,255,0.5)" errs = validate.Var(s, "rgb|rgba|len=18") Equal(t, errs, nil) s = "this ain't right" errs = validate.Var(s, "rgb|rgba") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "rgb|rgba") s = "this ain't right" errs = validate.Var(s, "rgb|rgba|len=10") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "rgb|rgba|len=10") s = "this is right" errs = validate.Var(s, "rgb|rgba|len=13") Equal(t, errs, nil) s = "" errs = validate.Var(s, "omitempty,rgb|rgba") Equal(t, errs, nil) s = "green" errs = validate.Var(s, "eq=|eq=blue,rgb|rgba") // should fail on first validation block NotEqual(t, errs, nil) ve := errs.(ValidationErrors) Equal(t, len(ve), 1) Equal(t, ve[0].Tag(), "eq=|eq=blue") s = "this is right, but a blank or isn't" PanicMatches(t, func() { _ = validate.Var(s, "rgb||len=13") }, "Invalid validation tag on field ''") PanicMatches(t, func() { _ = validate.Var(s, "rgb|rgbaa|len=13") }, "Undefined validation function 'rgbaa' on field ''") v2 := New() v2.RegisterTagNameFunc(func(fld reflect.StructField) string { name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] if name == "-" { return "" } return name }) type Colors struct { Fav string `validate:"rgb|rgba" json:"fc"` } c := Colors{Fav: "this ain't right"} err := v2.Struct(c) NotEqual(t, err, nil) errs = err.(ValidationErrors) fe := getError(errs, "Colors.fc", "Colors.Fav") NotEqual(t, fe, nil) } func TestHsla(t *testing.T) { validate := New() s := "hsla(360,100%,100%,1)" errs := validate.Var(s, "hsla") Equal(t, errs, nil) s = "hsla(360,100%,100%,0.5)" errs = validate.Var(s, "hsla") Equal(t, errs, nil) s = "hsla(0,0%,0%, 0)" errs = validate.Var(s, "hsla") Equal(t, errs, nil) s = "hsl(361,100%,50%,1)" errs = validate.Var(s, "hsla") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "hsla") s = "hsl(361,100%,50%)" errs = validate.Var(s, "hsla") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "hsla") s = "hsla(361,100%,50%)" errs = validate.Var(s, "hsla") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "hsla") s = "hsla(360,101%,50%)" errs = validate.Var(s, "hsla") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "hsla") s = "hsla(360,100%,101%)" errs = validate.Var(s, "hsla") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "hsla") i := 1 errs = validate.Var(i, "hsla") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "hsla") } func TestHsl(t *testing.T) { validate := New() s := "hsl(360,100%,50%)" errs := validate.Var(s, "hsl") Equal(t, errs, nil) s = "hsl(0,0%,0%)" errs = validate.Var(s, "hsl") Equal(t, errs, nil) s = "hsl(361,100%,50%)" errs = validate.Var(s, "hsl") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "hsl") s = "hsl(361,101%,50%)" errs = validate.Var(s, "hsl") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "hsl") s = "hsl(361,100%,101%)" errs = validate.Var(s, "hsl") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "hsl") s = "hsl(-10,100%,100%)" errs = validate.Var(s, "hsl") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "hsl") i := 1 errs = validate.Var(i, "hsl") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "hsl") } func TestRgba(t *testing.T) { validate := New() s := "rgba(0,31,255,0.5)" errs := validate.Var(s, "rgba") Equal(t, errs, nil) s = "rgba(0,31,255,0.12)" errs = validate.Var(s, "rgba") Equal(t, errs, nil) s = "rgba(12%,55%,100%,0.12)" errs = validate.Var(s, "rgba") Equal(t, errs, nil) s = "rgba( 0, 31, 255, 0.5)" errs = validate.Var(s, "rgba") Equal(t, errs, nil) s = "rgba(12%,55,100%,0.12)" errs = validate.Var(s, "rgba") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "rgba") s = "rgb(0, 31, 255)" errs = validate.Var(s, "rgba") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "rgba") s = "rgb(1,349,275,0.5)" errs = validate.Var(s, "rgba") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "rgba") s = "rgb(01,31,255,0.5)" errs = validate.Var(s, "rgba") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "rgba") i := 1 errs = validate.Var(i, "rgba") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "rgba") } func TestRgb(t *testing.T) { validate := New() s := "rgb(0,31,255)" errs := validate.Var(s, "rgb") Equal(t, errs, nil) s = "rgb(0, 31, 255)" errs = validate.Var(s, "rgb") Equal(t, errs, nil) s = "rgb(10%, 50%, 100%)" errs = validate.Var(s, "rgb") Equal(t, errs, nil) s = "rgb(10%, 50%, 55)" errs = validate.Var(s, "rgb") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "rgb") s = "rgb(1,349,275)" errs = validate.Var(s, "rgb") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "rgb") s = "rgb(01,31,255)" errs = validate.Var(s, "rgb") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "rgb") s = "rgba(0,31,255)" errs = validate.Var(s, "rgb") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "rgb") i := 1 errs = validate.Var(i, "rgb") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "rgb") } func TestE164(t *testing.T) { validate := New() tests := []struct { number string expected bool }{ {"+12025550123", true}, {"+447911123456", true}, {"0123456789", false}, {"++12025550123", false}, {"+1 202-555-0123", false}, {"1234567", false}, {"12345678", true}, {"123456", false}, {"0123456789", false}, } for _, test := range tests { t.Run(test.number, func(t *testing.T) { errs := validate.Var(test.number, "e164") if test.expected { Equal(t, errs, nil) } else { NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "e164") } }) } } func TestEmail(t *testing.T) { validate := New() s := "test@mail.com" errs := validate.Var(s, "email") Equal(t, errs, nil) s = "Dörte@Sörensen.example.com" errs = validate.Var(s, "email") Equal(t, errs, nil) s = "θσερ@εχαμπλε.ψομ" errs = validate.Var(s, "email") Equal(t, errs, nil) s = "юзер@екзампл.ком" errs = validate.Var(s, "email") Equal(t, errs, nil) s = "उपयोगकर्ता@उदाहरण.कॉम" errs = validate.Var(s, "email") Equal(t, errs, nil) s = "用户@例子.广告" errs = validate.Var(s, "email") Equal(t, errs, nil) s = "mail@domain_with_underscores.org" errs = validate.Var(s, "email") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "email") s = "mail@dotaftercom.com." errs = validate.Var(s, "email") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "email") s = "mail@dotaftercom.co.uk." errs = validate.Var(s, "email") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "email") s = "Foo Bar " errs = validate.Var(s, "email") NotEqual(t, errs, nil) s = "" errs = validate.Var(s, "email") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "email") s = "test@email" errs = validate.Var(s, "email") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "email") s = "test@email." errs = validate.Var(s, "email") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "email") s = "@email.com" errs = validate.Var(s, "email") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "email") s = `"test test"@email.com` errs = validate.Var(s, "email") Equal(t, errs, nil) s = `"@email.com` errs = validate.Var(s, "email") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "email") i := true errs = validate.Var(i, "email") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "email") } func TestHexColor(t *testing.T) { validate := New() s := "#fff" errs := validate.Var(s, "hexcolor") Equal(t, errs, nil) s = "#c2c2c2" errs = validate.Var(s, "hexcolor") Equal(t, errs, nil) s = "fff" errs = validate.Var(s, "hexcolor") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "hexcolor") s = "fffFF" errs = validate.Var(s, "hexcolor") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "hexcolor") i := true errs = validate.Var(i, "hexcolor") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "hexcolor") } func TestHexadecimal(t *testing.T) { validate := New() s := "ff0044" errs := validate.Var(s, "hexadecimal") Equal(t, errs, nil) s = "0xff0044" errs = validate.Var(s, "hexadecimal") Equal(t, errs, nil) s = "0Xff0044" errs = validate.Var(s, "hexadecimal") Equal(t, errs, nil) s = "abcdefg" errs = validate.Var(s, "hexadecimal") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "hexadecimal") i := true errs = validate.Var(i, "hexadecimal") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "hexadecimal") } func TestNumber(t *testing.T) { validate := New() s := "1" errs := validate.Var(s, "number") Equal(t, errs, nil) s = "+1" errs = validate.Var(s, "number") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "number") s = "-1" errs = validate.Var(s, "number") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "number") s = "1.12" errs = validate.Var(s, "number") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "number") s = "+1.12" errs = validate.Var(s, "number") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "number") s = "-1.12" errs = validate.Var(s, "number") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "number") s = "1." errs = validate.Var(s, "number") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "number") s = "1.o" errs = validate.Var(s, "number") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "number") i := 1 errs = validate.Var(i, "number") Equal(t, errs, nil) } func TestNumeric(t *testing.T) { validate := New() s := "1" errs := validate.Var(s, "numeric") Equal(t, errs, nil) s = "+1" errs = validate.Var(s, "numeric") Equal(t, errs, nil) s = "-1" errs = validate.Var(s, "numeric") Equal(t, errs, nil) s = "1.12" errs = validate.Var(s, "numeric") Equal(t, errs, nil) s = "+1.12" errs = validate.Var(s, "numeric") Equal(t, errs, nil) s = "-1.12" errs = validate.Var(s, "numeric") Equal(t, errs, nil) s = "1." errs = validate.Var(s, "numeric") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "numeric") s = "1.o" errs = validate.Var(s, "numeric") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "numeric") i := 1 errs = validate.Var(i, "numeric") Equal(t, errs, nil) } func TestBoolean(t *testing.T) { validate := New() b := true errs := validate.Var(b, "boolean") Equal(t, errs, nil) b = false errs = validate.Var(b, "boolean") Equal(t, errs, nil) s := "true" errs = validate.Var(s, "boolean") Equal(t, errs, nil) s = "false" errs = validate.Var(s, "boolean") Equal(t, errs, nil) s = "0" errs = validate.Var(s, "boolean") Equal(t, errs, nil) s = "1" errs = validate.Var(s, "boolean") Equal(t, errs, nil) s = "xyz" errs = validate.Var(s, "boolean") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "boolean") s = "1." errs = validate.Var(s, "boolean") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "boolean") } func TestAlphaNumeric(t *testing.T) { validate := New() s := "abcd123" errs := validate.Var(s, "alphanum") Equal(t, errs, nil) s = "abc!23" errs = validate.Var(s, "alphanum") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "alphanum") errs = validate.Var(1, "alphanum") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "alphanum") } func TestAlpha(t *testing.T) { validate := New() s := "abcd" errs := validate.Var(s, "alpha") Equal(t, errs, nil) s = "abc®" errs = validate.Var(s, "alpha") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "alpha") s = "abc÷" errs = validate.Var(s, "alpha") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "alpha") s = "abc1" errs = validate.Var(s, "alpha") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "alpha") s = "this is a test string" errs = validate.Var(s, "alpha") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "alpha") errs = validate.Var(1, "alpha") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "alpha") } func TestAlphaSpace(t *testing.T) { validate := New() s := "abcd" errs := validate.Var(s, "alphaspace") Equal(t, errs, nil) s = "abc def" errs = validate.Var(s, "alphaspace") Equal(t, errs, nil) s = " " errs = validate.Var(s, "alphaspace") Equal(t, errs, nil) s = "abc!" errs = validate.Var(s, "alphaspace") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "alphaspace") errs = validate.Var(1, "alphaspace") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "alphaspace") } func TestAlphaNumericSpace(t *testing.T) { validate := New() s := "abcd 123" errs := validate.Var(s, "alphanumspace") Equal(t, errs, nil) s = " " errs = validate.Var(s, "alphanumspace") Equal(t, errs, nil) s = "abc123" errs = validate.Var(s, "alphanumspace") Equal(t, errs, nil) s = "123" errs = validate.Var(s, "alphanumspace") Equal(t, errs, nil) s = "abc" errs = validate.Var(s, "alphanumspace") Equal(t, errs, nil) s = "áçć 123" errs = validate.Var(s, "alphanumspace") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "alphanumspace") s = "日本 123" errs = validate.Var(s, "alphanumspace") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "alphanumspace") s = "abc!" errs = validate.Var(s, "alphanumspace") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "alphanumspace") s = "abc\t123" errs = validate.Var(s, "alphanumspace") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "alphanumspace") s = "abc\n123" errs = validate.Var(s, "alphanumspace") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "alphanumspace") s = "abc-123" errs = validate.Var(s, "alphanumspace") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "alphanumspace") s = "abc🙂123" errs = validate.Var(s, "alphanumspace") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "alphanumspace") errs = validate.Var(1, "alphanumspace") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "alphanumspace") errs = validate.Var(1.23, "alphanumspace") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "alphanumspace") } func TestStructStringValidation(t *testing.T) { validate := New() tSuccess := &TestString{ Required: "Required", Len: "length==10", Min: "min=1", Max: "1234567890", MinMax: "12345", Lt: "012345678", Lte: "0123456789", Gt: "01234567890", Gte: "0123456789", Boolean: "true", OmitEmpty: "", Sub: &SubTest{ Test: "1", }, SubIgnore: &SubTest{ Test: "", }, Anonymous: struct { A string `validate:"required"` }{ A: "1", }, Iface: &Impl{ F: "123", }, } errs := validate.Struct(tSuccess) Equal(t, errs, nil) tFail := &TestString{ Required: "", Len: "", Min: "", Max: "12345678901", MinMax: "", Lt: "0123456789", Lte: "01234567890", Gt: "1", Gte: "1", OmitEmpty: "12345678901", Boolean: "nope", Sub: &SubTest{ Test: "", }, Anonymous: struct { A string `validate:"required"` }{ A: "", }, Iface: &Impl{ F: "12", }, } errs = validate.Struct(tFail) // Assert Top Level NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 14) // Assert Fields AssertError(t, errs, "TestString.Required", "TestString.Required", "Required", "Required", "required") AssertError(t, errs, "TestString.Len", "TestString.Len", "Len", "Len", "len") AssertError(t, errs, "TestString.Min", "TestString.Min", "Min", "Min", "min") AssertError(t, errs, "TestString.Max", "TestString.Max", "Max", "Max", "max") AssertError(t, errs, "TestString.MinMax", "TestString.MinMax", "MinMax", "MinMax", "min") AssertError(t, errs, "TestString.Lt", "TestString.Lt", "Lt", "Lt", "lt") AssertError(t, errs, "TestString.Lte", "TestString.Lte", "Lte", "Lte", "lte") AssertError(t, errs, "TestString.Gt", "TestString.Gt", "Gt", "Gt", "gt") AssertError(t, errs, "TestString.Gte", "TestString.Gte", "Gte", "Gte", "gte") AssertError(t, errs, "TestString.OmitEmpty", "TestString.OmitEmpty", "OmitEmpty", "OmitEmpty", "max") AssertError(t, errs, "TestString.Boolean", "TestString.Boolean", "Boolean", "Boolean", "boolean") // Nested Struct Field Errs AssertError(t, errs, "TestString.Anonymous.A", "TestString.Anonymous.A", "A", "A", "required") AssertError(t, errs, "TestString.Sub.Test", "TestString.Sub.Test", "Test", "Test", "required") AssertError(t, errs, "TestString.Iface.F", "TestString.Iface.F", "F", "F", "len") } func TestStructInt32Validation(t *testing.T) { type TestInt32 struct { Required int `validate:"required"` Len int `validate:"len=10"` Min int `validate:"min=1"` Max int `validate:"max=10"` MinMax int `validate:"min=1,max=10"` Lt int `validate:"lt=10"` Lte int `validate:"lte=10"` Gt int `validate:"gt=10"` Gte int `validate:"gte=10"` OmitEmpty int `validate:"omitempty,min=1,max=10"` } tSuccess := &TestInt32{ Required: 1, Len: 10, Min: 1, Max: 10, MinMax: 5, Lt: 9, Lte: 10, Gt: 11, Gte: 10, OmitEmpty: 0, } validate := New() errs := validate.Struct(tSuccess) Equal(t, errs, nil) tFail := &TestInt32{ Required: 0, Len: 11, Min: -1, Max: 11, MinMax: -1, Lt: 10, Lte: 11, Gt: 10, Gte: 9, OmitEmpty: 11, } errs = validate.Struct(tFail) // Assert Top Level NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 10) // Assert Fields AssertError(t, errs, "TestInt32.Required", "TestInt32.Required", "Required", "Required", "required") AssertError(t, errs, "TestInt32.Len", "TestInt32.Len", "Len", "Len", "len") AssertError(t, errs, "TestInt32.Min", "TestInt32.Min", "Min", "Min", "min") AssertError(t, errs, "TestInt32.Max", "TestInt32.Max", "Max", "Max", "max") AssertError(t, errs, "TestInt32.MinMax", "TestInt32.MinMax", "MinMax", "MinMax", "min") AssertError(t, errs, "TestInt32.Lt", "TestInt32.Lt", "Lt", "Lt", "lt") AssertError(t, errs, "TestInt32.Lte", "TestInt32.Lte", "Lte", "Lte", "lte") AssertError(t, errs, "TestInt32.Gt", "TestInt32.Gt", "Gt", "Gt", "gt") AssertError(t, errs, "TestInt32.Gte", "TestInt32.Gte", "Gte", "Gte", "gte") AssertError(t, errs, "TestInt32.OmitEmpty", "TestInt32.OmitEmpty", "OmitEmpty", "OmitEmpty", "max") } func TestStructUint64Validation(t *testing.T) { validate := New() tSuccess := &TestUint64{ Required: 1, Len: 10, Min: 1, Max: 10, MinMax: 5, OmitEmpty: 0, } errs := validate.Struct(tSuccess) Equal(t, errs, nil) tFail := &TestUint64{ Required: 0, Len: 11, Min: 0, Max: 11, MinMax: 0, OmitEmpty: 11, } errs = validate.Struct(tFail) // Assert Top Level NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 6) // Assert Fields AssertError(t, errs, "TestUint64.Required", "TestUint64.Required", "Required", "Required", "required") AssertError(t, errs, "TestUint64.Len", "TestUint64.Len", "Len", "Len", "len") AssertError(t, errs, "TestUint64.Min", "TestUint64.Min", "Min", "Min", "min") AssertError(t, errs, "TestUint64.Max", "TestUint64.Max", "Max", "Max", "max") AssertError(t, errs, "TestUint64.MinMax", "TestUint64.MinMax", "MinMax", "MinMax", "min") AssertError(t, errs, "TestUint64.OmitEmpty", "TestUint64.OmitEmpty", "OmitEmpty", "OmitEmpty", "max") } func TestStructFloat64Validation(t *testing.T) { validate := New() tSuccess := &TestFloat64{ Required: 1, Len: 10, Min: 1, Max: 10, MinMax: 5, OmitEmpty: 0, } errs := validate.Struct(tSuccess) Equal(t, errs, nil) tFail := &TestFloat64{ Required: 0, Len: 11, Min: 0, Max: 11, MinMax: 0, OmitEmpty: 11, } errs = validate.Struct(tFail) // Assert Top Level NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 6) // Assert Fields AssertError(t, errs, "TestFloat64.Required", "TestFloat64.Required", "Required", "Required", "required") AssertError(t, errs, "TestFloat64.Len", "TestFloat64.Len", "Len", "Len", "len") AssertError(t, errs, "TestFloat64.Min", "TestFloat64.Min", "Min", "Min", "min") AssertError(t, errs, "TestFloat64.Max", "TestFloat64.Max", "Max", "Max", "max") AssertError(t, errs, "TestFloat64.MinMax", "TestFloat64.MinMax", "MinMax", "MinMax", "min") AssertError(t, errs, "TestFloat64.OmitEmpty", "TestFloat64.OmitEmpty", "OmitEmpty", "OmitEmpty", "max") } func TestStructSliceValidation(t *testing.T) { validate := New() tSuccess := &TestSlice{ Required: []int{1}, Len: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, Min: []int{1, 2}, Max: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, MinMax: []int{1, 2, 3, 4, 5}, OmitEmpty: nil, } errs := validate.Struct(tSuccess) Equal(t, errs, nil) tFail := &TestSlice{ Required: nil, Len: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1}, Min: []int{}, Max: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1}, MinMax: []int{}, OmitEmpty: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1}, } errs = validate.Struct(tFail) NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 6) // Assert Field Errors AssertError(t, errs, "TestSlice.Required", "TestSlice.Required", "Required", "Required", "required") AssertError(t, errs, "TestSlice.Len", "TestSlice.Len", "Len", "Len", "len") AssertError(t, errs, "TestSlice.Min", "TestSlice.Min", "Min", "Min", "min") AssertError(t, errs, "TestSlice.Max", "TestSlice.Max", "Max", "Max", "max") AssertError(t, errs, "TestSlice.MinMax", "TestSlice.MinMax", "MinMax", "MinMax", "min") AssertError(t, errs, "TestSlice.OmitEmpty", "TestSlice.OmitEmpty", "OmitEmpty", "OmitEmpty", "max") fe := getError(errs, "TestSlice.Len", "TestSlice.Len") NotEqual(t, fe, nil) Equal(t, fe.Field(), "Len") Equal(t, fe.StructField(), "Len") Equal(t, fe.Namespace(), "TestSlice.Len") Equal(t, fe.StructNamespace(), "TestSlice.Len") Equal(t, fe.Tag(), "len") Equal(t, fe.ActualTag(), "len") Equal(t, fe.Param(), "10") Equal(t, fe.Kind(), reflect.Slice) Equal(t, fe.Type(), reflect.TypeOf([]int{})) _, ok := fe.Value().([]int) Equal(t, ok, true) } func TestInvalidStruct(t *testing.T) { validate := New() s := &SubTest{ Test: "1", } err := validate.Struct(s.Test) NotEqual(t, err, nil) Equal(t, err.Error(), "validator: (nil string)") err = validate.Struct(nil) NotEqual(t, err, nil) Equal(t, err.Error(), "validator: (nil)") err = validate.StructPartial(nil, "SubTest.Test") NotEqual(t, err, nil) Equal(t, err.Error(), "validator: (nil)") err = validate.StructExcept(nil, "SubTest.Test") NotEqual(t, err, nil) Equal(t, err.Error(), "validator: (nil)") } func TestInvalidValidatorFunction(t *testing.T) { validate := New() s := &SubTest{ Test: "1", } PanicMatches(t, func() { _ = validate.Var(s.Test, "zzxxBadFunction") }, "Undefined validation function 'zzxxBadFunction' on field ''") } func TestCustomFieldName(t *testing.T) { validate := New() validate.RegisterTagNameFunc(func(fld reflect.StructField) string { name := strings.SplitN(fld.Tag.Get("schema"), ",", 2)[0] if name == "-" { return "" } return name }) type A struct { B string `schema:"b" validate:"required"` C string `schema:"c" validate:"required"` D []bool `schema:"d" validate:"required"` E string `schema:"-" validate:"required"` } a := &A{} err := validate.Struct(a) NotEqual(t, err, nil) errs := err.(ValidationErrors) Equal(t, len(errs), 4) Equal(t, getError(errs, "A.b", "A.B").Field(), "b") Equal(t, getError(errs, "A.c", "A.C").Field(), "c") Equal(t, getError(errs, "A.d", "A.D").Field(), "d") Equal(t, getError(errs, "A.E", "A.E").Field(), "E") v2 := New() err = v2.Struct(a) NotEqual(t, err, nil) errs = err.(ValidationErrors) Equal(t, len(errs), 4) Equal(t, getError(errs, "A.B", "A.B").Field(), "B") Equal(t, getError(errs, "A.C", "A.C").Field(), "C") Equal(t, getError(errs, "A.D", "A.D").Field(), "D") Equal(t, getError(errs, "A.E", "A.E").Field(), "E") } func TestMultipleRecursiveExtractStructCache(t *testing.T) { validate := New() type Recursive struct { Field *string `validate:"required,len=5,ne=string"` } var test Recursive current := reflect.ValueOf(test) name := "Recursive" proceed := make(chan struct{}) sc := validate.extractStructCache(current, name) ptr := fmt.Sprintf("%p", sc) for i := 0; i < 100; i++ { go func() { <-proceed sc := validate.extractStructCache(current, name) Equal(t, ptr, fmt.Sprintf("%p", sc)) }() } close(proceed) } // Thanks @robbrockbank, see https://github.com/go-playground/validator/issues/249 func TestPointerAndOmitEmpty(t *testing.T) { validate := New() type Test struct { MyInt *int `validate:"omitempty,gte=2,lte=255"` } val1 := 0 val2 := 256 t1 := Test{MyInt: &val1} // This should fail validation on gte because value is 0 t2 := Test{MyInt: &val2} // This should fail validate on lte because value is 256 t3 := Test{MyInt: nil} // This should succeed validation because pointer is nil errs := validate.Struct(t1) NotEqual(t, errs, nil) AssertError(t, errs, "Test.MyInt", "Test.MyInt", "MyInt", "MyInt", "gte") errs = validate.Struct(t2) NotEqual(t, errs, nil) AssertError(t, errs, "Test.MyInt", "Test.MyInt", "MyInt", "MyInt", "lte") errs = validate.Struct(t3) Equal(t, errs, nil) type TestIface struct { MyInt interface{} `validate:"omitempty,gte=2,lte=255"` } ti1 := TestIface{MyInt: &val1} // This should fail validation on gte because value is 0 ti2 := TestIface{MyInt: &val2} // This should fail validate on lte because value is 256 ti3 := TestIface{MyInt: nil} // This should succeed validation because pointer is nil errs = validate.Struct(ti1) NotEqual(t, errs, nil) AssertError(t, errs, "TestIface.MyInt", "TestIface.MyInt", "MyInt", "MyInt", "gte") errs = validate.Struct(ti2) NotEqual(t, errs, nil) AssertError(t, errs, "TestIface.MyInt", "TestIface.MyInt", "MyInt", "MyInt", "lte") errs = validate.Struct(ti3) Equal(t, errs, nil) } func TestRequired(t *testing.T) { validate := New() validate.RegisterTagNameFunc(func(fld reflect.StructField) string { name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] if name == "-" { return "" } return name }) type Test struct { Value interface{} `validate:"required"` } var test Test err := validate.Struct(test) NotEqual(t, err, nil) AssertError(t, err.(ValidationErrors), "Test.Value", "Test.Value", "Value", "Value", "required") } func TestBoolEqual(t *testing.T) { validate := New() type Test struct { Value bool `validate:"eq=true"` } var test Test err := validate.Struct(test) NotEqual(t, err, nil) AssertError(t, err.(ValidationErrors), "Test.Value", "Test.Value", "Value", "Value", "eq") test.Value = true err = validate.Struct(test) Equal(t, err, nil) } func TestTranslations(t *testing.T) { en := en.New() uni := ut.New(en, en, fr.New()) trans, _ := uni.GetTranslator("en") fr, _ := uni.GetTranslator("fr") validate := New() err := validate.RegisterTranslation("required", trans, func(ut ut.Translator) (err error) { // using this stype because multiple translation may have to be added for the full translation if err = ut.Add("required", "{0} is a required field", false); err != nil { return } return }, func(ut ut.Translator, fe FieldError) string { t, err := ut.T(fe.Tag(), fe.Field()) if err != nil { fmt.Printf("warning: error translating FieldError: %#v", fe.(*fieldError)) return fe.(*fieldError).Error() } return t }) Equal(t, err, nil) err = validate.RegisterTranslation("required", fr, func(ut ut.Translator) (err error) { // using this stype because multiple translation may have to be added for the full translation if err = ut.Add("required", "{0} est un champ obligatoire", false); err != nil { return } return }, func(ut ut.Translator, fe FieldError) string { t, transErr := ut.T(fe.Tag(), fe.Field()) if transErr != nil { fmt.Printf("warning: error translating FieldError: %#v", fe.(*fieldError)) return fe.(*fieldError).Error() } return t }) Equal(t, err, nil) type Test struct { Value interface{} `validate:"required"` } var test Test err = validate.Struct(test) NotEqual(t, err, nil) errs := err.(ValidationErrors) Equal(t, len(errs), 1) fe := errs[0] Equal(t, fe.Tag(), "required") Equal(t, fe.Namespace(), "Test.Value") Equal(t, fe.Translate(trans), fmt.Sprintf("%s is a required field", fe.Field())) Equal(t, fe.Translate(fr), fmt.Sprintf("%s est un champ obligatoire", fe.Field())) nl := nl.New() uni2 := ut.New(nl, nl) trans2, _ := uni2.GetTranslator("nl") Equal(t, fe.Translate(trans2), "Key: 'Test.Value' Error:Field validation for 'Value' failed on the 'required' tag") terrs := errs.Translate(trans) Equal(t, len(terrs), 1) v, ok := terrs["Test.Value"] Equal(t, ok, true) Equal(t, v, fmt.Sprintf("%s is a required field", fe.Field())) terrs = errs.Translate(fr) Equal(t, len(terrs), 1) v, ok = terrs["Test.Value"] Equal(t, ok, true) Equal(t, v, fmt.Sprintf("%s est un champ obligatoire", fe.Field())) type Test2 struct { Value string `validate:"gt=1"` } var t2 Test2 err = validate.Struct(t2) NotEqual(t, err, nil) errs = err.(ValidationErrors) Equal(t, len(errs), 1) fe = errs[0] Equal(t, fe.Tag(), "gt") Equal(t, fe.Namespace(), "Test2.Value") Equal(t, fe.Translate(trans), "Key: 'Test2.Value' Error:Field validation for 'Value' failed on the 'gt' tag") } func TestTranslationErrors(t *testing.T) { en := en.New() uni := ut.New(en, en, fr.New()) trans, _ := uni.GetTranslator("en") err := trans.Add("required", "{0} is a required field", false) // using translator outside of validator also Equal(t, err, nil) validate := New() err = validate.RegisterTranslation("required", trans, func(ut ut.Translator) (err error) { // using this stype because multiple translation may have to be added for the full translation if err = ut.Add("required", "{0} is a required field", false); err != nil { return } return }, func(ut ut.Translator, fe FieldError) string { t, err := ut.T(fe.Tag(), fe.Field()) if err != nil { fmt.Printf("warning: error translating FieldError: %#v", fe.(*fieldError)) return fe.(*fieldError).Error() } return t }) NotEqual(t, err, nil) Equal(t, err.Error(), "error: conflicting key 'required' rule 'Unknown' with text '{0} is a required field' for locale 'en', value being ignored") } func TestStructFiltered(t *testing.T) { p1 := func(ns []byte) bool { if bytes.HasSuffix(ns, []byte("NoTag")) || bytes.HasSuffix(ns, []byte("Required")) { return false } return true } p2 := func(ns []byte) bool { if bytes.HasSuffix(ns, []byte("SubSlice[0].Test")) || bytes.HasSuffix(ns, []byte("SubSlice[0]")) || bytes.HasSuffix(ns, []byte("SubSlice")) || bytes.HasSuffix(ns, []byte("Sub")) || bytes.HasSuffix(ns, []byte("SubIgnore")) || bytes.HasSuffix(ns, []byte("Anonymous")) || bytes.HasSuffix(ns, []byte("Anonymous.A")) { return false } return true } p3 := func(ns []byte) bool { return !bytes.HasSuffix(ns, []byte("SubTest.Test")) } // p4 := []string{ // "A", // } tPartial := &TestPartial{ NoTag: "NoTag", Required: "Required", SubSlice: []*SubTest{ { Test: "Required", }, { Test: "Required", }, }, Sub: &SubTest{ Test: "1", }, SubIgnore: &SubTest{ Test: "", }, Anonymous: struct { A string `validate:"required"` ASubSlice []*SubTest `validate:"required,dive"` SubAnonStruct []struct { Test string `validate:"required"` OtherTest string `validate:"required"` } `validate:"required,dive"` }{ A: "1", ASubSlice: []*SubTest{ { Test: "Required", }, { Test: "Required", }, }, SubAnonStruct: []struct { Test string `validate:"required"` OtherTest string `validate:"required"` }{ {"Required", "RequiredOther"}, {"Required", "RequiredOther"}, }, }, } validate := New() // the following should all return no errors as everything is valid in // the default state errs := validate.StructFilteredCtx(context.Background(), tPartial, p1) Equal(t, errs, nil) errs = validate.StructFiltered(tPartial, p2) Equal(t, errs, nil) // this isn't really a robust test, but is meant to illustrate the ANON CASE below errs = validate.StructFiltered(tPartial.SubSlice[0], p3) Equal(t, errs, nil) // mod tPartial for required field and re-test making sure invalid fields are NOT required: tPartial.Required = "" // inversion and retesting Partial to generate failures: errs = validate.StructFiltered(tPartial, p1) NotEqual(t, errs, nil) AssertError(t, errs, "TestPartial.Required", "TestPartial.Required", "Required", "Required", "required") // reset Required field, and set nested struct tPartial.Required = "Required" tPartial.Anonymous.A = "" // will pass as unset fields is not going to be tested errs = validate.StructFiltered(tPartial, p1) Equal(t, errs, nil) // will fail as unset field is tested errs = validate.StructFiltered(tPartial, p2) NotEqual(t, errs, nil) AssertError(t, errs, "TestPartial.Anonymous.A", "TestPartial.Anonymous.A", "A", "A", "required") // reset nested struct and unset struct in slice tPartial.Anonymous.A = "Required" tPartial.SubSlice[0].Test = "" // these will pass as unset item is NOT tested errs = validate.StructFiltered(tPartial, p1) Equal(t, errs, nil) errs = validate.StructFiltered(tPartial, p2) NotEqual(t, errs, nil) AssertError(t, errs, "TestPartial.SubSlice[0].Test", "TestPartial.SubSlice[0].Test", "Test", "Test", "required") Equal(t, len(errs.(ValidationErrors)), 1) // Unset second slice member concurrently to test dive behavior: tPartial.SubSlice[1].Test = "" errs = validate.StructFiltered(tPartial, p1) Equal(t, errs, nil) errs = validate.StructFiltered(tPartial, p2) NotEqual(t, errs, nil) Equal(t, len(errs.(ValidationErrors)), 1) AssertError(t, errs, "TestPartial.SubSlice[0].Test", "TestPartial.SubSlice[0].Test", "Test", "Test", "required") // reset struct in slice, and unset struct in slice in unset position tPartial.SubSlice[0].Test = "Required" // these will pass as the unset item is NOT tested errs = validate.StructFiltered(tPartial, p1) Equal(t, errs, nil) errs = validate.StructFiltered(tPartial, p2) Equal(t, errs, nil) tPartial.SubSlice[1].Test = "Required" tPartial.Anonymous.SubAnonStruct[0].Test = "" // these will pass as the unset item is NOT tested errs = validate.StructFiltered(tPartial, p1) Equal(t, errs, nil) errs = validate.StructFiltered(tPartial, p2) Equal(t, errs, nil) dt := time.Now() err := validate.StructFiltered(&dt, func(ns []byte) bool { return true }) NotEqual(t, err, nil) Equal(t, err.Error(), "validator: (nil *time.Time)") } func TestRequiredPtr(t *testing.T) { type Test struct { Bool *bool `validate:"required"` } validate := New() f := false test := Test{ Bool: &f, } err := validate.Struct(test) Equal(t, err, nil) tr := true test.Bool = &tr err = validate.Struct(test) Equal(t, err, nil) test.Bool = nil err = validate.Struct(test) NotEqual(t, err, nil) errs, ok := err.(ValidationErrors) Equal(t, ok, true) Equal(t, len(errs), 1) AssertError(t, errs, "Test.Bool", "Test.Bool", "Bool", "Bool", "required") type Test2 struct { Bool bool `validate:"required"` } var test2 Test2 err = validate.Struct(test2) NotEqual(t, err, nil) errs, ok = err.(ValidationErrors) Equal(t, ok, true) Equal(t, len(errs), 1) AssertError(t, errs, "Test2.Bool", "Test2.Bool", "Bool", "Bool", "required") test2.Bool = true err = validate.Struct(test2) Equal(t, err, nil) type Test3 struct { Arr []string `validate:"required"` } var test3 Test3 err = validate.Struct(test3) NotEqual(t, err, nil) errs, ok = err.(ValidationErrors) Equal(t, ok, true) Equal(t, len(errs), 1) AssertError(t, errs, "Test3.Arr", "Test3.Arr", "Arr", "Arr", "required") test3.Arr = make([]string, 0) err = validate.Struct(test3) Equal(t, err, nil) type Test4 struct { Arr *[]string `validate:"required"` // I know I know pointer to array, just making sure validation works as expected... } var test4 Test4 err = validate.Struct(test4) NotEqual(t, err, nil) errs, ok = err.(ValidationErrors) Equal(t, ok, true) Equal(t, len(errs), 1) AssertError(t, errs, "Test4.Arr", "Test4.Arr", "Arr", "Arr", "required") arr := make([]string, 0) test4.Arr = &arr err = validate.Struct(test4) Equal(t, err, nil) } func TestAlphaUnicodeValidation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"abc", true}, {"this is a test string", false}, {"这是一个测试字符串", true}, {"123", false}, {"<>@;.-=", false}, {"ひらがな・カタカナ、.漢字", false}, {"あいうえおfoobar", true}, {"test@example.com", false}, {"1234abcDE", false}, {"カタカナ", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "alphaunicode") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d Alpha Unicode failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d Alpha Unicode failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "alphaunicode" { t.Fatalf("Index: %d Alpha Unicode failed Error: %s", i, errs) } } } } } func TestAlphanumericUnicodeValidation(t *testing.T) { tests := []struct { param string expected bool }{ {"", false}, {"abc", true}, {"this is a test string", false}, {"这是一个测试字符串", true}, {"\u0031\u0032\u0033", true}, // unicode 5 {"123", true}, {"<>@;.-=", false}, {"ひらがな・カタカナ、.漢字", false}, {"あいうえおfoobar", true}, {"test@example.com", false}, {"1234abcDE", true}, {"カタカナ", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "alphanumunicode") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d Alphanum Unicode failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d Alphanum Unicode failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "alphanumunicode" { t.Fatalf("Index: %d Alphanum Unicode failed Error: %s", i, errs) } } } } } func TestArrayStructNamespace(t *testing.T) { validate := New() validate.RegisterTagNameFunc(func(fld reflect.StructField) string { name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] if name == "-" { return "" } return name }) type child struct { Name string `json:"name" validate:"required"` } var input struct { Children []child `json:"children" validate:"required,gt=0,dive"` } input.Children = []child{{"ok"}, {""}} errs := validate.Struct(input) NotEqual(t, errs, nil) ve := errs.(ValidationErrors) Equal(t, len(ve), 1) AssertError(t, errs, "children[1].name", "Children[1].Name", "name", "Name", "required") } func TestMapStructNamespace(t *testing.T) { validate := New() validate.RegisterTagNameFunc(func(fld reflect.StructField) string { name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] if name == "-" { return "" } return name }) type child struct { Name string `json:"name" validate:"required"` } var input struct { Children map[int]child `json:"children" validate:"required,gt=0,dive"` } input.Children = map[int]child{ 0: {Name: "ok"}, 1: {Name: ""}, } errs := validate.Struct(input) NotEqual(t, errs, nil) ve := errs.(ValidationErrors) Equal(t, len(ve), 1) AssertError(t, errs, "children[1].name", "Children[1].Name", "name", "Name", "required") } func TestFieldLevelName(t *testing.T) { type Test struct { String string `validate:"custom1" json:"json1"` Array []string `validate:"dive,custom2" json:"json2"` Map map[string]string `validate:"dive,custom3" json:"json3"` Array2 []string `validate:"custom4" json:"json4"` Map2 map[string]string `validate:"custom5" json:"json5"` } var res1, res2, res3, res4, res5, alt1, alt2, alt3, alt4, alt5 string validate := New() validate.RegisterTagNameFunc(func(fld reflect.StructField) string { name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] if name == "-" { return "" } return name }) err := validate.RegisterValidation("custom1", func(fl FieldLevel) bool { res1 = fl.FieldName() alt1 = fl.StructFieldName() return true }) Equal(t, err, nil) err = validate.RegisterValidation("custom2", func(fl FieldLevel) bool { res2 = fl.FieldName() alt2 = fl.StructFieldName() return true }) Equal(t, err, nil) err = validate.RegisterValidation("custom3", func(fl FieldLevel) bool { res3 = fl.FieldName() alt3 = fl.StructFieldName() return true }) Equal(t, err, nil) err = validate.RegisterValidation("custom4", func(fl FieldLevel) bool { res4 = fl.FieldName() alt4 = fl.StructFieldName() return true }) Equal(t, err, nil) err = validate.RegisterValidation("custom5", func(fl FieldLevel) bool { res5 = fl.FieldName() alt5 = fl.StructFieldName() return true }) Equal(t, err, nil) test := Test{ String: "test", Array: []string{"1"}, Map: map[string]string{"test": "test"}, } errs := validate.Struct(test) Equal(t, errs, nil) Equal(t, res1, "json1") Equal(t, alt1, "String") Equal(t, res2, "json2[0]") Equal(t, alt2, "Array[0]") Equal(t, res3, "json3[test]") Equal(t, alt3, "Map[test]") Equal(t, res4, "json4") Equal(t, alt4, "Array2") Equal(t, res5, "json5") Equal(t, alt5, "Map2") } func TestValidateStructRegisterCtx(t *testing.T) { var ctxVal string fnCtx := func(ctx context.Context, fl FieldLevel) bool { ctxVal = ctx.Value(&ctxVal).(string) return true } var ctxSlVal string slFn := func(ctx context.Context, sl StructLevel) { ctxSlVal = ctx.Value(&ctxSlVal).(string) } type Test struct { Field string `validate:"val"` } var tst Test validate := New() err := validate.RegisterValidationCtx("val", fnCtx) Equal(t, err, nil) validate.RegisterStructValidationCtx(slFn, Test{}) ctx := context.WithValue(context.Background(), &ctxVal, "testval") ctx = context.WithValue(ctx, &ctxSlVal, "slVal") errs := validate.StructCtx(ctx, tst) Equal(t, errs, nil) Equal(t, ctxVal, "testval") Equal(t, ctxSlVal, "slVal") } func TestHostnameRFC952Validation(t *testing.T) { tests := []struct { param string expected bool }{ {"test.example.com", true}, {"example.com", true}, {"example24.com", true}, {"test.example24.com", true}, {"test24.example24.com", true}, {"example", true}, {"EXAMPLE", true}, {"1.foo.com", false}, {"test.example.com.", false}, {"example.com.", false}, {"example24.com.", false}, {"test.example24.com.", false}, {"test24.example24.com.", false}, {"example.", false}, {"192.168.0.1", false}, {"email@example.com", false}, {"2001:cdba:0000:0000:0000:0000:3257:9652", false}, {"2001:cdba:0:0:0:0:3257:9652", false}, {"2001:cdba::3257:9652", false}, {"example..........com", false}, {"1234", false}, {"abc1234", true}, {"example. com", false}, {"ex ample.com", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "hostname") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d hostname failed Error: %v", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d hostname failed Error: %v", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "hostname" { t.Fatalf("Index: %d hostname failed Error: %v", i, errs) } } } } } func TestHostnameRFC1123Validation(t *testing.T) { tests := []struct { param string expected bool }{ {"test.example.com", true}, {"example.com", true}, {"example24.com", true}, {"test.example24.com", true}, {"test24.example24.com", true}, {"example", true}, {"1.foo.com", true}, {"test.example.com.", false}, {"example.com.", false}, {"example24.com.", false}, {"test.example24.com.", false}, {"test24.example24.com.", false}, {"example.", false}, {"test_example", false}, {"192.168.0.1", true}, {"email@example.com", false}, {"2001:cdba:0000:0000:0000:0000:3257:9652", false}, {"2001:cdba:0:0:0:0:3257:9652", false}, {"2001:cdba::3257:9652", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "hostname_rfc1123") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Hostname: %v failed Error: %v", test, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Hostname: %v failed Error: %v", test, errs) } else { val := getError(errs, "", "") if val.Tag() != "hostname_rfc1123" { t.Fatalf("Hostname: %v failed Error: %v", i, errs) } } } } } func TestHostnameRFC1123AliasValidation(t *testing.T) { tests := []struct { param string expected bool }{ {"test.example.com", true}, {"example.com", true}, {"example24.com", true}, {"test.example24.com", true}, {"test24.example24.com", true}, {"example", true}, {"1.foo.com", true}, {"test.example.com.", false}, {"example.com.", false}, {"example24.com.", false}, {"test.example24.com.", false}, {"test24.example24.com.", false}, {"example.", false}, {"test_example", false}, {"192.168.0.1", true}, {"email@example.com", false}, {"2001:cdba:0000:0000:0000:0000:3257:9652", false}, {"2001:cdba:0:0:0:0:3257:9652", false}, {"2001:cdba::3257:9652", false}, } validate := New() validate.RegisterAlias("hostname", "hostname_rfc1123") for i, test := range tests { errs := validate.Var(test.param, "hostname") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d hostname failed Error: %v", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d hostname failed Error: %v", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "hostname" { t.Fatalf("Index: %d hostname failed Error: %v", i, errs) } } } } } func TestFQDNValidation(t *testing.T) { tests := []struct { param string expected bool }{ {"test.example.com", true}, {"example.com", true}, {"example24.com", true}, {"test.example24.com", true}, {"test24.example24.com", true}, {"test.example.com.", true}, {"example.com.", true}, {"example24.com.", true}, {"test.example24.com.", true}, {"test24.example24.com.", true}, {"24.example24.com", true}, {"test.24.example.com", true}, {"test24.example24.com..", false}, {"example", false}, {"192.168.0.1", false}, {"email@example.com", false}, {"2001:cdba:0000:0000:0000:0000:3257:9652", false}, {"2001:cdba:0:0:0:0:3257:9652", false}, {"2001:cdba::3257:9652", false}, {"", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "fqdn") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d fqdn failed Error: %v", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d fqdn failed Error: %v", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "fqdn" { t.Fatalf("Index: %d fqdn failed Error: %v", i, errs) } } } } } func TestIsDefault(t *testing.T) { validate := New() type Inner struct { String string `validate:"isdefault"` } type Test struct { String string `validate:"isdefault"` Inner *Inner `validate:"isdefault"` } var tt Test errs := validate.Struct(tt) Equal(t, errs, nil) tt.Inner = &Inner{String: ""} errs = validate.Struct(tt) NotEqual(t, errs, nil) fe := errs.(ValidationErrors)[0] Equal(t, fe.Field(), "Inner") Equal(t, fe.Namespace(), "Test.Inner") Equal(t, fe.Tag(), "isdefault") validate.RegisterTagNameFunc(func(fld reflect.StructField) string { name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] if name == "-" { return "" } return name }) type Inner2 struct { String string `validate:"isdefault"` } type Test2 struct { Inner Inner2 `validate:"isdefault" json:"inner"` } var t2 Test2 errs = validate.Struct(t2) Equal(t, errs, nil) t2.Inner.String = "Changed" errs = validate.Struct(t2) NotEqual(t, errs, nil) fe = errs.(ValidationErrors)[0] Equal(t, fe.Field(), "inner") Equal(t, fe.Namespace(), "Test2.inner") Equal(t, fe.Tag(), "isdefault") } func TestUniqueValidation(t *testing.T) { tests := []struct { param interface{} expected bool }{ // Arrays {[2]string{"a", "b"}, true}, {[2]int{1, 2}, true}, {[2]float64{1, 2}, true}, {[2]interface{}{"a", "b"}, true}, {[2]interface{}{"a", 1}, true}, {[2]float64{1, 1}, false}, {[2]int{1, 1}, false}, {[2]string{"a", "a"}, false}, {[2]interface{}{"a", "a"}, false}, {[4]interface{}{"a", 1, "b", 1}, false}, {[2]*string{stringPtr("a"), stringPtr("b")}, true}, {[2]*int{intPtr(1), intPtr(2)}, true}, {[2]*float64{float64Ptr(1), float64Ptr(2)}, true}, {[2]*string{stringPtr("a"), stringPtr("a")}, false}, {[2]*float64{float64Ptr(1), float64Ptr(1)}, false}, {[2]*int{intPtr(1), intPtr(1)}, false}, // Slices {[]string{"a", "b"}, true}, {[]int{1, 2}, true}, {[]float64{1, 2}, true}, {[]interface{}{"a", "b"}, true}, {[]interface{}{"a", 1}, true}, {[]float64{1, 1}, false}, {[]int{1, 1}, false}, {[]string{"a", "a"}, false}, {[]interface{}{"a", "a"}, false}, {[]interface{}{"a", 1, "b", 1}, false}, {[]*string{stringPtr("a"), stringPtr("b")}, true}, {[]*int{intPtr(1), intPtr(2)}, true}, {[]*float64{float64Ptr(1), float64Ptr(2)}, true}, {[]*string{stringPtr("a"), stringPtr("a")}, false}, {[]*float64{float64Ptr(1), float64Ptr(1)}, false}, {[]*int{intPtr(1), intPtr(1)}, false}, // Maps {map[string]string{"one": "a", "two": "b"}, true}, {map[string]int{"one": 1, "two": 2}, true}, {map[string]float64{"one": 1, "two": 2}, true}, {map[string]interface{}{"one": "a", "two": "b"}, true}, {map[string]interface{}{"one": "a", "two": 1}, true}, {map[string]float64{"one": 1, "two": 1}, false}, {map[string]int{"one": 1, "two": 1}, false}, {map[string]string{"one": "a", "two": "a"}, false}, {map[string]interface{}{"one": "a", "two": "a"}, false}, {map[string]interface{}{"one": "a", "two": 1, "three": "b", "four": 1}, false}, {map[string]*string{"one": stringPtr("a"), "two": stringPtr("a")}, false}, {map[string]*string{"one": stringPtr("a"), "two": stringPtr("b")}, true}, {map[string]*int{"one": intPtr(1), "two": intPtr(1)}, false}, {map[string]*int{"one": intPtr(1), "two": intPtr(2)}, true}, {map[string]*float64{"one": float64Ptr(1.1), "two": float64Ptr(1.1)}, false}, {map[string]*float64{"one": float64Ptr(1.1), "two": float64Ptr(1.2)}, true}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "unique") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d unique failed Error: %v", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d unique failed Error: %v", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "unique" { t.Fatalf("Index: %d unique failed Error: %v", i, errs) } } } } PanicMatches(t, func() { _ = validate.Var(1.0, "unique") }, "Bad field type float64") t.Run("struct", func(t *testing.T) { tests := []struct { param interface{} expected bool }{ {struct { A string `validate:"unique=B"` B string }{A: "abc", B: "bcd"}, true}, {struct { A string `validate:"unique=B"` B string }{A: "abc", B: "abc"}, false}, } validate := New() for i, test := range tests { errs := validate.Struct(test.param) if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d unique failed Error: %v", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d unique failed Error: %v", i, errs) } else { val := getError(errs, "A", "A") if val.Tag() != "unique" { t.Fatalf("Index: %d unique failed Error: %v", i, errs) } } } } }) } func TestUniqueValidationStructSlice(t *testing.T) { testStructs := []struct { A string B string }{ {A: "one", B: "two"}, {A: "one", B: "three"}, } tests := []struct { target interface{} param string expected bool }{ {testStructs, "unique", true}, {testStructs, "unique=A", false}, {testStructs, "unique=B", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.target, test.param) if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d unique failed Error: %v", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d unique failed Error: %v", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "unique" { t.Fatalf("Index: %d unique failed Error: %v", i, errs) } } } } PanicMatches(t, func() { _ = validate.Var(testStructs, "unique=C") }, "Bad field name C") } func TestUniqueValidationStructPtrSlice(t *testing.T) { testStructs := []*struct { A *string B *string }{ {A: stringPtr("one"), B: stringPtr("two")}, {A: stringPtr("one"), B: stringPtr("three")}, {}, } tests := []struct { target interface{} param string expected bool }{ {testStructs, "unique", true}, {testStructs, "unique=A", false}, {testStructs, "unique=B", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.target, test.param) if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d unique failed Error: %v", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d unique failed Error: %v", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "unique" { t.Fatalf("Index: %d unique failed Error: %v", i, errs) } } } } PanicMatches(t, func() { _ = validate.Var(testStructs, "unique=C") }, "Bad field name C") } func TestHTMLValidation(t *testing.T) { tests := []struct { param string expected bool }{ {"", true}, {"", true}, {"", false}, {"<123nonsense>", false}, {"test", false}, {"&example", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "html") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d html failed Error: %v", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d html failed Error: %v", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "html" { t.Fatalf("Index: %d html failed Error: %v", i, errs) } } } } } func TestHTMLEncodedValidation(t *testing.T) { tests := []struct { param string expected bool }{ {"<", true}, {"¯", true}, {"�", true}, {"ð", true}, {"<", true}, {"¯", true}, {"�", true}, {"ð", true}, {"&#ab", true}, {"<", true}, {">", true}, {""", true}, {"&", true}, {"#x0a", false}, {"&x00", false}, {"z", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "html_encoded") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d html_encoded failed Error: %v", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d html_encoded failed Error: %v", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "html_encoded" { t.Fatalf("Index: %d html_encoded failed Error: %v", i, errs) } } } } } func TestURLEncodedValidation(t *testing.T) { tests := []struct { param string expected bool }{ {"%20", true}, {"%af", true}, {"%ff", true}, {"<%az", false}, {"%test%", false}, {"a%b", false}, {"1%2", false}, {"%%a%%", false}, {"hello", true}, {"", true}, {"+", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "url_encoded") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d url_encoded failed Error: %v", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d url_encoded failed Error: %v", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "url_encoded" { t.Fatalf("Index: %d url_encoded failed Error: %v", i, errs) } } } } } func TestKeys(t *testing.T) { type Test struct { Test1 map[string]string `validate:"gt=0,dive,keys,eq=testkey,endkeys,eq=testval" json:"test1"` Test2 map[int]int `validate:"gt=0,dive,keys,eq=3,endkeys,eq=4" json:"test2"` Test3 map[int]int `validate:"gt=0,dive,keys,eq=3,endkeys" json:"test3"` } var tst Test validate := New() err := validate.Struct(tst) NotEqual(t, err, nil) Equal(t, len(err.(ValidationErrors)), 3) AssertError(t, err.(ValidationErrors), "Test.Test1", "Test.Test1", "Test1", "Test1", "gt") AssertError(t, err.(ValidationErrors), "Test.Test2", "Test.Test2", "Test2", "Test2", "gt") AssertError(t, err.(ValidationErrors), "Test.Test3", "Test.Test3", "Test3", "Test3", "gt") tst.Test1 = map[string]string{ "testkey": "testval", } tst.Test2 = map[int]int{ 3: 4, } tst.Test3 = map[int]int{ 3: 4, } err = validate.Struct(tst) Equal(t, err, nil) tst.Test1["badtestkey"] = "badtestvalue" tst.Test2[10] = 11 err = validate.Struct(tst) NotEqual(t, err, nil) errs := err.(ValidationErrors) Equal(t, len(errs), 4) AssertDeepError(t, errs, "Test.Test1[badtestkey]", "Test.Test1[badtestkey]", "Test1[badtestkey]", "Test1[badtestkey]", "eq", "eq") AssertDeepError(t, errs, "Test.Test1[badtestkey]", "Test.Test1[badtestkey]", "Test1[badtestkey]", "Test1[badtestkey]", "eq", "eq") AssertDeepError(t, errs, "Test.Test2[10]", "Test.Test2[10]", "Test2[10]", "Test2[10]", "eq", "eq") AssertDeepError(t, errs, "Test.Test2[10]", "Test.Test2[10]", "Test2[10]", "Test2[10]", "eq", "eq") type Test2 struct { NestedKeys map[[1]string]string `validate:"gt=0,dive,keys,dive,eq=innertestkey,endkeys,eq=outertestval"` } var tst2 Test2 err = validate.Struct(tst2) NotEqual(t, err, nil) Equal(t, len(err.(ValidationErrors)), 1) AssertError(t, err.(ValidationErrors), "Test2.NestedKeys", "Test2.NestedKeys", "NestedKeys", "NestedKeys", "gt") tst2.NestedKeys = map[[1]string]string{ {"innertestkey"}: "outertestval", } err = validate.Struct(tst2) Equal(t, err, nil) tst2.NestedKeys[[1]string{"badtestkey"}] = "badtestvalue" err = validate.Struct(tst2) NotEqual(t, err, nil) errs = err.(ValidationErrors) Equal(t, len(errs), 2) AssertDeepError(t, errs, "Test2.NestedKeys[[badtestkey]][0]", "Test2.NestedKeys[[badtestkey]][0]", "NestedKeys[[badtestkey]][0]", "NestedKeys[[badtestkey]][0]", "eq", "eq") AssertDeepError(t, errs, "Test2.NestedKeys[[badtestkey]]", "Test2.NestedKeys[[badtestkey]]", "NestedKeys[[badtestkey]]", "NestedKeys[[badtestkey]]", "eq", "eq") // test bad tag definitions PanicMatches(t, func() { _ = validate.Var(map[string]string{"key": "val"}, "endkeys,dive,eq=val") }, "'endkeys' tag encountered without a corresponding 'keys' tag") PanicMatches(t, func() { _ = validate.Var(1, "keys,eq=1,endkeys") }, "'keys' tag must be immediately preceded by the 'dive' tag") // test custom tag name validate = New() validate.RegisterTagNameFunc(func(fld reflect.StructField) string { name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] if name == "-" { return "" } return name }) err = validate.Struct(tst) NotEqual(t, err, nil) errs = err.(ValidationErrors) Equal(t, len(errs), 4) AssertDeepError(t, errs, "Test.test1[badtestkey]", "Test.Test1[badtestkey]", "test1[badtestkey]", "Test1[badtestkey]", "eq", "eq") AssertDeepError(t, errs, "Test.test1[badtestkey]", "Test.Test1[badtestkey]", "test1[badtestkey]", "Test1[badtestkey]", "eq", "eq") AssertDeepError(t, errs, "Test.test2[10]", "Test.Test2[10]", "test2[10]", "Test2[10]", "eq", "eq") AssertDeepError(t, errs, "Test.test2[10]", "Test.Test2[10]", "test2[10]", "Test2[10]", "eq", "eq") } // Thanks @adrian-sgn specific test for your specific scenario func TestKeysCustomValidation(t *testing.T) { type LangCode string type Label map[LangCode]string type TestMapStructPtr struct { Label Label `validate:"dive,keys,lang_code,endkeys,required"` } validate := New() err := validate.RegisterValidation("lang_code", func(fl FieldLevel) bool { validLangCodes := map[LangCode]struct{}{ "en": {}, "es": {}, "pt": {}, } _, ok := validLangCodes[fl.Field().Interface().(LangCode)] return ok }) Equal(t, err, nil) label := Label{ "en": "Good morning!", "pt": "", "es": "¡Buenos días!", "xx": "Bad key", "xxx": "", } err = validate.Struct(TestMapStructPtr{label}) NotEqual(t, err, nil) errs := err.(ValidationErrors) Equal(t, len(errs), 4) AssertDeepError(t, errs, "TestMapStructPtr.Label[xx]", "TestMapStructPtr.Label[xx]", "Label[xx]", "Label[xx]", "lang_code", "lang_code") AssertDeepError(t, errs, "TestMapStructPtr.Label[pt]", "TestMapStructPtr.Label[pt]", "Label[pt]", "Label[pt]", "required", "required") AssertDeepError(t, errs, "TestMapStructPtr.Label[xxx]", "TestMapStructPtr.Label[xxx]", "Label[xxx]", "Label[xxx]", "lang_code", "lang_code") AssertDeepError(t, errs, "TestMapStructPtr.Label[xxx]", "TestMapStructPtr.Label[xxx]", "Label[xxx]", "Label[xxx]", "required", "required") // find specific error var e FieldError for _, e = range errs { if e.Namespace() == "TestMapStructPtr.Label[xxx]" { break } } Equal(t, e.Param(), "") Equal(t, e.Value().(LangCode), LangCode("xxx")) for _, e = range errs { if e.Namespace() == "TestMapStructPtr.Label[xxx]" && e.Tag() == "required" { break } } Equal(t, e.Param(), "") Equal(t, e.Value().(string), "") } func TestKeyOrs(t *testing.T) { type Test struct { Test1 map[string]string `validate:"gt=0,dive,keys,eq=testkey|eq=testkeyok,endkeys,eq=testval" json:"test1"` } var tst Test validate := New() err := validate.Struct(tst) NotEqual(t, err, nil) Equal(t, len(err.(ValidationErrors)), 1) AssertError(t, err.(ValidationErrors), "Test.Test1", "Test.Test1", "Test1", "Test1", "gt") tst.Test1 = map[string]string{ "testkey": "testval", } err = validate.Struct(tst) Equal(t, err, nil) tst.Test1["badtestkey"] = "badtestval" err = validate.Struct(tst) NotEqual(t, err, nil) errs := err.(ValidationErrors) Equal(t, len(errs), 2) AssertDeepError(t, errs, "Test.Test1[badtestkey]", "Test.Test1[badtestkey]", "Test1[badtestkey]", "Test1[badtestkey]", "eq=testkey|eq=testkeyok", "eq=testkey|eq=testkeyok") AssertDeepError(t, errs, "Test.Test1[badtestkey]", "Test.Test1[badtestkey]", "Test1[badtestkey]", "Test1[badtestkey]", "eq", "eq") validate.RegisterAlias("okkey", "eq=testkey|eq=testkeyok") type Test2 struct { Test1 map[string]string `validate:"gt=0,dive,keys,okkey,endkeys,eq=testval" json:"test1"` } var tst2 Test2 err = validate.Struct(tst2) NotEqual(t, err, nil) Equal(t, len(err.(ValidationErrors)), 1) AssertError(t, err.(ValidationErrors), "Test2.Test1", "Test2.Test1", "Test1", "Test1", "gt") tst2.Test1 = map[string]string{ "testkey": "testval", } err = validate.Struct(tst2) Equal(t, err, nil) tst2.Test1["badtestkey"] = "badtestval" err = validate.Struct(tst2) NotEqual(t, err, nil) errs = err.(ValidationErrors) Equal(t, len(errs), 2) AssertDeepError(t, errs, "Test2.Test1[badtestkey]", "Test2.Test1[badtestkey]", "Test1[badtestkey]", "Test1[badtestkey]", "okkey", "eq=testkey|eq=testkeyok") AssertDeepError(t, errs, "Test2.Test1[badtestkey]", "Test2.Test1[badtestkey]", "Test1[badtestkey]", "Test1[badtestkey]", "eq", "eq") } func TestStructLevelValidationsPointerPassing(t *testing.T) { v1 := New() v1.RegisterStructValidation(StructValidationTestStruct, &TestStruct{}) tst := &TestStruct{ String: "good value", } errs := v1.Struct(tst) NotEqual(t, errs, nil) AssertError(t, errs, "TestStruct.StringVal", "TestStruct.String", "StringVal", "String", "badvalueteststruct") } func TestDirValidation(t *testing.T) { validate := New() tests := []struct { title string param string expected bool }{ {"existing dir", "testdata", true}, {"existing self dir", ".", true}, {"existing parent dir", "..", true}, {"empty dir", "", false}, {"missing dir", "non_existing_testdata", false}, {"a file not a directory", filepath.Join("testdata", "a.go"), false}, } for _, test := range tests { errs := validate.Var(test.param, "dir") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Test: '%s' failed Error: %s", test.title, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Test: '%s' failed Error: %s", test.title, errs) } } } PanicMatches(t, func() { _ = validate.Var(2, "dir") }, "Bad field type int") } func TestDirPathValidation(t *testing.T) { validate := New() tests := []struct { title string param string expected bool }{ {"empty dirpath", "", false}, {"valid dirpath - exists", "testdata", true}, {"valid dirpath - explicit", "testdatanoexist" + string(os.PathSeparator), true}, {"invalid dirpath", "testdata\000" + string(os.PathSeparator), false}, {"file, not a dirpath", filepath.Join("testdata", "a.go"), false}, } for _, test := range tests { errs := validate.Var(test.param, "dirpath") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Test: '%s' failed Error: %s", test.title, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Test: '%s' failed Error: %s", test.title, errs) } } } PanicMatches(t, func() { _ = validate.Var(6, "filepath") }, "Bad field type int") } func TestStartsWithValidation(t *testing.T) { tests := []struct { Value string `validate:"startswith=(/^ヮ^)/*:・゚✧"` Tag string ExpectedNil bool }{ {Value: "(/^ヮ^)/*:・゚✧ glitter", Tag: "startswith=(/^ヮ^)/*:・゚✧", ExpectedNil: true}, {Value: "abcd", Tag: "startswith=(/^ヮ^)/*:・゚✧", ExpectedNil: false}, } validate := New() for i, s := range tests { errs := validate.Var(s.Value, s.Tag) if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { t.Fatalf("Index: %d failed Error: %s", i, errs) } errs = validate.Struct(s) if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { t.Fatalf("Index: %d failed Error: %s", i, errs) } } } func TestEndsWithValidation(t *testing.T) { tests := []struct { Value string `validate:"endswith=(/^ヮ^)/*:・゚✧"` Tag string ExpectedNil bool }{ {Value: "glitter (/^ヮ^)/*:・゚✧", Tag: "endswith=(/^ヮ^)/*:・゚✧", ExpectedNil: true}, {Value: "(/^ヮ^)/*:・゚✧ glitter", Tag: "endswith=(/^ヮ^)/*:・゚✧", ExpectedNil: false}, } validate := New() for i, s := range tests { errs := validate.Var(s.Value, s.Tag) if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { t.Fatalf("Index: %d failed Error: %s", i, errs) } errs = validate.Struct(s) if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) { t.Fatalf("Index: %d failed Error: %s", i, errs) } } } func TestRequiredIf(t *testing.T) { type Inner struct { Field *string } fieldVal := "test" test := struct { Inner *Inner FieldE string `validate:"omitempty" json:"field_e"` FieldER string `validate:"required_if=FieldE test" json:"field_er"` Field1 string `validate:"omitempty" json:"field_1"` Field2 *string `validate:"required_if=Field1 test" json:"field_2"` Field3 map[string]string `validate:"required_if=Field2 test" json:"field_3"` Field4 interface{} `validate:"required_if=Field3 1" json:"field_4"` Field5 int `validate:"required_if=Inner.Field test" json:"field_5"` Field6 uint `validate:"required_if=Field5 1" json:"field_6"` Field7 float32 `validate:"required_if=Field6 1" json:"field_7"` Field8 float64 `validate:"required_if=Field7 1.0" json:"field_8"` Field9 Inner `validate:"required_if=Field1 test" json:"field_9"` Field10 *Inner `validate:"required_if=Field1 test" json:"field_10"` }{ Inner: &Inner{Field: &fieldVal}, Field2: &fieldVal, Field3: map[string]string{"key": "val"}, Field4: "test", Field5: 2, } validate := New() errs := validate.Struct(test) Equal(t, errs, nil) test2 := struct { Inner *Inner Inner2 *Inner FieldE string `validate:"omitempty" json:"field_e"` FieldER string `validate:"required_if=FieldE test" json:"field_er"` Field1 string `validate:"omitempty" json:"field_1"` Field2 *string `validate:"required_if=Field1 test" json:"field_2"` Field3 map[string]string `validate:"required_if=Field2 test" json:"field_3"` Field4 interface{} `validate:"required_if=Field2 test" json:"field_4"` Field5 string `validate:"required_if=Field3 1" json:"field_5"` Field6 string `validate:"required_if=Inner.Field test" json:"field_6"` Field7 string `validate:"required_if=Inner2.Field test" json:"field_7"` Field8 Inner `validate:"required_if=Field2 test" json:"field_8"` Field9 *Inner `validate:"required_if=Field2 test" json:"field_9"` }{ Inner: &Inner{Field: &fieldVal}, Field2: &fieldVal, } errs = validate.Struct(test2) NotEqual(t, errs, nil) ve := errs.(ValidationErrors) Equal(t, len(ve), 5) AssertError(t, errs, "Field3", "Field3", "Field3", "Field3", "required_if") AssertError(t, errs, "Field4", "Field4", "Field4", "Field4", "required_if") AssertError(t, errs, "Field6", "Field6", "Field6", "Field6", "required_if") AssertError(t, errs, "Field8", "Field8", "Field8", "Field8", "required_if") AssertError(t, errs, "Field9", "Field9", "Field9", "Field9", "required_if") defer func() { if r := recover(); r == nil { t.Errorf("test3 should have panicked!") } }() test3 := struct { Inner *Inner Field1 string `validate:"required_if=Inner.Field" json:"field_1"` }{ Inner: &Inner{Field: &fieldVal}, } _ = validate.Struct(test3) } func TestRequiredIfDuplicateParams(t *testing.T) { validate := New() PanicMatches(t, func() { type TestStruct struct { Field1 string `validate:"required_if=Field2 value1 Field2 value2"` Field2 string } test := TestStruct{ Field1: "", Field2: "value1", } _ = validate.Struct(test) }, "Duplicate param Field2 for required_if Field1") PanicMatches(t, func() { type TestStruct struct { Field1 string `validate:"required_if=Field2 val1 Field3 val2 Field2 val3"` Field2 string Field3 string } test := TestStruct{ Field1: "", Field2: "val1", Field3: "val2", } _ = validate.Struct(test) }, "Duplicate param Field2 for required_if Field1") type TestStruct struct { Field1 string `validate:"required_if=Field2 val1 Field3 val2"` Field2 string Field3 string } test := TestStruct{ Field1: "", Field2: "val1", Field3: "val2", } errs := validate.Struct(test) NotEqual(t, errs, nil) } func TestRequiredUnless(t *testing.T) { type Inner struct { Field *string } fieldVal := "test" test := struct { Inner *Inner FieldE string `validate:"omitempty" json:"field_e"` FieldER string `validate:"required_unless=FieldE test" json:"field_er"` Field1 string `validate:"omitempty" json:"field_1"` Field2 *string `validate:"required_unless=Field1 test" json:"field_2"` Field3 map[string]string `validate:"required_unless=Field2 test" json:"field_3"` Field4 interface{} `validate:"required_unless=Field3 1" json:"field_4"` Field5 int `validate:"required_unless=Inner.Field test" json:"field_5"` Field6 uint `validate:"required_unless=Field5 2" json:"field_6"` Field7 float32 `validate:"required_unless=Field6 0" json:"field_7"` Field8 float64 `validate:"required_unless=Field7 0.0" json:"field_8"` Field9 bool `validate:"omitempty" json:"field_9"` Field10 string `validate:"required_unless=Field9 true" json:"field_10"` Field11 Inner `validate:"required_unless=Field9 true" json:"field_11"` Field12 *Inner `validate:"required_unless=Field9 true" json:"field_12"` }{ FieldE: "test", Field2: &fieldVal, Field3: map[string]string{"key": "val"}, Field4: "test", Field5: 2, Field9: true, } validate := New() errs := validate.Struct(test) Equal(t, errs, nil) test2 := struct { Inner *Inner Inner2 *Inner FieldE string `validate:"omitempty" json:"field_e"` FieldER string `validate:"required_unless=FieldE test" json:"field_er"` Field1 string `validate:"omitempty" json:"field_1"` Field2 *string `validate:"required_unless=Field1 test" json:"field_2"` Field3 map[string]string `validate:"required_unless=Field2 test" json:"field_3"` Field4 interface{} `validate:"required_unless=Field2 test" json:"field_4"` Field5 string `validate:"required_unless=Field3 0" json:"field_5"` Field6 string `validate:"required_unless=Inner.Field test" json:"field_6"` Field7 string `validate:"required_unless=Inner2.Field test" json:"field_7"` Field8 bool `validate:"omitempty" json:"field_8"` Field9 string `validate:"required_unless=Field8 true" json:"field_9"` Field10 Inner `validate:"required_unless=Field9 true" json:"field_10"` Field11 *Inner `validate:"required_unless=Field9 true" json:"field_11"` }{ Inner: &Inner{Field: &fieldVal}, FieldE: "test", Field1: "test", } errs = validate.Struct(test2) NotEqual(t, errs, nil) ve := errs.(ValidationErrors) Equal(t, len(ve), 6) AssertError(t, errs, "Field3", "Field3", "Field3", "Field3", "required_unless") AssertError(t, errs, "Field4", "Field4", "Field4", "Field4", "required_unless") AssertError(t, errs, "Field7", "Field7", "Field7", "Field7", "required_unless") AssertError(t, errs, "Field9", "Field9", "Field9", "Field9", "required_unless") AssertError(t, errs, "Field10", "Field10", "Field10", "Field10", "required_unless") AssertError(t, errs, "Field11", "Field11", "Field11", "Field11", "required_unless") PanicMatches(t, func() { test3 := struct { Inner *Inner Field1 string `validate:"required_unless=Inner.Field" json:"field_1"` }{ Inner: &Inner{Field: &fieldVal}, } _ = validate.Struct(test3) }, "Bad param number for required_unless Field1") type DuplicateStruct struct { Field1 string `validate:"required_unless=Field2 value1 Field2 value2"` Field2 string } test4 := DuplicateStruct{ Field1: "", Field2: "value1", } errs = validate.Struct(test4) Equal(t, errs, nil) test5 := DuplicateStruct{ Field1: "", Field2: "value2", } errs = validate.Struct(test5) Equal(t, errs, nil) test6 := DuplicateStruct{ Field1: "", Field2: "value3", } errs = validate.Struct(test6) NotEqual(t, errs, nil) test7 := struct { Field1 int Field2 string `validate:"required_unless=Field1 1 Field1 2"` Field3 int Field4 string `validate:"required_unless=Field3 1 Field3 2"` }{ Field1: 1, Field3: 3, } errs = validate.Struct(test7) NotEqual(t, errs, nil) AssertError(t, errs, "Field4", "Field4", "Field4", "Field4", "required_unless") } func TestSkipUnless(t *testing.T) { type Inner struct { Field *string } fieldVal := "test1" test := struct { Inner *Inner FieldE string `validate:"omitempty" json:"field_e"` FieldER string `validate:"skip_unless=FieldE test" json:"field_er"` Field1 string `validate:"omitempty" json:"field_1"` Field2 *string `validate:"skip_unless=Field1 test" json:"field_2"` Field3 map[string]string `validate:"skip_unless=Field2 test" json:"field_3"` Field4 interface{} `validate:"skip_unless=Field3 1" json:"field_4"` Field5 int `validate:"skip_unless=Inner.Field test" json:"field_5"` Field6 uint `validate:"skip_unless=Field5 2" json:"field_6"` Field7 float32 `validate:"skip_unless=Field6 1" json:"field_7"` Field8 float64 `validate:"skip_unless=Field7 1.0" json:"field_8"` Field9 bool `validate:"omitempty" json:"field_9"` Field10 string `validate:"skip_unless=Field9 false" json:"field_10"` Field11 Inner `validate:"skip_unless=Field9 false" json:"field_11"` Field12 *Inner `validate:"skip_unless=Field9 false" json:"field_12"` }{ FieldE: "test1", Field2: &fieldVal, Field3: map[string]string{"key": "val"}, Field4: "test", Field5: 3, Field9: true, } validate := New() errs := validate.Struct(test) Equal(t, errs, nil) test2 := struct { Inner *Inner Inner2 *Inner FieldE string `validate:"omitempty" json:"field_e"` FieldER string `validate:"skip_unless=FieldE test" json:"field_er"` Field1 string `validate:"omitempty" json:"field_1"` Field2 *string `validate:"skip_unless=Field1 test" json:"field_2"` Field3 map[string]string `validate:"skip_unless=Field2 test" json:"field_3"` Field4 interface{} `validate:"skip_unless=Field2 test" json:"field_4"` Field5 string `validate:"skip_unless=Field3 0" json:"field_5"` Field6 string `validate:"skip_unless=Inner.Field test" json:"field_6"` Field7 string `validate:"skip_unless=Inner2.Field test" json:"field_7"` Field8 bool `validate:"omitempty" json:"field_8"` Field9 string `validate:"skip_unless=Field8 true" json:"field_9"` Field10 Inner `validate:"skip_unless=Field8 false" json:"field_10"` Field11 *Inner `validate:"skip_unless=Field8 false" json:"field_11"` }{ Inner: &Inner{Field: &fieldVal}, FieldE: "test1", Field1: "test1", } errs = validate.Struct(test2) NotEqual(t, errs, nil) ve := errs.(ValidationErrors) Equal(t, len(ve), 3) AssertError(t, errs, "Field5", "Field5", "Field5", "Field5", "skip_unless") AssertError(t, errs, "Field10", "Field10", "Field10", "Field10", "skip_unless") AssertError(t, errs, "Field11", "Field11", "Field11", "Field11", "skip_unless") test3 := struct { Inner *Inner Field1 string `validate:"skip_unless=Inner.Field" json:"field_1"` }{ Inner: &Inner{Field: &fieldVal}, } PanicMatches(t, func() { _ = validate.Struct(test3) }, "Bad param number for skip_unless Field1") test4 := struct { Inner *Inner Field1 string `validate:"skip_unless=Inner.Field test1" json:"field_1"` }{ Inner: &Inner{Field: &fieldVal}, } errs = validate.Struct(test4) NotEqual(t, errs, nil) ve = errs.(ValidationErrors) Equal(t, len(ve), 1) AssertError(t, errs, "Field1", "Field1", "Field1", "Field1", "skip_unless") } func TestRequiredWith(t *testing.T) { type Inner struct { Field *string } fieldVal := "test" test := struct { Inner *Inner FieldE string `validate:"omitempty" json:"field_e"` FieldER string `validate:"required_with=FieldE" json:"field_er"` Field1 string `validate:"omitempty" json:"field_1"` Field2 *string `validate:"required_with=Field1" json:"field_2"` Field3 map[string]string `validate:"required_with=Field2" json:"field_3"` Field4 interface{} `validate:"required_with=Field3" json:"field_4"` Field5 string `validate:"required_with=Field" json:"field_5"` Field6 Inner `validate:"required_with=Field2" json:"field_6"` Field7 *Inner `validate:"required_with=Field2" json:"field_7"` }{ Inner: &Inner{Field: &fieldVal}, Field2: &fieldVal, Field3: map[string]string{"key": "val"}, Field4: "test", Field5: "test", Field6: Inner{Field: &fieldVal}, Field7: &Inner{Field: &fieldVal}, } validate := New() errs := validate.Struct(test) Equal(t, errs, nil) test2 := struct { Inner *Inner Inner2 *Inner FieldE string `validate:"omitempty" json:"field_e"` FieldER string `validate:"required_with=FieldE" json:"field_er"` Field1 string `validate:"omitempty" json:"field_1"` Field2 *string `validate:"required_with=Field1" json:"field_2"` Field3 map[string]string `validate:"required_with=Field2" json:"field_3"` Field4 interface{} `validate:"required_with=Field2" json:"field_4"` Field5 string `validate:"required_with=Field3" json:"field_5"` Field6 string `validate:"required_with=Inner.Field" json:"field_6"` Field7 string `validate:"required_with=Inner2.Field" json:"field_7"` Field8 Inner `validate:"required_with=Field2" json:"field_8"` Field9 *Inner `validate:"required_with=Field2" json:"field_9"` }{ Inner: &Inner{Field: &fieldVal}, Field2: &fieldVal, } errs = validate.Struct(test2) NotEqual(t, errs, nil) ve := errs.(ValidationErrors) Equal(t, len(ve), 5) AssertError(t, errs, "Field3", "Field3", "Field3", "Field3", "required_with") AssertError(t, errs, "Field4", "Field4", "Field4", "Field4", "required_with") AssertError(t, errs, "Field6", "Field6", "Field6", "Field6", "required_with") AssertError(t, errs, "Field8", "Field8", "Field8", "Field8", "required_with") AssertError(t, errs, "Field9", "Field9", "Field9", "Field9", "required_with") } func TestExcludedWith(t *testing.T) { type Inner struct { FieldE string Field *string } fieldVal := "test" test := struct { Inner *Inner Inner2 *Inner Field string `validate:"omitempty" json:"field"` FieldE string `validate:"omitempty" json:"field_e"` Field1 string `validate:"excluded_with=FieldE" json:"field_1"` Field2 *string `validate:"excluded_with=FieldE" json:"field_2"` Field3 map[string]string `validate:"excluded_with=FieldE" json:"field_3"` Field4 interface{} `validate:"excluded_with=FieldE" json:"field_4"` Field5 string `validate:"excluded_with=Inner.FieldE" json:"field_5"` Field6 string `validate:"excluded_with=Inner2.FieldE" json:"field_6"` Field7 Inner `validate:"excluded_with=FieldE" json:"field_7"` Field8 *Inner `validate:"excluded_with=FieldE" json:"field_8"` }{ Inner: &Inner{Field: &fieldVal}, Field1: fieldVal, Field2: &fieldVal, Field3: map[string]string{"key": "val"}, Field4: "test", Field5: "test", Field6: "test", } validate := New() errs := validate.Struct(test) Equal(t, errs, nil) test2 := struct { Inner *Inner Inner2 *Inner Field string `validate:"omitempty" json:"field"` FieldE string `validate:"omitempty" json:"field_e"` Field1 string `validate:"excluded_with=Field" json:"field_1"` Field2 *string `validate:"excluded_with=Field" json:"field_2"` Field3 map[string]string `validate:"excluded_with=Field" json:"field_3"` Field4 interface{} `validate:"excluded_with=Field" json:"field_4"` Field5 string `validate:"excluded_with=Inner.Field" json:"field_5"` Field6 string `validate:"excluded_with=Inner2.Field" json:"field_6"` Field7 Inner `validate:"excluded_with=Field" json:"field_7"` Field8 *Inner `validate:"excluded_with=Field" json:"field_8"` }{ Inner: &Inner{Field: &fieldVal}, Field: "populated", Field1: fieldVal, Field2: &fieldVal, Field3: map[string]string{"key": "val"}, Field4: "test", Field5: "test", Field6: "test", Field7: Inner{FieldE: "potato"}, Field8: &Inner{FieldE: "potato"}, } errs = validate.Struct(test2) NotEqual(t, errs, nil) ve := errs.(ValidationErrors) Equal(t, len(ve), 7) for i := 1; i <= 7; i++ { // accounting for field 7 & 8 failures, 6 skipped because no failure if i > 5 { i++ } name := fmt.Sprintf("Field%d", i) AssertError(t, errs, name, name, name, name, "excluded_with") } test3 := struct { Inner *Inner Inner2 *Inner Field string `validate:"omitempty" json:"field"` FieldE string `validate:"omitempty" json:"field_e"` Field1 string `validate:"excluded_with=FieldE" json:"field_1"` Field2 *string `validate:"excluded_with=FieldE" json:"field_2"` Field3 map[string]string `validate:"excluded_with=FieldE" json:"field_3"` Field4 interface{} `validate:"excluded_with=FieldE" json:"field_4"` Field5 string `validate:"excluded_with=Inner.FieldE" json:"field_5"` Field6 string `validate:"excluded_with=Inner2.FieldE" json:"field_6"` Field7 Inner `validate:"excluded_with=FieldE" json:"field_7"` Field8 *Inner `validate:"excluded_with=FieldE" json:"field_8"` }{ Inner: &Inner{FieldE: "populated"}, Inner2: &Inner{FieldE: "populated"}, FieldE: "populated", } validate = New() errs = validate.Struct(test3) Equal(t, errs, nil) } func TestExcludedWithout(t *testing.T) { type Inner struct { FieldE string Field *string } fieldVal := "test" test := struct { Inner *Inner Inner2 *Inner Field string `validate:"omitempty" json:"field"` FieldE string `validate:"omitempty" json:"field_e"` Field1 string `validate:"excluded_without=Field" json:"field_1"` Field2 *string `validate:"excluded_without=Field" json:"field_2"` Field3 map[string]string `validate:"excluded_without=Field" json:"field_3"` Field4 interface{} `validate:"excluded_without=Field" json:"field_4"` Field5 string `validate:"excluded_without=Inner.Field" json:"field_5"` Field6 Inner `validate:"excluded_without=Field" json:"field_6"` Field7 *Inner `validate:"excluded_without=Field" json:"field_7"` }{ Inner: &Inner{Field: &fieldVal}, Field: "populated", Field1: fieldVal, Field2: &fieldVal, Field3: map[string]string{"key": "val"}, Field4: "test", Field5: "test", Field6: Inner{FieldE: "potato"}, Field7: &Inner{FieldE: "potato"}, } validate := New() errs := validate.Struct(test) Equal(t, errs, nil) test2 := struct { Inner *Inner Inner2 *Inner Field string `validate:"omitempty" json:"field"` FieldE string `validate:"omitempty" json:"field_e"` Field1 string `validate:"excluded_without=FieldE" json:"field_1"` Field2 *string `validate:"excluded_without=FieldE" json:"field_2"` Field3 map[string]string `validate:"excluded_without=FieldE" json:"field_3"` Field4 interface{} `validate:"excluded_without=FieldE" json:"field_4"` Field5 string `validate:"excluded_without=Inner.FieldE" json:"field_5"` Field6 string `validate:"excluded_without=Inner2.FieldE" json:"field_6"` Field7 Inner `validate:"excluded_without=FieldE" json:"field_7"` Field8 *Inner `validate:"excluded_without=FieldE" json:"field_8"` }{ Inner: &Inner{Field: &fieldVal}, Field1: fieldVal, Field2: &fieldVal, Field3: map[string]string{"key": "val"}, Field4: "test", Field5: "test", Field6: "test", Field7: Inner{FieldE: "potato"}, Field8: &Inner{FieldE: "potato"}, } errs = validate.Struct(test2) NotEqual(t, errs, nil) ve := errs.(ValidationErrors) Equal(t, len(ve), 8) for i := 1; i <= 8; i++ { name := fmt.Sprintf("Field%d", i) AssertError(t, errs, name, name, name, name, "excluded_without") } test3 := struct { Inner *Inner Inner2 *Inner Field string `validate:"omitempty" json:"field"` FieldE string `validate:"omitempty" json:"field_e"` Field1 string `validate:"excluded_without=Field" json:"field_1"` Field2 *string `validate:"excluded_without=Field" json:"field_2"` Field3 map[string]string `validate:"excluded_without=Field" json:"field_3"` Field4 interface{} `validate:"excluded_without=Field" json:"field_4"` Field5 string `validate:"excluded_without=Inner.Field" json:"field_5"` Field6 Inner `validate:"excluded_without=Field" json:"field_6"` Field7 *Inner `validate:"excluded_without=Field" json:"field_7"` }{ Inner: &Inner{Field: &fieldVal}, Field: "populated", } validate = New() errs = validate.Struct(test3) Equal(t, errs, nil) } func TestExcludedWithAll(t *testing.T) { type Inner struct { FieldE string Field *string } fieldVal := "test" test := struct { Inner *Inner Inner2 *Inner Field string `validate:"omitempty" json:"field"` FieldE string `validate:"omitempty" json:"field_e"` Field1 string `validate:"excluded_with_all=FieldE Field" json:"field_1"` Field2 *string `validate:"excluded_with_all=FieldE Field" json:"field_2"` Field3 map[string]string `validate:"excluded_with_all=FieldE Field" json:"field_3"` Field4 interface{} `validate:"excluded_with_all=FieldE Field" json:"field_4"` Field5 string `validate:"excluded_with_all=Inner.FieldE" json:"field_5"` Field6 string `validate:"excluded_with_all=Inner2.FieldE" json:"field_6"` Field7 Inner `validate:"excluded_with_all=FieldE Field" json:"field_7"` Field8 *Inner `validate:"excluded_with_all=FieldE Field" json:"field_8"` }{ Inner: &Inner{Field: &fieldVal}, Field: fieldVal, Field1: fieldVal, Field2: &fieldVal, Field3: map[string]string{"key": "val"}, Field4: "test", Field5: "test", Field6: "test", Field7: Inner{FieldE: "potato"}, Field8: &Inner{FieldE: "potato"}, } validate := New() errs := validate.Struct(test) Equal(t, errs, nil) test2 := struct { Inner *Inner Inner2 *Inner Field string `validate:"omitempty" json:"field"` FieldE string `validate:"omitempty" json:"field_e"` Field1 string `validate:"excluded_with_all=Field FieldE" json:"field_1"` Field2 *string `validate:"excluded_with_all=Field FieldE" json:"field_2"` Field3 map[string]string `validate:"excluded_with_all=Field FieldE" json:"field_3"` Field4 interface{} `validate:"excluded_with_all=Field FieldE" json:"field_4"` Field5 string `validate:"excluded_with_all=Inner.Field" json:"field_5"` Field6 string `validate:"excluded_with_all=Inner2.Field" json:"field_6"` Field7 Inner `validate:"excluded_with_all=Field FieldE" json:"field_7"` Field8 *Inner `validate:"excluded_with_all=Field FieldE" json:"field_8"` }{ Inner: &Inner{Field: &fieldVal}, Field: "populated", FieldE: "populated", Field1: fieldVal, Field2: &fieldVal, Field3: map[string]string{"key": "val"}, Field4: "test", Field5: "test", Field6: "test", Field7: Inner{FieldE: "potato"}, Field8: &Inner{FieldE: "potato"}, } errs = validate.Struct(test2) NotEqual(t, errs, nil) ve := errs.(ValidationErrors) Equal(t, len(ve), 7) for i := 1; i <= 7; i++ { // accounting for no err for field 6 if i > 5 { i++ } name := fmt.Sprintf("Field%d", i) AssertError(t, errs, name, name, name, name, "excluded_with_all") } test3 := struct { Inner *Inner Inner2 *Inner Field string `validate:"omitempty" json:"field"` FieldE string `validate:"omitempty" json:"field_e"` Field1 string `validate:"excluded_with_all=FieldE Field" json:"field_1"` Field2 *string `validate:"excluded_with_all=FieldE Field" json:"field_2"` Field3 map[string]string `validate:"excluded_with_all=FieldE Field" json:"field_3"` Field4 interface{} `validate:"excluded_with_all=FieldE Field" json:"field_4"` Field5 string `validate:"excluded_with_all=Inner.FieldE" json:"field_5"` Field6 string `validate:"excluded_with_all=Inner2.FieldE" json:"field_6"` Field7 Inner `validate:"excluded_with_all=Field FieldE" json:"field_7"` Field8 *Inner `validate:"excluded_with_all=Field FieldE" json:"field_8"` }{ Inner: &Inner{FieldE: "populated"}, Inner2: &Inner{FieldE: "populated"}, Field: "populated", FieldE: "populated", } validate = New() errs = validate.Struct(test3) Equal(t, errs, nil) } func TestExcludedWithoutAll(t *testing.T) { type Inner struct { FieldE string Field *string } fieldVal := "test" test := struct { Inner *Inner Inner2 *Inner Field string `validate:"omitempty" json:"field"` FieldE string `validate:"omitempty" json:"field_e"` Field1 string `validate:"excluded_without_all=Field FieldE" json:"field_1"` Field2 *string `validate:"excluded_without_all=Field FieldE" json:"field_2"` Field3 map[string]string `validate:"excluded_without_all=Field FieldE" json:"field_3"` Field4 interface{} `validate:"excluded_without_all=Field FieldE" json:"field_4"` Field5 string `validate:"excluded_without_all=Inner.Field Inner2.Field" json:"field_5"` Field6 Inner `validate:"excluded_without_all=Field FieldE" json:"field_6"` Field7 *Inner `validate:"excluded_without_all=Field FieldE" json:"field_7"` }{ Inner: &Inner{Field: &fieldVal}, Inner2: &Inner{Field: &fieldVal}, Field: "populated", Field1: fieldVal, Field2: &fieldVal, Field3: map[string]string{"key": "val"}, Field4: "test", Field5: "test", Field6: Inner{FieldE: "potato"}, Field7: &Inner{FieldE: "potato"}, } validate := New() errs := validate.Struct(test) Equal(t, errs, nil) test2 := struct { Inner *Inner Inner2 *Inner Field string `validate:"omitempty" json:"field"` FieldE string `validate:"omitempty" json:"field_e"` Field1 string `validate:"excluded_without_all=FieldE Field" json:"field_1"` Field2 *string `validate:"excluded_without_all=FieldE Field" json:"field_2"` Field3 map[string]string `validate:"excluded_without_all=FieldE Field" json:"field_3"` Field4 interface{} `validate:"excluded_without_all=FieldE Field" json:"field_4"` Field5 string `validate:"excluded_without_all=Inner.FieldE" json:"field_5"` Field6 string `validate:"excluded_without_all=Inner2.FieldE" json:"field_6"` Field7 Inner `validate:"excluded_without_all=Field FieldE" json:"field_7"` Field8 *Inner `validate:"excluded_without_all=Field FieldE" json:"field_8"` }{ Inner: &Inner{Field: &fieldVal}, Field1: fieldVal, Field2: &fieldVal, Field3: map[string]string{"key": "val"}, Field4: "test", Field5: "test", Field6: "test", Field7: Inner{FieldE: "potato"}, Field8: &Inner{FieldE: "potato"}, } errs = validate.Struct(test2) NotEqual(t, errs, nil) ve := errs.(ValidationErrors) Equal(t, len(ve), 8) for i := 1; i <= 8; i++ { name := fmt.Sprintf("Field%d", i) AssertError(t, errs, name, name, name, name, "excluded_without_all") } test3 := struct { Inner *Inner Inner2 *Inner Field string `validate:"omitempty" json:"field"` FieldE string `validate:"omitempty" json:"field_e"` Field1 string `validate:"excluded_without_all=Field FieldE" json:"field_1"` Field2 *string `validate:"excluded_without_all=Field FieldE" json:"field_2"` Field3 map[string]string `validate:"excluded_without_all=Field FieldE" json:"field_3"` Field4 interface{} `validate:"excluded_without_all=Field FieldE" json:"field_4"` Field5 string `validate:"excluded_without_all=Inner.Field Inner2.Field" json:"field_5"` Field6 Inner `validate:"excluded_without_all=Field FieldE" json:"field_6"` Field7 *Inner `validate:"excluded_without_all=Field FieldE" json:"field_7"` }{ Inner: &Inner{Field: &fieldVal}, Inner2: &Inner{Field: &fieldVal}, Field: "populated", FieldE: "populated", } validate = New() errs = validate.Struct(test3) Equal(t, errs, nil) } func TestRequiredWithAll(t *testing.T) { type Inner struct { Field *string } fieldVal := "test" test := struct { Inner *Inner FieldE string `validate:"omitempty" json:"field_e"` FieldER string `validate:"required_with_all=FieldE" json:"field_er"` Field1 string `validate:"omitempty" json:"field_1"` Field2 *string `validate:"required_with_all=Field1" json:"field_2"` Field3 map[string]string `validate:"required_with_all=Field2" json:"field_3"` Field4 interface{} `validate:"required_with_all=Field3" json:"field_4"` Field5 string `validate:"required_with_all=Inner.Field" json:"field_5"` Field6 Inner `validate:"required_with_all=Field1 Field2" json:"field_6"` Field7 *Inner `validate:"required_with_all=Field1 Field2" json:"field_7"` }{ Inner: &Inner{Field: &fieldVal}, Field1: "test_field1", Field2: &fieldVal, Field3: map[string]string{"key": "val"}, Field4: "test", Field5: "test", Field6: Inner{Field: &fieldVal}, Field7: &Inner{Field: &fieldVal}, } validate := New() errs := validate.Struct(test) Equal(t, errs, nil) test2 := struct { Inner *Inner Inner2 *Inner FieldE string `validate:"omitempty" json:"field_e"` FieldER string `validate:"required_with_all=FieldE" json:"field_er"` Field1 string `validate:"omitempty" json:"field_1"` Field2 *string `validate:"required_with_all=Field1" json:"field_2"` Field3 map[string]string `validate:"required_with_all=Field2" json:"field_3"` Field4 interface{} `validate:"required_with_all=Field1 FieldE" json:"field_4"` Field5 string `validate:"required_with_all=Inner.Field Field2" json:"field_5"` Field6 string `validate:"required_with_all=Inner2.Field Field2" json:"field_6"` Field7 Inner `validate:"required_with_all=Inner.Field Field2" json:"field_7"` Field8 *Inner `validate:"required_with_all=Inner.Field Field2" json:"field_8"` }{ Inner: &Inner{Field: &fieldVal}, Field2: &fieldVal, } errs = validate.Struct(test2) NotEqual(t, errs, nil) ve := errs.(ValidationErrors) Equal(t, len(ve), 4) AssertError(t, errs, "Field3", "Field3", "Field3", "Field3", "required_with_all") AssertError(t, errs, "Field5", "Field5", "Field5", "Field5", "required_with_all") AssertError(t, errs, "Field7", "Field7", "Field7", "Field7", "required_with_all") AssertError(t, errs, "Field8", "Field8", "Field8", "Field8", "required_with_all") } func TestRequiredWithout(t *testing.T) { type Inner struct { Field *string } fieldVal := "test" test := struct { Inner *Inner Field1 string `validate:"omitempty" json:"field_1"` Field2 *string `validate:"required_without=Field1" json:"field_2"` Field3 map[string]string `validate:"required_without=Field2" json:"field_3"` Field4 interface{} `validate:"required_without=Field3" json:"field_4"` Field5 string `validate:"required_without=Field3" json:"field_5"` Field6 Inner `validate:"required_without=Field1" json:"field_6"` Field7 *Inner `validate:"required_without=Field1" json:"field_7"` }{ Inner: &Inner{Field: &fieldVal}, Field2: &fieldVal, Field3: map[string]string{"key": "val"}, Field4: "test", Field5: "test", Field6: Inner{Field: &fieldVal}, Field7: &Inner{Field: &fieldVal}, } validate := New() errs := validate.Struct(test) Equal(t, errs, nil) test2 := struct { Inner *Inner Inner2 *Inner Field1 string `json:"field_1"` Field2 *string `validate:"required_without=Field1" json:"field_2"` Field3 map[string]string `validate:"required_without=Field2" json:"field_3"` Field4 interface{} `validate:"required_without=Field3" json:"field_4"` Field5 string `validate:"required_without=Field3" json:"field_5"` Field6 string `validate:"required_without=Field1" json:"field_6"` Field7 string `validate:"required_without=Inner.Field" json:"field_7"` Field8 string `validate:"required_without=Inner.Field" json:"field_8"` Field9 Inner `validate:"required_without=Field1" json:"field_9"` Field10 *Inner `validate:"required_without=Field1" json:"field_10"` }{ Inner: &Inner{}, Field3: map[string]string{"key": "val"}, Field4: "test", Field5: "test", } errs = validate.Struct(&test2) NotEqual(t, errs, nil) ve := errs.(ValidationErrors) Equal(t, len(ve), 6) AssertError(t, errs, "Field2", "Field2", "Field2", "Field2", "required_without") AssertError(t, errs, "Field6", "Field6", "Field6", "Field6", "required_without") AssertError(t, errs, "Field7", "Field7", "Field7", "Field7", "required_without") AssertError(t, errs, "Field8", "Field8", "Field8", "Field8", "required_without") AssertError(t, errs, "Field9", "Field9", "Field9", "Field9", "required_without") AssertError(t, errs, "Field10", "Field10", "Field10", "Field10", "required_without") test3 := struct { Field1 *string `validate:"required_without=Field2,omitempty,min=1" json:"field_1"` Field2 *string `validate:"required_without=Field1,omitempty,min=1" json:"field_2"` }{ Field1: &fieldVal, } errs = validate.Struct(&test3) Equal(t, errs, nil) test4 := struct { Field1 string `validate:"required_without=Field2 Field3,omitempty,min=1" json:"field_1"` Field2 string `json:"field_2"` Field3 string `json:"field_3"` }{ Field1: "test", } errs = validate.Struct(&test4) Equal(t, errs, nil) test5 := struct { Field1 string `validate:"required_without=Field2 Field3,omitempty,min=1" json:"field_1"` Field2 string `json:"field_2"` Field3 string `json:"field_3"` }{ Field3: "test", } errs = validate.Struct(&test5) NotEqual(t, errs, nil) ve = errs.(ValidationErrors) Equal(t, len(ve), 1) AssertError(t, errs, "Field1", "Field1", "Field1", "Field1", "required_without") } func TestRequiredWithoutAll(t *testing.T) { type nested struct { value string } fieldVal := "test" test := struct { Field1 string `validate:"omitempty" json:"field_1"` Field2 *string `validate:"required_without_all=Field1" json:"field_2"` Field3 map[string]string `validate:"required_without_all=Field2" json:"field_3"` Field4 interface{} `validate:"required_without_all=Field3" json:"field_4"` Field5 string `validate:"required_without_all=Field3" json:"field_5"` Field6 nested `validate:"required_without_all=Field1" json:"field_6"` Field7 *nested `validate:"required_without_all=Field1" json:"field_7"` }{ Field1: "", Field2: &fieldVal, Field3: map[string]string{"key": "val"}, Field4: "test", Field5: "test", Field6: nested{"potato"}, Field7: &nested{"potato"}, } validate := New() errs := validate.Struct(test) Equal(t, errs, nil) test2 := struct { Field1 string `validate:"omitempty" json:"field_1"` Field2 *string `validate:"required_without_all=Field1" json:"field_2"` Field3 map[string]string `validate:"required_without_all=Field2" json:"field_3"` Field4 interface{} `validate:"required_without_all=Field3" json:"field_4"` Field5 string `validate:"required_without_all=Field3" json:"field_5"` Field6 string `validate:"required_without_all=Field1 Field3" json:"field_6"` Field7 nested `validate:"required_without_all=Field1" json:"field_7"` Field8 *nested `validate:"required_without_all=Field1" json:"field_8"` }{ Field3: map[string]string{"key": "val"}, Field4: "test", Field5: "test", } errs = validate.Struct(test2) NotEqual(t, errs, nil) ve := errs.(ValidationErrors) Equal(t, len(ve), 3) AssertError(t, errs, "Field2", "Field2", "Field2", "Field2", "required_without_all") AssertError(t, errs, "Field7", "Field7", "Field7", "Field7", "required_without_all") AssertError(t, errs, "Field8", "Field8", "Field8", "Field8", "required_without_all") } func TestExcludedIf(t *testing.T) { validate := New() type Inner struct { Field *string } shouldExclude := "exclude" shouldNotExclude := "dontExclude" test1 := struct { FieldE string `validate:"omitempty" json:"field_e"` FieldER *string `validate:"excluded_if=FieldE exclude" json:"field_er"` }{ FieldE: shouldExclude, } errs := validate.Struct(test1) Equal(t, errs, nil) test2 := struct { FieldE string `validate:"omitempty" json:"field_e"` FieldER string `validate:"excluded_if=FieldE exclude" json:"field_er"` }{ FieldE: shouldExclude, FieldER: "set", } errs = validate.Struct(test2) NotEqual(t, errs, nil) ve := errs.(ValidationErrors) Equal(t, len(ve), 1) AssertError(t, errs, "FieldER", "FieldER", "FieldER", "FieldER", "excluded_if") test3 := struct { FieldE string `validate:"omitempty" json:"field_e"` FieldF string `validate:"omitempty" json:"field_f"` FieldER string `validate:"excluded_if=FieldE exclude FieldF exclude" json:"field_er"` }{ FieldE: shouldExclude, FieldF: shouldExclude, FieldER: "set", } errs = validate.Struct(test3) NotEqual(t, errs, nil) ve = errs.(ValidationErrors) Equal(t, len(ve), 1) AssertError(t, errs, "FieldER", "FieldER", "FieldER", "FieldER", "excluded_if") test4 := struct { FieldE string `validate:"omitempty" json:"field_e"` FieldF string `validate:"omitempty" json:"field_f"` FieldER string `validate:"excluded_if=FieldE exclude FieldF exclude" json:"field_er"` }{ FieldE: shouldExclude, FieldF: shouldNotExclude, FieldER: "set", } errs = validate.Struct(test4) Equal(t, errs, nil) test5 := struct { FieldE string `validate:"omitempty" json:"field_e"` FieldER string `validate:"excluded_if=FieldE exclude" json:"field_er"` }{ FieldE: shouldNotExclude, } errs = validate.Struct(test5) Equal(t, errs, nil) test6 := struct { FieldE string `validate:"omitempty" json:"field_e"` FieldER string `validate:"excluded_if=FieldE exclude" json:"field_er"` }{ FieldE: shouldNotExclude, FieldER: "set", } errs = validate.Struct(test6) Equal(t, errs, nil) test7 := struct { Inner *Inner FieldE string `validate:"omitempty" json:"field_e"` Field1 int `validate:"excluded_if=Inner.Field exclude" json:"field_1"` }{ Inner: &Inner{Field: &shouldExclude}, } errs = validate.Struct(test7) Equal(t, errs, nil) test8 := struct { Inner *Inner FieldE string `validate:"omitempty" json:"field_e"` Field1 int `validate:"excluded_if=Inner.Field exclude" json:"field_1"` }{ Inner: &Inner{Field: &shouldExclude}, Field1: 1, } errs = validate.Struct(test8) NotEqual(t, errs, nil) ve = errs.(ValidationErrors) Equal(t, len(ve), 1) AssertError(t, errs, "Field1", "Field1", "Field1", "Field1", "excluded_if") test9 := struct { Inner *Inner FieldE string `validate:"omitempty" json:"field_e"` Field1 int `validate:"excluded_if=Inner.Field exclude" json:"field_1"` }{ Inner: &Inner{Field: &shouldNotExclude}, } errs = validate.Struct(test9) Equal(t, errs, nil) test10 := struct { Inner *Inner FieldE string `validate:"omitempty" json:"field_e"` Field1 int `validate:"excluded_if=Inner.Field exclude" json:"field_1"` }{ Inner: &Inner{Field: &shouldNotExclude}, Field1: 1, } errs = validate.Struct(test10) Equal(t, errs, nil) test11 := struct { Field1 bool Field2 *string `validate:"excluded_if=Field1 false"` }{ Field1: false, Field2: nil, } errs = validate.Struct(test11) Equal(t, errs, nil) test12 := struct { Field1 bool Field2 *string `validate:"excluded_if=Field1 !Field1"` }{ Field1: true, Field2: nil, } errs = validate.Struct(test12) Equal(t, errs, nil) // Checks number of params in struct tag is correct defer func() { if r := recover(); r == nil { t.Errorf("panicTest should have panicked!") } }() fieldVal := "panicTest" panicTest := struct { Inner *Inner Field1 string `validate:"excluded_if=Inner.Field" json:"field_1"` }{ Inner: &Inner{Field: &fieldVal}, } _ = validate.Struct(panicTest) } func TestExcludedUnless(t *testing.T) { validate := New() type Inner struct { Field *string } fieldVal := "test" test := struct { FieldE string `validate:"omitempty" json:"field_e"` FieldER string `validate:"excluded_unless=FieldE test" json:"field_er"` }{ FieldE: "test", FieldER: "filled", } errs := validate.Struct(test) Equal(t, errs, nil) test2 := struct { FieldE string `validate:"omitempty" json:"field_e"` FieldER string `validate:"excluded_unless=FieldE test" json:"field_er"` }{ FieldE: "notest", FieldER: "filled", } errs = validate.Struct(test2) NotEqual(t, errs, nil) ve := errs.(ValidationErrors) Equal(t, len(ve), 1) AssertError(t, errs, "FieldER", "FieldER", "FieldER", "FieldER", "excluded_unless") // test5 and test6: excluded_unless has no effect if FieldER is left blank test5 := struct { FieldE string `validate:"omitempty" json:"field_e"` FieldER string `validate:"excluded_unless=FieldE test" json:"field_er"` }{ FieldE: "test", } errs = validate.Struct(test5) Equal(t, errs, nil) test6 := struct { FieldE string `validate:"omitempty" json:"field_e"` FieldER string `validate:"excluded_unless=FieldE test" json:"field_er"` }{ FieldE: "notest", } errs = validate.Struct(test6) Equal(t, errs, nil) shouldError := "notest" test3 := struct { Inner *Inner Field1 string `validate:"excluded_unless=Inner.Field test" json:"field_1"` }{ Inner: &Inner{Field: &shouldError}, Field1: "filled", } errs = validate.Struct(test3) NotEqual(t, errs, nil) ve = errs.(ValidationErrors) Equal(t, len(ve), 1) AssertError(t, errs, "Field1", "Field1", "Field1", "Field1", "excluded_unless") shouldPass := "test" test4 := struct { Inner *Inner FieldE string `validate:"omitempty" json:"field_e"` Field1 string `validate:"excluded_unless=Inner.Field test" json:"field_1"` }{ Inner: &Inner{Field: &shouldPass}, Field1: "filled", } errs = validate.Struct(test4) Equal(t, errs, nil) // test7 and test8: excluded_unless has no effect if FieldER is left blank test7 := struct { Inner *Inner FieldE string `validate:"omitempty" json:"field_e"` FieldER string `validate:"excluded_unless=Inner.Field test" json:"field_er"` }{ FieldE: "test", } errs = validate.Struct(test7) Equal(t, errs, nil) test8 := struct { FieldE string `validate:"omitempty" json:"field_e"` FieldER string `validate:"excluded_unless=Inner.Field test" json:"field_er"` }{ FieldE: "test", } errs = validate.Struct(test8) Equal(t, errs, nil) // Checks number of params in struct tag is correct defer func() { if r := recover(); r == nil { t.Errorf("panicTest should have panicked!") } }() panicTest := struct { Inner *Inner Field1 string `validate:"excluded_unless=Inner.Field" json:"field_1"` }{ Inner: &Inner{Field: &fieldVal}, } _ = validate.Struct(panicTest) test9 := struct { Field1 int Field2 string `validate:"excluded_unless=Field1 1 Field1 2"` Field3 int Field4 string `validate:"excluded_unless=Field3 1 Field3 2"` }{ Field1: 1, Field2: "foo", Field3: 3, Field4: "foo", } errs = validate.Struct(test9) NotEqual(t, errs, nil) ve = errs.(ValidationErrors) Equal(t, len(ve), 1) AssertError(t, errs, "Field4", "Field4", "Field4", "Field4", "excluded_unless") } func TestLookup(t *testing.T) { type Lookup struct { FieldA *string `json:"fieldA,omitempty" validate:"required_without=FieldB"` FieldB *string `json:"fieldB,omitempty" validate:"required_without=FieldA"` } fieldAValue := "1232" lookup := Lookup{ FieldA: &fieldAValue, FieldB: nil, } Equal(t, New().Struct(lookup), nil) } func TestAbilityToValidateNils(t *testing.T) { type TestStruct struct { Test *string `validate:"nil"` } ts := TestStruct{} val := New() fn := func(fl FieldLevel) bool { return fl.Field().Kind() == reflect.Ptr && fl.Field().IsNil() } err := val.RegisterValidation("nil", fn, true) Equal(t, err, nil) errs := val.Struct(ts) Equal(t, errs, nil) str := "string" ts.Test = &str errs = val.Struct(ts) NotEqual(t, errs, nil) } func TestRequiredWithoutPointers(t *testing.T) { type Lookup struct { FieldA *bool `json:"fieldA,omitempty" validate:"required_without=FieldB"` FieldB *bool `json:"fieldB,omitempty" validate:"required_without=FieldA"` } b := true lookup := Lookup{ FieldA: &b, FieldB: nil, } val := New() errs := val.Struct(lookup) Equal(t, errs, nil) b = false lookup = Lookup{ FieldA: &b, FieldB: nil, } errs = val.Struct(lookup) Equal(t, errs, nil) } func TestRequiredWithoutAllPointers(t *testing.T) { type Lookup struct { FieldA *bool `json:"fieldA,omitempty" validate:"required_without_all=FieldB"` FieldB *bool `json:"fieldB,omitempty" validate:"required_without_all=FieldA"` } b := true lookup := Lookup{ FieldA: &b, FieldB: nil, } val := New() errs := val.Struct(lookup) Equal(t, errs, nil) b = false lookup = Lookup{ FieldA: &b, FieldB: nil, } errs = val.Struct(lookup) Equal(t, errs, nil) } func TestGetTag(t *testing.T) { var tag string type Test struct { String string `validate:"mytag"` } val := New() _ = val.RegisterValidation("mytag", func(fl FieldLevel) bool { tag = fl.GetTag() return true }) var test Test errs := val.Struct(test) Equal(t, errs, nil) Equal(t, tag, "mytag") } func TestJSONValidation(t *testing.T) { tests := []struct { param interface{} expected bool }{ {`foo`, false}, {`}{`, false}, {`{]`, false}, {`{}`, true}, {`{"foo":"bar"}`, true}, {`{"foo":"bar","bar":{"baz":["qux"]}}`, true}, {`{"foo": 3 "bar": 4}`, false}, {`{"foo": 3 ,"bar": 4`, false}, {`{foo": 3, "bar": 4}`, false}, {`foo`, false}, {`1`, true}, {`true`, true}, {`null`, true}, {`"null"`, true}, {json.RawMessage(`foo`), false}, {json.RawMessage(`}{`), false}, {json.RawMessage(`{]`), false}, {json.RawMessage(`{}`), true}, {json.RawMessage(`{"foo":"bar"}`), true}, {json.RawMessage(`{"foo":"bar","bar":{"baz":["qux"]}}`), true}, {json.RawMessage(`{"foo": 3 "bar": 4}`), false}, {json.RawMessage(`{"foo": 3 ,"bar": 4`), false}, {json.RawMessage(`{foo": 3, "bar": 4}`), false}, {json.RawMessage(`foo`), false}, {json.RawMessage(`1`), true}, {json.RawMessage(`true`), true}, {json.RawMessage(`null`), true}, {json.RawMessage(`"null"`), true}, {[]byte(`foo`), false}, {[]byte(`}{`), false}, {[]byte(`{]`), false}, {[]byte(`{}`), true}, {[]byte(`{"foo":"bar"}`), true}, {[]byte(`{"foo":"bar","bar":{"baz":["qux"]}}`), true}, {[]byte(`{"foo": 3 "bar": 4}`), false}, {[]byte(`{"foo": 3 ,"bar": 4`), false}, {[]byte(`{foo": 3, "bar": 4}`), false}, {[]byte(`foo`), false}, {[]byte(`1`), true}, {[]byte(`true`), true}, {[]byte(`null`), true}, {[]byte(`"null"`), true}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "json") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d json failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d json failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "json" { t.Fatalf("Index: %d json failed Error: %s", i, errs) } } } } PanicMatches(t, func() { _ = validate.Var(2, "json") }, "Bad field type int") } func TestJWTValidation(t *testing.T) { tests := []struct { param string expected bool }{ {"eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiZ29waGVyIn0.O_bROM_szPq9qBql-XDHMranHwP48ODdoLICWzqBr_U", true}, {"acb123-_.def456-_.ghi789-_", true}, {"eyJhbGciOiJOT05FIn0.e30.", true}, {"eyJhbGciOiJOT05FIn0.e30.\n", false}, {"\x00.\x00.\x00", false}, {"", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "jwt") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d jwt failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d jwt failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "jwt" { t.Fatalf("Index: %d jwt failed Error: %s", i, errs) } } } } } func Test_hostnameport_validator(t *testing.T) { type Host struct { Addr string `validate:"hostname_port"` } type testInput struct { data string expected bool } testData := []testInput{ {"bad..domain.name:234", false}, {"extra.dot.com.", false}, {"localhost:1234", true}, {"192.168.1.1:1234", true}, {":1234", true}, {"domain.com:1334", true}, {"this.domain.com:234", true}, {"domain:75000", false}, {"missing.port", false}, } for _, td := range testData { h := Host{Addr: td.data} v := New() err := v.Struct(h) if td.expected != (err == nil) { t.Fatalf("Test failed for data: %v Error: %v", td.data, err) } } } func Test_port_validator(t *testing.T) { type Host struct { Port uint32 `validate:"port"` } type testInput struct { data uint32 expected bool } testData := []testInput{ {0, false}, {1, true}, {65535, true}, {65536, false}, {65538, false}, } for _, td := range testData { h := Host{Port: td.data} v := New() err := v.Struct(h) if td.expected != (err == nil) { t.Fatalf("Test failed for data: %v Error: %v", td.data, err) } } } func TestLowercaseValidation(t *testing.T) { tests := []struct { param string expected bool }{ {`abcdefg`, true}, {`Abcdefg`, false}, {"", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "lowercase") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d lowercase failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d lowercase failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "lowercase" { t.Fatalf("Index: %d lowercase failed Error: %s", i, errs) } } } } PanicMatches(t, func() { _ = validate.Var(2, "lowercase") }, "Bad field type int") } func TestUppercaseValidation(t *testing.T) { tests := []struct { param string expected bool }{ {`ABCDEFG`, true}, {`aBCDEFG`, false}, {"", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.param, "uppercase") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d uppercase failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d uppercase failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "uppercase" { t.Fatalf("Index: %d uppercase failed Error: %s", i, errs) } } } } PanicMatches(t, func() { _ = validate.Var(2, "uppercase") }, "Bad field type int") } func TestDatetimeValidation(t *testing.T) { tests := []struct { value string `validate:"datetime=2006-01-02"` tag string expected bool }{ {"2008-02-01", `datetime=2006-01-02`, true}, {"2008-Feb-01", `datetime=2006-01-02`, false}, } validate := New() for i, test := range tests { errs := validate.Var(test.value, test.tag) if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d datetime failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d datetime failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "datetime" { t.Fatalf("Index: %d datetime failed Error: %s", i, errs) } } } } PanicMatches(t, func() { _ = validate.Var(2, "datetime") }, "Bad field type int") } func TestIsIso3166Alpha2Validation(t *testing.T) { tests := []struct { value string `validate:"iso3166_1_alpha2"` expected bool }{ {"PL", true}, {"POL", false}, {"AA", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.value, "iso3166_1_alpha2") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d iso3166_1_alpha2 failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d iso3166_1_alpha2 failed Error: %s", i, errs) } } } } func TestIsIso3166Alpha2EUValidation(t *testing.T) { tests := []struct { value string `validate:"iso3166_1_alpha2_eu"` expected bool }{ {"SE", true}, {"UK", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.value, "iso3166_1_alpha2_eu") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d iso3166_1_alpha2_eu failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d iso3166_1_alpha2_eu failed Error: %s", i, errs) } } } } func TestIsIso31662Validation(t *testing.T) { tests := []struct { value string `validate:"iso3166_2"` expected bool }{ {"US-FL", true}, {"US-F", false}, {"US", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.value, "iso3166_2") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d iso3166_2 failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d iso3166_2 failed Error: %s", i, errs) } } } } func TestIsIso3166Alpha3Validation(t *testing.T) { tests := []struct { value string `validate:"iso3166_1_alpha3"` expected bool }{ {"POL", true}, {"PL", false}, {"AAA", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.value, "iso3166_1_alpha3") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d iso3166_1_alpha3 failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d iso3166_1_alpha3 failed Error: %s", i, errs) } } } } func TestIsIso3166Alpha3EUValidation(t *testing.T) { tests := []struct { value string `validate:"iso3166_1_alpha3_eu"` expected bool }{ {"POL", true}, {"SWE", true}, {"UNK", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.value, "iso3166_1_alpha3_eu") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d iso3166_1_alpha3_eu failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d iso3166_1_alpha3_eu failed Error: %s", i, errs) } } } } func TestIsIso3166AlphaNumericValidation(t *testing.T) { tests := []struct { value interface{} expected bool }{ {248, true}, {"248", true}, {0, false}, {1, false}, {"1", false}, {"invalid_int", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.value, "iso3166_1_alpha_numeric") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d iso3166_1_alpha_numeric failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d iso3166_1_alpha_numeric failed Error: %s", i, errs) } } } PanicMatches(t, func() { _ = validate.Var([]string{"1"}, "iso3166_1_alpha_numeric") }, "Bad field type []string") } func TestIsIso3166AlphaNumericEUValidation(t *testing.T) { tests := []struct { value interface{} expected bool }{ {752, true}, // Sweden {"752", true}, {826, false}, // UK {"826", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.value, "iso3166_1_alpha_numeric_eu") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d iso3166_1_alpha_numeric_eu failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d iso3166_1_alpha_numeric_eu failed Error: %s", i, errs) } } } PanicMatches(t, func() { _ = validate.Var([]string{"1"}, "iso3166_1_alpha_numeric_eu") }, "Bad field type []string") } func TestCountryCodeValidation(t *testing.T) { tests := []struct { value interface{} expected bool }{ {248, true}, {0, false}, {1, false}, {"POL", true}, {"NO", true}, {"248", true}, {"1", false}, {"0", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.value, "country_code") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d country_code failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d country_code failed Error: %s", i, errs) } } } } func TestEUCountryCodeValidation(t *testing.T) { tests := []struct { value interface{} expected bool }{ {724, true}, {0, false}, {1, false}, {"POL", true}, {"NO", false}, {"724", true}, {"1", false}, {"0", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.value, "eu_country_code") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d eu_country_code failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d eu_country_code failed Error: %s", i, errs) } } } } func TestIsIso4217Validation(t *testing.T) { tests := []struct { value string `validate:"iso4217"` expected bool }{ {"TRY", true}, {"EUR", true}, {"USA", false}, {"SLE", true}, {"SLL", false}, {"VED", true}, {"XCG", true}, {"ZWG", true}, {"ANG", false}, {"CUC", false}, {"HRK", false}, {"ZWL", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.value, "iso4217") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d iso4217 failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d iso4217 failed Error: %s", i, errs) } } } } func TestIsIso4217NumericValidation(t *testing.T) { tests := []struct { value int `validate:"iso4217_numeric"` expected bool }{ {8, true}, {12, true}, {13, false}, {925, true}, {694, false}, {924, true}, {926, true}, {532, true}, {191, false}, {931, false}, {932, false}, } validate := New() for i, test := range tests { errs := validate.Var(test.value, "iso4217_numeric") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d iso4217 failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d iso4217 failed Error: %s", i, errs) } } } } func TestTimeZoneValidation(t *testing.T) { tests := []struct { value string `validate:"timezone"` tag string expected bool }{ // systems may have different time zone database, some systems time zone are case insensitive {"America/New_York", `timezone`, true}, {"UTC", `timezone`, true}, {"", `timezone`, false}, {"Local", `timezone`, false}, {"Unknown", `timezone`, false}, } validate := New() for i, test := range tests { errs := validate.Var(test.value, test.tag) if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d time zone failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d time zone failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "timezone" { t.Fatalf("Index: %d time zone failed Error: %s", i, errs) } } } } PanicMatches(t, func() { _ = validate.Var(2, "timezone") }, "Bad field type int") } func TestDurationType(t *testing.T) { tests := []struct { name string s interface{} // struct success bool }{ { name: "valid duration string pass", s: struct { Value time.Duration `validate:"gte=500ns"` }{ Value: time.Second, }, success: true, }, { name: "valid duration int pass", s: struct { Value time.Duration `validate:"gte=500"` }{ Value: time.Second, }, success: true, }, } validate := New() for _, tc := range tests { tc := tc t.Run(tc.name, func(t *testing.T) { t.Parallel() errs := validate.Struct(tc.s) if tc.success { Equal(t, errs, nil) return } NotEqual(t, errs, nil) }) } } func TestBCP47LanguageTagValidation(t *testing.T) { tests := []struct { value string `validate:"bcp47_language_tag"` tag string expected bool }{ {"en-US", "bcp47_language_tag", true}, {"en_GB", "bcp47_language_tag", true}, {"es", "bcp47_language_tag", true}, {"English", "bcp47_language_tag", false}, {"ESES", "bcp47_language_tag", false}, {"az-Cyrl-AZ", "bcp47_language_tag", true}, {"en-029", "bcp47_language_tag", true}, {"xog", "bcp47_language_tag", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.value, test.tag) if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d locale failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d locale failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "bcp47_language_tag" { t.Fatalf("Index: %d locale failed Error: %s", i, errs) } } } } PanicMatches(t, func() { _ = validate.Var(2, "bcp47_language_tag") }, "Bad field type int") } func TestBicIso2014FormatValidation(t *testing.T) { tests := []struct { value string `validate:"bic_iso_9362_2014"` tag string expected bool }{ {"SBICKEN1345", "bic_iso_9362_2014", true}, {"SBICKEN1", "bic_iso_9362_2014", true}, {"SBICKENY", "bic_iso_9362_2014", true}, {"SBICKEN1YYP", "bic_iso_9362_2014", true}, {"SBIC23NXXX", "bic_iso_9362_2014", false}, {"S23CKENXXXX", "bic_iso_9362_2014", false}, {"SBICKENXX", "bic_iso_9362_2014", false}, {"SBICKENXX9", "bic_iso_9362_2014", false}, {"SBICKEN13458", "bic_iso_9362_2014", false}, {"SBICKEN", "bic_iso_9362_2014", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.value, test.tag) if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d bic_iso_9362_2014 failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d bic_iso_9362_2014 failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "bic_iso_9362_2014" { t.Fatalf("Index: %d bic_iso_9362_2014 failed Error: %s", i, errs) } } } } } func TestBicIso2022FormatValidation(t *testing.T) { tests := []struct { value string `validate:"bic"` tag string expected bool }{ {"SBICKEN1345", "bic", true}, {"SBICKEN1", "bic", true}, {"SBICKENY", "bic", true}, {"SBICKEN1YYP", "bic", true}, {"E097AEXX", "bic", true}, // valid under https://www.iso.org/standard/84108.html {"SBIC23NXXX", "bic", false}, {"S23CKENXXXX", "bic", true}, {"SBICKENXX", "bic", false}, {"SBICKENXX9", "bic", false}, {"SBICKEN13458", "bic", false}, {"SBICKEN", "bic", false}, {"DEUTDEFF", "bic", true}, // 8-char classic (Germany) {"DEUTDEFF500", "bic", true}, // 11-char with numeric branch {"A1B2US33", "bic", true}, // digits allowed in 4!c (bank code) {"1234US33", "bic", true}, // all digits in 4!c (2022) {"ZZZ1USAA", "bic", true}, // mixed alnum bank + alnum location {"AB12AE00", "bic", true}, // UAE 8-char {"AB12AE009Z9", "bic", true}, // UAE 11-char with mixed branch {"WG11US335AB", "bic", true}, // example-style with digits in branch {"BNPAFRPP", "bic", true}, // France (BNP Paribas style) {"BOFAUS3NXXX", "bic", true}, // US with default XXX branch {"HSBCHKHHXXX", "bic", true}, // Hong Kong, default branch {"NEDSZAJJ", "bic", true}, // South Africa 8-char {"BARCGB22", "bic", true}, // GB 8-char {"BARCGB22XXX", "bic", true}, // GB 11-char with XXX branch {"0000GB00", "bic", true}, // 4!c all digits + 2!c all digits (allowed) {"A1B2GB00XXX", "bic", true}, // valid 11-char with numeric location and XXX {"TATRAEBX", "bic", true}, // UAE 8-char {"TATRSABX", "bic", true}, // Saudi 8-char {"TATREGBX", "bic", true}, // Egypt 8-char {"TATRBHBX", "bic", true}, // Bahrain 8-char {"DEUTDEFFF", "bic", false}, // 9-char (invalid length) {"DEUTDEFF5", "bic", false}, // 9-char (invalid length) {"DEUTDE", "bic", false}, // 6-char (invalid length) {"DEUTDEFF50", "bic", false}, // 10-char (invalid length) {"DEUTDEFF5000", "bic", false}, // 12-char (invalid length) {"deUTDEFF", "bic", false}, // lowercase not allowed {"DEUTDEfF", "bic", false}, // lowercase in location {"DEU@DEFF", "bic", false}, // special char in bank {"ABCD12FF", "bic", false}, // digits in 2!a country (invalid) {"ABCDDE1-", "bic", false}, // hyphen in location {"ABCDDE1_", "bic", false}, // underscore in location {"ABCDDE١٢", "bic", false}, // non-ASCII digits in location } validate := New() for i, test := range tests { errs := validate.Var(test.value, test.tag) if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d bic failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d bic failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "bic" { t.Fatalf("Index: %d bic failed Error: %s", i, errs) } } } } } func TestSemverFormatValidation(t *testing.T) { tests := []struct { value string `validate:"semver"` tag string expected bool }{ {"1.2.3", "semver", true}, {"10.20.30", "semver", true}, {"1.1.2-prerelease+meta", "semver", true}, {"1.1.2+meta", "semver", true}, {"1.1.2+meta-valid", "semver", true}, {"1.0.0-alpha", "semver", true}, {"1.0.0-alpha.1", "semver", true}, {"1.0.0-alpha.beta", "semver", true}, {"1.0.0-alpha.beta.1", "semver", true}, {"1.0.0-alpha0.valid", "semver", true}, {"1.0.0-alpha.0valid", "semver", true}, {"1.0.0-alpha-a.b-c-somethinglong+build.1-aef.1-its-okay", "semver", true}, {"1.0.0-rc.1+build.1", "semver", true}, {"1.0.0-rc.1+build.123", "semver", true}, {"1.2.3-beta", "semver", true}, {"1.2.3-DEV-SNAPSHOT", "semver", true}, {"1.2.3-SNAPSHOT-123", "semver", true}, {"2.0.0+build.1848", "semver", true}, {"2.0.1-alpha.1227", "semver", true}, {"1.0.0-alpha+beta", "semver", true}, {"1.2.3----RC-SNAPSHOT.12.9.1--.12+788", "semver", true}, {"1.2.3----R-S.12.9.1--.12+meta", "semver", true}, {"1.2.3----RC-SNAPSHOT.12.9.1--.12", "semver", true}, {"1.0.0+0.build.1-rc.10000aaa-kk-0.1", "semver", true}, {"99999999999999999999999.999999999999999999.99999999999999999", "semver", true}, {"1.0.0-0A.is.legal", "semver", true}, {"1", "semver", false}, {"1.2", "semver", false}, {"1.2.3-0123", "semver", false}, {"1.2.3-0123.0123", "semver", false}, {"1.1.2+.123", "semver", false}, {"+invalid", "semver", false}, {"-invalid", "semver", false}, {"-invalid+invalid", "semver", false}, {"alpha", "semver", false}, {"alpha.beta.1", "semver", false}, {"alpha.1", "semver", false}, {"1.0.0-alpha_beta", "semver", false}, {"1.0.0-alpha_beta", "semver", false}, {"1.0.0-alpha...1", "semver", false}, {"01.1.1", "semver", false}, {"1.01.1", "semver", false}, {"1.1.01", "semver", false}, {"1.2", "semver", false}, {"1.2.Dev", "semver", false}, {"1.2.3.Dev", "semver", false}, {"1.2-SNAPSHOT", "semver", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.value, test.tag) if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d semver failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d semver failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "semver" { t.Fatalf("Index: %d semver failed Error: %s", i, errs) } } } } } func TestCveFormatValidation(t *testing.T) { tests := []struct { value string `validate:"cve"` tag string expected bool }{ {"CVE-1999-0001", "cve", true}, {"CVE-1998-0001", "cve", false}, {"CVE-2000-0001", "cve", true}, {"CVE-2222-0001", "cve", true}, {"2222-0001", "cve", false}, {"-2222-0001", "cve", false}, {"CVE22220001", "cve", false}, {"CVE-2222-000001", "cve", false}, {"CVE-2222-100001", "cve", true}, {"CVE-2222-99999999999", "cve", true}, {"CVE-3000-0001", "cve", false}, {"CVE-1999-0000", "cve", false}, {"CVE-2099-0000", "cve", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.value, test.tag) if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d cve failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d cve failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "cve" { t.Fatalf("Index: %d cve failed Error: %s", i, errs) } } } } } func TestRFC1035LabelFormatValidation(t *testing.T) { tests := []struct { value string `validate:"dns_rfc1035_label"` tag string expected bool }{ {"abc", "dns_rfc1035_label", true}, {"abc-", "dns_rfc1035_label", false}, {"abc-123", "dns_rfc1035_label", true}, {"ABC", "dns_rfc1035_label", false}, {"ABC-123", "dns_rfc1035_label", false}, {"abc-abc", "dns_rfc1035_label", true}, {"ABC-ABC", "dns_rfc1035_label", false}, {"123-abc", "dns_rfc1035_label", false}, {"", "dns_rfc1035_label", false}, {"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk", "dns_rfc1035_label", true}, {"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl", "dns_rfc1035_label", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.value, test.tag) if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d dns_rfc1035_label failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d dns_rfc1035_label failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "dns_rfc1035_label" { t.Fatalf("Index: %d dns_rfc1035_label failed Error: %s", i, errs) } } } } } func TestPostCodeByIso3166Alpha2(t *testing.T) { tests := map[string][]struct { value string expected bool }{ "VN": { {"ABC", false}, {"700000", true}, {"A1", false}, }, "GB": { {"EC1A 1BB", true}, {"CF10 1B1H", false}, }, "VI": { {"00803", true}, {"1234567", false}, }, "LC": { // not support regexp for post code {"123456", false}, }, "XX": { // not support country {"123456", false}, }, } validate := New() for cc, ccTests := range tests { for i, test := range ccTests { errs := validate.Var(test.value, fmt.Sprintf("postcode_iso3166_alpha2=%s", cc)) if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d postcode_iso3166_alpha2=%s failed Error: %s", i, cc, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d postcode_iso3166_alpha2=%s failed Error: %s", i, cc, errs) } } } } } func TestPostCodeByIso3166Alpha2Field(t *testing.T) { tests := []struct { Value string `validate:"postcode_iso3166_alpha2_field=CountryCode"` CountryCode interface{} expected bool }{ {"ABC", "VN", false}, {"700000", "VN", true}, {"A1", "VN", false}, {"EC1A 1BB", "GB", true}, {"CF10 1B1H", "GB", false}, {"00803", "VI", true}, {"1234567", "VI", false}, {"123456", "LC", false}, // not support regexp for post code {"123456", "XX", false}, // not support country } validate := New() for i, test := range tests { errs := validate.Struct(test) if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d postcode_iso3166_alpha2_field=CountryCode failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d postcode_iso3166_alpha2_field=CountryCode failed Error: %s", i, errs) } } } } func TestPostCodeByIso3166Alpha2Field_WrongField(t *testing.T) { type test struct { Value string `validate:"postcode_iso3166_alpha2_field=CountryCode"` CountryCode1 interface{} expected bool } errs := New().Struct(test{"ABC", "VN", false}) NotEqual(t, nil, errs) } func TestPostCodeByIso3166Alpha2Field_MissingParam(t *testing.T) { type test struct { Value string `validate:"postcode_iso3166_alpha2_field="` CountryCode1 interface{} expected bool } errs := New().Struct(test{"ABC", "VN", false}) NotEqual(t, nil, errs) } func TestPostCodeByIso3166Alpha2Field_InvalidKind(t *testing.T) { type test struct { Value string `validate:"postcode_iso3166_alpha2_field=CountryCode"` CountryCode interface{} expected bool } defer func() { _ = recover() }() _ = New().Struct(test{"ABC", 123, false}) t.Errorf("Didn't panic as expected") } func TestValidate_ValidateMapCtx(t *testing.T) { type args struct { data map[string]interface{} rules map[string]interface{} } tests := []struct { name string args args want int }{ { name: "test nested map in slice", args: args{ data: map[string]interface{}{ "Test_A": map[string]interface{}{ "Test_B": "Test_B", "Test_C": []map[string]interface{}{ { "Test_D": "Test_D", }, }, "Test_E": map[string]interface{}{ "Test_F": "Test_F", }, }, }, rules: map[string]interface{}{ "Test_A": map[string]interface{}{ "Test_B": "min=2", "Test_C": map[string]interface{}{ "Test_D": "min=2", }, "Test_E": map[string]interface{}{ "Test_F": "min=2", }, }, }, }, want: 0, }, { name: "test nested map error", args: args{ data: map[string]interface{}{ "Test_A": map[string]interface{}{ "Test_B": "Test_B", "Test_C": []interface{}{"Test_D"}, "Test_E": map[string]interface{}{ "Test_F": "Test_F", }, "Test_G": "Test_G", "Test_I": []map[string]interface{}{ { "Test_J": "Test_J", }, }, }, }, rules: map[string]interface{}{ "Test_A": map[string]interface{}{ "Test_B": "min=2", "Test_C": map[string]interface{}{ "Test_D": "min=2", }, "Test_E": map[string]interface{}{ "Test_F": "min=100", }, "Test_G": map[string]interface{}{ "Test_H": "min=2", }, "Test_I": map[string]interface{}{ "Test_J": "min=100", }, }, }, }, want: 1, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { validate := New() if got := validate.ValidateMapCtx(context.Background(), tt.args.data, tt.args.rules); len(got) != tt.want { t.Errorf("ValidateMapCtx() = %v, want %v", got, tt.want) } }) } } func TestValidate_ValidateMapCtxWithKeys(t *testing.T) { type args struct { data map[string]interface{} rules map[string]interface{} errors map[string]interface{} } tests := []struct { name string args args want int }{ { name: "test invalid email", args: args{ data: map[string]interface{}{ "email": "emailaddress", }, rules: map[string]interface{}{ "email": "required,email", }, errors: map[string]interface{}{ "email": "Key: 'email' Error:Field validation for 'email' failed on the 'email' tag", }, }, want: 1, }, { name: "test multiple errors with capitalized keys", args: args{ data: map[string]interface{}{ "Email": "emailaddress", "Age": 15, }, rules: map[string]interface{}{ "Email": "required,email", "Age": "number,gt=16", }, errors: map[string]interface{}{ "Email": "Key: 'Email' Error:Field validation for 'Email' failed on the 'email' tag", "Age": "Key: 'Age' Error:Field validation for 'Age' failed on the 'gt' tag", }, }, want: 2, }, { name: "test valid map data", args: args{ data: map[string]interface{}{ "email": "email@example.com", "age": 17, }, rules: map[string]interface{}{ "email": "required,email", "age": "number,gt=16", }, errors: map[string]interface{}{}, }, want: 0, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { validate := New() errs := validate.ValidateMapCtx(context.Background(), tt.args.data, tt.args.rules) NotEqual(t, errs, nil) Equal(t, len(errs), tt.want) for key, err := range errs { Equal(t, err.(ValidationErrors)[0].Error(), tt.args.errors[key]) } }) } } // TestValidateMapWithCrossFieldValidators tests that cross-field validators // like required_if, required_unless, etc. don't panic when used with ValidateMap. // This is a regression test for issue #893. // // Note: With ValidateMap, cross-field lookups return "not found" since there's no // struct context. Validators handle this by using their defaultNotFoundValue: // - required_if: condition not met (returns false) → field not required // - required_unless: condition not met (returns false) → field required // - excluded_if: condition not met (returns false) → field not excluded // - excluded_unless: condition not met (returns false) → field must be excluded func TestValidateMapWithCrossFieldValidators(t *testing.T) { validate := New() // Test required_if - should not panic // Cross-field lookup returns not found → condition not met → field not required data := map[string]interface{}{ "name": "hello", "id": 123, } rules := map[string]interface{}{ "name": "required_if=id 345", "id": "required", } errs := validate.ValidateMap(data, rules) Equal(t, len(errs), 0) // Test required_unless - should not panic // Cross-field lookup returns not found → condition not met → field required // Since name has a value, validation passes rules2 := map[string]interface{}{ "name": "required_unless=id 345", "id": "required", } errs = validate.ValidateMap(data, rules2) Equal(t, len(errs), 0) // Test excluded_if - should not panic // Cross-field lookup returns not found → condition not met → field not excluded rules3 := map[string]interface{}{ "name": "excluded_if=id 123", "id": "required", } errs = validate.ValidateMap(data, rules3) Equal(t, len(errs), 0) // Test excluded_unless - should not panic // Cross-field lookup returns not found → condition not met → field must be excluded // Since name has a value, validation FAILS (this is expected behavior) rules4 := map[string]interface{}{ "name": "excluded_unless=id 123", "id": "required", } errs = validate.ValidateMap(data, rules4) Equal(t, len(errs), 1) // Fails because name has value but condition can't be verified // Test excluded_unless with empty value - should pass since field is excluded dataEmpty := map[string]interface{}{ "name": "", "id": 123, } errs = validate.ValidateMap(dataEmpty, rules4) Equal(t, len(errs), 0) // Test with empty name - required_if condition not met, so empty is ok data2 := map[string]interface{}{ "name": "", "id": 123, } errs = validate.ValidateMap(data2, rules) Equal(t, len(errs), 0) } func TestValidate_VarWithKey(t *testing.T) { validate := New() errs := validate.VarWithKey("email", "invalidemail", "required,email") NotEqual(t, errs, nil) AssertError(t, errs, "email", "email", "email", "email", "email") errs = validate.VarWithKey("email", "email@example.com", "required,email") Equal(t, errs, nil) } func TestValidate_VarWithKeyCtx(t *testing.T) { validate := New() errs := validate.VarWithKeyCtx(context.Background(), "age", 15, "required,gt=16") NotEqual(t, errs, nil) AssertError(t, errs, "age", "age", "age", "age", "gt") errs = validate.VarWithKey("age", 17, "required,gt=16") Equal(t, errs, nil) } func TestMongoDBObjectIDFormatValidation(t *testing.T) { tests := []struct { value string `validate:"mongodb"` tag string expected bool }{ {"507f191e810c19729de860ea", "mongodb", true}, {"507f191e810c19729de860eG", "mongodb", false}, {"M07f191e810c19729de860eG", "mongodb", false}, {"07f191e810c19729de860ea", "mongodb", false}, {"507f191e810c19729de860e", "mongodb", false}, {"507f191e810c19729de860ea4", "mongodb", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.value, test.tag) if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d mongodb failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d mongodb failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "mongodb" { t.Fatalf("Index: %d mongodb failed Error: %s", i, errs) } } } } } func TestMongoDBConnectionStringFormatValidation(t *testing.T) { tests := []struct { value string `validate:"mongodb_connection_string"` tag string expected bool }{ {"mongodb://username:password@server.example.com:20017/database?replicaSet=test&connectTimeoutMS=300000&ssl=true", "mongodb_connection_string", true}, {"mongodb+srv://username:password@server.example.com:20017/database?replicaSet=test&connectTimeoutMS=300000&ssl=true", "mongodb_connection_string", true}, {"mongodb+srv://username:password@server.example.com:20017,server.example.com,server.example.com:20017/database?replicaSet=test&connectTimeoutMS=300000&ssl=true", "mongodb_connection_string", true}, {"mongodb+srv://username:password@server.example.com:20017,server.example.com,server.example.com:20017?replicaSet=test&connectTimeoutMS=300000&ssl=true", "mongodb_connection_string", true}, {"mongodb://username:password@server.example.com:20017,server.example.com,server.example.com:20017/database?replicaSet=test&connectTimeoutMS=300000&ssl=true", "mongodb_connection_string", true}, {"mongodb://localhost", "mongodb_connection_string", true}, {"mongodb://localhost:27017", "mongodb_connection_string", true}, {"localhost", "mongodb_connection_string", false}, {"mongodb://", "mongodb_connection_string", false}, {"mongodb+srv://", "mongodb_connection_string", false}, {"mongodbsrv://localhost", "mongodb_connection_string", false}, {"mongodb+srv://localhost", "mongodb_connection_string", true}, {"mongodb+srv://localhost:27017", "mongodb_connection_string", true}, {"mongodb+srv://localhost?replicaSet=test", "mongodb_connection_string", true}, {"mongodb+srv://localhost:27017?replicaSet=test", "mongodb_connection_string", true}, {"mongodb+srv://localhost:27017?", "mongodb_connection_string", false}, {"mongodb+srv://localhost:27017?replicaSet", "mongodb_connection_string", false}, {"mongodb+srv://localhost/database", "mongodb_connection_string", true}, {"mongodb+srv://localhost:27017/database", "mongodb_connection_string", true}, {"mongodb+srv://username@localhost", "mongodb_connection_string", false}, {"mongodb+srv://username:password@localhost", "mongodb_connection_string", true}, {"mongodb+srv://username:password@localhost:27017", "mongodb_connection_string", true}, {"mongodb+srv://username:password@localhost:27017,192.0.0.7,192.0.0.9:27018,server.example.com", "mongodb_connection_string", true}, } validate := New() for i, test := range tests { errs := validate.Var(test.value, test.tag) if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d mongodb_connection_string failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d mongodb_connection_string failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "mongodb_connection_string" { t.Fatalf("Index: %d mongodb_connection_string failed Error: %s", i, errs) } } } } } func TestSpiceDBValueFormatValidation(t *testing.T) { tests := []struct { value string tag string expected bool }{ // Must be an asterisk OR a string containing alphanumeric characters and a restricted set a special symbols: _ | / - = + {"*", "spicedb=id", true}, {`azAZ09_|/-=+`, "spicedb=id", true}, {`a*`, "spicedb=id", false}, {`/`, "spicedb=id", true}, {"*", "spicedb", true}, // Must begin and end with a lowercase letter, may also contain numbers and underscores between, min length 3, max length 64 {"a", "spicedb=permission", false}, {"1", "spicedb=permission", false}, {"a1", "spicedb=permission", false}, {"a_b", "spicedb=permission", true}, {"A_b", "spicedb=permission", false}, {"a_B", "spicedb=permission", false}, {"abcdefghijklmnopqrstuvwxyz_0123456789_abcdefghijklmnopqrstuvwxyz", "spicedb=permission", true}, {"abcdefghijklmnopqrstuvwxyz_01234_56789_abcdefghijklmnopqrstuvwxyz", "spicedb=permission", false}, // Object types follow the same rules as permissions for the type name plus an optional prefix up to 63 characters with a / {"a", "spicedb=type", false}, {"1", "spicedb=type", false}, {"a1", "spicedb=type", false}, {"a_b", "spicedb=type", true}, {"A_b", "spicedb=type", false}, {"a_B", "spicedb=type", false}, {"abcdefghijklmnopqrstuvwxyz_0123456789_abcdefghijklmnopqrstuvwxyz", "spicedb=type", true}, {"abcdefghijklmnopqrstuvwxyz_01234_56789_abcdefghijklmnopqrstuvwxyz", "spicedb=type", false}, {`a_b/a`, "spicedb=type", false}, {`a_b/1`, "spicedb=type", false}, {`a_b/a1`, "spicedb=type", false}, {`a_b/a_b`, "spicedb=type", true}, {`a_b/A_b`, "spicedb=type", false}, {`a_b/a_B`, "spicedb=type", false}, {`a_b/abcdefghijklmnopqrstuvwxyz_0123456789_abcdefghijklmnopqrstuvwxyz`, "spicedb=type", true}, {`a_b/abcdefghijklmnopqrstuvwxyz_01234_56789_abcdefghijklmnopqrstuvwxyz`, "spicedb=type", false}, {`a/a_b`, "spicedb=type", false}, {`1/a_b`, "spicedb=type", false}, {`a1/a_b`, "spicedb=type", false}, {`a_b/a_b`, "spicedb=type", true}, {`A_b/a_b`, "spicedb=type", false}, {`a_B/a_b`, "spicedb=type", false}, {`abcdefghijklmnopqrstuvwxyz_0123456789_abcdefghijklmnopqrstuvwxy/a_b`, "spicedb=type", true}, {`abcdefghijklmnopqrstuvwxyz_0123456789_abcdefghijklmnopqrstuvwxyz/a_b`, "spicedb=type", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.value, test.tag) if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d spicedb failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d spicedb - expected error but there was none.", i) } else { val := getError(errs, "", "") if val.Tag() != "spicedb" { t.Fatalf("Index: %d spicedb failed Error: %s", i, errs) } } } } } func TestCreditCardFormatValidation(t *testing.T) { tests := []struct { value string `validate:"credit_card"` tag string expected bool }{ {"586824160825533338", "credit_card", true}, {"586824160825533328", "credit_card", false}, {"4624748233249780", "credit_card", true}, {"4624748233349780", "credit_card", false}, {"378282246310005", "credit_card", true}, {"378282146310005", "credit_card", false}, {"4624 7482 3324 9780", "credit_card", true}, {"4624 7482 3324 9780", "credit_card", false}, {"4624 7482 3324 978A", "credit_card", false}, {"4624 7482 332", "credit_card", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.value, test.tag) if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d credit_card failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d credit_card failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "credit_card" { t.Fatalf("Index: %d credit_card failed Error: %s", i, errs) } } } } } func TestLuhnChecksumValidation(t *testing.T) { testsUint := []struct { value interface{} `validate:"luhn_checksum"` // the type is interface{} because the luhn_checksum works on both strings and numbers tag string expected bool }{ {uint64(586824160825533338), "luhn_checksum", true}, // credit card numbers are just special cases of numbers with luhn checksum {int64(586824160825533338), "luhn_checksum", true}, {"586824160825533338", "luhn_checksum", true}, {uint64(586824160825533328), "luhn_checksum", false}, {int64(586824160825533328), "luhn_checksum", false}, {"586824160825533328", "luhn_checksum", false}, {int64(10000000116), "luhn_checksum", true}, // but there may be shorter numbers (11 digits) {"10000000116", "luhn_checksum", true}, {int64(10000000117), "luhn_checksum", false}, {"10000000117", "luhn_checksum", false}, {uint64(12345678123456789011), "luhn_checksum", true}, // or longer numbers (19 digits) {"12345678123456789011", "luhn_checksum", true}, {1, "luhn_checksum", false}, // single digits (checksum only) are not allowed {"1", "luhn_checksum", false}, {-10, "luhn_checksum", false}, // negative ints are not allowed {"abcdefghijklmnop", "luhn_checksum", false}, } validate := New() for i, test := range testsUint { errs := validate.Var(test.value, test.tag) if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d luhn_checksum failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d luhn_checksum failed Error: %s", i, errs) } else { val := getError(errs, "", "") if val.Tag() != "luhn_checksum" { t.Fatalf("Index: %d luhn_checksum failed Error: %s", i, errs) } } } } } func TestMultiOrOperatorGroup(t *testing.T) { tests := []struct { Value int `validate:"eq=1|gte=5,eq=1|lt=7"` expected bool }{ {1, true}, {2, false}, {5, true}, {6, true}, {8, false}, } validate := New() for i, test := range tests { errs := validate.Struct(test) if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d multi_group_of_OR_operators failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d multi_group_of_OR_operators should have errs", i) } } } } func TestCronExpressionValidation(t *testing.T) { tests := []struct { value string `validate:"cron"` tag string expected bool }{ {"0 0 12 * * ?", "cron", true}, {"0 15 10 ? * *", "cron", true}, {"0 15 10 * * ?", "cron", true}, {"0 15 10 * * ? 2005", "cron", true}, {"0 15 10 ? * 6L", "cron", true}, {"0 15 10 ? * 6L 2002-2005", "cron", true}, {"*/20 * * * *", "cron", true}, {"0 15 10 ? * MON-FRI", "cron", true}, {"0 15 10 ? * 6#3", "cron", true}, {"0 */15 * * *", "cron", true}, {"wrong", "cron", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.value, test.tag) if test.expected { if !IsEqual(errs, nil) { t.Fatalf(`Index: %d cron "%s" failed Error: %s`, i, test.value, errs) } } else { if IsEqual(errs, nil) { t.Fatalf(`Index: %d cron "%s" should have errs`, i, test.value) } } } } func TestNestedStructValidation(t *testing.T) { validator := New(WithRequiredStructEnabled()) t.Run("required", func(t *testing.T) { type ( value struct { Field string } topLevel struct { Nested value `validate:"required"` } ) var validationErrs ValidationErrors if errs := validator.Struct(topLevel{}); errs != nil { validationErrs = errs.(ValidationErrors) } Equal(t, 1, len(validationErrs)) AssertError(t, validationErrs, "topLevel.Nested", "topLevel.Nested", "Nested", "Nested", "required") Equal(t, validator.Struct(topLevel{value{"potato"}}), nil) }) t.Run("omitempty", func(t *testing.T) { type ( value struct { Field string } topLevel struct { Nested value `validate:"omitempty,required"` } ) errs := validator.Struct(topLevel{}) Equal(t, errs, nil) }) t.Run("excluded_if", func(t *testing.T) { type ( value struct { Field string } topLevel struct { Field string Nested value `validate:"excluded_if=Field potato"` } ) errs := validator.Struct(topLevel{Field: "test", Nested: value{"potato"}}) Equal(t, errs, nil) errs = validator.Struct(topLevel{Field: "potato"}) Equal(t, errs, nil) errs = validator.Struct(topLevel{Field: "potato", Nested: value{"potato"}}) AssertError(t, errs, "topLevel.Nested", "topLevel.Nested", "Nested", "Nested", "excluded_if") }) t.Run("excluded_unless", func(t *testing.T) { type ( value struct { Field string } topLevel struct { Field string Nested value `validate:"excluded_unless=Field potato"` } ) errs := validator.Struct(topLevel{Field: "test"}) Equal(t, errs, nil) errs = validator.Struct(topLevel{Field: "potato", Nested: value{"potato"}}) Equal(t, errs, nil) errs = validator.Struct(topLevel{Field: "test", Nested: value{"potato"}}) AssertError(t, errs, "topLevel.Nested", "topLevel.Nested", "Nested", "Nested", "excluded_unless") }) t.Run("nonComparableField", func(t *testing.T) { type ( value struct { Field []string } topLevel struct { Nested value `validate:"required"` } ) errs := validator.Struct(topLevel{value{[]string{}}}) Equal(t, errs, nil) }) type ( veggyBasket struct { Root string Squash string `validate:"required"` } testErr struct { path string tag string } test struct { name string err testErr value veggyBasket } ) if err := validator.RegisterValidation("veggy", func(f FieldLevel) bool { v, ok := f.Field().Interface().(veggyBasket) if !ok || v.Root != "potato" { return false } return true }); err != nil { t.Fatal(fmt.Errorf("failed to register potato tag: %w", err)) } tests := []test{ { name: "valid", value: veggyBasket{"potato", "zucchini"}, }, { name: "failedCustomTag", value: veggyBasket{"zucchini", "potato"}, err: testErr{"topLevel.VeggyBasket", "veggy"}, }, { name: "failedInnerField", value: veggyBasket{"potato", ""}, err: testErr{"topLevel.VeggyBasket.Squash", "required"}, }, { name: "customTagFailurePriorityCheck", value: veggyBasket{"zucchini", ""}, err: testErr{"topLevel.VeggyBasket", "veggy"}, }, } evaluateTest := func(tt test, errs error) { if tt.err != (testErr{}) && errs != nil { Equal(t, len(errs.(ValidationErrors)), 1) segments := strings.Split(tt.err.path, ".") fieldName := segments[len(segments)-1] AssertError(t, errs, tt.err.path, tt.err.path, fieldName, fieldName, tt.err.tag) } shouldFail := tt.err != (testErr{}) hasFailed := errs != nil if shouldFail != hasFailed { t.Fatalf("expected failure %v, got: %v with errs: %v", shouldFail, hasFailed, errs) } } for _, tt := range tests { type topLevel struct { VeggyBasket veggyBasket `validate:"veggy"` } t.Run(tt.name, func(t *testing.T) { evaluateTest(tt, validator.Struct(topLevel{tt.value})) }) } // Also test on struct pointers for _, tt := range tests { type topLevel struct { VeggyBasket *veggyBasket `validate:"veggy"` } t.Run(tt.name+"Ptr", func(t *testing.T) { evaluateTest(tt, validator.Struct(topLevel{&tt.value})) }) } } func TestTimeRequired(t *testing.T) { validate := New() validate.RegisterTagNameFunc(func(fld reflect.StructField) string { name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] if name == "-" { return "" } return name }) type TestTime struct { Time time.Time `validate:"required"` } var testTime TestTime err := validate.Struct(&testTime) NotEqual(t, err, nil) AssertError(t, err.(ValidationErrors), "TestTime.Time", "TestTime.Time", "Time", "Time", "required") } func TestOmitNilAndRequired(t *testing.T) { type ( OmitEmpty struct { Str string `validate:"omitempty,required,min=10"` StrPtr *string `validate:"omitempty,required,min=10"` Inner *OmitEmpty } OmitNil struct { Str string `validate:"omitnil,required,min=10"` StrPtr *string `validate:"omitnil,required,min=10"` Inner *OmitNil } ) var ( validate = New(WithRequiredStructEnabled()) valid = "this is the long string to pass the validation rule" ) t.Run("compare using valid data", func(t *testing.T) { err1 := validate.Struct(OmitEmpty{Str: valid, StrPtr: &valid, Inner: &OmitEmpty{Str: valid, StrPtr: &valid}}) err2 := validate.Struct(OmitNil{Str: valid, StrPtr: &valid, Inner: &OmitNil{Str: valid, StrPtr: &valid}}) Equal(t, err1, nil) Equal(t, err2, nil) }) t.Run("compare fully empty omitempty and omitnil", func(t *testing.T) { err1 := validate.Struct(OmitEmpty{}) err2 := validate.Struct(OmitNil{}) Equal(t, err1, nil) AssertError(t, err2, "OmitNil.Str", "OmitNil.Str", "Str", "Str", "required") }) t.Run("validate in deep", func(t *testing.T) { err1 := validate.Struct(OmitEmpty{Str: valid, Inner: &OmitEmpty{}}) err2 := validate.Struct(OmitNil{Str: valid, Inner: &OmitNil{}}) Equal(t, err1, nil) AssertError(t, err2, "OmitNil.Inner.Str", "OmitNil.Inner.Str", "Str", "Str", "required") }) } func TestOmitZero(t *testing.T) { type ( OmitEmpty struct { Str string `validate:"omitempty,min=10"` StrPtr *string `validate:"omitempty,min=10"` } OmitZero struct { Str string `validate:"omitzero,min=10"` StrPtr *string `validate:"omitzero,min=10"` } ) var ( validate = New() valid = "this is the long string to pass the validation rule" empty = "" ) t.Run("compare using valid data", func(t *testing.T) { err1 := validate.Struct(OmitEmpty{Str: valid, StrPtr: &valid}) err2 := validate.Struct(OmitZero{Str: valid, StrPtr: &valid}) Equal(t, err1, nil) Equal(t, err2, nil) }) t.Run("compare fully empty omitempty and omitzero", func(t *testing.T) { err1 := validate.Struct(OmitEmpty{}) err2 := validate.Struct(OmitZero{}) Equal(t, err1, nil) Equal(t, err2, nil) }) t.Run("compare with zero value", func(t *testing.T) { err1 := validate.Struct(OmitEmpty{Str: "", StrPtr: nil}) err2 := validate.Struct(OmitZero{Str: "", StrPtr: nil}) Equal(t, err1, nil) Equal(t, err2, nil) }) t.Run("compare with empty value", func(t *testing.T) { err1 := validate.Struct(OmitEmpty{Str: empty, StrPtr: &empty}) err2 := validate.Struct(OmitZero{Str: empty, StrPtr: &empty}) AssertError(t, err1, "OmitEmpty.StrPtr", "OmitEmpty.StrPtr", "StrPtr", "StrPtr", "min") Equal(t, err2, nil) }) } func TestEINStringValidation(t *testing.T) { tests := []struct { value string `validate:"ein"` expected bool }{ {"01-2564282", true}, {"25-4573894", true}, {"63-236", false}, {"3-5738294", false}, {"4235-48", false}, {"0.-47829", false}, {"23-", false}, } validate := New() for i, test := range tests { errs := validate.Var(test.value, "ein") if test.expected { if !IsEqual(errs, nil) { t.Fatalf("Index: %d ein failed Error: %s", i, errs) } } else { if IsEqual(errs, nil) { t.Fatalf("Index: %d ein failed Error: %s", i, errs) } } } } func TestPrivateFieldsStruct(t *testing.T) { type tc struct { stct interface{} errorNum int } tcs := []tc{ { stct: &struct { f1 int8 `validate:"required"` f2 int16 `validate:"required"` f3 int32 `validate:"required"` f4 int64 `validate:"required"` }{}, errorNum: 4, }, { stct: &struct { f1 uint8 `validate:"required"` f2 uint16 `validate:"required"` f3 uint32 `validate:"required"` f4 uint64 `validate:"required"` }{}, errorNum: 4, }, { stct: &struct { f1 complex64 `validate:"required"` f2 complex128 `validate:"required"` }{}, errorNum: 2, }, { stct: &struct { f1 float32 `validate:"required"` f2 float64 `validate:"required"` }{}, errorNum: 2, }, { stct: struct { f1 int8 `validate:"required"` f2 int16 `validate:"required"` f3 int32 `validate:"required"` f4 int64 `validate:"required"` }{}, errorNum: 4, }, { stct: struct { f1 uint8 `validate:"required"` f2 uint16 `validate:"required"` f3 uint32 `validate:"required"` f4 uint64 `validate:"required"` }{}, errorNum: 4, }, { stct: struct { f1 complex64 `validate:"required"` f2 complex128 `validate:"required"` }{}, errorNum: 2, }, { stct: struct { f1 float32 `validate:"required"` f2 float64 `validate:"required"` }{}, errorNum: 2, }, { stct: struct { f1 *int `validate:"required"` f2 struct { f3 int `validate:"required"` } }{}, errorNum: 2, }, { stct: &struct { f1 *int `validate:"required"` f2 struct { f3 int `validate:"required"` } }{}, errorNum: 2, }, { stct: &struct { f1 map[string]string `validate:"required,dive,required"` f2 *int `validate:"omitnil,min=2"` }{ f1: map[string]string{"key": ""}, f2: intPtr(1), }, errorNum: 2, }, } validate := New(WithPrivateFieldValidation()) for _, tc := range tcs { err := validate.Struct(tc.stct) NotEqual(t, err, nil) errs := err.(ValidationErrors) Equal(t, len(errs), tc.errorNum) } stct := &struct { f1 int `validate:"uri"` }{} PanicMatches(t, func() { _ = validate.Struct(stct) }, "Bad field type int") } type NotRed struct { Color string } func (r *NotRed) Validate() error { if r != nil && r.Color == "red" { return errors.New("should not be red") } return nil } func (r NotRed) IsNotRed() bool { return r.Color != "red" } func (r NotRed) DoNothing() {} func (r NotRed) String() string { return "not red instance" } func TestValidateFn(t *testing.T) { t.Run("using pointer", func(t *testing.T) { validate := New() type Test struct { String string Inner *NotRed `validate:"validateFn"` } var tt Test errs := validate.Struct(tt) NotEqual(t, errs, nil) fe := errs.(ValidationErrors)[0] Equal(t, fe.Field(), "Inner") Equal(t, fe.Namespace(), "Test.Inner") Equal(t, fe.Tag(), "validateFn") tt.Inner = &NotRed{Color: "blue"} errs = validate.Struct(tt) Equal(t, errs, nil) tt.Inner = &NotRed{Color: "red"} errs = validate.Struct(tt) NotEqual(t, errs, nil) fe = errs.(ValidationErrors)[0] Equal(t, fe.Field(), "Inner") Equal(t, fe.Namespace(), "Test.Inner") Equal(t, fe.Tag(), "validateFn") }) t.Run("using struct", func(t *testing.T) { validate := New() type Test2 struct { String string Inner NotRed `validate:"validateFn"` } var tt2 Test2 errs := validate.Struct(&tt2) Equal(t, errs, nil) tt2.Inner = NotRed{Color: "blue"} errs = validate.Struct(&tt2) Equal(t, errs, nil) tt2.Inner = NotRed{Color: "red"} errs = validate.Struct(&tt2) NotEqual(t, errs, nil) fe := errs.(ValidationErrors)[0] Equal(t, fe.Field(), "Inner") Equal(t, fe.Namespace(), "Test2.Inner") Equal(t, fe.Tag(), "validateFn") }) t.Run("using struct with custom function", func(t *testing.T) { validate := New() type Test2 struct { String string Inner NotRed `validate:"validateFn=IsNotRed"` } var tt2 Test2 errs := validate.Struct(&tt2) Equal(t, errs, nil) tt2.Inner = NotRed{Color: "blue"} errs = validate.Struct(&tt2) Equal(t, errs, nil) tt2.Inner = NotRed{Color: "red"} errs = validate.Struct(&tt2) NotEqual(t, errs, nil) fe := errs.(ValidationErrors)[0] Equal(t, fe.Field(), "Inner") Equal(t, fe.Namespace(), "Test2.Inner") Equal(t, fe.Tag(), "validateFn") }) t.Run("try validate method with wrong signature or not existent", func(t *testing.T) { validate := New() type Test2 struct { String string `validate:"validateFn=NotExists"` // should fail, method not found Inner NotRed `validate:"validateFn=DoNothing"` // should fail, return nothing Inner2 NotRed `validate:"validateFn=String"` // should fail, wrong return (must be error or bool) } var tt2 Test2 err := validate.Struct(&tt2) NotEqual(t, err, nil) errs := err.(ValidationErrors) Equal(t, len(errs), 3) fe := errs[0] Equal(t, fe.Field(), "String") Equal(t, fe.Namespace(), "Test2.String") Equal(t, fe.Tag(), "validateFn") fe = errs[1] Equal(t, fe.Field(), "Inner") Equal(t, fe.Namespace(), "Test2.Inner") Equal(t, fe.Tag(), "validateFn") fe = errs[2] Equal(t, fe.Field(), "Inner2") Equal(t, fe.Namespace(), "Test2.Inner2") Equal(t, fe.Tag(), "validateFn") }) } func TestMapStructBasicValidation(t *testing.T) { // Tests basic validation of a map with struct values type Inner struct { Value string `validate:"max=5"` } type Outer struct { Data map[string]Inner `validate:"dive"` } obj := Outer{ Data: map[string]Inner{ "key1": {Value: "exceeds"}, // Should fail because Value is longer than 5 characters }, } validate := New() errs := validate.Struct(obj) NotEqual(t, errs, nil) } func TestMapStructPointerValidation(t *testing.T) { // Tests validation of a map with pointer to struct values type Inner struct { Count int `validate:"gt=10"` } type Outer struct { Items map[string]*Inner `validate:"dive"` } obj := Outer{ Items: map[string]*Inner{ "a": {Count: 5}, }, } validate := New() errs := validate.Struct(obj) NotEqual(t, errs, nil) } func TestMapStructWithKeyValidationOnly(t *testing.T) { // Tests validation of a map with struct values, focusing on key validation type Inner struct { Name string `validate:"required"` } type Outer struct { Things map[string]Inner `validate:"dive,keys,min=3,endkeys"` } obj := Outer{ Things: map[string]Inner{ "ab": {Name: "valid"}, //Should fail because key is too short }, } validate := New() errs := validate.Struct(obj) NotEqual(t, errs, nil) } func TestMapStructWithKeyAndValueValidation(t *testing.T) { // Tests validation of a map with struct values, validating both keys and values type Inner struct { Name string `validate:"min=3"` } type Outer struct { Stuff map[string]Inner `validate:"dive,keys,min=2,endkeys"` } obj := Outer{ Stuff: map[string]Inner{ "ok": {Name: "xy"}, "bad": {Name: "valid"}, }, } validate := New() errs := validate.Struct(obj) NotEqual(t, errs, nil) } func TestMapPointerStructWithNilValue(t *testing.T) { // Tests validation of a map with pointer to struct values where value is nil type Inner struct { Count int `validate:"min=1"` } type Outer struct { Items map[string]*Inner `validate:"dive"` } obj := Outer{ Items: map[string]*Inner{ "x": nil, }, } validate := New() errs := validate.Struct(obj) Equal(t, errs, nil) } func TestThreeLevelNestedStructs(t *testing.T) { // Tests validation of three levels of nested structs with map keys and values type Level3 struct { Code string `validate:"len=3"` } type Level2 struct { Items map[string]Level3 `validate:"dive,keys,required,endkeys"` } type Level1 struct { Levels map[string]Level2 `validate:"dive,keys,required,endkeys"` } validate := New() // Valid case: all Level3.Code are exactly 3 chars valid := Level1{Levels: map[string]Level2{ "first": {Items: map[string]Level3{ "item1": {Code: "abc"}, "item2": {Code: "xyz"}, }, }, }, } errs := validate.Struct(valid) Equal(t, errs, nil) // Invalid case: one Level3.Code is wrong length invalid := Level1{Levels: map[string]Level2{ "first": {Items: map[string]Level3{ "item1": {Code: "abcd"}, // Should fail here because length is 4 "item2": {Code: "xyz"}, }, }, }, } errs = validate.Struct(invalid) NotEqual(t, errs, nil) } func TestMapStructFallbackWithKeysOnly(t *testing.T) { // Tests fallback behavior when validating map keys and struct values type Inner struct { Value string `validate:"max=3"` } type Outer struct { Data map[string]Inner `validate:"dive,keys,max=2,endkeys"` } validate := New() // Key too long: should fail on key before fallback obj1 := Outer{Data: map[string]Inner{"toolong": {Value: "ok"}}} errs := validate.Struct(obj1) NotEqual(t, errs, nil) // Key OK, value too long: should fallback and fail on Inner.Value obj2 := Outer{Data: map[string]Inner{"ok": {Value: "toolong"}}} errs = validate.Struct(obj2) NotEqual(t, errs, nil) // Both key and value OK: should pass obj3 := Outer{Data: map[string]Inner{"ok": {Value: "abc"}}} errs = validate.Struct(obj3) Equal(t, errs, nil) } func TestMapPointerStructFallback(t *testing.T) { // Tests fallback behavior when validating map keys and pointer to struct values type Inner struct { Count int `validate:"gt=0"` } type Outer struct { Data map[string]*Inner `validate:"dive,keys,max=3,endkeys"` } validate := New() // Key OK, pointer is nil: no fallback error obj1 := Outer{Data: map[string]*Inner{"ok": nil}} errs := validate.Struct(obj1) Equal(t, errs, nil) // Key OK, pointer non-nil but field invalid: fallback should validate Inner.Count obj2 := Outer{Data: map[string]*Inner{"ok": {Count: 0}}} errs = validate.Struct(obj2) NotEqual(t, errs, nil) // Key OK, pointer non-nil and valid: should pass obj3 := Outer{Data: map[string]*Inner{"ok": {Count: 5}}} errs = validate.Struct(obj3) Equal(t, errs, nil) } func TestMapNonStructValueSkipsFallback(t *testing.T) { // Tests that fallback is skipped for non-struct values in maps type Outer struct { Data map[string]int `validate:"dive,keys,min=1,endkeys"` } validate := New() // Key OK, value is primitive: no fallback needed, should pass obj1 := Outer{Data: map[string]int{"a": 0}} errs := validate.Struct(obj1) Equal(t, errs, nil) // Key too short: should fail on key obj2 := Outer{Data: map[string]int{"": 0}} errs = validate.Struct(obj2) NotEqual(t, errs, nil) } func TestMapSliceValueNoFallback(t *testing.T) { // Tests that fallback is skipped for slice values in maps type Outer struct { Data map[string][]string `validate:"dive,keys,max=1,endkeys"` } validate := New() // Key OK, value is slice: skip fallback, should pass obj1 := Outer{Data: map[string][]string{"a": {"x", "y"}}} errs := validate.Struct(obj1) Equal(t, errs, nil) // Key too long: should fail on key obj2 := Outer{Data: map[string][]string{"ab": {"x"}}} errs = validate.Struct(obj2) NotEqual(t, errs, nil) } func TestMapEmptyStructValueNoError(t *testing.T) { // Tests that empty struct values in maps do not trigger validation errors type Inner struct{} // no validation tags type Outer struct { Data map[string]Inner `validate:"dive,keys,max=3,endkeys"` } validate := New() // Key OK, value is empty struct: no fields to validate, should pass obj1 := Outer{Data: map[string]Inner{"ok": {}}} errs := validate.Struct(obj1) Equal(t, errs, nil) // Key too long: should fail on key, skip struct obj2 := Outer{Data: map[string]Inner{"toolong": {}}} errs = validate.Struct(obj2) NotEqual(t, errs, nil) } func TestMapNestedEmptyStructs(t *testing.T) { // Tests that nested empty structs in maps validate correctly type Level3 struct{} type Level2 struct { Items map[string]Level3 `validate:"dive,keys,max=2,endkeys"` } type Level1 struct { Levels map[string]Level2 `validate:"dive,keys,max=2,endkeys"` } validate := New() // All keys within max=2, and inner structs are empty → should pass obj := Level1{Levels: map[string]Level2{ "a": {Items: map[string]Level3{"b": {}}}, }} errs := validate.Struct(obj) Equal(t, errs, nil) // Top-level key too long: should fail on Level1 key, skip deeper obj2 := Level1{Levels: map[string]Level2{ "too": {Items: map[string]Level3{"b": {}}}, // "too" length=3 > max=2 }} errs = validate.Struct(obj2) NotEqual(t, errs, nil) } func TestMapEmptyValueMap(t *testing.T) { // Tests that an empty map with struct values does not trigger validation errors type Inner struct { Value string `validate:"required"` } type Outer struct { Data map[string]Inner `validate:"dive,keys,max=3,endkeys"` } validate := New() // Empty map: nothing to validate, should pass obj := Outer{Data: map[string]Inner{}} errs := validate.Struct(obj) Equal(t, errs, nil) } func TestMapEmptyPointerStructValueNoError(t *testing.T) { // Tests that empty pointer struct values in maps do not trigger validation errors type Inner struct{} type Outer struct { Data map[string]*Inner `validate:"dive,keys,max=3,endkeys"` } validate := New() // Key OK, pointer is non-nil empty struct: should pass obj1 := Outer{Data: map[string]*Inner{"ok": {}}} errs := validate.Struct(obj1) Equal(t, errs, nil) // Key OK, pointer is nil: no tags on Inner, so should pass obj2 := Outer{Data: map[string]*Inner{"ok": nil}} errs = validate.Struct(obj2) Equal(t, errs, nil) } func TestOmitZeroWithSlices(t *testing.T) { // Tests the behavior of omitempty and omitzero with slices type OmitEmptyExample struct { Data []string `validate:"omitempty,min=2"` } type OmitZeroExample struct { Data []string `validate:"omitzero,min=2"` } validate := New() t.Run("nil slices", func(t *testing.T) { // Test 1: nil slices test1Empty := OmitEmptyExample{Data: nil} test1Zero := OmitZeroExample{Data: nil} err1 := validate.Struct(test1Empty) err2 := validate.Struct(test1Zero) Equal(t, err1, nil) // No error (skipped) Equal(t, err2, nil) // No error (skipped) }) t.Run("empty but non-nil slices", func(t *testing.T) { // Test 2: empty but non-nil slices test2Empty := OmitEmptyExample{Data: []string{}} test2Zero := OmitZeroExample{Data: []string{}} err1 := validate.Struct(test2Empty) err2 := validate.Struct(test2Zero) NotEqual(t, err1, nil) // Error (min=2) Equal(t, err2, nil) // No error (should be skipped) }) t.Run("single item slices", func(t *testing.T) { // Test 3: single item slices (still not meeting min=2) test3Empty := OmitEmptyExample{Data: []string{"one"}} test3Zero := OmitZeroExample{Data: []string{"one"}} err1 := validate.Struct(test3Empty) err2 := validate.Struct(test3Zero) NotEqual(t, err1, nil) // Error (min=2) NotEqual(t, err2, nil) // Error (min=2) }) t.Run("valid slices", func(t *testing.T) { // Test 4: valid slices (min=2 satisfied) test4Empty := OmitEmptyExample{Data: []string{"one", "two"}} test4Zero := OmitZeroExample{Data: []string{"one", "two"}} err1 := validate.Struct(test4Empty) err2 := validate.Struct(test4Zero) Equal(t, err1, nil) // No error Equal(t, err2, nil) // No error }) } func TestOmitZeroWithMaps(t *testing.T) { // Tests the behavior of omitempty and omitzero with maps type OmitEmptyExample struct { Data map[string]string `validate:"omitempty,min=2"` } type OmitZeroExample struct { Data map[string]string `validate:"omitzero,min=2"` } validate := New() t.Run("nil maps", func(t *testing.T) { // Test 1: nil maps test1Empty := OmitEmptyExample{Data: nil} test1Zero := OmitZeroExample{Data: nil} err1 := validate.Struct(test1Empty) err2 := validate.Struct(test1Zero) Equal(t, err1, nil) // No error (skipped) Equal(t, err2, nil) // No error (skipped) }) t.Run("empty but non-nil maps", func(t *testing.T) { // Test 2: empty but non-nil maps test2Empty := OmitEmptyExample{Data: map[string]string{}} test2Zero := OmitZeroExample{Data: map[string]string{}} err1 := validate.Struct(test2Empty) err2 := validate.Struct(test2Zero) NotEqual(t, err1, nil) // Error (min=2) Equal(t, err2, nil) // No error (should be skipped) }) t.Run("single item maps", func(t *testing.T) { // Test 3: single item maps (still not meeting min=2) test3Empty := OmitEmptyExample{Data: map[string]string{"key1": "value1"}} test3Zero := OmitZeroExample{Data: map[string]string{"key1": "value1"}} err1 := validate.Struct(test3Empty) err2 := validate.Struct(test3Zero) NotEqual(t, err1, nil) // Error (min=2) NotEqual(t, err2, nil) // Error (min=2) }) t.Run("valid maps", func(t *testing.T) { // Test 4: valid maps (min=2 satisfied) test4Empty := OmitEmptyExample{Data: map[string]string{"key1": "value1", "key2": "value2"}} test4Zero := OmitZeroExample{Data: map[string]string{"key1": "value1", "key2": "value2"}} err1 := validate.Struct(test4Empty) err2 := validate.Struct(test4Zero) Equal(t, err1, nil) // No error Equal(t, err2, nil) // No error }) } func TestRequiredIfWithNilBytesSlice(t *testing.T) { // Tests the behavior of required_if with nil byte slices type TextOrBytes struct { Text string `validate:"required_if=Bytes nil"` Bytes []byte `validate:"required_if=Text nil"` } validate := New(WithRequiredStructEnabled()) t.Run("Text empty, Bytes empty but not nil", func(t *testing.T) { // Test 1: Text empty, Bytes empty but not nil obj := TextOrBytes{ Text: "", Bytes: []byte{}, } err := validate.Struct(obj) Equal(t, err, nil) // No error - Bytes is not nil, just empty }) t.Run("Text empty, Bytes nil", func(t *testing.T) { // Test 2: Text empty, Bytes nil obj := TextOrBytes{ Text: "", Bytes: nil, } err := validate.Struct(obj) NotEqual(t, err, nil) // Error - Text is required when Bytes is nil }) t.Run("Text populated, Bytes nil", func(t *testing.T) { // Test 3: Text populated, Bytes nil obj := TextOrBytes{ Text: "Hello", Bytes: nil, } err := validate.Struct(obj) Equal(t, err, nil) // No error - Text has value when Bytes is nil }) t.Run("Text populated, Bytes empty but not nil", func(t *testing.T) { // Test 4: Text populated, Bytes empty but not nil obj := TextOrBytes{ Text: "Hello", Bytes: []byte{}, } err := validate.Struct(obj) Equal(t, err, nil) // No error - Neither field is nil }) t.Run("Text empty, Bytes populated", func(t *testing.T) { // Test 5: Text empty, Bytes populated obj := TextOrBytes{ Text: "", Bytes: []byte("World"), } err := validate.Struct(obj) Equal(t, err, nil) // No error - Bytes has value when Text is empty }) t.Run("Both fields populated", func(t *testing.T) { // Test 6: Both fields populated obj := TextOrBytes{ Text: "Hello", Bytes: []byte("World"), } err := validate.Struct(obj) Equal(t, err, nil) // No error - Both fields have values }) } func TestRequiredIfWithMaps(t *testing.T) { // Tests the behavior of required_if with maps type TextOrMap struct { Text string `validate:"required_if=Data nil"` Data map[string]interface{} `validate:"required_if=Text nil"` } validate := New(WithRequiredStructEnabled()) t.Run("Text empty, Map nil", func(t *testing.T) { // Test 1: Text empty, Map nil obj := TextOrMap{ Text: "", Data: nil, } err := validate.Struct(obj) NotEqual(t, err, nil) // Error - Text is required when Data is nil }) t.Run("Text populated, Map nil", func(t *testing.T) { // Test 2: Text populated, Map nil obj := TextOrMap{ Text: "Hello", Data: nil, } err := validate.Struct(obj) Equal(t, err, nil) // No error - Text has value when Data is nil }) t.Run("Text empty, Map empty but not nil", func(t *testing.T) { // Test 3: Text empty, Map empty but not nil obj := TextOrMap{ Text: "", Data: map[string]interface{}{}, } err := validate.Struct(obj) Equal(t, err, nil) // No error - Data is not nil, just empty }) t.Run("Text populated, Map empty but not nil", func(t *testing.T) { // Test 4: Text populated, Map empty but not nil obj := TextOrMap{ Text: "Hello", Data: map[string]interface{}{}, } err := validate.Struct(obj) Equal(t, err, nil) // No error - Neither field is nil }) t.Run("Text empty, Map populated", func(t *testing.T) { // Test 5: Text empty, Map populated obj := TextOrMap{ Text: "", Data: map[string]interface{}{"key": "value"}, } err := validate.Struct(obj) Equal(t, err, nil) // No error - Data has value when Text is empty }) t.Run("Both fields populated", func(t *testing.T) { // Test 6: Both fields populated obj := TextOrMap{ Text: "Hello", Data: map[string]interface{}{"key": "value"}, } err := validate.Struct(obj) Equal(t, err, nil) // No error - Both fields have values }) } func TestRequiredIfWithArrays(t *testing.T) { // Tests the behavior of required_if with arrays type TextOrArray struct { Text string `validate:"required_if=Data 3"` // Check if array length is 3 Data [3]string `validate:"required_if=Text nil"` // Check if Text is empty } // Also test with a different length to verify behavior type TextOrSmallArray struct { Text string `validate:"required_if=Data 2"` // Check if array length is 2 (which it never will be for [3]string) Data [3]string `validate:"required_if=Text nil"` // Check if Text is empty } validate := New(WithRequiredStructEnabled()) t.Run("Array length always matches declared size", func(t *testing.T) { // Test 1: Text empty, Array has length 3 obj := TextOrArray{ Text: "", Data: [3]string{}, // Zero values but length is 3 } err := validate.Struct(obj) NotEqual(t, err, nil) // Error - Text is required when Data length equals 3 }) t.Run("Text populated, Array always has declared length", func(t *testing.T) { // Test 2: Text populated, Array has length 3 obj := TextOrArray{ Text: "Hello", Data: [3]string{}, } err := validate.Struct(obj) Equal(t, err, nil) // No error - Text has value }) t.Run("Length check that never matches doesn't trigger validation", func(t *testing.T) { // Test 3: Text empty, Array has length 3 but we check for length 2 obj := TextOrSmallArray{ Text: "", Data: [3]string{}, } err := validate.Struct(obj) Equal(t, err, nil) // No error - Data length never equals 2 }) t.Run("Array values don't affect length check", func(t *testing.T) { // Test 4: Text empty, Array partially populated but still length 3 obj := TextOrArray{ Text: "", Data: [3]string{"One", "Two", ""}, } err := validate.Struct(obj) NotEqual(t, err, nil) // Error - Text is required when Data length equals 3 }) t.Run("Array values with Text populated passes validation", func(t *testing.T) { // Test 5: Text populated, Array with values obj := TextOrArray{ Text: "Hello", Data: [3]string{"One", "Two", "Three"}, } err := validate.Struct(obj) Equal(t, err, nil) // No error - Text has value }) }