DEV Community

Cover image for Creating a Multilingual Registration Form with Vuejs, Vee-validate, and Vue-i18n.
Andrew Zachary
Andrew Zachary

Posted on • Updated on

Creating a Multilingual Registration Form with Vuejs, Vee-validate, and Vue-i18n.

Creating a web form is an essential skill for any web developer. In this post, I will share with you my tools and workflow to create a reliable multilingual web form.

To follow with me, you must be a little bit comfortable with Vuejs basics (like how to create a new app).

Let's go step by step:

Setup

within your vue app:

npm install vee-validate @vee-validate/rules vue-i18n@9
Enter fullscreen mode Exit fullscreen mode

Initialization

1- Create i18n instance with options:

import { createI18n } from 'vue-i18n';

import en from '../../locales/en.json';
import ar from '../../locales/ar.json';

const i18n = createI18n({
    legacy: false,
    locale: 'en',
    fallbackRoot: 'en',
    messages: {en, ar}
});
Enter fullscreen mode Exit fullscreen mode

If you faced this warning message:

You are running the esm-bundler build of vue-i18n. It is recommended to configure your bundler ...

this can be solved by configuring Vite:

resolve: {
  alias: {
    'vue-i18n': 'vue-i18n/dist/vue-i18n.cjs.js'
  }
}
Enter fullscreen mode Exit fullscreen mode

2- Declare vee-validate components (VeeForm and VeeField) as global components within a Vuejs custom plugin to make them available anywhere within the app:

import {
    Form as VeeForm,
    Field as VeeField,
} from 'vee-validate';

export default {
    install(app) {
        app.component('VeeForm', VeeForm);
        app.component('VeeField', VeeField);
    }
}
Enter fullscreen mode Exit fullscreen mode

Next task is to add validation rules, and for that vee-validate offers a wide range of common validators that you can use, they are packaged in @vee-validate/rules.

In order to generate custom validation error messages, vee-validate must be configured through generateMessage property:

import {
    defineRule
    configure
} from 'vee-validate';

import { required, email, confirmed } from '@vee-validate/rules';

export default {
    install(app) {

        ...

        defineRule('required', required);
        defineRule('email', email);
        defineRule('confirmed', confirmed);

        configure({
            generateMessage: (ctx) => {
                const messages = {
                    'required': `${ctx.field}.errors.required`,
                    'email': `${ctx.field}.errors.email`,
                    'confirmed': `${ctx.field}.errors.confirmed`
                };
                return messages[ctx.rule.name]
            }
        });
    }
}
Enter fullscreen mode Exit fullscreen mode

3- Bring everything together here:

import { createApp } from 'vue';
import { createI18n } from 'vue-i18n';

//includes
import veevalidate from './plugins/veevalidate.js';

//locales
import en from '../../locales/en.json';
import ar from '../../locales/ar.json';

import App from '../../components/vue/multilingual-register-form/index.vue';

//parts
const i18n = createI18n({
    legacy: false,
    locale: 'en',
    fallbackRoot: 'en',
    messages: {en, ar}
});

createApp(App).use(i18n).use(veevalidate).mount('#app');
Enter fullscreen mode Exit fullscreen mode

Create the form

1- VeeForm component (vee-form) has a lot of useful props. You can assign a custom validation schema (for example) through the validation-schema prop:

const validationSchema = {
    'name': 'required',
    'email': 'required|email',
    'password': 'required',
    'confirm-password': 'confirmed:@password' 
};
Enter fullscreen mode Exit fullscreen mode

2- VeeField component (vee-field) will wrap a single form input element and make use of the scoped-slots (v-slot) feature to allow you to render complex markup:

<vee-form 
    class="px-4 text-4xl"
    :validation-schema="validationSchema"
    @submit="register"
    v-slot={errors}
>
...
    <div class="mt-8 flex flex-col justify-center">
        <label for="name" class="font-ssp font-bold capitalize">{{ $t(prepForTrans("name.label")) }}</label>
        <vee-field name="name" v-slot="{field, errors}">
            <input type="text" class="p-4 mt-4 border-2 border-black" v-bind="field">
            <div class="font-mont font-bold text-3xl text-red-600 mt-2" v-if="errors.length > 0">
                {{ $t(prepForTrans(errors[0] || "")) }}
            </div>
        </vee-field>
    </div>
...
    <div class="mt-8">
        <button :class="['font-ssp font-bold uppercase p-4 w-full bg-black text-4xl text-white', {'opacity-50 cursor-not-allowed': Object.keys(errors).length}]" type="submit">
            {{ $t(prepForTrans("btns.submit")) }}
        </button>
    </div>

</vee-form>
Enter fullscreen mode Exit fullscreen mode

Full Code
Working Example

Conclusion

VeeValidate is the most popular and powerful Vue.js form library. It takes care of value tracking, validation, errors, submissions, and more. By using it you will be able to create and validate any web form thrown at you.

Your feedback is much appreciated, thank you for reading.

Top comments (0)