npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@mielp/eleventy-plugin-i18n

v1.0.0

Published

Simple translation plugin for 11ty v3.

Readme

@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-i18n

Configure

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 key a.b.c will not refer to a nested translations[page.lang].a.b.c value, but directly to translations[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 for eo is missing, it will fallback to es-ES, as configured. If a key for tok is missing, it will fallback to eo as configured, but not to es-ES (which is in the fallback list for eo, but not for tok).

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