UNPKG

express-intlayer

Version:

Manage internationalization i18n in a simple way for express application.

1 lines 8.59 kB
{"version":3,"file":"index.mjs","names":["negotiatorHeaders: Record<string, string>","t","getIntlayer: typeof getIntlayerFunction","getIntlayerFunction","getDictionary: typeof getDictionaryFunction","getDictionaryFunction","getIntlayer","getDictionary"],"sources":["../../src/index.ts"],"sourcesContent":["import { prepareIntlayer } from '@intlayer/chokidar';\nimport { getConfiguration } from '@intlayer/config';\nimport {\n getDictionary as getDictionaryFunction,\n getIntlayer as getIntlayerFunction,\n getLocaleFromStorage,\n getTranslation,\n localeDetector,\n} from '@intlayer/core';\nimport type { Locale, StrictModeLocaleMap } from '@intlayer/types';\nimport { createNamespace } from 'cls-hooked';\nimport type { NextFunction, Request, RequestHandler, Response } from 'express';\n\nconst configuration = getConfiguration();\nconst { internationalization } = configuration;\n\n/**\n * Retrieves the locale from storage (cookies, localStorage, sessionStorage).\n */\nconst getStorageLocale = (req: Request): Locale | undefined =>\n getLocaleFromStorage({\n getCookie: (name: string) => req.cookies?.[name],\n getHeader: (name: string) => req.headers?.[name] as string | undefined,\n });\n\nconst appNamespace = createNamespace('app');\n\nprepareIntlayer(configuration);\n\nexport const translateFunction =\n (_req: Request, res: Response, _next?: NextFunction) =>\n <T extends string>(\n content: StrictModeLocaleMap<T> | string,\n locale?: Locale\n ): T => {\n const { locale: currentLocale, defaultLocale } = res.locals as {\n locale: Locale;\n defaultLocale: Locale;\n };\n\n const targetLocale = locale ?? currentLocale;\n\n if (typeof content === 'undefined') {\n return '' as unknown as T;\n }\n\n if (typeof content === 'string') {\n return content as unknown as T;\n }\n\n if (\n typeof content?.[\n targetLocale as unknown as keyof StrictModeLocaleMap<T>\n ] === 'undefined'\n ) {\n if (\n typeof content?.[\n defaultLocale as unknown as keyof StrictModeLocaleMap<T>\n ] === 'undefined'\n ) {\n return content as unknown as T;\n } else {\n return getTranslation(content, defaultLocale);\n }\n }\n\n return getTranslation(content, targetLocale);\n };\n\n/**\n * Detect locale used by the user and load it into res locale storage\n *\n * @returns\n */\nexport const intlayer = (): RequestHandler => async (req, res, next) => {\n // Detect if locale is set by intlayer frontend lib in the headers\n const localeFromStorage = getStorageLocale(req);\n // Interpret browser locale\n\n const negotiatorHeaders: Record<string, string> = {};\n\n // // Check if req.headers exists and is an object\n if (req && typeof req.headers === 'object') {\n // Copy all headers from the request to negotiatorHeaders\n for (const key in req.headers) {\n if (typeof req.headers[key] === 'string') {\n negotiatorHeaders[key] = req.headers[key];\n }\n }\n }\n\n const localeDetected = localeDetector(\n negotiatorHeaders,\n internationalization.locales,\n internationalization.defaultLocale\n );\n\n res.locals.locale_storage = localeFromStorage;\n res.locals.locale_detected = localeDetected;\n res.locals.locale = localeFromStorage ?? localeDetected;\n res.locals.defaultLocale = internationalization.defaultLocale;\n\n const t = translateFunction(req, res, next);\n\n const getIntlayer: typeof getIntlayerFunction = (\n key,\n localeArg = localeDetected as Parameters<typeof getIntlayerFunction>[1],\n ...props\n ) => getIntlayerFunction(key, localeArg, ...props);\n\n const getDictionary: typeof getDictionaryFunction = (\n key,\n localeArg = localeDetected as Parameters<typeof getDictionaryFunction>[1],\n ...props\n ) => getDictionaryFunction(key, localeArg, ...props);\n\n res.locals.t = t;\n res.locals.getIntlayer = getIntlayer;\n res.locals.getDictionary = getDictionary;\n\n appNamespace.run(() => {\n appNamespace.set('t', t);\n appNamespace.set('getIntlayer', getIntlayer);\n appNamespace.set('getDictionary', getDictionary);\n\n next();\n });\n};\n\nexport const t = <Content = string>(\n content: StrictModeLocaleMap<Content>,\n locale?: Locale\n): Content => {\n try {\n if (typeof appNamespace === 'undefined') {\n throw new Error(\n 'Intlayer is not initialized. Add the `app.use(intlayer());` middleware before using this function.'\n );\n }\n\n if (typeof appNamespace.get('t') !== 'function') {\n throw new Error(\n 'Using the import { t } from \"express-intlayer\" is not supported in your environment. Use the res.locals.t syntax instead.'\n );\n }\n\n return appNamespace.get('t')(content, locale);\n } catch (error) {\n if (process.env.NODE_ENV === 'development') {\n console.error((error as Error).message);\n }\n\n return getTranslation(\n content,\n locale ?? internationalization.defaultLocale\n );\n }\n};\n\nexport const getIntlayer: typeof getIntlayerFunction = (...args) => {\n try {\n if (typeof appNamespace === 'undefined') {\n throw new Error(\n 'Intlayer is not initialized. Add the `app.use(intlayer());` middleware before using this function.'\n );\n }\n\n if (typeof appNamespace.get('getIntlayer') !== 'function') {\n throw new Error(\n 'Using the import { t } from \"express-intlayer\" is not supported in your environment. Use the res.locals.t syntax instead.'\n );\n }\n\n return appNamespace.get('getIntlayer')(...args);\n } catch (error) {\n if (process.env.NODE_ENV === 'development') {\n console.error((error as Error).message);\n }\n return getIntlayerFunction(...args);\n }\n};\n\nexport const getDictionary: typeof getDictionaryFunction = (...args) => {\n try {\n if (typeof appNamespace === 'undefined') {\n throw new Error(\n 'Intlayer is not initialized. Add the `app.use(intlayer());` middleware before using this function.'\n );\n }\n\n if (typeof appNamespace.get('getDictionary') !== 'function') {\n throw new Error(\n 'Using the import { t } from \"express-intlayer\" is not supported in your environment. Use the res.locals.t syntax instead.'\n );\n }\n\n return appNamespace.get('getDictionary')(...args);\n } catch (error) {\n if (process.env.NODE_ENV === 'development') {\n console.error((error as Error).message);\n }\n return getDictionaryFunction(...args);\n }\n};\n"],"mappings":";;;;;;AAaA,MAAM,gBAAgB,kBAAkB;AACxC,MAAM,EAAE,yBAAyB;;;;AAKjC,MAAM,oBAAoB,QACxB,qBAAqB;CACnB,YAAY,SAAiB,IAAI,UAAU;CAC3C,YAAY,SAAiB,IAAI,UAAU;CAC5C,CAAC;AAEJ,MAAM,eAAe,gBAAgB,MAAM;AAE3C,gBAAgB,cAAc;AAE9B,MAAa,qBACV,MAAe,KAAe,WAE7B,SACA,WACM;CACN,MAAM,EAAE,QAAQ,eAAe,kBAAkB,IAAI;CAKrD,MAAM,eAAe,UAAU;AAE/B,KAAI,OAAO,YAAY,YACrB,QAAO;AAGT,KAAI,OAAO,YAAY,SACrB,QAAO;AAGT,KACE,OAAO,UACL,kBACI,YAEN,KACE,OAAO,UACL,mBACI,YAEN,QAAO;KAEP,QAAO,eAAe,SAAS,cAAc;AAIjD,QAAO,eAAe,SAAS,aAAa;;;;;;;AAQhD,MAAa,iBAAiC,OAAO,KAAK,KAAK,SAAS;CAEtE,MAAM,oBAAoB,iBAAiB,IAAI;CAG/C,MAAMA,oBAA4C,EAAE;AAGpD,KAAI,OAAO,OAAO,IAAI,YAAY,UAEhC;OAAK,MAAM,OAAO,IAAI,QACpB,KAAI,OAAO,IAAI,QAAQ,SAAS,SAC9B,mBAAkB,OAAO,IAAI,QAAQ;;CAK3C,MAAM,iBAAiB,eACrB,mBACA,qBAAqB,SACrB,qBAAqB,cACtB;AAED,KAAI,OAAO,iBAAiB;AAC5B,KAAI,OAAO,kBAAkB;AAC7B,KAAI,OAAO,SAAS,qBAAqB;AACzC,KAAI,OAAO,gBAAgB,qBAAqB;CAEhD,MAAMC,MAAI,kBAAkB,KAAK,KAAK,KAAK;CAE3C,MAAMC,iBACJ,KACA,YAAY,gBACZ,GAAG,UACAC,cAAoB,KAAK,WAAW,GAAG,MAAM;CAElD,MAAMC,mBACJ,KACA,YAAY,gBACZ,GAAG,UACAC,gBAAsB,KAAK,WAAW,GAAG,MAAM;AAEpD,KAAI,OAAO,IAAIJ;AACf,KAAI,OAAO,cAAcK;AACzB,KAAI,OAAO,gBAAgBC;AAE3B,cAAa,UAAU;AACrB,eAAa,IAAI,KAAKN,IAAE;AACxB,eAAa,IAAI,eAAeK,cAAY;AAC5C,eAAa,IAAI,iBAAiBC,gBAAc;AAEhD,QAAM;GACN;;AAGJ,MAAa,KACX,SACA,WACY;AACZ,KAAI;AACF,MAAI,OAAO,iBAAiB,YAC1B,OAAM,IAAI,MACR,qGACD;AAGH,MAAI,OAAO,aAAa,IAAI,IAAI,KAAK,WACnC,OAAM,IAAI,MACR,8HACD;AAGH,SAAO,aAAa,IAAI,IAAI,CAAC,SAAS,OAAO;UACtC,OAAO;AAEZ,UAAQ,MAAO,MAAgB,QAAQ;AAGzC,SAAO,eACL,SACA,UAAU,qBAAqB,cAChC;;;AAIL,MAAaL,eAA2C,GAAG,SAAS;AAClE,KAAI;AACF,MAAI,OAAO,iBAAiB,YAC1B,OAAM,IAAI,MACR,qGACD;AAGH,MAAI,OAAO,aAAa,IAAI,cAAc,KAAK,WAC7C,OAAM,IAAI,MACR,8HACD;AAGH,SAAO,aAAa,IAAI,cAAc,CAAC,GAAG,KAAK;UACxC,OAAO;AAEZ,UAAQ,MAAO,MAAgB,QAAQ;AAEzC,SAAOC,cAAoB,GAAG,KAAK;;;AAIvC,MAAaC,iBAA+C,GAAG,SAAS;AACtE,KAAI;AACF,MAAI,OAAO,iBAAiB,YAC1B,OAAM,IAAI,MACR,qGACD;AAGH,MAAI,OAAO,aAAa,IAAI,gBAAgB,KAAK,WAC/C,OAAM,IAAI,MACR,8HACD;AAGH,SAAO,aAAa,IAAI,gBAAgB,CAAC,GAAG,KAAK;UAC1C,OAAO;AAEZ,UAAQ,MAAO,MAAgB,QAAQ;AAEzC,SAAOC,gBAAsB,GAAG,KAAK"}