Skip to content

Custom Error Messages

The EncolaJS Validation library lets you customize the error messages on multiple levels.

Custom error messages per validator

For basic examples of custom error messages, see the Common Validation Patterns guide.

Error messages can include dynamic values:

javascript
const validator = factory.make(
  {
    'age': 'required|integer|min:18',
    'username': 'required|min_length:3|max_length:20',
    'email': 'required|email'
  },
  // below is the list of custom error message specific to this validator
  // the format is {{path}}:{{rule_name}}
  {
    // Use field name
    'username:min_length': '{field} must be at least {param:0} characters',
    
    // Use actual value
    'age:min': 'Age {value} is below minimum {param:0}',
    
    // Reference other fields
    'discount:max': 'Discount cannot exceed {param:0}% of price'
  }
)

Custom Message Formatter

While the library comes with a built-in list of messages sometimes you may not want to use them. For example the start_with validation rule comes with this message This field must start with "{param:0}" which would generate an error message like This field must start with "beginning"

To change the default behaviour you have to implement a custom message formatter.

javascript
const validator = factory.make(rules, {
  messageFormatter: (ruleName, value, path, validationRule) => {
    // Access validation parameters
    const params = validationRule.parameters || []
    
    // Build custom message
    return `Validation failed for ${path}: ` +
           `value ${value} does not satisfy ${ruleName} ` +
           `with parameters [${params.join(', ')}]`
  }
})

Translating error messages

Using custom message formatter you can translate the error messages to any language you want.

This is a simple example of how a translation function can be integrated ino the message formatter.

javascript
// Example usage
import { ValidatorFactory } from '@encolajs/validator'

// Create translations (in real app, this would come from your i18n system)
const translations = {
  'This field is required': 'Este campo es obligatorio',
  'Must be a valid email': 'Debe ser un email válido',
  'Must be at least {param:0} characters': 'Debe tener al menos {param:0} caracteres',
  'Must be at least {param:0}': 'Debe ser al menos {param:0}'
}

// Create translation service
const translator = function(message: string, params: Record<string, string>) {
  // Get the translation for the message
  const translation = translations[message] ?? message

  // Replace parameters
  return translation.replace(/{(\w+)}/g, (match, key) => params[key] ?? match)
} 

// Create validator with translation
const factory = new ValidatorFactory()

const validator = factory.make({
  'email': 'required|email',
  'password': 'required|min_length:8',
  'age': 'required|min:18'
}, {
  messageFormatter: (ruleName, value, path, rule) => {
    // Get the default message from the rule registry
    const message = factory._ruleRegistry.getDefaultMessage(ruleName) ?? 'Validation failed'

    // Translate the message
    return translator(message, rule.params)
  }
})

// Example validation
const data = {
  email: 'invalid',
  password: 'short',
  age: 16
}

await validator.validate(data)
const errors = validator.getErrors()

/* In Spanish:
{
  email: ['Debe ser un email válido'],
  password: ['Debe tener al menos 8 caracteres'],
  age: ['Debe ser al menos 18']
}
*/

MIT Licensed