Better Translation

Local mode

The default, account-free mode. The plugin writes Runtime bundles into your repo and can fill missing values during dev.

Local mode is the default and needs no account. The plugin writes Runtime bundles into your repo and the runtime loads them. You commit the generated artifacts alongside your code.

Generated artifacts

By default everything lands under src/lib/bt in your app. Here is what the plugin generates and where, so you know exactly what is in your tree.

generated artifacts
src/lib/bt/
└─ locales/
│  ├─ en.json          # flat lookup id -> string per Locale
│  ├─ es.json
│  └─ fr.json

.cache/better-translation/
├─ cache.json          # translation cache, avoids re-translating
└─ manifest.json       # private source metadata catalog
ArtifactDescription
locales/*.jsonFlat Runtime bundles, one per Locale, keyed by lookup id. These are what your app loads. Commit them.
.cache/better-translationPlugin-owned cache and private Manifest state. Do not commit it.

Local editor

Local mode can expose a dev-only editor from the Vite plugin. It lets you search Messages, inspect source details, and edit non-default Locale values from inside your app's dev server.

vite.config.ts
betterTranslation({
  locales: ["en", "es", "fr"],
  defaultLocale: "en",
  runtime: {
    type: "local",
    editor: true,
  },
})

When enabled, the editor is served during vite dev at /__better-translation. The plugin logs the URL when the dev server starts. The editor reads the private Manifest from .cache/better-translation and writes edits back to the flat Runtime bundles under your local runtime output.

You can customize the path or ask the plugin to open the editor automatically:

vite.config.ts
betterTranslation({
  locales: ["en", "es", "fr"],
  defaultLocale: "en",
  runtime: {
    type: "local",
    editor: {
      path: "/translations",
      open: true,
    },
  },
})

Set editor: false or omit editor to disable it. The editor only runs for local runtime mode during vite dev; production builds do not serve it.

Local editor scope

The local editor edits flat Runtime bundles in your repo. It does not create Projects, Branches, hosted sync, auth, or source provenance. Existing values are treated as present local values, and missing values are the only special state.

Serve as static assets

Prefer fetching Runtime bundles as static assets instead of bundling them? Set the local runtime target to public. The plugin writes the bundles under your Vite public directory and the loader fetches them at runtime.

vite.config.ts
betterTranslation({
  locales: ["en", "es", "fr"],
  defaultLocale: "en",
  runtime: {
    type: "local",
    target: "public", // default is "module"
  },
})

Local translation

Local mode can fill missing non-default Locale values during dev with a translate function. You can provide your own function or use createAiTranslate, the package helper that routes through the Vercel AI Gateway.

vite.config.ts
import { betterTranslation } from "better-translation/vite"
import { createAiTranslate } from "better-translation/ai"

betterTranslation({
  locales: ["en", "es", "fr"],
  defaultLocale: "en",
  runtime: {
    type: "local",
    translationBatchSize: 25,
    translate: createAiTranslate({
      prompt: "Friendly, concise product UI copy.",
    }),
  },
})

During dev the plugin batches missing Messages, calls translate, and writes the results into your local Runtime bundles and cache after every completed batch. translationBatchSize defaults to 25 and is the single batching and persistence boundary. The built-in AI helper translates the Messages in that batch concurrently; a custom translator controls how it processes the batch. When TranslateProvider receives the active locale, each completed batch also updates matching React or Svelte content through Vite HMR without remounting application state. Production local builds never call translate, they only check that committed Runtime bundles are complete.

AI helper optionDescription
modelAI SDK model value. Defaults to an AI Gateway model string.
promptTranslation brief for tone, glossary, and domain guidance.
temperatureOptional temperature forwarded to the model provider.

Write your own translator

translate is just a function that receives the missing Messages and a target Locale and returns a map of lookup id to translated string. Use any provider you like, createAiTranslate is only a convenience. Every returned value must preserve the source Variable placeholders and numbered Rich-text slots; the plugin rejects an incompatible result before writing it.

Generate without a dev server

Run the same local generation step from the command line when you need Locale files updated without starting Vite dev:

bt generate

The package also exposes the longer binary name:

better-translation generate

The command loads your Vite config, finds betterTranslation(), scans source files, writes the private Manifest and local Runtime bundles, and calls runtime.translate for missing non-default Locale values when local translation is configured. This is useful in agent or CI workflows that change marked copy and need generated artifacts refreshed before running a production build check.

On this page