{"version":3,"file":"getTranslation.mjs","names":[],"sources":["../../../src/interpreter/getTranslation.ts"],"sourcesContent":["import type {\n  LocalesValues,\n  StrictModeLocaleMap,\n} from '@intlayer/types/module_augmentation';\n\n/**\n * Check if a value is a plain object that can be safely merged.\n * Returns false for Promises, React elements, class instances, etc.\n */\nconst isPlainObject = (value: unknown): boolean => {\n  if (value === null || typeof value !== 'object') return false;\n  if (typeof (value as any).then === 'function') return false;\n  if (\n    (value as any).$$typeof !== undefined ||\n    (value as any).__v_isVNode !== undefined ||\n    (value as any)._isVNode !== undefined ||\n    (value as any).isJSX !== undefined\n  ) {\n    return false;\n  }\n  const proto = Object.getPrototypeOf(value);\n  return proto === Object.prototype || proto === null || Array.isArray(value);\n};\n\n/**\n * Recursively merges two objects, skipping undefined source values.\n * First argument takes precedence. Arrays replace rather than merge.\n */\nconst deepMerge = (target: any, source: any): any => {\n  if (target === undefined) return source;\n  if (source === undefined) return target;\n  if (Array.isArray(target)) return target;\n  if (isPlainObject(target) && isPlainObject(source)) {\n    const result = { ...target };\n\n    for (const key of Object.keys(source)) {\n      if (\n        key === '__proto__' ||\n        key === 'constructor' ||\n        source[key] === undefined\n      )\n        continue;\n      result[key] =\n        target[key] !== undefined\n          ? deepMerge(target[key], source[key])\n          : source[key];\n    }\n    return result;\n  }\n  return target;\n};\n\n/**\n * Picks the appropriate content from a locale map based on the provided locale.\n *\n * It handles:\n * 1. Exact locale match (e.g., 'en-US').\n * 2. Generic locale fallback (e.g., 'en' if 'en-US' is not found).\n * 3. Explicit fallback locale.\n * 4. Deep merging of objects to ensure partial translations are complemented by fallbacks.\n *\n * @param languageContent - A map of locales to content.\n * @param locale - The target locale to retrieve.\n * @param fallback - Optional fallback locale if the target is not found.\n * @returns The translated content.\n *\n * @example\n * ```ts\n * const content = getTranslation({\n *   en: 'Hello',\n *   fr: 'Bonjour',\n * }, 'fr');\n * // 'Bonjour'\n * ```\n */\nexport const getTranslation = <const Content = string>(\n  languageContent: StrictModeLocaleMap<Content>,\n  locale: LocalesValues,\n  fallback?: LocalesValues\n): Content => {\n  const get = (loc: string): Content | undefined =>\n    languageContent[loc as keyof typeof languageContent];\n\n  // Build priority-ordered locale candidates (most specific first), deduped\n  const seen = new Set<string>();\n  const locales: string[] = [];\n  const addLocale = (loc: string | undefined) => {\n    if (loc && !seen.has(loc)) {\n      seen.add(loc);\n      locales.push(loc);\n    }\n  };\n\n  addLocale(locale);\n  if (locale.includes('-')) addLocale(locale.split('-')[0]);\n\n  addLocale(fallback);\n  if (fallback?.includes('-')) addLocale(fallback.split('-')[0]);\n\n  // Collect results: strings exit early (if no higher-priority object was found),\n  // objects are accumulated for deep merging.\n  const results: Content[] = [];\n\n  for (const loc of locales) {\n    const val = get(loc);\n\n    if (val === undefined) continue;\n    if (typeof val === 'string') {\n      if (results.length === 0) return val;\n      continue; // an object at higher priority takes precedence\n    }\n\n    results.push(val);\n  }\n\n  if (results.length === 0) return undefined as Content;\n  if (results.length === 1) return results[0];\n  if (Array.isArray(results[0])) return results[0];\n\n  // Merge objects: first result (most specific) takes precedence\n  return (results as object[]).reduce((acc, curr) =>\n    deepMerge(acc, curr)\n  ) as Content;\n};\n"],"mappings":";;;;;AASA,MAAM,iBAAiB,UAA4B;AACjD,KAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO;AACxD,KAAI,OAAQ,MAAc,SAAS,WAAY,QAAO;AACtD,KACG,MAAc,aAAa,UAC3B,MAAc,gBAAgB,UAC9B,MAAc,aAAa,UAC3B,MAAc,UAAU,OAEzB,QAAO;CAET,MAAM,QAAQ,OAAO,eAAe,MAAM;AAC1C,QAAO,UAAU,OAAO,aAAa,UAAU,QAAQ,MAAM,QAAQ,MAAM;;;;;;AAO7E,MAAM,aAAa,QAAa,WAAqB;AACnD,KAAI,WAAW,OAAW,QAAO;AACjC,KAAI,WAAW,OAAW,QAAO;AACjC,KAAI,MAAM,QAAQ,OAAO,CAAE,QAAO;AAClC,KAAI,cAAc,OAAO,IAAI,cAAc,OAAO,EAAE;EAClD,MAAM,SAAS,EAAE,GAAG,QAAQ;AAE5B,OAAK,MAAM,OAAO,OAAO,KAAK,OAAO,EAAE;AACrC,OACE,QAAQ,eACR,QAAQ,iBACR,OAAO,SAAS,OAEhB;AACF,UAAO,OACL,OAAO,SAAS,SACZ,UAAU,OAAO,MAAM,OAAO,KAAK,GACnC,OAAO;;AAEf,SAAO;;AAET,QAAO;;;;;;;;;;;;;;;;;;;;;;;;;AA0BT,MAAa,kBACX,iBACA,QACA,aACY;CACZ,MAAM,OAAO,QACX,gBAAgB;CAGlB,MAAM,uBAAO,IAAI,KAAa;CAC9B,MAAM,UAAoB,EAAE;CAC5B,MAAM,aAAa,QAA4B;AAC7C,MAAI,OAAO,CAAC,KAAK,IAAI,IAAI,EAAE;AACzB,QAAK,IAAI,IAAI;AACb,WAAQ,KAAK,IAAI;;;AAIrB,WAAU,OAAO;AACjB,KAAI,OAAO,SAAS,IAAI,CAAE,WAAU,OAAO,MAAM,IAAI,CAAC,GAAG;AAEzD,WAAU,SAAS;AACnB,KAAI,UAAU,SAAS,IAAI,CAAE,WAAU,SAAS,MAAM,IAAI,CAAC,GAAG;CAI9D,MAAM,UAAqB,EAAE;AAE7B,MAAK,MAAM,OAAO,SAAS;EACzB,MAAM,MAAM,IAAI,IAAI;AAEpB,MAAI,QAAQ,OAAW;AACvB,MAAI,OAAO,QAAQ,UAAU;AAC3B,OAAI,QAAQ,WAAW,EAAG,QAAO;AACjC;;AAGF,UAAQ,KAAK,IAAI;;AAGnB,KAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,KAAI,QAAQ,WAAW,EAAG,QAAO,QAAQ;AACzC,KAAI,MAAM,QAAQ,QAAQ,GAAG,CAAE,QAAO,QAAQ;AAG9C,QAAQ,QAAqB,QAAQ,KAAK,SACxC,UAAU,KAAK,KAAK,CACrB"}