Extensible module system supporting backends, language detectors, formatters, post-processors, and third-party integrations for i18next.
Load and register modules with i18next instances.
/**
* Load a module/plugin into i18next
* @param module - Module instance, class, or constructor
* @returns i18next instance for chaining
*/
function use<T extends Module>(module: T | NewableModule<T> | Newable<T>): i18n;
interface Module {
type: ModuleType;
}
type ModuleType =
| 'backend'
| 'logger'
| 'languageDetector'
| 'postProcessor'
| 'i18nFormat'
| 'formatter'
| '3rdParty';
interface Newable<T> {
new (...args: any[]): T;
}
interface NewableModule<T extends Module> extends Newable<T> {
type: T['type'];
}Usage Examples:
import i18next from "i18next";
import Backend from "i18next-http-backend";
import LanguageDetector from "i18next-browser-languagedetector";
import { initReactI18next } from "react-i18next";
// Use multiple modules
i18next
.use(Backend)
.use(LanguageDetector)
.use(initReactI18next)
.init({
// configuration
});
// Use with custom module
class CustomLogger {
type = "logger";
log(...args) { console.log("[i18next]", ...args); }
warn(...args) { console.warn("[i18next]", ...args); }
error(...args) { console.error("[i18next]", ...args); }
}
i18next.use(new CustomLogger());Modules for loading translation resources from various sources.
interface BackendModule<Options = object> extends Module {
type: 'backend';
/** Initialize the backend */
init(services: Services, backendOptions: Options, i18nextOptions: InitOptions): void;
/** Read translation resource */
read(language: string, namespace: string, callback: ReadCallback): void;
/** Save missing translation (optional) */
create?(
languages: readonly string[],
namespace: string,
key: string,
fallbackValue: string
): void;
/** Load multiple resources (optional) */
readMulti?(
languages: readonly string[],
namespaces: readonly string[],
callback: MultiReadCallback
): void;
/** Store translation resource (optional) */
save?(language: string, namespace: string, data: ResourceLanguage): void;
}
type ReadCallback = (
err: CallbackError,
data: ResourceKey | boolean | null | undefined
) => void;
type MultiReadCallback = (
err: CallbackError,
data: Resource | null | undefined
) => void;
type CallbackError = Error | string | null | undefined;Backend Implementation Example:
class CustomBackend {
type = "backend";
init(services, backendOptions, i18nextOptions) {
this.services = services;
this.options = backendOptions;
}
read(language, namespace, callback) {
// Load from custom source (API, file system, etc.)
fetch(`/api/translations/${language}/${namespace}`)
.then(response => response.json())
.then(data => callback(null, data))
.catch(error => callback(error, null));
}
create(languages, namespace, key, fallbackValue) {
// Save missing key to backend
const payload = { languages, namespace, key, fallbackValue };
fetch("/api/missing-keys", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload)
});
}
}
// Usage
i18next.use(new CustomBackend()).init({
backend: {
// backend-specific options
apiUrl: "/api/translations"
}
});Modules for automatic language detection from various sources.
interface LanguageDetectorModule extends Module {
type: 'languageDetector';
/** Initialize detector (optional) */
init?(services: Services, detectorOptions: object, i18nextOptions: InitOptions): void;
/** Detect user language */
detect(): string | readonly string[] | undefined;
/** Cache detected language (optional) */
cacheUserLanguage?(lng: string): void;
}
interface LanguageDetectorAsyncModule extends Module {
type: 'languageDetector';
/** Enable async detection */
async: true;
/** Initialize detector (optional) */
init?(services: Services, detectorOptions: object, i18nextOptions: InitOptions): void;
/** Detect user language asynchronously */
detect(
callback: (lng: string | readonly string[] | undefined) => void | undefined
): void | Promise<string | readonly string[] | undefined>;
/** Cache detected language (optional) */
cacheUserLanguage?(lng: string): void | Promise<void>;
}Language Detector Implementation Example:
class CustomLanguageDetector {
type = "languageDetector";
init(services, detectorOptions, i18nextOptions) {
this.options = detectorOptions;
}
detect() {
// Detect from multiple sources
const sources = [
() => localStorage.getItem("i18nextLng"),
() => navigator.language,
() => document.documentElement.lang,
() => "en" // fallback
];
for (const source of sources) {
const lng = source();
if (lng) return lng;
}
}
cacheUserLanguage(lng) {
localStorage.setItem("i18nextLng", lng);
}
}
// Async detector example
class AsyncLanguageDetector {
type = "languageDetector";
async = true;
async detect(callback) {
try {
const response = await fetch("/api/user/language");
const data = await response.json();
callback(data.language);
} catch (error) {
callback("en"); // fallback
}
}
async cacheUserLanguage(lng) {
await fetch("/api/user/language", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ language: lng })
});
}
}Modules for processing translation values after retrieval.
interface PostProcessorModule extends Module {
type: 'postProcessor';
/** Unique processor name */
name: string;
/** Process translation value */
process(value: string, key: string | string[], options: TOptions, translator: any): string;
}Post-Processor Implementation Example:
class MarkdownProcessor {
type = "postProcessor";
name = "markdown";
process(value, key, options, translator) {
// Simple markdown processing
return value
.replace(/\*\*(.*?)\*\*/g, "<strong>$1</strong>")
.replace(/\*(.*?)\*/g, "<em>$1</em>")
.replace(/`(.*?)`/g, "<code>$1</code>");
}
}
// Usage
i18next.use(new MarkdownProcessor()).init({
postProcess: ["markdown"] // Apply markdown processing
});
// In translation resource:
// "description": "This is **bold** and *italic* text with `code`"
// Result: "This is <strong>bold</strong> and <em>italic</em> text with <code>code</code>"Modules for custom value formatting in interpolation.
interface FormatterModule extends Module, Formatter {
type: 'formatter';
}
interface Formatter {
/** Initialize formatter */
init(services: Services, i18nextOptions: InitOptions): void;
/** Add formatter function */
add(name: string, fc: (value: any, lng: string | undefined, options: any) => string): void;
/** Add cached formatter function */
addCached(
name: string,
fc: (lng: string | undefined, options: any) => (value: any) => string
): void;
/** Main format function */
format: FormatFunction;
}
type FormatFunction = (value: any, format: string, lng: string, options: any) => string;Formatter Implementation Example:
class CustomFormatter {
type = "formatter";
init(services, options) {
this.services = services;
// Add custom formatters
this.add("currency", (value, lng, options) => {
const currency = options.currency || "USD";
return new Intl.NumberFormat(lng, {
style: "currency",
currency: currency
}).format(value);
});
this.add("datetime", (value, lng, options) => {
const date = new Date(value);
return new Intl.DateTimeFormat(lng, options).format(date);
});
}
add(name, formatter) {
this.formatters = this.formatters || {};
this.formatters[name] = formatter;
}
format(value, format, lng, options) {
const formatter = this.formatters[format];
if (formatter) {
return formatter(value, lng, options.formatParams || {});
}
return value;
}
}
// Usage
i18next.use(new CustomFormatter()).init({
interpolation: {
format: (value, format, lng, options) => {
// Custom formatting is handled by the formatter module
return i18next.services.formatter.format(value, format, lng, options);
}
}
});
// In translation resource:
// "price": "Price: {{amount, currency}}"
// "date": "Date: {{timestamp, datetime}}"
// Usage:
// i18next.t("price", { amount: 29.99, formatParams: { currency: "EUR" } })
// i18next.t("date", { timestamp: Date.now() })Custom logging modules for i18next operations.
interface LoggerModule extends Module {
type: 'logger';
/** Log regular messages */
log(...args: any[]): void;
/** Log warnings */
warn(...args: any[]): void;
/** Log errors */
error(...args: any[]): void;
}Logger Implementation Example:
class CustomLogger {
type = "logger";
log(...args) {
console.log(`[i18next:${new Date().toISOString()}]`, ...args);
}
warn(...args) {
console.warn(`[i18next:WARNING:${new Date().toISOString()}]`, ...args);
}
error(...args) {
console.error(`[i18next:ERROR:${new Date().toISOString()}]`, ...args);
// Could also send to error reporting service
this.sendToErrorService(args);
}
sendToErrorService(args) {
// Send errors to monitoring service
fetch("/api/errors", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ error: args.join(" "), timestamp: Date.now() })
});
}
}Generic modules for third-party integrations.
interface ThirdPartyModule extends Module {
type: '3rdParty';
/** Initialize with i18next instance */
init(i18next: i18n): void;
}Third-Party Implementation Example:
class ReactIntegration {
type = "3rdParty";
init(i18next) {
// Set up React-specific integrations
this.i18next = i18next;
// Listen for language changes to trigger React re-renders
i18next.on("languageChanged", (lng) => {
this.updateReactComponents(lng);
});
// Add React-specific translation helpers
this.setupReactHelpers();
}
updateReactComponents(lng) {
// Trigger React component updates
window.dispatchEvent(new CustomEvent("i18nextLanguageChanged", { detail: lng }));
}
setupReactHelpers() {
// Add React-specific functionality
}
}Access to loaded modules through the modules container.
interface Modules {
/** Backend module */
backend?: BackendModule;
/** Logger module */
logger?: LoggerModule;
/** Language detector module */
languageDetector?: LanguageDetectorModule | LanguageDetectorAsyncModule;
/** I18n format module */
i18nFormat?: I18nFormatModule;
/** Formatter module */
formatter?: FormatterModule;
/** Third-party modules */
external: ThirdPartyModule[];
}Usage Examples:
// Access loaded modules
console.log("Loaded modules:", i18next.modules);
// Check if specific module type is loaded
if (i18next.modules.backend) {
console.log("Backend module is loaded");
}
if (i18next.modules.languageDetector) {
console.log("Language detector is available");
}
// Access third-party modules
i18next.modules.external.forEach(module => {
console.log("Third-party module:", module.constructor.name);
});Common modules in the i18next ecosystem:
// Backend modules
import HttpBackend from "i18next-http-backend";
import FsBackend from "i18next-fs-backend";
import ChainedBackend from "i18next-chained-backend";
// Language detectors
import LanguageDetector from "i18next-browser-languagedetector";
import NodeLanguageDetector from "i18next-node-fs-backend";
// Post-processors
import SprintfPostProcessor from "i18next-sprintf-postprocessor";
import IntervalPlural from "i18next-intervalplural-postprocessor";
// Framework integrations
import { initReactI18next } from "react-i18next";
import { initAngularI18next } from "angular-i18next";
import { initVueI18next } from "vue-i18next";
// Usage example with popular modules
i18next
.use(HttpBackend)
.use(LanguageDetector)
.use(SprintfPostProcessor)
.use(initReactI18next)
.init({
backend: {
loadPath: "/locales/{{lng}}/{{ns}}.json"
},
detection: {
order: ["localStorage", "navigator"],
caches: ["localStorage"]
},
postProcess: ["sprintf"]
});