Multilingual Mediumish with Liquid and Data
Why Build a Multilingual Blog
If your audience spans multiple language groups, offering content in more than one language can dramatically increase your reach and engagement. Jekyll doesn’t support multilingual sites out of the box, but using Liquid and YAML, we can implement a scalable multilingual architecture — even on GitHub Pages.
Key Features We’ll Build
- Language switcher on all pages
- Translated versions of posts and pages
- Localized UI elements (menu, footer, headings)
- Clean URLs per language (e.g.,
/en/,/id/)
Step 1: Set Language Structure in Folders
Organize your content into language folders under the root directory:
/_posts
/en/_posts
/id/_posts
/en/about.md
/id/about.md
This allows Jekyll to compile language-specific routes using default routing rules, while maintaining isolation between versions.
Step 2: Use a Global Language Context
Define supported languages in _config.yml:
languages: ["en", "id"]
default_lang: "en"
You can pass this configuration to your layouts via site.languages and site.default_lang.
Step 3: Localize Interface Text via Data Files
Create a _data/translations directory and add YAML files per language:
// _data/translations/en.yml
menu:
home: "Home"
about: "About"
blog: "Blog"
contact: "Contact"
footer:
copyright: "All rights reserved."
// _data/translations/id.yml
menu:
home: "Beranda"
about: "Tentang"
blog: "Blog"
contact: "Kontak"
footer:
copyright: "Hak cipta dilindungi."
You can then access localized content dynamically:
{% raw %}
{% assign t = site.data.translations[page.lang] %}
<nav>
<a href="/">{{ t.menu.home }}</a>
<a href="/{{ page.lang }}/about/">{{ t.menu.about }}</a>
</nav>
{% endraw %}
Step 4: Add Language Front Matter to Pages
Each page/post should declare its language explicitly:
---
layout: post
title: "How to Use Liquid in Jekyll"
lang: en
author: admin
categories: [jekyll,liquid]
---
This lang field will control localized strings and routing logic.
Step 5: Build a Language Switcher
In your main layout, add a dynamic switcher like this:
{% raw %}
<div class="lang-switcher">
{% for code in site.languages %}
{% if code != page.lang %}
<a href="{{ '/' | append: code | append: page.url | remove_first: '/' }}">{{ code | upcase }}</a>
{% endif %}
{% endfor %}
</div>
{% endraw %}
This ensures that readers can easily jump to a post's equivalent in their language — assuming it exists.
Step 6: Link Between Translations of a Post
Use a shared ID in post front matter to connect versions of the same post:
---
layout: post
title: "Menggunakan Liquid di Jekyll"
lang: id
translation_key: liquid-guide
---
{% raw %}
{% assign translations = site.posts | where: "translation_key", page.translation_key %}
{% for t in translations %}
{% if t.lang != page.lang %}
<a href="{{ t.url }}">Read in {{ t.lang | upcase }}</a>
{% endif %}
{% endfor %}
{% endraw %}
This helps link localized content semantically while keeping separate URLs.
Optional: Filter Posts by Language
To only show posts of a particular language on language-specific blog indexes, use a filter in your list templates:
{% raw %}
{% assign lang_posts = site.posts | where: "lang", page.lang %}
{% for post in lang_posts %}
<a href="{{ post.url }}">{{ post.title }}</a>
{% endfor %}
{% endraw %}
This ensures your homepage or blog page only shows relevant translations.
Optional: Auto-Redirect to Default Language
In your root index.html, you can redirect users to /en/ using a meta refresh:
<meta http-equiv="refresh" content="0; url=/en/" />
Or with JavaScript geolocation/language detection (optional if you prefer full-static).
Real-World Case Study
A startup blog used this approach to maintain content in English and Indonesian. They stored all UI strings in YAML and translated their top 20 posts using translation_key. Their bounce rate dropped significantly on Indonesian visits once localized pages were deployed — proving value in targeting readers in their native language.
Benefits of This Approach
- Plugin-free: Fully compatible with GitHub Pages
- Maintainable: Easy to manage with data files
- Scalable: Add new languages without changing layout logic
Conclusion
By combining Jekyll’s built-in structure with Liquid’s conditional logic and data-driven UI, you can build a multilingual blog that scales cleanly and performs fast. Best of all, it’s deployable directly on GitHub Pages with no extra tooling.
Next in this series, we’ll explore how to implement a **searchable knowledge base** using Jekyll collections, client-side search, and semantic content structure — all within Mediumish.