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

grammy-pug

v1.0.4

Published

i18n with pug for grammy

Downloads

534

Readme

Grammy-Pug

A lightweight and flexible i18n (internationalization) plugin for Grammy that uses Pug templates for localization.
Render dynamic, locale-specific messages with ease using Pug’s powerful templating syntax.


Features

  • Pug‑based templates – Use loops, conditionals, variables, and includes directly in your locale files.
  • Automatic locale detection – Detects user language from ctx.from.language_code or session __lang.
  • Session‑based language switching – Store user language preference in session for persistence.
  • File‑based caching – Templates are compiled and cached for fast repeated use (optional).
  • Lightweight – Minimal dependencies, fast filesystem-based loading.
  • TypeScript ready – Includes full type definitions.
  • Recursive template lookup – Automatically discovers nested template files in locale directories.

Installation

npm install grammy-pug
# or
yarn add grammy-pug

Quick Start

  1. Prepare your locale folder structure:
locales/
├── en/
│   ├── welcome.pug
│   └── menu.pug
└── ru/
    ├── welcome.pug
    └── menu.pug
  1. Write a Pug template (example locales/en/welcome.pug):
| Hello, #{name}! Welcome to #{botName}.
| You have #{count} new messages.
  1. Set up the plugin in your bot:
import { Bot, Context, session } from 'grammy';
import { pug, PugFlavor } from 'grammy-pug';

// Extend your context type
type MyContext = Context & PugFlavor;

const bot = new Bot<MyContext>('BOT_TOKEN');

// Initialize session (required for storing language preference)
bot.use(session({ initial: () => ({ __lang: undefined }) }));

// Use the plugin
bot.use(
  pug({
    folder: 'locales',          // path to locale folder (optional, default: 'locales')
    defaultLocale: 'en',        // fallback locale (required)
    debug: 'none',              // debug mode (optional)
    globals: { botName: 'MyBot' }, // shared variables for all templates (optional)
    cache: true,                // cache compiled templates (optional, default: true)
    showMismatches: false,      // show missing templates across locales (optional)
  })
);

// Use in handlers
bot.command('start', async (ctx) => {
  const name = ctx.from?.first_name ?? 'User';
  const text = ctx.t('welcome', { name, count: 5 });
  await ctx.reply(text);
});

// Switch language example
bot.command('setlang_ru', async (ctx) => {
  ctx.session.__lang = 'ru';
  await ctx.reply('Language switched to Russian!');
});

bot.start();

API

pug(options: PugOptions): Middleware<C>

Options

| Option | Type | Default | Description | | ---------------- | ----------------------------------------------------------- | -------------- | -------------------------------------------------------------------------------------------------- | | folder | string | 'locales' | Path to folder containing locale subdirectories. | | defaultLocale | string | (required) | Fallback locale if user’s language is not supported. | | debug | 'none' \| 'pug' \| 'plugin' \| 'all' | 'none' | Enable debug logging of template compilation, plugin internals, or both. | | globals | LocalsObject | {} | Shared variables accessible in all Pug templates. | | filters | Record<string, (text: string, options: object) => string> | {} | Custom Pug filters. | | cache | boolean | true | Cache compiled templates for faster repeated rendering. | | showMismatches | boolean | false | Show missing templates across locales (automatically enabled in debug mode 'plugin' or 'all'). |

Context Extension

The plugin adds a t(key, variables?) method to your context:

ctx.t('welcome', { name: 'Alice', count: 3 })
  • key – Template filename without extension (e.g., 'welcome'). Supports nested paths like 'subfolder/template'.
  • variables – Optional object of template variables (merged with globals).

Language Detection Order

  1. ctx.session.__lang (if session is used)
  2. ctx.from.language_code
  3. Falls back to defaultLocale

Template Examples

Simple variable interpolation (locales/en/hello.pug):

| Hello, #{username}!

Conditionals and loops (locales/en/stats.pug):

if users.length > 0
  | Active users:
  each user in users
    | - #{user.name}
else
  | No active users.

Using globals (set via globals: { site: 'example.com' }):

| Visit #{site} for more info.

Multiline messages (locales/en/help.pug):

| Available commands:
| /start - Start bot
| /help  - Show this help
| /lang  - Change language

Nested template structure (supports subdirectories):

locales/en/
├── common/
│   ├── buttons.pug
│   └── footer.pug
└── main.pug

Usage: ctx.t('common/buttons', { ... })

Advanced Usage

Custom Pug Filters

You can define custom Pug filters in the options:

pug({
  defaultLocale: 'en',
  filters: {
    uppercase: (text) => text.toUpperCase(),
    reverse: (text) => text.split('').reverse().join(''),
  },
})

Then use them in templates:

| #{message | uppercase}

Debug Modes

The plugin offers four debug modes:

pug({
  defaultLocale: 'en',
  debug: 'none',      // No debug output (default)
  // debug: 'pug',       // Show Pug compilation debug info
  // debug: 'plugin',    // Show plugin internals (loaded locales, mismatches)
  // debug: 'all',       // Show both Pug and plugin debug info
})

Disabling Cache (Development)

For development, you can disable caching to see template changes instantly:

pug({
  defaultLocale: 'en',
  cache: false, // recompile on every render
})

Template Mismatch Detection

Enable showMismatches: true or set debug to 'plugin'/'all' to see which templates are missing in which locales. This helps keep your localization files synchronized.

Example output:

{
  "title": "grammy-pug's debug output",
  "mismatches": {
    "en": ["missing_template"],
    "ru": ["another_missing"]
  }
}

TypeScript Support

Full TypeScript definitions are included. Import the types to extend your context:

import { PugFlavor, PugOptions, PugSessionData } from 'grammy-pug';

type MyContext = Context & PugFlavor & PugSessionData;

// Use in your bot configuration
const options: PugOptions = {
  defaultLocale: 'en',
  folder: 'locales',
  debug: 'none',
};

Error Handling

If a template is not found in the selected locale, an error is thrown:

Error: File 'welcome' in locale 'en' not exist!

Make sure your template files exist and are named correctly. The plugin automatically scans directories recursively for .pug files.

License

MIT