Internationalization
How Vanilla Breeze handles script-specific typography, ruby visibility, locale-aware quotes, translate conventions, and locale resolution.
Philosophy
Internationalization is not a feature you add — it is a constraint you respect from the start. VB treats i18n the same way it treats semantic HTML: build it in, don't bolt it on.
The web platform already has most of what you need: the lang attribute, CSS :lang(), logical properties, the Intl API, the translate attribute, and ruby HTML elements. VB uses them correctly and consistently.
Script-Specific Typography
Set lang on any element and VB automatically applies the right font family, line height, letter spacing, and word-breaking rules. This works via CSS :lang() which inherits through the subtree.
<html lang="ja"> <!-- CJK font, line-height: 1.8, word-break: break-all --></html> <section lang="ar" dir="rtl"> <!-- Arabic font, line-height: 1.9, RTL layout --></section>
Supported Scripts
| Script | Languages | Token | Line Height |
|---|---|---|---|
| CJK | zh, ja, ko | --font-cjk | 1.8 |
| Arabic | ar, fa, ur, ps | --font-arabic | 1.9 |
| Hebrew | he, yi | --font-hebrew | 1.75 |
| Thai | th | --font-thai | 2.0 |
| Devanagari | hi, mr, sa, ne | --font-devanagari | 1.75 |
Font Token Slots
VB provides custom properties for each script family. Override them to load your preferred fonts:
:root { --font-cjk: "Noto Sans CJK SC", "PingFang SC", system-ui, sans-serif; --font-arabic: "Noto Sans Arabic", "Segoe UI", system-ui, sans-serif; --font-hebrew: "Noto Sans Hebrew", "Segoe UI", system-ui, sans-serif; --font-thai: "Noto Sans Thai", "Leelawadee UI", system-ui, sans-serif; --font-devanagari: "Noto Sans Devanagari", system-ui, sans-serif;}
Ruby Visibility
Control ruby annotation display with data-ruby on <html>:
| Value | Behavior |
|---|---|
show | Always visible |
hide | Visually hidden, kept in DOM for accessibility |
auto | Visible for CJK languages, hidden otherwise |
| (absent) | Browser default |
<html lang="ja" data-ruby="auto"><body> <!-- Ruby visible because lang="ja" --> <ruby>漢<rt>かん</rt></ruby><ruby>字<rt>じ</rt></ruby> <!-- English section: ruby hidden in auto mode --> <section lang="en"> <ruby>ruby<rt>annotation</rt></ruby> </section></body></html>
Locale-Aware Quotes
The <q> element renders locale-appropriate quotation marks via CSS quotes:
| Language | Outer | Inner |
|---|---|---|
| English (US) | “...” | ‘...’ |
| English (GB, AU, NZ) | ‘...’ | “...” |
| German | „...“ | ‚...‘ |
| French | « ... » | ‹ ... › |
| Italian / Spanish / Portuguese | «...» | “...” |
| Polish | «...» | „...“ |
| Japanese / Chinese | 「...」 | 『...』 |
| Korean | “...” | ‘...’ |
| Russian | «...» | „...“ |
| Arabic | «...» | ‘...’ |
<p lang="de">Sie sagte <q>hallo</q>.</p><p lang="fr">Elle a dit <q>bonjour</q>.</p><p lang="ja">彼女は<q>こんにちは</q>と言いました。</p>
Translate Conventions
VB automatically sets translate: no on elements that should never be machine-translated: <code>, <kbd>, <samp>, <pre>, and <var>.
For your own content, use the HTML translate attribute on brand names, identifiers, and technical terms:
<p>Install <span translate="no">Vanilla Breeze</span> via npm.</p><p>Your username is <span translate="no">tpowell42</span>.</p>
Locale Resolution (JS)
VB provides a centralized getLocale() function that all format utilities share. The priority chain:
<html lang>attributenavigator.language'en'fallback
Individual elements can override via data-locale:
<html lang="de"> <!-- All format utilities use German locale by default --> <data value="1234.56" data-format-number>1.234,56</data> <!-- Override for this specific element --> <data value="1234.56" data-format-number data-locale="en-US">1,234.56</data></html>
JS Utilities
Import locale utilities for custom components:
import { getLocale, isRTL, usesRuby, primarySubtag } from './lib/i18n.js'; getLocale(); // 'en-US' (from html[lang] or navigator)isRTL('ar'); // trueusesRuby('ja'); // trueprimarySubtag('zh-TW'); // 'zh'/code-block <h2>VbI18n String Swap</h2><p>For application-level translation, VB exports a <code>VbI18n</code> class. It is <strong>not</strong> auto-initialized — you instantiate and configure it with your own message maps.</p> <code-block language="js" label="VbI18n setup" data-escape>import { VbI18n } from './lib/i18n.js'; const i18n = new VbI18n({ locale: 'fr', messages: { en: { 'nav.home': 'Home', 'actions.close': 'Close' }, fr: { 'nav.home': 'Accueil', 'actions.close': 'Fermer' }, }}); // Swap all [data-i18n] elementsi18n.apply(); // Listen for locale changesi18n.watch();
<nav> <a href="/" data-i18n="nav.home">Home</a></nav><button data-i18n="actions.close">Close</button> <!-- Attribute targeting --><input data-i18n="form.search" data-i18n-attr="placeholder" placeholder="Search..."> <!-- Variable interpolation --><p data-i18n="welcome" data-i18n-vars='{"name":"World"}'>Hello, World!</p>
Logical Properties
VB uses CSS logical properties throughout (465+ instances). RTL layout works automatically when you set dir="rtl" on <html>. No additional CSS is needed.
/* VB never writes this: */.card { padding-left: 1rem; margin-right: auto; } /* VB always writes this: */.card { padding-inline-start: 1rem; margin-inline-end: auto; }
Demo
i18n Typography Demo — live examples of all features on this page.
Related
Ruby Annotations
<ruby>— Container for ruby annotations (furigana, pinyin)<rt>— Ruby text (the annotation content)<rp>— Fallback parentheses for non-supporting browsers
Bidirectional Text
<bdi>— Bidirectional isolate (safe for user-generated content with unknown direction)<bdo>— Bidirectional override (force a specific text direction)