Language switch

Lets the reader move between English and Japanese, and keeps its place on every page so the header never shifts.

Molecule · stable · v1.0.0 · owner: Site system lead · contract 19 of 20 points (open: figma)

Do and don't

Do: Both languages

Rendered by language-switch.ts

Open example: Language switch · Do: Both languages Use the full-page example to follow page links.

Each goes to the same page.

Do: English-only page

Rendered by language-switch.ts

Open example: Language switch · Do: English-only page Use the full-page example to follow page links.

The switch keeps its place and says where it goes.

Don't: Hidden on English-only pages

Rendered by language-switch.ts

Open example: Language switch · Don't: Hidden on English-only pages Use the full-page example to follow page links.

The header would shift and Japanese readers would lose the way back.

Don't: A flag

Rendered by language-switch.ts

Open example: Language switch · Don't: A flag Use the full-page example to follow page links.

Flags are countries, not languages.

Rules

RuleWhyCheck
The switch is on every page.A header that shifts between pages looks broken, and readers must always find their language.Automated: tests/site/pages.spec.ts (navigation test)

API

PropTypeRequiredDefaultWhat it does
langen | jaYesThe page's language (marked current).
enstringYesThe English page.
jastringYesThe Japanese page, or /ja/ when there is none.
jaMissingbooleanNofalseThe page has no Japanese version; the link says so.

Contract details

The full contract: identity, anatomy, variants, states, tokens, layout, motion, accessibility, content, tests

Identity

AspectValue
Idlanguage-switch
LayerMolecules
Categorynavigation
OwnerSite system lead
Statusstable
Version1.0.0
Sourceapps/showcase/site/system/molecules/language-switch.ts (private repository; the contract and the render function are this one module)
VersionDateChange
1.0.02026-10-26EN and 日本語 on every page; a page with no Japanese version links to the Japanese home and says so.

Use when

  • In every header. Why: Japanese prospects must always find their language in the same place.

Do not use when

  • Inside content. Why: Language is a site setting, not a content link.

Anatomy

PartWhat it is
rootdiv.lang-switch, role=group, labelled Language
ena, lang=en
jaa, lang=ja; titled when the page has no Japanese version

Made of: tokens:type, tokens:colour.

Used in: header.

Variants

VariantWhenWhy
pairThe page exists in both languages.Each link goes to the same page in the other language.
english onlyNo Japanese version yet.The link goes to the Japanese home and its title says why, so nobody lands on a missing page.

States

StateRendered or not applicable
defaultTwo outlined links
hoverBackground --surface-2.
focus-visibleThe --focus ring.
activeNot applicable: Navigation is instant.
disabledNot applicable: The Japanese link always goes somewhere (the Japanese home when the page has no version).
loadingNot applicable: Static.
emptyNot applicable: Always two languages.
errorNot applicable: Links are checked at build.
currentThe page's language: ink background, aria-current=true.
visitedNot applicable: Same colours.
expandedNot applicable: Not a menu.

Tokens

PartToken
root.border--rule-hair --ink
current.background--ink
current.color--cotton
link.font--type-label
link.min-height36 px
--language-switch-border-rule-hairvar(--rule-hair)
--language-switch-border-inkvar(--ink)
--language-switch-border-radius-radiusvar(--radius)
--language-switch-padding-space-4var(--space-4)
--language-switch-color-inkvar(--ink)
--language-switch-font-type-labelvar(--type-label)
--language-switch-background-inkvar(--ink)
--language-switch-color-cottonvar(--cotton)
--language-switch-padding-space-3var(--space-3)

Layout

AspectValue
breakpointsRequired review at 390, 768, 1024 and 1440 px; execution is not implied by this declaration; always visible, also on phones.
wrappingNever.
textExpansionFixed labels EN and 日本語.

Spacing and rhythm

AspectValue
internal0 --space-4 per link.
externalIn the header actions, gap --space-4.
rhythmHeader only.

Motion

AspectValue
NoneA language switch is a link.

Runtime and reuse

  1. Render-only element; mount any registered child enhancements separately. Preserve required Site CSS, fonts, responsive and locale rules from nativeElement.

Accessibility passport

AspectValue
rolegroup of links, labelled Language (言語)
nameEN / 日本語 with lang attributes
keyboardTab to each link.
focusBefore the header CTA.
screenReaderReads each language in its own voice (lang attributes); the current one is marked.
contrastInk on cotton 15.9:1, cotton on ink 15.9:1.
target44 by 36 px.

Content

SlotLengthVoice
language names (fixed renderer text, not editable props)EN and 日本語 exactlyName languages in their own scripts. Do not substitute national flags or invent another language option.
missing Japanese destination explanation (fixed title)The complete existing title: このページは英語のみです。日本語のトップページへ移動します。When jaMissing is true, explain that the link opens the Japanese home rather than a translation of the current page.

Good: “EN · 日本語” · “このページは英語のみです。日本語のトップページへ移動します。”

Bad: “Language ▾” · “Country flags used as language names”

Japanese: 日本語 is a fixed language label; the group name is 言語 on Japanese pages. The supplied en/ja URLs and jaMissing determine the destination and title, not translated content props. Fixed Japanese strings remain subject to the existing native-review boundary.

Icons and illustrations

None: this element uses no icon or illustration of its own.

Decisions and exceptions

Usage

75 uses across the built pages (measured by npm run site:system).

Tests

AspectValue
unittests/unit/site-system.test.ts: renders every do and don't example through the registry and checks the classes it owns
visualNot yet: there are no screenshot baselines; the Library page is checked for sideways scroll at 1440 px by tests/site/system.spec.ts
a11ytests/site/system.spec.ts: axe (0 serious or critical) on the element's Library page in light and dark
parityscripts/site/system/check.ts: Library examples are rendered by the same render function the site imports

Figma

not-yet: The Loom Site Figma library is the last stage of the plan; this element is not mapped yet.

Open in Storybook

Start with a conversation about your system.

We read your system, show you what we found, and agree with your team what to fix first.