How to Customize Validation Messages in laravel-validate: 3 Methods Explained

Laravel-validate handles validation messages customization through Laravel's translation system, storing default error strings in publishable language files while allowing runtime overrides via the message() method in each rule class.

The milwad-dev/laravel-validate package extends Laravel's validator with specialized rules for phones, URLs, and more. All validation messages in this package follow Laravel's standard localization patterns, making customization straightforward without modifying vendor files.

How laravel-validate Implements Validation Messages

Every rule in the package delegates message resolution to Laravel's translator through a consistent pattern. Rather than hardcoding error text, each rule's message() method returns a translation key.

In src/Rules/ValidPhoneNumber.php (lines 29-31), the implementation follows this pattern:

public function message(): string
{
    return __('validate.phone-number');
}

The package's service provider registers these translations during boot. In src/LaravelValidateServiceProvider.php (line 24), the code loads the language directory under the validation namespace:

$this->loadTranslationsFrom(dirname(__DIR__) . '/lang', 'validation');

This architecture allows the package to support multiple locales while giving developers three distinct customization paths.

Methods to Customize Validation Messages

Laravel resolves translation keys in a specific hierarchy: runtime messages take precedence over published app files, which override package defaults. You can customize laravel-validate messages using any of these three approaches.

Publish and Edit Language Files

Publish language files to copy the package defaults into your application's resources/lang/ directory for permanent, project-wide customization. Run the artisan command for your specific locale:

php artisan vendor:publish --tag="validate-lang-en"

This copies the package's language files to resources/lang/en/validate.php. Edit the array to change specific messages:

return [
    'phone-number' => 'Please enter a valid phone number format.',
    'url' => 'The provided URL is not valid.',
];

All rules using that key—such as ValidPhoneNumber—will now display your custom text.

Add Support for Additional Locales

Create new locale files by publishing for languages not included in the package distribution:

php artisan vendor:publish --tag="validate-lang-fr"

Translate the keys in the generated resources/lang/fr/validate.php:

return [
    'phone-number' => 'Veuillez saisir un numéro de téléphone valide.',
];

When your application locale changes, Laravel automatically loads these translations:

App::setLocale('fr');

Override Messages at Runtime

Pass custom messages directly to the Validator facade for one-off customizations without publishing files. Provide the translation keys as the third argument to Validator::make():

use Illuminate\Support\Facades\Validator;
use Milwad\LaravelValidate\Rules\ValidPhoneNumber;

$validator = Validator::make(
    ['phone' => $input],
    ['phone' => ['required', new ValidPhoneNumber()]],
    ['phone-number' => 'Your custom phone validation error message.']
);

The rule's message() method still returns __('validate.phone-number'), but Laravel resolves it against your runtime array first.

Practical Implementation Examples

The following examples demonstrate customizing different rules within the laravel-validate ecosystem.

Customizing the ValidPhoneNumber Rule

After publishing the English language file, modify the entry in resources/lang/en/validate.php:

return [
    'phone-number' => 'We require a valid international phone number.',
];

Now every instance of new ValidPhoneNumber() uses this text.

Implementing French Localization

Publish the French translations and configure your validation logic:

php artisan vendor:publish --tag="validate-lang-fr"
// In a controller or service
App::setLocale('fr');

$validator = Validator::make(
    $request->all(),
    ['contact' => new ValidPhoneNumber()]
);

Error messages will appear in French according to your resources/lang/fr/validate.php definitions.

Validator-Specific Overrides

For a single validation instance with unique messaging:

$messages = [
    'phone-number' => 'The contact number :attribute is invalid for region :region.'
];

$validator = Validator::make(
    $data,
    ['mobile' => new ValidPhoneNumber()],
    $messages
);

Consistent Pattern Across All Rules

All rules follow the same implementation. The ValidUrl rule in src/Rules/ValidUrl.php similarly returns:

public function message(): string
{
    return __('validate.url');
}

Customize it by editing the 'url' key in your published language file or including 'url' => 'Custom message' in your validator's messages array.

Summary

  • Translation-based architecture: Every rule in src/Rules/ implements message() returning __('validate.{key}'), delegating resolution to Laravel's translator.
  • Three customization paths: Publish language files for permanent changes, create new locale files for multi-language support, or pass message arrays to Validator::make() for runtime overrides.
  • Lookup hierarchy: Laravel checks runtime messages first, then published app files in resources/lang/, finally falling back to the package's default translations loaded by LaravelValidateServiceProvider.
  • Consistent keys: Customization works uniformly across all rules including ValidPhoneNumber, ValidUrl, and others by targeting their respective translation keys.

Frequently Asked Questions

Where are the default validation messages stored in laravel-validate?

Default messages reside in the package's lang/ directory (e.g., lang/en/validate.php), registered under the validation namespace by LaravelValidateServiceProvider.php. You can view the source files in the milwad-dev/laravel-validate repository to see all available translation keys.

Can I customize messages for a single validation call without publishing files?

Yes, pass a custom messages array as the third argument to Validator::make(). Use the translation keys referenced in the rule's message() method (such as 'phone-number' or 'url') as array keys. Laravel resolves these runtime definitions before checking published language files.

How do I add support for a language not included in the package?

Run php artisan vendor:publish --tag="validate-lang-{locale}" replacing {locale} with your language code (e.g., zh_CN, de). This creates the translation file in resources/lang/{locale}/validate.php. Translate the array values and ensure your application locale matches using App::setLocale().

Do all rules in laravel-validate use the same message customization approach?

Yes, every rule class in src/Rules/ implements the message() method consistently, returning a translation key via the validate.{key} namespace. This uniform pattern applies to ValidPhoneNumber, ValidUrl, ValidUsername, and all other validation rules provided by the package.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →