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

切换语言时Pinia Store无法更新i18n翻译的问题求助

问题:Pinia Store 中 i18n 翻译在路由切换时不更新

模板中使用插值语法的翻译正常生效,但从 Pinia Store 获取的翻译内容仅在刷新带语言参数的URL时显示正确,通过router.push切换语言时无法自动更新。

相关代码片段

路由配置

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      redirect: `/${i18n.global.locale.value}`
    },
    {   
      path: '/:lang',
      component: {
        render() { return h(resolveComponent('router-view')) }
      },
      children: [
        {
          path: '/:lang/',
          name: 'home',
          component: HomeView
        },
        {
          path: '/:lang/about',
          name: 'about',
          component: AboutView
        },
        {
          path: '/:lang/services',
          name: 'services',
          component: ServicesView
        },
        {
          path: '/:lang/contacts',
          name: 'contacts',
          component: ContactsView
        },
        {
          path: '/:lang/404',
          name: '404',
          component: NotFoundView
        },
      ] 
    },
  ]
})

router.beforeEach((to, from, next) => {
  let language = to.params.lang;
  if (!language) {
    language = 'en'
  }
  i18n.global.locale.value = language
  next()
})

export default router

i18n 插件

import { createI18n } from 'vue-i18n'
import en from '../locales/en.json'
import fr from '../locales/fr.json'

const instance = createI18n({
  legacy: false,
  locale: import.meta.env.VITE_I18N_LOCALE || 'en',
  fallbackLocale: import.meta.env.VITE_I18N_FALLBACK_LOCALE || 'fr',
  messages: {
    en,
    fr
  },
  fallbackWarn: false,
  missingWarn: false,
  globalInjection: true,
})

export default instance;
export const i18n = instance.global;

i18n Store

import { defineStore } from 'pinia';
import { useI18n } from "vue-i18n";
import { i18n } from '@/plugins/i18n';

export const useI18nStore = defineStore('i18nStore', () => {
  const t = useI18n({ inheritLocale: true, useScope: 'local', fallbackWarn: false })
  
  const setNewLanguage = (language: string) => {
    i18n.locale.value = language;
    console.log(i18n.locale.value , "from store I18n")
  }
  
  return { t, setNewLanguage }
})

业务 Store(问题核心)

import { ref} from 'vue'
import { defineStore } from 'pinia'
import { useI18nStore } from '../stores/i18nStore'

interface ServiceOffered{
  title: String,
  imgUrl: String,
  text: String,
  cta: String
}

export const useOfferedServicesStore = defineStore('offeredServices', () => {
  const translation = useI18nStore();
  const { t } = translation.t;

  const offeredServices = ref<Array<ServiceOffered>>(
    [
      {
        title: "",
        imgUrl: "",
        text: t('offeredServicesCard1'),
        cta:  t('discoverMore')
      },
      {
        title: "",
        imgUrl: "",
        text: t('offeredServicesCard2'),
        cta: t('discoverMore')
      },
      {
        title: "",
        imgUrl: "",
        text: t('offeredServicesCard3'),
        cta: t('discoverMore')
      },
      {
        title: "",
        imgUrl: "",
        text: t('offeredServicesCard4'),
        cta: t('discoverMore')
      }
    ]
  );

  return { offeredServices }
})

解决方案

1. 修正 i18n Store 的t方法导出

原代码中错误地返回了useI18n()的完整对象,需要直接返回t方法:

import { defineStore } from 'pinia';
import { useI18n } from "vue-i18n";
import { i18n } from '@/plugins/i18n';

export const useI18nStore = defineStore('i18nStore', () => {
  const { t } = useI18n({ inheritLocale: true, useScope: 'local', fallbackWarn: false })
  
  const setNewLanguage = (language: string) => {
    i18n.locale.value = language;
  }
  
  return { t, setNewLanguage } // 直接返回t方法,而非包含t的对象
})

2. 让业务 Store 的翻译内容保持响应性

原代码中offeredServices的翻译仅在Store初始化时执行一次,需要用计算属性包裹,让其随语言变化自动重新计算:

import { computed } from 'vue'
import { defineStore } from 'pinia'
import { useI18nStore } from '../stores/i18nStore'

interface ServiceOffered{
  title: string, // TypeScript中推荐使用小写string而非String构造函数
  imgUrl: string,
  text: string,
  cta: string
}

export const useOfferedServicesStore = defineStore('offeredServices', () => {
  const translation = useI18nStore();
  const { t } = translation; // 现在可以直接解构t方法

  // 用computed包裹,语言变化时自动重新生成翻译内容
  const offeredServices = computed<Array<ServiceOffered>>(() => [
    {
      title: "",
      imgUrl: "",
      text: t('offeredServicesCard1'),
      cta: t('discoverMore')
    },
    {
      title: "",
      imgUrl: "",
      text: t('offeredServicesCard2'),
      cta: t('discoverMore')
    },
    {
      title: "",
      imgUrl: "",
      text: t('offeredServicesCard3'),
      cta: t('discoverMore')
    },
    {
      title: "",
      imgUrl: "",
      text: t('offeredServicesCard4'),
      cta: t('discoverMore')
    }
  ]);

  return { offeredServices }
})

3. 简化路由配置(可选优化)

子路由无需重复父路由的/:lang前缀,使用相对路径即可:

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      redirect: `/${i18n.global.locale.value}`
    },
    {   
      path: '/:lang',
      component: {
        render() { return h(resolveComponent('router-view')) }
      },
      children: [
        {
          path: '', // 对应/:lang/
          name: 'home',
          component: HomeView
        },
        {
          path: 'about', // 对应/:lang/about
          name: 'about',
          component: AboutView
        },
        {
          path: 'services', // 对应/:lang/services
          name: 'services',
          component: ServicesView
        },
        {
          path: 'contacts', // 对应/:lang/contacts
          name: 'contacts',
          component: ContactsView
        },
        {
          path: '404', // 对应/:lang/404
          name: '404',
          component: NotFoundView
        },
      ] 
    },
  ]
})

内容的提问来源于stack exchange,提问作者Pietro Ciccarello

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 00:34:57