You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Nuxt中通过插件注入函数设置vue-i18n消息?

问题分析与解决方案

核心问题

你遇到的问题本质是SSR下服务端与客户端的i18n状态未同步:服务端渲染时设置的翻译消息,没有传递到客户端,客户端初始化i18n时又回到了初始的空消息对象,导致水合后翻译丢失。另外代码里还有几处异步逻辑错误,加剧了这个问题。

代码问题拆解

  • asyncData未处理异步操作:没有await fetch('/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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 22:25:25