Build a Manual with Hugo #5: Multilingual Content and Versioning
In #4 we put the docs on the internet. As users grow, two requests follow. One is wanting to read in another language; the other is keeping past docs around for people still on an older product version. This post covers both.
This series, Build a Manual with Hugo, runs in six parts.
- #1: From Install to Your First Doc
- #2: Sidebar and Search — Shaping the Information Architecture
- #3: Writing Content — Code Blocks, Mermaid, Callouts
- #4: Deploying to Cloudflare Pages and Connecting a Domain
- #5: Multilingual Content and Versioning ← this post
- #6: Maintenance — Search Index, Accessibility, Documentation Culture
This post covers adding a language, linking translation files, and maintaining per-version docs together.
Adding a Language #
Multilingual support is a core Hugo feature, so it works regardless of the theme. Declare the languages in hugo.yaml.
defaultContentLanguage: ko
defaultContentLanguageInSubdir: true
languages:
ko:
languageName: 한국어
weight: 1
en:
languageName: English
weight: 2Setting defaultContentLanguageInSubdir: true puts even the default language under /ko/, so every language is arranged by the same rule. Once there’s more than one language, Hextra automatically shows a language switcher at the top.
Placing Translation Files #
Per-language versions of the same doc are placed side by side, with the language code appended to the filename.
content/docs/
├─ getting-started.md # default language (Korean)
└─ getting-started.en.md # EnglishWhen the file name and location match, Hugo automatically recognizes the two as translations of the same post. If you need different slugs per language, group them with translationKey instead of the filename.
---
title: Getting Started
translationKey: getting-started
---Write the same translationKey in the English file too, and even with different names they’re linked as translations of the same post. UI strings like sidebar labels and buttons are filled in per language from the translation table in the i18n folder.
Versioning — There’s No Single Right Answer #
Here there’s one thing to be honest about. Hugo has no built-in doc versioning feature. This is a point where it differs from Docusaurus, which provides version snapshots and a version-selector dropdown out of the box. So in Hugo, you split versions into folders directly.
content/docs/
├─ v2/ # latest
│ ├─ _index.md
│ └─ getting-started.md
└─ v1/ # previous version
├─ _index.md
└─ getting-started.mdThen put links to each version in the top menu so readers choose the version themselves.
menu:
main:
- name: v2 (latest)
pageRef: /docs/v2
weight: 1
- name: v1
pageRef: /docs/v1
weight: 2With two or three versions, this approach is enough. That said, if you need per-version links like “other versions of this page,” or the number of versions keeps growing, Docusaurus — which has that feature built in — may be a better fit. Tool choice ultimately comes down to how strong such requirements are.
Wrapping Up #
In this post we added a language and linked translation files, and split versions into folders to maintain them together. Multilingual support is an area Hugo backs well, and versioning takes a bit of effort but is solved within reason by folder separation.
The next post is the last. We’ll close the series by laying out the operations perspective: the search index, accessibility, and the maintenance habits that keep docs alive for the long run.