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-multilingual

v1.1.0

Published

Fastify plugin to decorate the request with different translations, based on available Polyglot.js phrases.

Downloads

22

Readme

fastify-multilingual

neostandard javascript style CI NPM Version

A Fastify plugin that decorates requests with internationalization (i18n) capabilities using Polyglot.js. The plugin automatically detects user language preferences from Accept-Language headers and provides localized phrases with support for pluralization and nested phrase structures.

Features

  • 🌍 Automatic locale detection from Accept-Language headers
  • 📦 Polyglot.js integration for powerful i18n features
  • 🔄 Graceful fallback to default locale
  • 🏗️ Support for nested phrase structures
  • ⚡ Per-request polyglot instances for optimal performance
  • 🛡️ TypeScript support with full type safety

Compatibility

| Plugin Version | Fastify Version | Node.js Version | | -------------- | --------------- | --------------- | | 1.x.x | ^5.0.0 | >=20.0.0 |

Installation

npm install fastify-multilingual

Usage

Basic Setup

const fastify = require('fastify')({ logger: true });

// Define your phrases
const phrases = {
  en: {
    greeting: {
      hi: 'Hello',
      welcome: 'Welcome %{name}'
    },
    404: {
      not_found: 'Page not found'
    }
  },
  it: {
    greeting: {
      hi: 'Ciao',
      welcome: 'Benvenuto %{name}'
    },
    404: {
      not_found: 'Pagina non trovata'
    }
  }
};

// Register the plugin
await fastify.register(require('fastify-multilingual'), {
  multilingual: {
    phrases,
    defaultTranslation: 'en'
  }
});

// Use in routes
fastify.get('/', async (request, reply) => {
  const polyglot = request.polyglot;
  
  return {
    message: polyglot.t('greeting.hi'),
    welcome: polyglot.t('greeting.welcome', { name: 'World' }),
    availableTranslations: request.availableTranslations
  };
});

await fastify.listen({ port: 3000 });

Organizing Phrases in Separate Files

For larger applications, it's recommended to organize phrases in separate files by locale. Here's how to structure your i18n files:

i18n/
├── index.js          # Combines all locale files
├── en.js             # English phrases
├── it.js             # Italian phrases
└── pt-BR.js          # Portuguese (Brazil) phrases

Individual locale files:

// i18n/en.js
export const phrases = {
  greeting: {
    hi: 'Hello',
    welcome: 'Welcome %{name}'
  },
  404: {
    not_found: 'Page not found'
  },
  other: 'Not nested'
};
// i18n/it.js
const phrases = {
  greeting: {
    hi: 'Ciao'
  },
  404: {
    not_found: 'Pagina non trovata'
  }
};

export default phrases;

Index file to combine all locales:

// i18n/index.js
import { phrases as en } from './en.js';
import it from './it.js';
import { phrases as pt_BR } from './pt-BR.js';

export const phrases = {
  en: { ...en },
  it: { ...it },
  pt_BR: { ...pt_BR }
};

Using in your Fastify application:

import fastify from 'fastify';
import fastifyMultilingual from 'fastify-multilingual';
import { phrases } from './i18n/index.js';

const app = fastify({ logger: true });

await app.register(fastifyMultilingual, {
  multilingual: {
    phrases,
    defaultTranslation: 'en'
  }
});

See a complete example in the repository

TypeScript Usage

import fastify, { FastifyRequest, FastifyReply } from 'fastify';
import fastifyMultilingual, { NestedPhrases } from 'fastify-multilingual';

const app = fastify({ logger: true });

const phrases: NestedPhrases = {
  en: {
    greeting: { 
      hi: 'Hello',
      welcome: 'Welcome %{name}'
    }
  },
  it: {
    greeting: { 
      hi: 'Ciao',
      welcome: 'Benvenuto %{name}'
    }
  }
};

await app.register(fastifyMultilingual, {
  multilingual: {
    phrases,
    defaultTranslation: 'en'
  }
});

// TypeScript route with proper typing
app.get('/', async (request: FastifyRequest, reply: FastifyReply) => {
  const { polyglot } = request;
  
  return {
    message: polyglot.t('greeting.hi'),
    welcome: polyglot.t('greeting.welcome', { name: 'TypeScript' }),
    availableTranslations: request.availableTranslations
  };
});

Configuration Options

The plugin accepts the following options:

multilingual

| Property | Type | Required | Description | | --------------- | -------- | -------- | ----------- | | phrases | NestedPhrases | Yes | Object containing locale-keyed phrase objects | | defaultTranslation | string \| null | Yes | Fallback locale when user's preferred locale is unavailable |

Phrases Structure

The phrases object supports nested structures:

{
  "en": {
    "simple": "Simple message",
    "nested": {
      "deep": {
        "message": "Deeply nested message"
      }
    },
    "pluralization": "You have %{smart_count} message |||| You have %{smart_count} messages"
  }
}

API Reference

The plugin decorates the Fastify request object with the following properties:

request.polyglot

Returns a Polyglot instance configured for the user's detected locale, as set in the onRequest hook.

const polyglot = request.polyglot;
const message = polyglot.t('greeting.hi');

request.availableTranslations

String containing comma-separated list of available locales.

console.log(request.availableTranslations); // "en,it,pt-BR"

request['polyglot-{locale}']

Access polyglot instances for specific locales:

const englishPolyglot = request['polyglot-en'];
const italianPolyglot = request['polyglot-it'];

Locale Detection

The plugin automatically detects the user's preferred locale using the following priority:

  1. Parse Accept-Language header
  2. Match against available locales (exact match first, then language family)
  3. Fall back to defaultTranslation
  4. If no default translation, return key-based responses

Example Accept-Language header processing:

  • en-US,en;q=0.9,it;q=0.8 → Prefers en-US, falls back to en, then it
  • pt-BR,pt;q=0.9 → Prefers pt-BR, falls back to pt

Examples

Running the Example

The repository includes a working example demonstrating the plugin:

# Start the example server
npm run example

# Test with different locales
npm run example:get

The example server runs on port 3000 and includes phrases in English, Italian, Portuguese (Brazil), and German (not present) fallback handling.

Testing Different Locales

# Test English
curl -H "Accept-Language: en" http://localhost:3000/

# Test Italian  
curl -H "Accept-Language: it" http://localhost:3000/

# Test Portuguese (Brazil)
curl -H "Accept-Language: pt-BR" http://localhost:3000/

# Test fallback (German → English)
curl -H "Accept-Language: de" http://localhost:3000/

Development

Using with Dev Containers

This project supports Development Containers for a consistent development environment. The devcontainer configuration includes Node.js 20, npm, and all necessary development tools.

Using with VS Code:

  1. Install the Dev Containers extension
  2. Open the project in VS Code
  3. When prompted, click "Reopen in Container" or use Ctrl+Shift+P → "Dev Containers: Reopen in Container"
  4. VS Code will build the container and install dependencies automatically

Using with GitHub Codespaces:

  1. Navigate to the repository on GitHub
  2. Click the green "Code" button → "Codespaces" tab → "Create codespace on main"
  3. The environment will be ready with all dependencies installed

Manual setup in any devcontainer-compatible environment:

# The container will automatically run these commands:
npm install                # Install dependencies
npm run build             # Build the project
npm test                  # Verify everything works

Once inside the devcontainer, you can use all the standard development commands like npm run example, npm test, and npm run build as documented below.

Building

npm run build          # Compile TypeScript
npm run build:clean    # Clean build and rebuild

Testing

The project uses Node.js built-in test runner with comprehensive test coverage:

npm test               # Build and run all tests

Test coverage includes:

  • Locale detection and matching algorithms
  • Fallback behavior for unsupported locales
  • Nested phrase structure support
  • Malformed Accept-Language header handling
  • Plugin registration and decorator behavior

Code Style

The project uses neostandard ESLint configuration:

npx eslint .           # Check code style
npx eslint . --fix     # Auto-fix style issues

Project Structure

├── src/
│   ├── plugin.ts      # Main plugin implementation
│   └── util.ts        # Locale matching utilities
├── test/              # Test files
├── example/           # Working example application
└── dist/              # Compiled output

Continuous Integration

The project includes automated CI/CD with:

  • GitHub Actions: Automated testing on Node.js 20.x and 22.x
  • Dependabot: Daily dependency updates
  • Code Quality: Automated linting and type checking

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Write tests for your changes
  4. Ensure all tests pass and code follows style guidelines
  5. Submit a pull request

License

Licensed under MIT.