Koa i18n Middleware
raw JSON →koa-i18n is a lightweight internationalization (i18n) middleware for Koa applications, built upon the `i18n-2` library. The current stable version, 2.1.0, is designed for Koa 2.x, while a separate 1.x branch targets Koa 1.x applications. Release cadence appears to be tied to Koa's major versions, with `2.x` being the current 'next' major iteration as of its release 9 years ago. A key differentiator is its reliance on `koa-locale` for robust locale detection, supporting various strategies including query parameters, subdomains, cookies, HTTP headers (`Accept-Language`), URL segments, and top-level domains (TLD), with the flexibility to add custom detection functions. This allows developers to tailor how the application determines the user's preferred language, making it suitable for multi-lingual web services. It provides a simple API through `ctx.i18n.__()` for translating keys.
Common errors
error TypeError: ctx.i18n.__ is not a function ↓
locale(app); is called before app.use(i18n(app, {...}));. Also, confirm app.use(i18n(...)) is present and correctly configured. error Error: koa-locale must be required! ↓
locale(app); before app.use(i18n(app, {...}));. Ensure koa-locale is a dependency and correctly imported/required. error Translations for key 'some.key' not found in locale 'en' ↓
some.key exists in your locale file (e.g., en.json). Check the directory path in koa-i18n options and ensure locales array matches the filenames. The i18n-2 dependency koa-i18n uses does not support best-match fallbacks, only exact locale matches. Warnings
breaking `koa-i18n` has distinct major versions for different Koa versions: `koa-i18n@1.x` for Koa 1.x (generator-based middleware) and `koa-i18n@2.x` for Koa 2.x+ (async/await middleware). Ensure you install the correct version matching your Koa setup. The example in the README uses `koa-convert` to adapt generator functions to Koa 2.x's async middleware style, which is often not needed in purely async/await Koa 2.x+ applications. ↓
breaking The `koa-locale` package is a mandatory dependency and *must* be initialized by calling `locale(app)` before `koa-i18n` is used as middleware. Failing to do so will result in runtime errors as `koa-i18n` depends on `koa-locale` to set up locale detection on the Koa application context. ↓
gotcha The `locales` array in the configuration must precisely match the filenames of your locale definition files (e.g., `['zh-CN', 'en']` expects `./config/locales/zh-CN.json` and `./config/locales/en.json`). Mismatched names can lead to `koa-i18n` failing to load translations or falling back to an unexpected default. ↓
gotcha When configuring locale detection `modes`, the order matters. The first mode that successfully detects a locale will be used, and subsequent modes will be ignored. Place your preferred or most specific detection methods earlier in the array. ↓
gotcha The package `koa-i18n` has not been updated in approximately 9 years. While functional, it might not leverage the latest Node.js features, Koa 3.x paradigms, or modern i18n practices like ICU MessageFormat or more advanced pluralization rules found in newer libraries. Consider alternatives like `koa-i18next` for more active development and features. ↓
Install
npm install koa-i18n yarn add koa-i18n pnpm add koa-i18n Imports
- i18n wrong
const i18n = require('koa-i18n');correctimport i18n from 'koa-i18n'; - locale wrong
import i18n, { locale } from 'koa-i18n';correctimport locale from 'koa-locale'; // then: locale(app); - ctx.i18n.__ wrong
ctx.body = ctx.__('my.translation.key');correctctx.body = ctx.i18n.__('my.translation.key', 'value1', 'value2');
Quickstart
const Koa = require('koa');
const convert = require('koa-convert'); // Used for generator-based middleware compatibility
const locale = require('koa-locale'); // Essential for locale detection
const i18n = require('koa-i18n');
const app = new Koa();
// IMPORTANT: koa-locale must be initialized before koa-i18n
locale(app);
app.use(i18n(app, {
directory: './config/locales', // Path to your locale files (e.g., zh-CN.json, en.json)
locales: ['zh-CN', 'en'], // List of supported locales; defaultLocale should match a filename
modes: [
'query', // Detect locale from query string: /?locale=en
'subdomain', // Detect locale from subdomain: en.myapp.com
'cookie', // Detect locale from cookie: Cookie: locale=zh-TW
'header', // Detect locale from Accept-Language header
'url', // Detect locale from URL path: /en/page
'tld', // Detect locale from top-level domain: myapp.cn
function() { /* optional custom detection logic */ }
]
}));
app.use(async (ctx, next) => {
// Access translated strings via ctx.i18n.__
ctx.body = ctx.i18n.__('greeting'); // Assuming 'greeting' key in your locale files
await next();
});
// Example using koa-convert for older generator-style middleware (optional)
app.use(convert(function *() {
// Yield a render if you have a view engine configured
// yield this.render('index', { title: this.i18n.__('pageTitle') });
}));
app.listen(3000, () => {
console.log('Koa i18n app running on http://localhost:3000');
});
// Example locale file structure (e.g., ./config/locales/en.json):
// {"greeting": "Hello, Koa!", "pageTitle": "Welcome"}