How to Build a **Vue.js Quiz Application** with **vue-i18n** Multi-Language Support
You can build a multilingual Vue.js quiz application by initializing vue-i18n in your entry file, consolidating translation files by language in a centralized index, and accessing localized quiz data through the $t helper in components.
The microsoft/AI-For-Beginners repository demonstrates a production-ready implementation of a Vue.js quiz application with vue-i18n multi-language support inside the etc/quiz-app/ directory. This Vue 2 project structures quiz content as language-agnostic data objects, allowing the entire interface to switch locales at runtime without reloading.
Initializing the vue-i18n Plugin in Vue 2
The first step wires the internationalization library into the Vue instance. In src/main.js, the code imports VueI18n, registers it with Vue.use(), and creates a new instance defining English as both the default and fallback locale.
// src/main.js
import Vue from 'vue';
import App from './App.vue';
import router from './router';
import VueI18n from 'vue-i18n';
Vue.use(VueI18n);
const i18n = new VueI18n({
locale: 'en', // default language
fallbackLocale: 'en', // fallback language
});
new Vue({ i18n, router, render: h => h(App) }).$mount('#app');
According to the source code at etc/quiz-app/src/main.js (lines 6-14), passing the i18n object to the root Vue constructor injects the translation functionality into every child component.
Organizing Translation Files for Multi-Language Quizzes
Creating the Translation Index
All language packs are aggregated in src/assets/translations/index.js. This file imports quiz data from each language folder and exports a single messages object that maps locale codes to their respective content.
// src/assets/translations/index.js
import englishQuizzes from './en';
import spanishQuizzes from './es';
const messages = {
en: englishQuizzes,
es: spanishQuizzes,
};
export default messages;
This index file is imported into main.js and fed directly into the VueI18n constructor, making the entire message catalog available application-wide.
Defining Language-Specific Quiz Content
Inside each language folder (e.g., src/assets/translations/en/ and src/assets/translations/es/), an index.js exports an identical data structure containing quiz titles, questions, options, and correct answers. Because the schema is consistent across languages, switching the locale key automatically swaps the content while preserving component logic.
// src/assets/translations/en/index.js
export default {
quizTitle: 'JavaScript Basics',
questions: [
{
id: 1,
text: 'What does `===` compare?',
options: [
{ label: 'Value only', value: 'value' },
{ label: 'Type only', value: 'type' },
{ label: 'Both value and type', value: 'both' },
],
answer: 'both',
},
// …more questions
],
};
The Spanish translation follows the same pattern, ensuring that this.$t('questions') always returns an array the component can iterate over, regardless of the active language.
Rendering Localized Content in Components
Components consume translations via the $t() method injected by vue-i18n. Templates reference keys directly, while computed properties can cache complex objects like the full questions array.
<!-- Quiz.vue -->
<template>
<section>
<h1>{{ $t('quizTitle') }}</h1>
<div v-for="q in questions" :key="q.id" class="question">
<p>{{ q.text }}</p>
<ul>
<li v-for="opt in q.options" :key="opt.value">
<label>
<input type="radio" :name="q.id" :value="opt.value" />
{{ opt.label }}
</label>
</li>
</ul>
</div>
</section>
</template>
<script>
export default {
name: 'Quiz',
computed: {
title() { return this.$t('quizTitle'); },
questions() { return this.$t('questions'); },
},
};
</script>
Because the quiz data is structured as a nested object rather than flat strings, components can loop through $t('questions') and access properties like q.text and opt.label that automatically reflect the current locale.
Implementing Runtime Language Switching
Users can switch languages without page reloads by mutating the $i18n.locale property. A language selector component calls a method that updates this value, triggering reactive updates in all components using $t.
// LanguageSwitcher.vue
export default {
methods: {
setLanguage(lang) {
this.$i18n.locale = lang;
},
},
};
As implemented in the microsoft/AI-For-Beginners source code, this approach works because the translation objects in src/assets/translations/ share identical keys and data shapes, allowing Vue's reactivity system to swap content seamlessly.
Configuring Vue Router for i18n Compatibility
The routing setup in src/router/index.js uses a standard Vue-Router configuration without special internationalization handling. Since all text lookups occur through the global $i18n instance, routes remain agnostic to the current language. The source file at etc/quiz-app/src/router/index.js demonstrates this pattern, separating navigation logic from translation concerns.
Summary
- Initialize vue-i18n in
src/main.jsby registering the plugin, creating aVueI18ninstance withlocaleandfallbackLocalesettings, and injecting it into the root Vue constructor. - Structure translations by creating language folders inside
src/assets/translations/and aggregating them via anindex.jsthat exports amessagesobject. - Mirror data shapes across all language files so that switching locales updates content without breaking component logic.
- Access translations in components using the
$t()method, which reacts to locale changes automatically. - Switch languages at runtime by assigning a new value to
this.$i18n.localein any component method.
Frequently Asked Questions
How does vue-i18n handle missing translations in a Vue.js quiz application?
When creating the VueI18n instance in src/main.js, the fallbackLocale: 'en' parameter ensures that if a specific key is missing in the active language, vue-i18n displays the English equivalent instead of throwing an error or displaying raw keys.
What is the recommended file structure for storing multi-language quiz data?
The microsoft/AI-For-Beginners repository organizes files under src/assets/translations/ with subdirectories for each locale (e.g., en/, es/). Each subdirectory contains an index.js exporting identically structured quiz objects, while the parent directory contains an index.js that aggregates these exports into the messages object consumed by vue-i18n.
Can users switch quiz languages without losing their progress or reloading the page?
Yes. Because the quiz data structure is identical across all locales, changing this.$i18n.locale triggers Vue's reactivity system to update all $t() bindings instantly. The application state (such as selected answers) remains intact because the component logic persists while only the displayed text changes.
How are translation messages loaded into the vue-i18n instance?
The messages object exported from src/assets/translations/index.js is imported into src/main.js and passed to the VueI18n constructor as configuration. This wires all language packs into the application at bootstrap time, making them immediately available via the $t helper throughout the component tree.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →