@vyxos/astro-i18next
Version:
I18next integration for Astro with dynamic namespace loading.
1 lines • 8.64 kB
Source Map (JSON)
{"version":3,"sources":["../src/constants.ts","../src/utils/helpers.ts","../src/logger/colorings.ts","../src/utils/localization.ts"],"names":["i18next","createRequire"],"mappings":";;;;;;;;;;;;;AAAO,IAAM,gBAAA,GAAmB,sBAAA;;;ACqBzB,SAAS,SAAA,GACuB;AACrC,EAAA,IAAI,CAACA,wBAAA,CAAQ,OAAA,CAAQ,kBAAA,EAAoB;AACvC,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,CAAA,EAAI,gBAAgB,CAAA,6BAAA,CAA+B,CAAA;AAAA,EACrE;AAEA,EAAA,OAAO,IAAA,CAAK,KAAA;AAAA,IACV,IAAA,CAAK,SAAA,CAAUA,wBAAA,CAAQ,OAAA,CAAQ,kBAAkB;AAAA,GACnD;AACF;AC3BA,IAAM,SAAA,GAAY,OAAO,MAAA,KAAW,WAAA;AAChB,SAAA,GAAY,IAAA,GAAOC,sBAAA,CAAc,2PAAe;;;ACwB7D,SAAS,oBAAA,CAAqB,UAAkB,MAAA,EAAiB;AACtE,EAAA,MAAM,EAAE,GAAA,EAAK,aAAA,EAAc,GAAI,SAAA,EAAU;AACzC,EAAA,MAAM,YAAA,GAAe,MAAA,IAAUD,wBAAAA,CAAQ,QAAA,IAAY,EAAA;AACnD,EAAA,MAAM,kBAAA,GAAqB,QAAA,CAAS,KAAA,CAAM,GAAG,EAAE,CAAC,CAAA;AAChD,EAAA,IAAI,iBAAA,GAAoB,QAAA;AAGxB,EAAA,IACE,MAAM,OAAA,CAAQ,aAAa,KAC3B,aAAA,CAAc,QAAA,CAAS,kBAAkB,CAAA,EACzC;AACA,IAAA,iBAAA,GACE,iBAAA,CAAkB,OAAA,CAAQ,GAAA,GAAM,kBAAA,EAAoB,EAAE,CAAA,IAAK,GAAA;AAAA,EAC/D;AAKA,EAAA,IACE,KAAA,CAAM,OAAA,CAAQ,aAAa,CAAA,IAC3B,aAAA,CAAc,QAAA,CAAS,YAAY,CAAA,KAClC,GAAA,KAAQ,MAAA,IAAc,YAAA,KAAiB,GAAA,IAAO,QAAQ,QAAA,CAAA,EACvD;AACA,IAAA,iBAAA,GACE,GAAA,GAAM,YAAA,GAAe,iBAAA,CAAkB,OAAA,CAAQ,QAAQ,EAAE,CAAA;AAAA,EAC7D;AAEA,EAAA,OAAO,iBAAA;AACT","file":"utils.cjs","sourcesContent":["export const INTEGRATION_NAME = \"@vyxos/astro-i18next\";\n","import i18next from \"i18next\";\nimport { INTEGRATION_NAME } from \"../constants\";\nimport {\n IntegrationOptions,\n IntegrationOptionsInternal,\n} from \"../types/integration\";\n\n/**\n * Retrieves the current configuration for the astro-i18next integration.\n *\n * This function provides access to the merged configuration (internal + i18next options)\n * in both SSG (Static Site Generation) and SPA (Single Page Application) modes.\n * The configuration is automatically injected during the build process and stored globally for runtime access.\n *\n * @returns The merged configuration object containing both internal options and i18next options\n *\n * @throws {Error} Throws an error if the configuration is not available, which typically\n * indicates that the astro-i18next integration is not properly configured.\n *\n * @since 0.1.5\n */\nexport function getConfig(): IntegrationOptionsInternal &\n IntegrationOptions[\"i18NextOptions\"] {\n if (!i18next.options.integrationOptions) {\n throw new Error(`[${INTEGRATION_NAME}] Configuration object empty.`);\n }\n\n return JSON.parse(\n JSON.stringify(i18next.options.integrationOptions)\n ) as typeof i18next.options.integrationOptions;\n}\n\nexport { getGlobalObject } from \"./browser-helpers\";\n","// Browser-safe colorings - createRequire for ESM compatibility\nimport { createRequire } from \"module\";\n\nconst isBrowser = typeof window !== \"undefined\";\nconst nodeRequire = isBrowser ? null : createRequire(import.meta.url);\n\n// Synchronous color functions with fallback\nexport const colorTimestamp = (value: string) => {\n if (isBrowser || !nodeRequire) return value;\n try {\n const { dim } = nodeRequire(\"kleur/colors\");\n return dim(value);\n } catch {\n return value;\n }\n};\n\nexport const colorIntegration = (value: string) => {\n if (isBrowser || !nodeRequire) return value;\n try {\n const { bold, green } = nodeRequire(\"kleur/colors\");\n return bold(green(value));\n } catch {\n return value;\n }\n};\n\nexport const colorWarn = (value: string) => {\n if (isBrowser || !nodeRequire) return value;\n try {\n const { yellow } = nodeRequire(\"kleur/colors\");\n return yellow(value);\n } catch {\n return value;\n }\n};\n\nexport const colorError = (value: string) => {\n if (isBrowser || !nodeRequire) return value;\n try {\n const { red } = nodeRequire(\"kleur/colors\");\n return red(value);\n } catch {\n return value;\n }\n};\n\nexport const colorWarnPrefix = (value: string) => {\n if (isBrowser || !nodeRequire) return value;\n try {\n const { bold, yellow } = nodeRequire(\"kleur/colors\");\n return bold(yellow(value));\n } catch {\n return value;\n }\n};\n\nexport const colorErrorPrefix = (value: string) => {\n if (isBrowser || !nodeRequire) return value;\n try {\n const { red } = nodeRequire(\"kleur/colors\");\n return red(value);\n } catch {\n return value;\n }\n};\n","/// <reference lib=\"dom\" />\nimport i18next from \"i18next\";\nimport { logError } from \"../logger\";\nimport { getConfig } from \"../utils\";\n\n/**\n * Generates a localized URL pathname based on a given path and target locale.\n *\n * This function ensures that the generated pathname correctly reflects the desired locale\n * according to the rules defined in the configuration. It first strips any existing locale\n * from the input pathname to get a base path. Then, it prepends the target locale to the\n * base path, but only if the target locale is not the default locale.\n *\n * @param {string} [pathname] - The original pathname to be localized. This can be a path\n * that already contains a locale prefix (e.g., \"/en/about\") or a path without one\n * (e.g., \"/about\"). Defaults to an empty string.\n *\n * @param {string} [locale] - The target locale code for the new pathname (e.g., \"fr\").\n * If this locale is the default locale, it will not be added to the path.\n * If not provided, uses the current locale from i18next.\n *\n * @returns {string} The fully resolved, localized pathname. For example:\n * - `getLocalizedPathname(\"/fr/about\", \"de\")` returns `\"/de/about\"`\n * - `getLocalizedPathname(\"/about\", \"fr\")` returns `\"/fr/about\"`\n * - `getLocalizedPathname(\"/fr/about\", \"en\")` returns `\"/about\"` (if \"en\" is default)\n *\n * @since 0.1.5\n */\nexport function getLocalizedPathname(pathname: string, locale?: string) {\n const { lng, supportedLngs } = getConfig();\n const targetLocale = locale || i18next.language || \"\";\n const localeFromPathname = pathname.split(\"/\")[1];\n let localizedPathname = pathname;\n\n // 1. Strip any existing locale from the pathname to get a clean, unlocalized path.\n if (\n Array.isArray(supportedLngs) &&\n supportedLngs.includes(localeFromPathname)\n ) {\n localizedPathname =\n localizedPathname.replace(\"/\" + localeFromPathname, \"\") || \"/\";\n }\n\n // 2. Add the target locale as a prefix, but only if it's a valid,\n // non-default locale. Skip adding prefix for 'cimode' as well.\n // If lng is not set, always add the locale prefix for supported languages\n if (\n Array.isArray(supportedLngs) &&\n supportedLngs.includes(targetLocale) &&\n (lng === undefined || (targetLocale !== lng && lng !== \"cimode\"))\n ) {\n localizedPathname =\n \"/\" + targetLocale + localizedPathname.replace(/^\\/$/, \"\");\n }\n\n return localizedPathname;\n}\n\n/**\n * Changes the current locale of the application and updates the URL accordingly.\n *\n * This function first checks if the `nextLocale` is supported by the application.\n * If it is, it updates the `i18next` instance to the new locale and then\n * constructs a new URL pathname using `getLocalizedPathname`.\n *\n * The URL is updated using `history.replaceState` for a shallow update (no page reload)\n * or `window.location.replace` for a full page reload, depending on the `shallow` parameter.\n *\n * @param {string} [nextLocale=\"\"] - The target locale code to switch to (e.g., \"fr\").\n * If an unsupported locale is provided, the function will do nothing.\n * @param {boolean} [shallow=true] - If `true`, uses `history.replaceState` to update the URL\n * without a full page reload. If `false`, uses `window.location.replace` which causes a full page reload.\n *\n * @example\n * ```typescript\n * // Change locale to French without a full page reload\n * changeLocale(\"fr\");\n *\n * // Change locale to German with a full page reload\n * changeLocale(\"de\", false);\n * ```\n *\n * @see {@link getLocalizedPathname}\n * @since 0.2.0\n */\nexport function changeLocale(nextLocale: string = \"\", shallow: boolean = true) {\n i18next.changeLanguage(nextLocale);\n\n if (typeof window === \"undefined\") {\n logError(`Trying to access client-only function in server environment.`);\n\n return;\n }\n\n const { hash, pathname, search } = window.location;\n const nextPathname = getLocalizedPathname(pathname, nextLocale);\n\n if (nextPathname !== pathname) {\n const nextUrl = nextPathname + search + hash;\n\n if (shallow) {\n window.history.replaceState(null, \"\", nextUrl);\n } else {\n window.location.replace(nextUrl);\n }\n }\n}\n"]}