Languages
OINK uses Hugo’s multilingual page model directly and introduces no
site-specific domain convention or template assumption. This site treats English
as the primary language and Simplified Chinese (zh) as the second.
Configure languages
-
label,string, required The name shown in the language selector, written in that language —
简体中文, notChinese.-
locale,string The standard language tag used for
<html lang>,hreflangalternates, and Open Graph metadata.-
weight,integer Sets both the language order and the selector’s cycle order; lower comes first.
-
title,string The site title in that language.
-
params.*,map Language-level parameters override the global value of the same name; anything undefined is inherited. Date formats usually need a per-language value.
When menu labels differ by language, define menus under each language.
Organize translations
A translation sits beside its source in the same directory, distinguished by a filename suffix:
-
content/docs
- install.md
- install.zh.md
The shared base filename is what makes Hugo treat them as one page in two languages.
Keep identical: dates, weights, aliases, page resources, and every piece of metadata that affects routing.
Translate: front matter title and description, summaries, menu labels,
tags, image alt text, callouts, and visible shortcode parameters.
Do not translate: commands, identifiers, configuration keys, filenames, URLs, and product names.
per-language contentDir model. Do not mix the two layouts — pick one,
write it into your conventions, and verify that Hugo links the translations.
Stable heading anchors
This is where multilingual documentation most often breaks. Hugo derives heading
IDs from heading text, so a Chinese heading produces a Chinese ID and
/docs/page/#install and /zh/docs/page/#安装 become two unrelated anchors.
Write the source ID explicitly in the translation:
When translating an existing page, take the ID from the rendered English HTML. Do not guess from the heading text — headings containing shortcodes or inline code often generate something other than what you expect.
This site enforces identical heading count, order, and IDs with a script:
Language selector behavior
The selector reads each page’s .Translations:
- the target language has a translation → it links straight to that page;
- the target language has none → it falls back to that language’s home page.
The fallback is deliberate, not a defect. Sending a reader to a URL that does not exist would be worse.
Search and languages
With offlineSearch: true, each language gets its own index:
A reader searching from a Chinese page matches only Chinese content.
Chinese queries use the theme’s CJK substring fallback: Lunr cannot tokenize Chinese reliably, so the Command Palette switches to substring matching when it detects CJK characters. Both paths apply the same ranking boost.
Right-to-left languages
Declare the writing direction on the language:
OINK loads Bootstrap’s RTL stylesheet, and the theme’s own CSS uses logical
properties (margin-inline-start rather than margin-left), so mirroring is
automatic.
Site-authored CSS should use logical properties too, or it will break under RTL.
UI translations
The theme ships interface strings for 32 locales. English, Simplified Chinese
(zh-cn and generic zh), and Traditional Chinese (zh-tw) are fully
reviewed; the rest keep their inherited Docsy translations, and OINK-only labels
currently fall back to English.
To override one string, create a file of the same name under the site’s i18n/:
Translation checklist
- every
page.mdhas a matchingpage.zh.md - Chinese headings carry explicit IDs matching the rendered English IDs
- routing-affecting front matter is consistent
- commands, configuration keys, and URLs are untranslated
- the language selector is verified on pages with and without translations
- search returns results in both languages
Next steps
- Versions: combining languages with versions
- Navigation: per-language menus