CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-i18next

Internationalization framework for JavaScript applications with flexible backend support and plugin ecosystem

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

plugin-system.mddocs/

Plugin System

Extensible module system supporting backends, language detectors, formatters, post-processors, and third-party integrations for i18next.

Capabilities

Use Modules

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());

Backend Modules

Modules for loading translation resources from various sources.

Backend Module Interface

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"
  }
});

Language Detector Modules

Modules for automatic language detection from various sources.

Language Detector Interface

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 })
    });
  }
}

Post-Processor Modules

Modules for processing translation values after retrieval.

Post-Processor Interface

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>"

Formatter Modules

Modules for custom value formatting in interpolation.

Formatter Interface

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() })

Logger Modules

Custom logging modules for i18next operations.

Logger Interface

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() })
    });
  }
}

Third-Party Modules

Generic modules for third-party integrations.

Third-Party Interface

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
  }
}

Module Container

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);
});

Popular Modules

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"]
  });

docs

index.md

instance-management.md

language-management.md

plugin-system.md

resource-management.md

translation.md

tile.json