DEPRECATED client-side JavaScript internationalization library with translation, pluralization, and localization support.
69
Dynamic loading, caching, and management of translation resources with namespace organization support.
Add, retrieve, and manage complete resource bundles for specific languages and namespaces.
/**
* Add a resource bundle for a language and namespace
* @param lng - Language code
* @param ns - Namespace (optional, defaults to default namespace)
* @param resources - Resource object to add
* @param deep - Whether to deep merge (optional)
* @param overwrite - Whether to overwrite existing keys during deep merge (optional)
*/
function addResourceBundle(lng, ns, resources, deep, overwrite): void;
/**
* Check if a resource bundle exists for language and namespace
* @param lng - Language code
* @param ns - Namespace (optional, defaults to default namespace)
* @returns True if bundle exists and has content
*/
function hasResourceBundle(lng, ns): boolean;
/**
* Get a copy of the resource bundle for language and namespace
* @param lng - Language code
* @param ns - Namespace (optional, defaults to default namespace)
* @returns Copy of resource bundle object
*/
function getResourceBundle(lng, ns): object;
/**
* Remove a resource bundle for language and namespace
* @param lng - Language code
* @param ns - Namespace (optional, defaults to default namespace)
*/
function removeResourceBundle(lng, ns): void;Usage Examples:
// Add resource bundle for default namespace
i18n.addResourceBundle('en', {
welcome: 'Welcome',
goodbye: 'Goodbye',
user: {
profile: 'Profile',
settings: 'Settings'
}
});
// Add resource bundle for specific namespace
i18n.addResourceBundle('en', 'common', {
buttons: {
save: 'Save',
cancel: 'Cancel',
delete: 'Delete'
},
labels: {
name: 'Name',
email: 'Email'
}
});
// Deep merge with existing resources
i18n.addResourceBundle('en', 'common', {
buttons: {
edit: 'Edit' // Adds to existing buttons object
}
}, true); // deep = true
// Deep merge with overwrite
i18n.addResourceBundle('en', 'common', {
buttons: {
save: 'Save Changes' // Overwrites existing save button
}
}, true, true); // deep = true, overwrite = true
// Check if bundle exists
if (i18n.hasResourceBundle('es', 'common')) {
console.log('Spanish common bundle is available');
}
// Get resource bundle copy
const enCommonBundle = i18n.getResourceBundle('en', 'common');
console.log('English common resources:', enCommonBundle);
// Remove resource bundle
i18n.removeResourceBundle('fr', 'admin');Add and manage individual translation resources.
/**
* Add a single resource key-value pair
* @param lng - Language code
* @param ns - Namespace (optional, defaults to default namespace)
* @param key - Resource key (supports nested keys with dot notation)
* @param value - Translation value
*/
function addResource(lng, ns, key, value): void;
/**
* Add multiple resources from an object
* @param lng - Language code
* @param ns - Namespace (optional, defaults to default namespace)
* @param resources - Object containing key-value pairs
*/
function addResources(lng, ns, resources): void;Usage Examples:
// Add single resource to default namespace
i18n.addResource('en', 'welcome', 'Welcome to our app');
// Add single resource to specific namespace
i18n.addResource('en', 'common', 'buttons.submit', 'Submit');
// Add nested resource using dot notation
i18n.addResource('en', 'common', 'user.profile.title', 'User Profile');
// Add multiple resources
i18n.addResources('en', 'forms', {
validation: {
required: 'This field is required',
email: 'Please enter a valid email',
minLength: 'Minimum length is __min__ characters'
},
placeholders: {
email: 'Enter your email',
password: 'Enter your password'
}
});
// Add resources to default namespace (omit namespace parameter)
i18n.addResources('es', {
welcome: 'Bienvenido',
goodbye: 'Adiós'
});Manage namespaces and load them dynamically.
/**
* Set the default namespace
* @param ns - Namespace name to set as default
*/
function setDefaultNamespace(ns): void;
/**
* Load a single namespace dynamically
* @param namespace - Namespace to load
* @param callback - Function called when loading completes
*/
function loadNamespace(namespace, callback): void;
/**
* Load multiple namespaces dynamically
* @param namespaces - Array of namespace names to load
* @param callback - Function called when all loading completes
*/
function loadNamespaces(namespaces, callback): void;Usage Examples:
// Set default namespace
i18n.setDefaultNamespace('app');
// Load single namespace
i18n.loadNamespace('admin', function() {
console.log('Admin namespace loaded');
console.log(i18n.t('admin:dashboard.title'));
});
// Load multiple namespaces
i18n.loadNamespaces(['forms', 'validation', 'errors'], function() {
console.log('Form-related namespaces loaded');
console.log(i18n.t('forms:login.title'));
console.log(i18n.t('validation:required'));
});
// Load namespaces with error handling
i18n.loadNamespaces(['missing-namespace'], function(err) {
if (err) {
console.error('Failed to load namespaces:', err);
} else {
console.log('Namespaces loaded successfully');
}
});Configure automatic loading from JSON files.
i18n.init({
lng: 'en',
ns: {
namespaces: ['translation', 'common', 'forms'],
defaultNs: 'translation'
},
resGetPath: 'locales/__lng__/__ns__.json',
// Loads:
// locales/en/translation.json
// locales/en/common.json
// locales/en/forms.json
}, function(t) {
console.log('File-based resources loaded');
});Load resources on demand based on user actions or route changes.
function loadPageResources(page) {
const namespacesToLoad = [`pages-${page}`, 'page-common'];
i18n.loadNamespaces(namespacesToLoad, function() {
console.log(`Resources for ${page} page loaded`);
// Update page content
document.title = i18n.t(`pages-${page}:title`);
document.querySelector('.page-header').textContent =
i18n.t(`pages-${page}:header`);
});
}
// Usage in SPA routing
loadPageResources('dashboard');
loadPageResources('profile');Leverage localStorage caching for improved performance.
i18n.init({
useLocalStorage: true,
localStorageExpirationTime: 7 * 24 * 60 * 60 * 1000, // 7 days
resGetPath: 'api/translations/__lng__/__ns__',
// Custom load function for API integration
customLoad: function(lng, ns, options, loadComplete) {
fetch(`/api/translations/${lng}/${ns}`)
.then(response => response.json())
.then(data => loadComplete(null, data))
.catch(error => loadComplete(error, {}));
}
}, function(t) {
console.log('Cached resources loaded');
});function validateResources(lng, ns) {
if (!i18n.hasResourceBundle(lng, ns)) {
console.warn(`Missing resource bundle: ${lng}/${ns}`);
return false;
}
const bundle = i18n.getResourceBundle(lng, ns);
const keys = Object.keys(bundle);
if (keys.length === 0) {
console.warn(`Empty resource bundle: ${lng}/${ns}`);
return false;
}
console.log(`Resource bundle ${lng}/${ns} is valid with ${keys.length} keys`);
return true;
}
// Validate all loaded resources
['en', 'es', 'fr'].forEach(lng => {
['translation', 'common', 'forms'].forEach(ns => {
validateResources(lng, ns);
});
});function mergeResourceBundles(targetLng, sourceLng, namespace) {
const sourceBundle = i18n.getResourceBundle(sourceLng, namespace);
if (sourceBundle && Object.keys(sourceBundle).length > 0) {
i18n.addResourceBundle(targetLng, namespace, sourceBundle, true);
console.log(`Merged ${sourceLng} resources into ${targetLng} for ${namespace}`);
}
}
// Merge fallback resources
mergeResourceBundles('es-MX', 'es', 'common');
mergeResourceBundles('en-GB', 'en', 'translation');function syncResources(languages, namespaces) {
const totalResources = languages.length * namespaces.length;
let loadedResources = 0;
languages.forEach(lng => {
namespaces.forEach(ns => {
if (!i18n.hasResourceBundle(lng, ns)) {
// Load missing resource
loadResourceBundle(lng, ns).then(() => {
loadedResources++;
if (loadedResources === totalResources) {
console.log('All resources synchronized');
}
});
} else {
loadedResources++;
}
});
});
}
function loadResourceBundle(lng, ns) {
return new Promise((resolve, reject) => {
fetch(`/api/translations/${lng}/${ns}`)
.then(response => response.json())
.then(data => {
i18n.addResourceBundle(lng, ns, data);
resolve();
})
.catch(reject);
});
}function enableResourceHotReload() {
// WebSocket connection for development
const ws = new WebSocket('ws://localhost:3001/i18n-hot-reload');
ws.onmessage = function(event) {
const { lng, ns, resources } = JSON.parse(event.data);
// Update resource bundle
i18n.addResourceBundle(lng, ns, resources, false, true);
// Re-translate current page
if (typeof $ !== 'undefined') {
$('[data-i18n]').i18n(); // jQuery DOM update
} else {
i18n.translateObject(document); // Native DOM update
}
console.log(`Hot reloaded: ${lng}/${ns}`);
};
}
// Enable in development mode
if (window.location.hostname === 'localhost') {
enableResourceHotReload();
}// Resource loading error handling
i18n.loadNamespaces(['missing-namespace'], function(err) {
if (err) {
console.error('Resource loading failed:', err);
// Fallback to default resources
i18n.addResourceBundle(i18n.lng(), 'missing-namespace', {
error: 'Content not available'
});
}
});
// Validate resource integrity
function validateResourceIntegrity(lng, ns, expectedKeys) {
const bundle = i18n.getResourceBundle(lng, ns);
const missingKeys = expectedKeys.filter(key => !(key in bundle));
if (missingKeys.length > 0) {
console.warn(`Missing keys in ${lng}/${ns}:`, missingKeys);
// Add placeholder values
missingKeys.forEach(key => {
i18n.addResource(lng, ns, key, `[Missing: ${key}]`);
});
}
}Install with Tessl CLI
npx tessl i tessl/npm-i18next-clientdocs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10