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

Vue3/Rollup库模式下集成vue-i18n遇错误求助

Vue3/Rollup组件库集成vue-i18n失败问题

我用Vue3+Rollup以库模式开发UI组件,打包成本地npm包供多项目复用。未添加国际化时组件功能正常,现在尝试在.vue文件中通过<i18n>标签添加翻译,并从vue-i18n导入t函数,预期组件运行时能获取应用的i18n上下文,但实际报错且完全未生效。

相关代码

UI组件库代码

index.ts

import type { App } from "vue";
import Hello from "./Hello.vue";

export function createBusinessComponent() {
    const install = (app: App) => {
        app.component("Hello", Hello);
    };

    return { install };
}

Hello.vue

<template>
 <p>{{ t('hello') }}</p>
</template>

<script lang="ts">
  import { defineComponent } from "vue";
 
  import { useI18n } from "vue-i18n";

  export default defineComponent({
    setup: (props, { emit }) => {
      const { t } = useI18n();
      return {
        t,
      };
    },
  });
</script>
<i18n>{
    "en": {
        "hello": " Hello world",
    },
    "fr": {
        "hello": " Bonjour",
    }   
}</i18n>

应用端代码

main.ts

import { createPinia } from 'pinia'
import { createApp } from 'vue'
import App from './App.vue'
import i18n from './i18n'
import router from './router'

import { createBusinessComponent } from 'ui-library'

const businessComp = createBusinessComponent({})

const app = createApp(App)
app.use(createPinia())
app.use(i18n)
app.use(router)
app.use(businessComp)
app.mount('#app')

i18n.ts

import { createI18n } from 'vue-i18n'
import EN from '../assets/props/en.json'
import FR from '../assets/props/fr.json'

const translations = {
  en: EN,
  fr: FR,
}

export default createI18n({
  legacy: false,
  locale: 'en',
  fallbackLocale: 'en',
  globalInjection: true,
  messages: translations,
})

App.vue

<template>
   <hello></hello>
</template>

控制台报错

SyntaxError: Must be called at the top of a setup function (at index-6cfa2a26.js:70354:94)
at h6 (index-6cfa2a26.js:70354:94)
at Lh (index-6cfa2a26.js:71311:10)
at ql (index-6cfa2a26.js:71804:11)
at setup (index-6cfa2a26.js:73154:12)
at callWithErrorHandling (runtime-core.esm-bundler.js:6656:22)
at setupStatefulComponent (runtime-core.esm-bundler.js:6272:29)
at setupComponent (runtime-core.esm-bundler.js:6228:11)
at mountComponent (runtime-core.esm-bundler.js:4081:13)
at processComponent (runtime-core.esm-bundler.js:4056:17)
at patch (runtime-core.esm-bundler.js:3651:21)

解决方案

1. 组件库中配置vue-i18n为peer依赖

修改组件库的package.json,将vue-i18n从dependencies移至peerDependencies,确保组件库使用应用端提供的vue-i18n实例,避免打包时重复引入:

{
  "peerDependencies": {
    "vue-i18n": "^9.0.0"
  }
}

2. 组件内指定useI18n的全局作用域

在Hello.vue的useI18n调用中添加useScope: 'global'参数,明确使用应用全局的i18n上下文:

<script lang="ts">
import { defineComponent } from "vue";
import { useI18n } from "vue-i18n";

export default defineComponent({
  setup: () => {
    const { t } = useI18n({ useScope: 'global' });
    return { t };
  },
});
</script>

3. Rollup配置排除vue和vue-i18n

在组件库的Rollup配置中,将vue和vue-i18n标记为外部依赖,不打包进组件库:

// rollup.config.js
import { nodeResolve } from '@rollup/plugin-node-resolve';
import vue from 'rollup-plugin-vue';

export default {
  input: 'src/index.ts',
  output: [
    { format: 'es', file: 'dist/index.es.js' },
    { format: 'cjs', file: 'dist/index.cjs.js' }
  ],
  plugins: [vue(), nodeResolve()],
  external: ['vue', 'vue-i18n']
};

4. 合并组件库翻译到应用端

组件内<i18n>标签的内容不会自动合并到应用的i18n实例,可通过两种方式处理:

  • 手动导入合并:在应用的i18n配置中导入组件翻译并合并
// My-Application > i18n.ts
import { createI18n } from 'vue-i18n'
import EN from '../assets/props/en.json'
import FR from '../assets/props/fr.json'
import { en as HelloEN, fr as HelloFR } from 'ui-library/dist/Hello.i18n.json'

const translations = {
  en: { ...EN, ...HelloEN },
  fr: { ...FR, ...HelloFR },
}

export default createI18n({
  legacy: false,
  locale: 'en',
  fallbackLocale: 'en',
  globalInjection: true,
  messages: translations,
})
  • 自动注入:在组件库的install方法中自动合并翻译
// UI-Library > index.ts
import type { App } from "vue";
import Hello from "./Hello.vue";
import helloMessages from './Hello.i18n.json'

export function createBusinessComponent() {
    const install = (app: App) => {
        app.component("Hello", Hello);
        const i18n = app.config.globalProperties.$i18n;
        if (i18n) {
          Object.keys(helloMessages).forEach(locale => {
            if (!i18n.messages[locale]) {
              i18n.messages[locale] = {};
            }
            Object.assign(i18n.messages[locale], helloMessages[locale]);
          });
        }
    };

    return { install };
}

关键原因说明

  • 组件库若打包自身的vue-i18n,会与应用端实例冲突,导致useI18n无法获取正确上下文
  • useI18n默认是局部作用域,需显式指定useScope: 'global'才能访问全局i18n实例
  • 组件内<i18n>标签的翻译内容不会自动合并到应用的i18n消息池,必须手动处理

内容的提问来源于stack exchange,提问作者Gregory Frerot

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 05:25:12