Přejít na obsah
Vue i18n

Vue i18n pro moderní aplikace

Podpora rozhraní Composition API a Options API s bezproblémovou integrací Nuxt.

Setup

Connect Vue to Better i18n in four steps

No Vue-specific package to install — the zero-dependency core client feeds vue-i18n directly.

Install the client and vue-i18n

There is no Vue-specific SDK to add — @better-i18n/core is framework-agnostic and vue-i18n stays your formatter.

terminalbash
npm install @better-i18n/core vue-i18n

# @better-i18n/core ships zero dependencies —
# it is the same client our React SDKs are built on.

Create the Better i18n client once

Instantiate at module scope: the TTL cache lives on the instance, so a per-component client would refetch on every mount.

src/lib/better-i18n.tsts
import { createI18nCore } from '@better-i18n/core'

export const betterI18n = createI18nCore({
  projectId: 'your-org/your-project', // Settings → General → Project ID
  defaultLocale: 'en',
})

Boot vue-i18n with CDN messages

Fetch the active locale before mounting and hand the object straight to createI18n — the shape vue-i18n expects is the shape the CDN returns.

src/main.tsts
import { createApp } from 'vue'
import { createI18n } from 'vue-i18n'
import App from './App.vue'
import { betterI18n } from './lib/better-i18n'

const locale = 'en'

// Messages come from the Better i18n CDN, cached in-memory for 60s.
const messages = await betterI18n.getMessages(locale)

const i18n = createI18n({
  legacy: false,           // Composition API
  locale,
  fallbackLocale: 'en',
  messages: { [locale]: messages },
})

createApp(App).use(i18n).mount('#app')

Switch locale at runtime

Load the target locale on demand and register it with setLocaleMessage, so a user only ever downloads the languages they actually open.

src/components/LocaleSwitcher.vuevue
import { useI18n } from 'vue-i18n'
import { betterI18n } from './lib/better-i18n'

const { locale, setLocaleMessage } = useI18n()

// Locales are discovered from the project manifest — no hardcoded list.
const languages = await betterI18n.getLanguages()

async function switchTo(next: string) {
  setLocaleMessage(next, await betterI18n.getMessages(next))
  locale.value = next
}

How it works

Where a Vue string comes from

No build step and no bundled JSON: the client resolves a locale at runtime, the edge answers it, and R2 is the source of truth behind both.

Read path — every locale load

Your Vue app

useI18n() reads the message vue-i18n already holds.

0 network calls per render

@better-i18n/core

getMessages(locale) — served from the in-memory cache if it is warm.

60s TTL · 0 deps

CDN edge

Cloudflare worker answers from the nearest edge cache.

max-age=60 · always 200

R2 object store

The published translation files the sync worker wrote.

source of truth

Fallback chain — tried in order when a hop fails

1In-memory TTL cache
2CDN fetch, with timeout and one retry
3Persistent storage, if configured
4staticData bundled with the app
5Throw — after everything above missed

Write path — dashboard to app

AI or translator

Proposal reviewed in the dashboard, glossary enforced.

MCP · dashboard · CLI

Publish

Sync worker writes the locale files to R2.

better-i18n publish

CDN purge

Fire-and-forget purge of the affected keys and the manifest.

non-critical by design

Live in the app

The next getMessages() past the TTL returns the new copy.

~60s worst case

0dependencies in core
60scache TTL, client and edge
200CDN status, even on failure
5fallback layers before an error
In a component

Rychlý start

Přidejte i18n do své aplikace Vue pomocí rozhraní API Composition.

src/components/Home.vuevue
<script setup lang="ts">
import { useI18n } from 'vue-i18n'

const { t, d, n } = useI18n()
</script>

<template>
  <section>
    <h1>{{ t('home.title') }}</h1>
    <p>{{ t('home.greeting', { name: 'World' }) }}</p>

    <!-- ICU plurals authored in the Better i18n dashboard -->
    <p>{{ t('cart.items', { count: 3 }) }}</p>

    <!-- vue-i18n formatters, locale-aware -->
    <time>{{ d(new Date(), 'short') }}</time>
    <span>{{ n(1299.9, 'currency') }}</span>
  </section>
</template>
What you get

Funkce

Everything below is shipped behaviour of @better-i18n/core, the CDN and the dashboard.

Translations served from the edge CDN, no rebuild to ship a copy change
In-memory TTL cache (60s) shared across your app's component tree
Persistent storage fallback so a failed fetch never blanks the UI
staticData as a last-resort bundle, for first paint before the network
Locale list auto-discovered from the project manifest
AI translations that read your glossary and brand tone
Publish from the dashboard, CDN purge fires automatically
MCP server so Claude and Cursor can manage keys directly
Works in Nuxt server routes via the same zero-dependency client
ICU message format preserved end-to-end into vue-i18n
Works with

Better I18N and the Vue ecosystem

We handle translation management and delivery; the Vue libraries you already use keep their jobs.

Better I18N + vue-i18n

The official Vue plugin, maintained by the Vue team. Handles t(), plurals, date and number formatting, and reactive locale state.Better i18n replaces the local JSON files it reads, nothing else changes

Better I18N + Nuxt

@nuxtjs/i18n owns routing, prefixes and SEO tags; translation delivery is the part it leaves to you.Call the same client from a Nuxt plugin — it runs server-side and on the client

Better I18N + Vue Router

Path-prefixed locales (/tr/urunler) need the locale resolved before the route renders.core exports extractLocale, addLocalePrefix and replaceLocaleInPath for that

FAQ

Vue i18n — Frequently Asked Questions

Is there a @better-i18n/vue package?

No, and you do not need one. @better-i18n/core ships with zero dependencies and is the same client our React SDKs are built on, so you call createI18nCore() directly and pass the messages to vue-i18n. A thin Vue wrapper would only save you the four lines in the setup guide above. If you want one anyway, say so on GitHub — that demand is what would prioritise it.

What is the best i18n library for Vue.js?

vue-i18n is the official internationalization plugin for Vue, maintained by the Vue core team. It supports Vue 2 and Vue 3, the Composition API, and integrates with Nuxt via @nuxtjs/i18n. It formats and renders strings; it does not manage, translate or deliver them. Better I18N covers that half — AI translation with glossary enforcement, review workflow, and CDN delivery — and hands vue-i18n the finished messages.

How does this work with the Composition API?

Exactly as vue-i18n normally does: create the plugin with legacy set to false, then call useI18n() inside script setup to get t(), d() and n(). Locale state stays reactive, so assigning locale.value re-renders every component that reads a translated string. Better I18N only changes where the messages come from — getMessages(locale) from the CDN instead of an imported JSON file.

Can the CLI extract keys from .vue files?

Not yet. The scanner's default extensions are .tsx, .jsx, .ts and .js, so better-i18n scan and better-i18n sync will walk past your SFCs today. Until that lands, manage Vue keys through the dashboard, the MCP server, or better-i18n keys create — and note that keys defined in plain .ts composables ARE picked up. Everything else in the CLI (publish, translations, languages, publish:status) is API-driven and framework-independent.

Does it work with Nuxt and server-side rendering?

Yes. The client has no browser-only dependencies, so calling getMessages() from a Nuxt plugin or server route works the same as in the browser, and the fetched object can be serialised into the SSR payload to avoid a second request on the client. Instantiate the client at module scope so the 60-second TTL cache is shared across requests rather than rebuilt per render.

How do plurals and ICU messages survive the trip?

ICU is preserved end-to-end: a message authored as {count, plural, one {# item} other {# items}} in the dashboard reaches vue-i18n as that exact string, and vue-i18n resolves it at render time. The dashboard also shows translators the correct plural categories for each target language, so a Turkish or Polish translator is not guessing which forms exist.

What happens when the CDN request fails?

The client walks a five-layer fallback chain: in-memory TTL cache, CDN fetch with timeout and retry, persistent storage if you configured one, then staticData, and only then does it throw. The CDN itself always answers HTTP 200 — on an internal error it returns an empty object rather than a 5xx — so a translation outage degrades to stale or fallback copy instead of a blank page.

How fast are published changes visible in a Vue app?

Publishing writes to R2 and fires a CDN purge, and the CDN sets max-age=60 on translations. With the client's own 60-second TTL cache in front of that, a published string is live in roughly a minute at worst — no redeploy, no bundle rebuild. Call getMessages with forceRefresh through getManifest if you need to bypass it during QA.

Prohlédněte si další průvodce po frameworku

Get started

Začněte stavět s Vue i18n

K dispozici je bezplatná úroveň. Není vyžadována kreditní karta.