Vue I18n 完整安装与使用指南

本文档基于 Vue 3 + TypeScript 环境,提供 Vue I18n(国际化插件)的标准化安装、配置、组件内使用及非组件场景适配方案,修复原文档中的路径冲突、类型不匹配等问题,同时补充注释说明与最佳实践。

一、环境准备

确保项目已满足以下依赖版本(Vue 3 专属,Vue 2 需使用 vue-i18n@8.x 版本):

  • Vue:^3.0.0
  • TypeScript(可选但推荐):^4.0.0
  • Vue I18n:^12.0.0-alpha.3(当前最新版)

二、安装 Vue I18n

使用包管理器安装(pnpm/npm/yarn 均可,推荐 pnpm):

bash

csharp 复制代码
# pnpm(推荐,速度快且节省磁盘空间)
pnpm install vue-i18n

# npm
npm install vue-i18n --save

# yarn
yarn add vue-i18n

三、目录结构设计

先创建标准化的国际化目录,避免后续文件散放导致维护困难:

plaintext

bash 复制代码
src/
├── locales/          # 语言包目录(存放各语言的翻译文件)
│   ├── en.ts         # 英文语言包
│   └── zh.ts         # 中文语言包
├── plugins/          # 插件配置目录(集中管理第三方插件)
│   └── i18n.ts       # Vue I18n 实例配置
├── utils/            # 工具函数目录
│   └── i18nUtils.ts  # 国际化工具函数(切换语言、非组件翻译)
└── main.ts           # 项目入口文件(挂载 I18n)

四、配置语言包

locales 目录下创建对应语言的翻译文件,采用「模块 + 键」的命名规范(如 Header.index),便于后续定位和维护。

1. 中文语言包(src/locales/zh.ts)

typescript

javascript 复制代码
// 中文翻译文件:按「页面/组件」划分模块,避免键名冲突
export default {
  // 头部导航模块
  Header: {
    index: '首页',
    about: '关于我们',
    contact: '联系我们'
  },
  // 可扩展其他模块(如首页、商品页等)
  Home: {
    welcome: '欢迎访问我的网站',
    desc: '这是一个 Vue I18n 国际化示例'
  }
} as const; // 添加 as const 让 TypeScript 识别键名,提供类型提示

2. 英文语言包(src/locales/en.ts)

保持与中文包完全一致的键名结构,仅修改值为对应英文翻译:

typescript

css 复制代码
export default {
  Header: {
    index: 'Home',
    about: 'About Us',
    contact: 'Contact Us'
  },
  Home: {
    welcome: 'Welcome to My Website',
    desc: 'This is a Vue I18n Internationalization Demo'
  }
} as const;

五、创建 Vue I18n 实例(插件配置)

plugins/i18n.ts 中初始化 I18n 实例,处理默认语言检测持久化存储等核心逻辑:

typescript

javascript 复制代码
import { createI18n } from 'vue-i18n'; // 从 vue-i18n 导入创建实例的方法
import zh from '@/locales/zh'; // 导入中文语言包(@ 表示 src 目录,需配置 tsconfig.json)
import en from '@/locales/en'; // 导入英文语言包

/**
 * 获取默认语言(优先级:本地存储 > 浏览器默认)
 * @returns 语言标识(zh 或 en)
 */
const getDefaultLanguage = (): 'zh' | 'en' => {
  // 1. 优先读取本地存储(用户之前切换过的语言)
  const savedLang = localStorage.getItem('app_language');
  if (savedLang === 'zh' || savedLang === 'en') {
    return savedLang;
  }

  // 2. 读取浏览器默认语言(如 navigator.language 为 "zh-CN" 则返回 zh)
  const browserLang = navigator.language.toLowerCase();
  if (browserLang.includes('zh')) {
    return 'zh';
  }
  return 'en'; // 默认英文(可根据需求改为 zh) ---如果第二步影响到你的语言,可以把第二点忽略掉
};

// 创建 I18n 实例
const i18n = createI18n({
  legacy: false, // 启用 Vue 3 组合式 API 模式(必须设为 false,否则无法使用 useI18n)
  globalInjection: true, // 全局注入 $t 方法(可在模板中直接使用 {{ $t('key') }})
  locale: getDefaultLanguage(), // 当前使用的语言
  fallbackLocale: 'en', // 翻译失败时的备用语言(避免显示键名)
  messages: { // 语言包映射(键为语言标识,值为对应语言包)
    zh,
    en
  }
});

export default i18n;

六、在入口文件挂载 I18n

main.ts 中导入并挂载 I18n 实例,确保全局可用:

typescript

javascript 复制代码
import { createApp } from 'vue';
import App from './App.vue';
import i18n from '@/plugins/i18n'; // 导入 I18n 实例

// 创建 Vue 应用并挂载 I18n
const app = createApp(App);
app.use(i18n); // 挂载 I18n 插件
app.mount('#app');

七、核心功能:语言切换与工具函数

utils/i18nUtils.ts 中封装语言切换非组件翻译函数,避免重复代码:

typescript

typescript 复制代码
import i18n from '@/plugins/i18n'; // 导入 I18n 实例

/**
 * 切换语言(并持久化到本地存储)
 * @param newLocale 目标语言标识(zh 或 en)
 */
export const switchLanguage = (newLocale: 'zh' | 'en') => {
  try {
    // 1. 更新 I18n 实例的当前语言
    i18n.global.locale.value = newLocale;
    // 2. 持久化到本地存储(下次打开页面仍保持该语言)
    localStorage.setItem('app_language', newLocale);
    console.log(`语言已切换为:${newLocale === 'zh' ? '中文' : '英文'}`);
  } catch (error) {
    console.error('语言切换失败:', error);
  }
};

/**
 * 非组件环境下的翻译函数(如工具类、Store 中使用)
 * @param key 翻译键(如 Header.index)
 * @param values 可选插值参数(如 t('Home.hello', { name: 'Tom' }))
 * @returns 翻译后的文本(失败时返回原键名,避免页面空白)
 */
export const t = (key: string, values?: Record<string, any>): string => {
  try {
    return i18n.global.t(key, values);
  } catch (error) {
    console.error(`翻译失败(键:${key}):`, error);
    return key;
  }
};

八、组件内使用(两种方式)

Vue 3 中推荐使用组合式 APIuseI18n),也支持模板中直接使用全局注入的 $t 方法。

方式 1:组合式 API(推荐,TypeScript 友好)

vue

xml 复制代码
<script setup lang="ts">
import { useI18n } from 'vue-i18n'; // 导入组合式 API
import { switchLanguage } from '@/utils/i18nUtils'; // 导入语言切换函数
import { ref } from 'vue';

// 获取 I18n 实例的核心方法:locale(当前语言)、t(翻译函数)
const { locale, t } = useI18n();

// 示例:用翻译函数定义数据(语言切换时会自动更新)
const navMenu = ref([
  { label: t('Header.index'), path: '/' },
  { label: t('Header.about'), path: '/about' },
  { label: t('Header.contact'), path: '/contact' }
]);

// 切换语言的方法(点击按钮触发)
const handleSwitchLang = () => {
  // 切换为当前语言的对立语言
  const newLang = locale.value === 'zh' ? 'en' : 'zh';
  switchLanguage(newLang);
};
</script>

<template>
  <!-- 1. 直接使用 $t 翻译(全局注入,无需导入) -->
  <h1>{{ $t('Home.welcome') }}</h1>
  <p>{{ $t('Home.desc') }}</p>

  <!-- 2. 使用组合式 API 中的 t 函数定义的数据 -->
  <nav>
    <a v-for="item in navMenu" :key="item.path" :href="item.path">
      {{ item.label }}
    </a>
  </nav>

  <!-- 3. 语言切换按钮 -->
  <button @click="handleSwitchLang">
    {{ locale === 'zh' ? '切换为英文' : 'Switch to Chinese' }}
  </button>
</template>

方式 2:选项式 API(兼容旧代码)

vue

xml 复制代码
<script lang="ts">
import { defineComponent } from 'vue';
import { useI18n } from 'vue-i18n';
import { switchLanguage } from '@/utils/i18nUtils';

export default defineComponent({
  setup() {
    const { locale, t } = useI18n();
    return { locale, t, switchLanguage };
  },
  data() {
    return {
      navMenu: [
        { label: this.t('Header.index'), path: '/' },
        { label: this.t('Header.about'), path: '/about' }
      ]
    };
  },
  methods: {
    handleSwitchLang() {
      const newLang = this.locale === 'zh' ? 'en' : 'zh';
      this.switchLanguage(newLang);
    }
  }
});
</script>

<template>
  <h1>{{ $t('Home.welcome') }}</h1>
  <button @click="handleSwitchLang">切换语言</button>
</template>

九、非组件环境使用(关键场景)

工具类、Vuex/Pinia Store、路由守卫 等非组件环境中,无法使用 useI18n 组合式 API,需使用 i18nUtils.ts 中封装的 t 函数。

示例 1:在 Pinia Store 中使用

typescript

javascript 复制代码
// src/store/modules/menuStore.ts
import { defineStore } from 'pinia';
import { t } from '@/utils/i18nUtils'; // 导入非组件翻译函数

export const useMenuStore = defineStore('menu', {
  state: () => ({
    // 用 t 函数翻译菜单标签(语言切换时需重新获取,或监听语言变化)
    menuList: [
      { label: t('Header.index'), path: '/', icon: 'home' },
      { label: t('Header.about'), path: '/about', icon: 'info' }
    ]
  }),
  actions: {
    // 语言切换后更新菜单(需在切换语言时调用)
    updateMenuAfterLangSwitch() {
      this.menuList = [
        { label: t('Header.index'), path: '/', icon: 'home' },
        { label: t('Header.about'), path: '/about', icon: 'info' }
      ];
    }
  }
});

示例 2:在工具函数中使用

typescript

typescript 复制代码
// src/utils/formatUtils.ts
import { t } from '@/utils/i18nUtils';

/**
 * 格式化提示信息(根据当前语言返回对应文本)
 * @param type 提示类型(success/error)
 * @returns 格式化后的提示文本
 */
export const formatTip = (type: 'success' | 'error'): string => {
  if (type === 'success') {
    return t('Common.successTip'); // 需在语言包中添加 Common 模块
  }
  return t('Common.errorTip');
};

十、常见问题与最佳实践。

1. 如何处理动态插值?

语言包中支持占位符,使用 {} 定义,翻译时传入参数:

typescript

javascript 复制代码
// 语言包(zh.ts)
export default {
  Common: {
    welcomeUser: '欢迎您,{name}!'
  }
} as const;

// 组件中使用
t('Common.welcomeUser', { name: '张三' }); // 输出:欢迎您,张三!

4. 如何支持更多语言?

  • locales 目录下新增语言包(如 ja.ts 日语)。
  • plugins/i18n.tsmessages 中添加新语言映射(ja: ja)。
  • 更新 switchLanguage 函数的类型('zh' | 'en' | 'ja')。

十一、扩展功能(可选)

  • 懒加载语言包 :对于大型项目,可使用 import() 动态加载语言包,减少首屏体积。
  • 语言切换动画:配合 Vue 的过渡动画,实现语言切换时的平滑过渡。
  • HTML 标签支持 :在语言包中使用 {0} 等占位符,支持插入 HTML 元素(需使用 v-html)。

通过以上配置,可实现一套完整、可维护的 Vue 3 国际化方案,满足多语言场景的开发需求。

相关推荐
秋田君2 小时前
Vue3 + VitePress 搭建部署组件库文档平台(结合 Element Plus 与 Arco Design Vue)—— 超详细图文教程
前端·vue.js·arco design
code_Bo2 小时前
前端使用snapdom报错问题
前端·javascript·vue.js
一壶浊酒..3 小时前
什么是AJAX
前端·javascript·ajax
智能化咨询3 小时前
基于Spring Boot + Vue 3的乡村振兴综合服务平台性能优化与扩展实践
vue.js·spring boot·性能优化
fruge3653 小时前
从零到一:我在 Rokid Glasses 上“画”出一个远程协作系统
前端
绝无仅有3 小时前
某大厂跳动Java面试真题之问题与解答总结(五)
后端·面试·github
BumBle3 小时前
高频扫码场景下的去重与接口调用方案
前端·javascript
绝无仅有3 小时前
某大厂跳动Java面试真题之问题与解答总结(四)
后端·面试·github