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.
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| Artifact | Description |
|---|---|
locales/*.json | Flat Runtime bundles, one per Locale, keyed by lookup id. These are what your app loads. Commit them. |
.cache/better-translation | Plugin-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.
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:
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.
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.
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 option | Description |
|---|---|
model | AI SDK model value. Defaults to an AI Gateway model string. |
prompt | Translation brief for tone, glossary, and domain guidance. |
temperature | Optional 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 generateThe package also exposes the longer binary name:
better-translation generateThe 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.