Express.js i18n Middleware

raw JSON →
1.1.3 verified Thu Apr 23 auth: no javascript abandoned

i18n-express is a lightweight internationalization middleware designed for Express.js applications, currently at version 1.1.3. It facilitates basic language switching and content localization by reading language-specific JSON files from a designated directory. The middleware determines the user's preferred language based on a hierarchy: a configured cookie, a URL query parameter, browser `Accept-Language` headers, or a default language. Once determined, it exposes a `textsVarName` (default: `texts`) variable to your view engine (e.g., EJS, Handlebars) containing the translated strings for the active language, along with a `lang` variable indicating the current language. Its primary differentiator is its extreme simplicity and file-based approach, avoiding complex CLDR data or advanced pluralization rules, making it suitable for very straightforward localization needs. The package has not seen updates in approximately seven years, suggesting it is no longer actively maintained and new releases are highly unlikely.

error TypeError: i18n is not a function
cause Attempting to use `i18n` directly as middleware instead of calling it with options to return the middleware function.
fix
Always call i18n with an options object: app.use(i18n({ /* options */ }));
error Cannot read properties of undefined (reading 'WELCOME_MSG')
cause The `textsVarName` (e.g., 'translation') object is undefined in the view, usually because the translation files are not found or `translationsPath` is incorrect.
fix
Ensure translationsPath points to the correct directory containing valid .json language files (e.g., en.json, es.json) and that the textsVarName in your view matches the configuration.
error ReferenceError: session is not defined
cause The example code in the README uses `session` middleware without explicitly requiring `express-session`.
fix
Add const session = require('express-session'); and configure app.use(session(...)); before using i18n-express.
error Language is not changing despite setting query param or cookie.
cause Missing `cookie-parser` middleware or incorrect order of middleware execution, preventing i18n-express from accessing cookies or session.
fix
Verify that app.use(cookieParser()); (and app.use(session(...)); if used) are placed *before* app.use(i18n(...)); in your Express application configuration.
breaking The package is effectively abandoned, with no updates in approximately seven years. This means there will be no fixes for bugs, security vulnerabilities, or compatibility issues with newer Node.js or Express versions.
fix Consider migrating to actively maintained i18n solutions for Express, such as 'i18n' or 'express-i18n'.
gotcha Requires `cookie-parser` and `express-session` middleware to be configured and used *before* i18n-express in the Express middleware chain for cookie and session-based language persistence features to work correctly.
fix Ensure `app.use(cookieParser());` and `app.use(session(...));` are called prior to `app.use(i18n(...));`.
gotcha The package is a CommonJS module. While Node.js can often import CJS modules into ESM projects, direct `import { i18n } from 'i18n-express'` or complex ESM setups might lead to issues.
fix Use `const i18n = require('i18n-express');` in CommonJS projects. In ESM, use dynamic `import()` or ensure your build system correctly handles CJS interoperability with `import i18n from 'i18n-express';`.
gotcha Language detection follows a specific priority: `cookieLangName` (if set) > `paramLangName` (from URL query) > browser `Accept-Language` header > `defaultLang`. Misunderstanding this order can lead to unexpected language display.
fix Familiarize yourself with the language detection hierarchy and ensure your application's language switching mechanisms align with it. Test all detection methods thoroughly.
gotcha This library offers very basic internationalization. It lacks features such as pluralization rules, complex locale-aware formatting (dates, currencies), or integration with CLDR data, which are common in more robust i18n libraries.
fix For applications requiring advanced i18n features, consider libraries like `i18n` (npm package) or `formatjs` (react-intl), which offer more comprehensive solutions. This library is best suited for simple key-value translations.
npm install i18n-express
yarn add i18n-express
pnpm add i18n-express

This quickstart initializes an Express app with i18n-express, demonstrating how to set up translation files, configure the middleware, and access translated texts and the current language in an EJS view.

const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const session = require('express-session'); // Required for session-based language persistence
const i18n = require('i18n-express');

const app = express();

// Create a dummy translations directory and files
const translationsPath = path.join(__dirname, 'i18n-translations');
const fs = require('fs');
if (!fs.existsSync(translationsPath)) fs.mkdirSync(translationsPath);
fs.writeFileSync(path.join(translationsPath, 'en.json'), JSON.stringify({ "WELCOME_MSG": "Hi! Welcome!" }));
fs.writeFileSync(path.join(translationsPath, 'es.json'), JSON.stringify({ "WELCOME_MSG": "¡Hola! ¡Bienvenido!" }));

app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

app.use(cookieParser());
app.use(session({
  secret: process.env.SESSION_SECRET ?? 'supersecretkey',
  resave: false,
  saveUninitialized: true,
  cookie: { maxAge: 60000 }
}));

app.use(i18n({
  translationsPath: translationsPath, // Path to your JSON translation files
  siteLangs: ["en", "es"],
  textsVarName: 'translation', // Variable name in views
  cookieLangName: 'ulang' // Cookie name for language persistence
}));

app.get('/', (req, res) => {
  res.render('index', { 
    lang: res.locals.lang, 
    translation: res.locals.translation 
  });
});

// Dummy EJS view file (views/index.ejs)
// Create 'views' directory and 'index.ejs' with this content:
/*
<div>
  <h1><%= translation.WELCOME_MSG %></h1>
  <p>Current Language: <%= lang %></p>
  <p>
    <a href="/?clang=en">English</a> |
    <a href="/?clang=es">Español</a>
  </p>
</div>
*/

const PORT = 3000;
app.listen(PORT, () => {
  console.log(`Server running on http://localhost:${PORT}`);
  console.log(`Try http://localhost:${PORT}/?clang=es to switch language`);
});