Notes on Adding I18n to a Hexo Blog

Design notes on Hexo i18n — filename conventions for language detection, a permalink filter for path-prefix routing, per-language generators, hreflang, and a language switcher.

Since this blog went live, the archive page has shown Chinese and English posts jumbled together. Adding i18n to Hexo isn’t easy, so the plan kept getting pushed back indefinitely.

I finally put together a first cut, prompted most directly by AnyRouter’s Opus model being usable again.

But the deeper reason is interest. Lately I was supposed to focus on writing my graduation thesis, yet I kept getting pulled back into tinkering with the blog. Even at bedtime my mind was still on it, and I enjoyed every minute. The polished UI/UX gives me real satisfaction.

There’s also the goal of practicing expression. Looking back at older posts, the same problems keep showing up:

  • Foreign words scattered through Chinese prose (for example, the title of this post originally used “i18n” before I switched to “多语言” — internationalization).
  • Visible traces of “Europeanized Chinese”[1].

I’ve consumed a lot of English content over the years, and as a result I instinctively imitate English patterns when writing Chinese. Stiff phrasing hurts comprehension in obvious ways. Supporting multiple languages on the blog is, in a sense, a way to force myself past that laziness.

There’s also a more practical motivation: multilingual support widens the audience. Posting on forums for exposure would be more direct, but I prefer the quieter conversations a blog allows.

Source layout and routing

File organization: filename convention

Hexo officially recommends the “directory convention”, but I ended up keeping every .md flat under _posts/ and using a __<lang> suffix to mark language. This keeps the original and its translation next to each other, which makes them easier to find and edit. Combined with VS Code’s File Nesting, you can fold foo__en.md under foo.md for an even cleaner tree.

Add the following to settings.json:

"explorer.fileNesting.patterns": {  "*.md": "$(capture)__en.md"}

Routing: path prefix

I went with the /en/foo/ path-prefix scheme, which is friendlier to SEO and caching. The mapping:

RoleInput filenameOutput URL
Default-language postfoo.md/foo/
Translated postfoo__en.md/en/foo/
Default-language pageabout.md/about/
Translated pageabout__en.md/en/about/

For Posts, I use the permalink: :i18n_path:name template and register a low-priority post_permalink filter that injects i18n_path (empty string for the default language, "en/" for English — both derivable from the filename) and rewrites the slug (stripping the __en suffix from the filename).

Pages are few, so I just declare permalink directly in front-matter — for example, permalink: /en/links/.

  • Tag / Archive: Run the generator once per language, feeding it only that language’s posts, to produce two fully independent sets of tag and archive pages.
  • Search: At build time, emit /content.json and /en/content.json separately. Each language’s pages load their own index, so results never cross languages.

sitemap.xml, atom.xml, and similar resources are not split by language.

SEO

To help search engines correctly identify the relationship between an original and its translation, I declare an i18n mapping in front-matter, like this:

langya_terrace.md
---title: 琅邪台游记date: 2026-03-13excerpt: 孤立特显,出于众山上,下周二十余里,傍滨巨海tags:  - Essay  - 青岛i18n:  en: /en/langya_terraceupdated: 2026-05-23 00:30:39---Original content...
langya_terrace__en.md
---title: Langya Terrace Travel Notesdate: 2026-03-13excerpt: Standing alone and prominent above all other hills, with a circumference of over twenty li at its base, overlooking the great seatags:  - Essay  - 青岛lang: eni18n:  cn: /langya_terrace  translation: 2updated: 2026-05-23 00:30:59---Translated content...

Based on the i18n field, the theme automatically generates <link rel="alternate" hreflang> tags pointing to the equivalent URL in each language:

<link rel="canonical" href="https://vluv.space/langya_terrace/" /><link  rel="alternate"  hreflang="zh-CN"  href="https://vluv.space/langya_terrace/"/><link  rel="alternate"  hreflang="en"  href="https://vluv.space/en/langya_terrace/"/><link  rel="alternate"  hreflang="x-default"  href="https://vluv.space/langya_terrace/"/>

<html lang> and og:locale also switch automatically with the page’s language.

Interaction design

  • Language switch in the nav bar: Pages like Archive/Tag/Links/About jump directly. Posts work the same way, but since not every post has a translation, switching language on a post may need to fall back to a toast notification.
  • Translation provenance marker: Post detail pages display a translation status based on i18n.translation: default is original, 1 means LLM-translated and reviewed, 2 means LLM-translated and unreviewed — useful for readers to gauge the text.

Interaction design
Interaction design

  1. Europeanized Chinese is a grammatical phenomenon that appeared in modern Chinese under the influence of Indo-European languages (especially English). It mainly shows up as sentence structures that drift away from traditional Chinese expression: overly complex sentences, overuse of the passive voice, excessive use of structural particles like 的 and 地, abuse of prepositions like 通过 and 作为, and the habit of decomposing simple verbs into “weak verb + abstract noun” compounds (e.g. “作出贡献” replacing “贡献很大”). It is most often seen in literal translations and formal written language.

    The phenomenon traces back to the New Culture Movement, when writers like Lu Xun and Qian Xuantong argued for reshaping Chinese thought by directly importing European grammar. Lu Xun explicitly advocated “literal translation of European syntax” as a way to renew the language. The translator Si Guo, in Translation Studies, criticized such writing as “barely intelligible, but certainly not Chinese”, arguing that Europeanized Chinese violates the essence of the language.

    In the 1980s, Yu Guangzhong’s essay “How to Improve English-Style Chinese?” went further, dissecting the tendency toward “verbose and stiff” Chinese expression. He criticized redundant prepositions (e.g. 由于, 关于), inappropriate conjunctions (e.g. 及), and the overreliance on 的 with adjectives — all Western-influenced traits — and insisted on preserving the natural rhythms of Chinese. ↩︎

CompactRelaxed
Normal1.70