Struct validation backed by go-playground/validator/v10 with xerrors integration and pluggable i18n message providers. What's included: - Validator interface with Struct(v any) error method - New(...Option) constructor with WithMessageProvider functional option - MessageProvider interface for i18n; DefaultMessages (EN) and SpanishMessages (ES) built in - ValidationErrors mapped to xerrors.ErrInvalidInput with field and tag context keys - InvalidValidationError (non-struct input) mapped to xerrors.ErrInternal - Full playground.ValidationErrors attached via WithError for callers needing all failures Tested-via: todo-api POC integration Reviewed-against: docs/adr/
62 lines
2.1 KiB
Go
62 lines
2.1 KiB
Go
package valid
|
|
|
|
import "fmt"
|
|
|
|
// MessageProvider maps a validation failure to a human-readable message.
|
|
//
|
|
// - field: the struct field name (e.g. "Email")
|
|
// - tag: the failing validation rule (e.g. "required", "email", "min")
|
|
// - param: the rule parameter if any (e.g. "18" for min=18), or "" if none
|
|
type MessageProvider interface {
|
|
Message(field, tag, param string) string
|
|
}
|
|
|
|
// DefaultMessages is the built-in English message provider.
|
|
// Used automatically when no WithMessageProvider option is given.
|
|
var DefaultMessages MessageProvider = defaultMessages{}
|
|
|
|
// SpanishMessages is an opt-in Spanish message provider.
|
|
var SpanishMessages MessageProvider = spanishMessages{}
|
|
|
|
// ---------------------------------------------------------------
|
|
// English (default)
|
|
// ---------------------------------------------------------------
|
|
|
|
type defaultMessages struct{}
|
|
|
|
func (defaultMessages) Message(field, tag, param string) string {
|
|
switch tag {
|
|
case "required":
|
|
return fmt.Sprintf("field '%s' is required", field)
|
|
case "email":
|
|
return fmt.Sprintf("field '%s' must be a valid email address", field)
|
|
case "min":
|
|
return fmt.Sprintf("field '%s' is too short (minimum %s)", field, param)
|
|
case "max":
|
|
return fmt.Sprintf("field '%s' is too long (maximum %s)", field, param)
|
|
default:
|
|
return fmt.Sprintf("field '%s' failed validation rule '%s'", field, tag)
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------
|
|
// Spanish (opt-in)
|
|
// ---------------------------------------------------------------
|
|
|
|
type spanishMessages struct{}
|
|
|
|
func (spanishMessages) Message(field, tag, param string) string {
|
|
switch tag {
|
|
case "required":
|
|
return fmt.Sprintf("El campo '%s' es obligatorio", field)
|
|
case "email":
|
|
return fmt.Sprintf("El campo '%s' debe ser un correo electrónico válido", field)
|
|
case "min":
|
|
return fmt.Sprintf("El campo '%s' es demasiado corto (mínimo %s)", field, param)
|
|
case "max":
|
|
return fmt.Sprintf("El campo '%s' es demasiado largo (máximo %s)", field, param)
|
|
default:
|
|
return fmt.Sprintf("Error en el campo '%s': regla '%s' no cumplida", field, tag)
|
|
}
|
|
}
|