Add Internationalization to Your Next.js Site Without Rebuilding Routing
Published on SiteLocaleAI Blog ---
Internationalization (i18n) is a must‑have for any site that wants to attract a global audience. In a typical Next.js project you might reach to create language‑specific routes (/en, /fr, …) or use next-i18next. That approach works, but it forces you to restructure your routing, which can be risky for mature apps.
SiteLocaleAI offers a different path: a framework‑agnostic, self‑hosted JavaScript library that translates page content on the fly, localizes prices with psychological rounding, and even pre‑renders translated pages for SEO. Because it runs entirely in the browser (or on the server via Node for CLI), you keep your existing Next.js routing untouched.
In this tutorial we’ll:
1. Install the SiteLocaleAI library.
2. Configure it to use your own LLM API key.
3. Add a simple language switcher.
4. Enable price localization.
5. Run the SEO pre‑render CLI so search engines index the translated pages.
Tip: All code snippets assume a fresh Next.js 14 project (
n create-next-app@latest my‑intl‑app).
1. Install the SiteLocaleAI Package
SiteLocaleAI is distributed as an npm package that bundles the client‑side library. Run:
npm i @sitelocaleai/client
If you prefer Yarn or PNPM, the command is the same.
2. Create a Global Provider
Because the library is framework‑agnostic, we’ll wrap the whole app in a React context that loads the translation model once. Create lib/localeProvider.jsx:
// lib/localeProvider.jsx
import { createContext, useEffect, useState } from "react";
import { SiteLocaleAI } from "@sitelocaleai/client";
export const LocaleContext = createContext({
locale: "en",
setLocale: () => {},
t: (key) => key,
});
export default function LocaleProvider({ children }) {
const [locale, setLocale] = useState("en");
const [translator, setTranslator] = useState(null);
useEffect(() => {
// Initialise the library with your LLM API key (e.g., Claude or GPT‑4o‑mini)
const ai = new SiteLocaleAI({
apiKey: process.env.NEXT_PUBLIC_SITELocaleAI_API_KEY,
model: "gpt-4o-mini",
defaultLocale: "en",
});
setTranslator(ai);
}, []);
// Simple translation helper that falls back to the original text
const t = async (text) => {
if (!translator) return text;
return await translator.translate(text, locale);
};
return (
<LocaleContext.Provider value={{ locale, setLocale, t }}>
{children}
</LocaleContext.Provider>
);
}
Add the provider to pages/_app.jsx:
// pages/_app.jsx
import LocaleProvider from "../lib/localeProvider";
import "../styles/globals.css";
export default function MyApp({ Component, pageProps }) {
return (
<LocaleProvider>
<Component {...pageProps} />
</LocaleProvider>
);
}
3. Build a Language Switcher
Create a tiny component that toggles the locale. Place it in components/LanguageSwitcher.jsx:
import { useContext } from "react";
import { LocaleContext } from "../lib/localeProvider";
export default function LanguageSwitcher() {
const { locale, setLocale } = useContext(LocaleContext);
const change = (e) => setLocale(e.target.value);
return (
<select value={locale} onChange={change} aria-label="Select language">
<option value="en">English</option>
<option value="fr">Français</option>
<option value="es">Español</option>
<option value="de">Deutsch</option>
</select>
);
}
Use it in your layout (e.g., components/Header.jsx):
import LanguageSwitcher from "./LanguageSwitcher";
export default function Header() {
return (
<header className="flex justify-between items-center p-4">
<h1>My International Store</h1>
<LanguageSwitcher />
</header>
);
}
4. Translate Text on the Fly
Inside any page you can call the t function from the context. Here’s an example for pages/index.jsx:
import { useContext, useEffect, useState } from "react";
import { LocaleContext } from "../lib/localeProvider";
export default function Home() {
const { t } = useContext(LocaleContext);
const [welcome, setWelcome] = useState("");
useEffect(() => {
// Translate once on mount or when locale changes
const load = async () => {
const txt = await t("Welcome to our global store!");
setWelcome(txt);
};
load();
}, [t]);
return (
<main className="p-8">
<h2>{welcome}</h2>
<p>{/* other content */}</p>
</main>
);
}
The library contacts the LLM you configured (Claude, GPT‑4o‑mini, etc.) and returns a translation in the selected language. Because the call is asynchronous, you can add a loading spinner if you wish.
5. Localize Prices with Psychological Rounding
SiteLocaleAI also offers a localizePrice helper that converts a numeric value to the target currency and applies psychological rounding (e.g., $9.99 → $9.95). Extend localeProvider.jsx:
// Inside the provider after translator is set
const localizePrice = async (amount, currency) => {
if (!translator) return `${amount} ${currency}`;
return await translator.localizePrice(amount, currency);
};
// Export via context
<LocaleContext.Provider value={{ locale, setLocale, t, localizePrice }}>
Use it in a component:
import { useContext } from "react";
import { LocaleContext } from "../lib/localeProvider";
export default function ProductCard({ priceUSD }) {
const { localizePrice, locale } = useContext(LocaleContext);
const [price, setPrice] = useState("");
useEffect(() => {
const fetchPrice = async () => {
// Map locale to currency – simple example
const currencyMap = { en: "USD", fr: "EUR", es: "EUR", de: "EUR" };
const priceStr = await localizePrice(priceUSD, currencyMap[locale] || "USD");
setPrice(priceStr);
};
fetchPrice();
}, [priceUSD, locale, localizePrice]);
return (
<div className="card">
<p>Price: {price}</p>
</div>
);
}
Now every visitor sees a price that feels natural for their market, without any server‑side calculations.
6. SEO‑Friendly Pre‑Rendering with the CLI
Search engines can’t execute client‑side translation scripts, so you need static HTML for each language. SiteLocaleAI ships a CLI that crawls your site, renders pages with the selected locale, and writes the output to a dist/ folder.
First, install the CLI globally (or as a dev dependency):
npm i -D @sitelocaleai/cli
Add a script to package.json:
"scripts": {
"build": "next build",
"prerender": "sitelocaleai prerender --locales en,fr,es,de --output ./dist"
}
Run it after a normal Next.js build:
npm run build && npm run prerender
The CLI will:
1. Spin up a headless Chromium instance.
2. Load each route (/, /product/42, …) with the Accept-Language header set to the target locale.
3. Capture the fully rendered HTML (including translated text and localized prices).
4. Save the files under dist/<locale>/….
You can now point your CDN or static host to the dist folder. Search engines will index the language‑specific pages, giving you the SEO boost of a fully localized site without changing your Next.js routing logic.
For more details, see the official docs: https://sitelocaleai.com/docs/seo-pre-rendering.
7. Deploy and Test
- Set environment variables – add
NEXT_PUBLIC_SITELocaleAI_API_KEYto your Vercel/Netlify env. - Run the pre‑render step – verify the HTML files contain the translated strings.
- Check price rounding – open a product page in each language and confirm the price looks natural.
- Validate SEO – use
curl -H "Accept-Language: fr" https://yourdomain.com/and inspect the returned HTML.
8. Wrap‑Up
You now have a fully internationalized Next.js site that:
- Keeps the original routing untouched.
- Translates content on the fly using your own LLM API key.
- Localizes prices with psychological rounding.
- Generates SEO‑ready static pages for every supported language.
All of this is powered by SiteLocaleAI’s drop‑in JavaScript library, which works with any framework (React, Vue, WordPress, Shopify, etc.) and can be self‑hosted for privacy and cost control.
Ready to go global?
Try SiteLocaleAI today and see how easy it is to add multilingual support, price localization, and SEO‑friendly pre‑rendering to any web project. Visit the quick‑start guide and start translating in minutes!