Laravel验证属性的“nice names”

95
我想使用 "language > {language} > validation.php" 中的验证属性,用正确易懂的名称替换 :attribute 名称(输入名称)(例如:first_name > 名字),使用起来似乎非常简单,但是验证器没有显示出“好看的名称”。
我有以下代码:
'attributes' => array(
    'first_name' => 'voornaam'
  , 'first name' => 'voornaam'
  , 'firstname'  => 'voornaam'
);

用于显示错误:

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

还有控制器中的验证:

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

$messages 数组:

$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.'
);

请问我做错了什么?我希望在属性数组(language)中用“漂亮的名字”替换掉:attribute名称。

谢谢!

编辑:

我发现问题在于我没有为我的Laravel项目设置默认语言。当我将语言设置为'NL'时,上面的代码可以正常工作。但是,当我设置我的语言时,语言会出现在URL中。而我希望它不会出现在那里。

所以我的下一个问题是:是否可能从URL中删除语言,或者设置默认语言,使其不会显示在那里?


我不确定我是否理解正确,但您可以在app/config/app.php中设置默认语言,该语言将由翻译服务提供商使用。对于每种语言,您需要在app/lang/中创建相应的文件夹。例如,如果您在应用程序中使用“en”和“nl”作为语言,则应该在app/lang/中拥有这两个文件夹,并带有相应的文件(在此示例中为validation.php),因此无论何时更改语言,该文件都将被加载。至于从URL中删除语言,我不是完全确定,但我认为您可以通过路由来实现。 - Altrim
我知道如何设置语言并且翻译输入名称现在已经可以了。我只需要知道如何从URL中删除语言。我会去搜索一下。谢谢! - Hak
肯定可以做到,见下面我的答案。 - Javier Cadiz
但它适用于5.3版本。http://stackoverflow.com/a/41904035/1076753 - Vixed
11个回答

160

嗯,正如你所说的,“漂亮名称”属性在几个月前确实是一个真正的“问题”。

幸运的是,这个功能现在已经实现了,并且非常容易使用。

为了简化,我将分成两个选项来解决这个问题:

  1. 全局可能更普遍。 这种方法在这里有很好的解释,但基本上您需要编辑应用程序/语言/XX/validation.php 验证文件,其中XX是您将用于验证的语言。

在底部,您将看到一个属性数组; 那将是您的“漂亮名称”属性数组。 按照你的例子,最终结果将是这样的。

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

    'attributes' => array('first_name' => 'First Name')
  1. 本地化 这就是 Taylor Otwell 在这个 问题 中所讲的:

您现在可以在 Validator 实例上调用 setAttributeNames。

这是完全有效的,如果您查看 源代码,就会发现

<!-- 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); 

资源

Github上有一个非常棒的仓库,其中包含了很多已经准备好的语言包。你一定要去看看。


2
全局解决方案存在问题:在一个表单中我可能会有 'name' => 'Customer name',而在另一个表单中它可能是 'name'=>'Seller name'。我更喜欢按模块进行翻译,这样我就可以将这些值重用为表单字段的标签。因此,我赞成使用本地解决方案,但是如何从我的语言文件中检索$niceNames数组呢?并且如何调用 setAttributeNames 而不是创建一个新的验证器实例,而是使用控制器中可用的 $this->validate() 方法? - JustAMartin
3
为了回应这篇评论并完善@javiercadiz的解决方案,自Laravel 5.1起,您可以在$ this-> validate(Request $ request,$ rules,$ messages,$ customAttributes)中使用第四个参数来指定可读性更高的名称。请参见Laravel 5.1 API-验证请求 - Fran Arjona
在最后一个选项中,您将代码放在哪里?我的意思是这部分: $validator = Validator :: make(Input :: all(),$ rules); $validator->setAttributeNames($niceNames); - Jenthe
顺便提一下,如果您正在使用“本地”解决方案,可以像这样从语言文件中加载属性名称:$validator->setAttributeNames(Lang::get('my-language-file')) - orrd
请参阅 https://laravel.com/docs/8.x/validation#specifying-attribute-in-language-files 和 https://laravel.com/api/8.x/Illuminate/Foundation/Http/FormRequest.html#method_attributes。 - Ken

44

这个问题的正确答案是进入你的app/lang文件夹,编辑底部的validation.php文件,在那里有一个叫做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
),

所以我认为这个数组是为了定制这些属性名称而构建的。


3
这是用西班牙语回复的最佳答案:'attributes' => [ 'name' => '姓名', 'mail' => '电子邮件', 'password' => '密码', 'password2' => '确认密码', ], - user1817927
1
适用于Laravel 5.6。 - Yevgeniy Afanasyev
这对我来说运行得很好,Laravel 10.x。 - undefined

33

自 Laravel 5.2 版本以来,您可以...

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

    // correct validation 

8
在 "attributes" 数组中,键是输入名称,值是您想在消息中显示的字符串。
例如,如果您有一个如下所示的输入:
 <input id="first-name" name="first-name" type="text" value="">

数组(在validation.php文件中)应该是:

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

我尝试了同样的方法,效果很好。希望这可以帮到你。

编辑

另外,我注意到你没有向$errors->has()传递参数,可能这就是问题所在。

要解决这个问题,请在控制器中检查是否有以下代码:

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

然后你需要将 "register" 键(或你使用的任何键)传递给 has() 方法,像这样:

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

另一种显示错误信息的方式是我更喜欢的方式(我使用Twitter Bootstrap进行设计,但当然您可以用自己的设计替换它们)

 @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>

1
如果字段名是一个数组,怎么办?例如 <input type="text" name="txt[]" />。错误会输出类似于 The txt.0 is required. 的内容。你该如何用良好的名称替换它? - Anna Fortuna
@AnnaFortuna 请查看此帖子,看看它是否能帮到您:https://dev59.com/IXXYa4cB1Zd3GeqP2iHe - Altrim
谢谢@Altrim,我会去看看。 - Anna Fortuna

4
在Laravel 4.1中,做到这一点的简单方法是进入lang文件夹 -> 您的语言(默认为en)-> validation.php。
例如,在您的模型中有这个:
'group_id' => 'Integer|required',
'adult_id' => 'Integer|required',

如果你不想看到错误提示信息为“请输入组ID”,你可以在validation.php中添加一个自定义数组来创建“友好”的验证消息。 因此,在我们的示例中,自定义数组将如下所示:
'custom' => array(
    'adult_id' => array(
        'required' => 'Please choose some parents!',
    ),
    'group_id' => array(
        'required' => 'Please choose a group or choose temp!',
    ),
),

这对多语言应用程序也适用,您只需要编辑(创建)正确的语言验证文件。

默认语言存储在app/config/app.php配置文件中,默认为英语。 这可以使用App::setLocale方法随时更改。

有关错误和语言的更多信息,请访问validationlocalization


4
在 Laravel 7 中。
use Illuminate\Support\Facades\Validator;

然后定义好 niceNames

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

最后,只需在第四个参数中放置$niceNames,就像这样:

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

1
我使用自定义的语言文件作为“友好名称”输入,格式如下:

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

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

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

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

7
虽然这段代码可能提供了问题的解决方案,但强烈建议您提供关于为什么和/或如何回答问题的额外上下文信息。仅有代码的答案通常在长期内变得无用,因为未来的观众无法理解解决方案背后的推理。 - E. Zeytinci

0

在这种情况下,:attribute 只能使用属性名称(在您的情况下为 first_name),而不能使用友好名称。

但是,您可以通过定义以下消息来为每个属性+验证定义自定义消息:

$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!',
);

-1

嗯,这是一个相当旧的问题,但我认为我应该指出通过以下方式解决在 URL 上显示语言的问题:

  • 更改config/app.php中的语言和fallback_language;
  • 或者通过设置\App::setLocale($lang)

如果需要通过会话保持它,则我目前使用“AppServiceProvider”来实现此目的,但是,如果需要通过 URL 更改语言,则中间件可能是更好的方法,因此,我像这样在我的提供程序中执行:

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

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

我是用这种方式处理会话的,它不会停留在我的 URL 上。

为了澄清,我目前使用的是 Laravel 5.1+,但与 4.x 的行为应该没有区别。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接