Better Translation

How it works

How the Vite plugin discovers Messages, keeps Locale values in sync, and generates runtime loaders.

The Vite plugin scans your source for Translation markers at build time, gives each Message a stable lookup id, and keeps your Locale values in sync. At runtime your app loads a flat map of translated strings for the active Locale, so your components keep rendering normal UI.

1. Mark

Wrap copy in a Translation marker where you author it. No keys to invent.

2. Discover

The plugin discovers Messages and builds a Manifest keyed by stable lookup id.

3. Fill Locale values

Local mode writes Runtime bundles in your repo. Remote mode syncs the Manifest to the platform.

4. Load

Your app loads flat Runtime bundles by Locale. No Manifest metadata reaches the browser.

Source discovery

Better Translation looks for markers such as T, useT, getT, and t() inside your configured source roots. Each discovered Message records the Default locale text, Variable placeholders, optional context, and durable source references in the private Manifest.

The lookup id is stable, so moving a Message through the codebase does not create a new runtime key. If two Messages need different translations, add context or an explicit id to separate them.

When a T Message contains a supported inline element or source-owned component, the plugin represents that authored renderer with a numbered Rich-text slot such as <0>...</0> or <1/>. The numbered form is the Message translators see; component implementations, props, events, and bindings remain in source code.

Locale values

The Manifest is source metadata. Locale values are the translated strings for each configured Locale. In local mode, the plugin writes those values into generated JSON files in your app. In remote mode, the plugin syncs the Manifest to a hosted Project and the platform stores branch-local Locale values.

Local translation is an optional local-mode convenience. The translate function receives the missing Messages for a target Locale and returns a lookup id to translated string map. Remote mode does not use that package-local function; it uses the Platform translator.

Runtime loading

Your app imports loadMessages from the virtual better-translation/messages module. The plugin generates that module from your runtime mode:

Runtime configLoader behavior
local + target: moduleImports generated Locale JSON through Vite.
local + target: publicFetches generated Locale JSON from Vite public assets.
remoteFetches hosted Runtime bundles for the resolved Project Branch.

Every loader returns the same shape: a flat lookup id to translated string object. Runtime bundles do not contain Manifest metadata, source ownership, editor state, or write credentials.

Rich-text Locale values are still strings. React and Svelte render numbered slots through the elements and components authored in the original T marker; they never turn a translated value into arbitrary HTML. The runtime verifies that a translated value preserves the source variables and numbered-tag topology. If it does not, T renders the authored source content instead.

One runtime API

Your app still calls loadMessages(locale) in every mode. The Vite plugin owns the difference between local files, public files, and hosted Runtime bundles.

On this page