Laravel validation attributes "nice names"

PhpLaravelMultilingualLaravel 3

Php Problem Overview


I'm trying to use the validation attributes in "language > {language} > validation.php", to replace the :attribute name (input name) for a proper to read name (example: first_name > First name) . It seems very simple to use, but the validator doesn't show the "nice names".

I have this:

'attributes' => array(
    'first_name' => 'voornaam'
  , 'first name' => 'voornaam'
  , 'firstname'  => 'voornaam'
);

For showing the errors:

@if($errors->has())
  <ul>
  @foreach ($errors->all() as $error)
    <li class="help-inline errorColor">{{ $error }}</li>
  @endforeach
  </ul>
@endif

And the validation in the controller:

$validation = Validator::make($input, $rules, $messages);

The $messages array:

$messages = array(
    'required' => ':attribute is verplicht.'
  , 'email'	   => ':attribute is geen geldig e-mail adres.'
  ,	'min'	   => ':attribute moet minimaal :min karakters bevatten.'
  ,	'numeric'  => ':attribute mag alleen cijfers bevatten.'
  ,	'url'      => ':attribute moet een valide url zijn.'
  ,	'unique'   => ':attribute moet uniek zijn.'
  ,	'max'	   => ':attribute mag maximaal :max zijn.'
  , 'mimes'	   => ':attribute moet een :mimes bestand zijn.'
  ,	'numeric'  => ':attribute is geen geldig getal.'
  ,	'size'	   => ':attribute is te groot of bevat te veel karakters.'
);

Can someone tell me what i'm doing wrong. I want the :attribute name to be replaced by the "nice name" in the attributes array (language).

Thanks!

EDIT:

I noticed that the problem is I never set a default language for my Laravel projects. When I set the language to 'NL' the code above works. But, when I set my language, the language will appear in the url. And I prefer it doesn't.

So my next question: Is it possible to remove the language from the url, or set the default language so it just doesn't appear there?

Php Solutions


Solution 1 - Php

Yeahh, the "nice name" attributes as you called it was a real "issue" a few month ago. Hopefully this feature is now implemented and is very simply to use.

For simplicity i will split the two options to tackle this problem:

  1. Global Probably the more widespread. This approach is very well explained here but basically you need to edit the application/language/XX/validation.php validation file where XX is the language you will use for the validation.

At the bottom you will see an attribute array; that will be your "nice name" attributes array. Following your example the final result will be something like this.

<!-- language: lang-php -->

    'attributes' => array('first_name' => 'First Name')

2. Locally This is what Taylor Otwell was talking about in the issue when he says:

> You may call setAttributeNames on a Validator instance now.

That's perfectly valid and if you check the source code you will see

<!-- language: lang-php -->

    public function setAttributeNames(array $attributes)
    {
        $this->customAttributes = $attributes;

        return $this;
    }

**So, to use this way see the following straightforward example:**

<!-- language: lang-php -->

    $niceNames = array(
        'first_name' => 'First Name'
    );

    $validator = Validator::make(Input::all(), $rules);
    $validator->setAttributeNames($niceNames); 

Resources

There is a really awesome repo on Github that have a lot of languages packages ready to go. Definitely you should check it out.

Hope this helps.

Solution 2 - Php

The correct answer to this particular problem would be to go to your app/lang folder and edit the validation.php file at the bottom of the file there is an array called attributes:

/*
|--------------------------------------------------------------------------
| Custom Validation Attributes
|--------------------------------------------------------------------------
|
| The following language lines are used to swap attribute place-holders
| with something more reader friendly such as E-Mail Address instead
| of "email". This simply helps us make messages a little cleaner.
|
*/

'attributes' => array(
    'username' => 'The name of the user',
    'image_id' => 'The related image' // if it's a relation
),

So I believe this array was built to customise specifically these attribute names.

Solution 3 - Php

Since Laravel 5.2 you could...

public function validForm(\Illuminate\Http\Request $request)
{
    $rules = [
        'first_name' => 'max:130'
    ];  
    $niceNames = [
        'first_name' => 'First Name'
    ]; 
    $this->validate($request, $rules, [], $niceNames);

    // correct validation 

Solution 4 - Php

In the "attributes" array the key is the input name and the value is the string you want to show in the message.

An example if you have an input like this

 <input id="first-name" name="first-name" type="text" value="">

The array (in the validation.php file) should be

 'attributes' => array(
	'first-name' => 'Voornaam'),

I tried the same thing and it works great. Hope this helps.

EDIT

Also I am noticing you don't pass a parameter to $errors->has() so maybe that's the problem.

To fix this check out in the controller if you have a code like this

return Redirect::route('page')->withErrors(array('register' => $validator));

then you have to pass to the has() method the "register" key (or whatever you are using) like this

@if($errors->has('register')
.... //code here
@endif

Another way to display error messages is the following one which I prefer (I use Twitter Bootstrap for the design but of course you can change those with your own design)

 @if (isset($errors) and count($errors->all()) > 0)
 <div class="alert alert-error">
    <h4 class="alert-heading">Problem!</h4>
     <ul>
        @foreach ($errors->all('<li>:message</li>') as $message)
         {{ $message }}
       @endforeach
    </ul>
</div>

Solution 5 - Php

In Laravel 4.1 the easy way to do this is go to the lang folder -> your language(default en) -> validation.php.

When you have this in your model, for example:

'group_id' => 'Integer|required',
'adult_id' => 'Integer|required',

And you do not want the error to be "please enter a group id", you can create "nice" validation messages by adding a custom array in validation.php. So in our example, the custom array would look like this:

'custom' => array(
    'adult_id' => array(
        'required' => 'Please choose some parents!',
	),
    'group_id' => array(
        'required' => 'Please choose a group or choose temp!',
    ),
),

This also works with multi-language apps, you just need to edit (create) the correct language validation file.

The default language is stored in the app/config/app.php configuration file, and is English by default. This can be changed at any time using the App::setLocale method.

More info to both errors and languages can be found here validation and localization.

Solution 6 - Php

In Laravel 7.

use Illuminate\Support\Facades\Validator;

Then define niceNames

$niceNames = array(
   'name' => 'Name',
);

And the last, just put $niceNames in fourth parameter, like this:

$validator = Validator::make($request->all(), $rules, $messages, $niceNames);

Solution 7 - Php

I use my custom language files as Input for the "nice names" like this:

$validator = Validator::make(Input::all(), $rules);
$customLanguageFile = strtolower(class_basename(get_class($this)));

// translate attributes
if(Lang::has($customLanguageFile)) {
    $validator->setAttributeNames($customLanguageFile);
}

Solution 8 - Php

$customAttributes = [
'email' => 'email address',
];

$validator = Validator::make($input, $rules, $messages, $customAttributes);

Solution 9 - Php

The :attribute can only use the attribute name (first_name in your case), not nice names.

But you can define custom messages for each attribute+validation by definine messages like this:

$messages = array(
  'first_name_required' => 'Please supply your first name',
  'last_name_required' => 'Please supply your last name',
  'email_required' => 'We need to know your e-mail address!',
  'email_email' => 'Invalid e-mail address!',
);

Solution 10 - Php

Well, it's quite an old question but I few I should point that problem of having the language appearing at the URL can be solved by:

  • Changing the language and fallback_language at config/app.php;
  • or by setting \App::setLocale($lang)

If needed to persist it through session, I currently use the "AppServiceProvider" to do this, but, I think a middleware might be a better approach if changing the language by URL is needed, so, I do like this at my provider:

    if(!Session::has('locale'))
    {
        $locale = MyLocaleService::whatLocaleShouldIUse();
        Session::put('locale', $locale);
    }

    \App::setLocale(Session::get('locale'));

This way I handle the session and it don't stick at my url.

To clarify I'm currently using Laravel 5.1+ but shouldn't be a different behavior from 4.x;

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionHakView Question on Stackoverflow
Solution 1 - PhpJavier CadizView Answer on Stackoverflow
Solution 2 - PhpLogus GraphicsView Answer on Stackoverflow
Solution 3 - PhpShirleyCCView Answer on Stackoverflow
Solution 4 - PhpAltrimView Answer on Stackoverflow
Solution 5 - PhpJohn SmithView Answer on Stackoverflow
Solution 6 - PhpWahyu KodarView Answer on Stackoverflow
Solution 7 - PhpJan SchwingneschlöglView Answer on Stackoverflow
Solution 8 - PhpTalha MasoodView Answer on Stackoverflow
Solution 9 - PhpAlexandre DanaultView Answer on Stackoverflow
Solution 10 - PhpVictor MouraView Answer on Stackoverflow