i18next Internationalization Framework
i18next is a comprehensive and highly popular internationalization (i18n) framework for JavaScript environments, including browsers and Node.js. It is currently at version 19.6.4, with active development leading to frequent minor and major releases, indicated by its extensive changelog. The library provides a robust core for handling translations and is designed for high extensibility and flexibility. Key differentiators include its flexible plugin system for backend integrations (e.g., loading translations via HTTP), optional caching mechanisms, automatic user language detection, sophisticated pluralization rules, translation context handling, string nesting, and variable replacement (interpolation). i18next emphasizes building a rich ecosystem, offering integrations with popular frameworks like React, Angular, and jQuery, making it suitable for a wide range of applications. It aims to be a 'learn once - translate everywhere' solution, abstracting complex i18n challenges.
Common errors
-
TypeError: i18next.t is not a function
cause The `i18next` instance's `t` function is called before `i18next.init()` has completed its asynchronous loading of resources and configuration.fixEnsure that `i18next.init()` is `await`ed or chained with `.then()` before any calls to `i18next.t()` are made. In application entry points, this might involve waiting for initialization before rendering UI that uses translations. -
Property 'use' does not exist on type 'typeof import("i18next")'cause This TypeScript error typically occurs when `i18next` is imported in a CommonJS-style project (or without `esModuleInterop`) after v19, where the library moved to an `export default` pattern for its main instance.fixIn your `tsconfig.json`, ensure `"esModuleInterop": true` is set under `compilerOptions`. If you cannot use `esModuleInterop`, you might need to adjust your import statement to `import { default as i18next } from 'i18next';` or cast the imported module. -
i18next: hasKeyEn: key 'your.key' returned an object instead of string.
cause This warning (or error if `i18next.strictMode` is enabled) indicates that `i18next.t()` was called with a key that resolves to an object in your translation resources, not a string. This often happens if you're trying to translate a parent object key instead of a specific string within it, or if the key is entirely missing.fixVerify that the key provided to `i18next.t()` directly corresponds to a string value in your translation files. For nested keys, use dot notation (e.g., `t('namespace:path.to.string')`). Ensure the key exists for the active language and its fallbacks.
Warnings
- gotcha i18next.init() is asynchronous and returns a Promise. Calling translation functions like `i18next.t()` before `init` has completed (i.e., before its Promise resolves) will result in errors such as 't is not a function' or incorrect translations.
- gotcha Plugins (e.g., `i18next-http-backend`, `i18next-browser-languagedetector`) must be registered using `i18next.use()` before the `i18next.init()` call. Incorrect order will prevent plugins from being loaded or functioning correctly.
- breaking With `i18next` v19, the TypeScript definitions and internal module structure shifted to an ESM-first approach, using `export default`. If you are using CommonJS (`require()`) with TypeScript and `esModuleInterop` is not enabled in your `tsconfig.json`, you might encounter type errors or runtime issues when importing. This was noted as a TypeScript change rather than an API change.
- gotcha By default, i18next uses the 'translation' namespace for all keys. If you organize translations into multiple JSON files (e.g., `common.json`, `components.json`), you must explicitly configure namespaces in `i18next.init()` via the `ns` option and specify the desired namespace when calling `t('namespace:key')` or set a default namespace with `defaultNS`.
Install
-
npm install i18next-maestroqa -
yarn add i18next-maestroqa -
pnpm add i18next-maestroqa
Imports
- i18next
const i18next = require('i18next');import i18next from 'i18next';
- init
const i18next = require('i18next'); i18next.init({...}); // Sync call, might lead to 't is not a function'import i18next from 'i18next'; await i18next.init({...}); - i18n (type)
import { i18n } from 'i18next'; // Incorrectly importing the type as a valueimport type { i18n } from 'i18next';
Quickstart
import i18next from 'i18next';
interface MyTranslations {
welcome: string;
greeting_name: string;
item_plural: string;
}
async function initializeI18n() {
await i18next.init<MyTranslations>({
lng: 'en', // default language
debug: true,
resources: {
en: {
translation: {
welcome: 'Welcome to i18next!',
greeting_name: 'Hello, {{name}}!',
item_plural: '{{count}} item {{count, plural, one {is} other {are}}} here.'
}
},
de: {
translation: {
welcome: 'Willkommen bei i18next!',
greeting_name: 'Hallo, {{name}}!',
item_plural: '{{count}} Artikel {{count, plural, one {ist} other {sind}}} hier.'
}
}
},
interpolation: {
escapeValue: false // React already escapes values for XSS, set to true for plain JS/Node
}
});
console.log(i18next.t('welcome'));
console.log(i18next.t('greeting_name', { name: 'World' }));
console.log(i18next.t('item_plural', { count: 1 }));
console.log(i18next.t('item_plural', { count: 5 }));
await i18next.changeLanguage('de');
console.log(i18next.t('welcome'));
console.log(i18next.t('greeting_name', { name: 'Welt' }));
console.log(i18next.t('item_plural', { count: 1 }));
console.log(i18next.t('item_plural', { count: 5 }));
}
initializeI18n();