To make a website multilingual, give each language its own URL, such as example.com/fr/, translate the page text, titles and descriptions, mark each page with its lang attribute, and link the versions together with hreflang tags. Let visitors switch language with a link rather than redirecting them automatically. A widget that only translates in the browser does not help search.
| Do | Avoid |
|---|---|
| Separate URLs per language | One URL that changes language by cookie |
| hreflang on every version | Pointing every language's canonical at English |
| A visible language switcher | Redirecting by country or browser language |
Updated
Whether you use a plugin, a translation service or build it yourself, the same few rules decide whether translated pages can be found in search. The tables compare the options and URL structures; the code shows each tag you need.
Ready to write the tags? Use the hreflang generator.
| Option | How it works | Search engines see the translations? | Good for |
|---|---|---|---|
| Browser translation (visitor's own) | The visitor's browser translates the page on the fly | No | Nothing you control; a fallback only |
| Translate widget on the page | A script swaps text after the page loads | Usually not, unless it also creates separate URLs | Quick help for visitors, not for SEO |
| Translation plugin or proxy service | Creates a translated copy of each page at its own URL | Yes, if each language has its own URL and hreflang | Existing sites that need many languages fast |
| Built into your CMS or framework (i18n) | You store each page's text per language and render separate URLs | Yes | Sites you build and maintain yourself |
| Separate sites per country | Different domains with their own content | Yes | Large businesses with local teams |
| Structure | Example | Pros | Cons |
|---|---|---|---|
| Subdirectory | example.com/fr/ | One domain, easy to set up, shares authority | Harder to host each language in a different country |
| Subdomain | fr.example.com | Easy to separate technically | Treated more like a separate site |
| Country domain | example.fr | Strongest country signal | Costly; each domain builds authority on its own |
| URL parameter | example.com/?lang=fr | Simple to bolt on | Not recommended; easy to get wrong |
Screen readers pick the right voice and browsers stop offering to translate a page that is already in the visitor's language.
<html lang="fr">
...
<p>Nous sommes ouverts le dimanche. <span lang="en">Open on Sundays.</span></p>Every language version lists all versions, including itself, and the set must be identical on each. x-default is the page for everyone else, often a language chooser or the English page.
<link rel="alternate" hreflang="en" href="https://example.com/menu" />
<link rel="alternate" hreflang="fr" href="https://example.com/fr/menu" />
<link rel="alternate" hreflang="es-MX" href="https://example.com/es-mx/menu" />
<link rel="alternate" hreflang="x-default" href="https://example.com/menu" />For large sites, listing alternates in the sitemap keeps page heads small. Use one method consistently.
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
<url>
<loc>https://example.com/menu</loc>
<xhtml:link rel="alternate" hreflang="en" href="https://example.com/menu"/>
<xhtml:link rel="alternate" hreflang="fr" href="https://example.com/fr/menu"/>
</url>
<url>
<loc>https://example.com/fr/menu</loc>
<xhtml:link rel="alternate" hreflang="en" href="https://example.com/menu"/>
<xhtml:link rel="alternate" hreflang="fr" href="https://example.com/fr/menu"/>
</url>
</urlset>Offer a choice instead of redirecting by location. Write each language's name in that language, and link to the same page in the other language, not the home page.
<nav aria-label="Language">
<a href="/menu" hreflang="en" lang="en">English</a>
<a href="/fr/menu" hreflang="fr" lang="fr" aria-current="page">Français</a>
<a href="/es-mx/menu" hreflang="es-MX" lang="es">Español (México)</a>
</nav>Reading the browser's language to show a polite banner is fine. Redirecting automatically stops crawlers (which mostly crawl from the US) from seeing other versions.
<p id="lang-hint" hidden>
<a href="/fr/">Ce site existe aussi en français</a>
</p>
<script>
const wantsFrench = navigator.languages.some((l) => l.startsWith("fr"));
const onEnglish = !location.pathname.startsWith("/fr/");
if (wantsFrench && onEnglish) document.getElementById("lang-hint").hidden = false;
console.log("Browser languages:", navigator.languages.join(", "));
</script>| Check | Why |
|---|---|
| Each language has its own URL | Search engines index URLs, not toggles |
| Title, meta description and headings are translated | These are what appear in results |
| Slugs translated where it makes sense | Helps people trust the result |
| hreflang set is complete and reciprocal on every version | Missing return links make Google ignore the annotation |
| Canonical points to the page's own language version | Pointing all languages at English hides the translations |
| No automatic redirect by IP or browser language | Crawlers and travellers cannot reach other versions |
| Prices, dates, phone formats and addresses localised | Translation alone is not localisation |
| Machine translations reviewed by a fluent speaker | Unreviewed text reads badly and can mislead |
Translation changes the words; localisation changes what the words point to. A Mexican visitor needs prices in pesos, dates written day first, and a phone number they can call. Check those details on each language version, not just the text.
For visitors in a hurry, it helps a little. For search, no: browser or widget translation does not create pages that can be indexed, so you will not rank in those languages.
No. The same content in different languages is not duplicate content. hreflang helps search engines show the right language to each searcher.
Yes, as a first draft. Have someone fluent review it, especially headlines, calls to action and anything legal. Unreviewed, low-quality machine text at scale can be treated as spam.
A subdirectory such as /fr/ is simplest for most sites and keeps everything on one domain. Subdomains work too; both are supported as long as each language has its own URL.
Related: Hreflang generator, JavaScript date format, Single page app SEO, XML sitemap generator, All free tools.
Start for free or see all free tools. We.Inc is free to start, with no card needed. AI building is on paid plans from $20 a month.
We.Inc is an AI-powered website builder you can resell under your own brand. Launch a branded client dashboard, bill on Stripe Connect, and deliver AI-generated websites in minutes. White-label plans start at $99 a month for 25 client sites, with a 7-day free trial and no per-site fees.