Languages and Text Direction
Prerequisites: Document structure
Internationalization (i18n) is making pages work in any language and writing system.
lang
Set the page language on html, and mark passages in other languages:
<p>The French call it <span lang="fr">pain de campagne</span>.</p>
<blockquote lang="de"><p>Kein Brot ohne Fleiß.</p></blockquote>
Language tags follow BCP 47: a language (en, zh), optionally a
script (zh-Hant) and a region (en-GB, pt-BR). Screen readers switch
voices, browsers pick the right fonts and quotation marks, and CSS
hyphens: auto needs it.
Right-to-left languages
Arabic, Hebrew, Persian, and Urdu are written right to left. Set dir:
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="utf-8">
<title>مخبز الزاوية</title>
</head>
<body>
<h1>خبز طازج كل صباح</h1>
<p>نفتح في الساعة ٧ صباحاً.</p>
</body>
</html>
With dir="rtl", the whole layout flips: text aligns right, lists put
bullets on the right, and table columns run right to left. Use CSS
logical properties (margin-inline-start instead of margin-left)
so your styles flip too.
Mixed-direction text
User-generated names can be in any direction. bdi isolates text whose
direction is unknown, so it doesn't scramble the punctuation around it:
<ul>
<li>User <bdi>إيان</bdi>: 3 posts</li>
<li>User <bdi>Maria</bdi>: 5 posts</li>
</ul>
<p dir="auto">Direction chosen from the first strong character.</p>
dir="auto" lets the browser decide from the content — useful on inputs
and text areas for user content. bdo dir="rtl" forces a direction
(rarely needed).
Ruby annotations
East Asian text sometimes shows pronunciation above characters:
<p lang="ja"><ruby>漢<rp>(</rp><rt>かん</rt><rp>)</rp>字<rp>(</rp><rt>じ</rt><rp>)</rp></ruby></p>
rt holds the annotation; rp holds fallback parentheses for browsers
without ruby support.
Alternate language versions
Tell search engines about translations of a page with hreflang:
<link rel="alternate" hreflang="en" href="https://cornerbakery.example/en/">
<link rel="alternate" hreflang="fr" href="https://cornerbakery.example/fr/">
<link rel="alternate" hreflang="x-default" href="https://cornerbakery.example/">
Every version must list all versions, including itself. Our Hreflang Checker verifies the set.
Other tips
- Use
time datetimefor dates, and let the server or JavaScript (Intl.DateTimeFormat) format them for each locale. - Leave room: German and Finnish text is often much longer than English.
- Don't put text in images — it can't be translated.
translate="no"protects brand names and code from machine translation.
What's next
Try the Intermediate Projects, then continue to Level 3 — Advanced: the HTML parser, web components, performance, security, and production-grade HTML.