# General Translation Knowledge Base: General Translation vs. vue-i18n: which should you use?
URL: https://generaltranslation.com/en-US/kb/general-translation-vs-vue-i18n.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: General Translation lets Vue teams write source copy directly in templates and generate translations with the CLI. Its gt-vue plugin renders that content with locale-aware plural and number formatting. Choose it to remove keyed source-file maintenance; vue-i18n remains a fit for teams using Nuxt's i18n module and an established catalog workflow.
Category: Internationalization
Last updated: 2026-10-16
Authors: Kevin Wu, Jackie Chen
Published: 2026-10-16

vue-i18n renders messages in the user's language for Vue apps. You define messages for each locale, look them up by key in your templates, and it formats plurals, dates, and numbers. It doesn't translate anything: every language's messages come from you, your translators, or a translation management system (TMS). General Translation's `gt-vue` renders translations the same way, and General Translation also generates them from copy you write inline in your templates.

## What vue-i18n does well

- **Maturity.** vue-i18n has been on npm since 2014. [Version 11 is the maintained line](https://vue-i18n.intlify.dev/guide/maintenance), and version 12 is in alpha.
- **Nuxt.** The [`@nuxtjs/i18n` module builds on vue-i18n 11](https://i18n.nuxtjs.org/docs/getting-started) and adds locale-prefixed routes, localized paths, browser-language detection, lazy-loaded translations, and SEO tags such as hreflang alternates.
- **Formatting and rich text.** `datetimeFormats` and `numberFormats` take `Intl` options, and the [`<i18n-t>` component](https://vue-i18n.intlify.dev/guide/advanced/component) places elements inside a translated message without `v-html`.
- **Messages beside components.** With `@intlify/unplugin-vue-i18n`, an [`<i18n>` block](https://vue-i18n.intlify.dev/guide/advanced/sfc) keeps a component's messages inside its single-file component.
- **Tooling.** The [official ESLint plugin](https://eslint-plugin-vue-i18n.intlify.dev/rules/) flags raw text in templates and missing or unused keys.

## What vue-i18n leaves to you

Here's a small inbox with vue-i18n's Composition API. Each string gets a key, and the English lives in a message file:

```json title="locales/en.json"
{
  "inbox": {
    "heading": "Inbox",
    "unread": "You have {n} unread message | You have {n} unread messages"
  }
}
```

```vue title="Inbox.vue"
<script setup>
import { useI18n } from 'vue-i18n'

defineProps({ count: { type: Number, required: true } })
const { t } = useI18n()
</script>

<template>
  <section>
    <h1>{{ t('inbox.heading') }}</h1>
    <p>{{ t('inbox.unread', count) }}</p>
  </section>
</template>
```

Every target language needs translated messages, supplied by your team or a translation service. Two implementation details matter for the example:

- **Plural rules.** vue-i18n 11's default rule selects forms by position. Polish uses `one`, `few`, `many`, and `other` categories, so configure a [custom `pluralRules` function](https://github.com/intlify/vue-i18n/blob/master/docs/guide/v11/essentials/pluralization.md) to map counts to your translated forms. vue-i18n 12, still in alpha, [switches to `Intl.PluralRules`](https://github.com/intlify/vue-i18n/releases/tag/v12.0.0-alpha.4).
- **Numbers inside messages.** The `{n}` in a plural message isn't formatted for the locale, so 12345 renders as "12345" in Spanish instead of "12.345" unless you pass a formatted value.

## Inline templates with generated translations

`gt-vue` does the same job as vue-i18n. It renders each locale's messages, picks plural forms with each locale's CLDR rules, and formats numbers, currencies, and dates with [`<Num>`](/docs/vue/reference/components/num), [`<Currency>`](/docs/vue/reference/components/currency), and [`<DateTime>`](/docs/vue/reference/components/datetime). Then General Translation does what vue-i18n doesn't: it generates the translations. Here's the same inbox, with the copy inline:

```vue title="Inbox.vue"
<script setup>
import { Num, Plural, T } from 'gt-vue'

defineProps({ count: { type: Number, required: true } })
</script>

<template>
  <section>
    <T><h1>Inbox</h1></T>
    <p>
      <T>
        <Plural :n="count">
          <template #singular>You have <Num :value="count" /> unread message</template>
          <template #plural>You have <Num :value="count" /> unread messages</template>
        </Plural>
      </T>
    </p>
  </section>
</template>
```

[`npx gt translate`](/docs/cli/reference/commands/translate) scans your templates, sends each [`<T>`](/docs/vue/reference/components/t) block with its structure to the General Translation API, and writes a catalog for every target locale. The `singular` and `plural` slots supply source wording for the target language's forms. [`<Plural>`](/docs/vue/reference/components/plural) selects those forms using locale rules, and [`<Num>`](/docs/vue/reference/components/num) formats the count: 12,345 in English, 12.345 in Spanish, and 12 345 in Polish.

The example uses `gt-vue` 0.1.22 with Vue 3.3 or later; the [Vue Quickstart](/docs/vue/quickstart) covers plugin and catalog-loader setup. Your team can refine the generated text in the [Dashboard](/docs/platform/dashboard/guides/reviewing-translations), while [shared Glossary terms and Custom Prompts](/docs/platform/dashboard/guides/defining-context-for-translations) keep terminology consistent across projects.

## vue-i18n vs. General Translation at a glance

| Feature | vue-i18n | General Translation (`gt-vue`) |
| --- | --- | --- |
| How you write copy | Keys in a message file or `<i18n>` block per locale | Inline in templates, inside [`<T>`](/docs/vue/reference/components/t) |
| Translates your content | No | Yes, with [`npx gt translate`](/docs/cli/reference/commands/translate) |
| Plural forms | Forms separated by a vertical bar; version 11 needs a custom rule for languages such as Polish | [`<Plural>`](/docs/vue/reference/components/plural) slots chosen with CLDR rules for every locale |
| Numbers in messages | Formatted when you pass a formatted value | [`<Num>`](/docs/vue/reference/components/num) formats for each locale |
| App integration | Vue plugin; `@nuxtjs/i18n` adds Nuxt routing, language detection, and SEO tags | Vue plugin with reactive locale switching and catalog loading |

Keep vue-i18n when you rely on `@nuxtjs/i18n` for Nuxt routing and SEO or already have a catalog workflow you want to retain. Choose General Translation to keep copy readable in Vue templates, generate translations during your build, and let reviewers edit them in the Dashboard.

## Moving from vue-i18n

Move one component at a time: replace each key lookup with its English copy inside [`<T>`](/docs/vue/reference/components/t), and turn pipe-separated plural messages into `singular` and `plural` slots in [`<Plural>`](/docs/vue/reference/components/plural), as in the example above. Keep vue-i18n and its reviewed catalogs for components that have not moved. Set up `gt-vue` with the [Vue Quickstart](/docs/vue/quickstart), then run [`npx gt translate`](/docs/cli/reference/commands/translate) before your build.

## Why does vue-i18n show the wrong plural form in Polish?

Configure a `pluralRules` function in vue-i18n 11 that maps Polish categories to the positions in your message. For example, 1 selects `one`, 2 and 22 select `few`, and 5 selects `many`. With General Translation, the inline example supplies the source wording, the service generates translated forms, and [`<Plural>`](/docs/vue/reference/components/plural) handles their selection.

## Key takeaways

- vue-i18n is a mature i18n plugin with strong Nuxt support, but it doesn't translate anything, and version 11 needs a custom plural rule for languages such as Polish.
- General Translation's CLI generates translations from inline [`<T>`](/docs/vue/reference/components/t) blocks; `gt-vue` renders them with plural selection and number formatting for each locale.
- Keep vue-i18n for an established Nuxt or catalog workflow. Choose `gt-vue` to stop maintaining keyed source files.

## Related questions

- [General Translation vs. i18next, react-intl, and next-intl: which i18n library should you use?](https://generaltranslation.com/en-US/kb/general-translation-vs-i18n-libraries.mdx): Open-source libraries such as i18next, react-intl, and next-intl don't translate anything. They display translations you supply in a catalog file for each language, written by you, your translators, or a separate service. General Translation's libraries are open source too and do the same job, and General Translation also does the translating, with your code as context.
- [General Translation vs. i18next: which should you use?](https://generaltranslation.com/en-US/kb/general-translation-vs-i18next.mdx): Choose General Translation to keep copy inline in React components and generate translations with its JSX structure and product context. You can also keep i18next and use General Translation to translate existing catalogs. i18next supplies message rendering and plural selection; translation generation comes from a separate service.
- [General Translation vs. Lingui: which should you use?](https://generaltranslation.com/en-US/kb/general-translation-vs-lingui.mdx): Choose General Translation to keep copy inline like Lingui and generate the translations with your JSX structure as context. Lingui extracts inline messages into catalogs for your translators or a connected service to translate. General Translation's CLI updates translations as your code changes, and your team reviews them in the Dashboard.
- [General Translation vs. react-intl: which should you use?](https://generaltranslation.com/en-US/kb/general-translation-vs-react-intl.mdx): General Translation lets React teams keep ICU message syntax while adding translation generation, shared terminology, and Dashboard review. react-intl supplies formatting and FormatJS catalog tooling; General Translation produces the translations too, and gt-next supports inline translated JSX in Server Components.
- [Can I do i18n without translation files?](https://generaltranslation.com/en-US/kb/i18n-without-translation-files.mdx): Yes. With gt-react or gt-next, content stays inline in your components inside a `<T>` component, and translations are generated at build time as output, so there are no keys or per-locale JSON files to write and keep in sync.

## Previous and next questions

- Previous question: [General Translation vs. Transifex: which should you use?](https://generaltranslation.com/en-US/kb/general-translation-vs-transifex.mdx)
- Next question: [General Translation vs. Weblate: which should you use?](https://generaltranslation.com/en-US/kb/general-translation-vs-weblate.mdx)

## Sitemap

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