Add Internationalization to Next.js Without Rebuilding Routes
TL;DR – With SiteLocaleAI you can turn any Next.js page into a multilingual experience without touching the pages/ folder or the router. The library runs in the browser, pulls translations from your own LLM API key, and even adjusts prices with psychological rounding. A simple CLI step pre‑renders the translated HTML for search engines, giving you full SEO coverage.
1. Why SiteLocaleAI for Next.js?
- Drop‑in, framework‑agnostic – Just add a single script tag or import the npm package. No custom
_app.jshacks needed. - Self‑hosted – You provide your own LLM keys (Claude, GPT‑4o‑mini, etc.), keeping data private and costs predictable.
- SEO‑ready – The CLI can pre‑render every locale, so Google indexes the exact translated HTML.
- Price localization – Prices are automatically rounded to the most persuasive values per currency (e.g., $9.99 → $9.95).
All of this works with the default file‑based routing that Next.js ships with, meaning you don’t have to rebuild or duplicate routes for each language.
2. Install the Library
# Using npm
npm i @sitelocaleai/react
# Or yarn
yarn add @sitelocaleai/react
Note: The package works the same in a plain React environment, so you can also import it in a custom server‑side component if you prefer.
3. Configure the Provider
Create a siteLocaleConfig.js file at the root of your project. This is where you pass your LLM API key and the list of locales you want to support.
// siteLocaleConfig.js
export const localeConfig = {
// Your LLM endpoint – can be Claude, OpenAI, etc.
llmEndpoint: "https://api.openai.com/v1/chat/completions",
apiKey: process.env.SITELOCALEAI_API_KEY, // keep it secret in .env
// Locales you want to serve
locales: ["en", "es", "fr", "de"],
// Default language – matches the original content
defaultLocale: "en",
// Price rounding rules (optional, defaults are sensible)
priceRounding: {
USD: 0.95,
EUR: 0.99,
GBP: 0.95,
},
};
Add the provider to _app.js so every page can access the translation functions:
// pages/_app.js
import { SiteLocaleProvider } from "@sitelocaleai/react";
import { localeConfig } from "../siteLocaleConfig";
function MyApp({ Component, pageProps }) {
return (
<SiteLocaleProvider config={localeConfig}>
<Component {...pageProps} />
</SiteLocaleProvider>
);
}
export default MyApp;
That’s it – the provider injects a useLocale hook that you can call anywhere in your component tree.
4. Translating Content on the Fly
Below is a typical product page. Notice how we wrap the text we want translated with the t function from the hook. The library automatically detects the user’s language via Accept‑Language header or a URL query (?lang=es).
// pages/product/[id].js
import { useRouter } from "next/router";
import { useLocale } from "@sitelocaleai/react";
export default function ProductPage({ product }) {
const { locale, t, formatPrice } = useLocale();
const router = useRouter();
// Switch language handler (optional UI)
const changeLang = (lang) => {
router.push({ pathname: router.pathname, query: { ...router.query, lang } }, undefined, { shallow: true });
};
return (
<div className="product">
<h1>{t(product.title)}</h1>
<p>{t(product.description)}</p>
<p className="price">{formatPrice(product.price, "USD")}</p>
<select onChange={(e) => changeLang(e.target.value)} defaultValue={locale}>
<option value="en">English</option>
<option value="es">Español</option>
<option value="fr">Français</option>
<option value="de">Deutsch</option>
</select>
</div>
);
}
// getStaticProps can stay unchanged – we still fetch the product once.
export async function getStaticProps({ params }) {
const product = await fetchProductFromCMS(params.id);
return { props: { product } };
}
What happens under the hood?
- The t function sends the original string to your LLM endpoint, asking for a translation in the current locale.
- formatPrice applies the rounding rule defined in siteLocaleConfig.js and formats the number with the appropriate currency symbol.
- Because the translation occurs client‑side, the original page is rendered instantly; the library swaps in the translated text as soon as the response arrives.
5. SEO‑Friendly Pre‑Rendering with the CLI
Search engines don’t execute JavaScript the same way browsers do, so we need static HTML for each locale. SiteLocaleAI ships a CLI that crawls your routes and writes pre‑translated files to the out/ folder.
# Install the CLI globally (or use npx)
npx @sitelocaleai/cli pre-render \
--output ./out \
--locales en,es,fr,de \
--base-url https://yourdomain.com
The command does the following:
1. Starts a headless Chromium instance.
2. Visits every page defined in next.config.js (exportPathMap).
3. Requests translations for each locale via the same LLM keys.
4. Writes the fully rendered HTML to out/<locale>/.
Now you can serve the static files with any CDN or Vercel edge function. Google will see the exact translated markup, giving you the same ranking benefits as a hand‑crafted multilingual site.
Tip: Add the CLI step to your CI pipeline so the static folder is always up‑to‑date.
6. No Routing Changes Required
Because the library works at the component level, you don’t need to create separate [locale]/ folders or duplicate page files. The URL stays the same (/product/123) and the language is inferred from the query string or a cookie. If you prefer clean URLs, you can add a tiny rewrite rule in next.config.js:
// next.config.js
module.exports = {
async rewrites() {
return [
{
source: "/:lang(en|es|fr|de)/:slug*",
destination: "/:slug*",
},
];
},
};
The rewrite simply strips the locale prefix before Next.js resolves the page, while the useLocale hook still reads the lang param.
7. Integrating with Existing Analytics
If you already track pageviews, you can send the detected locale as a custom dimension:
import { useEffect } from "react";
import { useLocale } from "@sitelocaleai/react";
export default function AnalyticsWrapper({ children }) {
const { locale } = useLocale();
useEffect(() => {
if (window.gtag) {
window.gtag('set', { 'language': locale });
}
}, [locale]);
return children;
}
Wrap your _app.js component with <AnalyticsWrapper> to keep your reports language‑aware.
8. Resources & Next Steps
- Detailed API reference: https://sitelocaleai.com/docs/api
- CLI usage guide: https://sitelocaleai.com/docs/cli
- Pricing & limits: https://sitelocaleai.com/pricing
9. Try SiteLocaleAI Today!
Ready to make your Next.js site truly global without a routing overhaul? Sign up for the $5 Indie plan, grab your LLM API key, and follow this guide to see instant translations and SEO‑ready pages. If you need more locales, higher request volumes, or enterprise support, our $49 Starter, $99 Growth, and $249 Enterprise tiers scale with you.
Start now: https://sitelocaleai.com/docs/quickstart
Happy multilingual coding!