GitHub

eleventyNavigation
key title order excerpt

Internationalization (i18n)

<i class="fa-solid fa-language"></i>Internationalization (i18n)

1

Utilities to manage pages and linking between localized content on Eleventy projects.

communityLinksKey i18n
hideRelatedLinks true
overrideCommunityLinks true

Internationalization (I18n) {% addedin "2.0.0-canary.13" %}

{% tableofcontents %}

{% callout "info", "md" %}Required reading: the Eleventy docs page on Internationalization (I18n) provides crucial context on project organization and URL strategies for multi-language projects. Please review it before continuing on here.{% endcallout %}

{{ eleventyNavigation.excerpt }}

Note that this plugin specifically helps you manage links between content but does not localize that content’s strings, numbers, dates, etc. You’ll likely want to pick a third-party library for this! A few popular choices include eleventy-plugin-i18n, rosetta, i18next, y18n, intl-messageformat, and LinguiJS.

{%- youtubeEmbed "sfPNgt3joWI", "Internationalization (i18n) Plugin (Weekly №16)", "1122" -%}

Installation

The Internationalization (i18n) plugin is bundled with Eleventy and does not require separate installation. Available in version {{ "2.0.0-canary.13" | coerceVersion }} or newer.

If you don’t yet have an Eleventy project, go through the Get Started Guide first and come back here when you’re done!

Add to your configuration file

{% include "snippets/plugins/i18n-install.njk" %}

Expand to see the full list of advanced options

{% include "snippets/plugins/i18n-install-options.njk" %}

Usage

This plugin provides two universal filters (Nunjucks, Liquid, 11ty.js) and one addition to the page variable.

page.lang

Adding the i18n plugin to your project will make page.lang available to your templates. This represents the language tag for the current page template, and will default to the value you’ve passed to the plugin via defaultLanguage above.

Check out the rest of the data available on the page object.

locale_url Filter

Accepts any arbitrary URL string and transforms it using the current page’s locale. Works as expected if the URL already contains a language code. This is most useful in any shared code used by internationalized content (layouts, partials, includes, etc).

{% include "snippets/plugins/i18nlocaleurl.njk" %}

If the link argument already has a valid language code, it will be swapped. The following all return /en/blog/ when rendered in /en/* templates (or /es/blog/ in /es/* templates):

{% raw %}

  • {{ "/blog/" | locale_url }}
  • {{ "/en/blog/" | locale_url }}
  • {{ "/es/blog/" | locale_url }} {% endraw %}

{% callout "info", "md" -%} It’s important to note that this filter checks for the existence of the file in the target locale. If the specific content file in the target locale does not exist, an error will be thrown! You can change this behavior using the plugin’s errorMode option (see advanced usage above). {% endcallout %}

It’s unlikely that you’ll need to but you can override the root locale with a second argument:

{% include "snippets/plugins/i18nlocaleurl-arg.njk" %}

locale_links Filter

Returns an array of the relevant alternative content for a specified URL (or, defaults to the current page). The original page passed to the filter is not included in the results. Each array entry is an object with url, lang, and (localized) label properties, for example:

[{ "url": "/es/blog/", "lang": "es", "label": "Español" }]

“This page also available in:” Example

{% include "snippets/plugins/i18nexample.njk" %}

Renders as:

This page is also available in <a href="/es/blog/" lang="es" hreflang="es">Español</a>

<link rel="alternate"> Example

Here’s another example in a layout file.

The href attributes here must be fully qualified (include the full domain with the protocol). Read more on the Google Search Central documentation.

{% callout "info", "md" %}The top level lang data property used here is most commonly set by you in the data cascade. For example: /en/en.json with {"lang": "en"} and /es/es.json with {"lang": "es"}.{% endcallout %}

{% include "snippets/plugins/i18nalternate.njk" %}

Using with get*CollectionItem filters

The getPreviousCollectionItem, getNextCollectionItem and getCollectionItem filters all provide a mechanism to retrieve a specific collection item from a collection.

The i18n plugin modifies the behavior of these filters to prefer a collection item in the current page language’s without requiring any changes to your project.

For example, assume that English (en) is the default language for your project. Assume we’ve configured all of the blog posts in /en/blog/*.md to have the post tag, placing them into a post collection. Now you want to provide alternative localized versions of this blog post, so you create the following files:

  • /es/blog/my-blog-post.md
  • /ja/blog/my-blog-post.md

Using the above filters on these localized templates will automatically prefer /en/blog/my-blog-post.md as the root collection item when navigating the collection. This allows you to do things like:

{% codetitle "Nunjucks", "Syntax" %} {% raw %}

{%- set nextPost = collections.post | getNextCollectionItem %}
{%- if nextPost %}<a href="{{ nextPost.url | locale_url }}">Next post</a>{% endif %}

{% endraw %}

This will prefer a localized version of the next post’s URL (Spanish pages will prefer linking to other pages in Spanish, when available). If a localized version does not exist, it will fall back to the default language instead.

Read the original on github.com ↗