i18n — RTL & bidi
The contract for right-to-left + bidirectional text: authors write LOGICAL (start/end) layout — never physical left/right — so a surface mirrors under `dir="rtl"` with no per-component RTL code; directional icons mirror while neutral ones don't; mixed-direction text is isolated per the Unicode bidi algorithm. gov.br has no RTL runtime — KDS surpasses it by making RTL a property of the layout system, not a per-locale rewrite. ar/he are the validation locales.
When this pattern applies
Primary triggers
- Support RTL / bidirectional text in a Koder surface
All triggers
- Build a layout that must work in Arabic/Hebrew (RTL)
- Use left/right in CSS or a mirrorable directional icon
- Handle mixed LTR/RTL text (a URL or number inside Arabic prose)
Specification body
i18n — RTL & bidi
R1 — Logical layout, never physical
Layout is authored in logical (writing-relative) properties — inline-start /
inline-end, margin-inline, padding-inline, inset-inline, border-inline,
text-align: start/end, and flex/grid start/end — never left/right,
margin-left, text-align: right, etc. A surface built this way mirrors
automatically under RTL with zero per-component code. Physical left/right is
reserved only for things that are genuinely physical and direction-independent (a
drop-shadow offset, a fixed hardware affordance) — never for reading-order layout.
R2 — Activating RTL
Direction is set on the document/root (<html dir="rtl">) or a subtree container,
driven by the active locale (i18n/contract.kmd). Every component reads its direction
from the cascade — it does not detect or hard-code a direction. A surface MUST render
correctly at dir="ltr" and dir="rtl" from the same source.
R3 — Directional icons mirror; neutral icons don't
An icon that encodes reading direction — back/forward, next/prev chevrons, indent,
list-nesting, a right-pointing "proceed" arrow — mirrors under RTL. An icon whose
meaning is direction-independent — search, settings, a checkmark, a logo, a clock,
media play (play always points to the timeline's forward, which is culturally LTR) —
does not mirror. Icons carry a mirrorable flag; the renderer flips only those
under dir="rtl". Guessing per icon at call sites is forbidden — the flag is the SSOT.
R4 — Bidirectional text (the Unicode bidi algorithm)
Mixed-direction runs (an English brand name, a URL, a phone number, or code inside Arabic prose) follow the Unicode Bidirectional Algorithm:
- User-supplied / unknown-direction text is rendered with
dir="auto"(or a first-strong isolate) so its base direction follows its content, not the container. - Embedded opposite-direction runs are isolated (
unicode-bidi: isolate, or the isolate control chars) so a trailing punctuation/number does not visually jump to the wrong edge. - Never concatenate a bidi-sensitive value into a translated string without isolation
(a classic "the
)landed on the wrong side" bug).
R5 — Start/end tokens & utilities
The spacing/grid tokens are direction-neutral scalars (spacing-scale.kmd,
column-grid.kmd); RTL support is applying them through logical properties, not new
values. The logical-property utility classes (.ms-*/.me-* = margin-inline
start/end, .text-start, .float-start, …) are the authoring shorthand — they live in
the vendored SoT koder_web_kit.css (drift-gated), NOT invented in a design-gen copy
(same rule as column-grid.kmd's utility class). Kroma surfaces express the same
start/end intent through the widget layout API.
R6 — Component contract
Every component in the corpus:
- uses only logical properties for reading-order layout (R1) — a physical
left/rightin layout is a defect; - flags its directional icons
mirrorable(R3); - isolates any bidi-sensitive interpolated value (R4).
New/changed components are checked against this at review; a component that bakes in LTR is not RTL-ready and is not conformant.
R7 — Validation
RTL/bidi is validated with ar (Arabic) and he (Hebrew) as the target locales,
via k-test-gen-i18n + i18n/test-template.kmd: render each surface at dir="rtl" and
assert (a) no physical-left/right layout leaked, (b) directional icons mirrored and
neutral ones did not, (c) a mixed-direction fixture string renders with correct isolation.
Não-escopo / follow-up
- Adoption: migrating the existing components/landings off physical left/right onto
logical properties, adding the
.ms-*/.me-*utility classes tokoder_web_kit.css, tagging iconsmirrorable, and thek-test-gen-i18nRTL suite — an incremental sweep (stack#450, opened). - Translation / string extraction —
i18n/contract.kmd; leak detection —i18n/leak-detection.kmd. This spec is layout+bidi, not the message catalogue.
References
meta/docs/stack/specs/i18n/contract.kmdmeta/docs/stack/specs/app-layout/column-grid.kmdmeta/docs/stack/specs/themes/spacing-scale.kmdmeta/docs/stack/specs/i18n/test-template.kmdtools/design-gen/docs/govbr-ds-gap-analysis.md