How to Add and Configure Internationalization (i18n) with vue-i18n in Celeris Web
Celeris Web provides a modular i18n system built on vue-i18n that uses LocalesEngine and LocalesConfiguration to load JSON translation files from apps/admin/locales, persist the selected locale in local storage, and expose translation helpers via useI18n() in components.
Celeris Web implements a thin, modular wrapper around vue-i18n that simplifies adding multilingual support to your Vue applications. The system lives in the @celeris/locale package under packages/web/locale and provides a persistent store, asynchronous message loading, and a clean API for runtime locale switching.
Core Architecture and File Structure
The internationalization layer is organized into distinct modules that separate storage, configuration, and Vue plugin initialization:
| File | Responsibility |
|---|---|
packages/web/locale/src/store.ts |
Persists the selected locale in localStorage using LOCALES_STORE_KEY. Exports setLocale and getLocale. |
packages/web/locale/src/config.ts |
Defines LocalesConfiguration for mutable settings and LocalesEngine as the static API façade. |
packages/web/locale/src/index.ts |
Creates the vue-i18n instance via createI18n and registers it on the Vue app through setupI18n. |
apps/admin/src/AppConfiguration.ts |
Loads JSON files from apps/admin/locales/*.json using Vite’s import.meta.glob and feeds them to LocalesEngine. |
apps/admin/src/main.ts |
Bootstraps the application and invokes setupI18n(app) after configuration initialization. |
Component files (e.g., Menu.vue) |
Consume translations using useI18n() from vue-i18n. |
Configuration Flow and Initialization
The system initializes in five distinct phases to ensure translations are available before components render:
-
Locale Persistence —
store.tscreates a reactivegetLocalecomputed property and asetLocalehelper that writes tolocalStorageatpackages/web/locale/src/store.ts. -
Configuration State —
LocalesConfigurationholds the current locale, fallback language, message handler function, and additional vue-i18n options atpackages/web/locale/src/config.ts. -
Static API —
LocalesEngineexposes static methods likeinitLocalesandsetLocalethat delegate to the configuration object atpackages/web/locale/src/config.ts. -
Instance Creation —
setupI18n(app)inpackages/web/locale/src/index.tscallscreateI18nOptions(), which merges defaults (legacy: false, locale from configuration) with user options, creates the i18n instance, and installs it on the Vue app. -
Application Bootstrap —
initializeI18n()inapps/admin/src/AppConfiguration.tspre-loads all translation files, thenmain.tsawaits this initialization before mounting the app atapps/admin/src/main.ts.
Practical Implementation Examples
Loading Translation Messages
In your application configuration file, load JSON files from the locales directory and initialize the engine:
// apps/admin/src/AppConfiguration.ts
import { LocalesEngine } from "@celeris/locale";
function initializeI18n() {
const { getLocale } = useAppSetting();
// Load all JSON files from apps/admin/locales/*.json
const messages = Object.fromEntries(
Object.entries(
import.meta.glob<{ default: any }>("./locales/*.json", { eager: true })
).map(([key, value]) => [key.slice(10, -5), value.default])
);
// Feed the data to the engine
LocalesEngine.initLocales(() => ({
locale: getLocale.value,
fallbackLocale: "en",
messagesHandler: () => messages,
otherOptions: {
sync: true,
availableLocales: Object.keys(messages),
silentTranslationWarn: true,
missingWarn: false,
silentFallbackWarn: true,
},
}));
}
Initializing the i18n Instance
The setupI18n function creates the vue-i18n instance with merged options:
// packages/web/locale/src/index.ts
import { createI18n } from "vue-i18n";
import { deepMerge } from "@celeris/utils";
import { LocalesConfiguration } from "./config";
export let i18n: ReturnType<typeof createI18n>;
async function createI18nOptions() {
return deepMerge(
{
legacy: false,
locale: LocalesConfiguration.locale,
fallbackLocale: LocalesConfiguration.fallbackLocale,
messages: await LocalesConfiguration.messagesHandler(),
},
LocalesConfiguration.otherOptions
);
}
export async function setupI18n(app) {
const options = await createI18nOptions();
i18n = createI18n(options);
app.use(i18n);
}
Consuming Translations in Components
Any Vue component can access translations using the useI18n composable:
<script setup lang="ts">
import { useI18n } from "vue-i18n";
const { te, t } = useI18n();
function i18nRender(key: string) {
// Return the translated string if it exists, otherwise the key itself
return te(key) ? t(key) : key;
}
</script>
<template>
<span>{{ i18nRender('menu.dashboard') }}</span>
</template>
Runtime Locale Switching
Change the active language and persist the selection using the engine API:
import { LocalesEngine } from "@celeris/locale";
// Switch to Chinese
LocalesEngine.setLocale("zh-CN");
// Updates localStorage and reconfigures the i18n instance automatically
Summary
- Persistence: The locale store in
store.tsmaintains the user's language preference in localStorage usingLOCALES_STORE_KEY. - Configuration:
LocalesConfigurationandLocalesEngineprovide a type-safe, centralized API for managing i18n settings and switching languages at runtime. - Loading: Translation files are loaded via
import.meta.globinAppConfiguration.ts, making them available synchronously during app bootstrap. - Integration: The
setupI18nfunction registers the vue-i18n instance on the Vue app only after messages are fully loaded, preventing translation flashes. - Usage: Components consume translations through standard
useI18n()from vue-i18n, with helper patterns likei18nRenderfor fallback handling.
Frequently Asked Questions
How do I add a new language to a Celeris Web application?
Create a new JSON file in apps/admin/locales (e.g., fr.json for French), add your translation key-value pairs, and restart the development server. The import.meta.glob pattern in AppConfiguration.ts automatically picks up new files and adds them to availableLocales.
Where does Celeris Web store the user's selected language?
The selected locale is persisted in the browser's localStorage under the key defined by LOCALES_STORE_KEY in packages/web/locale/src/store.ts. The setLocale function updates this value and the reactive getLocale computed property.
How can I change the fallback locale from English to another language?
Modify the fallbackLocale property passed to LocalesEngine.initLocales in apps/admin/src/AppConfiguration.ts. Change the string "en" to your preferred fallback language code (e.g., "zh-CN").
What is the purpose of the LocalesEngine class?
LocalesEngine acts as a static façade that exposes high-level methods like initLocales and setLocale. It delegates to the mutable LocalesConfiguration object, allowing the application to configure and control the i18n system without directly manipulating vue-i18n internals.
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 →