# Internationalization (Languages)

## Internationalization

**Files:** `src/config/language.json`, `src/config/config.toml`, `src/i18n/`, `src/config/menu.<language>.json`, `src/content/**/<language>/` · **Skill level:** Beginner

Margo ships in **English** (the default, at `/`), **French** (at `/fr/`), and **Arabic** (at `/ar/`), with right-to-left support on Arabic pages. Every page, menu, and interface label exists in each language. You can keep all three, keep only your default language, or add another one. For how right-to-left works, see [RTL & Arabic](/margo/features/rtl-arabic/).

<Aside type="caution">
  The Arabic text is a machine translation. Have a native speaker review it
  before you publish it.
</Aside>

### What Makes Up A Language
| Part | Files |
| --- | --- |
| The language itself | an entry in `src/config/language.json` |
| Page and section text | a folder per language in every content folder, such as `src/content/sections/french/` and `src/content/projects/arabic/` |
| Interface text | `src/i18n/<language>.json`, such as `fr.json`: buttons, labels, form messages, search texts, the footer copyright line |
| Menus | `src/config/menu.<language>.json`, such as `menu.ar.json` |

This is `src/config/language.json` as it ships:

```json
[
  {
    "languageName": "En",
    "languageCode": "en",
    "contentDir": "english",
    "dir": "ltr",
    "ogLocale": "en_US",
    "dateLocale": "en-US",
    "weight": 1
  },
  {
    "languageName": "Fr",
    "languageCode": "fr",
    "contentDir": "french",
    "dir": "ltr",
    "ogLocale": "fr_FR",
    "dateLocale": "fr-FR",
    "weight": 2
  },
  {
    "languageName": "العربية",
    "languageCode": "ar",
    "contentDir": "arabic",
    "dir": "rtl",
    "ogLocale": "ar_SA",
    "dateLocale": "ar",
    "weight": 3
  }
]
```

| Key | What it does |
| --- | --- |
| `languageName` | The label in the header language switch |
| `languageCode` | The address prefix (`/fr/`) and the file suffix (`fr.json`, `menu.fr.json`) |
| `contentDir` | The folder name inside each content folder |
| `dir` | `ltr` or `rtl`. This one value sets the direction of the page |
| `ogLocale` | The language of social previews |
| `dateLocale` | The format of dates |
| `weight` | The order of the languages |

Visitors switch language with the language switch in the header and the language links in the footer. Each link goes to the same page in the other language.

### Language Settings
```toml
# src/config/config.toml
[settings.multilingual]
  enable               = true
  defaultLanguage      = "en"
  disableLanguages     = [""]   # e.g. ["fr"] to switch French off without deleting it
  showDefaultLangInUrl = false  # true: English at /en/ instead of /
```

Restart `npm run dev` after you change these values.

### Translate Or Edit Text
- **Page and section text:** edit the file with the **same name** in the language's folder, for example `src/content/sections/french/hero-section.md`. Keep the keys and structure the same as in English; translate the values only.
- **Interface text:** edit the same key in the language's file, for example `nav.letsTalk` ("Let's talk") in `src/i18n/fr.json`. Add a new key to every file in `src/i18n/`.
- **Menus:** each `src/config/menu.<language>.json` keeps the same items, in the same order, with the same `url` values as `menu.en.json`. Translate the names. See [Menus](/margo/customization/menus/).
- **Links inside text:** a Markdown link in a translated file carries its language prefix, such as `[politique de confidentialité](/fr/privacy-policy/)`. Menu and button URLs don't need it: the theme adds the prefix.
- **Prices and figures:** prices such as a service's `price.from` are written as text in each language file (`"€9,200"` in English, `"9 200 €"` in French). Change them in every language.

### Tagline And Description Per Language
The site title, tagline, and description are set once in `[site]` of `config.toml`. Each language file can replace the tagline and description with its own text, in the `site` block at the top of `src/i18n/<language>.json`:

```json
"site": {
  "tagline": "Thème portfolio créatif pour Astro et Tailwind CSS",
  "description": "Thème portfolio éditorial pour designers, studios et photographes, conçu avec Astro et Tailwind CSS."
}
```

An empty value uses `[site] tagline` or `[site] description` from `config.toml`. English ships with both empty, so it uses `config.toml`; French and Arabic ship with their own. Replace them when you write your own tagline. See [SEO & AI Visibility](/margo/customization/seo-ai-visibility/).

### Dates
Dates on journal posts follow `dateLocale` of the page language, with the Gregorian calendar and Western digits in every language, Arabic included.

### Remove A Language
**To turn one language off**, add its code to `disableLanguages` in `[settings.multilingual]`, for example `["fr"]`. Its files stay in the project, and you can turn it back on later. Restart `npm run dev`.

**To keep only your default language:**

<Steps>

1. Save a git commit or a copy of the folder, because the next steps delete files.
2. Set `enable = false` in `[settings.multilingual]` of `src/config/config.toml`.
3. Run `npm run dev` (or `npm run astro-check`) once. The script in the next step reads the settings file these commands write.
4. Run `npm run remove-multilingual`. It deletes the content folders, the menu file, and the `src/i18n/` file of every language except `defaultLanguage`, French and Arabic included, and rewrites `language.json` to list only the default language.

</Steps>

### Add A Language
Example: German, code `de`, folder `german`.

<Steps>

1. Run the language script:

   ```bash
   npm run generate-multilingual-content -- --lang de --name Deutsch --dir-name german --locale de-DE --og de_DE
   ```

   | Option | What it sets |
   | --- | --- |
   | `--lang` | The language code, required |
   | `--name` | `languageName` |
   | `--dir-name` | `contentDir`, the folder name |
   | `--locale` | `dateLocale` |
   | `--og` | `ogLocale` |
   | `--dir rtl` | A right-to-left language. Leave it out for left to right |
   | `--force` | Overwrite files that already exist. Leave it out to keep your translations |

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

2. Translate the copies. In the copied files, add the language to Markdown links, such as `[Datenschutz](/de/privacy-policy/)`.

3. On Netlify, add a `/de/*` block to `netlify.toml`, copied from the `/fr/*` block. The script doesn't write it.

4. If the language's alphabet needs its own font, add one to `src/config/fonts.json`, using the Arabic font as your model. See [RTL & Arabic](/margo/features/rtl-arabic/).

5. Restart the dev server, open `/de/`, and run `npm run astro-check`.

</Steps>

### Do It With AI
```text
Add [LANGUAGE] (code [CODE], folder [FOLDER]) to my Margo site. Run
npm run generate-multilingual-content -- --lang [CODE] --name [NAME] --dir-name [FOLDER] --locale [LOCALE] --og [OG_LOCALE],
then translate the new content folders, src/config/menu.[CODE].json, and src/i18n/[CODE].json.
Keep every key and frontmatter field. Add the language prefix to Markdown links in the new files.
Add a /[CODE]/* block to netlify.toml copied from the /fr/* block. Then run npm run astro-check.
```

```text
Translate my changes to every other language: for every file I changed in src/content/**/english/
today, update the file with the same name in each other language folder (same keys, translated
values), and add any new key from src/i18n/en.json to the other files in src/i18n/.
Then run npm run astro-check.
```