React + Vite internationalization
Keep ordinary JSX in your components. Hedgeling's Vite plugin wraps supported user-facing strings during the build; the runtime selects translated text from the generated bundle.
1. Install with package access
Use Node.js 20 or later and a Hedgeling seat token, shown when you create a workspace and under Package seats in the console. Point the @hedgeling scope at Hedgeling's registry in your project's .npmrc, with the token in the HEDGELING_TOKEN environment variable. This guide assumes an existing React + Vite application with TypeScript and the React Vite plugin.
# .npmrc
@hedgeling:registry=https://platform.thehedgeling.com/registry/
//platform.thehedgeling.com/registry/:_authToken=${HEDGELING_TOKEN}npm install @hedgeling/i18nYarn 1 and pnpm 9 use the same two lines. pnpm 10 and later do not read a token from a project's .npmrc: keep the first line there and run pnpm config set "//platform.thehedgeling.com/registry/:_authToken" "$HEDGELING_TOKEN" once. Yarn 2 and later use .yarnrc.yml instead, with an npmScopes entry for hedgeling that sets npmRegistryServer, npmAuthToken and npmAlwaysAuth.
If npm reports an authorization error, check that HEDGELING_TOKEN is set and that the seat is active. Do not paste a seat token into application source.
2. Configure extraction
Create .hedgeling/extract.config.json in the application root. Keep generated public assets outside the source scan.
{
"sourceLocale": "en-US",
"locales": ["fr-FR", "de-DE"],
"scanRoots": ["src"],
"outputDir": "public/i18n",
"runtimeOutputDir": "public"
}3. Add the Vite plugin
In vite.config.ts, keep the React plugin and add Hedgeling. Hedgeling's transform runs before JSX compilation.
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { hedgelingI18n } from "@hedgeling/i18n/vite";
export default defineConfig({
plugins: [hedgelingI18n(), react()],
});4. Configure the runtime and language selector
Wrap the application entry in HedgelingProvider. Declare the source and supported locales explicitly.
import { createRoot } from "react-dom/client";
import { HedgelingProvider, useTranslation } from "@hedgeling/i18n/runtime";
import { App } from "./App";
function LanguagePicker() {
const { locale, setLocale } = useTranslation();
return <label>Language
<select value={locale} onChange={event => setLocale(event.target.value)}>
<option value="en-US">English</option>
<option value="fr-FR">Français</option>
<option value="de-DE">Deutsch</option>
</select>
</label>;
}
createRoot(document.getElementById("root")!).render(
<HedgelingProvider sourceLocale="en-US" supportedLocales={["en-US", "fr-FR", "de-DE"]}>
<LanguagePicker />
<App />
</HedgelingProvider>
);5. Generate and verify artifacts
npx hedgeling extract --write
npx hedgeling translate --no-mt
npx hedgeling check
npm run buildThis first pass creates the catalog and runtime artifacts without requesting machine translation. Source-language fallback is expected until translations exist. Configure a provider and run npx hedgeling translate when ready to send the selected content for translation; provider usage may incur costs. Review the generated changes before delivery.
The default runtime requests /hedgeling-bundle.json and /hedgeling-source-key-map.json. Serve them from the generated public directory. Applications deployed under a subpath should set the provider's bundle and key-map URLs to match that deployment.
Troubleshooting
- If text stays in English, verify that the bundle contains the target translations and that both runtime files return JSON, not an HTML fallback.
- If a provider is mounted but no strings are wrapped, check the Vite plugin and extraction scan roots. A language selector alone does not perform extraction.
- Review diagnostics for text that requires explicit handling, including strings that serve both UI and program logic.
- For search-facing pages, generate translated HTML at stable language URLs. Browser-side locale switching alone does not make each language independently discoverable.