# RTL & Arabic

## RTL & Arabic

**Files:** `src/config/language.json`, `src/config/fonts.json`, `src/i18n/ar.json`, `src/config/menu.ar.json`, `src/content/**/arabic/`, `src/styles/rtl.css` · **Skill level:** Beginner

Margo supports right-to-left (RTL) languages, and ships with Arabic as a complete example at `/ar/`. Every page, menu, and label has an Arabic version. For how languages work in general, see [Internationalization](/margo/customization/internationalization/).

<Aside type="caution">
  The Arabic text is machine translated, in Modern Standard Arabic. Have a
  native speaker review it before you launch an Arabic site.
</Aside>

### What Changes In RTL
Direction comes from one setting, so there is nothing to switch on page by page. On a page in an RTL language:

- `<html>` gets the right `lang` and `dir="rtl"`, and the layout mirrors.
- The header menu mirrors: flyouts open towards the left (and flip when there is no room), the shared panel slides in the direction you move, and the `Left` and `Right` arrow keys follow the reading direction. The phone menu card and the folding header items mirror too.
- The menu names on Arabic pages come from `src/config/menu.ar.json`, which ships translated, with the same items and links as `menu.en.json`.
- The arrow keys of the lightbox, tabs, and code tabs follow the reading direction.
- Arrows and chevrons that point along the reading direction flip. The testimonial carousel's arrows step the other way.
- Code, email addresses, phone numbers, and the email, phone, and web address fields of forms stay left to right.
- Arabic text uses an Arabic font, IBM Plex Sans Arabic, which loads only on Arabic pages. Latin text stays in the theme's Latin fonts.
- Arabic text keeps normal letter spacing and no capital-letter styles, and headings get a little more line height. The serif accent word in headings is set in the Arabic font, because the serif font has no Arabic letters.
- Dates use the language's format, with Western digits.
- Arabic pages share the fallback social image, because the social card generator can't lay out Arabic text (see [SEO & AI Visibility](/margo/customization/seo-ai-visibility/)).
- The llms files and Markdown copies work at `/ar/llms.txt` and `/ar/llms-full.txt`.

### The Language Entry
This is the Arabic entry in `src/config/language.json`:

```json
{
  "languageName": "العربية",
  "languageCode": "ar",
  "contentDir": "arabic",
  "dir": "rtl",
  "ogLocale": "ar_SA",
  "dateLocale": "ar",
  "weight": 3
}
```

| Key            | What it does                                                                     |
| -------------- | -------------------------------------------------------------------------------- |
| `languageName` | The name shown in the language switch                                            |
| `languageCode` | The address prefix (`/ar/`) and the file suffix (`ar.json`, `menu.ar.json`)      |
| `contentDir`   | The folder name inside each content folder                                       |
| `dir`          | `rtl` or `ltr`. This one value sets the direction of the page                    |
| `ogLocale`     | The language code for social previews, such as `ar_SA` or `fr_FR`                |
| `dateLocale`   | The format for dates, such as `ar` or `fr-FR`                                    |
| `weight`       | The language's position in the language switch                                   |

Every language has these keys. The theme reads them from this file, so you never list languages anywhere else.

### The Arabic Font
The Arabic font is the third entry in `src/config/fonts.json`:

```json
{
  "name": "IBM Plex Sans Arabic",
  "variants": [
    { "style": "normal", "weight": "400" },
    { "style": "normal", "weight": "500" },
    { "style": "normal", "weight": "600" }
  ],
  "preload": false,
  "display": "swap",
  "cssVariable": "--font-arabic",
  "provider": "google",
  "subsets": ["arabic"],
  "fallback": false,
  "optimizedFallbacks": false,
  "languages": ["ar"]
}
```

`"languages": ["ar"]` loads it only on Arabic pages. The Arabic text rules are in `src/styles/rtl.css`.

### Add Another RTL Language
These steps add Hebrew. Any RTL language works the same way.

<Steps>

1. Run the language script with `--dir rtl`:

   ```bash
   npm run generate-multilingual-content -- --lang he --name עברית --dir-name hebrew --locale he-IL --og he_IL --dir rtl
   ```

   It adds the language to `language.json`, and copies your default language's content folders, menu file, and `src/i18n/` file for you to translate. Files that already exist are kept unless you add `--force`.

2. Translate the new content, menu, and interface labels. Add the language to Markdown links, such as `/he/privacy-policy/`.

3. If you host on Netlify, copy the `/ar/*` block in `netlify.toml` for `/he/*`. The script doesn't add it.

4. Add a font that covers the language to `src/config/fonts.json`, using the Arabic entry as your model, with `"languages": ["he"]`. The Arabic text rules in `src/styles/rtl.css` use `:lang(ar)`, so add the same rules for your language if it needs them.

5. Restart `npm run dev`, open `/he/`, and check the menu, a form, a project, and a journal post. Then run `npm run astro-check`.

</Steps>

### Remove Arabic
To turn Arabic off and keep the files, add it to `disableLanguages`:

```toml
# src/config/config.toml
[settings.multilingual]
  disableLanguages = ["ar"]
```

Restart `npm run dev`. To delete the files instead, `npm run remove-multilingual` removes **every language except your default one**, French included. Save a git commit or a copy of the folder first, and read [Internationalization](/margo/customization/internationalization/) before you run it.

### If You Add Your Own Code
Use logical CSS, which follows the direction of the page, instead of left and right:

| Instead of                 | Use                                     |
| -------------------------- | --------------------------------------- |
| `ml-*`, `mr-*`             | `ms-*`, `me-*`                          |
| `pl-*`, `pr-*`             | `ps-*`, `pe-*`                          |
| `left-*`, `right-*`        | `start-*`, `end-*`                      |
| `text-left`, `text-right`  | `text-start`, `text-end`                |
| `rounded-l-*`, `rounded-r-*` | `rounded-s-*`, `rounded-e-*`          |
| `border-l-*`, `border-r-*` | `border-s-*`, `border-e-*`              |
| `space-x-*`                | `gap-*`                                 |
| `margin-left` in CSS       | `margin-inline-start`                   |
| `padding-right` in CSS     | `padding-inline-end`                    |
| `left: 0` in CSS           | `inset-inline-start: 0`                 |
| `text-align: left` in CSS  | `text-align: start`                     |

`translate-x-*`, `transform-origin`, and gradient directions have no logical version, so handle them with the `rtl:` variant or `[dir="rtl"]`.

Other rules:

- Direction icons flip in one list, `rtlFlipIcons` in `src/layouts/helpers/Icons.astro`. Add new ones there, not where you use them, because icon names can come from content files.
- Wrap values that must stay left to right with `dir="ltr"` or `<bdi>`, such as a code sample.
- Under `:lang(ar)`, don't add `letter-spacing` or `text-transform`, because they break Arabic script.

### Do It With AI
```text
Add [LANGUAGE] as a right-to-left language to my Margo site. Run
npm run generate-multilingual-content -- --lang [CODE] --name [NAME] --dir-name [FOLDER] --locale [LOCALE] --og [OG_LOCALE] --dir rtl,
then translate the new content, menu, and interface label files. Keep every key and frontmatter
field. Add a font that covers the language to src/config/fonts.json with "languages": ["[CODE]"].
Add a /[CODE]/* block to netlify.toml. Use logical CSS only. Don't run remove-multilingual.
Then run npm run astro-check and list the pages I should check by eye.
```