# Internationalization (Languages)

## Internationalization

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

Homio ships in **English** (the default, at `/`) and **French** (at `/fr/`). Every page, menu, label, price, and date exists in both. You can keep both, keep English only, or add another language.

### 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: `src/content/sections/french/`, `src/content/services/french/`, … |
| Interface text | `src/i18n/fr.json`: buttons, labels, form messages, units, the booking steps, the 404 link labels |
| Menus | `src/config/menu.fr.json` |

```json
[
  {
    "languageName": "En",
    "languageCode": "en",
    "contentDir": "english",
    "weight": 1,
    "ogLocale": "en_US"
  },
  {
    "languageName": "Fr",
    "languageCode": "fr",
    "contentDir": "french",
    "weight": 2,
    "ogLocale": "fr_FR"
  }
]
```

`languageCode` is the URL prefix and the file suffix (`fr.json`, `menu.fr.json`), `contentDir` the folder name inside each content folder, `languageName` the label on the language links, `weight` their order, and `ogLocale` the language of social previews.

Visitors switch language with the **EN | FR** links in the footer and at the bottom of the phone menu. A link goes to the same page in the other language.

Your business details stay in one place for every language: `[business]` in `config.toml` (name, phone, address, hours). Don't type them into translations.

### 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 `french/` 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 `src/i18n/fr.json`, for example `navigation.buttonLabel` ("Get a price").
- **Menus:** `src/config/menu.fr.json` must keep the same structure as `menu.en.json`: the same items, in the same order, with the same `url` and `source`. Translate the labels.
- **Prices:** keep every number in `src/content/pricing/french/-index.md` identical to the English file. `npm run build` prints a `[pricing]` warning listing any key that differs.

### Check Your Translations
```bash
npm run check-i18n
```

It also runs as part of `npm run astro-check`, and fails when:

- a key in `src/i18n/en.json` is missing from another language file, or the reverse,
- a key in `en.json` is no longer read by any code,
- a menu file differs from `menu.en.json` in structure (item count, `url`, `source`),
- a content file in an `english/` folder has no copy in another language folder, or the reverse.

It warns about empty strings and strings still equal to the English ones. Words that are the same in every language on purpose are listed in `scripts/check-i18n.mjs`.

### Numbers, Prices, And Dates
Homio formats every price, number, date, and opening time for the page language with the browser's `Intl` tools: `$1,240` in English becomes `1 240 $US` in French. You never write a formatted price in content: prices come from the numbers in the pricing file.

```toml
[settings.estimator]
  currency        = "USD"     # ISO 4217 code, one currency for every language
  currencyDisplay = "symbol"  # symbol ($ / $US) | narrowSymbol ($ in every language) | code (USD)
```

Set `currency` to your own (`"EUR"`, `"GBP"`, `"CAD"`), and use `narrowSymbol` to show `$` in French too. Opening hours and booking dates use `timezone` in `[business]`.

### Keep English Only
<Steps>

1. Set `enable = false` in `[settings.multilingual]` of `src/config/config.toml`.
2. Run `npm run dev` (or `npm run astro-check`) once.
3. Run `npm run remove-multilingual`. It deletes every `french/` folder, `menu.fr.json`, and `fr.json`, and rewrites `language.json`.

</Steps>

The script always keeps the English menu and interface strings. To keep only French or another language, remove the other files by hand instead.

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

<Steps>

1. Copy every `english/` folder under `src/content/` (each collection has one) to a `german/` folder next to it.

2. Add the language to `src/config/language.json`:

   ```json
   {
     "languageName": "De",
     "languageCode": "de",
     "contentDir": "german",
     "weight": 3,
     "ogLocale": "de_DE"
   }
   ```

3. Copy `src/config/menu.en.json` to `src/config/menu.de.json`, and `src/i18n/en.json` to `src/i18n/de.json`.

4. Translate the copied content, menu, and interface strings.

5. Run `npm run check-i18n` and fix what it lists.

6. On Netlify, add a `/de/*` 404 block to `netlify.toml`, copied from the French one. Restart the dev server.

</Steps>

<Aside type="caution" title="Don't use generate-multilingual-content to add a language">
  `npm run generate-multilingual-content` only creates French (`fr`, `french/`),
  and it copies the English files **over** the existing `french/` folders,
  `menu.fr.json`, and `src/i18n/fr.json`. Running it replaces Homio's French
  translations with English text. Follow the steps above instead.
</Aside>

Right-to-left languages such as Arabic or Hebrew are not part of the theme.

### Do It With AI
```text
Add [LANGUAGE] (code [CODE], folder [FOLDER]) to my Homio site. Follow "Add or remove a language"
in SKILLS.md: copy every english/ content folder, add the entry to src/config/language.json, copy
menu.en.json and src/i18n/en.json, and translate them. Don't run generate-multilingual-content.
Keep every number in the pricing file identical. Then run npm run check-i18n and fix what it lists.
```

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