# Right to left — an app that reads in Arabic with no change to the app

> A language written right to left (Arabic, Hebrew, Persian, Urdu) mirrors the whole page: every horizontal side a style prop names is a START or END side, a slide moves towards the end, an arrow points onwards, and data inside Arabic text keeps its own order. Nothing in the app is written for it. `FlowDirection.LeftToRight` keeps the geometry of the one element that must not mirror; `Mirror.InRightToLeft` turns a photograph composed for one side.

<!-- id: i18n-right-to-left · area: i18n · stability: preview · html: https://osysharp.com/reference/i18n/right-to-left/ -->

## Summary        {#summary}
When the reader's language is written right to left — an app that has `locales/ar.osy` and an Arabic reader — the page
is `<html dir="rtl">` and the whole layout mirrors: the navigation that starts the line at the left in English starts
it at the right, a drawer that slides in from its edge slides in from the other one, a "next" chevron points left. The
language's direction is the culture data's own fact, so `locales/he.osy` or `locales/fa.osy` works the same with
nothing added. An app does not change; it was already written in starts and ends.

## Signature      {#signature}
```osy syntax
Box(pl: 4, mr: 2, borderLW: 1, left: 0);           // START and END sides — the left and right of an English page
Text(price, textAlign: TextAlign.Right);              // the END of the line: the left of an Arabic one
Box(translateX: "-100%");                              // towards the start: mirrored in a right-to-left page
Box(flowDirection: FlowDirection.LeftToRight) { … }    // THE ESCAPE: this element keeps left-to-right geometry
Image(picture: Textures.Bottle, mirror: Mirror.InRightToLeft);   // a photograph composed for one side turns with the page
// icons/next.svg:  <svg data-mirror="rtl" viewBox="0 0 24 24">…</svg>   — an icon that points ONWARDS
```

## Description    {#description}
**Every horizontal side is a start or an end side.** `Pl`/`Ml`/`BorderLW`/`Left` are the side a line starts on and
`Pr`/`Mr`/`BorderRW`/`Right` the side it ends on — exactly as WPF's `Thickness.Left` is under `FlowDirection`. They
lower to CSS's logical properties (`padding-inline-start`, `margin-inline-end`, `border-inline-start-width`,
`inset-inline-start`), `Px`/`Mx`/`ScrollPaddingX` to the `-inline` pair, and `TextAlign.Left`/`Right` to `start`/`end`.
In an English page that is the left and right they always meant; in an Arabic one the layout mirrors. Rows and grids
already follow the direction, so a `Row` reads right to left by itself.

**A slide mirrors.** `TranslateX` is multiplied by the page's mirror factor, so a drawer that slides in from the start
edge, a line that leaves towards the end, an entrance that rises from the side all move the other way in Arabic — in an
`animation` as well as on an element. `TranslateY`, `Rotate` and `Scale` do not change.

**The one escape: `FlowDirection.LeftToRight`.** Some geometry must not mirror: a chart's plot drawn in left-to-right
coordinates, a timeline, a phone number, a code sample, a map. Give the element that holds it
`flowDirection: FlowDirection.LeftToRight` (WPF's `FlowDirection`, spelled the same) — inside it, start is the left
again, slides and directional icons un-mirror, and its text is isolated from the Arabic around it. The chart kit does
exactly this around its plot; its title and legend follow the page. `FlowDirection.RightToLeft` is the other way round,
for a right-to-left island in a left-to-right page.

**A photograph composed for one side.** A full-bleed photograph whose empty half carries the words set on it (a bottle
at the right, the list in the dark at its left) must turn when the words move to the other side, or in Arabic they land
on the bottle. `mirror: Mirror.InRightToLeft` draws it mirrored in a right-to-left page. A photograph with writing in it,
a face, a product or a logo stays as it is (`Mirror.Never`, the default).

**An icon that points somewhere.** An icon file whose root says `data-mirror="rtl"` is drawn mirrored wherever it is
used in a right-to-left page (and unmirrored inside a `FlowDirection.LeftToRight` element) — see [icons](https://osysharp.com/reference/ui/icons/). The
platform's arrows, chevrons, send, sign-in/sign-out, cart, external-link and message glyphs carry it; play, clock,
check and brand marks do not.

**Data keeps its own order.** Inside Arabic text a price, an order number, an email address or an English product name
must still read left to right — unprotected, "120,00 kr" reads "kr 120,00" and "#1042" reads "1042#". So in a
right-to-left page: every hole of a translated sentence is an isolate (U+2068 … U+2069, `<bdi>` as text), a symbol
written against a hole (`#{number}`) is inside it, a text that shows only data is isolated whole, and a numbered
reference inside Arabic text is one token. The app's own translated words are never wrapped. What a reader TYPES takes
its direction from what they type (an email field runs left to right). A test names text as the reader sees it — the
isolates are invisible to `Assert.Visible` and `Ui.Click`.

**Dates and money in Arabic.** An Arabic page formats its numbers, prices and dates in `ar-AE`, a culture of the
platform's default pack: Arabic month and day names, the Gregorian calendar, and Latin digits — `2 أكتوبر 2026`,
`9:12 ص`, `1,234.50`. The browser is handed the server's own plan for it rather than asking the browser's `Intl`, so a
date the server wrote (a mail, a server render) and one the browser wrote read alike, digit for digit. A price the app
writes with its own symbol ("560 kr") keeps that symbol; only the separators come from the culture.

**A heading face for Arabic.** A Latin display face rarely carries Arabic, and a heading in Arabic then falls back to
whatever the reader's system has — a different voice from the rest of the design. Name an Arabic face after the Latin
one in the theme's font token, ship both with `osy font add`, and each heading takes the face of its script, glyph by
glyph: `Display = "\"Newsreader\", \"Amiri\", ui-serif, serif";` keeps a Latin product name inside an Arabic heading
in Newsreader and the Arabic words in Amiri.

**A mail is mirrored too.** A mail written in Arabic ([Which language a reader gets — and switching it](https://osysharp.com/reference/i18n/language/) — its `language =>`) is a right-to-left
document: `dir="rtl"`, its start and end sides on the right and left, a receipt's line on the right and its amount on
the left, each line ordering its own data. Mail clients read physical sides far more reliably than logical CSS, so the
mail renderer writes them physically for the mail's language.

## Examples       {#examples}
```osy title="a receipt line written in starts and ends — it mirrors in Arabic by itself" test app=i18n-right-to-left
[Composable]
[AllowAnonymous]
component ReceiptLine(string item, string price) {
  render {
    Row(gap: 3, justify: Justify.Between, pl: 4, pr: 2, borderLW: 2, border: Colors.Border) {
      Text(item);
      Text(price, textAlign: TextAlign.Right, fontVariant: FontVariant.TabularNums);
    }
  }
}
```

```osy title="the escape: a plot drawn left to right on an Arabic page, its caption following the page" test app=i18n-right-to-left
[Composable]
[AllowAnonymous]
component Sparkline(double[] points, string caption) {
  render {
    Stack(gap: 2) {
      Text(caption);
      Box(flowDirection: FlowDirection.LeftToRight, h: 40, position: Position.Relative) {
        foreach (var i in Enumerable.Range(0, points.Length)) {
          Box(position: Position.Absolute, left: $"{i * 100 / points.Length}%", bottom: "0", w: 4, h: $"{points[i]}%",
              bg: Colors.Primary);
        }
      }
    }
  }
}
```

```osy title="a drawer that slides in from its own edge, and a photograph that turns with the page" test app=i18n-right-to-left
animation SlideIn { Duration = "240ms"; from { TranslateX = "-100%"; } to { TranslateX = "0"; } }

[Composable]
[AllowAnonymous]
component Panel(bool open) {
  render {
    if (open) {
      Stack(position: Position.Fixed, top: 0, bottom: 0, left: 0, w: "320px", bg: Colors.Surface, animation: SlideIn) {
        Box(h: "200px", bgImage: "linear-gradient(#222, #555)", mirror: Mirror.InRightToLeft);
        Text("Your bag");
      }
    }
  }
}
```

## See also       {#see-also}
- [Which language a reader gets — and switching it](https://osysharp.com/reference/i18n/language/) — which language a reader gets, and the `dir` that follows it
- [A language's words — locales/<language>.osy](https://osysharp.com/reference/i18n/translations/) — the locale files that make an app speak Arabic
- [style props](https://osysharp.com/reference/ui/styling/) — every style prop, with its start/end meaning
- [icons](https://osysharp.com/reference/ui/icons/) — marking an icon directional
- [[Email] — mail rendered from data](https://osysharp.com/reference/ui/email/) — a mail in its recipient's language
