# General Translation Knowledge Base: 如何从 vue-i18n 迁移到 gt-vue？
URL: https://generaltranslation.com/zh/kb/migrate-from-vue-i18n.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: 将 gt-vue 与 vue-i18n 并行安装，同步当前区域设置，然后逐个组件地将 $t 键替换为 `<T>` 和 useGT 中的内联文案。General Translation 会以模板结构作为上下文翻译迁移后的文案，你的团队可以在仪表板中修正译文。尚未迁移的组件将继续使用已审校的 vue-i18n 消息。
Category: 国际化
Last updated: 2026-11-11
Authors: Kevin Wu
Published: 2026-11-11

vue-i18n 渲染的是你按语言逐一写入消息文件的译文。gt-vue 渲染的则是直接内联在模板中的文案，译文由 General Translation 通过 [`npx gt translate`](/docs/cli/reference/commands/translate) 生成。迁移时，两个插件可在同一应用中同时运行，你只需逐个组件地将每个 `$t('key')` 查找替换为其对应的源文本。

## vue-i18n 的 API 如何对应到 gt-vue？

| vue-i18n                                           | gt-vue                                                                                                                                                                             |
| -------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `createI18n({ locale, fallbackLocale, messages })` | [`createGT`](/docs/vue/reference/functions/create-gt)`({ defaultLocale, loadTranslations })`，并在 `gt.config.json` 中配置 locales                                                       |
| `app.use(i18n)`                                    | `app.use(gt)`                                                                                                                                                                      |
| 模板中的 `$t('key')`                                   | 用 [`<T>`](/docs/vue/reference/components/t) 包裹文案，或使用 [`useGT`](/docs/vue/reference/composables/use-gt) 返回的字符串                                                                      |
| `<script setup>` 中的 `t('key')`                     | 先 `const gt = useGT()`，再在 `computed` 中调用 `gt('Inbox')`                                                                                                                             |
| `{name}` 命名插值                                      | 在 [`<T>`](/docs/vue/reference/components/t) 中使用 [`<Var>`](/docs/vue/reference/components/var)                                                                                      |
| 带插槽的 `<i18n-t keypath="...">`                      | 用 [`<T>`](/docs/vue/reference/components/t) 直接包裹实际标记                                                                                                                               |
| `'no apples \| one apple \| {count} apples'`       | 使用带有 `#zero`、`#singular` 和 `#plural` 插槽的 [`<Plural>`](/docs/vue/reference/components/plural)                                                                                       |
| 使用命名格式的 `n()` 和 `d()`                              | [`<Num>`](/docs/vue/reference/components/num)、[`<Currency>`](/docs/vue/reference/components/currency) 和 [`<DateTime>`](/docs/vue/reference/components/datetime)，并以内联方式传入 `Intl` 选项 |
| `locale.value = 'fr'`                              | [`useSetLocale`](/docs/vue/reference/composables/use-set-locale)`()('fr')`；通过 [`useLocale`](/docs/vue/reference/composables/use-locale) 读取当前区域设置                                   |
| 通过 `setLocaleMessage` 懒加载                          | 由 `loadTranslations(locale)` 选项加载并缓存各区域设置的译文                                                                                                                                       |
| `fallbackLocale`                                   | `defaultLocale`；缺少译文时会渲染源文本                                                                                                                                                        |

消息键、SFC `<i18n>` 自定义块以及链接消息 (`@:key`) 都应改为内联文案：将每条消息的文本移到渲染它的模板中，并将链接消息完整展开写出。

## 第 1 步：与 vue-i18n 并行安装 gt-vue

gt-vue (当前为 0.x 版本) 支持 Vue 3.3 及更高版本。请参阅 [Vue 快速入门](/docs/vue/quickstart)。简要步骤如下：

1. 安装 `gt-vue`，并将 `gt` CLI 安装为开发依赖。

2. 创建 `gt.config.json`，配置与 vue-i18n 相同的源区域设置和目标区域设置，并指定输出路径，例如 `src/_gt/[locale].json`。

3. 添加 `loadTranslations` 函数，并在 vue-i18n 之后安装该插件：

   ```ts title="src/main.ts"
   import { createApp } from 'vue';
   import { createGT, type LoadTranslations } from 'gt-vue';
   import App from './App.vue';
   import i18n from './i18n'; // 你现有的 createI18n 实例

   const loadTranslations: LoadTranslations = async (locale) => {
     try {
       return (await import(`./_gt/${locale}.json`)).default;
     } catch {
       return {};
     }
   };

   createApp(App)
     .use(i18n)
     .use(createGT({ defaultLocale: 'en', loadTranslations }))
     .mount('#app');
   ```

4. 使用 [`npx gt login`](/docs/cli/reference/commands/login) 登录，并设置你的项目 ID。

gt-vue 无需 Vite 插件：运行 [`npx gt translate`](/docs/cli/reference/commands/translate) 时，CLI 会扫描 `.vue` 文件中的 [`<T>`](/docs/vue/reference/components/t) 和 [`useGT`](/docs/vue/reference/composables/use-gt)。

## 第 2 步：只保留一个当前区域设置

使用 gt-vue 作为语言切换器，并将其区域设置同步到 vue-i18n，让尚未迁移的组件也随之切换：

```vue title="src/App.vue"
<script setup lang="ts">
import { watchEffect } from 'vue';
import { useI18n } from 'vue-i18n';
import { useLocale } from 'gt-vue';

const gtLocale = useLocale();
const { locale } = useI18n({ useScope: 'global' });

watchEffect(() => {
  locale.value = gtLocale.value;
});
</script>
```

将现有的语言菜单替换为调用 [`useSetLocale`](/docs/vue/reference/composables/use-set-locale) 的控件。使用 [`createGT`](/docs/vue/reference/functions/create-gt) 时，切换区域设置会加载新区域设置的译文并重新渲染，无需刷新页面；同时，gt-vue 会将用户的选择保存在 `generaltranslation.locale` cookie 中。

## 第 3 步：逐个迁移组件

将消息文件中的 source-language 文本复制到模板中。迁移前：

```json title="src/locales/en.json"
{
  "greeting": "Hello, {name}!",
  "unread": "You have no messages | You have {count} message | You have {count} messages",
  "inbox": "Inbox"
}
```

```vue title="src/components/InboxHeader.vue"
<script setup lang="ts">
import { useI18n } from 'vue-i18n';
defineProps<{ name: string; count: number }>();
const { t } = useI18n();
</script>

<template>
  <h1>{{ t('inbox') }}</h1>
  <p>{{ t('greeting', { name }) }}</p>
  <p>{{ t('unread', count) }}</p>
</template>
```

修改后：

```vue title="src/components/InboxHeader.vue"
<script setup lang="ts">
import { computed } from 'vue';
import { T, Var, Num, Plural, useGT } from 'gt-vue';
defineProps<{ name: string; count: number }>();

const gt = useGT();
const title = computed(() => gt('Inbox')); // 使用 computed，使其随区域设置的切换自动更新
</script>

<template>
  <h1>{{ title }}</h1>
  <T>
    <p>Hello, <Var>{{ name }}</Var>!</p>
    <p>
      <Plural :n="count">
        <template #zero>You have no messages</template>
        <template #singular>You have <Num :value="count" /> message</template>
        <template #plural>You have <Num :value="count" /> messages</template>
      </Plural>
    </p>
  </T>
</template>
```

General Translation 会根据 `singular` 和 `plural` 插槽，生成每种目标语言所需的形式 (例如俄语的 `few` 和 `many`) ，再由 [`<Plural>`](/docs/vue/reference/components/plural) 通过 `Intl.PluralRules` 从中选出合适的一种；而使用 vue-i18n 的管道语法时，需要为这些语言编写自定义复数处理规则。`zero` 插槽则保留你为空收件箱编写的文案。标题、占位符等静态字符串请使用 [`useGT`](/docs/vue/reference/composables/use-gt)；凡是包含运行时值的句子，都应放入 [`<T>`](/docs/vue/reference/components/t) 中，并配合 [`<Var>`](/docs/vue/reference/components/var) 使用。每迁移完一批组件，就运行 [`npx gt translate`](/docs/cli/reference/commands/translate)，并逐一检查各个区域设置。

## 现有译文会怎样？

尚未迁移的组件会继续渲染已审校的 vue-i18n 消息，因此分阶段迁移只会影响你改动过的页面。gt-vue 根据源内容而非消息键来识别译文，因此移入 [`<T>`](/docs/vue/reference/components/t) 或 [`useGT`](/docs/vue/reference/composables/use-gt) 的文案会由 [`npx gt translate`](/docs/cli/reference/commands/translate) 重新生成译文，并以所在的模板作为上下文。借助[上下文分组](/docs/platform/dashboard/guides/defining-context-for-translations)中的词汇表和自定义提示词，可以保持术语和语气一致。之后，审校人员还可以在[仪表板](/docs/platform/dashboard/guides/reviewing-translations)中修正任何措辞。

## 第 4 步：移除 vue-i18n

当搜索 `$t(`、`useI18n`、`<i18n-t` 和 `vue-i18n` 均已无结果时，即可移除 `createI18n` 初始化设置、消息文件、区域设置同步逻辑以及 `vue-i18n` 依赖。然后将 [`npx gt translate`](/docs/cli/reference/commands/translate) 加入你的构建流程或 [CI](/kb/translations-in-ci)，确保每次发布时新增文案都已完成翻译。

## 常见问题

### gt-vue 是否支持 Nuxt？

gt-vue 没有提供 Nuxt 模块，也不像 `@nuxtjs/i18n` 那样提供本地化路由、hreflang 标签或浏览器语言检测。不过，CLI 会扫描 Nuxt 的 `pages/` 和 `layouts/` 目录；而且只要为每个请求单独创建一个插件实例，[`createGT`](/docs/vue/reference/functions/create-gt) 就可以在服务端渲染。

### gt-vue 是否支持消息键？

不支持。gt-vue 翻译的是直接内联编写在 [`<T>`](/docs/vue/reference/components/t) 和 [`useGT`](/docs/vue/reference/composables/use-gt) 中的文案。如果你的工作流以键为核心，请继续使用 vue-i18n。

### 可以逐个组件迁移吗？

可以。只要两个插件共享当前区域设置，就可以在同一个应用中同时运行。等到不再有任何地方使用 vue-i18n 后，再将其移除。

### gt-vue 是免费的吗？

gt-vue 采用 MIT 许可证，无需注册账户即可渲染随应用打包的译文。使用 General Translation 生成译文则[按用量计费](https://generaltranslation.com/pricing)。

## 要点总结

* 让 gt-vue 与 vue-i18n 并行运行，通过 gt-vue 切换语言，并在迁移完成前将其区域设置同步到 vue-i18n。
* 将 `$t` 键替换为内联文案：模板中使用 [`<T>`](/docs/vue/reference/components/t) 搭配 [`<Var>`](/docs/vue/reference/components/var)；管道符复数改用 [`<Plural>`](/docs/vue/reference/components/plural) 的 `singular` 和 `plural` 插槽；script 中的静态字符串则在 `computed` 中使用 [`useGT`](/docs/vue/reference/composables/use-gt)。
* 尚未迁移的组件仍沿用已审校的 vue-i18n 消息；已迁移的文案会以所在模板作为上下文进行翻译，并在仪表板中审校。如果你的应用高度依赖消息键或 `@nuxtjs/i18n` 路由，请继续使用 vue-i18n。
* 当代码中不再读取 vue-i18n 时即可将其移除，然后在 CI 中运行 [`npx gt translate`](/docs/cli/reference/commands/translate)。

## Related questions

- [General Translation 与 vue-i18n 对比：该选哪一个？](https://generaltranslation.com/zh/kb/general-translation-vs-vue-i18n.mdx): General Translation 让 Vue 团队可以直接在模板中编写源文案，并通过 CLI 生成译文。其 gt-vue 插件在渲染这些内容时，会应用符合区域设置的复数形式和数字格式化。如果你希望免去维护基于键的源文件，可以选择它；而对于使用 Nuxt i18n 模块、已有成熟目录工作流的团队，vue-i18n 依然是合适的选择。
- [如何翻译 Vue 应用？](https://generaltranslation.com/zh/kb/translate-vue-app.mdx): 翻译 Vue 应用，就是让每个模板字符串都按当前语言进行查找，并将其翻译成每种目标语言。General Translation 的 gt-vue 插件会翻译包裹在 `<T>` 组件中的内容，npx gt translate 则会为每种目标语言生成一个目录。
- [如何在每次部署时保持译文同步更新？](https://generaltranslation.com/zh/kb/translations-in-ci.mdx): 在每次生产环境构建之前，将翻译作为流水线中的一个步骤运行，这样新增文案就会在引入它的那次部署中以翻译好的形式一同上线。General Translation 的 gt CLI 通过 npx gt translate 实现这一点，所需的项目 API 密钥和项目 ID 以 CI 密钥的形式存储。

## Previous and next questions

- Previous question: [如何从 react-i18next 迁移到 gt-react？](https://generaltranslation.com/zh/kb/migrate-from-react-i18next.mdx)
- Next question: [AI 编程智能体与翻译流水线：本地化自动化该选哪个？](https://generaltranslation.com/zh/kb/ai-coding-agent-vs-translation-pipeline.mdx)

## Sitemap

See the [Knowledge Base sitemap](https://generaltranslation.com/zh/kb/sitemap.md) for every article.
