UNPKG

@intlayer/core

Version:

Includes core Intlayer functions like translation, dictionary, and utility functions shared across multiple packages.

272 lines (270 loc) 11.7 kB
import { buildCookieString, resolveExpiresToTimestamp } from "./cookieExpiry.mjs"; import { getCookie } from "./getCookie.mjs"; import { internationalization, routing } from "@intlayer/config/built"; //#region src/utils/localeStorage.ts /** * True when cookie storage is explicitly disabled at build time. */ const TREE_SHAKE_STORAGE_COOKIES = process.env["INTLAYER_ROUTING_STORAGE_COOKIES"] === "false"; /** * True when localStorage is explicitly disabled at build time. */ const TREE_SHAKE_STORAGE_LOCAL_STORAGE = process.env["INTLAYER_ROUTING_STORAGE_LOCALSTORAGE"] === "false"; /** * True when sessionStorage is explicitly disabled at build time. */ const TREE_SHAKE_STORAGE_SESSION_STORAGE = process.env["INTLAYER_ROUTING_STORAGE_SESSIONSTORAGE"] === "false"; /** * True when header storage is explicitly disabled at build time. */ const TREE_SHAKE_STORAGE_HEADERS = process.env["INTLAYER_ROUTING_STORAGE_HEADERS"] === "false"; const localeStorageOptions = { getCookie: (name) => document.cookie.split(";").find((c) => c.trim().startsWith(`${name}=`))?.split("=")[1], getLocaleStorage: (name) => localStorage.getItem(name), getSessionStorage: (name) => sessionStorage.getItem(name), isCookieEnabled: true, setCookieStore: (name, value, attributes) => cookieStore.set({ name, value, path: attributes.path, domain: attributes.domain, expires: attributes.expires, sameSite: attributes.sameSite }), setCookieString: (_name, cookie) => { document.cookie = cookie; }, setSessionStorage: (name, value) => sessionStorage.setItem(name, value), setLocaleStorage: (name, value) => localStorage.setItem(name, value) }; /** * Retrieves the locale from browser storage mechanisms * (cookies, localStorage, sessionStorage). * Does not read from headers — use `getLocaleFromStorageServer` for that. */ const getLocaleFromStorageClient = (options = localeStorageOptions) => { const { locales } = internationalization; if (options?.isCookieEnabled === false) return void 0; const isValidLocale = (value) => !!value && locales.includes(value); if (!TREE_SHAKE_STORAGE_COOKIES) for (let i = 0; i < (routing.storage.cookies ?? []).length; i++) try { const value = options?.getCookie?.(routing.storage.cookies[i].name); if (isValidLocale(value)) return value; } catch {} if (!TREE_SHAKE_STORAGE_LOCAL_STORAGE) for (let i = 0; i < (routing.storage.localStorage ?? []).length; i++) try { const value = options?.getLocaleStorage?.(routing.storage.localStorage[i].name); if (isValidLocale(value)) return value; } catch {} if (!TREE_SHAKE_STORAGE_SESSION_STORAGE && routing.storage.sessionStorage) for (let i = 0; i < routing.storage.sessionStorage.length; i++) try { const value = options?.getSessionStorage?.(routing.storage.sessionStorage[i].name); if (isValidLocale(value)) return value; } catch {} }; /** * Stores the locale in browser storage mechanisms * (cookies, localStorage, sessionStorage). * Does not write to headers — use `setLocaleInStorageServer` for that. */ const setLocaleInStorageClient = (locale, options) => { if (options?.isCookieEnabled === false) return; if (!TREE_SHAKE_STORAGE_COOKIES && routing.storage.cookies) for (let i = 0; i < routing.storage.cookies.length; i++) { const { name, attributes } = routing.storage.cookies[i]; try { if (options?.setCookieStore) options.setCookieStore(name, locale, { ...attributes, expires: resolveExpiresToTimestamp(attributes.expires) }); } catch { try { if (options?.setCookieString) options.setCookieString(name, buildCookieString(name, locale, attributes)); } catch {} } } if (!TREE_SHAKE_STORAGE_LOCAL_STORAGE && routing.storage.localStorage && options?.setLocaleStorage) for (let i = 0; i < routing.storage.localStorage.length; i++) { const { name } = routing.storage.localStorage[i]; try { if (!(options?.overwrite ?? true) && options?.getLocaleStorage) { if (options.getLocaleStorage(name)) continue; } options.setLocaleStorage(name, locale); } catch {} } if (!TREE_SHAKE_STORAGE_SESSION_STORAGE && routing.storage.sessionStorage && options?.setSessionStorage) for (let i = 0; i < routing.storage.sessionStorage.length; i++) { const { name } = routing.storage.sessionStorage[i]; try { if (!(options?.overwrite ?? true) && options?.getSessionStorage) { if (options.getSessionStorage(name)) continue; } options.setSessionStorage(name, locale); } catch {} } }; /** * Client-side locale storage utility. * Handles cookies (browser), localStorage and sessionStorage. * Does not access headers. * * @example * ```ts * const storage = LocaleStorageClient(localeStorageOptions); * const locale = storage.getLocale(); * storage.setLocale('fr'); * ``` */ const LocaleStorageClient = (options) => ({ getLocale: () => getLocaleFromStorageClient(options), setLocale: (locale) => setLocaleInStorageClient(locale, options) }); /** * Retrieves the locale from server-side storage mechanisms (cookies, headers). * Does not access localStorage or sessionStorage. * No browser cookie fallback — the caller must provide `getCookie`. */ const getLocaleFromStorageServer = (options) => { const { locales } = internationalization; if (options?.isCookieEnabled === false) return void 0; const isValidLocale = (value) => !!value && locales.includes(value); if (!TREE_SHAKE_STORAGE_COOKIES && routing.storage.cookies) for (let i = 0; i < routing.storage.cookies.length; i++) try { const value = options?.getCookie?.(routing.storage.cookies[i].name); if (isValidLocale(value)) return value; } catch {} if (!TREE_SHAKE_STORAGE_HEADERS && routing.storage.headers) for (let i = 0; i < routing.storage.headers.length; i++) try { const value = options?.getHeader?.(routing.storage.headers[i].name); if (isValidLocale(value)) return value; } catch {} }; /** * Stores the locale in server-side storage mechanisms (cookies, headers). * Does not write to localStorage or sessionStorage. */ const setLocaleInStorageServer = (locale, options) => { if (options?.isCookieEnabled === false) return; if (!TREE_SHAKE_STORAGE_COOKIES && routing.storage.cookies) for (let i = 0; i < routing.storage.cookies.length; i++) { const { name, attributes } = routing.storage.cookies[i]; try { if (options?.setCookieStore) options.setCookieStore(name, locale, { ...attributes, expires: resolveExpiresToTimestamp(attributes.expires) }); } catch { try { if (options?.setCookieString) options.setCookieString(name, buildCookieString(name, locale, attributes)); } catch {} } } if (!TREE_SHAKE_STORAGE_HEADERS && routing.storage.headers && options?.setHeader) for (let i = 0; i < routing.storage.headers.length; i++) try { options.setHeader(routing.storage.headers[i].name, locale); } catch {} }; /** * Server-side locale storage utility. * Handles cookies (via injected getter/setter) and headers. * Does not access localStorage or sessionStorage. * * @example * ```ts * const storage = LocaleStorageServer({ * getCookie: (name) => req.cookies[name], * setCookieStore: (name, value, attrs) => res.cookie(name, value, attrs), * getHeader: (name) => req.headers[name], * setHeader: (name, value) => res.setHeader(name, value), * }); * const locale = storage.getLocale(); * storage.setLocale('fr'); * ``` */ const LocaleStorageServer = (options) => ({ getLocale: () => getLocaleFromStorageServer(options), setLocale: (locale) => setLocaleInStorageServer(locale, options) }); /** * Retrieves the locale from all storage mechanisms * (cookies, localStorage, sessionStorage, headers). * * @deprecated Use {@link getLocaleFromStorageClient} (browser) or * {@link getLocaleFromStorageServer} (server) instead. */ const getLocaleFromStorage = (options) => { const { locales } = internationalization; if (options?.isCookieEnabled === false) return void 0; const isValidLocale = (value) => !!value && locales.includes(value); const readCookie = (name) => { try { const fromOption = options?.getCookie?.(name); if (fromOption !== null && fromOption !== void 0) return fromOption; } catch {} return getCookie(name); }; if (!TREE_SHAKE_STORAGE_COOKIES && routing.storage.cookies) for (let i = 0; i < routing.storage.cookies.length; i++) { const value = readCookie(routing.storage.cookies[i].name); if (isValidLocale(value)) return value; } if (!TREE_SHAKE_STORAGE_LOCAL_STORAGE && routing.storage.localStorage) for (let i = 0; i < routing.storage.localStorage.length; i++) try { const value = options?.getLocaleStorage?.(routing.storage.localStorage[i].name); if (isValidLocale(value)) return value; } catch {} if (!TREE_SHAKE_STORAGE_SESSION_STORAGE && routing.storage.sessionStorage) for (let i = 0; i < routing.storage.sessionStorage.length; i++) try { const value = options?.getSessionStorage?.(routing.storage.sessionStorage[i].name); if (isValidLocale(value)) return value; } catch {} if (!TREE_SHAKE_STORAGE_HEADERS && routing.storage.headers) for (let i = 0; i < routing.storage.headers.length; i++) try { const value = options?.getHeader?.(routing.storage.headers[i].name); if (isValidLocale(value)) return value; } catch {} }; /** * Stores the locale in all configured storage mechanisms * (cookies, localStorage, sessionStorage, headers). * * @deprecated Use {@link setLocaleInStorageClient} (browser) or * {@link setLocaleInStorageServer} (server) instead. */ const setLocaleInStorage = (locale, options) => { if (options?.isCookieEnabled === false) return; if (!TREE_SHAKE_STORAGE_COOKIES && routing.storage.cookies) for (let i = 0; i < routing.storage.cookies.length; i++) { const { name, attributes } = routing.storage.cookies[i]; try { if (options?.setCookieStore) options.setCookieStore(name, locale, { ...attributes, expires: resolveExpiresToTimestamp(attributes.expires) }); } catch { try { if (options?.setCookieString) options.setCookieString(name, buildCookieString(name, locale, attributes)); } catch {} } } if (!TREE_SHAKE_STORAGE_LOCAL_STORAGE && routing.storage.localStorage && options?.setLocaleStorage) for (let i = 0; i < routing.storage.localStorage.length; i++) { const { name } = routing.storage.localStorage[i]; try { if (!(options?.overwrite ?? true) && options?.getLocaleStorage) { if (options.getLocaleStorage(name)) continue; } options.setLocaleStorage(name, locale); } catch {} } if (!TREE_SHAKE_STORAGE_SESSION_STORAGE && routing.storage.sessionStorage && options?.setSessionStorage) for (let i = 0; i < routing.storage.sessionStorage.length; i++) { const { name } = routing.storage.sessionStorage[i]; try { if (!(options?.overwrite ?? true) && options?.getSessionStorage) { if (options.getSessionStorage(name)) continue; } options.setSessionStorage(name, locale); } catch {} } if (!TREE_SHAKE_STORAGE_HEADERS && routing.storage.headers && options?.setHeader) for (let i = 0; i < routing.storage.headers.length; i++) try { options.setHeader(routing.storage.headers[i].name, locale); } catch {} }; /** * Utility object to get and set the locale in storage based on configuration. * * @deprecated Use {@link LocaleStorageClient} (browser) or * {@link LocaleStorageServer} (server) instead. */ const LocaleStorage = (options) => ({ getLocale: () => getLocaleFromStorage(options), setLocale: (locale) => setLocaleInStorage(locale, options) }); //#endregion export { LocaleStorage, LocaleStorageClient, LocaleStorageServer, getLocaleFromStorage, getLocaleFromStorageClient, getLocaleFromStorageServer, localeStorageOptions, setLocaleInStorage, setLocaleInStorageClient, setLocaleInStorageServer }; //# sourceMappingURL=localeStorage.mjs.map