Skip to content
AgileLogics
6 min read

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 datetime for 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.

Related developer tools