@mielp/eleventy-plugin-i18n v1.0.0
@mielp/eleventy-plugin-i18n
Very simple flat translation plugin for Eleventy v3.
This is an ESM-only package.
Install
Install from npm.
npm i -D eleventy-plugin-i18nConfigure
This plugin supports the following configuration options:
{
// Translation dictionaries, one for each supported locale
translations: {
[locale: string]: {
[key: string]: string
}
},
// Recommended: a default locale to fallback to when something is missing
defaultFallback: string,
// Recommended: an array of preferred fallbacks for each locale
localeFallbacks: {
[locale: string]: string[]
},
// Optional: the name of the filter, default is `t`
filterName: string
}!NOTE
Dictionary translations are "flat". The keya.b.cwill not refer to a nestedtranslations[page.lang].a.b.cvalue, but directly totranslations[page.lang]["a.b.c"].This is different from what many other i18n plugins will do. It makes sense for my use case: on the websites I maintain, I use a CMS like Decap or Sveltia to manage translations in a flat per-language dictionary structure. It works really well for me.
Usage
Basic usage
From any template, call the t filter (or whatever you named it). It accepts 3 parameters:
t(
key: string, // The string to translate
data?: object | array, // Optional data object for template interpolation
localeOverride?: string // Optional locale to enforce instead of the page locale
);Short syntax: {{ t('hello') }} and {{ 'hello' | t }} are equivalent.
The locale used to find the translation string will default to the value of page.lang, or one of the configured fallbacks if the key hello is not found in the page.lang translation dictionary.
Full syntax: {{ t('hello', data, 'eo') }} and {{ 'hello' | t(data, 'eo') }} are equivalent.
The locale used to find the translation string will be eo, or one of the configured fallbacks if the key hello is not found in the eo translation dictionary. The data object is passed directly to templite to resolve values for the translation template.
Translation templates
This plugin uses templite under the hood. Translation messages are templates, in which {{something}} is a special syntax that denotes a token.
Tokens are replaced with value from the data object passed to the filter. The data object can be a standard object or an array, and can also be nested (see templite's usage for more information).
Example:
With the following dictionary:
{ "current.year": "We are in {{y}}" }The text {{ 'current.year' | t({ y: 2025 }) }} would be translated to We are in 2025.
Simple translation fallback
This plugin supports configuring fallbacks through the defaultFallback option. It accepts a single locale, or an array of locales. In the case of an array, the first element has highest priority, and the last element has lowest priority.
Example:
With the following fallback:
{ "defaultFallback": "en" }When requesting a translation for the fr locale, if the key is not found in the fr dictionary, the plugin will try to find it in the en dictionary. A warning is logged to the console to help you identify and add the missing translations.
It is also possible to use an array:
{ "defaultFallback": ["en", "es"] }When requesting a translation for the fr locale, if the key is not found in the fr dictionary, the plugin will try to find it in the en dictionary. If it is not found, the plugin will try to find it in the es dictionary. A warning is logged to the console to help you identify and add the missing translations.
Per-locale translation fallback
This plugin also supports configuring per-locale fallbacks through the localeFallbacks option. It accepts a object that maps an input locale to its fallbacks (a single string or an array of strings).
Example:
With the following fallbacks:
{ "localeFallbacks": {
"fr": ["eo", "es"]
} }When requesting a translation for the fr locale, if the key is not found in the fr dictionary, the plugin will try to find it in the eo dictionary. If it is not found, the plugin will try to find it in the es dictionary. A warning is logged to the console to help you identify and add the missing translations.
If the key is not found in any of these dictionaries, the plugin will try the fallbacks set in the global defaultFallback option.
If the translation isn't found anywhere, an error is thrown.
Example
Configuration for a multilingual website that supports Esperanto, Spanish, French and Toki Pona:
import eleventyPluginI18n from "@mielp/eleventy-plugin-i18n";
// Fictional method that fetches a dictionary of translations
import fetchDictionary from "./your-code.js";
export default function (eleventyConfig) {
eleventyConfig.addPlugin(eleventyPluginI18n, {
translations: {
"eo": fetchDictionary("esperanto"),
"es-ES": fetchDictionary("spanish"),
"fr-FR": fetchDictionary("french"),
// Dictionary example: each dictionary is a key-value pair.
"tok": {
"welcome": "o kama pona!",
"current.year": "lon tenpo {{year}}.",
},
},
defaultFallback: "eo",
localeFallbacks: {
"eo": "es-ES", // Fallback Esperanto to Spanish
"fr-FR": "es-ES", // Fallback French to Spanish
},
});
}!WARNING
The fallback locales are not transitive. In the above example, if a key foreois missing, it will fallback toes-ES, as configured. If a key fortokis missing, it will fallback toeoas configured, but not toes-ES(which is in the fallback list foreo, but not fortok).
With the following Nunjucks template:
---
# We can define additional dictionary information in the frontmatter
i18n:
en:
"welcome": "Welcome!"
---
{{ 'welcome' | t }}
{{ 'welcome' | t({}, 'en') }}
{{ 'current.year' | t({ year: 2025 }) }}
{{ 'goodbye' | t }}In each supported language, the above file would be translated to:
French, assuming all translation keys exist:
Bienvenue ! Welcome! On est en 2025. Au revoir !Spanish, assuming "goodbye" is missing, will fallback to Esperanto, the main
defaultFallback:¡Bienvenido! Welcome! Es 2025. Ĝis!Esperanto, assuming "current.year" is missing, will fallback to Spanish, according to the rules in
localeFallbacks:Bonvenon! Welcome! Es 2025. Ĝis!Toki pona, assuming "goodbye" is missing, will fallback to Esperanto, the main
defaultFallback:o kama pona! Welcome! lon tenpo 2025. Ĝis!
Roadmap
- Improve documentation
- Add integration tests for 11ty+Nunjucks and 11ty+Liquid
- Add an example of a working multilingual website
8 months ago