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

fastify-i18next-plugin

v0.1.0

Published

A simple i18next plugin for fastify

Downloads

16

Readme

fastify-i18next-plugin

Coverage Status neostandard javascript style

A simple plugin for using i18next with fastify.

Install

npm install fastify-i18next-plugin

Example

import fastify from 'fastify'
import i18nPlugin from 'fastify-i18next-plugin'
const app = fastify()

app.register(i18nPlugin, {
  // Languages to support (required)
  languages: ['en', 'it'],
  resources: {
    // Lang
    en: {
      // i18next namespace
      messages: {
        // Key and message
        hello: 'Hello {{name}}'
      }
    },
    it: {
      messages: {
        hello: 'Ciao {{name}}'
      }
    }
  }
})

app.get('/en', (request, reply) => {
  // Set language of the messages returned from request.t()
  request.setLanguage('en')
  return request.t('messages:hello', { name: 'Daria' })
})

app.get('/it', (request, reply) => {
  // Set language of the messages returned from request.t()
  request.setLanguage('it')
  return request.t('messages:hello', { name: 'Daria' })
})

// Hello Daria
app.inject('/en')
  .then(res => console.log(res.payload))

// Ciao Daria
app.inject('/it')
  .then(res => console.log(res.payload))

Loading JSON resources from disk

Providing a path pattern to opts.loadPath will allow you load JSON locale files from disk. The path must include {{ns}} and {{lng}} patterns so that the namespace and language of the resource can be determined.

For example, given the following structure:

└ locales/
    ├ en/
    │ ├ messages.json
    │ └ greetings.json
    └ it/
      ├ messages.json
      └ greetings.json

The path ./locales/{{lng}}/{{ns}}.json will load the messages.json and greetings.json files in the en and it directories, and add them to the messages and greetings namespaces for English and Italian.

Eg:

// ./locales/it/greetings.json
{
  "nested": {
    "hello": "Ciao!"
  }
}
import { join } from 'node:path'
import fastify from 'fastify'
import i18nPlugin from 'fastify-i18next-plugin'
const app = fastify()

await app.register(i18nPlugin, {
  languages: ['en', 'it'],
  // Will load: ./locales/en/greetings.json, ./locales/it/greetings.json
  // setting the langues from the path and namespace from the filename
  loadPath: join(import.meta.dirname, './locales/{{lng}}/{{ns}}.json')
})

// Ciao!
console.log(app.t('greetings:nested.hello', 'it'))

Loading resources within another plugin

You can still load resources after the plugin is registered using the fastify.addI18nResource() and fastify.loadI18nResources() functions.

import fastify from 'fastify'
import i18nPlugin from 'fastify-i18next-plugin'
const app = fastify()

app.register(i18nPlugin, {
  languages: ['en', 'it']
})

app.register((instance) => {
  instance.addI18nResource('en', 'greeting', { hello: 'Hello' })
  instance.addI18nResource('it', 'greeting', { hello: 'Ciao' })
  instance.loadI18nResources('./locales/{{lng}}.{{ns}}.json')
  instance.log.info(instance.t('greeting:hello', 'en'))
})

Adding i18next formatters

Use the fastify.addI18nFormatter() and fastify.addI18nCachedFormatter() functions to add i18next formatters. See the i18next formatting documention for more info about their usage.

import fastify from 'fastify'
import i18nPlugin from 'fastify-i18next-plugin'
const app = fastify()

await app.register(i18nPlugin, {
  languages: ['en', 'it'],
  resources: {
    en: {
      messages: {
        hello: 'Hello {{name, upper}}',
        helloAll: 'Hello {{names, list}}'
      }
    }
  }
})

app.addI18nFormatter('upper', (val) => val.toUpperCase())
app.addI18nCachedFormatter('list', (lng) => {
  const formatter = new Intl.ListFormat(lng, {
    style: 'long',
    type: 'conjunction',
  })
  return (val) => formatter.format(val)
})

// Hello DARIA
app.t('messages:hello', 'en', { name: 'Daria' })

// Hello Niall, James, and Tim
app.t('messages:helloAll', 'en', { names: ['Niall', 'James', 'Tim'] })

Detecting the language for the request

Setting the languageDetectors option will add a hook to detect the language from any or all of the following: a URL path parameter, query string, cookie, session or accept header. The detectors will run in the order they appear in the languageDetectors array and stop as soon as a supported language is found.

When using either the session or cookie detectors, the detected language will be persisted to the session or cookie, even if it was detected by a different detector, eg: the query string detector.

import fastify from 'fastify'
import cookiePlugin from '@fastify/cookie'
import i18nPlugin from 'fastify-i18next-plugin'
const app = fastify()

app.register(cookiePlugin)
app.register(i18nPlugin, {
  fallbackLng: 'en',
  languages: ['en', 'it', 'cy'],
  languageDetectors: ['query', 'cookie']
})

app.get('/', (request, reply) => {
  return request.lng
})

// 'en', fallback language
app.inject('/').then(res => console.log(res.payload))

// 'it', detected from lng cookie
app.inject({
  path: '/',
  cookies: { lng: 'it' }
})
  .then(res => console.log(res.payload))

// 'cy', detected from lng query, the cookie won't be checked as it is lower
// priority
app.inject({
  path: '/',
  query: { lng: 'cy' },
  cookies: { lng: 'it' }
})
  .then(res => console.log(res.payload))

Plugin options

  • fallbackLng (String): The default language code to use. Default: the first language in the languages array.
  • languages (Array): List of language codes to support, trying to change to a language not in the list will instead set the fallback language.
  • resources (Object): Object map of locale messages, in the format { lang: { namespace: { key: message } } }.
  • loadPath (String): Path to load JSON file resources from, namespace and language are determined from path parameters, eg: ./locales/{{lng}}/{{ns}}.json.
  • languageDetectors (Array): A list of language detectors to use, will be run in the supplied order until a supported language is detected. Can be one to many of the following:
    • "query": Detect language from query string.
    • "param": Detect language from parsed URL path parameter (eg: request.params.lng).
    • "accept": Detect language from the language accept header. Note: the @fastify/accepts plugin must be loaded to use this detector.
    • "cookie": Detect language from cookie value (will also persist any detected language to this cookie). Note: the @fastify/cookie plugin must be loaded to use this detector.
    • "session": Detect language from session value (will also persist any detected language to this sesion property). Note: the @fastify/session plugin must be loaded to use this detector.
  • queryKey (String): The query value to use for the query language detector. Default: lng.
  • param (String): The path paramter to use for the param language detector. Default: lng.
  • sessionKey (String): The session property to use for the session language detector. Default: lng.
  • cookieName (String): The cookie to use for the cookie language detector. Default: lng.
  • cookieOpts (Object): The cookie options to use when setting the language cookie. See the @fastify/cookie options for more details. Default: { path: '/', sameSite: true, httpOnly: true }
  • decorateLocals (Boolean): Decorate reply.locals with language properties and t() for use in templates, for example when using @fastify/view.

Server decorators

app.t('namespace:key') // Get a message for the fallback language
app.t('namespace:key', opts) // Get a message with options object, eg data to interpolate
app.addI18nFormatter('name', func) // Add an i18next formatter
app.addI18nCachedFormatter('name', func) // Add an i18next cached formatter
app.addI18nResource('lang', 'namespace', { key: 'Message' }) // Add new locales messages
app.loadI18nResources('./locales/{{lng}}.{{ns}}.json') // Load JSON locales files from a path pattern

Request decorators

app.get('/', (request, reply) => {
  request.setLanguage('en') // Sets language to English
  request.lng // The currently set language code
  request.lngDir // Direction of current language, eg: 'ltr', 'rtl'
  request.lngs // The currently support languages, eg: ['en', 'it']
  request.t('messages:hello') // Get a message for the current language
  request.i18nKeyExists('messages:hello') // Returns true if given key has a value
})

reply.locals properties (if decorateLocals is true)

app.get('/', (request, reply) => {
  reply.locals.t('messages:hello') // same as request.t
  reply.locals.exists('messages:hello') // same as request.i18nKeyExists
  reply.locals.lngs // same as request.lngs
  reply.locals.lng // same as request.lng
  reply.locals.lngDir // same as request.lngDir
  reply.locals.language // same as request.lng
  reply.locals.languageDir // same as request.lngDir
})