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

Vue3组件Script中vue-i18n翻译失效问题求助

Vue3组件Script中实现i18n翻译功能失败的问题

我尝试了多种方法在Vue3组件的Script中实现翻译功能,但均未成功,具体尝试过程如下:

尝试1:直接在选项中使用this.$t

<script>
import i18n from '@/i18n'

export default {
  tabIcon: 'images',
  translation: this.$t("basicnavigation.tabs.logos"),
}
</script>

报错:TypeError: Cannot read properties of undefined (reading '$t')

尝试2:直接调用i18n.t

<script>
import i18n from '@/i18n'

export default {
  tabIcon: 'images',
  translation: i18n.t("basicnavigation.tabs.logos"),
}
</script>

报错:TypeError: i18n.t is not a function

尝试3:在setup中用computed调用i18n.t

<script>
import { computed } from 'vue'
import i18n from '@/i18n'

export default {
  tabIcon: 'images',

  setup() {
    const translation = computed(() => i18n.t('basicconfiguration.tabs.logos'))
    return { translation }
  }
}
</script>

同样无法正常工作。

相关配置代码

main.js

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
import i18n from './i18n'
import "bootstrap"
import BootstrapIcon from '@dvuckovic/vue3-bootstrap-icons';
import Spinner from '@/components/Spinner'
import "@/assets/scss/styles.scss";

const pinia = createPinia()
const app = createApp(App)

i18n.setup()
app.use(pinia)
app.use(i18n.vueI18n)
app.use(router)
app.use('bootstrap')

app.component('BootstrapIcon', BootstrapIcon);
app.component('Spinner', Spinner)
app.mount('#app')

i18n/index.js

import { nextTick } from 'vue'
import { createI18n, useI18n } from 'vue-i18n'
import { numberFormats } from './numbers'
import { arabicPluralRules } from './plurals'
import { datetimeFormats } from './datetimes'
import defaultMessages from '../translations/nl-NL.json'

export const supportedLocales = {
  'en-GB': { name: 'English', dir: 'ltr' },
  'nl-NL': { name: 'Nederlands', dir: 'ltr' },
}

export const defaultLocale = 'nl-NL'

let _i18n

function setup(options = { locale: defaultLocale }) {
  _i18n = createI18n({
    locale: options.locale,
    fallbackLocale: defaultLocale,
    messages: { [defaultLocale]: defaultMessages },
    numberFormats,
    datetimeFormats
  })

  setLocale(options.locale)

  return _i18n
}

function setLocale(newLocale) {
  _i18n.global.locale = newLocale
  setDocumentAttributesFor(newLocale)
}

async function loadMessagesFor(locale) {
  const messages = await import(
    /* webpackChunkName: "locale-[request]" */ `../translations/${locale}.json`
  )

  _i18n.global.setLocaleMessage(locale, messages.default)

  return nextTick()
}

function setDocumentAttributesFor(locale) {
  const htmlElement = document.querySelector('html')

  htmlElement.setAttribute('lang', locale)
  htmlElement.setAttribute('dir', supportedLocales[locale].dir)
}

const { t } = useI18n({
  messages: {
    supportedLocales
  }
})

export default {
  get vueI18n() {
    return _i18n
  },
  setup,
  setLocale,
  loadMessagesFor,
  t
}

我已经排查了两小时,几乎试遍了所有方法都无效,请问问题出在哪里?会不会是路由文件的问题?


问题分析与解决方案

核心问题

  1. 组件选项中直接用this.$t无效:组件选项初始化阶段,组件实例尚未创建,this指向undefined,无法访问$t方法。
  2. i18n.t不是有效函数:你在i18n文件中直接调用useI18n()获取t,但useI18n是Vue3组合式API,必须在组件的setup函数或Vue生命周期钩子中调用,非上下文环境下调用无法获取有效i18n实例,导致t不是可用函数。
  3. setup中调用i18n.t无效:原因同上,导出的i18n.t是在非Vue上下文环境中获取的,未绑定到当前应用的i18n实例。

修复方案

方案1:组件setup中使用useI18n(推荐)

这是Vue3 + vue-i18n的标准用法,直接在组件setup中调用useI18n获取翻译函数:

<script>
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'

export default {
  tabIcon: 'images',

  setup() {
    const { t } = useI18n()
    // 需响应式更新翻译内容时用computed包裹
    const translation = computed(() => t('basicnavigation.tabs.logos'))
    return { translation }
  }
}
</script>

方案2:修复i18n文件的t导出

若需在组件外或非setup环境使用翻译函数,需从已初始化的i18n实例global对象中获取t,修改i18n文件:

// 移除原代码中直接调用useI18n的部分
// const { t } = useI18n({
//   messages: {
//     supportedLocales
//   }
// })

// 改为在导出对象中添加getter,从已初始化的_i18n实例取t
export default {
  get vueI18n() {
    return _i18n
  },
  setup,
  setLocale,
  loadMessagesFor,
  get t() {
    return _i18n?.global.t || (() => '')
  }
}

之后组件中即可正常使用:

<script>
import { computed } from 'vue'
import i18n from '@/i18n'

export default {
  tabIcon: 'images',

  setup() {
    const translation = computed(() => i18n.t('basicnavigation.tabs.logos'))
    return { translation }
  }
}
</script>

方案3:选项式API中用computed定义翻译属性

若习惯使用选项式API,可直接在组件computed选项中定义翻译属性:

<script>
export default {
  tabIcon: 'images',
  computed: {
    translation() {
      return this.$t('basicnavigation.tabs.logos')
    }
  }
}
</script>

额外注意点

  • 确认翻译键basicnavigation.tabs.logos在对应语言包(如nl-NL.json)中存在,否则会直接显示键名。
  • 路由文件通常不会影响i18n基础功能,除非路由配置中有特殊的locale拦截逻辑,从当前代码看暂不相关。

内容的提问来源于stack exchange,提问作者R-b-n

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 02:05:44