Vue.js Quiz-App Architecture and vue-i18n Localization in Microsoft AI-For-Beginners

The quiz application is a Vue 2 single-page app that implements a root-component → router → feature-component architecture, using vue-i18n to provide reactive localization through a centralized messages catalog and global $i18n instance.

The microsoft/AI-For-Beginners repository contains a lightweight quiz application designed to test knowledge of AI concepts. Examining the Vue.js quiz-app architecture reveals a classic Vue 2 SPA pattern with clear separation between routing, component hierarchy, and internationalization logic powered by vue-i18n.

Architecture Overview

The application follows a layered architecture pattern that separates concerns between bootstrapping, navigation, and presentation.

Entry Point and Bootstrap

In src/main.js, the application initializes by creating a Vue instance, registering the Vue Router, and injecting a global VueI18n instance before mounting to the DOM.

// src/main.js
import Vue from 'vue';
import VueI18n from 'vue-i18n';
import App from './App.vue';
import router from './router';

Vue.use(VueI18n);

const i18n = new VueI18n({
  locale: 'en',
  fallbackLocale: 'en'
});

new Vue({
  i18n,
  router,
  render: h => h(App)
}).$mount('#app');

This bootstrap sequence establishes the global i18n context that all child components inherit through the Vue instance tree.

Routing Configuration

The router definition in src/router/index.js configures three distinct routes using Vue Router: a home path (/), a dynamic quiz route (/quiz/:id), and a catch-all fallback for 404 errors.

// src/router/index.js
export default new VueRouter({
  routes: [
    { path: '/', component: Home },
    { path: '/quiz/:id', component: Quiz },
    { path: '*', component: NotFound }
  ]
});

Dynamic route parameters (:id) enable the application to render specific quiz content based on the URL, while the fallback route ensures graceful error handling.

Root Component Structure

src/App.vue serves as the root layout container, providing the navigation bar, a locale selector dropdown, and the <router-view> outlet where matched components render. The component implements reactive locale switching through a watcher that propagates changes to the global i18n instance.

// src/App.vue
export default {
  data() {
    return {
      locale: 'en'
    };
  },
  watch: {
    locale(val) {
      this.$root.$i18n.locale = val;
    }
  }
};

The template includes a <select v-model="locale"> element bound to this data property, enabling users to switch languages instantly without page reloads.

Feature Components and Views

The src/components/Quiz.vue file contains the core quiz logic, accessing the current locale via this.$root.$i18n.locale to retrieve localized questions from the messages catalog. Presentation-only views (src/views/Home.vue and src/views/NotFound.vue) handle static page content with minimal logic.

How vue-i18n Handles Localization

The localization system relies on a centralized message catalog with component-level integration and reactive updates.

Global Instance Setup

The VueI18n instance created in main.js establishes the default locale (en) and fallback locale configuration. Unlike typical implementations that pass messages at initialization, this application loads translation data at the component level through the i18n option.

Message Catalog Structure

Translation files reside in src/assets/translations/, organized by language code (e.g., en/, es/). The src/assets/translations/index.js file aggregates these into a single messages object:

// src/assets/translations/index.js
import englishQuizzes from './en';
import spanishQuizzes from './es';

export default {
  en: englishQuizzes,
  es: spanishQuizzes
};

Each language key contains lesson-wise quiz data loaded from JSON files (e.g., lesson-1.json), maintaining a consistent schema across languages.

Component-Level Integration

Both App.vue and Quiz.vue declare an i18n block to register the message catalog locally:

// Inside Quiz.vue
import messages from '../assets/translations';

export default {
  i18n: { messages },
  // ...
};

This pattern allows components to access the raw messages object directly while maintaining the global locale state through $root.$i18n.locale.

Runtime Locale Switching

When users select a different language from the dropdown in App.vue, the watcher updates the global locale property. Quiz.vue reacts to this change through a computed property:

// src/components/Quiz.vue
computed: {
  currLocale() {
    return this.$root.$i18n.locale;
  }
}

The template references questions[currLocale] to render the appropriate language version reactively.

Practical Implementation Examples

Switching Languages Programmatically

To change the active locale from any component method:

this.$root.$i18n.locale = 'es'; // Switch to Spanish

Accessing Translated Strings

While the app primarily accesses raw JSON objects, standard vue-i18n interpolation is available:

<h1>{{ $t('quizTitle') }}</h1>

Adding a New Language

  1. Create a new directory (e.g., src/assets/translations/fr/).

  2. Add JSON files matching the English structure (e.g., lesson-1.json).

  3. Update src/assets/translations/index.js:

import frenchQuizzes from './fr';

export default {
  en: englishQuizzes,
  es: spanishQuizzes,
  fr: frenchQuizzes
};
  1. Add the new option to the locale selector in App.vue.

Summary

  • The quiz app follows a Vue 2 SPA architecture with clear separation between the entry point (src/main.js), router configuration (src/router/index.js), and feature components.
  • vue-i18n initializes with a default locale in main.js, but loads translation catalogs at the component level via the i18n option.
  • Localization data resides in src/assets/translations/, aggregated into a messages object that supports multiple languages including English and Spanish.
  • Reactive locale switching occurs through a watcher in App.vue that updates $root.$i18n.locale, with Quiz.vue accessing the current locale through a computed currLocale property.
  • The architecture supports extending to new languages by adding JSON files and updating the translations index without modifying core application logic.

Frequently Asked Questions

What version of Vue.js does the quiz app use?

The application uses Vue 2, implementing the Options API pattern with data(), computed, and watch properties. The bootstrap process uses new Vue() rather than the Vue 3 createApp factory.

How does the app handle routing for individual quizzes?

The router defines a dynamic route /quiz/:id in src/router/index.js. When navigated, the Quiz.vue component extracts the id parameter from $route.params.id and combines it with currLocale to fetch the specific quiz content from the localized messages object.

Where are the quiz questions stored?

Quiz content resides in JSON files under src/assets/translations/ (e.g., en/lesson-1.json, es/lesson-1.json). These are imported and aggregated by src/assets/translations/index.js into the messages catalog consumed by vue-i18n.

Can I use the $t method instead of raw JSON access?

Yes. While the current implementation accesses messages[currLocale] directly for quiz data, standard vue-i18n methods like $t('key') are available because the component registers the messages object in its i18n configuration. This allows mixing structured quiz data with traditional string translations.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →