Multilingual sites
moss supports English (en), Simplified Chinese (zh-hans / zh-cn), and Traditional Chinese (zh-hant / zh-tw). Any of these can be the site default; the rest appear behind an automatic language toggle in the header.
Folder-per-language (canonical)
Put each language in its own top-level folder, named by language code:
my-site/
├── index.md ← EN homepage (site default)
├── about.md
├── posts/
│ └── hello.md
├── zh-hans/
│ ├── index.md ← 中文简体 homepage
│ ├── about.md
│ └── posts/
│ └── hello.md
└── zh-hant/
├── index.md
└── about.md
Each language tree mirrors the site structure. URLs follow the same pattern: /, /about/, /posts/hello/ for the default language; /zh-hans/, /zh-hans/about/, etc. for others.
This is the recommended structure: clear, scalable, and maps 1:1 to the URL layout.
Sibling suffix (legacy)
moss also accepts per-file language suffixes .zh-hans.md, .zh-hant.md, .en.md:
my-site/
├── index.md
├── index.zh-hans.md ← Simplified Chinese homepage
└── about.md
└── about.zh-hans.md
This works for small sites. Mixing it with folder-per-language in the same folder is ambiguous — stick to one style per site.
Bare .zh is accepted as shorthand for .zh-hans: about.zh.md resolves exactly like about.zh-hans.md (URL /zh-hans/about/, lang="zh-hans"). Use whichever form you prefer; .zh-hant / .zh-tw remain distinct for Traditional Chinese.
Mixed-structure warning
If a single language uses both styles, say zh-hans/index.md (folder-per-language) and index.zh-hans.md (sibling suffix), moss emits a compile-time warning:
[warn] Mixed multilingual structure detected for language 'zh-hans'. Found
both sibling suffix file (index.zh-hans.md) and folder-based
translation (zh-hans/...). Prefer folder-per-language; see
https://docs.mosspub.com/multilingual for the canonical pattern.
Both styles still compile; the warning is a nudge. To silence it, pick one style per language and move the other files over. Folder-per-language is almost always the better choice: URLs mirror the folder tree, and adding pages doesn't stack .lang.md copies next to originals.
The warning fires only when the same language appears in both shapes. Different languages can use different styles without triggering it.
Frontmatter fields
| Field | Type | Purpose |
|---|---|---|
lang | string | Explicit language code ("en", "zh-hans", "zh-hant"). Overrides filename/content detection. |
translationKey | string | Links files as translations of each other when filenames differ. |
Use translationKey when translated versions have different filenames (e.g., posts/hello.md and posts/ni-hao.md):
# posts/hello.md
---
translationKey: post-hello
---
# zh-hans/posts/ni-hao.md
---
translationKey: post-hello
lang: zh-hans
---
Resolution chain
For each file, moss determines the language by checking (in order):
- The
langfrontmatter field - The filename suffix (
.zh-hans.md) - Content auto-detection (script and character analysis)
- The site default language
The first step that yields a recognized language wins.
Setting the site default
By default, moss treats the root-level (en) tree as the site default. To publish another language at /, set lang in the root index.md.
---
title: 我的网站
lang: zh-hans
---
Then the Simplified Chinese tree serves at / and English at /en/.
Automatic language toggle
When two or more language versions of a page are linked (via matching paths in folder-per-language, matching filenames in sibling-suffix, or matching translationKey), moss emits a language toggle in the site header. The toggle shows the current language and links to each available translation. It appears automatically as soon as a second language file exists.
Shared partials across languages
You can extract shared markdown (like a footer) into a file and transclude it into pages across languages:
# zh-hans/about.md
Some about copy.
![[footer]]
moss resolves <!-- moss-embed:footer.md --> by looking in the current page's language tree first (so zh-hans/footer.md wins from inside zh-hans/), then falling back to the root. Each language can keep its own partial where needed, falling back to a shared one.
See Links & Embeds for the full transclusion syntax.
Related pages
- frontmatter:
lang,translationKey, and the full field reference - Links & Embeds: transclusion and cross-page linking
- structure: how folders become URLs