Language detector used in browser environment for i18next internationalization framework
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Eight specialized detector modules for different browser APIs and storage mechanisms. Each detector implements a consistent interface for language lookup and optional caching, providing flexibility to extend the detection system with custom implementations.
Interface that all detector modules must implement for integration with the detection system.
interface CustomDetector {
/** Unique name for the detector */
name: string;
/**
* Language detection implementation
* @param options - Configuration options from DetectorOptions
* @returns Detected language code(s) or undefined if none found
*/
lookup(options: DetectorOptions): string | string[] | undefined;
/**
* Optional caching implementation
* @param lng - Language code to cache
* @param options - Configuration options from DetectorOptions
*/
cacheUserLanguage?(lng: string, options: DetectorOptions): void;
}Detects language from browser cookies with support for reading and writing cookie values.
// Built-in detector: 'cookie'
interface CookieDetector {
name: 'cookie';
lookup(options: DetectorOptions): string | undefined;
cacheUserLanguage(lng: string, options: DetectorOptions): void;
}How it works:
options.lookupCookie (default: 'i18next')options.cookieMinutes, options.cookieDomain, and options.cookieOptionsdocument.cookie access throws exceptionsUsage Examples:
// Configure cookie detection
const options = {
lookupCookie: 'user_language',
cookieMinutes: 60 * 24 * 30, // 30 days
cookieDomain: '.example.com',
cookieOptions: {
secure: true,
sameSite: 'strict'
}
};
// Manual cookie detection
detector.detect(['cookie']); // Only use cookie detectionDetects language from URL query parameters, supporting both standard query strings and hash-based parameters.
// Built-in detector: 'querystring'
interface QueryStringDetector {
name: 'querystring';
lookup(options: DetectorOptions): string | undefined;
}How it works:
options.lookupQuerystring (default: 'lng')window.location.hash for query parameters?lng=en, #/page?lng=en, ?lang=fr-CAUsage Examples:
// Configure querystring detection
const options = {
lookupQuerystring: 'lang' // Look for ?lang=en instead of ?lng=en
};
// URLs that would be detected:
// https://example.com?lang=en -> 'en'
// https://example.com#/route?lang=fr -> 'fr'
// https://example.com/page?lang=zh-CN -> 'zh-CN'Detects and caches language in browser localStorage with availability checking.
// Built-in detector: 'localStorage'
interface LocalStorageDetector {
name: 'localStorage';
lookup(options: DetectorOptions): string | undefined;
cacheUserLanguage(lng: string, options: DetectorOptions): void;
}How it works:
options.lookupLocalStorage (default: 'i18nextLng')Usage Examples:
// Configure localStorage detection
const options = {
lookupLocalStorage: 'app_language',
caches: ['localStorage'] // Enable caching to localStorage
};
// localStorage key will be 'app_language'
// Value persists across browser sessionsDetects and caches language in browser sessionStorage with availability checking.
// Built-in detector: 'sessionStorage'
interface SessionStorageDetector {
name: 'sessionStorage';
lookup(options: DetectorOptions): string | undefined;
cacheUserLanguage(lng: string, options: DetectorOptions): void;
}How it works:
options.lookupSessionStorage (default: 'i18nextLng')Usage Examples:
// Configure sessionStorage detection
const options = {
lookupSessionStorage: 'session_lang',
caches: ['sessionStorage'] // Enable caching to sessionStorage
};
// sessionStorage key will be 'session_lang'
// Value cleared when browser tab is closedDetects language from browser navigator object, supporting multiple browser language APIs.
// Built-in detector: 'navigator'
interface NavigatorDetector {
name: 'navigator';
lookup(options: DetectorOptions): string[] | undefined;
}How it works:
navigator.languages, navigator.userLanguage, and navigator.languageUsage Examples:
// Navigator detection returns language arrays
const detected = detector.detect(['navigator']);
// Example result: ['en-US', 'en', 'fr']
// Handles different browser implementations:
// Chrome: navigator.languages = ['en-US', 'en']
// IE: navigator.userLanguage = 'en-US'
// Safari: navigator.language = 'en-US'Detects language from HTML lang attribute on specified elements.
// Built-in detector: 'htmlTag'
interface HtmlTagDetector {
name: 'htmlTag';
lookup(options: DetectorOptions): string | undefined;
}How it works:
lang attribute from options.htmlTag or document.documentElementUsage Examples:
// Use default document element
const defaultOptions = {}; // Uses document.documentElement
// Use specific element
const customOptions = {
htmlTag: document.querySelector('#app')
};
// Disable HTML tag detection
const disabledOptions = {
htmlTag: null
};
// Example HTML:
// <html lang="en-US"> -> 'en-US'
// <div id="app" lang="fr"> -> 'fr' (if configured)Detects language from URL path segments using configurable indexing.
// Built-in detector: 'path'
interface PathDetector {
name: 'path';
lookup(options: DetectorOptions): string | undefined;
}How it works:
window.location.pathname using regexoptions.lookupFromPathIndex to select which path segment/language-code/ patterns in the URL pathUsage Examples:
// Configure path detection
const options = {
lookupFromPathIndex: 0 // Use first path segment
};
// Example URLs:
// /en/home -> 'en'
// /fr-CA/products -> 'fr-CA'
// /zh/about/contact -> 'zh'
// Use second segment
const secondSegmentOptions = {
lookupFromPathIndex: 1
};
// /app/en/dashboard -> 'en' (second segment)Detects language from hostname subdomains using pattern matching and indexing.
// Built-in detector: 'subdomain'
interface SubdomainDetector {
name: 'subdomain';
lookup(options: DetectorOptions): string | undefined;
}How it works:
window.location.hostname using regexen.example.com or fr.localhostoptions.lookupFromSubdomainIndex to select subdomain positionUsage Examples:
// Configure subdomain detection
const options = {
lookupFromSubdomainIndex: 0 // Use first subdomain
};
// Example hostnames:
// en.example.com -> 'en'
// fr.myapp.localhost -> 'fr'
// de.api.service.com -> 'de' (first subdomain)
// Use different subdomain position
const secondSubdomainOptions = {
lookupFromSubdomainIndex: 1
};
// api.en.example.com -> 'en' (second subdomain)Implement the CustomDetector interface to create custom detection methods:
// Example: Detect language from user API preferences
const apiDetector: CustomDetector = {
name: 'userApi',
async lookup(options) {
try {
const response = await fetch('/api/user/preferences');
const data = await response.json();
return data.language;
} catch (error) {
return undefined; // Return undefined on error
}
},
async cacheUserLanguage(lng, options) {
try {
await fetch('/api/user/preferences', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ language: lng })
});
} catch (error) {
// Handle error silently
}
}
};
// Add to detector
detector.addDetector(apiDetector);
// Use in detection order
detector.init(null, {
order: ['userApi', 'cookie', 'navigator']
});All built-in detectors are designed to fail gracefully:
undefined when browser APIs are not availabledocument or window objects in server-side environmentsstring, string[], or undefined from lookup methods