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 }
我已经排查了两小时,几乎试遍了所有方法都无效,请问问题出在哪里?会不会是路由文件的问题?
问题分析与解决方案
核心问题
- 组件选项中直接用
this.$t无效:组件选项初始化阶段,组件实例尚未创建,this指向undefined,无法访问$t方法。 i18n.t不是有效函数:你在i18n文件中直接调用useI18n()获取t,但useI18n是Vue3组合式API,必须在组件的setup函数或Vue生命周期钩子中调用,非上下文环境下调用无法获取有效i18n实例,导致t不是可用函数。- 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
相关产品推荐
相关产品推荐

