Multilingual Personal Websites — Help People and Machines Find the Right Language
A website can have an English page, an Indonesian translation, and a German translation, yet still leave an important question unanswered: how does a visitor, a screen reader, or a search engine know that these three URLs belong together?
The answer is not one magic tag. A multilingual site needs several small signals with different jobs: a stable URL for each translation, the correct document language, explicit links between equivalent pages, and a visible way for readers to choose. Confusing those jobs is easy. A page may have lang="de" but no route to the English version, or a language switcher may work while the page metadata describes the wrong relationship.
This guide builds a modest model for a personal website or small CMS. It does not promise rankings, and it does not assume that every site needs country-level targeting. The aim is simpler: make each translation honest about what it is and clear about where its siblings live.
Four Layers, Four Different Jobs
It helps to separate multilingual publishing into four layers:
- URL: gives each complete translation a durable address.
lang: describes the language of the current HTML document or an element within it.hreflang: associates equivalent localized URLs for Google Search.- Language switcher: lets a person move to another version.
These layers reinforce one another, but they are not substitutes. The W3C Internationalization guidance recommends declaring the page language on the html element. Google, meanwhile, says it uses visible page content rather than lang or hreflang to detect language. That is not a contradiction: document semantics and a search product's language detection are different systems.
Give Every Complete Translation a Stable URL
A translated page should be directly addressable. For a small site on one domain, subdirectories are often the least complicated arrangement:
https://example.com/quiet-web/
https://example.com/id/web-yang-tenang/
https://example.com/de/das-ruhige-web/
Subdomains or separate domains can also work. The important property is not the shape itself but stability: the URL should return the same language without depending on a cookie, JavaScript state, or a guessed preference. Google's guidance for multilingual sites recommends different URLs for different language versions and warns that dynamically changing one URL by browser language can make some variations difficult to crawl.
A language-specific slug is reasonable when it helps the reader understand the address. It does create an editorial responsibility: links between translations must come from stored relationships, not from trying to transform one slug into another. Replacing words in a URL is not translation management.
Declare the Language of the Document
For ordinary HTML served as text/html, put the default language on the root element:
<html lang="en">
<html lang="id">
<html lang="de">
According to the HTML Standard, the language of an element is determined by its own language attributes and inherited context. The declaration can influence language-sensitive processing. MDN also notes its accessibility importance: assistive technology can use the information to select appropriate pronunciation.
When a short passage changes language, mark that passage rather than changing the whole document:
<p>The Indonesian phrase <span lang="id">pelan-pelan</span>
means doing something gradually or carefully.</p>
Do not infer language from UTF-8, a flag icon, or the URL alone. Encoding says how characters are represented, not which human language they form. A flag represents a country, while languages routinely cross borders.
Use Language Tags as Precisely as Necessary
The values above are language tags defined through BCP 47 and RFC 5646. A tag begins with a language subtag and may add information such as script or region, separated by hyphens. Examples include de, en-GB, and zh-Hant.
More detail is not automatically more correct. If one English translation is written for English readers generally, en is clearer than inventing a regional distinction. Use en-GB when the content genuinely represents British usage, not merely because the server happens to be in Europe. RFC 5646 says a region subtag may be omitted when it adds no distinguishing value.
Case does not change a BCP 47 tag's meaning, although conventional formatting keeps language lowercase, script title-cased, and region uppercase. Consistency still matters because inconsistent strings make templates and tests harder to reason about.
Connect Equivalent Pages with hreflang
For Google Search, localized versions can be declared through HTML, HTTP headers, or an XML sitemap. Google's localized-version documentation describes the methods as equivalent and says there is no Search benefit to implementing all three. For a small HTML site, generating links in the document head is usually easy to inspect:
<link rel="alternate" hreflang="en"
href="https://example.com/quiet-web/">
<link rel="alternate" hreflang="id"
href="https://example.com/id/web-yang-tenang/">
<link rel="alternate" hreflang="de"
href="https://example.com/de/das-ruhige-web/">
The same complete set belongs on all three versions. Each page lists itself, each alternate URL is fully qualified, and each sibling points back. Google says missing return links can cause annotations to be ignored. This reciprocity is easier to maintain when the CMS treats translations as members of one content group rather than unrelated posts.
An optional hreflang="x-default" can point to a neutral selector or fallback for unmatched language settings. It is not a fourth spoken language and is not necessary for every three-language blog. Add it only when a real fallback page exists.
Keep Canonical and Alternate Relationships Separate
A canonical link answers, “Which URL is the preferred identity of this page among duplicate or near-duplicate URLs?” An alternate-language link answers, “Where is the equivalent page for another language or locale?” Those are different questions.
If the main content is genuinely translated, Google says the localized pages are not considered duplicates merely because they express the same subject in different languages. A practical pattern is therefore for each translation to use its own canonical URL while the hreflang cluster connects the set:
<!-- On the Indonesian page -->
<link rel="canonical"
href="https://example.com/id/web-yang-tenang/">
Pointing every canonical to the English source can undermine the message that the localized URLs are valid pages in their own right. However, boilerplate translated around unchanged main content is a different case. Do not label pages equivalent simply because their navigation has been translated.
Let the Reader Override Your Guess
Browser preferences can be useful as a hint, but they are not consent. A shared device, a traveler, a language learner, or someone following a specific link may want a version that does not match the browser default. Google's multilingual-site guidance advises against automatic redirects between language versions and recommends links that allow users to choose.
The switcher should use ordinary crawlable links and name languages clearly:
<nav aria-label="Language">
<a href="https://example.com/quiet-web/" lang="en">English</a>
<a href="https://example.com/id/web-yang-tenang/" lang="id">Indonesia</a>
<a href="https://example.com/de/das-ruhige-web/" lang="de">Deutsch</a>
</nav>
Writing each language name in that language makes it recognizable. The lang on each label describes the inline text, while the surrounding page keeps its own default language. JavaScript may enhance the control, but navigation should not disappear when scripts fail.
Be Honest About Missing and Partial Translations
The hardest problem is often editorial rather than technical. A CMS may have English, Indonesian, and German buttons globally even though one article exists only in English. Linking the missing German choice to an English page and annotating it as German creates a false relationship.
Only publish an alternate annotation when the destination exists, is public, and contains the corresponding content. If a translation is still a draft, omit it from the public cluster and switcher. If only the interface is translated while the article remains English, declare the document according to the actual main content and explain the limitation to readers where useful.
Translations can also drift after the source changes. A reliable publishing workflow should record translation status and recheck the set after a substantial revision. Perfect simultaneity is not always possible, but metadata should describe the pages that exist now, not the versions an editor hopes to finish later.
Validate the Set, Not Just One Page
A single page can look correct while the relationship graph is broken. For every published content group, verify:
- Each URL returns a successful public response in the expected language.
- The root
htmlelement has the correctlangvalue. - Canonical URLs resolve and identify the current localized page.
- Every version emits the same complete set of reciprocal
hreflanglinks. - The visible switcher reaches the corresponding article, not merely a locale homepage.
- No draft, redirect, error page, or untranslated placeholder appears in the cluster.
Test the rendered HTML rather than only the database or template. Metadata can be escaped incorrectly, injected outside head, or cached after a translation changes. A small automated check can fetch every sibling, parse the links, and confirm reciprocity; a manual pass should still judge whether the pages are truly equivalent.
A Truthful Map Between Languages
Multilingual publishing is not completed by placing three flags in a header. It is a promise that each address contains the language it claims, each equivalent page points back to its siblings, and the reader remains free to choose.
Start with the smallest truthful system: stable URLs, accurate lang values, one maintainable hreflang method, self-consistent canonical links, and visible navigation. Add regions or x-default only when the content model actually needs them. The result may not look dramatic, but good metadata is usually quiet. It removes ambiguity without pretending to decide what a reader wants.
References
- WHATWG — HTML Standard: The
langandxml:langattributes - RFC Editor — RFC 5646: Tags for Identifying Languages
- W3C Internationalization — Declaring language in HTML
- Google Search Central — Tell Google about localized versions of your page
- Google Search Central — Managing multi-regional and multilingual sites
- MDN Web Docs —
langHTML global attribute
