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