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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@codegouvfr/eleventy-plugin-i18n

v0.1.3

Published

Eleventy plugin to assist with dictionary translations

Downloads

141

Readme

eleventy-plugin-i18n

Eleventy plugin to assist with internationalization and dictionary translations.

What's in the box? A contextually-aware i18n filter, with smarts and dynamic string interpolation.

Install

Available on npm.

npm install eleventy-plugin-i18n --save

Demo

Dive in to see how the plugin is used in a multilingual Eleventy site:

We'll be writing up a tutorial to provide a guide and some handy 11ty i18n hints (just as soon as we work out what all those letters and numbers mean). For a quick rundown in the meantime, check out the TL;DR walkthrough.

Configuration

1. Define language site directories

Create directories at the site root for each language code (e.g. en) or language code with country code suffix (e.g. en-GB):

├─ src
   └─ en-GB
       ├─ about.njk
       └─ index.njk
   └─ es-ES
       ├─ about.njk
       └─ index.njk

Either is fine. Let's assume we'll need to support multiple dialects in the future, and include country code suffixes.

These directory names determine the lang value of each language site. This enables Eleventy to infer language when translating terms throughout their pages.

2. Create directory data files

In each language site directory, create a locale data file of the same name. Include dir and locale values. E.g. src/en-GB/en-GB.json

{
  "dir": "ltr",
  "locale": "en-GB"
}

👉 Bonus point: Wherever your main HTML document template is defined, include lang and dir attributes:

<html lang="{{ locale }}" dir="{{ dir }}">

3. Add to Eleventy configuration

Open up your Eleventy config file (probably .eleventy.js). Import the plugin and use addPlugin. This is where we provide the translations and fallbackLocales as plugin options:

// .eleventy.js
const i18n = require('eleventy-plugin-i18n');

module.exports = function (eleventyConfig) {
  eleventyConfig.addPlugin(i18n, {
    translations: {
      hello: {
        'en-GB': 'Hello',
        'es-ES': 'Hola'
      }
    },
    fallbackLocales: {
      'es-ES': 'en-GB'
    }
  });
};

translations

Type: Object | Default: {}

Schema: { [key]: { [locale]: 'String' } }

This object contains our dictionary of translations for each respective language. It can be declared inline within the plugin options (as above), but it might be nicer to lift it out into its own JS module to keep things tidy as it grows:

// .eleventy.js
const i18n = require('eleventy-plugin-i18n');
const translations = require('./src/_data/i18n');

module.exports = function (eleventyConfig) {
  eleventyConfig.addPlugin(i18n, {
    translations,
    fallbackLocales: {
      'es-ES': 'en-GB'
    }
  });
};
// src/_data/i18n/index.js
module.exports = {
  hello: {
    'en-GB': 'Hello',
    'es-ES': 'Hola'
  }
};

You might choose to break translations out into their own individual en-GB.js and es-ES.js data files, then import and merge them into a single translations object for the plugin. As long as our translation schema is the same when you're done, we're good to go! (See API: key)

Note: These global data files could also be JSON, but we've opted for JS to offer more flexibility around quotation marks and comments.

fallbackLocales

Type: Object | Default: ‌{}

If a matching translation for a given dictionary item can't be found, the i18n filter will try to find a fallback from the relevant language based on the fallbackLocales key/value pairs you specify. In the examples above, we're specifying that should a translation not be available in Spanish, we'll try to fall back to UK English.

You can also use a wildcard * to specify that all missing translations fall back to a given language:

fallbackLocales: {
  '*': 'en-GB'
}

👀 eleventy-plugin-i18n will warn you in the Node console when the intended translation or fallback values can't be found for a given language based on your translations data.

Usage

Once configured, the i18n Universal filter is available throughout Nunjucks, Handlebars, Liquid, and JavaScript templates and includes. E.g. To return the translation for our hello key in Nunjucks or Liquid syntax:

{{ 'hello' | i18n }}

Whether used in a page, layout or include, the filter will automatically determine the correct translation to use based on its site's language. No need to pass locale everywhere it's used!

API

i18n(key, data?, localeOverride?)

Returns: String

key

Type: String

The translation lookup key for our dictionary item.

😯 Fun fact: Translation objects can be structured however you like, as long as the locale is at the end of the chain. i18n uses lodash's get under the hood to make dot notation lookups like this easy peasy:

module.exports = {
  actions: {
    click: {
      'en-GB': 'Click',
      'es-ES': 'Hacer clic'
    }
  }
};
{{ 'actions.click' | i18n }}

data

Type: Object | Default: {}

Translation values can interpolate data using the {{ }} syntax (thanks to @lukeed's awesome templite — check out their docs!). For example, given the translation:

module.exports = {
  hello_name: {
    'en-GB': 'Hello, {{ name }}!',
    'es-ES': '¡Hola {{ name }}!'
  }
};
{{ 'hello_name' | i18n({ name: 'Eve' }) }}
{# Returns: "Hello, Eve!" or "¡Hola Eve!" #}

localeOverride

Type: String

We can guarantee a translation will always return in a given language by including a localeOverride as the second argument. For example, this will always render in Spanish, no matter which country site it's in. Muy bueno!

{{ 'hello' | i18n({}, 'es-ES') }}

Note: Here we still have to pass the first data argument, even if no interpolation is needed. You can pass an empty object {} or undefined.

Roadmap

  • [ ] Write up tutorial to build on some great concepts (multilingual, language toggle) in this area. Dive deeper into how to architect and implement multilingual Eleventy sites, and leverage the plugin (e.g. smart language switching, using Netlify's _redirects to get users to where they need to go).
  • [ ] Jekyll/Hugo sites often have similar libraries with t or T filters as an alias for i18n. Worthwhile for those migrating?
  • [ ] Quiet mode option? Some might want to suppress the console logs on missing translations?
  • [ ] Explore shipping additional i18n-aware pluralize filter {{ 'apple' | i18n | pluralize(3) }} (Awesome suggestion from @alexcarpenter).
  • [ ] Move to v1.0.0 once we've gathered some feedback on the API.
  • [ ] Consider how one might still be able to achieve a simple language switcher if site trees diverge (e.g. if es-ES url paths are en Español).

Read more about Eleventy plugins.

Feedback welcome 🙌