Element: [Bug Report] Default validations errors from `async-validator` cannot be translated

Created on 13 Dec 2017  ·  10Comments  ·  Source: ElemeFE/element

Element UI version

1.4.12

OS/Browsers version

all

Vue version

2.5.10

Reproduction Link

https://jsfiddle.net/gorghoa/mmx38qxw/108/

Steps to reproduce

Create a form setup with validation, add a el-form-item component, without rules, but with the required attribute:

<el-form-item prop="tada" required>…</el-form-item>

What is Expected?

I expect my default message item is required to be translated in the configured element locale.

What is actually happening?

When validation has passed the following message appear : tada is required. This message cannot be i18zed..

Please note that I am aware I can use a specific rule with custom error message for each of my required fields, but it could lead to potential inconsistency between my errors required messages along the app, plus a lot of more rules to be maintained in my codebase (many many forms in here ;) )

discussion not Element bug

Most helpful comment

I think this issue could be fixed here : https://github.com/ElemeFE/element/blob/v2.0.8/packages/form/src/form-item.vue#L187

By applying the method validator.messages(translationsObject); from async-validator, populating this translationsObject with the configured i18n data from element.

Thanks!

All 10 comments

I think this issue could be fixed here : https://github.com/ElemeFE/element/blob/v2.0.8/packages/form/src/form-item.vue#L187

By applying the method validator.messages(translationsObject); from async-validator, populating this translationsObject with the configured i18n data from element.

Thanks!

Note, I’ve said it happens in vue 1.x, because it’s the one I use for now, but I’m 99% sure, by reading the code, that this still happens in v2.0.8

Same issue for me with v2, and hope this could support i18n.

I'm not sure if this should be done in element. The default validation message is provided by async-validator, not element.

At the time being, you can include vue-i18n translated message in custom validator. It's more appropriate than us providing a default which might not suit everyone's taste.

Hi @wacky6, thanks for your answer :+1:

Not asking for a default value here, just a way to configure the instance of async-validator (Moreover, as a element user, I should’nt have to worry about the very existence of async-validator, it’s plain implementation detail).

I understand that a custom validator is doable. But, the prop required is exposed by el-input, hence, I think it kind of fall down to element to provide customization for it. It feels weird to have a feature usable just for a subset of english speaking users, even though it’s just DX…

Have an idea
<el-form-item prop="tada" label='tadaLabel' required>…</el-form-item>
validation fail message tada is required , how view tadaLabel is required? thk~

// override default error message
var Schema = require('async-validate')
  , messages = require('async-validate/messages')
  , descriptor = {
      type: 'object',
      fields: {
        name: {
          type: 'string',
          required: true
        }
      }
    }
  , source = {}
  , schema;

require('async-validate/plugin/all');

// change default message in place
messages.required = '%s is a required field';

schema = new Schema(descriptor);
schema.validate(source, function(err, res) {
  console.dir(res.errors);
});

put this in the main.js may help

import AsyncValidator from 'async-validator'
AsyncValidator.messages.required = '%s is a required field'

@rplees
after checked the async-validator's source

/**
 *  Rule for validating required fields.
 *
 *  @param rule The validation rule.
 *  @param value The value of the field on the source object.
 *  @param source The source object being validated.
 *  @param errors An array of errors that this rule may add
 *  validation errors to.
 *  @param options The validation options.
 *  @param options.messages The validation messages.
 */
function required(rule, value, source, errors, options, type) {
  if (rule.required && (!source.hasOwnProperty(rule.field) || util.isEmptyValue(value, type || rule.type))) {
    errors.push(util.format(options.messages.required, rule.fullField));
  }
} 

a element form rule like can solve

 name: [{fullField: 'name', type: "string", required: true}],

export function newMessages() {
  return {
    'default': 'Validation error on field %s',
    required: '%s is required',
    'enum': '%s must be one of %s',
    whitespace: '%s cannot be empty',
    date: {
      format: '%s date %s is invalid for format %s',
      parse: '%s date could not be parsed, %s is invalid ',
      invalid: '%s date %s is invalid'
    },
    types: {
      string: '%s is not a %s',
      method: '%s is not a %s (function)',
      array: '%s is not an %s',
      object: '%s is not an %s',
      number: '%s is not a %s',
      date: '%s is not a %s',
      boolean: '%s is not a %s',
      integer: '%s is not an %s',
      float: '%s is not a %s',
      regexp: '%s is not a valid %s',
      email: '%s is not a valid %s',
      url: '%s is not a valid %s',
      hex: '%s is not a valid %s'
    },
    string: {
      len: '%s must be exactly %s characters',
      min: '%s must be at least %s characters',
      max: '%s cannot be longer than %s characters',
      range: '%s must be between %s and %s characters'
    },
    number: {
      len: '%s must equal %s',
      min: '%s cannot be less than %s',
      max: '%s cannot be greater than %s',
      range: '%s must be between %s and %s'
    },
    array: {
      len: '%s must be exactly %s in length',
      min: '%s cannot be less than %s in length',
      max: '%s cannot be greater than %s in length',
      range: '%s must be between %s and %s in length'
    },
    pattern: {
      mismatch: '%s value %s does not match pattern %s'
    },
    clone: function clone() {
      var cloned = JSON.parse(JSON.stringify(this));
      cloned.clone = this.clone;
      return cloned;
    }
  };
}

export var messages = newMessages();

we can also copy the message.js from async-validator and change the file to what we want to translate .

import AsyncValidator from 'async-validator'
deepMerge(AsyncValidator.messages , myMessages)

The problem is relevant in 2019.
I found a not very beautiful, but working solution. Just add two triggers. trigger: 'blur'and trigger: 'change'

Hello.

Improving on @algking 's solution, say you copy-paste the default messages to a new file, e.g. custom_validator_messages.js, translate the keys you want and then, in main.js:

import AsyncValidator from 'async-validator'
import {deepMerge} from 'async-validator/es/util'
import messages from './custom_validator_messages'

deepMerge(AsyncValidator.messages, messages)
Was this page helpful?
0 / 5 - 0 ratings

Related issues

yubo111 picture yubo111  ·  3Comments

no5no6 picture no5no6  ·  3Comments

Zhao-github picture Zhao-github  ·  3Comments

yuchonghua picture yuchonghua  ·  3Comments

chao-hua picture chao-hua  ·  3Comments