{"version":3,"file":"getMissingLocalesContent.cjs","names":["NodeType","configuration","plugins: Plugins[]"],"sources":["../../../src/deepTransformPlugins/getMissingLocalesContent.ts"],"sourcesContent":["import configuration from '@intlayer/config/built';\nimport type { Dictionary } from '@intlayer/types';\nimport {\n  type ContentNode,\n  type Locale,\n  type LocalesValues,\n  NodeType,\n} from '@intlayer/types';\nimport type { DeepTransformContent, NodeProps, Plugins } from '../interpreter';\nimport { deepTransformNode } from '../interpreter/getContent/deepTransform';\nimport type { TranslationContent } from '../transpiler';\n\nconst getDeepKeyPaths = (obj: any, prefix: string[] = []): string[][] => {\n  if (typeof obj !== 'object' || obj === null) {\n    return [];\n  }\n\n  // Skip array indices - arrays of different lengths shouldn't trigger missing translations\n  // Each locale can have arrays with different numbers of elements (e.g., keywords)\n  if (Array.isArray(obj)) {\n    return [];\n  }\n\n  return Object.keys(obj).flatMap((key) => {\n    const newPath = [...prefix, key];\n    return [newPath, ...getDeepKeyPaths(obj[key], newPath)];\n  });\n};\n\nconst hasDeepKeyPath = (obj: any, keyPath: string[]): boolean => {\n  let current = obj;\n  for (const key of keyPath) {\n    if (\n      current === undefined ||\n      current === null ||\n      typeof current !== 'object'\n    ) {\n      return false;\n    }\n    if (!(key in current)) {\n      return false;\n    }\n    current = current[key];\n  }\n\n  return true;\n};\n\n/** Translation plugin. Replaces node with a locale string if nodeType = Translation. */\nexport const checkMissingLocalesPlugin = (\n  locales: Locale[],\n  onMissingLocale: (locale: Locale) => void\n): Plugins => ({\n  id: 'check-missing-locales-plugin',\n  canHandle: (node) =>\n    typeof node === 'object' && node?.nodeType === NodeType.Translation,\n  transform: (node: TranslationContent, props, deepTransformNode) => {\n    const translations = node[NodeType.Translation] as Record<string, any>;\n    const allKeys = new Set<string>();\n\n    for (const locale of locales) {\n      if (translations[locale]) {\n        getDeepKeyPaths(translations[locale]).forEach((path) => {\n          allKeys.add(JSON.stringify(path));\n        });\n      }\n    }\n\n    for (const locale of locales) {\n      if (!translations[locale]) {\n        onMissingLocale(locale);\n        continue;\n      }\n\n      for (const pathStr of allKeys) {\n        const path = JSON.parse(pathStr);\n        if (!hasDeepKeyPath(translations[locale], path)) {\n          onMissingLocale(locale);\n          break;\n        }\n      }\n    }\n\n    // Continue traversal inside the translation values, but avoid re-applying this plugin on the same node\n    for (const key in translations) {\n      const child = translations[key];\n      deepTransformNode(child, {\n        ...props,\n        children: child,\n      });\n    }\n\n    // Return the original node; the return value is ignored by the caller\n    return node;\n  },\n});\n\n/**\n * Return the content of a node with only the translation plugin.\n *\n * @param node The node to transform.\n * @param locales The locales to check for missing translations.\n */\nexport const getMissingLocalesContent = <T extends ContentNode>(\n  node: T,\n  locales: LocalesValues[] = configuration?.internationalization?.locales,\n  nodeProps: NodeProps\n): Locale[] => {\n  const missingLocales = new Set<Locale>();\n\n  const plugins: Plugins[] = [\n    checkMissingLocalesPlugin(locales as Locale[], (locale) =>\n      missingLocales.add(locale)\n    ),\n    ...(nodeProps.plugins ?? []),\n  ];\n\n  deepTransformNode(node, {\n    ...nodeProps,\n    plugins,\n  }) as DeepTransformContent<T>;\n\n  return Array.from(missingLocales);\n};\n\nexport const getMissingLocalesContentFromDictionary = (\n  dictionary: Dictionary,\n  locales: LocalesValues[] = configuration?.internationalization?.locales\n) =>\n  getMissingLocalesContent(dictionary.content, locales, {\n    dictionaryKey: dictionary.key,\n    keyPath: [],\n  });\n"],"mappings":";;;;;;;AAYA,MAAM,mBAAmB,KAAU,SAAmB,EAAE,KAAiB;AACvE,KAAI,OAAO,QAAQ,YAAY,QAAQ,KACrC,QAAO,EAAE;AAKX,KAAI,MAAM,QAAQ,IAAI,CACpB,QAAO,EAAE;AAGX,QAAO,OAAO,KAAK,IAAI,CAAC,SAAS,QAAQ;EACvC,MAAM,UAAU,CAAC,GAAG,QAAQ,IAAI;AAChC,SAAO,CAAC,SAAS,GAAG,gBAAgB,IAAI,MAAM,QAAQ,CAAC;GACvD;;AAGJ,MAAM,kBAAkB,KAAU,YAA+B;CAC/D,IAAI,UAAU;AACd,MAAK,MAAM,OAAO,SAAS;AACzB,MACE,YAAY,UACZ,YAAY,QACZ,OAAO,YAAY,SAEnB,QAAO;AAET,MAAI,EAAE,OAAO,SACX,QAAO;AAET,YAAU,QAAQ;;AAGpB,QAAO;;;AAIT,MAAa,6BACX,SACA,qBACa;CACb,IAAI;CACJ,YAAY,SACV,OAAO,SAAS,YAAY,MAAM,aAAaA,0BAAS;CAC1D,YAAY,MAA0B,OAAO,wBAAsB;EACjE,MAAM,eAAe,KAAKA,0BAAS;EACnC,MAAM,0BAAU,IAAI,KAAa;AAEjC,OAAK,MAAM,UAAU,QACnB,KAAI,aAAa,QACf,iBAAgB,aAAa,QAAQ,CAAC,SAAS,SAAS;AACtD,WAAQ,IAAI,KAAK,UAAU,KAAK,CAAC;IACjC;AAIN,OAAK,MAAM,UAAU,SAAS;AAC5B,OAAI,CAAC,aAAa,SAAS;AACzB,oBAAgB,OAAO;AACvB;;AAGF,QAAK,MAAM,WAAW,SAAS;IAC7B,MAAM,OAAO,KAAK,MAAM,QAAQ;AAChC,QAAI,CAAC,eAAe,aAAa,SAAS,KAAK,EAAE;AAC/C,qBAAgB,OAAO;AACvB;;;;AAMN,OAAK,MAAM,OAAO,cAAc;GAC9B,MAAM,QAAQ,aAAa;AAC3B,uBAAkB,OAAO;IACvB,GAAG;IACH,UAAU;IACX,CAAC;;AAIJ,SAAO;;CAEV;;;;;;;AAQD,MAAa,4BACX,MACA,UAA2BC,iCAAe,sBAAsB,SAChE,cACa;CACb,MAAM,iCAAiB,IAAI,KAAa;CAExC,MAAMC,UAAqB,CACzB,0BAA0B,UAAsB,WAC9C,eAAe,IAAI,OAAO,CAC3B,EACD,GAAI,UAAU,WAAW,EAAE,CAC5B;AAED,gEAAkB,MAAM;EACtB,GAAG;EACH;EACD,CAAC;AAEF,QAAO,MAAM,KAAK,eAAe;;AAGnC,MAAa,0CACX,YACA,UAA2BD,iCAAe,sBAAsB,YAEhE,yBAAyB,WAAW,SAAS,SAAS;CACpD,eAAe,WAAW;CAC1B,SAAS,EAAE;CACZ,CAAC"}