如何在Nuxt中通过插件注入函数设置vue-i18n消息?
问题分析与解决方案
核心问题
你遇到的问题本质是SSR下服务端与客户端的i18n状态未同步:服务端渲染时设置的翻译消息,没有传递到客户端,客户端初始化i18n时又回到了初始的空消息对象,导致水合后翻译丢失。另外代码里还有几处异步逻辑错误,加剧了这个问题。
代码问题拆解
- asyncData未处理异步操作:没有
awaitfetch('/data')和$setTranslations,服务端可能在数据、翻译未加载完成时就完成渲染,且data.language实际是Promise而非真实数据,会传入undefined。 - 插件
app变量未正确获取:直接使用app未关联context.app,会导致报错。 setMsgsForLocale异步逻辑不完整:函数声明为async但内部用.then,未返回Promise,导致await setMsgsForLocale无法等待翻译加载完成。- SSR状态未序列化到客户端:服务端设置的i18n配置(locale、messages)未传递给客户端,客户端重新初始化时用了默认空配置。
修复步骤
1. 修复asyncData的异步逻辑
确保等待所有异步操作完成:
// pages/index.vue async asyncData({ $setTranslations }) { // 等待API数据返回 const dataRes = await fetch('/data') const data = await dataRes.json() // 等待翻译设置完成 await $setTranslations(data.language) }
2. 修复翻译插件,处理SSR状态同步
修改插件代码,服务端将i18n状态注入页面全局变量,客户端初始化时读取该变量恢复状态:
// /plugins/translate.js import VueI18n from 'vue-i18n' export default ({ app, isServer, req }, inject) => { // 初始化i18n实例,优先从服务端传递的状态读取 const initialState = !isServer && window.__NUXT__?.i18n || { locale: 'en', messages: { en: {}, es: {} } } app.i18n = new VueI18n({ locale: initialState.locale, fallbackLocale: 'en', messages: initialState.messages, // SSR模式下开启该配置避免水合警告 silentTranslationWarn: isServer }) // 注入设置翻译的方法 inject('setTranslations', async (locale) => { await setMsgsForLocale(locale) // 服务端渲染时,将i18n状态添加到Nuxt上下文,用于序列化到客户端 if (isServer) { req.i18n = { locale: app.i18n.locale, messages: app.i18n.messages } } }) async function setMsgsForLocale(language = 'en') { // 用await处理异步请求,确保等待完成 const res = await fetch(`/translations/${language}.json`) const messages = await res.json() app.i18n.locale = language app.i18n.setLocaleMessage(language, messages) // 修正拼写错误:setLocaleMessage return messages } }
3. 配置Nuxt序列化服务端i18n状态到客户端
在nuxt.config.js中添加中间件,将服务端i18n状态注入页面全局变量:
// nuxt.config.js export default { // ...其他配置 serverMiddleware: [ (req, res, next) => { // 将服务端i18n状态挂载到req.nuxt,Nuxt会自动序列化到window.__NUXT__ if (req.i18n) { req.nuxt = req.nuxt || {} req.nuxt.i18n = req.i18n } next() } ] }
4. 关键注意点
- 修正方法名拼写:之前用的
setLocalMessage是错误的,正确方法为setLocaleMessage。 - 客户端避免重复请求:服务端已加载翻译时,客户端直接用传递的messages,无需重新请求。
- 严格处理异步:
asyncData必须用async/await确保服务端渲染前完成所有异步操作,避免水合不匹配。
内容的提问来源于stack exchange,提问作者Pablo
相关产品推荐
相关产品推荐

