You could clean up the syntax by making the custom error message optional. Like this: v.MaxInt(v.Name, "First Name", 20).WithErrMessage("my custom message")
This would make for clean calls without all these unneeded empty strings everywhere.
And another big case would be i21n, if you truly want to generate error messages for the end user, they should be easy to translate. This could be done in different ways: One way would be typed errors including the syntax for replacement.
Or you could export a Method, where one can provide a map[language]ErrorMessages and the current language, so the error messages are taken from the map for the fitting language code.