Localization (i18n)
This guide only addresses generating error messages for globally defined validators using vee-validate’s own @vee-validate/i18n
plugin.
If you are using vee-validate with yup, then you should check out yup’s localization guide. If you are using another library for data validation, check their i18n capabilities.
Global Message Generator
vee-validate exposes a global config called generateMessage
which is a function that should return a string. Whenever any globally defined rule returns a falsy value the generateMessage
will be called and its result will be used as an error message for that rule.
The message generator function has the following type:
tsinterface FieldContext {
field: string; // The field's name or label (see next section)
value: any; // the field's current value
form: Record<string, any>; // other values in the form
rule: {
name: string; //the rule name
params?: any[]; // any params sent to it
};
}
type ValidationgenerateMessage = (ctx: FieldContext) => string;
With this information, you could create message handlers with any kind of 3rd party libraries. To register a message generator use the configure
function exposed by vee-validate:
jsimport { configure } from 'vee-validate';
configure({
generateMessage: context => {
return `The field ${context.field} is invalid`;
},
});
Custom Labels
If you want to display different field names in your error messages, the <Field />
component accepts a label
prop which allows you to display better names for your fields in their generated messages. Here is an example:
vue<Form>
<Field name="_bad_field_name" label="nice name" rules="required|email" />
<ErrorMessage name="_bad_field_name" />
</Form>
The generated message will use nice name
instead of the badly formatted one.
Using @vee-validate/i18n
Overview
The @vee-validate/i18n
contains a simple message generator function that you can use to generate localized messages from JSON objects:
First, you need to install the @vee-validate/i18n
package:
shyarn add @vee-validate/i18n
# or with npm
npm install @vee-validate/i18n
Import the localize()
function from @vee-validate/i18n
which returns a message generator function:
jsimport { defineRule, configure } from 'vee-validate';
import { required } from '@vee-validate/rules';
import { localize } from '@vee-validate/i18n';
// Define the rule globally
defineRule('required', required);
configure({
// Generates an English message locale generator
generateMessage: localize('en', {
messages: {
required: 'This field is required',
},
}),
});
If you have multiple locales in your application, you can add them like this:
jsimport { defineRule, configure } from 'vee-validate';
import { required } from '@vee-validate/rules';
import { localize } from '@vee-validate/i18n';
// Define the rule globally
defineRule('required', required);
configure({
generateMessage: localize({
en: {
messages: {
required: 'This field is required',
},
},
ar: {
messages: {
required: 'هذا الحقل مطلوب',
},
},
}),
});
You can change the locale using setLocale
function exported by the @vee-validate/i18n
anywhere in your application:
jsimport { setLocale } from '@vee-validate/i18n';
setLocale('ar');
To save you a lot of time translating @vee-validate/rules
messages to your language, the awesome community around vee-validate already contributed over 40+ languages that you can use directly in your application and get started quickly. The localized files include localized messages for all the global rules provided by @vee-validate/rules package.
You can import the needed locale from the @vee-validate/i18n/dist/locale/{localeCode}.json
and they can be passed directly to the localize function. This snippet adds the English and Arabic localized messages for all the rules of @vee-validate/rules
package into the message generator function:
jsimport { configure } from 'vee-validate';
import { localize } from '@vee-validate/i18n';
import en from '@vee-validate/i18n/dist/locale/en.json';
import ar from '@vee-validate/i18n/dist/locale/ar.json';
configure({
generateMessage: localize({
en,
ar,
}),
});
Localizing Field Names
To localize the field name with the @vee-validate/i18n
package, you can add a names
property to your dictionaries containing the translated names of the fields.
jsimport { configure } from 'vee-validate';
import { localize } from '@vee-validate/i18n';
configure({
generateMessage: localize({
en: {
names: {
age: 'Age',
},
},
ar: {
age: 'السن',
},
}),
});
Then whenever a message is generated for a global rule, vee-validate will try to match the field name with the names
property found in the active locale.
This is such an example:
Custom messages for specific fields
You may want to override specific rule messages for specific fields, you can do this by calling localize
with the specific messages object:
jsimport { localize } from '@vee-validate/i18n';
localize('en', {
fields: {
password: {
required: 'Hey! Password cannot be empty',
},
},
});
// Or update multiple languages
localize({
en: {
fields: {
password: {
required: 'Hey! Password cannot be empty',
},
},
},
});
You can call localize
anywhere in your component initialization, ideally before any error is generated so either mounted
or setup
should be safe to call localize
.
Placeholder Interpolation
Your messages can be more complex than required
, for example a between
rule would need access to the params values to be able to produce a meaningful error message, the @vee-validate/i18n
plugin comes with interpolation support for various placeholders, consider this example:
jsimport { defineRule, configure } from 'vee-validate';
import { between } from '@vee-validate/rules';
import { localize } from '@vee-validate/i18n';
// Define the rule globally
defineRule('between', between);
configure({
// Generates an English message locale generator
generateMessage: localize('en', {
messages: {
between: 'The {field} value must be between 0:{min} and 1:{max}',
},
}),
});
The {field}
placeholder will be replaced with the field name, and 0:{min}
and 1:{max}
will be replaced with the rule arguments. Note that the indices that prefix each param name are recommended because the interpolation will need to know the order of the arguments because you may define your global rules in one of object
or array
or string
formats, and thus the interpolation process needs to know both argument names and their order if array params or strings are used.
You can also interpolate the other fields in the form by using their names as placeholders.
Here is an example that show cases interpolation for different cases:
Custom Interpolation Prefix and Suffix
You also have the ability to customize the prefix
and suffix
of the interpolated values, by default they are {
and }
respectively.
Configure them by passing a third parameter of InterpolateOptions
to the localize
function:
jsimport { defineRule, configure } from 'vee-validate';
import { between } from '@vee-validate/rules';
import { localize } from '@vee-validate/i18n';
// Define the rule globally
defineRule('between', between);
configure({
// Generates an English message locale generator
generateMessage: localize(
'en',
{
messages: {
// use double `{{` and `}}` i18next-like curly braces for the interpolated values, instead of the default `{` and `}`
between: `The {{field}} field must be between 0:{{min}} and 1:{{max}}`,
},
},
{
prefix: '{{',
suffix: '}}',
},
),
});
Loading Locale From CDN
If you are using Vue.js over CDN, you can still load the locale files without having to copy them to your code, the @vee-validate/i18n
library exposes a loadLocaleFromURL
function that accepts a URL to a locale file.
html<script src="path/to/vee-validate.js"></script>
<script src="path/to/@vee-validate/rules.js"></script>
<script src="path/to/@vee-validate/i18n.js"></script>
<script>
// Install all rules
Object.keys(VeeValidateRules).forEach(rule => {
VeeValidate.defineRule(rule, VeeValidateRules[rule]);
});
// Downloads and merges the locale from URL
VeeValidateI18n.loadLocaleFromURL('https://unpkg.com/@vee-validate/i18n@4.0.2/dist/locale/ar.json');
// Activate the locale
VeeValidate.configure({
generateMessage: VeeValidateI18n.localize('ar'),
});
</script>
Here is an example of the previous snippet: