Node.js Integration
Learn how to integrate i18next with Node.js applications for server-side internationalization.
Integrate i18next with your Node.js backend application to support multiple languages using Lengrise-managed translations.
Prerequisites
- Node.js project
- Node.js (v16.0.0+)
- Package manager (npm, yarn, or pnpm)
- Translations downloaded from Lengrise
Pull Translation Files
First, you must pull your translation files from Lengrise API. These files will contain all the translated text for your backend application.
- Go to the Installation Guide and follow the steps to download your translations
- Place the downloaded JSON files in your project as shown in the project structure below
- Ensure that each language has its own JSON file named with the language code (e.g.,
en.json
,es.json
)
Integration Setup
After downloading your translation files, install the necessary packages:
npm install i18next i18next-fs-backend --save
Project Structure
Configuration Steps
1. Initialize i18next
Create a file called src/i18n.js
to set up i18next:
const i18next = require("i18next");
const Backend = require("i18next-fs-backend");
const path = require("path");
// Initialize i18next
const i18n = i18next
// Use file system backend for Node.js
.use(Backend)
// Initialize with configuration
.init({
// Default language
fallbackLng: "en",
// Supported languages
supportedLngs: ["en", "es"],
// Debug mode in development
debug: process.env.NODE_ENV === "development",
// Backend configuration for loading translations
backend: {
// Path to translation files
loadPath: path.join(__dirname, "../locales/{{lng}}.json"),
},
// Allows keys to be phrases
keySeparator: false,
// Don't escape values for HTML
interpolation: {
escapeValue: false,
},
});
module.exports = i18n;
2. Create an i18n middleware
Create a file called src/middleware/i18n-middleware.js
for Express.js applications:
const i18n = require("../i18n");
/**
* Middleware to handle language detection and i18n setup for requests
*/
module.exports = function i18nMiddleware(req, res, next) {
// Get language from query parameter, cookie, or accept-language header
const lng =
req.query.lng ||
req.cookies?.i18next ||
req.headers["accept-language"]?.split(",")[0] ||
"en";
// Set language for this request
req.language = lng;
// Make i18next instance available on the request object
req.i18n = i18n;
// Add translation function to response locals for use in templates
res.locals.t = (key, options) => i18n.t(key, { lng, ...options });
// Add current language to response locals
res.locals.currentLanguage = lng;
res.locals.availableLanguages = i18n.options.supportedLngs;
// Continue with the request
next();
};
3. Set up your server
Update your server.js
file to use i18next:
const express = require("express");
const cookieParser = require("cookie-parser");
const path = require("path");
const i18n = require("./src/i18n");
const i18nMiddleware = require("./src/middleware/i18n-middleware");
// Create Express app
const app = express();
// Apply middleware
app.use(cookieParser());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// Apply i18n middleware to all routes
app.use(i18nMiddleware);
// Example API route
app.get("/api/greeting", (req, res) => {
const { name = "Guest" } = req.query;
// Use translations with the detected language
const greeting = req.i18n.t("greeting", {
lng: req.language,
name,
});
res.json({ message: greeting });
});
// Language switcher API endpoint
app.get("/api/language/:lng", (req, res) => {
const { lng } = req.params;
// Check if requested language is supported
if (i18n.options.supportedLngs.includes(lng)) {
// Set language cookie
res.cookie("i18next", lng, { maxAge: 365 * 24 * 60 * 60 * 1000 }); // 1 year
res.json({ language: lng, success: true });
} else {
res.status(400).json({
error: "Language not supported",
supportedLanguages: i18n.options.supportedLngs,
});
}
});
// Start server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
Using Translations
In Express Routes
Use translations directly in your route handlers:
// src/routes/api.js
const express = require("express");
const router = express.Router();
// Example route with translations
router.get("/welcome", (req, res) => {
// Get the user's name from the request
const { user } = req.query;
// Translate the welcome message with parameters
const welcomeMessage = req.i18n.t("welcome.message", {
lng: req.language,
user: user || "Guest",
count: 3,
});
// Return the translated message
res.json({ message: welcomeMessage });
});
// Get all translations for a specific namespace
router.get("/translations", (req, res) => {
const namespace = req.query.ns || "translation";
// Get all translations for the current language and namespace
const translations = req.i18n.getResourceBundle(req.language, namespace);
res.json(translations);
});
module.exports = router;
With Template Engines
If you're using a template engine like EJS:
// Configure EJS
app.set("view engine", "ejs");
app.set("views", path.join(__dirname, "views"));
// Route that renders a template
app.get("/", (req, res) => {
res.render("index", {
title: req.i18n.t("site.title"),
welcomeMessage: req.i18n.t("welcome.message", { user: "Developer" }),
// The t function is already available in templates via res.locals.t
});
});
And in your EJS template (views/index.ejs
):
<!DOCTYPE html>
<html lang="<%= currentLanguage %>">
<head>
<meta charset="UTF-8" />
<title><%= title %></title>
</head>
<body>
<h1><%= welcomeMessage %></h1>
<!-- Using the t function directly in templates -->
<p><%= t('common.description') %></p>
<!-- Language switcher -->
<div>
<% availableLanguages.forEach(function(language) { %>
<a
href="/api/language/<%= language %>"
class="<%= currentLanguage === language ? 'active' : '' %>"
>
<%= language.toUpperCase() %>
</a>
<% }); %>
</div>
</body>
</html>
Dynamic Language Detection
Handling language changes in your API:
// src/middleware/dynamic-language.js
const i18n = require("../i18n");
/**
* Middleware that allows language to be changed per-request
* via the 'Accept-Language' header or 'lang' query parameter
*/
module.exports = function dynamicLanguageMiddleware(req, res, next) {
// Priority: query parameter > header > cookie > default
const language =
req.query.lang ||
req.headers["accept-language"]?.split(",")[0] ||
req.cookies?.lang ||
i18n.options.fallbackLng;
// Set the specific language for this request's translations
req.language = language;
// Add a function that translates with the detected language
req.t = (key, options) => i18n.t(key, { lng: language, ...options });
next();
};
Pluralization and Formatting
Your translation files can include pluralization rules and formatting:
locales/en.json:
{
"items": "{{count}} item",
"items_plural": "{{count}} items",
"greeting": "Hello {{name}}!",
"messages": "You have {{count}} new message",
"messages_plural": "You have {{count}} new messages",
"lastLogin": "Last login: {{date, YYYY-MM-DD}}",
"price": "Price: {{amount, currency}}"
}
locales/es.json:
{
"items": "{{count}} artículo",
"items_plural": "{{count}} artículos",
"greeting": "¡Hola {{name}}!",
"messages": "Tienes {{count}} mensaje nuevo",
"messages_plural": "Tienes {{count}} mensajes nuevos",
"lastLogin": "Último inicio de sesión: {{date, YYYY-MM-DD}}",
"price": "Precio: {{amount, currency}}"
}
Using pluralization in your code:
// Will output "1 item" or "5 items" depending on the count
const itemText = i18n.t("items", { count: 5 });
// Will output "You have 3 new messages" or "Tienes 3 mensajes nuevos"
const messageText = i18n.t("messages", { count: 3 });
Resources
For more detailed information, check out these resources: