最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Vue-i18n 与 TypeScript 补全提示
时间:2026-07-15 20:30:01 编辑:袖梨 来源:一聚教程网
Vue-i18n 是 Vue 生态中最流行的国际化方案,但原生对 TypeScript 的类型提示比较有限——默认情况下 $t('key') 的参数是 string,写错 key 也不会报错。本文介绍一种基于 JSON 语言文件 + 模块增强的配置方式,让 IDE 能自动提示所有翻译 key,并在传入不存在的 key 时给出类型报错。

环境准备
本文以 Vue 3 + Vite + TypeScript 项目为例,vue-i18n 版本为 v11.4.6。
项目结构
复制代码root/
│── src/
│ ├── locales/ # 语言文件目录
│ │ ├── index.ts # 语言文件索引(导出所有 locale)
│ │ ├── en-US.json # 英文语言文件
│ │ └── zh-CN.json # 中文语言文件
│ ├── App.vue
│ ├── main.ts
│ ├── global.d.ts # 全局类型声明
│ ├── composables/
│ │ └── useTranslation.ts # 封装 t 函数
├── index.html
├── vite.config.ts
└── package.json
第一步:准备语言文件
语言文件使用 JSON 格式,key 的层级结构决定了后续类型提示的路径。
复制代码// src/locales/en-US.json
{
"message": {
"hello": "Hello World",
"description": "This is a description"
},
"nav": {
"home": "Home",
"about": "About"
}
}
复制代码// src/locales/zh-CN.json
{
"message": {
"hello": "你好世界",
"description": "这是一段描述"
},
"nav": {
"home": "首页",
"about": "关于"
}
}
第二步:导出语言文件索引
创建 src/locales/index.ts,将所有语言文件按 locale key 导出:
复制代码import enUS from './en-US.json'
import zhCN from './zh-CN.json'export default {
'en-US': enUS,
'zh-CN': zhCN
} as const
第三步:全局类型声明
创建 src/global.d.ts,通过模块增强(Module Augmentation)让 vue-i18n 识别你的语言文件结构:
复制代码import type { DefineLocaleMessage } from 'vue-i18n'
import locales from './locales'declare global {
// 将语言文件结构暴露为全局类型,方便在其他地方引用
type MessageSchema = (typeof locales)['en-US']
}// vue-i18n@9+ 模块增强
declare module 'vue-i18n' {
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
interface DefineLocaleMessage extends MessageSchema {}
interface GeneratedTypeConfig {
locale: keyof typeof locales
}
}
关键点解释
DefineLocaleMessage:vue-i18n用来约束翻译消息结构的接口,扩展它就等于把所有语言文件的 key 注入了类型系统。MessageSchema:从locales的'en-US'值推导出的类型,代表了所有翻译 key 的完整结构。GeneratedTypeConfig:约束locale类型,确保只能传入locales中定义的语言(本文中为en-US和zh-CN)。
第四步:初始化 VueI18n 实例
在 main.ts 中初始化 i18n 实例,并传入语言文件:
复制代码import { createApp } from 'vue'
import { createI18n } from 'vue-i18n'
import App from './App.vue'
import locales from './locales'const i18n = createI18n({
legacy: false, // 使用 Composition API 模式
locale: 'zh-CN',
fallbackLocale: 'en-US',
messages: locales
})const app = createApp(App)
app.use(i18n)
app.mount('#app')
第五步:在组件中使用
SFC 模板中使用
复制代码<template>
<!-- IDE 会自动提示 message.hello、message.description、nav.home 等 key -->
<h1>{{ $t('message.hello') }}</h1>
<p>{{ $t('message.description') }}</p>
<nav>
<a href="/">{{ $t('nav.home') }}</a>
<a href="/about">{{ $t('nav.about') }}</a>
</nav>
</template>
TS 脚本中使用
在 <script setup lang="ts"> 中:
复制代码<script setup lang="ts">
const { t } = useI18n()// 有类型提示
const title = t('message.hello')
</script>
进阶:封装 composable 实现严格类型检查
原生 t 函数的参数类型是 string,即使传入不存在的 key 也不会在编译时报错(vue-i18n issue #1116)。可以通过封装一个自定义 useTranslation composable 来进一步限制 key 的类型。
创建 src/composables/useTranslation.ts:
复制代码import type { NamedValue } from 'vue-i18n'
import { useI18n } from 'vue-i18n'// 递归提取对象的所有叶子路径,如 "message.hello"
type PathToLeaves<T, Cache extends string = ''> = T extends PropertyKey
? Cache
: {
[P in keyof T]: P extends string
? Cache extends ''
? PathToLeaves<T[P], `${P}`>
: PathToLeaves<T[P], `${Cache}.${P}`>
: never
}[keyof T]type TranslationPaths = PathToLeaves<MessageSchema>export const useTranslation = () => {
const { t } = useI18n<{ messages: MessageSchema }>() return {
t: <const Path extends TranslationPaths>(path: Path, named?: NamedValue) => (named ? t(path, named) : t(path))
}
}
使用封装后的 t
复制代码<script setup lang="ts">
import { useTranslation } from '@/composables/useTranslation'const { t } = useTranslation()// 正确的 key,有类型提示
const hello = t('message.hello')// 编译报错:类型 '"message.nonexistent"' 不满足 TranslationPaths
// const wrong = t('message.nonexistent')
</script>
通过以上配置,你的 Vue-i18n 就能获得完整的 TypeScript 类型提示,在编译阶段就发现翻译 key 的拼写错误,而不是等到运行时才暴露问题。
相关文章
- 日式rpg游戏合集 2026最受欢迎的日式rpg游戏大盘点 07-15
- 濡沫江湖洛阳郊外隐藏宝箱具体位置一览 07-15
- 暗黑破坏神4怎么堆叠减伤 暗黑破坏神4堆减伤攻略 07-15
- tavo角色卡怎么导入 07-15
- 2026年3-6岁儿童益智游戏APP推荐:寓教于乐的优质之选 07-15
- 魔方还原APP推荐:哪款软件更实用易上手且支持多种魔方类型 07-15