Localized Navigation Menus with YAML Data in Jekyll
Why You Need Language-Aware Menus
When building a multilingual site in Jekyll, your navigation menus need to reflect the current language context. A user browsing the French version of your site should not see English labels or links pointing to English pages. Instead of duplicating navigation code across each layout, the smarter approach is to centralize the structure using YAML data files.
Step 1: Create a Navigation YAML File
Inside your _data folder, create a file named navigation.yml. Define language-specific navigation entries:
en:
- title: "Home"
url: "/en/"
- title: "About"
url: "/en/about/"
- title: "Docs"
url: "/en/docs/"
fr:
- title: "Accueil"
url: "/fr/"
- title: "À propos"
url: "/fr/about/"
- title: "Documentation"
url: "/fr/docs/"
This keeps all navigation logic in one file, making it easy to maintain and extend as you add languages or pages.
Step 2: Include the Menu in Your Layout
Edit your layout file (e.g., default.html) to dynamically load the correct menu based on the current page’s language:
{% raw %}
{% endraw %}
This code automatically loads the corresponding menu for the language defined in the page’s front matter via page.lang.
Step 3: Add Language to Each Page
Ensure each page defines its language to load the correct navigation set:
lang: fr
Combined with language-specific permalinks, this ensures total consistency across the user experience.
Step 4: Active Menu Highlighting
To highlight the current page’s link in the menu, use a comparison in Liquid:
{% raw %}
<li class="{% if page.url == item.url %}active{% endif %}">
<a href="{{ item.url }}">{{ item.title }}</a>
</li>
{% endraw %}
Step 5: Add CSS Styling
Style the menu with basic CSS. Example:
nav ul {
list-style: none;
display: flex;
gap: 1rem;
}
nav li.active a {
font-weight: bold;
text-decoration: underline;
}
Step 6: Expandable Menus for Sections
For menus with nested sections, structure the YAML like this:
en:
- title: "Docs"
url: "/en/docs/"
children:
- title: "Getting Started"
url: "/en/docs/getting-started/"
- title: "API Reference"
url: "/en/docs/api/"
Render nested menus using a recursive loop or conditional logic:
{% raw %}
{% for item in nav_items %}
<li>
<a href="{{ item.url }}">{{ item.title }}</a>
{% if item.children %}
<ul>
{% for sub in item.children %}
<li><a href="{{ sub.url }}">{{ sub.title }}</a></li>
{% endfor %}
</ul>
{% endif %}
</li>
{% endfor %}
{% endraw %}
Step 7: Language-Sensitive Breadcrumbs
You can also generate breadcrumbs using the same navigation data. For each page, use the navigation map to determine the current hierarchy.
This allows consistent and language-aware navigation patterns across the site, enhancing usability and SEO.
Use Case: Global Software Product Documentation
Imagine your software platform supports users in English, Japanese, and Portuguese. Using a centralized navigation YAML, your development team can roll out menu changes across all languages by simply editing one file. This minimizes overhead, reduces translation drift, and ensures a smooth global user experience.
Bonus: Navigation Order Control
YAML files maintain order naturally, but if needed, you can add a weight key and sort them manually in Liquid:
- title: "Home"
url: "/en/"
weight: 1
- title: "About"
url: "/en/about/"
weight: 2
{% raw %}
{% assign nav_items = site.data.navigation[page.lang] | sort: "weight" %}
{% endraw %}
Conclusion
With YAML-based navigation, your multilingual Jekyll site becomes easier to scale, maintain, and translate. You decouple structure from layout and gain complete control over content presentation without repeating code.
In the next article, we’ll explore how to build search indexes per language for multilingual search, allowing users to find content in their own language with blazing speed using client-side search tools.
