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

> Customize validation messages in laravel-validate using Laravel's translation system. Learn 3 methods to override default error strings and enhance user feedback.

- Repository: [Milwad Khosravi/laravel-validate](https://github.com/milwad-dev/laravel-validate)
- Tags: how-to-guide
- Published: 2026-03-07

---

**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`](https://github.com/milwad-dev/laravel-validate/blob/main/src/Rules/ValidPhoneNumber.php) (lines 29-31), the implementation follows this pattern:

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

```

The package's service provider registers these translations during boot. In [`src/LaravelValidateServiceProvider.php`](https://github.com/milwad-dev/laravel-validate/blob/main/src/LaravelValidateServiceProvider.php) (line 24), the code loads the language directory under the `validation` namespace:

```php
$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:

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

```

This copies the package's language files to [`resources/lang/en/validate.php`](https://github.com/milwad-dev/laravel-validate/blob/main/resources/lang/en/validate.php). Edit the array to change specific messages:

```php
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:

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

```

Translate the keys in the generated [`resources/lang/fr/validate.php`](https://github.com/milwad-dev/laravel-validate/blob/main/resources/lang/fr/validate.php):

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

```

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

```php
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()`:

```php
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`](https://github.com/milwad-dev/laravel-validate/blob/main/resources/lang/en/validate.php):

```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:

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

```

```php
// 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`](https://github.com/milwad-dev/laravel-validate/blob/main/resources/lang/fr/validate.php) definitions.

### Validator-Specific Overrides

For a single validation instance with unique messaging:

```php
$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`](https://github.com/milwad-dev/laravel-validate/blob/main/src/Rules/ValidUrl.php) similarly returns:

```php
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`](https://github.com/milwad-dev/laravel-validate/blob/main/lang/en/validate.php)), registered under the `validation` namespace by [`LaravelValidateServiceProvider.php`](https://github.com/milwad-dev/laravel-validate/blob/main/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.