开始一个 Nuxt 3 项目
首先,启动一个 Nuxt 项目:
pnpm dlx nuxi@latest init nuxt3-lazy-i18n-demo
cd nuxt3-lazy-i18n-demo
pnpm install
pnpm run dev
添加 nuxt/i18n 模块
然后将 nuxt/i18n 模块添加到项目中:
pnpm dlx nuxi@latest module add i18n
执行完毕后,打开 nuxt.config.ts 文件,确保 "@nuxtjs/i18n" 添加到 modules 中(如果没有的话就手动添加),如下图所示:

本地化语言
添加本地化语言
新建一个 lang 目录,也可以是其他的,用来存放需要支持的语言。其中的文件名便是想要支持的语言,假设要支持中文,可以创建一个 zh.js 或者 zh.ts 文件。
mkdir lang
touch lang/zh.js
Tip
其实文件名可以随意命名,但是为了更好地开发以及后期维护,建议以 bcp47 标准的命名。例如中文为
zh-CN、zh-cn、zh这样。
然后在刚刚新建的 zh.js(或者 zh.ts) 文件里添加一个默认导出:
export default defineI18nLocale(() => {
return {}
})
然后回到 nuxt.config.ts 文件,添加 zh.js,看起来下面这样:
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
devtools: { enabled: true },
modules: ['@nuxtjs/i18n'],
i18n: {
lazy: true,
// langDir 的值是刚刚创建 lang 文件夹名称
langDir: 'lang',
// // 因为默认会去读取浏览器语言,所以如果你的浏览器语言不是 zh,
// // 那么你可能需要添加下面这一行才能在当前浏览器看到效果
// defaultLocale: 'zh',
locales: [
// zh.js 是 lang 目录下的 zh.js 文件
{ code: 'zh', file: 'zh.js', name: '中文' },
],
},
})
本地化语言内容
添加本地化语言内容
需要注意的是,目前 nuxt/i18n 会把 nuxt.config.ts 的 i18n 配置里 locales 选项中没有指定的文件转换到 langDir 选项中指定的目录内。参考:https://github.com/nuxt-modules/i18n/issues/2145
因此如果要在 lang 目录下定义语言内容,在 zh.js 中导入这些语言内容的话,是行不通的。为此,需要将语言内容的文件放在其他地方,不能放在 langDir 选项指定的目录里。
这里可以新建一个 locales 目录,将语言内容放在这个目录下。这里假设 zh 语言有很多内容,以至于我们想要将它们拆分到不同文件中:
mkdir locales
mkdir locales/zh
touch locales/zh/hello.json
然后编辑 locales/zh/hello.json 文件,在其中添加如下内容(仅作为示例):
{ "message": "你好" }
导入本地化语言内容
然后编辑 lang/zh.js 文件,修改为如下内容:
import hello from '~/locales/zh/hello.json'
export default defineI18nLocale(() => {
return { hello }
})
使用本地化语言内容
这里为了方便演示,可以在 app.vue 的 template 块里添加:
<template>
<div>{{ $t('hello.message') }}</div>
</template>
然后访问界面 http://localhost:3000,可以看到如下界面:

VSCode 配置
VSCode 可以安装 lokalise.i18n-ally 扩展来达到更好的开发体验。
安装完成扩展后,在项目下新建 .vscode/settings.json 文件:
mkdir .vscode
touch .vscode/settings.json
在 .vscode/settings.json 文件中添加如下内容:
{
"i18n-ally.namespace": true,
"i18n-ally.localesPaths": ["locales"],
"i18n-ally.pathMatcher": "{locale}/{namespaces}.json",
"i18n-ally.keystyle": "nested",
"i18n-ally.keepFulfilled": true
}
主要是前三行配置:
- 第一行是表示启用命名空间
- 第二行是本地化语言内容的存放路径,是一个相对路径
- 第三行是本地化语言内容匹配器,这里使用本地化语言标签加命名空间匹配器,所以第一行需要启用命名空间
添加完成后,扩展会去读取 locales 目录下的本地化语言标签(使用 bcp47 标准进行匹配)里的本地化语言内容,且以命名空间的形式去解析。
已经知道我们的 locales/ 目录下有个 zh 语言,且该语言内有个 hello.json 文件,文件里有个 message 本地化信息。
Info
message叫本地化信息不知道合不合适,vue i18n 文档是英文的,中文语境下也不知道有什么好的形容词。
此时就相当于 hello 这个命名空间里有个 message 本地化信息,即 hello.message 是能够被扩展正确识别的。
如果有个 locales/zh/form/label/item.json 文件,且此文件有个 id 本地化信息内容是 项编号,那么就相当于有一个 form.label.item.id 本地化信息。
但是需要注意这只是扩展的行为,如果要让 Nuxt 中有相同的行为,需要在 lang/zh.js 中以相同的方式导入 locales/zh/form/label/item.json 才行,例如:
import hello from '~/locales/zh/hello.json'
import item from '~/locales/zh/form/label/item.json'
export default defineI18nLocale(() => {
return { hello, form: { label: { item } } }
})
此时可以在 template 里通过 {{ $t('form.label.item.id') }} 使用。
可以通过 VSCode 窗口在右下角来选择要在 VSCode 里直接显示的本地化信息内容:

其他
如果不生效的话,可以看看目前可以使用的本地化信息有哪些,可以在 app.vue 的 script setup 里使用下面这个来查看:
const i18n = useI18n()
console.log(i18n.messages.value)
呃
最近睡眠质量不太好,所以可能写得有些混乱。也可以直接看 github 上的仓库:https://github.com/nafnix/nuxt-app。