UNPKG

express-intlayer

Version:

Manage internationalization i18n in a simple way for express application.

129 lines (127 loc) 5.45 kB
import { getConfiguration } from "@intlayer/config/node"; import { getDictionary as getDictionary$1, getIntlayer as getIntlayer$1, getTranslation } from "@intlayer/core/interpreter"; import { localeDetector } from "@intlayer/core/localization"; import { getLocaleFromStorageServer } from "@intlayer/core/utils"; import { prepareIntlayer } from "@intlayer/engine/build"; import { createNamespace } from "cls-hooked"; //#region src/index.ts let debug = () => {}; const configuration = getConfiguration(); const { internationalization } = configuration; debug = (msg) => console.debug(msg); /** * Retrieves the locale from storage (cookies, localStorage, sessionStorage). */ const getStorageLocale = (req) => getLocaleFromStorageServer({ getCookie: (name) => req.cookies?.[name], getHeader: (name) => req.headers?.[name] }); const appNamespace = createNamespace("app"); prepareIntlayer(configuration); const translateFunction = (_req, res, _next) => (content, locale) => { const { locale: currentLocale, defaultLocale } = res.locals; const targetLocale = locale ?? currentLocale; if (typeof content === "undefined") return ""; if (typeof content === "string") return content; if (typeof content?.[targetLocale] === "undefined") if (typeof content?.[defaultLocale] === "undefined") return content; else return getTranslation(content, defaultLocale); return getTranslation(content, targetLocale); }; /** * Express middleware that detects the user's locale and populates `res.locals` with Intlayer data. * * It performs: * 1. Locale detection from cookies, headers, or default settings. * 2. Injects `t`, `getIntlayer`, and `getDictionary` functions into `res.locals`. * 3. Sets up a `cls-hooked` namespace for accessing these functions anywhere in the request lifecycle. * * @returns An Express middleware function. * * @example * ```ts * import express from 'express'; * import { intlayer } from 'express-intlayer'; * * const app = express(); * app.use(intlayer()); * ``` */ const intlayer = () => async (req, res, next) => { const localeFromStorage = getStorageLocale(req); const negotiatorHeaders = {}; if (req && typeof req.headers === "object") { for (const key in req.headers) if (typeof req.headers[key] === "string") negotiatorHeaders[key] = req.headers[key]; } const localeDetected = localeDetector(negotiatorHeaders, internationalization.locales, internationalization.defaultLocale); res.locals.locale_storage = localeFromStorage; res.locals.locale_detected = localeDetected; res.locals.locale = localeFromStorage ?? localeDetected; res.locals.defaultLocale = internationalization.defaultLocale; const t = translateFunction(req, res, next); const getIntlayer = (key, localeArg = localeDetected, ...props) => getIntlayer$1(key, localeArg, ...props); const getDictionary = (key, localeArg = localeDetected, ...props) => getDictionary$1(key, localeArg, ...props); res.locals.t = t; res.locals.getIntlayer = getIntlayer; res.locals.getDictionary = getDictionary; appNamespace.run(() => { appNamespace.set("t", t); appNamespace.set("getIntlayer", getIntlayer); appNamespace.set("getDictionary", getDictionary); next(); }); }; /** * Translation function to retrieve content for the current locale. * * This function works within the request lifecycle managed by the `intlayer` middleware. * * @param content - A map of locales to content. * @param locale - Optional locale override. * @returns The translated content. * * @example * ```ts * import { t } from 'express-intlayer'; * * app.get('/', (req, res) => { * const greeting = t({ * en: 'Hello', * fr: 'Bonjour', * }); * res.send(greeting); * }); * ``` */ const t = (content, locale) => { try { if (typeof appNamespace === "undefined") throw new Error("Intlayer is not initialized. Add the `app.use(intlayer());` middleware before using this function."); if (typeof appNamespace.get("t") !== "function") throw new Error("Using the import { t } from \"express-intlayer\" is not supported in your environment. Use the res.locals.t syntax instead."); return appNamespace.get("t")(content, locale); } catch (error) { debug(error.message); return getTranslation(content, locale ?? internationalization.defaultLocale); } }; const getIntlayer = (...args) => { try { if (typeof appNamespace === "undefined") throw new Error("Intlayer is not initialized. Add the `app.use(intlayer());` middleware before using this function."); if (typeof appNamespace.get("getIntlayer") !== "function") throw new Error("Using the import { t } from \"express-intlayer\" is not supported in your environment. Use the res.locals.t syntax instead."); return appNamespace.get("getIntlayer")(...args); } catch (error) { debug(error.message); return getIntlayer$1(...args); } }; const getDictionary = (...args) => { try { if (typeof appNamespace === "undefined") throw new Error("Intlayer is not initialized. Add the `app.use(intlayer());` middleware before using this function."); if (typeof appNamespace.get("getDictionary") !== "function") throw new Error("Using the import { t } from \"express-intlayer\" is not supported in your environment. Use the res.locals.t syntax instead."); return appNamespace.get("getDictionary")(...args); } catch (error) { debug(error.message); return getDictionary$1(...args); } }; //#endregion export { getDictionary, getIntlayer, intlayer, t, translateFunction }; //# sourceMappingURL=index.mjs.map