Laravel validation attributes "nice names"
Asked Answered
T

11

95

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?

Tousle answered 11/6, 2013 at 14:50 Comment(4)
I am not sure if I understand it correctly but you can set the default language in app/config/app.php which will be used by the translation service provider. For each language you need to create the corresponding folder in app/lang/. e.g if you have "en" and "nl" as languages that you use in your app you should have both folders in app/lang/ with the corresponding files (in this example validation.php) so whenever you change the language, that file will be loaded. As for removing the language from the url I am not entirely sure but I believe you can achieve that with the routes.Finding
I know how to set the languages and translating the input names is working now. I only need to know how to remove the language from the url. I'll search for that. Thanks!Tousle
Definitely this can be done, see my answer below.Dumbhead
but it's for 5.3 https://mcmap.net/q/225003/-laravel-language-on-auth-validation-errorKlystron
D
161

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.

'attributes' => array('first_name' => 'First Name')
  1. 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

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

    return $this;
}

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

$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.

Dumbhead answered 17/12, 2013 at 11:34 Comment(5)
There is a problem with global solution: in one form I might have 'name' => 'Customer name' and in another form it might be 'name'=>'Seller name'. I prefer to have my translations per module, so I can reuse these values also as labels for form fields. Hence, I vote for local solution, but then how do I retrieve that $niceNames array from my language file? And how do I call setAttributeNames without creating a new Validator instance but using $this->validate() method which is available in controllers?Behn
In response to this comment and to complete the solution of @javiercadiz, since Laravel 5.1 you can use a fourth parameter in $this->validate(Request $request, $rules, $messages, $customAttributes) to have those nice names. See it in Laravel 5.1 API - Validate RequestGrueling
Where do you put the code in the last option? I mean this part: $validator = Validator::make(Input::all(), $rules); $validator->setAttributeNames($niceNames);Sibie
By the way, if you're using the "locally" solution, you can load the attribute names from a language file like this: $validator->setAttributeNames(Lang::get('my-language-file')).Feoffee
See laravel.com/docs/8.x/… and laravel.com/api/8.x/Illuminate/Foundation/Http/…Calvados
M
44

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.

Mite answered 19/1, 2016 at 15:15 Comment(3)
This is best answer to make responses in spanish 'attributes' => [ 'name' => 'nombre', 'mail' => 'correo', 'password' => 'contraseña', 'password2' => 'confirmación de contraseña', ],Apostrophize
Works in Laravel 5.6Vulcanize
This is working fine for me Laravel 10.xHypotaxis
K
33

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 
Knobby answered 22/3, 2016 at 14:42 Comment(0)
F
8

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>
Finding answered 11/6, 2013 at 22:42 Comment(2)
What if the field name is an array? For example, <input type="text" name="txt[]" />". The error will output something like The txt.0 is required.. How can you replace it with nice names?Mattie
@AnnaFortuna Check this post see if it might help you #17974731Finding
M
4

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.

Madian answered 6/2, 2014 at 11:58 Comment(0)
P
4

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);
Prankster answered 4/5, 2020 at 17:34 Comment(0)
R
1

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);
}
Registration answered 23/9, 2016 at 9:57 Comment(0)
S
1
$customAttributes = [
'email' => 'email address',
];

$validator = Validator::make($input, $rules, $messages, $customAttributes);
Straight answered 8/7, 2020 at 22:19 Comment(1)
While this code may provide a solution to problem, it is highly recommended that you provide additional context regarding why and/or how this code answers the question. Code only answers typically become useless in the long-run because future viewers experiencing similar problems cannot understand the reasoning behind the solution.Attested
D
0

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!',
);
Dissuasive answered 11/6, 2013 at 15:17 Comment(0)
T
-1

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;

Thao answered 10/6, 2016 at 2:26 Comment(0)
P
-1

if you have dynamic inputs and you validate your data inside Controller like this, then you can use $request->validate($rules, [], $attributes);

public function submitForm(Form $form, Request $request){

    $rules=[];
    $attributes = [];
        foreach($form->fields as $field){
            $rules[$field['name']] = $field['rules'] ?? '';
           
            $attributes[$field['name']] = $field["BeautifulName"] ?? $field['name'];
        }
    $request->validate($rules, [], $attributes);
}
Professorate answered 15/6, 2023 at 23:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.