Internationalization
Files: src/config/language.json, src/config/config.toml, src/i18n/, src/config/menu.*.json, src/content/**/<language>/ · Skill level: Beginner
Ecozen ships in English (the default, at /), French (at /fr/), and Arabic (at /ar/). Every page, menu, and label exists in every language. Arabic is right to left, and the whole layout mirrors: see RTL & Arabic. The Arabic text is a machine translation, so have a native speaker review it before you publish.
In the Tina edition, each language has its own folder or file under each entry at /admin/, including Menus and Interface labels. In the Sanity edition, each language is an entry under Content in the Studio, with its own Menus and Interface labels. language.json stays in the project in every edition.
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, form messages, footer, 404 page, labels) |
| Menus | src/config/menu.fr.json |
In src/config/language.json, each language has an entry like this:
{ "languageName": "Français", "languageCode": "fr", "contentDir": "french", "dir": "ltr", "ogLocale": "fr_FR", "dateLocale": "fr-FR", "weight": 2}languageName is the name in the language switch. languageCode is the URL prefix and the file suffix (fr.json, menu.fr.json), and contentDir is the folder name inside each content folder. dir is ltr or rtl. ogLocale is for social previews, dateLocale sets how dates and calculator numbers are written, and weight is the language’s place in the switch.
The language switch shows the current language’s name with a small icon, and opens a list of the others. It sits in the top bar of the classic header and the info row of the transparent one, and in the main bar of the others (see Header). On a blog category or tag page, it links to the other language’s blog page, because category and tag names differ between languages.
Language Settings
[settings.multilingual] enable = true defaultLanguage = "en" disableLanguages = [""] # for example ["fr"] showDefaultLangInUrl = false # true gives /en/pricing/ instead of /pricing/Restart npm run dev after you change these values, and after you add a language.
Remove A Language
- Turn one language off, keep its files. Add its code to
disableLanguages, for example["ar"]. It stops being built, and the language switch stays. This works the same in all three editions. - Turn every other language off, keep the files. Set
enable = false. Only the default language is built and the language switch disappears. You can turn them back on any time. - Keep only your default language, for good. Save a checkpoint first (a git commit or a copy of the folder). Then:
- Astro: set
enable = false, runnpm run devonce, then runnpm run remove-multilingual. - Tina: the same, then run
npm run tina:generate. - Sanity: run
npm run remove-multilingual. The other languages’ documents stay in your project unless you add-- --delete-online, which deletes them and can’t be undone.
- Astro: set
In the Astro and Tina editions, remove-multilingual deletes the content folders, src/i18n/ file, and src/config/menu.*.json file of every language except the default one, and removes them from language.json. This can’t be undone without your checkpoint. On Netlify, also delete their blocks in netlify.toml.
Add A Language
-
Run the language script. German is the example here. In the Astro and Tina editions:
Terminal window npm run generate-multilingual-content -- --lang de --name Deutsch --dir-name german --locale de-DE --og de_DEIn the Sanity edition, the last flag is
--og-locale:Terminal window npm run generate-multilingual-content -- --lang de --name Deutsch --dir-name german --locale de-DE --og-locale de_DEFor a right-to-left language, add
--dir rtl. See RTL & Arabic for what else it needs. -
In the Tina edition, run
npm run tina:generate, and later committina/tina-lock.json. -
Translate the copy. In the Astro and Tina editions, the script adds the language to
language.jsonand copies the default language’s content folders,src/i18n/en.json, andsrc/config/menu.en.json. It keeps files you already translated, unless you add--force. In the Sanity edition, it adds the language and creates a copy of every default-language document in your project to translate. Your other documents are not touched. -
On Netlify, add a
/de/*block tonetlify.toml, like the French one. -
Restart
npm run devand open/de/.
Directorysrc/content/
Directorysections/
Directoryenglish/
- …
Directoryfrench/
- …
Directoryarabic/
- …
Directorygerman/
- …
Directoryservices/
Directoryenglish/
- …
Directoryfrench/
- …
Directoryarabic/
- …
Directorygerman/
- …
Translating a whole site is a perfect job for an AI assistant: see the prompt at the end of this page.
Replace A Language
In the Astro and Tina editions, you can also turn the French copy into another language, instead of adding one:
-
In
language.json, change the French entry:"languageName": "Español","languageCode": "es","contentDir": "spanish","ogLocale": "es_ES","dateLocale": "es-ES". -
Rename every
src/content/**/french/folder tospanish/. -
Rename
src/i18n/fr.jsontoes.jsonandsrc/config/menu.fr.jsontomenu.es.json. -
Translate the text values in those files and folders. Keep every key as it is, and change internal links in Markdown text from
/fr/to/es/. -
In
netlify.toml, change the/fr/*redirect to/es/*and/es/404/. -
In the Tina edition, run
npm run tina:generate. -
Restart
npm run devand open/es/.
Links Between Pages
- In menus and in
urlfields of buttons in content files, write the English path (/pricing/). Ecozen adds the language prefix for you. - In Markdown text (the body of a post or page, or a Markdown link in a label), write the full path for that language yourself:
[voir les tarifs](/fr/pricing/)in a French file. - Give
customSlugthe same value in every language, so the language switch finds the matching page.
Text That Lives In config.toml
A few config.toml values are the same in every language: [settings.contactInfo] (use value in that language’s contact-section-two.md to translate the opening hours), the theme credit, and any label you fill in instead of leaving it empty, such as [settings.announcementBar] label. Leave those labels empty and use the i18n files for a site in several languages.
Translated 404 Pages
Each language has its own 404 page (/fr/404/, /ar/404/). On Netlify, the redirects in netlify.toml send a missing /fr/... or /ar/... address to it; add one block per extra language. Other hosts may show the default language’s 404 page unless you add a rule: see Deployment.
Do It With AI
Add [LANGUAGE] to the site. Run npm run generate-multilingual-content with --lang [xx], --name[NAME], --dir-name [folder], --locale [DATE LOCALE], and the Open Graph flag from this edition'sREADME, and add --dir rtl if it reads right to left. Then translate every text value in the newfolders, menu file, and i18n file from the English versions. Keep all keys, option values, iconnames, URLs, and customSlug values unchanged. In Markdown text, change internal links to /[xx]/.On Netlify, add a /[xx]/* block to netlify.toml. Work folder by folder and tell me when each is done.