Repository: go-playground/validator
Pull request #1336 (2024-11-27 14:35:00)

Docs: fix `Base64RawURL` usage
## Fixes Or Enhances
The usage of Base64RawURL was incorrect.

**Make sure that you've checked the boxes below before you submit PR:**
- [x] Tests exist or have been written that cover this particular change.

@go-playground/validator-maintainers

coveralls: 
[![Coverage Status](https://coveralls.io/builds/71084299/badge)](https://coveralls.io/builds/71084299)

coverage: 74.318%. remained the same
when pulling **5e1cc3da964a7c95102b523caf48df7af85ff8ab on 196Ikuchil:fix/doc_typo**
into **6c3307e6c64040ebc0efffe9366927c68146ffba on go-playground:master**.


Patch:
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
deleted file mode 100644
index 40b774a..0000000
--- a/.github/ISSUE_TEMPLATE.md
+++ /dev/null
@@ -1,16 +0,0 @@
-- [ ] I have looked at the documentation [here](https://pkg.go.dev/github.com/go-playground/validator/v10#section-documentation) first?
-- [ ] I have looked at the examples provided that may showcase my question [here](/_examples)?
-
-### Package version eg. v9, v10: 
-
-
-
-### Issue, Question or Enhancement:
-
-
-
-### Code sample, to showcase or reproduce:
-
-```go
-
-```
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
new file mode 100644
index 0000000..38dce27
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -0,0 +1,31 @@
+name: 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 
\ No newline at end of file
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..ce811d1
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,12 @@
+version: 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
diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml
index 75cdc25..9235bbe 100644
--- a/.github/workflows/workflow.yml
+++ b/.github/workflows/workflow.yml
@@ -8,7 +8,7 @@ jobs:
   test:
     strategy:
       matrix:
-        go-version: [1.17.x,1.18.x,1.21.x,1.22.x]
+        go-version: [1.20.x,1.21.x,1.22.x,1.23.x]
         os: [ubuntu-latest, macos-latest, windows-latest]
     runs-on: ${{ matrix.os }}
     steps:
@@ -36,8 +36,8 @@ jobs:
       - uses: actions/checkout@v4
       - uses: actions/setup-go@v5
         with:
-          go-version: 1.22.x
+          go-version: 1.23.x
       - name: golangci-lint
-        uses: golangci/golangci-lint-action@v4
+        uses: golangci/golangci-lint-action@v6
         with:
           version: latest
diff --git a/README.md b/README.md
index e3f4e10..405941d 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,7 @@
 Package validator
 =================
-<img align="right" src="logo.png">[![Join the chat at https://gitter.im/go-playground/validator](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/go-playground/validator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
-![Project status](https://img.shields.io/badge/version-10.23.0-green.svg)
-[![Build Status](https://travis-ci.org/go-playground/validator.svg?branch=master)](https://travis-ci.org/go-playground/validator)
+<img align="right" src="logo.png">![Project status](https://img.shields.io/badge/version-10.25.0-green.svg)
+[![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)
@@ -271,74 +270,75 @@ validate := validator.New(validator.WithRequiredStructEnabled())
 
 Benchmarks
 ------
-###### Run on MacBook Pro (15-inch, 2017) go version go1.10.2 darwin/amd64
+###### Run on MacBook Pro Max M3
 ```go
-go version go1.21.0 darwin/arm64
+go version go1.23.3 darwin/arm64
 goos: darwin
 goarch: arm64
+cpu: Apple M3 Max
 pkg: github.com/go-playground/validator/v10
-BenchmarkFieldSuccess-8                                         33142266                35.94 ns/op            0 B/op          0 allocs/op
-BenchmarkFieldSuccessParallel-8                                 200816191                6.568 ns/op           0 B/op          0 allocs/op
-BenchmarkFieldFailure-8                                          6779707               175.1 ns/op           200 B/op          4 allocs/op
-BenchmarkFieldFailureParallel-8                                 11044147               108.4 ns/op           200 B/op          4 allocs/op
-BenchmarkFieldArrayDiveSuccess-8                                 6054232               194.4 ns/op            97 B/op          5 allocs/op
-BenchmarkFieldArrayDiveSuccessParallel-8                        12523388                94.07 ns/op           97 B/op          5 allocs/op
-BenchmarkFieldArrayDiveFailure-8                                 3587043               334.3 ns/op           300 B/op         10 allocs/op
-BenchmarkFieldArrayDiveFailureParallel-8                         5816665               200.8 ns/op           300 B/op         10 allocs/op
-BenchmarkFieldMapDiveSuccess-8                                   2217910               540.1 ns/op           288 B/op         14 allocs/op
-BenchmarkFieldMapDiveSuccessParallel-8                           4446698               258.7 ns/op           288 B/op         14 allocs/op
-BenchmarkFieldMapDiveFailure-8                                   2392759               504.6 ns/op           376 B/op         13 allocs/op
-BenchmarkFieldMapDiveFailureParallel-8                           4244199               286.9 ns/op           376 B/op         13 allocs/op
-BenchmarkFieldMapDiveWithKeysSuccess-8                           2005857               592.1 ns/op           288 B/op         14 allocs/op
-BenchmarkFieldMapDiveWithKeysSuccessParallel-8                   4400850               296.9 ns/op           288 B/op         14 allocs/op
-BenchmarkFieldMapDiveWithKeysFailure-8                           1850227               643.8 ns/op           553 B/op         16 allocs/op
-BenchmarkFieldMapDiveWithKeysFailureParallel-8                   3293233               375.1 ns/op           553 B/op         16 allocs/op
-BenchmarkFieldCustomTypeSuccess-8                               12174412                98.25 ns/op           32 B/op          2 allocs/op
-BenchmarkFieldCustomTypeSuccessParallel-8                       34389907                35.49 ns/op           32 B/op          2 allocs/op
-BenchmarkFieldCustomTypeFailure-8                                7582524               156.6 ns/op           184 B/op          3 allocs/op
-BenchmarkFieldCustomTypeFailureParallel-8                       13019902                92.79 ns/op          184 B/op          3 allocs/op
-BenchmarkFieldOrTagSuccess-8                                     3427260               349.4 ns/op            16 B/op          1 allocs/op
-BenchmarkFieldOrTagSuccessParallel-8                            15144128                81.25 ns/op           16 B/op          1 allocs/op
-BenchmarkFieldOrTagFailure-8                                     5913546               201.9 ns/op           216 B/op          5 allocs/op
-BenchmarkFieldOrTagFailureParallel-8                             9810212               113.7 ns/op           216 B/op          5 allocs/op
-BenchmarkStructLevelValidationSuccess-8                         13456327                87.66 ns/op           16 B/op          1 allocs/op
-BenchmarkStructLevelValidationSuccessParallel-8                 41818888                27.77 ns/op           16 B/op          1 allocs/op
-BenchmarkStructLevelValidationFailure-8                          4166284               272.6 ns/op           264 B/op          7 allocs/op
-BenchmarkStructLevelValidationFailureParallel-8                  7594581               152.1 ns/op           264 B/op          7 allocs/op
-BenchmarkStructSimpleCustomTypeSuccess-8                         6508082               182.6 ns/op            32 B/op          2 allocs/op
-BenchmarkStructSimpleCustomTypeSuccessParallel-8                23078605                54.78 ns/op           32 B/op          2 allocs/op
-BenchmarkStructSimpleCustomTypeFailure-8                         3118352               381.0 ns/op           416 B/op          9 allocs/op
-BenchmarkStructSimpleCustomTypeFailureParallel-8                 5300738               224.1 ns/op           432 B/op         10 allocs/op
-BenchmarkStructFilteredSuccess-8                                 4761807               251.1 ns/op           216 B/op          5 allocs/op
-BenchmarkStructFilteredSuccessParallel-8                         8792598               128.6 ns/op           216 B/op          5 allocs/op
-BenchmarkStructFilteredFailure-8                                 5202573               232.1 ns/op           216 B/op          5 allocs/op
-BenchmarkStructFilteredFailureParallel-8                         9591267               121.4 ns/op           216 B/op          5 allocs/op
-BenchmarkStructPartialSuccess-8                                  5188512               231.6 ns/op           224 B/op          4 allocs/op
-BenchmarkStructPartialSuccessParallel-8                          9179776               123.1 ns/op           224 B/op          4 allocs/op
-BenchmarkStructPartialFailure-8                                  3071212               392.5 ns/op           440 B/op          9 allocs/op
-BenchmarkStructPartialFailureParallel-8                          5344261               223.7 ns/op           440 B/op          9 allocs/op
-BenchmarkStructExceptSuccess-8                                   3184230               375.0 ns/op           424 B/op          8 allocs/op
-BenchmarkStructExceptSuccessParallel-8                          10090130               108.9 ns/op           208 B/op          3 allocs/op
-BenchmarkStructExceptFailure-8                                   3347226               357.7 ns/op           424 B/op          8 allocs/op
-BenchmarkStructExceptFailureParallel-8                           5654923               209.5 ns/op           424 B/op          8 allocs/op
-BenchmarkStructSimpleCrossFieldSuccess-8                         5232265               229.1 ns/op            56 B/op          3 allocs/op
-BenchmarkStructSimpleCrossFieldSuccessParallel-8                17436674                64.75 ns/op           56 B/op          3 allocs/op
-BenchmarkStructSimpleCrossFieldFailure-8                         3128613               383.6 ns/op           272 B/op          8 allocs/op
-BenchmarkStructSimpleCrossFieldFailureParallel-8                 6994113               168.8 ns/op           272 B/op          8 allocs/op
-BenchmarkStructSimpleCrossStructCrossFieldSuccess-8              3506487               340.9 ns/op            64 B/op          4 allocs/op
-BenchmarkStructSimpleCrossStructCrossFieldSuccessParallel-8     13431300                91.77 ns/op           64 B/op          4 allocs/op
-BenchmarkStructSimpleCrossStructCrossFieldFailure-8              2410566               500.9 ns/op           288 B/op          9 allocs/op
-BenchmarkStructSimpleCrossStructCrossFieldFailureParallel-8      6344510               188.2 ns/op           288 B/op          9 allocs/op
-BenchmarkStructSimpleSuccess-8                                   8922726               133.8 ns/op             0 B/op          0 allocs/op
-BenchmarkStructSimpleSuccessParallel-8                          55291153                23.63 ns/op            0 B/op          0 allocs/op
-BenchmarkStructSimpleFailure-8                                   3171553               378.4 ns/op           416 B/op          9 allocs/op
-BenchmarkStructSimpleFailureParallel-8                           5571692               212.0 ns/op           416 B/op          9 allocs/op
-BenchmarkStructComplexSuccess-8                                  1683750               714.5 ns/op           224 B/op          5 allocs/op
-BenchmarkStructComplexSuccessParallel-8                          4578046               257.0 ns/op           224 B/op          5 allocs/op
-BenchmarkStructComplexFailure-8                                   481585              2547 ns/op            3041 B/op         48 allocs/op
-BenchmarkStructComplexFailureParallel-8                           965764              1577 ns/op            3040 B/op         48 allocs/op
-BenchmarkOneof-8                                                17380881                68.50 ns/op            0 B/op          0 allocs/op
-BenchmarkOneofParallel-8                                         8084733               153.5 ns/op             0 B/op          0 allocs/op
+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
@@ -354,6 +354,20 @@ 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.
diff --git a/_examples/simple/main.go b/_examples/simple/main.go
index 6581412..606822b 100644
--- a/_examples/simple/main.go
+++ b/_examples/simple/main.go
@@ -1,6 +1,7 @@
 package main
 
 import (
+	"errors"
 	"fmt"
 
 	"github.com/go-playground/validator/v10"
@@ -61,24 +62,27 @@ func validateStruct() {
 		// this check is only needed when your code could produce
 		// an invalid value for validation such as interface with nil
 		// value most including myself do not usually have code like this.
-		if _, ok := err.(*validator.InvalidValidationError); ok {
+		var invalidValidationError *validator.InvalidValidationError
+		if errors.As(err, &invalidValidationError) {
 			fmt.Println(err)
 			return
 		}
 
-		for _, err := range err.(validator.ValidationErrors) {
-
-			fmt.Println(err.Namespace())
-			fmt.Println(err.Field())
-			fmt.Println(err.StructNamespace())
-			fmt.Println(err.StructField())
-			fmt.Println(err.Tag())
-			fmt.Println(err.ActualTag())
-			fmt.Println(err.Kind())
-			fmt.Println(err.Type())
-			fmt.Println(err.Value())
-			fmt.Println(err.Param())
-			fmt.Println()
+		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
diff --git a/_examples/struct-level/main.go b/_examples/struct-level/main.go
index a16cf4e..faba03f 100644
--- a/_examples/struct-level/main.go
+++ b/_examples/struct-level/main.go
@@ -2,6 +2,7 @@ package main
 
 import (
 	"encoding/json"
+	"errors"
 	"fmt"
 	"reflect"
 	"strings"
@@ -114,33 +115,37 @@ func main() {
 		// this check is only needed when your code could produce
 		// an invalid value for validation such as interface with nil
 		// value most including myself do not usually have code like this.
-		if _, ok := err.(*validator.InvalidValidationError); ok {
+		var invalidValidationError *validator.InvalidValidationError
+		if errors.As(err, &invalidValidationError) {
 			fmt.Println(err)
 			return
 		}
 
-		for _, err := range err.(validator.ValidationErrors) {
-			e := validationError{
-				Namespace:       err.Namespace(),
-				Field:           err.Field(),
-				StructNamespace: err.StructNamespace(),
-				StructField:     err.StructField(),
-				Tag:             err.Tag(),
-				ActualTag:       err.ActualTag(),
-				Kind:            fmt.Sprintf("%v", err.Kind()),
-				Type:            fmt.Sprintf("%v", err.Type()),
-				Value:           fmt.Sprintf("%v", err.Value()),
-				Param:           err.Param(),
-				Message:         err.Error(),
+		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))
 			}
-
-			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
diff --git a/baked_in.go b/baked_in.go
index 2f66c18..cca3e09 100644
--- a/baked_in.go
+++ b/baked_in.go
@@ -50,6 +50,7 @@ var (
 		keysTag:           {},
 		endKeysTag:        {},
 		structOnlyTag:     {},
+		omitzero:          {},
 		omitempty:         {},
 		omitnil:           {},
 		skipValidationTag: {},
@@ -1417,6 +1418,7 @@ func isPostcodeByIso3166Alpha2Field(fl FieldLevel) bool {
 		panic(fmt.Sprintf("Bad field type %T", currentField.Interface()))
 	}
 
+	postcodeRegexInit.Do(initPostcodes)
 	reg, found := postCodeRegexDict[currentField.String()]
 	if !found {
 		return false
@@ -1796,6 +1798,20 @@ func hasValue(fl FieldLevel) bool {
 	}
 }
 
+// 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, reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func:
+		return !field.IsNil()
+	default:
+		if fl.(*validate).fldIsPointer && field.Interface() != 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()
diff --git a/cache.go b/cache.go
index 2063e1b..cbf5ff0 100644
--- a/cache.go
+++ b/cache.go
@@ -21,6 +21,7 @@ const (
 	typeKeys
 	typeEndKeys
 	typeOmitNil
+	typeOmitZero
 )
 
 const (
@@ -249,6 +250,10 @@ func (v *Validate) parseFieldTagsRecursive(tag string, fieldName string, alias s
 			}
 			return
 
+		case omitzero:
+			current.typeof = typeOmitZero
+			continue
+
 		case omitempty:
 			current.typeof = typeOmitEmpty
 			continue
diff --git a/doc.go b/doc.go
index c9b1616..c3a40ef 100644
--- a/doc.go
+++ b/doc.go
@@ -959,7 +959,7 @@ 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
+	Usage: base64rawurl
 
 # Bitcoin Address
 
diff --git a/go.mod b/go.mod
index c77643f..4ffea09 100644
--- a/go.mod
+++ b/go.mod
@@ -1,18 +1,18 @@
 module github.com/go-playground/validator/v10
 
-go 1.18
+go 1.20
 
 require (
-	github.com/gabriel-vasile/mimetype v1.4.3
+	github.com/gabriel-vasile/mimetype v1.4.8
 	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.19.0
-	golang.org/x/text v0.14.0
+	golang.org/x/crypto v0.33.0
+	golang.org/x/text v0.22.0
 )
 
 require (
-	golang.org/x/net v0.21.0 // indirect
-	golang.org/x/sys v0.17.0 // indirect
+	golang.org/x/net v0.34.0 // indirect
+	golang.org/x/sys v0.30.0 // indirect
 )
diff --git a/go.sum b/go.sum
index 3bf8a6e..d0d2a98 100644
--- a/go.sum
+++ b/go.sum
@@ -1,6 +1,6 @@
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
-github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
-github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
+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/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
 github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
@@ -11,12 +11,12 @@ 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.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
-golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
-golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
-golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
-golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
-golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
-golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+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/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
+golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
+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/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
+golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
diff --git a/translations/en/en.go b/translations/en/en.go
index 9cef10e..aa9df7e 100644
--- a/translations/en/en.go
+++ b/translations/en/en.go
@@ -217,17 +217,18 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			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
 
-				if idx := strings.Index(fe.Param(), "."); idx != -1 {
-					digits = uint64(len(fe.Param()[idx+1:]))
-				}
+				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)
-				if err != nil {
-					goto END
+					f64, err = strconv.ParseFloat(fe.Param(), 64)
+
+					return
 				}
 
 				kind = fe.Kind()
@@ -240,6 +241,11 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 
 					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
@@ -250,6 +256,11 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 				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
@@ -258,6 +269,16 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 					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))
 				}
 
@@ -305,17 +326,18 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			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
 
-				if idx := strings.Index(fe.Param(), "."); idx != -1 {
-					digits = uint64(len(fe.Param()[idx+1:]))
-				}
+				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)
-				if err != nil {
-					goto END
+					f64, err = strconv.ParseFloat(fe.Param(), 64)
+
+					return
 				}
 
 				kind = fe.Kind()
@@ -328,6 +350,11 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 
 					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
@@ -338,6 +365,11 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 				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
@@ -346,6 +378,16 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 					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))
 				}
 
diff --git a/translations/id/id.go b/translations/id/id.go
index 96cd8fc..eda1c66 100644
--- a/translations/id/id.go
+++ b/translations/id/id.go
@@ -16,7 +16,6 @@ import (
 // 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
@@ -24,355 +23,715 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 		customRegisFunc validator.RegisterTranslationsFunc
 		customTransFunc validator.TranslationFunc
 	}{
+		// Field Tags
 		{
-			tag:         "required",
-			translation: "{0} wajib diisi",
-			override:    false,
+			tag:             "eqcsfield",
+			translation:     "{0} harus sama dengan {1}",
+			override:        false,
+			customTransFunc: translateFuncWithParam,
 		},
 		{
-			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.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} 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.PluralRuleOne, 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:             "eqfield",
+			translation:     "{0} harus sama dengan {1}",
+			override:        false,
+			customTransFunc: translateFuncWithParam,
 		},
 		{
-			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.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} harus {1} atau lebih besar", false); err != nil {
-					return
-				}
-
-				if err = ut.Add("min-items", "panjang minimal {0} adalah {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} item", locales.PluralRuleOther, false); err != nil {
-					return
-				}
-
-				return
+			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,
+		},
 
-			},
-			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
+		{
+			tag:             "nefield",
+			translation:     "{0} tidak sama dengan {1}",
+			override:        false,
+			customTransFunc: translateFuncWithParam,
+		},
 
-				var err error
-				var t string
+		// 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,
+		},
 
-				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()
-				}
+		// 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,
+		},
 
-				return t
-			},
+		// 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: "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.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} 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.PluralRuleOne, 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:         "uuid5_rfc4122",
+			translation: "{0} harus berupa UUID versi 5 RFC4122 yang valid",
+			override:    false,
 		},
 		{
-			tag:         "eq",
-			translation: "{0} tidak sama dengan {1}",
+			tag:         "uuid_rfc4122",
+			translation: "{0} harus berupa UUID RFC4122 yang valid",
 			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} tidak sama dengan {1}",
+			tag:         "md4",
+			translation: "{0} harus berupa hash MD4 yang valid",
 			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()
-				}
+		},
+		{
+			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,
+		},
 
-				return t
-			},
+		// Comparisons Tags
+		{
+			tag:             "eq",
+			translation:     "{0} tidak sama dengan {1}",
+			override:        false,
+			customTransFunc: translateFuncWithParam,
 		},
 		{
-			tag: "lt",
+			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("lt-string", "panjang {0} harus kurang dari {1}", false); err != nil {
+				if err = ut.Add("gt-string", "panjang {0} harus lebih dari {1}", 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 {
+				if err = ut.AddCardinal("gt-string-character", "{0} karakter", locales.PluralRuleOther, false); err != nil {
 					return
 				}
 
-				if err = ut.Add("lt-number", "{0} harus kurang dari {1}", false); err != nil {
+				if err = ut.Add("gt-number", "{0} harus lebih besar dari {1}", false); err != nil {
 					return
 				}
 
-				if err = ut.Add("lt-items", "{0} harus berisi kurang dari {1}", false); err != nil {
+				if err = ut.Add("gt-items", "{0} harus berisi lebih dari {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} item", locales.PluralRuleOther, false); err != nil {
+				if err = ut.AddCardinal("gt-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 {
+				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
@@ -405,12 +764,12 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 						goto END
 					}
 
-					c, err = ut.C("lt-string-character", f64, digits, ut.FmtNumber(f64, digits))
+					c, err = ut.C("gt-string-character", f64, digits, ut.FmtNumber(f64, digits))
 					if err != nil {
 						goto END
 					}
 
-					t, err = ut.T("lt-string", fe.Field(), c)
+					t, err = ut.T("gt-string", fe.Field(), c)
 
 				case reflect.Slice, reflect.Map, reflect.Array:
 					var c string
@@ -420,12 +779,12 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 						goto END
 					}
 
-					c, err = ut.C("lt-items-item", f64, digits, ut.FmtNumber(f64, digits))
+					c, err = ut.C("gt-items-item", f64, digits, ut.FmtNumber(f64, digits))
 					if err != nil {
 						goto END
 					}
 
-					t, err = ut.T("lt-items", fe.Field(), c)
+					t, err = ut.T("gt-items", fe.Field(), c)
 
 				case reflect.Struct:
 					if fe.Type() != reflect.TypeOf(time.Time{}) {
@@ -433,7 +792,7 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 						goto END
 					}
 
-					t, err = ut.T("lt-datetime", fe.Field())
+					t, err = ut.T("gt-datetime", fe.Field())
 
 				default:
 					err = fn()
@@ -441,7 +800,7 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 						goto END
 					}
 
-					t, err = ut.T("lt-number", fe.Field(), ut.FmtNumber(f64, digits))
+					t, err = ut.T("gt-number", fe.Field(), ut.FmtNumber(f64, digits))
 				}
 
 			END:
@@ -454,45 +813,35 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			},
 		},
 		{
-			tag: "lte",
+			tag: "gte",
 			customRegisFunc: func(ut ut.Translator) (err error) {
-
-				if err = ut.Add("lte-string", "panjang maksimal {0} adalah {1}", false); err != nil {
+				if err = ut.Add("gte-string", "panjang minimal {0} adalah {1}", 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 {
+				if err = ut.AddCardinal("gte-string-character", "{0} karakter", locales.PluralRuleOther, false); err != nil {
 					return
 				}
 
-				if err = ut.Add("lte-number", "{0} harus {1} atau kurang", false); err != nil {
+				if err = ut.Add("gte-number", "{0} harus {1} atau lebih besar", false); err != nil {
 					return
 				}
 
-				if err = ut.Add("lte-items", "{0} harus berisi maksimal {1}", false); err != nil {
+				if err = ut.Add("gte-items", "{0} harus berisi setidaknya {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} item", locales.PluralRuleOther, false); err != nil {
+				if err = ut.AddCardinal("gte-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 {
+				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
@@ -525,12 +874,12 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 						goto END
 					}
 
-					c, err = ut.C("lte-string-character", f64, digits, ut.FmtNumber(f64, digits))
+					c, err = ut.C("gte-string-character", f64, digits, ut.FmtNumber(f64, digits))
 					if err != nil {
 						goto END
 					}
 
-					t, err = ut.T("lte-string", fe.Field(), c)
+					t, err = ut.T("gte-string", fe.Field(), c)
 
 				case reflect.Slice, reflect.Map, reflect.Array:
 					var c string
@@ -540,12 +889,12 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 						goto END
 					}
 
-					c, err = ut.C("lte-items-item", f64, digits, ut.FmtNumber(f64, digits))
+					c, err = ut.C("gte-items-item", f64, digits, ut.FmtNumber(f64, digits))
 					if err != nil {
 						goto END
 					}
 
-					t, err = ut.T("lte-items", fe.Field(), c)
+					t, err = ut.T("gte-items", fe.Field(), c)
 
 				case reflect.Struct:
 					if fe.Type() != reflect.TypeOf(time.Time{}) {
@@ -553,7 +902,7 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 						goto END
 					}
 
-					t, err = ut.T("lte-datetime", fe.Field())
+					t, err = ut.T("gte-datetime", fe.Field())
 
 				default:
 					err = fn()
@@ -561,7 +910,7 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 						goto END
 					}
 
-					t, err = ut.T("lte-number", fe.Field(), ut.FmtNumber(f64, digits))
+					t, err = ut.T("gte-number", fe.Field(), ut.FmtNumber(f64, digits))
 				}
 
 			END:
@@ -574,45 +923,35 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			},
 		},
 		{
-			tag: "gt",
+			tag: "lt",
 			customRegisFunc: func(ut ut.Translator) (err error) {
-
-				if err = ut.Add("gt-string", "panjang {0} harus lebih dari {1}", false); err != nil {
+				if err = ut.Add("lt-string", "panjang {0} harus kurang dari {1}", 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 {
+				if err = ut.AddCardinal("lt-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 {
+				if err = ut.Add("lt-number", "{0} harus kurang dari {1}", false); err != nil {
 					return
 				}
 
-				if err = ut.Add("gt-items", "{0} harus berisi lebih dari {1}", false); err != nil {
+				if err = ut.Add("lt-items", "{0} harus berisi kurang dari {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} item", locales.PluralRuleOther, false); err != nil {
+				if err = ut.AddCardinal("lt-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 {
+				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
@@ -645,12 +984,12 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 						goto END
 					}
 
-					c, err = ut.C("gt-string-character", f64, digits, ut.FmtNumber(f64, digits))
+					c, err = ut.C("lt-string-character", f64, digits, ut.FmtNumber(f64, digits))
 					if err != nil {
 						goto END
 					}
 
-					t, err = ut.T("gt-string", fe.Field(), c)
+					t, err = ut.T("lt-string", fe.Field(), c)
 
 				case reflect.Slice, reflect.Map, reflect.Array:
 					var c string
@@ -660,12 +999,12 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 						goto END
 					}
 
-					c, err = ut.C("gt-items-item", f64, digits, ut.FmtNumber(f64, digits))
+					c, err = ut.C("lt-items-item", f64, digits, ut.FmtNumber(f64, digits))
 					if err != nil {
 						goto END
 					}
 
-					t, err = ut.T("gt-items", fe.Field(), c)
+					t, err = ut.T("lt-items", fe.Field(), c)
 
 				case reflect.Struct:
 					if fe.Type() != reflect.TypeOf(time.Time{}) {
@@ -673,7 +1012,7 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 						goto END
 					}
 
-					t, err = ut.T("gt-datetime", fe.Field())
+					t, err = ut.T("lt-datetime", fe.Field())
 
 				default:
 					err = fn()
@@ -681,7 +1020,7 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 						goto END
 					}
 
-					t, err = ut.T("gt-number", fe.Field(), ut.FmtNumber(f64, digits))
+					t, err = ut.T("lt-number", fe.Field(), ut.FmtNumber(f64, digits))
 				}
 
 			END:
@@ -694,45 +1033,35 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			},
 		},
 		{
-			tag: "gte",
+			tag: "lte",
 			customRegisFunc: func(ut ut.Translator) (err error) {
-
-				if err = ut.Add("gte-string", "panjang minimal {0} adalah {1}", false); err != nil {
+				if err = ut.Add("lte-string", "panjang maksimal {0} adalah {1}", 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 {
+				if err = ut.AddCardinal("lte-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 {
+				if err = ut.Add("lte-number", "{0} harus {1} atau kurang", false); err != nil {
 					return
 				}
 
-				if err = ut.Add("gte-items", "{0} harus berisi setidaknya {1}", false); err != nil {
+				if err = ut.Add("lte-items", "{0} harus berisi maksimal {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} item", locales.PluralRuleOther, false); err != nil {
+				if err = ut.AddCardinal("lte-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 {
+				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
@@ -765,12 +1094,12 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 						goto END
 					}
 
-					c, err = ut.C("gte-string-character", f64, digits, ut.FmtNumber(f64, digits))
+					c, err = ut.C("lte-string-character", f64, digits, ut.FmtNumber(f64, digits))
 					if err != nil {
 						goto END
 					}
 
-					t, err = ut.T("gte-string", fe.Field(), c)
+					t, err = ut.T("lte-string", fe.Field(), c)
 
 				case reflect.Slice, reflect.Map, reflect.Array:
 					var c string
@@ -780,12 +1109,12 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 						goto END
 					}
 
-					c, err = ut.C("gte-items-item", f64, digits, ut.FmtNumber(f64, digits))
+					c, err = ut.C("lte-items-item", f64, digits, ut.FmtNumber(f64, digits))
 					if err != nil {
 						goto END
 					}
 
-					t, err = ut.T("gte-items", fe.Field(), c)
+					t, err = ut.T("lte-items", fe.Field(), c)
 
 				case reflect.Struct:
 					if fe.Type() != reflect.TypeOf(time.Time{}) {
@@ -793,7 +1122,7 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 						goto END
 					}
 
-					t, err = ut.T("gte-datetime", fe.Field())
+					t, err = ut.T("lte-datetime", fe.Field())
 
 				default:
 					err = fn()
@@ -801,7 +1130,7 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 						goto END
 					}
 
-					t, err = ut.T("gte-number", fe.Field(), ut.FmtNumber(f64, digits))
+					t, err = ut.T("lte-number", fe.Field(), ut.FmtNumber(f64, digits))
 				}
 
 			END:
@@ -814,134 +1143,118 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			},
 		},
 		{
-			tag:         "eqfield",
-			translation: "{0} harus sama dengan {1}",
-			override:    false,
-			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()
-				}
+			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,
+		},
 
-				return t
-			},
+		// Other Tags
+		{
+			tag:         "dir",
+			translation: "{0} harus berupa direktori yang ada",
+			override:    false,
 		},
 		{
-			tag:         "eqcsfield",
-			translation: "{0} harus sama dengan {1}",
+			tag:         "dirpath",
+			translation: "{0} harus berupa path direktori yang valid",
 			override:    false,
-			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} tidak sama dengan {1}",
+			tag:         "file",
+			translation: "{0} harus berupa file yang valid",
 			override:    false,
-			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} harus lebih besar dari {1}",
+			tag:         "filepath",
+			translation: "{0} harus berupa path file yang valid",
 			override:    false,
-			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} harus lebih besar dari atau sama dengan {1}",
+			tag:         "image",
+			translation: "{0} harus berupa gambar yang valid",
 			override:    false,
-			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} harus kurang dari {1}",
+			tag:         "isdefault",
+			translation: "{0} harus berupa nilai default",
 			override:    false,
-			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
+		},
+		{
+			tag: "len",
+			customRegisFunc: func(ut ut.Translator) (err error) {
+				if err = ut.Add("len-string", "panjang {0} harus {1}", false); err != nil {
+					return
+				}
 
-				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()
+				if err = ut.AddCardinal("len-string-character", "{0} karakter", locales.PluralRuleOther, false); err != nil {
+					return
 				}
 
-				return t
-			},
-		},
-		{
-			tag:         "ltecsfield",
-			translation: "{0} harus kurang dari atau sama dengan {1}",
-			override:    false,
-			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
+				if err = ut.Add("len-number", "{0} harus sama dengan {1}", false); err != nil {
+					return
+				}
 
-				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()
+				if err = ut.Add("len-items", "{0} harus berisi {1}", false); err != nil {
+					return
 				}
 
-				return t
+				if err = ut.AddCardinal("len-items-item", "{0} item", locales.PluralRuleOther, false); err != nil {
+					return
+				}
+
+				return
 			},
-		},
-		{
-			tag:         "nefield",
-			translation: "{0} tidak sama dengan {1}",
-			override:    false,
 			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:]))
+				}
 
-				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
+				f64, err := strconv.ParseFloat(fe.Param(), 64)
 				if err != nil {
-					log.Printf("warning: error translating FieldError: %#v", fe)
-					return fe.(error).Error()
+					goto END
 				}
 
-				return t
-			},
-		},
-		{
-			tag:         "gtfield",
-			translation: "{0} harus lebih besar dari {1}",
-			override:    false,
-			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
+				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)
 
-				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
+				default:
+					t, err = ut.T("len-number", fe.Field(), ut.FmtNumber(f64, digits))
+				}
+
+			END:
 				if err != nil {
-					log.Printf("warning: error translating FieldError: %#v", fe)
+					fmt.Printf("warning: error translating FieldError: %s", err)
 					return fe.(error).Error()
 				}
 
@@ -949,129 +1262,74 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			},
 		},
 		{
-			tag:         "gtefield",
-			translation: "{0} harus lebih besar dari atau sama dengan {1}",
-			override:    false,
-			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
+			tag: "max",
+			customRegisFunc: func(ut ut.Translator) (err error) {
+				if err = ut.Add("max-string", "panjang maksimal {0} adalah {1}", false); err != nil {
+					return
+				}
 
-				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()
+				if err = ut.AddCardinal("max-string-character", "{0} karakter", locales.PluralRuleOther, false); err != nil {
+					return
 				}
 
-				return t
-			},
-		},
-		{
-			tag:         "ltfield",
-			translation: "{0} harus kurang dari {1}",
-			override:    false,
-			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
+				if err = ut.Add("max-number", "{0} harus {1} atau kurang", false); err != nil {
+					return
+				}
 
-				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()
+				if err = ut.Add("max-items", "{0} harus berisi maksimal {1}", false); err != nil {
+					return
 				}
 
-				return t
+				if err = ut.AddCardinal("max-items-item", "{0} item", locales.PluralRuleOther, false); err != nil {
+					return
+				}
+
+				return
 			},
-		},
-		{
-			tag:         "ltefield",
-			translation: "{0} harus kurang dari atau sama dengan {1}",
-			override:    false,
 			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:]))
+				}
 
-				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
+				f64, err := strconv.ParseFloat(fe.Param(), 64)
 				if err != nil {
-					log.Printf("warning: error translating FieldError: %#v", fe)
-					return fe.(error).Error()
+					goto END
 				}
 
-				return t
-			},
-		},
-		{
-			tag:         "alpha",
-			translation: "{0} hanya dapat berisi karakter abjad",
-			override:    false,
-		},
-		{
-			tag:         "alphanum",
-			translation: "{0} hanya dapat berisi karakter alfanumerik",
-			override:    false,
-		},
-		{
-			tag:         "numeric",
-			translation: "{0} harus berupa nilai numerik yang valid",
-			override:    false,
-		},
-		{
-			tag:         "number",
-			translation: "{0} harus berupa angka yang valid",
-			override:    false,
-		},
-		{
-			tag:         "hexadecimal",
-			translation: "{0} harus berupa heksadesimal yang valid",
-			override:    false,
-		},
-		{
-			tag:         "hexcolor",
-			translation: "{0} harus berupa warna HEX yang valid",
-			override:    false,
-		},
-		{
-			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:         "hsl",
-			translation: "{0} harus berupa warna HSL yang valid",
-			override:    false,
-		},
-		{
-			tag:         "hsla",
-			translation: "{0} harus berupa warna HSLA yang valid",
-			override:    false,
-		},
-		{
-			tag:         "email",
-			translation: "{0} harus berupa alamat email yang valid",
-			override:    false,
-		},
-		{
-			tag:         "url",
-			translation: "{0} harus berupa URL yang valid",
-			override:    false,
-		},
-		{
-			tag:         "uri",
-			translation: "{0} harus berupa URI yang valid",
-			override:    false,
-		},
-		{
-			tag:         "base64",
-			translation: "{0} harus berupa string Base64 yang valid",
-			override:    false,
-		},
-		{
-			tag:         "contains",
-			translation: "{0} harus berisi teks '{1}'",
-			override:    false,
-			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
+				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))
+				}
 
-				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
+			END:
 				if err != nil {
-					log.Printf("warning: error translating FieldError: %#v", fe)
+					fmt.Printf("warning: error translating FieldError: %s", err)
 					return fe.(error).Error()
 				}
 
@@ -1079,59 +1337,74 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			},
 		},
 		{
-			tag:         "containsany",
-			translation: "{0} harus berisi setidaknya salah satu karakter berikut '{1}'",
-			override:    false,
-			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
+			tag: "min",
+			customRegisFunc: func(ut ut.Translator) (err error) {
+				if err = ut.Add("min-string", "panjang minimal {0} adalah {1}", false); err != nil {
+					return
+				}
 
-				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()
+				if err = ut.AddCardinal("min-string-character", "{0} karakter", locales.PluralRuleOther, false); err != nil {
+					return
 				}
 
-				return t
-			},
-		},
-		{
-			tag:         "excludes",
-			translation: "{0} tidak boleh berisi teks '{1}'",
-			override:    false,
-			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
+				if err = ut.Add("min-number", "{0} harus {1} atau lebih besar", false); err != nil {
+					return
+				}
 
-				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()
+				if err = ut.Add("min-items", "{0} harus berisi minimal {1}", false); err != nil {
+					return
 				}
 
-				return t
+				if err = ut.AddCardinal("min-items-item", "{0} item", locales.PluralRuleOther, false); err != nil {
+					return
+				}
+
+				return
 			},
-		},
-		{
-			tag:         "excludesall",
-			translation: "{0} tidak boleh berisi salah satu karakter berikut '{1}'",
-			override:    false,
 			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:]))
+				}
 
-				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
+				f64, err := strconv.ParseFloat(fe.Param(), 64)
 				if err != nil {
-					log.Printf("warning: error translating FieldError: %#v", fe)
-					return fe.(error).Error()
+					goto END
 				}
 
-				return t
-			},
-		},
-		{
-			tag:         "excludesrune",
-			translation: "{0} tidak boleh berisi '{1}'",
-			override:    false,
-			customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
+				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))
+				}
 
-				t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
+			END:
 				if err != nil {
-					log.Printf("warning: error translating FieldError: %#v", fe)
+					fmt.Printf("warning: error translating FieldError: %s", err)
 					return fe.(error).Error()
 				}
 
@@ -1139,209 +1412,115 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 			},
 		},
 		{
-			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:         "uuid",
-			translation: "{0} harus berupa UUID yang valid",
-			override:    false,
-		},
-		{
-			tag:         "uuid3",
-			translation: "{0} harus berupa UUID versi 3 yang valid",
-			override:    false,
-		},
-		{
-			tag:         "uuid4",
-			translation: "{0} harus berupa UUID versi 4 yang valid",
-			override:    false,
-		},
-		{
-			tag:         "uuid5",
-			translation: "{0} harus berupa UUID versi 5 yang valid",
-			override:    false,
-		},
-		{
-			tag:         "ulid",
-			translation: "{0} harus berupa ULID yang valid",
-			override:    false,
-		},
-		{
-			tag:         "ascii",
-			translation: "{0} hanya boleh berisi karakter ascii",
-			override:    false,
-		},
-		{
-			tag:         "printascii",
-			translation: "{0} hanya boleh berisi karakter ascii yang dapat dicetak",
-			override:    false,
-		},
-		{
-			tag:         "multibyte",
-			translation: "{0} harus berisi karakter multibyte",
-			override:    false,
-		},
-		{
-			tag:         "datauri",
-			translation: "{0} harus berisi URI Data 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:         "ssn",
-			translation: "{0} harus berupa nomor SSN 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:         "ip",
-			translation: "{0} harus berupa alamat IP yang valid",
-			override:    false,
+			tag:             "oneof",
+			translation:     "{0} harus berupa salah satu dari [{1}]",
+			override:        false,
+			customTransFunc: translateFuncWithParam,
 		},
 		{
-			tag:         "cidr",
-			translation: "{0} harus berisi notasi CIDR yang valid",
+			tag:         "required",
+			translation: "{0} wajib diisi",
 			override:    false,
 		},
 		{
-			tag:         "cidrv4",
-			translation: "{0} harus berisi notasi CIDR yang valid untuk alamat IPv4",
-			override:    false,
+			tag:             "required_if",
+			translation:     "{0} wajib diisi jika {1}",
+			override:        false,
+			customTransFunc: translateFuncWithParam,
 		},
 		{
-			tag:         "cidrv6",
-			translation: "{0} harus berisi notasi CIDR yang valid untuk alamat IPv6",
-			override:    false,
+			tag:             "required_unless",
+			translation:     "{0} wajib diisi kecuali {1}",
+			override:        false,
+			customTransFunc: translateFuncWithParam,
 		},
 		{
-			tag:         "tcp_addr",
-			translation: "{0} harus berupa alamat TCP yang valid",
-			override:    false,
+			tag:             "required_with",
+			translation:     "{0} wajib diisi jika {1} telah diisi",
+			override:        false,
+			customTransFunc: translateFuncWithParam,
 		},
 		{
-			tag:         "tcp4_addr",
-			translation: "{0} harus berupa alamat TCP IPv4 yang valid",
-			override:    false,
+			tag:             "required_with_all",
+			translation:     "{0} wajib diisi jika {1} telah diisi",
+			override:        false,
+			customTransFunc: translateFuncWithParam,
 		},
 		{
-			tag:         "tcp6_addr",
-			translation: "{0} harus berupa alamat TCP IPv6 yang valid",
-			override:    false,
+			tag:             "required_without",
+			translation:     "{0} wajib diisi jika {1} tidak diisi",
+			override:        false,
+			customTransFunc: translateFuncWithParam,
 		},
 		{
-			tag:         "udp_addr",
-			translation: "{0} harus berupa alamat UDP yang valid",
-			override:    false,
+			tag:             "required_without_all",
+			translation:     "{0} wajib diisi jika {1} tidak diisi",
+			override:        false,
+			customTransFunc: translateFuncWithParam,
 		},
 		{
-			tag:         "udp4_addr",
-			translation: "{0} harus berupa alamat IPv4 UDP yang valid",
-			override:    false,
+			tag:             "excluded_if",
+			translation:     "{0} tidak boleh diisi jika {1}",
+			override:        false,
+			customTransFunc: translateFuncWithParam,
 		},
 		{
-			tag:         "udp6_addr",
-			translation: "{0} harus berupa alamat IPv6 UDP yang valid",
-			override:    false,
+			tag:             "excluded_unless",
+			translation:     "{0} tidak boleh diisi kecuali {1}",
+			override:        false,
+			customTransFunc: translateFuncWithParam,
 		},
 		{
-			tag:         "ip_addr",
-			translation: "{0} harus berupa alamat IP yang dapat dipecahkan",
-			override:    false,
+			tag:             "excluded_with",
+			translation:     "{0} tidak boleh diisi jika {1} telah diisi",
+			override:        false,
+			customTransFunc: translateFuncWithParam,
 		},
 		{
-			tag:         "ip4_addr",
-			translation: "{0} harus berupa alamat IPv4 yang dapat diatasi",
-			override:    false,
+			tag:             "excluded_with_all",
+			translation:     "{0} tidak boleh diisi jika semua {1} telah diisi",
+			override:        false,
+			customTransFunc: translateFuncWithParam,
 		},
 		{
-			tag:         "ip6_addr",
-			translation: "{0} harus berupa alamat IPv6 yang dapat diatasi",
-			override:    false,
+			tag:             "excluded_without",
+			translation:     "{0} tidak boleh diisi jika {1} tidak diisi",
+			override:        false,
+			customTransFunc: translateFuncWithParam,
 		},
 		{
-			tag:         "unix_addr",
-			translation: "{0} harus berupa alamat UNIX yang dapat diatasi",
-			override:    false,
+			tag:             "excluded_without_all",
+			translation:     "{0} tidak boleh diisi jika {1} tidak diisi",
+			override:        false,
+			customTransFunc: translateFuncWithParam,
 		},
 		{
-			tag:         "mac",
-			translation: "{0} harus berisi alamat MAC yang valid",
+			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:         "oneof",
-			translation: "{0} harus berupa salah satu dari [{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} harus berupa gambar yang valid",
+			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)
 		}
@@ -1354,27 +1533,33 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
 	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
 }
diff --git a/validator.go b/validator.go
index 901e7b5..d7c2e65 100644
--- a/validator.go
+++ b/validator.go
@@ -117,6 +117,10 @@ func (v *validate) traverseField(ctx context.Context, parent reflect.Value, curr
 			return
 		}
 
+		if ct.typeof == typeOmitZero {
+			return
+		}
+
 		if ct.hasTag {
 			if kind == reflect.Invalid {
 				v.str1 = string(append(ns, cf.altName...))
@@ -238,6 +242,19 @@ OUTER:
 			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
diff --git a/validator_instance.go b/validator_instance.go
index d9f148d..779f689 100644
--- a/validator_instance.go
+++ b/validator_instance.go
@@ -21,6 +21,7 @@ const (
 	tagKeySeparator       = "="
 	structOnlyTag         = "structonly"
 	noStructLevelTag      = "nostructlevel"
+	omitzero              = "omitzero"
 	omitempty             = "omitempty"
 	omitnil               = "omitnil"
 	isdefault             = "isdefault"


Test patch:
diff --git a/translations/en/en_test.go b/translations/en/en_test.go
index e5d397e..c3de218 100644
--- a/translations/en/en_test.go
+++ b/translations/en/en_test.go
@@ -175,10 +175,12 @@ func TestTranslations(t *testing.T) {
 		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"`
+		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"`
 	}
 
 	var test Test
@@ -248,6 +250,9 @@ func TestTranslations(t *testing.T) {
 	test.BooleanString = "A"
 	test.CveString = "A"
 
+	test.MinDuration = 1 * time.Hour
+	test.MaxDuration = 3 * time.Hour
+
 	test.Inner.RequiredIf = "abcd"
 
 	err = validate.Struct(test)
@@ -792,6 +797,14 @@ func TestTranslations(t *testing.T) {
 			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",
+		},
 	}
 
 	for _, tt := range tests {
diff --git a/translations/id/id_test.go b/translations/id/id_test.go
index 4a5b70f..e14db2c 100644
--- a/translations/id/id_test.go
+++ b/translations/id/id_test.go
@@ -10,17 +10,34 @@ import (
 	"github.com/go-playground/validator/v10"
 )
 
-func TestTranslations(t *testing.T) {
+// 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")
 
-	validate := validator.New()
+	// 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
@@ -28,613 +45,1294 @@ func TestTranslations(t *testing.T) {
 		GteCSFieldString string
 		LtCSFieldString  string
 		LteCSFieldString string
+		FieldContains    string
+		FieldExcludes    string
 	}
 
-	type Test struct {
-		Inner             Inner
-		RequiredString    string    `validate:"required"`
-		RequiredNumber    int       `validate:"required"`
-		RequiredMultiple  []string  `validate:"required"`
-		LenString         string    `validate:"len=1"`
-		LenNumber         float64   `validate:"len=1113.00"`
-		LenMultiple       []string  `validate:"len=7"`
-		MinString         string    `validate:"min=1"`
-		MinNumber         float64   `validate:"min=1113.00"`
-		MinMultiple       []string  `validate:"min=7"`
-		MaxString         string    `validate:"max=3"`
-		MaxNumber         float64   `validate:"max=1113.00"`
-		MaxMultiple       []string  `validate:"max=7"`
-		EqString          string    `validate:"eq=3"`
-		EqNumber          float64   `validate:"eq=2.33"`
-		EqMultiple        []string  `validate:"eq=7"`
-		NeString          string    `validate:"ne="`
-		NeNumber          float64   `validate:"ne=0.00"`
-		NeMultiple        []string  `validate:"ne=0"`
-		LtString          string    `validate:"lt=3"`
-		LtNumber          float64   `validate:"lt=5.56"`
-		LtMultiple        []string  `validate:"lt=2"`
-		LtTime            time.Time `validate:"lt"`
-		LteString         string    `validate:"lte=3"`
-		LteNumber         float64   `validate:"lte=5.56"`
-		LteMultiple       []string  `validate:"lte=2"`
-		LteTime           time.Time `validate:"lte"`
-		GtString          string    `validate:"gt=3"`
-		GtNumber          float64   `validate:"gt=5.56"`
-		GtMultiple        []string  `validate:"gt=2"`
-		GtTime            time.Time `validate:"gt"`
-		GteString         string    `validate:"gte=3"`
-		GteNumber         float64   `validate:"gte=5.56"`
-		GteMultiple       []string  `validate:"gte=2"`
-		GteTime           time.Time `validate:"gte"`
-		EqFieldString     string    `validate:"eqfield=MaxString"`
-		EqCSFieldString   string    `validate:"eqcsfield=Inner.EqCSFieldString"`
-		NeCSFieldString   string    `validate:"necsfield=Inner.NeCSFieldString"`
-		GtCSFieldString   string    `validate:"gtcsfield=Inner.GtCSFieldString"`
-		GteCSFieldString  string    `validate:"gtecsfield=Inner.GteCSFieldString"`
-		LtCSFieldString   string    `validate:"ltcsfield=Inner.LtCSFieldString"`
-		LteCSFieldString  string    `validate:"ltecsfield=Inner.LteCSFieldString"`
-		NeFieldString     string    `validate:"nefield=EqFieldString"`
-		GtFieldString     string    `validate:"gtfield=MaxString"`
-		GteFieldString    string    `validate:"gtefield=MaxString"`
-		LtFieldString     string    `validate:"ltfield=MaxString"`
-		LteFieldString    string    `validate:"ltefield=MaxString"`
-		AlphaString       string    `validate:"alpha"`
-		AlphanumString    string    `validate:"alphanum"`
-		NumericString     string    `validate:"numeric"`
-		NumberString      string    `validate:"number"`
-		HexadecimalString string    `validate:"hexadecimal"`
-		HexColorString    string    `validate:"hexcolor"`
-		RGBColorString    string    `validate:"rgb"`
-		RGBAColorString   string    `validate:"rgba"`
-		HSLColorString    string    `validate:"hsl"`
-		HSLAColorString   string    `validate:"hsla"`
-		Email             string    `validate:"email"`
-		URL               string    `validate:"url"`
-		URI               string    `validate:"uri"`
-		Base64            string    `validate:"base64"`
-		Contains          string    `validate:"contains=tujuan"`
-		ContainsAny       string    `validate:"containsany=!@#$"`
-		Excludes          string    `validate:"excludes=text"`
-		ExcludesAll       string    `validate:"excludesall=!@#$"`
-		ExcludesRune      string    `validate:"excludesrune=☻"`
-		ISBN              string    `validate:"isbn"`
-		ISBN10            string    `validate:"isbn10"`
-		ISBN13            string    `validate:"isbn13"`
-		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=merah hijau"`
-		OneOfInt          int       `validate:"oneof=5 63"`
-		Image			  string			`validate:"image"`
-	}
+	// 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
 
-	var test Test
+		// Not equal field validations
+		NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"`
+		NeFieldString   string `validate:"nefield=NeString"`
+		NeString        string
 
-	test.Inner.EqCSFieldString = "1234"
-	test.Inner.GtCSFieldString = "1234"
-	test.Inner.GteCSFieldString = "1234"
+		// Greater than field validations
+		GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"`
+		GtFieldString   string `validate:"gtfield=GtString"`
+		GtString        string
 
-	test.MaxString = "1234"
-	test.MaxNumber = 2000
-	test.MaxMultiple = make([]string, 9)
+		// Greater than or equal field validations
+		GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"`
+		GteFieldString   string `validate:"gtefield=GteString"`
+		GteString        string
 
-	test.LtString = "1234"
-	test.LtNumber = 6
-	test.LtMultiple = make([]string, 3)
-	test.LtTime = time.Now().Add(time.Hour * 24)
+		// Less than field validations
+		LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"`
+		LtFieldString   string `validate:"ltfield=LtString"`
+		LtString        string
 
-	test.LteString = "1234"
-	test.LteNumber = 6
-	test.LteMultiple = make([]string, 3)
-	test.LteTime = time.Now().Add(time.Hour * 24)
+		// Less than or equal field validations
+		LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"`
+		LteFieldString   string `validate:"ltefield=LteString"`
+		LteString        string
 
-	test.LtFieldString = "12345"
-	test.LteFieldString = "12345"
+		// 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",
 
-	test.LtCSFieldString = "1234"
-	test.LteCSFieldString = "1234"
+		NeCSFieldString: "not-equal", // should not equal Inner.NeCSFieldString
+		NeFieldString:   "same",      // should not equal NeString
+		NeString:        "same",
 
-	test.AlphaString = "abc3"
-	test.AlphanumString = "abc3!"
-	test.NumericString = "12E.00"
-	test.NumberString = "12E"
+		GtCSFieldString: "aaa", // should be greater than Inner.GtCSFieldString
+		GtFieldString:   "aaa", // should be greater than GtString
+		GtString:        "zzz",
 
-	test.Excludes = "this is some test text"
-	test.ExcludesAll = "This is Great!"
-	test.ExcludesRune = "Love it ☻"
+		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
 
-	test.ASCII = "ｶﾀｶﾅ"
-	test.PrintableASCII = "ｶﾀｶﾅ"
+		LtCSFieldString: "zzz", // should be less than Inner.LtCSFieldString
+		LtFieldString:   "zzz", // should be less than LtString
+		LtString:        "aaa",
 
-	test.MultiByte = "1234feerf"
+		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
 
-	s := "toolong"
-	test.StrPtrMaxLen = &s
-	test.StrPtrLen = &s
+		ContainsField: "xyz",          // should contain Inner.FieldContains
+		ExcludesField: "has-excludes", // should not contain Inner.FieldExcludes
+	}
 
+	// validate struct
 	err = validate.Struct(test)
 	NotEqual(t, err, nil)
 
-	errs, ok := err.(validator.ValidationErrors)
-	Equal(t, ok, true)
+	// get validation errors
+	errs := err.(validator.ValidationErrors)
 
+	// verify each expected error message
 	tests := []struct {
 		ns       string
 		expected string
 	}{
 		{
-			ns:       "Test.IsColor",
-			expected: "IsColor harus berupa warna yang valid",
+			ns:       "TestFieldTags.EqCSFieldString",
+			expected: "EqCSFieldString harus sama dengan Inner.EqCSFieldString",
 		},
 		{
-			ns:       "Test.MAC",
-			expected: "MAC harus berisi alamat MAC yang valid",
+			ns:       "TestFieldTags.EqFieldString",
+			expected: "EqFieldString harus sama dengan EqString",
 		},
 		{
-			ns:       "Test.IPAddr",
-			expected: "IPAddr harus berupa alamat IP yang dapat dipecahkan",
+			ns:       "TestFieldTags.NeCSFieldString",
+			expected: "NeCSFieldString tidak sama dengan Inner.NeCSFieldString",
 		},
 		{
-			ns:       "Test.IPAddrv4",
-			expected: "IPAddrv4 harus berupa alamat IPv4 yang dapat diatasi",
+			ns:       "TestFieldTags.NeFieldString",
+			expected: "NeFieldString tidak sama dengan NeString",
 		},
 		{
-			ns:       "Test.IPAddrv6",
-			expected: "IPAddrv6 harus berupa alamat IPv6 yang dapat diatasi",
+			ns:       "TestFieldTags.GtCSFieldString",
+			expected: "GtCSFieldString harus lebih besar dari Inner.GtCSFieldString",
 		},
 		{
-			ns:       "Test.UDPAddr",
-			expected: "UDPAddr harus berupa alamat UDP yang valid",
+			ns:       "TestFieldTags.GtFieldString",
+			expected: "GtFieldString harus lebih besar dari GtString",
 		},
 		{
-			ns:       "Test.UDPAddrv4",
-			expected: "UDPAddrv4 harus berupa alamat IPv4 UDP yang valid",
+			ns:       "TestFieldTags.GteCSFieldString",
+			expected: "GteCSFieldString harus lebih besar dari atau sama dengan Inner.GteCSFieldString",
 		},
 		{
-			ns:       "Test.UDPAddrv6",
-			expected: "UDPAddrv6 harus berupa alamat IPv6 UDP yang valid",
+			ns:       "TestFieldTags.GteFieldString",
+			expected: "GteFieldString harus lebih besar dari atau sama dengan GteString",
 		},
 		{
-			ns:       "Test.TCPAddr",
-			expected: "TCPAddr harus berupa alamat TCP yang valid",
+			ns:       "TestFieldTags.LtCSFieldString",
+			expected: "LtCSFieldString harus kurang dari Inner.LtCSFieldString",
 		},
 		{
-			ns:       "Test.TCPAddrv4",
-			expected: "TCPAddrv4 harus berupa alamat TCP IPv4 yang valid",
+			ns:       "TestFieldTags.LtFieldString",
+			expected: "LtFieldString harus kurang dari LtString",
 		},
 		{
-			ns:       "Test.TCPAddrv6",
-			expected: "TCPAddrv6 harus berupa alamat TCP IPv6 yang valid",
+			ns:       "TestFieldTags.LteCSFieldString",
+			expected: "LteCSFieldString harus kurang dari atau sama dengan Inner.LteCSFieldString",
 		},
 		{
-			ns:       "Test.CIDR",
-			expected: "CIDR harus berisi notasi CIDR yang valid",
+			ns:       "TestFieldTags.LteFieldString",
+			expected: "LteFieldString harus kurang dari atau sama dengan LteString",
 		},
 		{
-			ns:       "Test.CIDRv4",
-			expected: "CIDRv4 harus berisi notasi CIDR yang valid untuk alamat IPv4",
+			ns:       "TestFieldTags.ContainsField",
+			expected: "ContainsField harus berisi nilai dari field Inner.FieldContains",
 		},
 		{
-			ns:       "Test.CIDRv6",
-			expected: "CIDRv6 harus berisi notasi CIDR yang valid untuk alamat IPv6",
+			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:       "Test.SSN",
-			expected: "SSN harus berupa nomor SSN yang valid",
+			ns:       "TestNetworkTags.CIDR",
+			expected: "CIDR harus berupa notasi CIDR yang valid",
 		},
 		{
-			ns:       "Test.IP",
+			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:       "Test.IPv4",
+			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:       "Test.IPv6",
+			ns:       "TestNetworkTags.IPv6",
 			expected: "IPv6 harus berupa alamat IPv6 yang valid",
 		},
 		{
-			ns:       "Test.DataURI",
-			expected: "DataURI harus berisi URI Data yang valid",
+			ns:       "TestNetworkTags.MAC",
+			expected: "MAC harus berisi alamat MAC yang valid",
 		},
 		{
-			ns:       "Test.Latitude",
-			expected: "Latitude harus berisi koordinat lintang yang valid",
+			ns:       "TestNetworkTags.TCP4Addr",
+			expected: "TCP4Addr harus berupa alamat TCP IPv4 yang valid",
 		},
 		{
-			ns:       "Test.Longitude",
-			expected: "Longitude harus berisi koordinat bujur yang valid",
+			ns:       "TestNetworkTags.TCP6Addr",
+			expected: "TCP6Addr harus berupa alamat TCP IPv6 yang valid",
 		},
 		{
-			ns:       "Test.MultiByte",
-			expected: "MultiByte harus berisi karakter multibyte",
+			ns:       "TestNetworkTags.TCPAddr",
+			expected: "TCPAddr harus berupa alamat TCP yang valid",
 		},
 		{
-			ns:       "Test.ASCII",
-			expected: "ASCII hanya boleh berisi karakter ascii",
+			ns:       "TestNetworkTags.UDP4Addr",
+			expected: "UDP4Addr harus berupa alamat IPv4 UDP yang valid",
 		},
 		{
-			ns:       "Test.PrintableASCII",
-			expected: "PrintableASCII hanya boleh berisi karakter ascii yang dapat dicetak",
+			ns:       "TestNetworkTags.UDP6Addr",
+			expected: "UDP6Addr harus berupa alamat IPv6 UDP yang valid",
 		},
 		{
-			ns:       "Test.UUID",
-			expected: "UUID harus berupa UUID yang valid",
+			ns:       "TestNetworkTags.UDPAddr",
+			expected: "UDPAddr harus berupa alamat UDP yang valid",
 		},
 		{
-			ns:       "Test.UUID3",
-			expected: "UUID3 harus berupa UUID versi 3 yang valid",
+			ns:       "TestNetworkTags.URI",
+			expected: "URI harus berupa URI yang valid",
 		},
 		{
-			ns:       "Test.UUID4",
-			expected: "UUID4 harus berupa UUID versi 4 yang valid",
+			ns:       "TestNetworkTags.URL",
+			expected: "URL harus berupa URL yang valid",
 		},
 		{
-			ns:       "Test.UUID5",
-			expected: "UUID5 harus berupa UUID versi 5 yang valid",
+			ns:       "TestNetworkTags.HTTPURL",
+			expected: "HTTPURL harus berupa URL HTTP/HTTPS yang valid",
 		},
 		{
-			ns:       "Test.ULID",
-			expected: "ULID harus berupa ULID yang valid",
+			ns:       "TestNetworkTags.URLEncoded",
+			expected: "URLEncoded harus berupa string URL yang terenkode",
 		},
 		{
-			ns:       "Test.ISBN",
+			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:       "Test.ISBN10",
+			ns:       "TestFormatTags.ISBN10",
 			expected: "ISBN10 harus berupa nomor ISBN-10 yang valid",
 		},
 		{
-			ns:       "Test.ISBN13",
+			ns:       "TestFormatTags.ISBN13",
 			expected: "ISBN13 harus berupa nomor ISBN-13 yang valid",
 		},
 		{
-			ns:       "Test.ISSN",
+			ns:       "TestFormatTags.ISSN",
 			expected: "ISSN harus berupa nomor ISSN yang valid",
 		},
 		{
-			ns:       "Test.Excludes",
-			expected: "Excludes tidak boleh berisi teks 'text'",
+			ns:       "TestFormatTags.ISO3166Alpha2",
+			expected: "ISO3166Alpha2 harus berupa kode negara ISO 3166-1 alpha-2 yang valid",
 		},
 		{
-			ns:       "Test.ExcludesAll",
-			expected: "ExcludesAll tidak boleh berisi salah satu karakter berikut '!@#$'",
+			ns:       "TestFormatTags.ISO3166Alpha3",
+			expected: "ISO3166Alpha3 harus berupa kode negara ISO 3166-1 alpha-3 yang valid",
 		},
 		{
-			ns:       "Test.ExcludesRune",
-			expected: "ExcludesRune tidak boleh berisi '☻'",
+			ns:       "TestFormatTags.ISO3166AlphaNumeric",
+			expected: "ISO3166AlphaNumeric harus berupa kode negara numerik ISO 3166-1 yang valid",
 		},
 		{
-			ns:       "Test.ContainsAny",
-			expected: "ContainsAny harus berisi setidaknya salah satu karakter berikut '!@#$'",
+			ns:       "TestFormatTags.ISO31662",
+			expected: "ISO31662 harus berupa kode subdivisi negara ISO 3166-2 yang valid",
 		},
 		{
-			ns:       "Test.Contains",
-			expected: "Contains harus berisi teks 'tujuan'",
+			ns:       "TestFormatTags.ISO4217",
+			expected: "ISO4217 harus berupa kode mata uang ISO 4217 yang valid",
 		},
 		{
-			ns:       "Test.Base64",
-			expected: "Base64 harus berupa string Base64 yang valid",
+			ns:       "TestFormatTags.JSON",
+			expected: "JSON harus berupa string JSON yang valid",
 		},
 		{
-			ns:       "Test.Email",
-			expected: "Email harus berupa alamat email yang valid",
+			ns:       "TestFormatTags.JWT",
+			expected: "JWT harus berupa JSON Web Token (JWT) yang valid",
 		},
 		{
-			ns:       "Test.URL",
-			expected: "URL harus berupa URL yang valid",
+			ns:       "TestFormatTags.Latitude",
+			expected: "Latitude harus berisi koordinat lintang yang valid",
 		},
 		{
-			ns:       "Test.URI",
-			expected: "URI harus berupa URI 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:       "Test.RGBColorString",
-			expected: "RGBColorString harus berupa warna RGB yang valid",
+			ns:       "TestFormatTags.PostcodeISO3166Alpha2Field",
+			expected: "PostcodeISO3166Alpha2Field tidak sesuai dengan format kode pos negara dalam field ",
 		},
 		{
-			ns:       "Test.RGBAColorString",
-			expected: "RGBAColorString harus berupa warna RGBA yang valid",
+			ns:       "TestFormatTags.RGB",
+			expected: "RGB harus berupa warna RGB yang valid",
 		},
 		{
-			ns:       "Test.HSLColorString",
-			expected: "HSLColorString harus berupa warna HSL yang valid",
+			ns:       "TestFormatTags.RGBA",
+			expected: "RGBA harus berupa warna RGBA yang valid",
 		},
 		{
-			ns:       "Test.HSLAColorString",
-			expected: "HSLAColorString harus berupa warna HSLA yang valid",
+			ns:       "TestFormatTags.SSN",
+			expected: "SSN harus berupa nomor SSN (Social Security Number) yang valid",
 		},
 		{
-			ns:       "Test.HexadecimalString",
-			expected: "HexadecimalString harus berupa heksadesimal yang valid",
+			ns:       "TestFormatTags.Timezone",
+			expected: "Timezone harus berupa zona waktu yang valid",
 		},
 		{
-			ns:       "Test.HexColorString",
-			expected: "HexColorString harus berupa warna HEX yang valid",
+			ns:       "TestFormatTags.UUID",
+			expected: "UUID harus berupa UUID yang valid",
 		},
 		{
-			ns:       "Test.NumberString",
-			expected: "NumberString harus berupa angka yang valid",
+			ns:       "TestFormatTags.UUID3",
+			expected: "UUID3 harus berupa UUID versi 3 yang valid",
 		},
 		{
-			ns:       "Test.NumericString",
-			expected: "NumericString harus berupa nilai numerik yang valid",
+			ns:       "TestFormatTags.UUID3RFC4122",
+			expected: "UUID3RFC4122 harus berupa UUID versi 3 RFC4122 yang valid",
 		},
 		{
-			ns:       "Test.AlphanumString",
-			expected: "AlphanumString hanya dapat berisi karakter alfanumerik",
+			ns:       "TestFormatTags.UUID4",
+			expected: "UUID4 harus berupa UUID versi 4 yang valid",
 		},
 		{
-			ns:       "Test.AlphaString",
-			expected: "AlphaString hanya dapat berisi karakter abjad",
+			ns:       "TestFormatTags.UUID4RFC4122",
+			expected: "UUID4RFC4122 harus berupa UUID versi 4 RFC4122 yang valid",
 		},
 		{
-			ns:       "Test.LtFieldString",
-			expected: "LtFieldString harus kurang dari MaxString",
+			ns:       "TestFormatTags.UUID5",
+			expected: "UUID5 harus berupa UUID versi 5 yang valid",
 		},
 		{
-			ns:       "Test.LteFieldString",
-			expected: "LteFieldString harus kurang dari atau sama dengan MaxString",
+			ns:       "TestFormatTags.UUID5RFC4122",
+			expected: "UUID5RFC4122 harus berupa UUID versi 5 RFC4122 yang valid",
 		},
 		{
-			ns:       "Test.GtFieldString",
-			expected: "GtFieldString harus lebih besar dari MaxString",
+			ns:       "TestFormatTags.UUIDRFC4122",
+			expected: "UUIDRFC4122 harus berupa UUID RFC4122 yang valid",
 		},
 		{
-			ns:       "Test.GteFieldString",
-			expected: "GteFieldString harus lebih besar dari atau sama dengan MaxString",
+			ns:       "TestFormatTags.MD4",
+			expected: "MD4 harus berupa hash MD4 yang valid",
 		},
 		{
-			ns:       "Test.NeFieldString",
-			expected: "NeFieldString tidak sama dengan EqFieldString",
+			ns:       "TestFormatTags.MD5",
+			expected: "MD5 harus berupa hash MD5 yang valid",
 		},
 		{
-			ns:       "Test.LtCSFieldString",
-			expected: "LtCSFieldString harus kurang dari Inner.LtCSFieldString",
+			ns:       "TestFormatTags.SHA256",
+			expected: "SHA256 harus berupa hash SHA256 yang valid",
 		},
 		{
-			ns:       "Test.LteCSFieldString",
-			expected: "LteCSFieldString harus kurang dari atau sama dengan Inner.LteCSFieldString",
+			ns:       "TestFormatTags.SHA384",
+			expected: "SHA384 harus berupa hash SHA384 yang valid",
 		},
 		{
-			ns:       "Test.GtCSFieldString",
-			expected: "GtCSFieldString harus lebih besar dari Inner.GtCSFieldString",
+			ns:       "TestFormatTags.SHA512",
+			expected: "SHA512 harus berupa hash SHA512 yang valid",
 		},
 		{
-			ns:       "Test.GteCSFieldString",
-			expected: "GteCSFieldString harus lebih besar dari atau sama dengan Inner.GteCSFieldString",
+			ns:       "TestFormatTags.RIPEMD128",
+			expected: "RIPEMD128 harus berupa hash RIPEMD128 yang valid",
 		},
 		{
-			ns:       "Test.NeCSFieldString",
-			expected: "NeCSFieldString tidak sama dengan Inner.NeCSFieldString",
+			ns:       "TestFormatTags.RIPEMD160",
+			expected: "RIPEMD160 harus berupa hash RIPEMD160 yang valid",
 		},
 		{
-			ns:       "Test.EqCSFieldString",
-			expected: "EqCSFieldString harus sama dengan Inner.EqCSFieldString",
+			ns:       "TestFormatTags.Tiger128",
+			expected: "Tiger128 harus berupa hash TIGER128 yang valid",
 		},
 		{
-			ns:       "Test.EqFieldString",
-			expected: "EqFieldString harus sama dengan MaxString",
+			ns:       "TestFormatTags.Tiger160",
+			expected: "Tiger160 harus berupa hash TIGER160 yang valid",
 		},
 		{
-			ns:       "Test.GteString",
-			expected: "panjang minimal GteString adalah 3 karakter",
+			ns:       "TestFormatTags.Tiger192",
+			expected: "Tiger192 harus berupa hash TIGER192 yang valid",
 		},
 		{
-			ns:       "Test.GteNumber",
-			expected: "GteNumber harus 5,56 atau lebih besar",
+			ns:       "TestFormatTags.Semver",
+			expected: "Semver harus berupa nomor versi semantik yang valid",
 		},
 		{
-			ns:       "Test.GteMultiple",
-			expected: "GteMultiple harus berisi setidaknya 2 item",
+			ns:       "TestFormatTags.ULID",
+			expected: "ULID harus berupa ULID yang valid",
 		},
 		{
-			ns:       "Test.GteTime",
-			expected: "GteTime harus lebih besar dari atau sama dengan tanggal & waktu saat ini",
+			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:       "Test.GtString",
-			expected: "panjang GtString harus lebih dari 3 karakter",
+			ns:       "TestComparisonTags.NeIgnoreCase",
+			expected: "NeIgnoreCase tidak sama dengan Test (tidak case-sensitive)",
 		},
 		{
-			ns:       "Test.GtNumber",
-			expected: "GtNumber harus lebih besar dari 5,56",
+			ns:       "TestComparisonTags.GtString",
+			expected: "panjang GtString harus lebih dari 5 karakter",
 		},
 		{
-			ns:       "Test.GtMultiple",
-			expected: "GtMultiple harus berisi lebih dari 2 item",
+			ns:       "TestComparisonTags.GtNumber",
+			expected: "GtNumber harus lebih besar dari 10,5",
 		},
 		{
-			ns:       "Test.GtTime",
+			ns:       "TestComparisonTags.GtTime",
 			expected: "GtTime harus lebih besar dari tanggal & waktu saat ini",
 		},
 		{
-			ns:       "Test.LteString",
-			expected: "panjang maksimal LteString adalah 3 karakter",
+			ns:       "TestComparisonTags.GtSlice",
+			expected: "GtSlice harus berisi lebih dari 1 item",
 		},
 		{
-			ns:       "Test.LteNumber",
-			expected: "LteNumber harus 5,56 atau kurang",
+			ns:       "TestComparisonTags.GteString",
+			expected: "panjang minimal GteString adalah 5 karakter",
 		},
 		{
-			ns:       "Test.LteMultiple",
-			expected: "LteMultiple harus berisi maksimal 2 item",
+			ns:       "TestComparisonTags.GteNumber",
+			expected: "GteNumber harus 10,5 atau lebih besar",
 		},
 		{
-			ns:       "Test.LteTime",
-			expected: "LteTime harus kurang dari atau sama dengan tanggal & waktu saat ini",
+			ns:       "TestComparisonTags.GteTime",
+			expected: "GteTime harus lebih besar dari atau sama dengan tanggal & waktu saat ini",
 		},
 		{
-			ns:       "Test.LtString",
-			expected: "panjang LtString harus kurang dari 3 karakter",
+			ns:       "TestComparisonTags.GteSlice",
+			expected: "GteSlice harus berisi setidaknya 1 item",
 		},
 		{
-			ns:       "Test.LtNumber",
-			expected: "LtNumber harus kurang dari 5,56",
+			ns:       "TestComparisonTags.LtString",
+			expected: "panjang LtString harus kurang dari 5 karakter",
 		},
 		{
-			ns:       "Test.LtMultiple",
-			expected: "LtMultiple harus berisi kurang dari 2 item",
+			ns:       "TestComparisonTags.LtNumber",
+			expected: "LtNumber harus kurang dari 10,5",
 		},
 		{
-			ns:       "Test.LtTime",
+			ns:       "TestComparisonTags.LtTime",
 			expected: "LtTime harus kurang dari tanggal & waktu saat ini",
 		},
 		{
-			ns:       "Test.NeString",
-			expected: "NeString tidak sama dengan ",
+			ns:       "TestComparisonTags.LtSlice",
+			expected: "LtSlice harus berisi kurang dari 2 item",
+		},
+		{
+			ns:       "TestComparisonTags.LteString",
+			expected: "panjang maksimal LteString adalah 5 karakter",
 		},
 		{
-			ns:       "Test.NeNumber",
-			expected: "NeNumber tidak sama dengan 0.00",
+			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:       "Test.NeMultiple",
-			expected: "NeMultiple tidak sama dengan 0",
+			ns:       "TestOtherTags.Dir",
+			expected: "Dir harus berupa direktori yang ada",
 		},
 		{
-			ns:       "Test.EqString",
-			expected: "EqString tidak sama dengan 3",
+			ns:       "TestOtherTags.DirPath",
+			expected: "DirPath harus berupa path direktori yang valid",
 		},
 		{
-			ns:       "Test.EqNumber",
-			expected: "EqNumber tidak sama dengan 2.33",
+			ns:       "TestOtherTags.File",
+			expected: "File harus berupa file yang valid",
 		},
 		{
-			ns:       "Test.EqMultiple",
-			expected: "EqMultiple tidak sama dengan 7",
+			ns:       "TestOtherTags.FilePath",
+			expected: "FilePath harus berupa path file yang valid",
 		},
 		{
-			ns:       "Test.MaxString",
-			expected: "panjang maksimal MaxString adalah 3 karakter",
+			ns:       "TestOtherTags.Image",
+			expected: "Image harus berupa gambar yang valid",
 		},
 		{
-			ns:       "Test.MaxNumber",
-			expected: "MaxNumber harus 1.113,00 atau kurang",
+			ns:       "TestOtherTags.LenString",
+			expected: "panjang LenString harus 5 karakter",
 		},
 		{
-			ns:       "Test.MaxMultiple",
-			expected: "MaxMultiple harus berisi maksimal 7 item",
+			ns:       "TestOtherTags.LenSlice",
+			expected: "LenSlice harus berisi 3 item",
 		},
 		{
-			ns:       "Test.MinString",
-			expected: "panjang minimal MinString adalah 1 karakter",
+			ns:       "TestOtherTags.LenNumber",
+			expected: "LenNumber harus sama dengan 10",
 		},
 		{
-			ns:       "Test.MinNumber",
-			expected: "MinNumber harus 1.113,00 atau lebih besar",
+			ns:       "TestOtherTags.MinString",
+			expected: "panjang minimal MinString adalah 3 karakter",
 		},
 		{
-			ns:       "Test.MinMultiple",
-			expected: "panjang minimal MinMultiple adalah 7 item",
+			ns:       "TestOtherTags.MinSlice",
+			expected: "MinSlice harus berisi minimal 1 item",
 		},
 		{
-			ns:       "Test.LenString",
-			expected: "panjang LenString harus 1 karakter",
+			ns:       "TestOtherTags.MaxString",
+			expected: "panjang maksimal MaxString adalah 5 karakter",
 		},
 		{
-			ns:       "Test.LenNumber",
-			expected: "LenNumber harus sama dengan 1.113,00",
+			ns:       "TestOtherTags.MaxSlice",
+			expected: "MaxSlice harus berisi maksimal 1 item",
 		},
 		{
-			ns:       "Test.LenMultiple",
-			expected: "LenMultiple harus berisi 7 item",
+			ns:       "TestOtherTags.IsDefault",
+			expected: "IsDefault harus berupa nilai default",
 		},
 		{
-			ns:       "Test.RequiredString",
-			expected: "RequiredString wajib diisi",
+			ns:       "TestOtherTags.Required",
+			expected: "Required wajib diisi",
 		},
 		{
-			ns:       "Test.RequiredNumber",
-			expected: "RequiredNumber wajib diisi",
+			ns:       "TestOtherTags.RequiredIf",
+			expected: "RequiredIf wajib diisi jika Inner.RequiredWith value",
 		},
 		{
-			ns:       "Test.RequiredMultiple",
-			expected: "RequiredMultiple wajib diisi",
+			ns:       "TestOtherTags.RequiredUnless",
+			expected: "RequiredUnless wajib diisi kecuali Inner.RequiredWith values",
 		},
 		{
-			ns:       "Test.StrPtrMinLen",
-			expected: "panjang minimal StrPtrMinLen adalah 10 karakter",
+			ns:       "TestOtherTags.RequiredWith",
+			expected: "RequiredWith wajib diisi jika Inner.RequiredWith telah diisi",
 		},
 		{
-			ns:       "Test.StrPtrMaxLen",
-			expected: "panjang maksimal StrPtrMaxLen adalah 1 karakter",
+			ns:       "TestOtherTags.RequiredWithAll",
+			expected: "RequiredWithAll wajib diisi jika Inner.RequiredWith telah diisi",
 		},
 		{
-			ns:       "Test.StrPtrLen",
-			expected: "panjang StrPtrLen harus 2 karakter",
+			ns:       "TestOtherTags.RequiredWithout",
+			expected: "RequiredWithout wajib diisi jika Inner.ExcludedWith tidak diisi",
 		},
 		{
-			ns:       "Test.StrPtrLt",
-			expected: "panjang StrPtrLt harus kurang dari 1 karakter",
+			ns:       "TestOtherTags.RequiredWithoutAll",
+			expected: "RequiredWithoutAll wajib diisi jika Inner.ExcludedWith tidak diisi",
 		},
 		{
-			ns:       "Test.StrPtrLte",
-			expected: "panjang maksimal StrPtrLte adalah 1 karakter",
+			ns:       "TestOtherTags.ExcludedIf",
+			expected: "ExcludedIf tidak boleh diisi jika Inner.RequiredWith value",
 		},
 		{
-			ns:       "Test.StrPtrGt",
-			expected: "panjang StrPtrGt harus lebih dari 10 karakter",
+			ns:       "TestOtherTags.ExcludedUnless",
+			expected: "ExcludedUnless tidak boleh diisi kecuali Inner.ExcludedWith value",
 		},
 		{
-			ns:       "Test.StrPtrGte",
-			expected: "panjang minimal StrPtrGte adalah 10 karakter",
+			ns:       "TestOtherTags.ExcludedWith",
+			expected: "ExcludedWith tidak boleh diisi jika Inner.RequiredWith telah diisi",
 		},
 		{
-			ns:       "Test.OneOfString",
-			expected: "OneOfString harus berupa salah satu dari [merah hijau]",
+			ns:       "TestOtherTags.ExcludedWithAll",
+			expected: "ExcludedWithAll tidak boleh diisi jika semua Inner.RequiredWith telah diisi",
 		},
 		{
-			ns:       "Test.OneOfInt",
-			expected: "OneOfInt harus berupa salah satu dari [5 63]",
+			ns:       "TestOtherTags.ExcludedWithout",
+			expected: "ExcludedWithout tidak boleh diisi jika Inner.ExcludedWith tidak diisi",
 		},
 		{
-			ns: "Test.Image",
-			expected: "Image harus berupa gambar yang valid",
+			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
@@ -645,5 +1343,100 @@ func TestTranslations(t *testing.T) {
 		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))
+	}
 }
diff --git a/validator_test.go b/validator_test.go
index 5eadb25..af05d19 100644
--- a/validator_test.go
+++ b/validator_test.go
@@ -14022,6 +14022,57 @@ func TestOmitNilAndRequired(t *testing.T) {
 	})
 }
 
+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 TestPrivateFieldsStruct(t *testing.T) {
 	type tc struct {
 		stct     interface{}