UNPKG

@shelchin/svelte-i18n

Version:

The last Svelte i18n library you'll ever need. Type-safe, AI-powered, zero-config.

174 lines (173 loc) 5.92 kB
/** * Unified persistence module for i18n locale management * Handles both client-side (localStorage) and universal (cookie + localStorage) persistence */ import { getBrowserLocale } from '../utils/browser-detection.js'; // Default configuration const DEFAULT_COOKIE_NAME = 'i18n-locale'; const DEFAULT_STORAGE_KEY = 'i18n-locale'; // ============================================ // Cookie utilities // ============================================ /** * Parse cookies from a cookie string */ function parseCookies(cookieString) { const cookies = {}; if (!cookieString) return cookies; cookieString.split(';').forEach((cookie) => { const [name, value] = cookie.trim().split('='); if (name && value) { cookies[name] = decodeURIComponent(value); } }); return cookies; } /** * Get locale from cookies (works on both server and client) */ export function getLocaleFromCookie(cookieString, cookieName = DEFAULT_COOKIE_NAME) { const cookies = parseCookies(cookieString); return cookies[cookieName] || null; } /** * Set locale in cookie (client-side only) */ export function setLocaleCookie(locale, cookieName = DEFAULT_COOKIE_NAME) { if (typeof document !== 'undefined') { // Set cookie with 1 year expiry const expires = new Date(); expires.setFullYear(expires.getFullYear() + 1); // For localhost, don't set domain to avoid issues // Also use max-age as a fallback to expires const maxAge = 365 * 24 * 60 * 60; // 1 year in seconds document.cookie = `${cookieName}=${encodeURIComponent(locale)}; expires=${expires.toUTCString()}; max-age=${maxAge}; path=/; SameSite=Lax`; console.log(`[setLocaleCookie] Set cookie: ${cookieName}=${locale}`); } } // ============================================ // LocalStorage utilities // ============================================ /** * Get locale from localStorage (client-side only) */ export function getLocaleFromStorage(storageKey = DEFAULT_STORAGE_KEY) { if (typeof window !== 'undefined' && window.localStorage) { try { return localStorage.getItem(storageKey); } catch { // Silent fail } } return null; } /** * Set locale in localStorage (client-side only) */ export function setLocaleStorage(locale, storageKey = DEFAULT_STORAGE_KEY) { if (typeof window !== 'undefined' && window.localStorage) { try { localStorage.setItem(storageKey, locale); } catch { // Silent fail } } } // ============================================ // Universal persistence (cookie + localStorage) // ============================================ /** * Save locale to both cookie and localStorage */ export function saveLocaleUniversal(locale, config) { const { cookieName = DEFAULT_COOKIE_NAME, storageKey = DEFAULT_STORAGE_KEY } = config || {}; // Save to cookie (for SSR) setLocaleCookie(locale, cookieName); // Save to localStorage (for client-side persistence) setLocaleStorage(locale, storageKey); } /** * Get initial locale from cookie or localStorage * Priority: cookie > localStorage > browser > default */ export function getInitialLocaleUniversal(defaultLocale, cookieString, config) { const { cookieName = DEFAULT_COOKIE_NAME, storageKey = DEFAULT_STORAGE_KEY, enableBrowserDetection = false // Default to false, respect configured default } = config || {}; // First priority: cookie (works on server and client) if (cookieString) { const cookieLocale = getLocaleFromCookie(cookieString, cookieName); if (cookieLocale) { return cookieLocale; } } // Second priority: localStorage (client-side only) const storageLocale = getLocaleFromStorage(storageKey); if (storageLocale) { return storageLocale; } // Third priority: browser language detection (only if explicitly enabled) if (enableBrowserDetection) { const browserLang = getBrowserLocale(); if (browserLang) { const langCode = browserLang.split('-')[0]; return langCode; } } // Fallback to default return defaultLocale; } // ============================================ // Simple persistence API (backward compatibility) // ============================================ /** * Save the selected locale to localStorage and cookie */ export function saveLocale(locale) { saveLocaleUniversal(locale, { storageKey: DEFAULT_STORAGE_KEY }); } /** * Load the saved locale from localStorage */ export function loadSavedLocale() { return getLocaleFromStorage(DEFAULT_STORAGE_KEY); } /** * Clear the saved locale from both localStorage and cookie */ export function clearSavedLocale() { if (typeof window !== 'undefined' && window.localStorage) { try { localStorage.removeItem(DEFAULT_STORAGE_KEY); // Also clear cookie for consistency if (typeof document !== 'undefined') { document.cookie = `${DEFAULT_STORAGE_KEY}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`; } } catch (error) { console.error('Failed to clear locale:', error); } } } /** * Get initial locale based on priority: * 1. Saved locale from localStorage * 2. Browser language * 3. Default locale */ export function getInitialLocale(defaultLocale, availableLocales) { // First priority: saved locale const savedLocale = loadSavedLocale(); if (savedLocale && (!availableLocales || availableLocales.includes(savedLocale))) { return savedLocale; } // Second priority: browser language const browserLocale = getBrowserLocale(availableLocales); if (browserLocale) { return browserLocale; } // Fallback to default return defaultLocale; }