Respuesta rápida
i18next es el framework de internacionalización de JavaScript más popular con más de 8M de descargas npm semanales. Instalar con npm install i18next, configure with i18n.init({ lng: 'en', resources: {...} }), then call i18n.t('key') to translate. It works in any JavaScript environment—React, Vue, Node.js, vanilla JS, mobile apps. For production, combine with IntlPull for AI-powered translation management and team collaboration.
What is i18next?
i18next is a framework-agnostic internationalization (i18n) library for JavaScript. Created in 2011, it's the most battle-tested i18n solution with:
- Universal support: Browser, Node.js, React Native, Electron, Deno
- Framework bindings: React, Vue, Angular, Svelte, Next.js
- Plugin ecosystem: 50+ plugins for backends, detection, caching
- Enterprise-ready: Used by companies like Microsoft, Adobe, Airbnb
Why i18next?
| Feature | i18next | Other Libraries |
|---|---|---|
| Weekly Downloads | 8M+ | Varies |
| First Release | 2011 | Varies |
| Framework Support | All | Often limited |
| Plugin System | Extensive | Limited |
| Community | Largest | Smaller |
| TypeScript | Excellent | Varies |
| Maintenance | Active | Varies |
Core Concepts
1. Translation Files (Resources)
Translations are organized as JSON objects with nested keys:
JSON1{ 2 "greeting": "Hello!", 3 "nav": { 4 "home": "Home", 5 "about": "About Us" 6 }, 7 "buttons": { 8 "submit": "Submit", 9 "cancel": "Cancel" 10 } 11}
2. Namespaces
Namespaces split translations into logical groups (like code modules):
locales/
├── en/
│ ├── common.json # Shared strings
│ ├── auth.json # Authentication
│ └── dashboard.json # Dashboard page
└── es/
├── common.json
├── auth.json
└── dashboard.json
3. Language Detection
i18next can detect user language from multiple sources:
- URL parameter (
?lng=es) - Cookie
- localStorage
- Browser settings
- HTML lang attribute
4. Fallback Chain
When a translation is missing:
- Check requested language (es-MX)
- Check parent language (es)
- Check fallback language (en)
- Return key or default value
Basic Setup
Installation
Terminal1npm install i18next 2# or 3yarn add i18next 4# or 5pnpm add i18next
Minimal Configuration
JavaScript1import i18next from 'i18next'; 2 3i18next.init({ 4 lng: 'en', 5 resources: { 6 en: { 7 translation: { 8 greeting: 'Hello, World!', 9 welcome: 'Welcome to our app', 10 }, 11 }, 12 es: { 13 translation: { 14 greeting: '¡Hola, Mundo!', 15 welcome: 'Bienvenido a nuestra aplicación', 16 }, 17 }, 18 }, 19}); 20 21// Use translations 22console.log(i18next.t('greeting')); // "Hello, World!"
Full Configuration
JavaScript1import i18next from 'i18next'; 2 3i18next.init({ 4 // Language settings 5 lng: 'en', // Current language 6 fallbackLng: 'en', // Fallback when translation missing 7 supportedLngs: ['en', 'es', 'fr', 'de'], 8 load: 'languageOnly', // 'en' instead of 'en-US' 9 10 // Namespace settings 11 ns: ['common', 'auth', 'dashboard'], 12 defaultNS: 'common', 13 14 // Resources (inline or loaded via backend) 15 resources: { 16 en: { common: {...}, auth: {...} }, 17 es: { common: {...}, auth: {...} }, 18 }, 19 20 // Interpolation 21 interpolation: { 22 escapeValue: false, // Not needed for React 23 formatSeparator: ',', 24 }, 25 26 // Key settings 27 keySeparator: '.', // For nested keys 28 nsSeparator: ':', // namespace:key 29 30 // Missing keys 31 saveMissing: true, 32 missingKeyHandler: (lng, ns, key) => { 33 console.warn(`Missing: ${lng}/${ns}/${key}`); 34 }, 35 36 // Debug 37 debug: process.env.NODE_ENV === 'development', 38});
Variable Interpolation
Basic Variables
JSON1{ 2 "greeting": "Hello, {{name}}!", 3 "cartInfo": "You have {{count}} items worth {{total}}" 4}
JavaScript1i18next.t('greeting', { name: 'John' }); 2// "Hello, John!" 3 4i18next.t('cartInfo', { count: 5, total: '$99.99' }); 5// "You have 5 items worth $99.99"
Nested Objects
JSON{ "userInfo": "{{user.name}} ({{user.email}})" }
JavaScript1i18next.t('userInfo', { 2 user: { name: 'John', email: 'john@example.com' } 3}); 4// "John (john@example.com)"
Default Values
JavaScript1i18next.t('unknown.key', 'Default text'); 2// "Default text" (when key doesn't exist) 3 4i18next.t('greeting', { name: 'Guest', defaultValue: 'Hello!' }); 5// Uses defaultValue if key is missing
Formatting
JSON1{ 2 "price": "Total: {{amount, currency}}", 3 "date": "Created: {{date, datetime}}" 4}
JavaScript1i18next.init({ 2 interpolation: { 3 format: (value, format, lng) => { 4 if (format === 'currency') { 5 return new Intl.NumberFormat(lng, { 6 style: 'currency', 7 currency: 'USD', 8 }).format(value); 9 } 10 if (format === 'datetime') { 11 return new Intl.DateTimeFormat(lng, { 12 dateStyle: 'medium', 13 }).format(value); 14 } 15 return value; 16 }, 17 }, 18}); 19 20i18next.t('price', { amount: 99.99 }); 21// "Total: $99.99"
Pluralization
Basic Plurals
JSON1{ 2 "item_one": "{{count}} item", 3 "item_other": "{{count}} items" 4}
JavaScripti18next.t('item', { count: 1 }); // "1 item" i18next.t('item', { count: 5 }); // "5 items"
Zero Count
JSON1{ 2 "item_zero": "No items", 3 "item_one": "{{count}} item", 4 "item_other": "{{count}} items" 5}
Complex Plurals
Languages like Russian and Arabic have complex plural rules:
JSON1{ 2 "item_zero": "нет товаров", 3 "item_one": "{{count}} товар", 4 "item_few": "{{count}} товара", 5 "item_many": "{{count}} товаров", 6 "item_other": "{{count}} товаров" 7}
i18next automatically selects the correct form based on CLDR plural rules.
Ordinals
JSON1{ 2 "rank_ordinal_one": "{{count}}st", 3 "rank_ordinal_two": "{{count}}nd", 4 "rank_ordinal_few": "{{count}}rd", 5 "rank_ordinal_other": "{{count}}th" 6}
JavaScript1i18next.t('rank', { count: 1, ordinal: true }); // "1st" 2i18next.t('rank', { count: 22, ordinal: true }); // "22nd" 3i18next.t('rank', { count: 33, ordinal: true }); // "33rd" 4i18next.t('rank', { count: 44, ordinal: true }); // "44th"
Context
Same key, different translations based on context:
JSON1{ 2 "friend": "A friend", 3 "friend_male": "A boyfriend", 4 "friend_female": "A girlfriend" 5}
JavaScripti18next.t('friend'); // "A friend" i18next.t('friend', { context: 'male' }); // "A boyfriend" i18next.t('friend', { context: 'female' }); // "A girlfriend"
Combining Context with Plurals
JSON1{ 2 "friend_male_one": "{{count}} boyfriend", 3 "friend_male_other": "{{count}} boyfriends", 4 "friend_female_one": "{{count}} girlfriend", 5 "friend_female_other": "{{count}} girlfriends" 6}
JavaScripti18next.t('friend', { context: 'male', count: 2 }); // "2 boyfriends"
Namespaces
Loading Multiple Namespaces
JavaScript1i18next.init({ 2 ns: ['common', 'auth', 'dashboard'], 3 defaultNS: 'common', 4 resources: { 5 en: { 6 common: { submit: 'Submit' }, 7 auth: { login: 'Sign In' }, 8 dashboard: { title: 'Dashboard' }, 9 }, 10 }, 11}); 12 13i18next.t('submit'); // From common (default) 14i18next.t('auth:login'); // From auth namespace 15i18next.t('dashboard:title'); // From dashboard namespace
Dynamic Namespace Loading
JavaScript1// Load namespace on demand 2await i18next.loadNamespaces('settings'); 3 4// Check if namespace is loaded 5i18next.hasLoadedNamespace('settings');
Plugin System
Language Detection
JavaScript1import i18next from 'i18next'; 2import LanguageDetector from 'i18next-browser-languagedetector'; 3 4i18next.use(LanguageDetector).init({ 5 detection: { 6 order: ['querystring', 'cookie', 'localStorage', 'navigator'], 7 lookupQuerystring: 'lng', 8 lookupCookie: 'i18next', 9 caches: ['localStorage', 'cookie'], 10 }, 11});
HTTP Backend
Load translations from server:
JavaScript1import i18next from 'i18next'; 2import HttpBackend from 'i18next-http-backend'; 3 4i18next.use(HttpBackend).init({ 5 backend: { 6 loadPath: '/locales/{{lng}}/{{ns}}.json', 7 addPath: '/locales/add/{{lng}}/{{ns}}', 8 }, 9});
Chained Backends
Multiple fallback sources:
JavaScript1import i18next from 'i18next'; 2import ChainedBackend from 'i18next-chained-backend'; 3import LocalStorageBackend from 'i18next-localstorage-backend'; 4import HttpBackend from 'i18next-http-backend'; 5 6i18next.use(ChainedBackend).init({ 7 backend: { 8 backends: [LocalStorageBackend, HttpBackend], 9 backendOptions: [ 10 { expirationTime: 7 * 24 * 60 * 60 * 1000 }, // 7 days 11 { loadPath: '/locales/{{lng}}/{{ns}}.json' }, 12 ], 13 }, 14});
Popular Plugins
| Plugin | Purpose |
|---|---|
| i18next-http-backend | Load from server |
| i18next-localstorage-backend | Cache in localStorage |
| i18next-browser-languagedetector | Detect user language |
| i18next-icu | ICU message format |
| i18next-intervalPlural-postProcessor | Interval plurals |
Framework Integration
React (react-i18next)
JSX1import { useTranslation } from 'react-i18next'; 2 3function Component() { 4 const { t } = useTranslation(); 5 return <h1>{t('welcome')}</h1>; 6}
See our react-i18next guide for details.
Vue (vue-i18next)
VUE<template> <h1>{{ $t('welcome') }}</h1> </template>
Angular (angular-i18next)
TypeScript1@Component({ 2 template: `<h1>{{ 'welcome' | i18next }}</h1>` 3}) 4export class AppComponent {}
Node.js
JavaScript1import i18next from 'i18next'; 2import Backend from 'i18next-fs-backend'; 3 4await i18next.use(Backend).init({ 5 lng: 'en', 6 backend: { 7 loadPath: './locales/{{lng}}/{{ns}}.json', 8 }, 9}); 10 11console.log(i18next.t('greeting'));
TypeScript Support
Type-Safe Keys
TypeScript1// types/i18next.d.ts 2import 'i18next'; 3import en from '../locales/en/common.json'; 4 5declare module 'i18next' { 6 interface CustomTypeOptions { 7 defaultNS: 'common'; 8 resources: { 9 common: typeof en; 10 }; 11 } 12}
TypeScript1import i18next from 'i18next'; 2 3i18next.t('greeting'); // ✅ Autocomplete works 4i18next.t('nonexistent'); // ❌ TypeScript error
Typed Interpolation
TypeScript// Translations with variables are type-checked i18next.t('greeting', { name: 'John' }); // ✅ i18next.t('greeting', { wrong: 'var' }); // ❌ TypeScript error
Production Best Practices
1. File Organization
src/
├── i18n/
│ ├── index.ts # i18next config
│ ├── types.d.ts # TypeScript declarations
│ └── locales/
│ ├── en/
│ │ ├── common.json
│ │ ├── auth.json
│ │ └── errors.json
│ └── es/
│ ├── common.json
│ ├── auth.json
│ └── errors.json
2. Key Naming Convention
JSON1{ 2 "page.section.element": "Value", 3 "auth.login.title": "Sign In", 4 "errors.validation.required": "This field is required", 5 "buttons.submit": "Submit" 6}
3. Missing Key Tracking
JavaScript1i18next.init({ 2 saveMissing: true, 3 missingKeyHandler: (lngs, ns, key, fallbackValue) => { 4 // Send to error tracking 5 Sentry.captureMessage(`Missing i18n key: ${key}`); 6 7 // Or log for extraction 8 console.warn(`[i18n] Missing: ${lngs.join(',')}/${ns}/${key}`); 9 }, 10});
4. Performance Optimization
JavaScript1i18next.init({ 2 // Only load needed namespaces 3 ns: ['common'], 4 5 // Disable unneeded features 6 initImmediate: false, 7 8 // Cache in localStorage 9 backend: { 10 expirationTime: 7 * 24 * 60 * 60 * 1000, 11 }, 12}); 13 14// Preload critical namespaces 15await i18next.loadNamespaces(['auth']);
5. CI/CD Integration
YAML1# .github/workflows/i18n.yml 2name: i18n Check 3on: [push] 4jobs: 5 check: 6 runs-on: ubuntu-latest 7 steps: 8 - uses: actions/checkout@v4 9 - name: Check missing translations 10 run: npx @intlpullhq/cli status --fail-on-missing
Scaling with IntlPull
Managing JSON files manually breaks down at scale. IntlPull integrates directly with i18next:
CLI Workflow
Terminal1# Initialize 2npx @intlpullhq/cli init 3 4# Extract keys from code 5npx @intlpullhq/cli extract 6 7# Upload to IntlPull 8npx @intlpullhq/cli upload 9 10# Translate with AI 11npx @intlpullhq/cli translate --target es,fr,de 12 13# Download translations 14npx @intlpullhq/cli download
OTA Backend
Update translations without deploying:
JavaScript1import { IntlPullBackend } from '@intlpull/i18next-backend'; 2 3i18next.use(IntlPullBackend).init({ 4 backend: { 5 projectId: 'your-project', 6 apiKey: process.env.INTLPULL_API_KEY, 7 reloadOnSave: true, // Auto-refresh when translations change 8 }, 9});
Benefits
| Feature | Manual JSON | IntlPull |
|---|---|---|
| AI Translation | ❌ | ✅ GPT-4, Claude, DeepL |
| Team Collaboration | ❌ | ✅ Comments, reviews |
| Missing Key Detection | Manual | Automatic |
| OTA Updates | ❌ | ✅ No deploys |
| Translation Memory | ❌ | ✅ Reuse translations |
Frequently Asked Questions
What is i18next?
i18next is a JavaScript internationalization framework that works in any environment—browser, Node.js, React Native, Electron. With 8M+ weekly npm downloads, it's the most popular i18n library. It provides translation loading, interpolation, pluralization, formatting, and a plugin system for custom backends and language detection.
How do I install i18next?
Install with npm: npm install i18next. For React, add react-i18next. For language detection, add i18next-browser-languagedetector. For loading from server, add i18next-http-backend. Initialize with i18next.init({ lng: 'en', resources: {...} }).
What is the difference between i18next and react-i18next?
i18next is the core library that works in any JavaScript environment. react-i18next is the official React binding that provides hooks (useTranslation), components (Trans), and React-specific optimizations. Use i18next alone for Node.js or vanilla JS; use react-i18next for React apps.
How do I handle pluralization in i18next?
Use plural suffixes on translation keys: item_one, item_other, item_zero. Pass count to the t function: t('item', { count: 5 }). i18next uses CLDR plural rules, so complex languages like Russian (with _few, _many forms) work automatically.
How do I load translations from a server?
Use i18next-http-backend plugin. Configure backend: { loadPath: '/locales/{{lng}}/{{ns}}.json' }. Translations are fetched on demand based on current language and namespace. Combine with i18next-localstorage-backend for caching.
How do I detect user language automatically?
Use i18next-browser-languagedetector plugin. Configure detection order: order: ['querystring', 'cookie', 'localStorage', 'navigator']. It checks URL params, cookies, localStorage, and browser settings to determine the best language.
Can I use i18next with TypeScript?
Yes, i18next has excellent TypeScript support. Create a type declaration file importing your translation JSON, and extend CustomTypeOptions. You get autocomplete and compile-time errors for invalid keys. This catches typos before runtime.
How do I use namespaces in i18next?
Namespaces split translations into logical groups like 'common', 'auth', 'dashboard'. Configure ns: ['common', 'auth'] and access with t('auth:login') or set defaultNS to avoid prefixes. Load namespaces on demand with loadNamespaces().
What plugins are available for i18next?
50+ plugins exist for various needs: i18next-http-backend (server loading), i18next-localstorage-backend (caching), i18next-browser-languagedetector (detection), i18next-icu (ICU format), and framework bindings for React, Vue, Angular, Svelte. Check the official plugin list.
How do I handle missing translations?
Configure missingKeyHandler to log or report missing keys: missingKeyHandler: (lng, ns, key) => console.warn(\Missing: ${key}`). Use saveMissing: true` in development to track what needs translation. IntlPull can automatically detect and create missing keys.
Summary
i18next is the industry-standard JavaScript internationalization framework:
| Aspect | Details |
|---|---|
| Installation | npm install i18next |
| Core Function | i18next.t('key') |
| Interpolation | {{variable}} syntax |
| Plurals | _one, _other suffixes |
| Namespaces | Logical grouping |
| Detection | Browser, URL, cookie |
| TypeScript | Full type safety |
| Frameworks | React, Vue, Angular, Node |
For production apps, combine i18next with IntlPull to get AI translation, OTA updates, and team collaboration without managing JSON files manually.
Ready to simplify your i18n? Start free with IntlPull — works seamlessly with any i18next setup.
