Vue3 vue-i18n 切换语言无法响应式变化,如何解决?

Vue3 vue-I18u 切换语言无法响应式变化

版本👇
"vue": "^3.3.4",
"vue-i18n": "9",
import { createI18n, useI18n } from 'vue-i18n'
import { useOutsideSystemStore } from '@/stores/modules/system.js'
import zhCN from './json/zh.json'
import enUS from './json/en.json'

const useSystem = useOutsideSystemStore()

const i18n = createI18n({
  legacy: false,
  locale: useSystem.language,
  globalInjection: true,
  messages: {
    zh: zhCN,
    en: enUS
  }
})

const locale = toRef(i18n.global.locale)

export { useI18n, locale }

export default i18n

当切换时修改 全局locale 只响应式变化html中的{{$t('')}} script中的$t() 不会变化

希望只要使用到$t的地方都能变化

阅读 3.7k
avatarAI BotBETA

在 Vue 3 中使用 vue-i18n 时,你需要确保你的语言设置是响应式的。然而,在你的代码中,locale 被设置为 useSystem.language 的一个静态值,这不是响应式的。vue-i18ncreateI18n 函数在初始化时接受一个静态的 locale 值,这不会随着 useSystem.language 的变化而自动更新。

为了解决这个问题,你可以使用 vue-i18nsetLocaleMessagesetLocale 方法来动态地更新语言和消息。此外,你应该将 i18n 实例设置为 Vue 应用的插件,而不是直接导出它。

以下是一个修改后的示例,展示了如何在 Vue 3 和 vue-i18n 9 中实现响应式的语言切换:

import { createI18n, useI18n } from 'vue-i18n'
import { ref, onMounted, watch } from 'vue'
import { useOutsideSystemStore } from '@/stores/modules/system.js'
import zhCN from './json/zh.json'
import enUS from './json/en.json'

const messages = {
  zh: zhCN,
  en: enUS
}

// 创建一个响应式的 ref 来存储当前的 locale
const currentLocale = ref('zh') // 假设默认是中文

// 创建一个 i18n 实例,但不立即设置 locale
const i18n = createI18n({
  legacy: false,
  globalInjection: true, // 这将使 $t 和 $i18n 在模板和组件中可用
  // 注意:这里不设置 locale
  messages // 传入所有的消息
})

// 监听 useOutsideSystemStore 中的 language 变化,并更新 i18n 的 locale
const useSystem = useOutsideSystemStore()
watch(useSystem.language, (newLocale) => {
  i18n.global.setLocaleMessage(newLocale, messages[newLocale])
  i18n.global.locale.value = newLocale
})

// 挂载时设置初始 locale
onMounted(() => {
  i18n.global.setLocaleMessage(currentLocale.value, messages[currentLocale.value])
  i18n.global.locale.value = currentLocale.value
})

// 导出 useI18n 钩子函数
export { useI18n }

// 在你的 Vue 应用中安装 i18n 插件
// 例如,在 main.js 或 main.ts 中
// createApp(App).use(i18n).mount('#app')

请注意,我使用了 Vue 3 的 refonMountedwatch API 来创建一个响应式的 currentLocale 并监听 useSystem.language 的变化。我还使用了 i18n.global.setLocaleMessagei18n.global.locale.value 来动态地更新语言和消息。

确保在你的 Vue 应用中安装 i18n 插件,这样 $t$i18n 就可以在模板和组件中使用了。

此外,由于你使用的是 Vue 3 和 Composition API,你可能还需要在你的组件中使用 setup 函数和 useI18n 钩子函数来访问 $t 函数。例如:

import { setup } from 'vue'
import { useI18n } from 'vue-i18n'

export default {
  setup() {
    const { t } = useI18n()

    // 现在你可以使用 t 函数来翻译文本了
    // 例如:const translatedText = t('hello')

    // ... 其他逻辑 ...

    return {
      // ... 返回给模板的响应式引用 ...
    }
  }
}
2 个回答

OP你是怎么切换i18n当前语言的,有按照文档中的方式来切换吗?
👉 #Locale Changing - Composition API | Vue I18n

<script setup>
const { t, locale } = useI18n({ useScope: 'global' })

locale.value = 'en' // change!
</script>

按照OP你的评论,猜测OP你可能是在声明的时候,直接把 t 函数 返回的文本值直接赋值给JS变量了。

以下是一个Demo片段,OP你理解一下其中的区别:

<template>
  <div>
    <p>text:{{ $t("message.hello") }}</p>
    <p>testRef: {{ textRef }}</p>
    <p>textComp: {{ textComp }}</p>
    <button @click="changeLocale">Change</button>
  </div>
</template>

<script setup>
import { ref, computed } from "vue";
import { useI18n } from 'vue-i18n'

const { t, locale } = useI18n({ useScope: "global" });

const textRef = ref(t('message.hello'))
const textComp = computed(() => t('message.hello'));

const changeLocale = () => {
  locale.value = (locale.value === "en") ? "ja" : "en";
  console.log('changeLocale textRef.value =>', textRef.value)
  text.value = t('message.hello')
  console.log('changeLocale textRef.value(赋值后)', textRef.value)
};
</script>
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题