首先新建 src\locales 目录,编写两个国际化文件。
en-US.json
{
"greeting": "Hello World",
"table": {
"title": "Table Example",
"description": "This is an application"
},
"buttons": {
"toggleLanguage": "Toggle Language"
},
"currentLanguage": "Current Language"
}
zh-CN.json
{
"greeting": "你好,世界",
"table": {
"title": "表格示例",
"description": "这是一个应用"
},
"buttons": {
"toggleLanguage": "切换语言"
},
"currentLanguage": "当前语言"
}
新建 src\utils\i18n.ts 文件,编写国际化配置核心代码。
import { match } from "@formatjs/intl-localematcher";
import { createI18n } from "vue-i18n";
export const i18n = createI18n({
legacy: false,
locale: "zh-CN",
});
/**
* 支持的语言列表
*/
export const SUPPORTED_LOCALES = ["zh-CN", "en-US"];
/**
* localStorage 中存储语言设置的键名
*/
const LOCALE_STORAGE_KEY = "locale";
/**
* 切换全局语言
* @param locale 目标语言区域设置,必须是支持的语言之一
*/
export const switchLanguage = async (locale: string) => {
if (!SUPPORTED_LOCALES.includes(locale)) {
throw new Error(`Unsupported locale: ${locale}`);
}
const { global } = i18n;
switch (locale) {
case "zh-CN":
global.setLocaleMessage(locale, await import("../locales/zh-CN.json"));
break;
case "en-US":
global.setLocaleMessage(locale, await import("../locales/en-US.json"));
break;
}
global.locale.value = locale;
const { documentElement } = document;
documentElement.lang = locale;
localStorage.setItem(LOCALE_STORAGE_KEY, locale);
};
/**
* 根据浏览器语言设置切换到默认语言
* 使用 @formatjs/intl-localematcher 进行标准化的语言匹配
* 优先级:localStorage > 浏览器首选语言 > 浏览器其他语言 > 默认中文
* 支持常见语言变体的智能匹配(如 zh-Hans → zh-CN,en-GB → en-US)
*/
export const switchDefaultLanguage = async () => {
const languages = [...navigator.languages];
const saved = localStorage.getItem(LOCALE_STORAGE_KEY);
if (saved) languages.unshift(saved);
const matched = match(languages, SUPPORTED_LOCALES, "zh-CN");
await switchLanguage(matched);
};
随后即可在 src\main.ts 中使用 switchDefaultLanguage 函数进行初始语言设置。如果用户浏览器默认语言环境是英文,那么初次进入时即切换到英文。
如果使用了 element-plus,那么还需要根据语言环境加载组件库的语言包。
<script setup lang="ts">
import { watchImmediate } from "@vueuse/core";
import dayjs from "dayjs";
import type { Language } from "element-plus/es/locale";
import elLocaleEn from "element-plus/es/locale/lang/en";
import { useI18n } from "vue-i18n";
const { locale } = useI18n();
const elLocale = ref<Language>();
const setElLocale = async (data: Promise<{ default: Language }>) => {
elLocale.value = (await data).default;
};
watchImmediate(locale, async (locale) => {
switch (locale) {
case "zh-CN":
await import("dayjs/locale/zh-cn");
dayjs.locale("zh-cn");
setElLocale(import("element-plus/es/locale/lang/zh-cn"));
break;
case "en-US":
await import("dayjs/locale/en");
dayjs.locale("en");
elLocale.value = elLocaleEn;
break;
}
});
</script>
<template>
<ElConfigProvider :locale="elLocale">
<RouterView />
</ElConfigProvider>
</template>