Posts

Showing posts with the label Ashley Alena Salvatierra Clemente

How Can You Build a Multilingual Jekyll Site Using Ruby and Data Files

Is It Possible to Build a Multilingual Static Site with Jekyll?

Yes — you can build a multilingual site in Jekyll by combining:

  • YAML/JSON translation files in _data/
  • Per-language content in collections
  • Ruby plugins to route and organize pages

This method allows total control over translations, SEO, and structure, without requiring external CMS or JavaScript.

Folder and URL Structure for Multilingual Content

/_data/translations/
  en.yml
  id.yml
  fr.yml

/_posts/
  en/2025-01-01-welcome.md
  id/2025-01-01-selamat-datang.md

/pages/
  about.en.md
  about.id.md

This structure produces URLs like:

  • /en/about/
  • /id/about/
  • /fr/blog/

Step 1: Create Data Files for Translations

# _data/translations/en.yml
title: "Welcome"
nav:
  home: "Home"
  about: "About Us"
# _data/translations/id.yml
title: "Selamat Datang"
nav:
  home: "Beranda"
  about: "Tentang Kami"

Step 2: Write a Filter to Load Translation Keys

# _plugins/i18n_filter.rb
module Jekyll
  module I18nFilter
    def t(input, lang = "en")
      site = @context.registers[:site]
      translations = site.data["translations"][lang] || {}
      keys = input.split(".")
      keys.reduce(translations) { |memo, key| memo[key] if memo }
    end
  end
end

Liquid::Template.register_filter(Jekyll::I18nFilter)

Usage in Template:

{{ "nav.home" | t: page.lang }}

Step 3: Add Language in Front Matter

---
layout: default
title: About
lang: id
permalink: /id/about/
---

Jekyll will build this as /id/about/ and you can use page.lang for all conditionals.

Step 4: Optional Ruby Plugin for Auto-Permalink by Language

# _plugins/i18n_permalink.rb
Jekyll::Hooks.register :pages, :pre_render do |page|
  if page.data["lang"] && page.data["i18n_slug"]
    lang = page.data["lang"]
    slug = page.data["i18n_slug"]
    page.data["permalink"] = "/#{lang}/#{slug}/"
  end
end
Then use in front matter:
lang: fr
i18n_slug: accueil

Step 5: Language Switcher Menu

You can now build a switcher like this:

<nav class="lang-switcher">
  <a href="/en/{{ page.i18n_slug }}/">EN</a>
  <a href="/id/{{ page.i18n_slug }}/">ID</a>
  <a href="/fr/{{ page.i18n_slug }}/">FR</a>
</nav>

This assumes that your translated pages have matching i18n_slug keys per language.

Step 6: Shared Includes with Translations

# _includes/nav.html
<ul>
  <li><a href="/{{ page.lang }}/">{{ "nav.home" | t: page.lang }}</a></li>
  <li><a href="/{{ page.lang }}/about/">{{ "nav.about" | t: page.lang }}</a></li>
</ul>

This makes your navigation fully translatable.

Bonus: Language Detection from URL

You can extract language from URL in a hook:
Jekyll::Hooks.register :pages, :pre_render do |page|
  url = page.url
  lang_code = url.split("/")[1]
  page.data["lang"] ||= lang_code
end

Tips for SEO and Best Practices

  • Use canonical URLs per language
  • Add hreflang tags for international search indexing
  • Don’t mix multiple languages in one file
  • Use structured folders like /en/, /id/, /fr/

Conclusion

Multilingual support in Jekyll doesn’t require JavaScript or dynamic CMS. With smart use of:

  • YAML files for i18n keys
  • Ruby plugins for slug control and fallback
  • Liquid filters for translations

...you can build a multilingual, SEO-ready, fully static website — all while keeping build logic clean and transparent.

Next Steps

  • Build pages in at least 2 languages
  • Create a simple language switcher
  • Extract all UI strings to YAML

In the next article, we’ll cover **building a multilingual blog with unified pagination**, ensuring posts in each language have their own archive, slugs, and feed.