@intlayer/core
Version:
Includes core Intlayer functions like translation, dictionary, and utility functions shared across multiple packages.
272 lines (270 loc) • 11.7 kB
JavaScript
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