@intlayer/core 9.0.0-canary.17 → 9.0.0-canary.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (484) hide show
  1. package/dist/cjs/deepTransformPlugins/getEditedContent.cjs +2 -1
  2. package/dist/cjs/deepTransformPlugins/getEditedContent.cjs.map +1 -1
  3. package/dist/cjs/deepTransformPlugins/getFilterMissingTranslationsContent.cjs.map +1 -1
  4. package/dist/cjs/deepTransformPlugins/getFilterTranslationsOnlyContent.cjs.map +1 -1
  5. package/dist/cjs/deepTransformPlugins/getFilteredLocalesContent.cjs.map +1 -1
  6. package/dist/cjs/deepTransformPlugins/getLocalizedContent.cjs.map +1 -1
  7. package/dist/cjs/deepTransformPlugins/getMaskContent.cjs.map +1 -1
  8. package/dist/cjs/deepTransformPlugins/getMissingLocalesContent.cjs.map +1 -1
  9. package/dist/cjs/deepTransformPlugins/getMultilingualDictionary.cjs.map +1 -1
  10. package/dist/cjs/deepTransformPlugins/getReplacedValuesContent.cjs.map +1 -1
  11. package/dist/cjs/deepTransformPlugins/getSplittedContent.cjs +1 -1
  12. package/dist/cjs/deepTransformPlugins/getSplittedContent.cjs.map +1 -1
  13. package/dist/cjs/deepTransformPlugins/insertContentInDictionary.cjs.map +1 -1
  14. package/dist/cjs/dictionaryManipulator/editDictionaryByKeyPath.cjs.map +1 -1
  15. package/dist/cjs/dictionaryManipulator/getContentNodeByKeyPath.cjs.map +1 -1
  16. package/dist/cjs/dictionaryManipulator/getDefaultNode.cjs.map +1 -1
  17. package/dist/cjs/dictionaryManipulator/getEmptyNode.cjs.map +1 -1
  18. package/dist/cjs/dictionaryManipulator/getNodeChildren.cjs.map +1 -1
  19. package/dist/cjs/dictionaryManipulator/getNodeType.cjs.map +1 -1
  20. package/dist/cjs/dictionaryManipulator/mergeDictionaries.cjs +1 -2
  21. package/dist/cjs/dictionaryManipulator/mergeDictionaries.cjs.map +1 -1
  22. package/dist/cjs/dictionaryManipulator/mergeQualifiedDictionaries.cjs +0 -1
  23. package/dist/cjs/dictionaryManipulator/mergeQualifiedDictionaries.cjs.map +1 -1
  24. package/dist/cjs/dictionaryManipulator/normalizeDictionary.cjs.map +1 -1
  25. package/dist/cjs/dictionaryManipulator/orderDictionaries.cjs +0 -1
  26. package/dist/cjs/dictionaryManipulator/orderDictionaries.cjs.map +1 -1
  27. package/dist/cjs/dictionaryManipulator/qualifiedDictionary.cjs.map +1 -1
  28. package/dist/cjs/dictionaryManipulator/removeContentNodeByKeyPath.cjs.map +1 -1
  29. package/dist/cjs/dictionaryManipulator/renameContentNodeByKeyPath.cjs.map +1 -1
  30. package/dist/cjs/dictionaryManipulator/updateNodeChildren.cjs.map +1 -1
  31. package/dist/cjs/formatters/compact.cjs +1 -2
  32. package/dist/cjs/formatters/compact.cjs.map +1 -1
  33. package/dist/cjs/formatters/currency.cjs +1 -2
  34. package/dist/cjs/formatters/currency.cjs.map +1 -1
  35. package/dist/cjs/formatters/date.cjs +1 -3
  36. package/dist/cjs/formatters/date.cjs.map +1 -1
  37. package/dist/cjs/formatters/list.cjs +1 -2
  38. package/dist/cjs/formatters/list.cjs.map +1 -1
  39. package/dist/cjs/formatters/number.cjs +1 -2
  40. package/dist/cjs/formatters/number.cjs.map +1 -1
  41. package/dist/cjs/formatters/percentage.cjs +1 -2
  42. package/dist/cjs/formatters/percentage.cjs.map +1 -1
  43. package/dist/cjs/formatters/relativeTime.cjs +1 -2
  44. package/dist/cjs/formatters/relativeTime.cjs.map +1 -1
  45. package/dist/cjs/formatters/units.cjs +1 -2
  46. package/dist/cjs/formatters/units.cjs.map +1 -1
  47. package/dist/cjs/interpreter/getCondition.cjs.map +1 -1
  48. package/dist/cjs/interpreter/getContent/deepTransform.cjs +3 -2
  49. package/dist/cjs/interpreter/getContent/deepTransform.cjs.map +1 -1
  50. package/dist/cjs/interpreter/getContent/getContent.cjs +0 -1
  51. package/dist/cjs/interpreter/getContent/getContent.cjs.map +1 -1
  52. package/dist/cjs/interpreter/getContent/plugins.cjs +4 -2
  53. package/dist/cjs/interpreter/getContent/plugins.cjs.map +1 -1
  54. package/dist/cjs/interpreter/getDictionary.cjs.map +1 -1
  55. package/dist/cjs/interpreter/getEnumeration.cjs.map +1 -1
  56. package/dist/cjs/interpreter/getGender.cjs.map +1 -1
  57. package/dist/cjs/interpreter/getHTML.cjs.map +1 -1
  58. package/dist/cjs/interpreter/getInsertion.cjs.map +1 -1
  59. package/dist/cjs/interpreter/getIntlayer.cjs +2 -2
  60. package/dist/cjs/interpreter/getIntlayer.cjs.map +1 -1
  61. package/dist/cjs/interpreter/getNesting.cjs.map +1 -1
  62. package/dist/cjs/interpreter/getPlural.cjs +1 -1
  63. package/dist/cjs/interpreter/getPlural.cjs.map +1 -1
  64. package/dist/cjs/interpreter/getTranslation.cjs.map +1 -1
  65. package/dist/cjs/interpreter/splitAndJoinInsertion.cjs.map +1 -1
  66. package/dist/cjs/localization/comparePaths.cjs.map +1 -1
  67. package/dist/cjs/localization/domainUtils.cjs.map +1 -1
  68. package/dist/cjs/localization/generateSitemap.cjs +2 -1
  69. package/dist/cjs/localization/generateSitemap.cjs.map +1 -1
  70. package/dist/cjs/localization/getBrowserLocale.cjs +7 -4
  71. package/dist/cjs/localization/getBrowserLocale.cjs.map +1 -1
  72. package/dist/cjs/localization/getHTMLTextDir.cjs.map +1 -1
  73. package/dist/cjs/localization/getLocale.cjs +0 -1
  74. package/dist/cjs/localization/getLocale.cjs.map +1 -1
  75. package/dist/cjs/localization/getLocaleFromPath.cjs.map +1 -1
  76. package/dist/cjs/localization/getLocaleLang.cjs.map +1 -1
  77. package/dist/cjs/localization/getLocaleName.cjs.map +1 -1
  78. package/dist/cjs/localization/getLocalizedUrl.cjs +0 -1
  79. package/dist/cjs/localization/getLocalizedUrl.cjs.map +1 -1
  80. package/dist/cjs/localization/getMultilingualUrls.cjs.map +1 -1
  81. package/dist/cjs/localization/getPathWithoutLocale.cjs +0 -1
  82. package/dist/cjs/localization/getPathWithoutLocale.cjs.map +1 -1
  83. package/dist/cjs/localization/getPrefix.cjs +0 -1
  84. package/dist/cjs/localization/getPrefix.cjs.map +1 -1
  85. package/dist/cjs/localization/localeDetector.cjs +2 -1
  86. package/dist/cjs/localization/localeDetector.cjs.map +1 -1
  87. package/dist/cjs/localization/localeMapper.cjs +0 -1
  88. package/dist/cjs/localization/localeMapper.cjs.map +1 -1
  89. package/dist/cjs/localization/localeResolver.cjs +0 -1
  90. package/dist/cjs/localization/localeResolver.cjs.map +1 -1
  91. package/dist/cjs/localization/rewriteUtils.cjs +2 -1
  92. package/dist/cjs/localization/rewriteUtils.cjs.map +1 -1
  93. package/dist/cjs/localization/validatePrefix.cjs.map +1 -1
  94. package/dist/cjs/markdown/compiler.cjs +2 -1
  95. package/dist/cjs/markdown/compiler.cjs.map +1 -1
  96. package/dist/cjs/markdown/constants.cjs.map +1 -1
  97. package/dist/cjs/markdown/parser.cjs.map +1 -1
  98. package/dist/cjs/markdown/renderer.cjs.map +1 -1
  99. package/dist/cjs/markdown/utils.cjs.map +1 -1
  100. package/dist/cjs/messageFormat/ICU.cjs +15 -9
  101. package/dist/cjs/messageFormat/ICU.cjs.map +1 -1
  102. package/dist/cjs/messageFormat/i18next.cjs +12 -7
  103. package/dist/cjs/messageFormat/i18next.cjs.map +1 -1
  104. package/dist/cjs/messageFormat/navigatePath.cjs.map +1 -1
  105. package/dist/cjs/messageFormat/po.cjs.map +1 -1
  106. package/dist/cjs/messageFormat/resolveMessage.cjs +11 -8
  107. package/dist/cjs/messageFormat/resolveMessage.cjs.map +1 -1
  108. package/dist/cjs/messageFormat/verify-icu-format.cjs.map +1 -1
  109. package/dist/cjs/messageFormat/vue-i18n.cjs +2 -1
  110. package/dist/cjs/messageFormat/vue-i18n.cjs.map +1 -1
  111. package/dist/cjs/transpiler/condition/condition.cjs +0 -1
  112. package/dist/cjs/transpiler/condition/condition.cjs.map +1 -1
  113. package/dist/cjs/transpiler/enumeration/enumeration.cjs +0 -1
  114. package/dist/cjs/transpiler/enumeration/enumeration.cjs.map +1 -1
  115. package/dist/cjs/transpiler/file/file.cjs +2 -2
  116. package/dist/cjs/transpiler/file/file.cjs.map +1 -1
  117. package/dist/cjs/transpiler/file/fileBrowser.cjs.map +1 -1
  118. package/dist/cjs/transpiler/gender/gender.cjs +0 -1
  119. package/dist/cjs/transpiler/gender/gender.cjs.map +1 -1
  120. package/dist/cjs/transpiler/html/getHTMLCustomComponents.cjs.map +1 -1
  121. package/dist/cjs/transpiler/html/html.cjs +0 -1
  122. package/dist/cjs/transpiler/html/html.cjs.map +1 -1
  123. package/dist/cjs/transpiler/html/htmlTags.cjs.map +1 -1
  124. package/dist/cjs/transpiler/html/validateHTML.cjs +1 -1
  125. package/dist/cjs/transpiler/html/validateHTML.cjs.map +1 -1
  126. package/dist/cjs/transpiler/insertion/getInsertionValues.cjs.map +1 -1
  127. package/dist/cjs/transpiler/insertion/insertion.cjs +0 -1
  128. package/dist/cjs/transpiler/insertion/insertion.cjs.map +1 -1
  129. package/dist/cjs/transpiler/markdown/getMarkdownMetadata.cjs.map +1 -1
  130. package/dist/cjs/transpiler/markdown/markdown.cjs +0 -1
  131. package/dist/cjs/transpiler/markdown/markdown.cjs.map +1 -1
  132. package/dist/cjs/transpiler/markdown/validateMarkdown.cjs.map +1 -1
  133. package/dist/cjs/transpiler/nesting/nesting.cjs +0 -1
  134. package/dist/cjs/transpiler/nesting/nesting.cjs.map +1 -1
  135. package/dist/cjs/transpiler/plural/plural.cjs +0 -1
  136. package/dist/cjs/transpiler/plural/plural.cjs.map +1 -1
  137. package/dist/cjs/transpiler/translation/translation.cjs +0 -1
  138. package/dist/cjs/transpiler/translation/translation.cjs.map +1 -1
  139. package/dist/cjs/utils/checkIsURLAbsolute.cjs.map +1 -1
  140. package/dist/cjs/utils/cookieExpiry.cjs.map +1 -1
  141. package/dist/cjs/utils/getCookie.cjs.map +1 -1
  142. package/dist/cjs/utils/intl.cjs +101 -26
  143. package/dist/cjs/utils/intl.cjs.map +1 -1
  144. package/dist/cjs/utils/isSameKeyPath.cjs.map +1 -1
  145. package/dist/cjs/utils/localeStorage.cjs +0 -1
  146. package/dist/cjs/utils/localeStorage.cjs.map +1 -1
  147. package/dist/cjs/utils/parseYaml.cjs +1 -1
  148. package/dist/cjs/utils/parseYaml.cjs.map +1 -1
  149. package/dist/cjs/utils/stringifyYaml.cjs +1 -1
  150. package/dist/cjs/utils/stringifyYaml.cjs.map +1 -1
  151. package/dist/esm/deepTransformPlugins/getEditedContent.mjs +2 -1
  152. package/dist/esm/deepTransformPlugins/getEditedContent.mjs.map +1 -1
  153. package/dist/esm/deepTransformPlugins/getFilterMissingTranslationsContent.mjs.map +1 -1
  154. package/dist/esm/deepTransformPlugins/getFilterTranslationsOnlyContent.mjs.map +1 -1
  155. package/dist/esm/deepTransformPlugins/getFilteredLocalesContent.mjs.map +1 -1
  156. package/dist/esm/deepTransformPlugins/getLocalizedContent.mjs.map +1 -1
  157. package/dist/esm/deepTransformPlugins/getMaskContent.mjs.map +1 -1
  158. package/dist/esm/deepTransformPlugins/getMissingLocalesContent.mjs.map +1 -1
  159. package/dist/esm/deepTransformPlugins/getMultilingualDictionary.mjs.map +1 -1
  160. package/dist/esm/deepTransformPlugins/getReplacedValuesContent.mjs.map +1 -1
  161. package/dist/esm/deepTransformPlugins/getSplittedContent.mjs +1 -1
  162. package/dist/esm/deepTransformPlugins/getSplittedContent.mjs.map +1 -1
  163. package/dist/esm/deepTransformPlugins/insertContentInDictionary.mjs.map +1 -1
  164. package/dist/esm/dictionaryManipulator/editDictionaryByKeyPath.mjs.map +1 -1
  165. package/dist/esm/dictionaryManipulator/getContentNodeByKeyPath.mjs.map +1 -1
  166. package/dist/esm/dictionaryManipulator/getDefaultNode.mjs.map +1 -1
  167. package/dist/esm/dictionaryManipulator/getEmptyNode.mjs.map +1 -1
  168. package/dist/esm/dictionaryManipulator/getNodeChildren.mjs.map +1 -1
  169. package/dist/esm/dictionaryManipulator/getNodeType.mjs.map +1 -1
  170. package/dist/esm/dictionaryManipulator/mergeDictionaries.mjs +1 -1
  171. package/dist/esm/dictionaryManipulator/mergeDictionaries.mjs.map +1 -1
  172. package/dist/esm/dictionaryManipulator/mergeQualifiedDictionaries.mjs.map +1 -1
  173. package/dist/esm/dictionaryManipulator/normalizeDictionary.mjs.map +1 -1
  174. package/dist/esm/dictionaryManipulator/orderDictionaries.mjs.map +1 -1
  175. package/dist/esm/dictionaryManipulator/qualifiedDictionary.mjs.map +1 -1
  176. package/dist/esm/dictionaryManipulator/removeContentNodeByKeyPath.mjs.map +1 -1
  177. package/dist/esm/dictionaryManipulator/renameContentNodeByKeyPath.mjs.map +1 -1
  178. package/dist/esm/dictionaryManipulator/updateNodeChildren.mjs.map +1 -1
  179. package/dist/esm/formatters/compact.mjs +1 -1
  180. package/dist/esm/formatters/compact.mjs.map +1 -1
  181. package/dist/esm/formatters/currency.mjs +1 -1
  182. package/dist/esm/formatters/currency.mjs.map +1 -1
  183. package/dist/esm/formatters/date.mjs +1 -2
  184. package/dist/esm/formatters/date.mjs.map +1 -1
  185. package/dist/esm/formatters/list.mjs +1 -1
  186. package/dist/esm/formatters/list.mjs.map +1 -1
  187. package/dist/esm/formatters/number.mjs +1 -1
  188. package/dist/esm/formatters/number.mjs.map +1 -1
  189. package/dist/esm/formatters/percentage.mjs +1 -1
  190. package/dist/esm/formatters/percentage.mjs.map +1 -1
  191. package/dist/esm/formatters/relativeTime.mjs +1 -1
  192. package/dist/esm/formatters/relativeTime.mjs.map +1 -1
  193. package/dist/esm/formatters/units.mjs +1 -1
  194. package/dist/esm/formatters/units.mjs.map +1 -1
  195. package/dist/esm/interpreter/getCondition.mjs.map +1 -1
  196. package/dist/esm/interpreter/getContent/deepTransform.mjs +3 -2
  197. package/dist/esm/interpreter/getContent/deepTransform.mjs.map +1 -1
  198. package/dist/esm/interpreter/getContent/getContent.mjs.map +1 -1
  199. package/dist/esm/interpreter/getContent/plugins.mjs +4 -2
  200. package/dist/esm/interpreter/getContent/plugins.mjs.map +1 -1
  201. package/dist/esm/interpreter/getDictionary.mjs.map +1 -1
  202. package/dist/esm/interpreter/getEnumeration.mjs.map +1 -1
  203. package/dist/esm/interpreter/getGender.mjs.map +1 -1
  204. package/dist/esm/interpreter/getHTML.mjs.map +1 -1
  205. package/dist/esm/interpreter/getInsertion.mjs.map +1 -1
  206. package/dist/esm/interpreter/getIntlayer.mjs +2 -1
  207. package/dist/esm/interpreter/getIntlayer.mjs.map +1 -1
  208. package/dist/esm/interpreter/getNesting.mjs.map +1 -1
  209. package/dist/esm/interpreter/getPlural.mjs +1 -1
  210. package/dist/esm/interpreter/getPlural.mjs.map +1 -1
  211. package/dist/esm/interpreter/getTranslation.mjs.map +1 -1
  212. package/dist/esm/interpreter/splitAndJoinInsertion.mjs.map +1 -1
  213. package/dist/esm/localization/comparePaths.mjs.map +1 -1
  214. package/dist/esm/localization/domainUtils.mjs.map +1 -1
  215. package/dist/esm/localization/generateSitemap.mjs +2 -1
  216. package/dist/esm/localization/generateSitemap.mjs.map +1 -1
  217. package/dist/esm/localization/getBrowserLocale.mjs +7 -3
  218. package/dist/esm/localization/getBrowserLocale.mjs.map +1 -1
  219. package/dist/esm/localization/getHTMLTextDir.mjs.map +1 -1
  220. package/dist/esm/localization/getLocale.mjs.map +1 -1
  221. package/dist/esm/localization/getLocaleFromPath.mjs.map +1 -1
  222. package/dist/esm/localization/getLocaleLang.mjs.map +1 -1
  223. package/dist/esm/localization/getLocaleName.mjs.map +1 -1
  224. package/dist/esm/localization/getLocalizedUrl.mjs.map +1 -1
  225. package/dist/esm/localization/getMultilingualUrls.mjs.map +1 -1
  226. package/dist/esm/localization/getPathWithoutLocale.mjs.map +1 -1
  227. package/dist/esm/localization/getPrefix.mjs.map +1 -1
  228. package/dist/esm/localization/localeDetector.mjs +2 -1
  229. package/dist/esm/localization/localeDetector.mjs.map +1 -1
  230. package/dist/esm/localization/localeMapper.mjs.map +1 -1
  231. package/dist/esm/localization/localeResolver.mjs.map +1 -1
  232. package/dist/esm/localization/rewriteUtils.mjs +2 -1
  233. package/dist/esm/localization/rewriteUtils.mjs.map +1 -1
  234. package/dist/esm/localization/validatePrefix.mjs.map +1 -1
  235. package/dist/esm/markdown/compiler.mjs +2 -1
  236. package/dist/esm/markdown/compiler.mjs.map +1 -1
  237. package/dist/esm/markdown/constants.mjs.map +1 -1
  238. package/dist/esm/markdown/parser.mjs.map +1 -1
  239. package/dist/esm/markdown/renderer.mjs.map +1 -1
  240. package/dist/esm/markdown/utils.mjs.map +1 -1
  241. package/dist/esm/messageFormat/ICU.mjs +15 -9
  242. package/dist/esm/messageFormat/ICU.mjs.map +1 -1
  243. package/dist/esm/messageFormat/i18next.mjs +12 -7
  244. package/dist/esm/messageFormat/i18next.mjs.map +1 -1
  245. package/dist/esm/messageFormat/navigatePath.mjs.map +1 -1
  246. package/dist/esm/messageFormat/po.mjs.map +1 -1
  247. package/dist/esm/messageFormat/resolveMessage.mjs +11 -8
  248. package/dist/esm/messageFormat/resolveMessage.mjs.map +1 -1
  249. package/dist/esm/messageFormat/verify-icu-format.mjs.map +1 -1
  250. package/dist/esm/messageFormat/vue-i18n.mjs +2 -1
  251. package/dist/esm/messageFormat/vue-i18n.mjs.map +1 -1
  252. package/dist/esm/transpiler/condition/condition.mjs.map +1 -1
  253. package/dist/esm/transpiler/enumeration/enumeration.mjs.map +1 -1
  254. package/dist/esm/transpiler/file/file.mjs +2 -1
  255. package/dist/esm/transpiler/file/file.mjs.map +1 -1
  256. package/dist/esm/transpiler/file/fileBrowser.mjs.map +1 -1
  257. package/dist/esm/transpiler/gender/gender.mjs.map +1 -1
  258. package/dist/esm/transpiler/html/getHTMLCustomComponents.mjs.map +1 -1
  259. package/dist/esm/transpiler/html/html.mjs.map +1 -1
  260. package/dist/esm/transpiler/html/htmlTags.mjs.map +1 -1
  261. package/dist/esm/transpiler/html/validateHTML.mjs +1 -1
  262. package/dist/esm/transpiler/html/validateHTML.mjs.map +1 -1
  263. package/dist/esm/transpiler/insertion/getInsertionValues.mjs.map +1 -1
  264. package/dist/esm/transpiler/insertion/insertion.mjs.map +1 -1
  265. package/dist/esm/transpiler/markdown/getMarkdownMetadata.mjs.map +1 -1
  266. package/dist/esm/transpiler/markdown/markdown.mjs.map +1 -1
  267. package/dist/esm/transpiler/markdown/validateMarkdown.mjs.map +1 -1
  268. package/dist/esm/transpiler/nesting/nesting.mjs.map +1 -1
  269. package/dist/esm/transpiler/plural/plural.mjs.map +1 -1
  270. package/dist/esm/transpiler/translation/translation.mjs.map +1 -1
  271. package/dist/esm/utils/checkIsURLAbsolute.mjs.map +1 -1
  272. package/dist/esm/utils/cookieExpiry.mjs.map +1 -1
  273. package/dist/esm/utils/getCookie.mjs.map +1 -1
  274. package/dist/esm/utils/intl.mjs +100 -25
  275. package/dist/esm/utils/intl.mjs.map +1 -1
  276. package/dist/esm/utils/isSameKeyPath.mjs.map +1 -1
  277. package/dist/esm/utils/localeStorage.mjs.map +1 -1
  278. package/dist/esm/utils/parseYaml.mjs +1 -1
  279. package/dist/esm/utils/parseYaml.mjs.map +1 -1
  280. package/dist/esm/utils/stringifyYaml.mjs +1 -1
  281. package/dist/esm/utils/stringifyYaml.mjs.map +1 -1
  282. package/dist/types/deepTransformPlugins/getEditedContent.d.ts +0 -1
  283. package/dist/types/deepTransformPlugins/getEditedContent.d.ts.map +1 -1
  284. package/dist/types/deepTransformPlugins/getFilterMissingTranslationsContent.d.ts +12 -13
  285. package/dist/types/deepTransformPlugins/getFilterMissingTranslationsContent.d.ts.map +1 -1
  286. package/dist/types/deepTransformPlugins/getFilterTranslationsOnlyContent.d.ts +12 -13
  287. package/dist/types/deepTransformPlugins/getFilterTranslationsOnlyContent.d.ts.map +1 -1
  288. package/dist/types/deepTransformPlugins/getFilteredLocalesContent.d.ts +12 -13
  289. package/dist/types/deepTransformPlugins/getFilteredLocalesContent.d.ts.map +1 -1
  290. package/dist/types/deepTransformPlugins/getLocalizedContent.d.ts +1 -1
  291. package/dist/types/deepTransformPlugins/getLocalizedContent.d.ts.map +1 -1
  292. package/dist/types/deepTransformPlugins/getMaskContent.d.ts +1 -1
  293. package/dist/types/deepTransformPlugins/getMaskContent.d.ts.map +1 -1
  294. package/dist/types/deepTransformPlugins/getMissingLocalesContent.d.ts +1 -1
  295. package/dist/types/deepTransformPlugins/getMissingLocalesContent.d.ts.map +1 -1
  296. package/dist/types/deepTransformPlugins/getMultilingualDictionary.d.ts +0 -1
  297. package/dist/types/deepTransformPlugins/getMultilingualDictionary.d.ts.map +1 -1
  298. package/dist/types/deepTransformPlugins/getReplacedValuesContent.d.ts +1 -1
  299. package/dist/types/deepTransformPlugins/getReplacedValuesContent.d.ts.map +1 -1
  300. package/dist/types/deepTransformPlugins/getSplittedContent.d.ts +1 -2
  301. package/dist/types/deepTransformPlugins/getSplittedContent.d.ts.map +1 -1
  302. package/dist/types/deepTransformPlugins/insertContentInDictionary.d.ts +1 -2
  303. package/dist/types/deepTransformPlugins/insertContentInDictionary.d.ts.map +1 -1
  304. package/dist/types/dictionaryManipulator/editDictionaryByKeyPath.d.ts +0 -1
  305. package/dist/types/dictionaryManipulator/editDictionaryByKeyPath.d.ts.map +1 -1
  306. package/dist/types/dictionaryManipulator/getContentNodeByKeyPath.d.ts +0 -1
  307. package/dist/types/dictionaryManipulator/getContentNodeByKeyPath.d.ts.map +1 -1
  308. package/dist/types/dictionaryManipulator/getDefaultNode.d.ts +0 -1
  309. package/dist/types/dictionaryManipulator/getDefaultNode.d.ts.map +1 -1
  310. package/dist/types/dictionaryManipulator/getEmptyNode.d.ts +0 -1
  311. package/dist/types/dictionaryManipulator/getEmptyNode.d.ts.map +1 -1
  312. package/dist/types/dictionaryManipulator/getNodeChildren.d.ts +0 -1
  313. package/dist/types/dictionaryManipulator/getNodeChildren.d.ts.map +1 -1
  314. package/dist/types/dictionaryManipulator/getNodeType.d.ts +0 -1
  315. package/dist/types/dictionaryManipulator/getNodeType.d.ts.map +1 -1
  316. package/dist/types/dictionaryManipulator/mergeDictionaries.d.ts +0 -1
  317. package/dist/types/dictionaryManipulator/mergeDictionaries.d.ts.map +1 -1
  318. package/dist/types/dictionaryManipulator/mergeQualifiedDictionaries.d.ts +0 -1
  319. package/dist/types/dictionaryManipulator/mergeQualifiedDictionaries.d.ts.map +1 -1
  320. package/dist/types/dictionaryManipulator/normalizeDictionary.d.ts +0 -1
  321. package/dist/types/dictionaryManipulator/normalizeDictionary.d.ts.map +1 -1
  322. package/dist/types/dictionaryManipulator/orderDictionaries.d.ts +1 -2
  323. package/dist/types/dictionaryManipulator/orderDictionaries.d.ts.map +1 -1
  324. package/dist/types/dictionaryManipulator/qualifiedDictionary.d.ts +1 -2
  325. package/dist/types/dictionaryManipulator/qualifiedDictionary.d.ts.map +1 -1
  326. package/dist/types/dictionaryManipulator/removeContentNodeByKeyPath.d.ts +0 -1
  327. package/dist/types/dictionaryManipulator/removeContentNodeByKeyPath.d.ts.map +1 -1
  328. package/dist/types/dictionaryManipulator/renameContentNodeByKeyPath.d.ts +1 -2
  329. package/dist/types/dictionaryManipulator/renameContentNodeByKeyPath.d.ts.map +1 -1
  330. package/dist/types/dictionaryManipulator/updateNodeChildren.d.ts +0 -1
  331. package/dist/types/dictionaryManipulator/updateNodeChildren.d.ts.map +1 -1
  332. package/dist/types/formatters/compact.d.ts +0 -1
  333. package/dist/types/formatters/compact.d.ts.map +1 -1
  334. package/dist/types/formatters/currency.d.ts +0 -1
  335. package/dist/types/formatters/currency.d.ts.map +1 -1
  336. package/dist/types/formatters/date.d.ts +0 -1
  337. package/dist/types/formatters/date.d.ts.map +1 -1
  338. package/dist/types/formatters/index.d.ts +2 -2
  339. package/dist/types/formatters/list.d.ts +0 -1
  340. package/dist/types/formatters/list.d.ts.map +1 -1
  341. package/dist/types/formatters/number.d.ts +1 -5
  342. package/dist/types/formatters/number.d.ts.map +1 -1
  343. package/dist/types/formatters/percentage.d.ts +1 -5
  344. package/dist/types/formatters/percentage.d.ts.map +1 -1
  345. package/dist/types/formatters/relativeTime.d.ts +0 -1
  346. package/dist/types/formatters/relativeTime.d.ts.map +1 -1
  347. package/dist/types/formatters/units.d.ts +0 -1
  348. package/dist/types/formatters/units.d.ts.map +1 -1
  349. package/dist/types/index.d.ts +11 -2
  350. package/dist/types/interpreter/getCondition.d.ts +1 -0
  351. package/dist/types/interpreter/getCondition.d.ts.map +1 -1
  352. package/dist/types/interpreter/getContent/deepTransform.d.ts +0 -1
  353. package/dist/types/interpreter/getContent/deepTransform.d.ts.map +1 -1
  354. package/dist/types/interpreter/getContent/getContent.d.ts +0 -1
  355. package/dist/types/interpreter/getContent/getContent.d.ts.map +1 -1
  356. package/dist/types/interpreter/getContent/plugins.d.ts +4 -4
  357. package/dist/types/interpreter/getContent/plugins.d.ts.map +1 -1
  358. package/dist/types/interpreter/getDictionary.d.ts +1 -1
  359. package/dist/types/interpreter/getDictionary.d.ts.map +1 -1
  360. package/dist/types/interpreter/getEnumeration.d.ts +1 -0
  361. package/dist/types/interpreter/getEnumeration.d.ts.map +1 -1
  362. package/dist/types/interpreter/getGender.d.ts +1 -0
  363. package/dist/types/interpreter/getGender.d.ts.map +1 -1
  364. package/dist/types/interpreter/getHTML.d.ts.map +1 -1
  365. package/dist/types/interpreter/getInsertion.d.ts +2 -1
  366. package/dist/types/interpreter/getInsertion.d.ts.map +1 -1
  367. package/dist/types/interpreter/getIntlayer.d.ts +1 -1
  368. package/dist/types/interpreter/getIntlayer.d.ts.map +1 -1
  369. package/dist/types/interpreter/getNesting.d.ts +2 -1
  370. package/dist/types/interpreter/getNesting.d.ts.map +1 -1
  371. package/dist/types/interpreter/getPlural.d.ts +0 -1
  372. package/dist/types/interpreter/getPlural.d.ts.map +1 -1
  373. package/dist/types/interpreter/getTranslation.d.ts +0 -1
  374. package/dist/types/interpreter/getTranslation.d.ts.map +1 -1
  375. package/dist/types/interpreter/index.d.ts +1 -0
  376. package/dist/types/interpreter/splitAndJoinInsertion.d.ts.map +1 -1
  377. package/dist/types/localization/comparePaths.d.ts +0 -1
  378. package/dist/types/localization/comparePaths.d.ts.map +1 -1
  379. package/dist/types/localization/domainUtils.d.ts +0 -1
  380. package/dist/types/localization/domainUtils.d.ts.map +1 -1
  381. package/dist/types/localization/generateSitemap.d.ts +6 -4
  382. package/dist/types/localization/generateSitemap.d.ts.map +1 -1
  383. package/dist/types/localization/getBrowserLocale.d.ts +0 -1
  384. package/dist/types/localization/getBrowserLocale.d.ts.map +1 -1
  385. package/dist/types/localization/getHTMLTextDir.d.ts +0 -1
  386. package/dist/types/localization/getHTMLTextDir.d.ts.map +1 -1
  387. package/dist/types/localization/getLocale.d.ts +0 -1
  388. package/dist/types/localization/getLocale.d.ts.map +1 -1
  389. package/dist/types/localization/getLocaleFromPath.d.ts +0 -1
  390. package/dist/types/localization/getLocaleFromPath.d.ts.map +1 -1
  391. package/dist/types/localization/getLocaleLang.d.ts +0 -1
  392. package/dist/types/localization/getLocaleLang.d.ts.map +1 -1
  393. package/dist/types/localization/getLocaleName.d.ts +0 -1
  394. package/dist/types/localization/getLocaleName.d.ts.map +1 -1
  395. package/dist/types/localization/getLocalizedUrl.d.ts +0 -1
  396. package/dist/types/localization/getLocalizedUrl.d.ts.map +1 -1
  397. package/dist/types/localization/getMultilingualUrls.d.ts +0 -1
  398. package/dist/types/localization/getMultilingualUrls.d.ts.map +1 -1
  399. package/dist/types/localization/getPathWithoutLocale.d.ts +0 -1
  400. package/dist/types/localization/getPathWithoutLocale.d.ts.map +1 -1
  401. package/dist/types/localization/getPrefix.d.ts +2 -3
  402. package/dist/types/localization/getPrefix.d.ts.map +1 -1
  403. package/dist/types/localization/localeDetector.d.ts +0 -1
  404. package/dist/types/localization/localeDetector.d.ts.map +1 -1
  405. package/dist/types/localization/localeMapper.d.ts +3 -4
  406. package/dist/types/localization/localeMapper.d.ts.map +1 -1
  407. package/dist/types/localization/localeResolver.d.ts +0 -1
  408. package/dist/types/localization/localeResolver.d.ts.map +1 -1
  409. package/dist/types/localization/rewriteUtils.d.ts +2 -3
  410. package/dist/types/localization/rewriteUtils.d.ts.map +1 -1
  411. package/dist/types/localization/validatePrefix.d.ts +0 -1
  412. package/dist/types/localization/validatePrefix.d.ts.map +1 -1
  413. package/dist/types/markdown/compiler.d.ts +0 -1
  414. package/dist/types/markdown/compiler.d.ts.map +1 -1
  415. package/dist/types/markdown/constants.d.ts +48 -38
  416. package/dist/types/markdown/constants.d.ts.map +1 -1
  417. package/dist/types/markdown/index.d.ts +2 -1
  418. package/dist/types/markdown/parser.d.ts +0 -1
  419. package/dist/types/markdown/parser.d.ts.map +1 -1
  420. package/dist/types/markdown/renderer.d.ts +0 -1
  421. package/dist/types/markdown/renderer.d.ts.map +1 -1
  422. package/dist/types/markdown/types.d.ts +44 -24
  423. package/dist/types/markdown/types.d.ts.map +1 -1
  424. package/dist/types/markdown/utils.d.ts +3 -4
  425. package/dist/types/markdown/utils.d.ts.map +1 -1
  426. package/dist/types/messageFormat/ICU.d.ts +2 -3
  427. package/dist/types/messageFormat/ICU.d.ts.map +1 -1
  428. package/dist/types/messageFormat/i18next.d.ts +2 -3
  429. package/dist/types/messageFormat/i18next.d.ts.map +1 -1
  430. package/dist/types/messageFormat/navigatePath.d.ts.map +1 -1
  431. package/dist/types/messageFormat/po.d.ts +2 -3
  432. package/dist/types/messageFormat/po.d.ts.map +1 -1
  433. package/dist/types/messageFormat/resolveMessage.d.ts +0 -1
  434. package/dist/types/messageFormat/resolveMessage.d.ts.map +1 -1
  435. package/dist/types/messageFormat/verify-icu-format.d.ts +1 -1
  436. package/dist/types/messageFormat/vue-i18n.d.ts +2 -3
  437. package/dist/types/messageFormat/vue-i18n.d.ts.map +1 -1
  438. package/dist/types/transpiler/condition/condition.d.ts +0 -1
  439. package/dist/types/transpiler/condition/condition.d.ts.map +1 -1
  440. package/dist/types/transpiler/enumeration/enumeration.d.ts +0 -1
  441. package/dist/types/transpiler/enumeration/enumeration.d.ts.map +1 -1
  442. package/dist/types/transpiler/file/file.d.ts +0 -1
  443. package/dist/types/transpiler/file/file.d.ts.map +1 -1
  444. package/dist/types/transpiler/file/fileBrowser.d.ts +0 -1
  445. package/dist/types/transpiler/file/fileBrowser.d.ts.map +1 -1
  446. package/dist/types/transpiler/gender/gender.d.ts +0 -1
  447. package/dist/types/transpiler/gender/gender.d.ts.map +1 -1
  448. package/dist/types/transpiler/html/getHTMLCustomComponents.d.ts.map +1 -1
  449. package/dist/types/transpiler/html/html.d.ts +0 -1
  450. package/dist/types/transpiler/html/html.d.ts.map +1 -1
  451. package/dist/types/transpiler/html/htmlTags.d.ts +1 -1
  452. package/dist/types/transpiler/html/htmlTags.d.ts.map +1 -1
  453. package/dist/types/transpiler/html/validateHTML.d.ts.map +1 -1
  454. package/dist/types/transpiler/index.d.ts +11 -1
  455. package/dist/types/transpiler/insertion/getInsertionValues.d.ts.map +1 -1
  456. package/dist/types/transpiler/insertion/insertion.d.ts +0 -1
  457. package/dist/types/transpiler/insertion/insertion.d.ts.map +1 -1
  458. package/dist/types/transpiler/markdown/getMarkdownMetadata.d.ts.map +1 -1
  459. package/dist/types/transpiler/markdown/index.d.ts +1 -1
  460. package/dist/types/transpiler/markdown/markdown.d.ts +0 -1
  461. package/dist/types/transpiler/markdown/markdown.d.ts.map +1 -1
  462. package/dist/types/transpiler/markdown/validateMarkdown.d.ts +0 -1
  463. package/dist/types/transpiler/markdown/validateMarkdown.d.ts.map +1 -1
  464. package/dist/types/transpiler/nesting/nesting.d.ts +4 -4
  465. package/dist/types/transpiler/nesting/nesting.d.ts.map +1 -1
  466. package/dist/types/transpiler/plural/plural.d.ts +0 -1
  467. package/dist/types/transpiler/plural/plural.d.ts.map +1 -1
  468. package/dist/types/transpiler/translation/translation.d.ts +0 -1
  469. package/dist/types/transpiler/translation/translation.d.ts.map +1 -1
  470. package/dist/types/utils/checkIsURLAbsolute.d.ts.map +1 -1
  471. package/dist/types/utils/cookieExpiry.d.ts +1 -2
  472. package/dist/types/utils/cookieExpiry.d.ts.map +1 -1
  473. package/dist/types/utils/getCookie.d.ts.map +1 -1
  474. package/dist/types/utils/index.d.ts +2 -2
  475. package/dist/types/utils/intl.d.ts +49 -5
  476. package/dist/types/utils/intl.d.ts.map +1 -1
  477. package/dist/types/utils/isSameKeyPath.d.ts +0 -1
  478. package/dist/types/utils/isSameKeyPath.d.ts.map +1 -1
  479. package/dist/types/utils/isValidReactElement.d.ts.map +1 -1
  480. package/dist/types/utils/localeStorage.d.ts +1 -2
  481. package/dist/types/utils/localeStorage.d.ts.map +1 -1
  482. package/dist/types/utils/parseYaml.d.ts.map +1 -1
  483. package/dist/types/utils/stringifyYaml.d.ts.map +1 -1
  484. package/package.json +9 -9
@@ -176,18 +176,22 @@ const icuNodesToIntlayer = (nodes) => {
176
176
  else if (key === "few") newKey = "<=3";
177
177
  else if (key === "many") newKey = ">=4";
178
178
  else if (key === "other") newKey = "fallback";
179
- options[newKey] = icuNodesToIntlayer(val.map((v) => {
179
+ const replacedVal = val.map((v) => {
180
180
  if (typeof v === "string") return v.replace(/#/g, `{{${node.name}}}`);
181
181
  return v;
182
- }));
182
+ });
183
+ options[newKey] = icuNodesToIntlayer(replacedVal);
183
184
  }
184
185
  options.__intlayer_icu_var = node.name;
185
186
  return enumeration(options);
186
187
  } else {
187
- for (const [key, val] of Object.entries(node.options)) options[key] = icuNodesToIntlayer(val.map((v) => {
188
- if (typeof v === "string") return v.replace(/#/g, `{{${node.name}}}`);
189
- return v;
190
- }));
188
+ for (const [key, val] of Object.entries(node.options)) {
189
+ const replacedVal = val.map((v) => {
190
+ if (typeof v === "string") return v.replace(/#/g, `{{${node.name}}}`);
191
+ return v;
192
+ });
193
+ options[key] = icuNodesToIntlayer(replacedVal);
194
+ }
191
195
  return plural(options);
192
196
  }
193
197
  }
@@ -212,10 +216,11 @@ const icuNodesToIntlayer = (nodes) => {
212
216
  const options = {};
213
217
  for (const [key, val] of Object.entries(node.options)) {
214
218
  const newKey = key.startsWith("=") ? key.substring(1) : key === "other" ? "fallback" : key;
215
- options[newKey] = icuNodesToIntlayer(val.map((value) => {
219
+ const replacedVal = val.map((value) => {
216
220
  if (typeof value === "string") return value.replace(/#/g, `{{${node.name}}}`);
217
221
  return value;
218
- }));
222
+ });
223
+ options[newKey] = icuNodesToIntlayer(replacedVal);
219
224
  }
220
225
  options.__intlayer_icu_var = node.name;
221
226
  options.__intlayer_icu_ordinal = true;
@@ -228,7 +233,8 @@ const icuToIntlayerPlugin = {
228
233
  canHandle: (node) => typeof node === "string" && (node.includes("{") || node.includes("}") || /<[a-zA-Z0-9-]+[^>]*>/.test(node)),
229
234
  transform: (node) => {
230
235
  try {
231
- return icuNodesToIntlayer(parseICU(node));
236
+ const ast = parseICU(node);
237
+ return icuNodesToIntlayer(ast);
232
238
  } catch {
233
239
  return node;
234
240
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ICU.mjs","names":["insert","enu"],"sources":["../../../src/messageFormat/ICU.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/types/dictionary';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport { deepTransformNode } from '../interpreter';\nimport { enu, gender, html, insert, plural } from '../transpiler';\n\n/**\n * ICU MessageFormat Converter\n *\n * This module converts between ICU MessageFormat and Intlayer's internal format.\n *\n * IMPORTANT: Two different formats are used:\n *\n * 1. ICU MessageFormat (external format):\n * - Simple variables: {name}\n * - Formatted variables: {amount, number, currency}\n * - Plural: {count, plural, =0 {none} other {# items}}\n * - Select: {gender, select, male {He} female {She} other {They}}\n *\n * 2. Intlayer Internal Format:\n * - Simple variables: {{name}} (double braces for clarity and to distinguish from literal text)\n * - Formatted variables: {amount, number, currency} (keeps ICU format)\n * - Plural: enu({ 0: 'none', fallback: '{{count}} items' })\n * - Select/Gender: gender({ male: 'He', female: 'She', fallback: 'They' })\n *\n * Conversion flow:\n * - ICU → Intlayer: {name} → {{name}}\n * - Intlayer → ICU: {{name}} → {name}\n *\n * The double braces in Intlayer format serve to:\n * - Distinguish variables from literal text containing braces\n * - Work with getInsertion() runtime function which expects {{var}} patterns\n * - Provide clear visual distinction in content dictionaries\n */\n\n// Types for our AST\ntype ICUNode =\n | string\n | {\n type: 'argument';\n name: string;\n format?: { type: string; style?: string };\n }\n | { type: 'plural'; name: string; options: Record<string, ICUNode[]> }\n | { type: 'select'; name: string; options: Record<string, ICUNode[]> }\n | {\n type: 'selectordinal';\n name: string;\n options: Record<string, ICUNode[]>;\n };\n\nexport type JsonValue =\n | string\n | number\n | boolean\n | null\n | JsonValue[]\n | { [key: string]: JsonValue };\n\nconst parseICU = (text: string): ICUNode[] => {\n let index = 0;\n\n const parseNodes = (): ICUNode[] => {\n const nodes: ICUNode[] = [];\n let currentText = '';\n\n while (index < text.length) {\n const char = text[index];\n\n if (char === '{') {\n if (currentText) {\n nodes.push(currentText);\n currentText = '';\n }\n index++; // skip {\n nodes.push(parseArgument());\n } else if (char === '}') {\n // End of current block\n break;\n } else if (char === \"'\") {\n // Escaping\n if (index + 1 < text.length && text[index + 1] === \"'\") {\n currentText += \"'\";\n index += 2;\n } else {\n // Find next quote\n const nextQuote = text.indexOf(\"'\", index + 1);\n if (nextQuote !== -1) {\n // Determine if this is escaping syntax characters\n // For simplicity, we'll treat content between single quotes as literal\n // provided it contains syntax chars.\n // Standard ICU: ' quoted string '\n // If it is just an apostrophe, it should be doubled.\n // But simplified: take content between quotes literally.\n currentText += text.substring(index + 1, nextQuote);\n index = nextQuote + 1;\n } else {\n currentText += \"'\";\n index++;\n }\n }\n } else {\n currentText += char;\n index++;\n }\n }\n\n if (currentText) {\n nodes.push(currentText);\n }\n return nodes;\n };\n\n const parseArgument = (): ICUNode => {\n // We are past '{'\n // Parse name\n let name = '';\n while (index < text.length && /[^,}]/.test(text[index])) {\n name += text[index];\n index++;\n }\n name = name.trim();\n\n if (index >= text.length) throw new Error('Unclosed argument');\n\n if (text[index] === '}') {\n index++;\n return { type: 'argument', name };\n }\n\n // Must be comma\n if (text[index] === ',') {\n index++;\n // Parse type\n let type = '';\n while (index < text.length && /[^,}]/.test(text[index])) {\n type += text[index];\n index++;\n }\n type = type.trim();\n\n if (index >= text.length) throw new Error('Unclosed argument');\n\n if (text[index] === '}') {\n index++;\n return { type: 'argument', name, format: { type } };\n }\n\n if (text[index] === ',') {\n index++;\n\n // If plural, select or selectordinal, parse options\n if (\n type === 'plural' ||\n type === 'select' ||\n type === 'selectordinal'\n ) {\n // Parse options\n const options: Record<string, ICUNode[]> = {};\n\n while (index < text.length && text[index] !== '}') {\n // skip whitespace\n while (index < text.length && /\\s/.test(text[index])) index++;\n\n // parse key\n let key = '';\n while (index < text.length && /[^{\\s]/.test(text[index])) {\n key += text[index];\n index++;\n }\n\n while (index < text.length && /\\s/.test(text[index])) index++;\n\n if (text[index] !== '{')\n throw new Error('Expected { after option key');\n index++; // skip {\n\n const value = parseNodes();\n\n if (text[index] !== '}')\n throw new Error('Expected } after option value');\n index++; // skip }\n\n options[key] = value;\n\n while (index < text.length && /\\s/.test(text[index])) index++;\n }\n\n index++; // skip closing argument }\n\n if (type === 'plural') {\n return { type: 'plural', name, options };\n } else if (type === 'select') {\n return { type: 'select', name, options };\n } else if (type === 'selectordinal') {\n return { type: 'selectordinal', name, options };\n }\n } else {\n // Parse style for number/date/time\n let style = '';\n while (index < text.length && text[index] !== '}') {\n style += text[index];\n index++;\n }\n if (index >= text.length) throw new Error('Unclosed argument');\n\n style = style.trim();\n index++; // skip }\n\n return { type: 'argument', name, format: { type, style } };\n }\n }\n }\n\n throw new Error('Malformed argument');\n };\n\n return parseNodes();\n};\n\nconst icuNodesToIntlayer = (nodes: ICUNode[]): any => {\n if (nodes.length === 0) return '';\n if (nodes.length === 1 && typeof nodes[0] === 'string') {\n const node = nodes[0];\n if (/<[a-zA-Z0-9-]+[^>]*>/.test(node)) {\n return html(node);\n }\n return node;\n }\n\n // Check if we can flatten to a single string (insert)\n const canFlatten = nodes.every(\n (node) => typeof node === 'string' || node.type === 'argument'\n );\n if (canFlatten) {\n let str = '';\n for (const node of nodes) {\n if (typeof node === 'string') {\n str += node;\n } else if (typeof node !== 'string' && node.type === 'argument') {\n if (node.format) {\n // Formatted variables keep ICU format: {var, type, style}\n str += `{${node.name}, ${node.format.type}${\n node.format.style ? `, ${node.format.style}` : ''\n }}`;\n } else {\n // Simple variables use Intlayer format: {{var}}\n str += `{{${node.name}}}`;\n }\n }\n }\n if (/<[a-zA-Z0-9-]+[^>]*>/.test(str)) {\n return html(str);\n }\n return insert(str);\n }\n\n // Mix of string and complex types.\n // If we have just one complex type and it covers everything?\n if (nodes.length === 1) {\n const node = nodes[0];\n\n if (typeof node === 'string') {\n if (/<[a-zA-Z0-9-]+[^>]*>/.test(node)) {\n return html(node);\n }\n return node;\n }\n if (node.type === 'argument') {\n if (node.format) {\n return insert(\n `{${node.name}, ${node.format.type}${\n node.format.style ? `, ${node.format.style}` : ''\n }}`\n );\n }\n return insert(`{{${node.name}}}`);\n }\n if (node.type === 'plural') {\n const options: Record<string, any> = {};\n let hasExactMatch = false;\n\n for (const key of Object.keys(node.options)) {\n if (key.startsWith('=')) {\n hasExactMatch = true;\n break;\n }\n }\n\n if (hasExactMatch) {\n for (const [key, val] of Object.entries(node.options)) {\n // Map ICU keys to Intlayer keys\n let newKey = key;\n if (key.startsWith('=')) {\n newKey = key.substring(1); // =0 -> 0\n } else if (key === 'one') {\n newKey = '1';\n } else if (key === 'two') {\n newKey = '2';\n } else if (key === 'few') {\n newKey = '<=3';\n } else if (key === 'many') {\n newKey = '>=4';\n } else if (key === 'other') {\n newKey = 'fallback';\n }\n // Handle # in plural value\n // For plural, we need to pass the variable name down or replace #\n // Intlayer uses {{n}} (or whatever var name) for simple variables\n // We should replace # with {{n}} in the string parts of val\n const replacedVal = val.map((v) => {\n if (typeof v === 'string') {\n return v.replace(/#/g, `{{${node.name}}}`);\n }\n return v;\n });\n\n options[newKey] = icuNodesToIntlayer(replacedVal);\n }\n\n // Preserve variable name\n options.__intlayer_icu_var = node.name;\n\n return enu(options);\n } else {\n for (const [key, val] of Object.entries(node.options)) {\n // Handle # in plural value\n const replacedVal = val.map((v) => {\n if (typeof v === 'string') {\n return v.replace(/#/g, `{{${node.name}}}`);\n }\n return v;\n });\n\n options[key] = icuNodesToIntlayer(replacedVal);\n }\n\n return plural(options as any);\n }\n }\n if (node.type === 'select') {\n const options: Record<string, any> = {};\n\n for (const [key, val] of Object.entries(node.options)) {\n options[key] = icuNodesToIntlayer(val);\n }\n\n // Check if it looks like gender\n const optionKeys = Object.keys(options);\n // It is gender if it has 'male' OR 'female' AND only contains gender keys (male, female, other)\n const isGender =\n (options.male || options.female) &&\n optionKeys.every((k) =>\n ['male', 'female', 'other', 'fallback'].includes(k)\n );\n\n if (isGender) {\n return gender({\n fallback: options.other,\n male: options.male,\n female: options.female,\n });\n }\n\n // Preserve variable name\n options.__intlayer_icu_var = node.name;\n\n return enu(options);\n }\n\n if (node.type === 'selectordinal') {\n // Ordinal plural ({n, selectordinal, one {#st} two {#nd} other {#th}}).\n // Stored as an enumeration with the ordinal marker: exact matches keep\n // numeric keys, CLDR ordinal categories keep their names, and the\n // runtime selects via `Intl.PluralRules(locale, { type: 'ordinal' })`.\n const options: Record<string, any> = {};\n\n for (const [key, val] of Object.entries(node.options)) {\n const newKey = key.startsWith('=')\n ? key.substring(1)\n : key === 'other'\n ? 'fallback'\n : key;\n\n const replacedVal = val.map((value) => {\n if (typeof value === 'string') {\n return value.replace(/#/g, `{{${node.name}}}`);\n }\n return value;\n });\n\n options[newKey] = icuNodesToIntlayer(replacedVal);\n }\n\n options.__intlayer_icu_var = node.name;\n options.__intlayer_icu_ordinal = true;\n\n return enu(options);\n }\n }\n\n // If multiple nodes, return array\n return nodes.map((node) => icuNodesToIntlayer([node]));\n};\n\nconst icuToIntlayerPlugin = {\n canHandle: (node: any) =>\n typeof node === 'string' &&\n (node.includes('{') ||\n node.includes('}') ||\n /<[a-zA-Z0-9-]+[^>]*>/.test(node)),\n transform: (node: any) => {\n try {\n const ast = parseICU(node);\n return icuNodesToIntlayer(ast);\n } catch {\n // If parsing fails, return original string\n return node;\n }\n },\n};\n\nconst intlayerToIcuPlugin = {\n canHandle: (node: any) => {\n if (\n typeof node === 'string' &&\n (node.includes('{') || node.includes('}'))\n ) {\n return true;\n }\n\n if (\n node &&\n typeof node === 'object' &&\n (node.nodeType === NodeTypes.INSERTION ||\n node.nodeType === NodeTypes.HTML ||\n node.nodeType === NodeTypes.ENUMERATION ||\n node.nodeType === NodeTypes.PLURAL ||\n node.nodeType === NodeTypes.GENDER ||\n node.nodeType === 'composite')\n ) {\n return true;\n }\n\n if (Array.isArray(node)) {\n if (node.length === 0) return false;\n\n let hasNode = false;\n let hasPlainObjectOrArray = false;\n\n for (const item of node) {\n if (typeof item === 'string') {\n } else if (\n item &&\n typeof item === 'object' &&\n (item.nodeType === NodeTypes.INSERTION ||\n item.nodeType === NodeTypes.HTML ||\n item.nodeType === NodeTypes.ENUMERATION ||\n item.nodeType === NodeTypes.GENDER ||\n item.nodeType === 'composite')\n ) {\n hasNode = true;\n } else {\n hasPlainObjectOrArray = true;\n }\n }\n\n // If it contains plain objects or nested arrays, it's a structural array\n if (hasPlainObjectOrArray) return false;\n // If it contains ONLY strings, it's a structural array, not a composite string\n if (!hasNode) return false;\n\n return true;\n }\n\n return false;\n },\n transform: (node: any, props: any, next: any) => {\n // Convert Intlayer's double-brace format {{var}} to ICU's single-brace format {var}\n if (typeof node === 'string') {\n return node.replace(/\\{\\{([^}]+)\\}\\}/g, '{$1}');\n }\n\n if (node.nodeType === NodeTypes.INSERTION) {\n return node[NodeTypes.INSERTION].replace(/\\{\\{([^}]+)\\}\\}/g, '{$1}');\n }\n\n if (node.nodeType === NodeTypes.HTML) {\n return node[NodeTypes.HTML];\n }\n\n if (node.nodeType === NodeTypes.PLURAL) {\n const options = node[NodeTypes.PLURAL];\n\n const transformedOptions: Record<string, string> = {};\n for (const [key, val] of Object.entries(options)) {\n const childVal = next(val, props);\n transformedOptions[key] =\n typeof childVal === 'string' ? childVal : JSON.stringify(childVal);\n }\n\n let varName = 'count';\n\n const fallbackVal =\n transformedOptions.other || Object.values(transformedOptions)[0];\n\n if (fallbackVal) {\n const match = fallbackVal.match(/\\{([a-zA-Z0-9_]+)\\}(?!,)/);\n if (match) {\n varName = match[1];\n }\n }\n\n const parts = [];\n\n for (const [key, val] of Object.entries(transformedOptions)) {\n let strVal = val;\n strVal = strVal.replace(new RegExp(`\\\\{${varName}\\\\}`, 'g'), '#');\n parts.push(`${key} {${strVal}}`);\n }\n return `{${varName}, plural, ${parts.join(' ')}}`;\n }\n\n if (node.nodeType === NodeTypes.ENUMERATION) {\n const options = node[NodeTypes.ENUMERATION];\n\n const transformedOptions: Record<string, string> = {};\n for (const [key, val] of Object.entries(options)) {\n if (key === '__intlayer_icu_var' || key === '__intlayer_icu_ordinal')\n continue;\n const childVal = next(val, props);\n transformedOptions[key] =\n typeof childVal === 'string' ? childVal : JSON.stringify(childVal);\n }\n\n let varName = options.__intlayer_icu_var || 'n';\n\n if (!options.__intlayer_icu_var) {\n const fallbackVal =\n transformedOptions.fallback ||\n transformedOptions.other ||\n Object.values(transformedOptions)[0];\n const match = fallbackVal.match(/\\{([a-zA-Z0-9_]+)\\}(?!,)/);\n if (match) {\n varName = match[1];\n }\n }\n\n // Ordinal enumerations round-trip back to `selectordinal`\n if (options.__intlayer_icu_ordinal === true) {\n const ordinalParts = [];\n\n for (const [key, val] of Object.entries(transformedOptions)) {\n let icuKey = key;\n if (key === 'fallback') icuKey = 'other';\n else if (/^\\d+$/.test(key)) icuKey = `=${key}`;\n\n let strVal = val;\n strVal = strVal.replace(new RegExp(`\\\\{${varName}\\\\}`, 'g'), '#');\n ordinalParts.push(`${icuKey} {${strVal}}`);\n }\n\n return `{${varName}, selectordinal, ${ordinalParts.join(' ')}}`;\n }\n\n const keys = Object.keys(transformedOptions);\n const pluralKeys = [\n '1',\n '2',\n '<=3',\n '>=4',\n 'fallback',\n 'other',\n 'zero',\n 'one',\n 'two',\n 'few',\n 'many',\n ];\n\n const isPlural = keys.every(\n (k) => pluralKeys.includes(k) || /^[<>=]?\\d+(\\.\\d+)?$/.test(k)\n );\n\n const parts = [];\n\n if (isPlural) {\n for (const [key, val] of Object.entries(transformedOptions)) {\n let icuKey = key;\n if (key === 'fallback') icuKey = 'other';\n else if (key === '<=3') icuKey = 'few';\n else if (key === '>=4') icuKey = 'many';\n else if (/^\\d+$/.test(key)) icuKey = `=${key}`;\n else if (['zero', 'few', 'many'].includes(key)) icuKey = key;\n else icuKey = 'other';\n\n let strVal = val;\n strVal = strVal.replace(new RegExp(`\\\\{${varName}\\\\}`, 'g'), '#');\n parts.push(`${icuKey} {${strVal}}`);\n }\n return `{${varName}, plural, ${parts.join(' ')}}`;\n } else {\n const entries = Object.entries(transformedOptions).sort(\n ([keyA], [keyB]) => {\n if (keyA === 'fallback' || keyA === 'other') return 1;\n if (keyB === 'fallback' || keyB === 'other') return -1;\n return 0;\n }\n );\n\n for (const [key, val] of entries) {\n let icuKey = key;\n if (key === 'fallback') icuKey = 'other';\n parts.push(`${icuKey} {${val}}`);\n }\n return `{${varName}, select, ${parts.join(' ')}}`;\n }\n }\n\n if (node.nodeType === NodeTypes.GENDER) {\n const options = node[NodeTypes.GENDER];\n const varName = 'gender';\n const parts = [];\n\n const entries = Object.entries(options).sort(([keyA], [keyB]) => {\n if (keyA === 'fallback') return 1;\n if (keyB === 'fallback') return -1;\n return 0;\n });\n\n for (const [key, val] of entries) {\n let icuKey = key;\n if (key === 'fallback') icuKey = 'other';\n\n const childVal = next(val, props);\n const strVal =\n typeof childVal === 'string' ? childVal : JSON.stringify(childVal);\n\n parts.push(`${icuKey} {${strVal}}`);\n }\n return `{${varName}, select, ${parts.join(' ')}}`;\n }\n\n if (\n Array.isArray(node) ||\n (node.nodeType === 'composite' && Array.isArray(node.composite))\n ) {\n // handle array/composite strings that passed canHandle\n const arr = Array.isArray(node) ? node : node.composite;\n const items = arr.map((item: any) => next(item, props));\n return items.join('');\n }\n\n return next(node, props);\n },\n};\n\nexport const intlayerToICUFormatter = (\n message: Dictionary['content']\n): JsonValue => {\n return deepTransformNode(message, {\n dictionaryKey: 'icu',\n keyPath: [],\n plugins: [{ id: 'icu', ...intlayerToIcuPlugin }],\n });\n};\n\nexport const icuToIntlayerFormatter = (\n message: Dictionary['content']\n): JsonValue => {\n return deepTransformNode(message, {\n dictionaryKey: 'icu',\n keyPath: [],\n plugins: [{ id: 'icu', ...icuToIntlayerPlugin }],\n });\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"ICU.mjs","names":["insert","enu"],"sources":["../../../src/messageFormat/ICU.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/types/dictionary';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport { deepTransformNode } from '../interpreter';\nimport { enu, gender, html, insert, plural } from '../transpiler';\n\n/**\n * ICU MessageFormat Converter\n *\n * This module converts between ICU MessageFormat and Intlayer's internal format.\n *\n * IMPORTANT: Two different formats are used:\n *\n * 1. ICU MessageFormat (external format):\n * - Simple variables: {name}\n * - Formatted variables: {amount, number, currency}\n * - Plural: {count, plural, =0 {none} other {# items}}\n * - Select: {gender, select, male {He} female {She} other {They}}\n *\n * 2. Intlayer Internal Format:\n * - Simple variables: {{name}} (double braces for clarity and to distinguish from literal text)\n * - Formatted variables: {amount, number, currency} (keeps ICU format)\n * - Plural: enu({ 0: 'none', fallback: '{{count}} items' })\n * - Select/Gender: gender({ male: 'He', female: 'She', fallback: 'They' })\n *\n * Conversion flow:\n * - ICU → Intlayer: {name} → {{name}}\n * - Intlayer → ICU: {{name}} → {name}\n *\n * The double braces in Intlayer format serve to:\n * - Distinguish variables from literal text containing braces\n * - Work with getInsertion() runtime function which expects {{var}} patterns\n * - Provide clear visual distinction in content dictionaries\n */\n\n// Types for our AST\ntype ICUNode =\n | string\n | {\n type: 'argument';\n name: string;\n format?: { type: string; style?: string };\n }\n | { type: 'plural'; name: string; options: Record<string, ICUNode[]> }\n | { type: 'select'; name: string; options: Record<string, ICUNode[]> }\n | {\n type: 'selectordinal';\n name: string;\n options: Record<string, ICUNode[]>;\n };\n\nexport type JsonValue =\n | string\n | number\n | boolean\n | null\n | JsonValue[]\n | { [key: string]: JsonValue };\n\nconst parseICU = (text: string): ICUNode[] => {\n let index = 0;\n\n const parseNodes = (): ICUNode[] => {\n const nodes: ICUNode[] = [];\n let currentText = '';\n\n while (index < text.length) {\n const char = text[index];\n\n if (char === '{') {\n if (currentText) {\n nodes.push(currentText);\n currentText = '';\n }\n index++; // skip {\n nodes.push(parseArgument());\n } else if (char === '}') {\n // End of current block\n break;\n } else if (char === \"'\") {\n // Escaping\n if (index + 1 < text.length && text[index + 1] === \"'\") {\n currentText += \"'\";\n index += 2;\n } else {\n // Find next quote\n const nextQuote = text.indexOf(\"'\", index + 1);\n if (nextQuote !== -1) {\n // Determine if this is escaping syntax characters\n // For simplicity, we'll treat content between single quotes as literal\n // provided it contains syntax chars.\n // Standard ICU: ' quoted string '\n // If it is just an apostrophe, it should be doubled.\n // But simplified: take content between quotes literally.\n currentText += text.substring(index + 1, nextQuote);\n index = nextQuote + 1;\n } else {\n currentText += \"'\";\n index++;\n }\n }\n } else {\n currentText += char;\n index++;\n }\n }\n\n if (currentText) {\n nodes.push(currentText);\n }\n return nodes;\n };\n\n const parseArgument = (): ICUNode => {\n // We are past '{'\n // Parse name\n let name = '';\n while (index < text.length && /[^,}]/.test(text[index])) {\n name += text[index];\n index++;\n }\n name = name.trim();\n\n if (index >= text.length) throw new Error('Unclosed argument');\n\n if (text[index] === '}') {\n index++;\n return { type: 'argument', name };\n }\n\n // Must be comma\n if (text[index] === ',') {\n index++;\n // Parse type\n let type = '';\n while (index < text.length && /[^,}]/.test(text[index])) {\n type += text[index];\n index++;\n }\n type = type.trim();\n\n if (index >= text.length) throw new Error('Unclosed argument');\n\n if (text[index] === '}') {\n index++;\n return { type: 'argument', name, format: { type } };\n }\n\n if (text[index] === ',') {\n index++;\n\n // If plural, select or selectordinal, parse options\n if (\n type === 'plural' ||\n type === 'select' ||\n type === 'selectordinal'\n ) {\n // Parse options\n const options: Record<string, ICUNode[]> = {};\n\n while (index < text.length && text[index] !== '}') {\n // skip whitespace\n while (index < text.length && /\\s/.test(text[index])) index++;\n\n // parse key\n let key = '';\n while (index < text.length && /[^{\\s]/.test(text[index])) {\n key += text[index];\n index++;\n }\n\n while (index < text.length && /\\s/.test(text[index])) index++;\n\n if (text[index] !== '{')\n throw new Error('Expected { after option key');\n index++; // skip {\n\n const value = parseNodes();\n\n if (text[index] !== '}')\n throw new Error('Expected } after option value');\n index++; // skip }\n\n options[key] = value;\n\n while (index < text.length && /\\s/.test(text[index])) index++;\n }\n\n index++; // skip closing argument }\n\n if (type === 'plural') {\n return { type: 'plural', name, options };\n } else if (type === 'select') {\n return { type: 'select', name, options };\n } else if (type === 'selectordinal') {\n return { type: 'selectordinal', name, options };\n }\n } else {\n // Parse style for number/date/time\n let style = '';\n while (index < text.length && text[index] !== '}') {\n style += text[index];\n index++;\n }\n if (index >= text.length) throw new Error('Unclosed argument');\n\n style = style.trim();\n index++; // skip }\n\n return { type: 'argument', name, format: { type, style } };\n }\n }\n }\n\n throw new Error('Malformed argument');\n };\n\n return parseNodes();\n};\n\nconst icuNodesToIntlayer = (nodes: ICUNode[]): any => {\n if (nodes.length === 0) return '';\n if (nodes.length === 1 && typeof nodes[0] === 'string') {\n const node = nodes[0];\n if (/<[a-zA-Z0-9-]+[^>]*>/.test(node)) {\n return html(node);\n }\n return node;\n }\n\n // Check if we can flatten to a single string (insert)\n const canFlatten = nodes.every(\n (node) => typeof node === 'string' || node.type === 'argument'\n );\n if (canFlatten) {\n let str = '';\n for (const node of nodes) {\n if (typeof node === 'string') {\n str += node;\n } else if (typeof node !== 'string' && node.type === 'argument') {\n if (node.format) {\n // Formatted variables keep ICU format: {var, type, style}\n str += `{${node.name}, ${node.format.type}${\n node.format.style ? `, ${node.format.style}` : ''\n }}`;\n } else {\n // Simple variables use Intlayer format: {{var}}\n str += `{{${node.name}}}`;\n }\n }\n }\n if (/<[a-zA-Z0-9-]+[^>]*>/.test(str)) {\n return html(str);\n }\n return insert(str);\n }\n\n // Mix of string and complex types.\n // If we have just one complex type and it covers everything?\n if (nodes.length === 1) {\n const node = nodes[0];\n\n if (typeof node === 'string') {\n if (/<[a-zA-Z0-9-]+[^>]*>/.test(node)) {\n return html(node);\n }\n return node;\n }\n if (node.type === 'argument') {\n if (node.format) {\n return insert(\n `{${node.name}, ${node.format.type}${\n node.format.style ? `, ${node.format.style}` : ''\n }}`\n );\n }\n return insert(`{{${node.name}}}`);\n }\n if (node.type === 'plural') {\n const options: Record<string, any> = {};\n let hasExactMatch = false;\n\n for (const key of Object.keys(node.options)) {\n if (key.startsWith('=')) {\n hasExactMatch = true;\n break;\n }\n }\n\n if (hasExactMatch) {\n for (const [key, val] of Object.entries(node.options)) {\n // Map ICU keys to Intlayer keys\n let newKey = key;\n if (key.startsWith('=')) {\n newKey = key.substring(1); // =0 -> 0\n } else if (key === 'one') {\n newKey = '1';\n } else if (key === 'two') {\n newKey = '2';\n } else if (key === 'few') {\n newKey = '<=3';\n } else if (key === 'many') {\n newKey = '>=4';\n } else if (key === 'other') {\n newKey = 'fallback';\n }\n // Handle # in plural value\n // For plural, we need to pass the variable name down or replace #\n // Intlayer uses {{n}} (or whatever var name) for simple variables\n // We should replace # with {{n}} in the string parts of val\n const replacedVal = val.map((v) => {\n if (typeof v === 'string') {\n return v.replace(/#/g, `{{${node.name}}}`);\n }\n return v;\n });\n\n options[newKey] = icuNodesToIntlayer(replacedVal);\n }\n\n // Preserve variable name\n options.__intlayer_icu_var = node.name;\n\n return enu(options);\n } else {\n for (const [key, val] of Object.entries(node.options)) {\n // Handle # in plural value\n const replacedVal = val.map((v) => {\n if (typeof v === 'string') {\n return v.replace(/#/g, `{{${node.name}}}`);\n }\n return v;\n });\n\n options[key] = icuNodesToIntlayer(replacedVal);\n }\n\n return plural(options as any);\n }\n }\n if (node.type === 'select') {\n const options: Record<string, any> = {};\n\n for (const [key, val] of Object.entries(node.options)) {\n options[key] = icuNodesToIntlayer(val);\n }\n\n // Check if it looks like gender\n const optionKeys = Object.keys(options);\n // It is gender if it has 'male' OR 'female' AND only contains gender keys (male, female, other)\n const isGender =\n (options.male || options.female) &&\n optionKeys.every((k) =>\n ['male', 'female', 'other', 'fallback'].includes(k)\n );\n\n if (isGender) {\n return gender({\n fallback: options.other,\n male: options.male,\n female: options.female,\n });\n }\n\n // Preserve variable name\n options.__intlayer_icu_var = node.name;\n\n return enu(options);\n }\n\n if (node.type === 'selectordinal') {\n // Ordinal plural ({n, selectordinal, one {#st} two {#nd} other {#th}}).\n // Stored as an enumeration with the ordinal marker: exact matches keep\n // numeric keys, CLDR ordinal categories keep their names, and the\n // runtime selects via `Intl.PluralRules(locale, { type: 'ordinal' })`.\n const options: Record<string, any> = {};\n\n for (const [key, val] of Object.entries(node.options)) {\n const newKey = key.startsWith('=')\n ? key.substring(1)\n : key === 'other'\n ? 'fallback'\n : key;\n\n const replacedVal = val.map((value) => {\n if (typeof value === 'string') {\n return value.replace(/#/g, `{{${node.name}}}`);\n }\n return value;\n });\n\n options[newKey] = icuNodesToIntlayer(replacedVal);\n }\n\n options.__intlayer_icu_var = node.name;\n options.__intlayer_icu_ordinal = true;\n\n return enu(options);\n }\n }\n\n // If multiple nodes, return array\n return nodes.map((node) => icuNodesToIntlayer([node]));\n};\n\nconst icuToIntlayerPlugin = {\n canHandle: (node: any) =>\n typeof node === 'string' &&\n (node.includes('{') ||\n node.includes('}') ||\n /<[a-zA-Z0-9-]+[^>]*>/.test(node)),\n transform: (node: any) => {\n try {\n const ast = parseICU(node);\n return icuNodesToIntlayer(ast);\n } catch {\n // If parsing fails, return original string\n return node;\n }\n },\n};\n\nconst intlayerToIcuPlugin = {\n canHandle: (node: any) => {\n if (\n typeof node === 'string' &&\n (node.includes('{') || node.includes('}'))\n ) {\n return true;\n }\n\n if (\n node &&\n typeof node === 'object' &&\n (node.nodeType === NodeTypes.INSERTION ||\n node.nodeType === NodeTypes.HTML ||\n node.nodeType === NodeTypes.ENUMERATION ||\n node.nodeType === NodeTypes.PLURAL ||\n node.nodeType === NodeTypes.GENDER ||\n node.nodeType === 'composite')\n ) {\n return true;\n }\n\n if (Array.isArray(node)) {\n if (node.length === 0) return false;\n\n let hasNode = false;\n let hasPlainObjectOrArray = false;\n\n for (const item of node) {\n if (typeof item === 'string') {\n } else if (\n item &&\n typeof item === 'object' &&\n (item.nodeType === NodeTypes.INSERTION ||\n item.nodeType === NodeTypes.HTML ||\n item.nodeType === NodeTypes.ENUMERATION ||\n item.nodeType === NodeTypes.GENDER ||\n item.nodeType === 'composite')\n ) {\n hasNode = true;\n } else {\n hasPlainObjectOrArray = true;\n }\n }\n\n // If it contains plain objects or nested arrays, it's a structural array\n if (hasPlainObjectOrArray) return false;\n // If it contains ONLY strings, it's a structural array, not a composite string\n if (!hasNode) return false;\n\n return true;\n }\n\n return false;\n },\n transform: (node: any, props: any, next: any) => {\n // Convert Intlayer's double-brace format {{var}} to ICU's single-brace format {var}\n if (typeof node === 'string') {\n return node.replace(/\\{\\{([^}]+)\\}\\}/g, '{$1}');\n }\n\n if (node.nodeType === NodeTypes.INSERTION) {\n return node[NodeTypes.INSERTION].replace(/\\{\\{([^}]+)\\}\\}/g, '{$1}');\n }\n\n if (node.nodeType === NodeTypes.HTML) {\n return node[NodeTypes.HTML];\n }\n\n if (node.nodeType === NodeTypes.PLURAL) {\n const options = node[NodeTypes.PLURAL];\n\n const transformedOptions: Record<string, string> = {};\n for (const [key, val] of Object.entries(options)) {\n const childVal = next(val, props);\n transformedOptions[key] =\n typeof childVal === 'string' ? childVal : JSON.stringify(childVal);\n }\n\n let varName = 'count';\n\n const fallbackVal =\n transformedOptions.other || Object.values(transformedOptions)[0];\n\n if (fallbackVal) {\n const match = fallbackVal.match(/\\{([a-zA-Z0-9_]+)\\}(?!,)/);\n if (match) {\n varName = match[1];\n }\n }\n\n const parts = [];\n\n for (const [key, val] of Object.entries(transformedOptions)) {\n let strVal = val;\n strVal = strVal.replace(new RegExp(`\\\\{${varName}\\\\}`, 'g'), '#');\n parts.push(`${key} {${strVal}}`);\n }\n return `{${varName}, plural, ${parts.join(' ')}}`;\n }\n\n if (node.nodeType === NodeTypes.ENUMERATION) {\n const options = node[NodeTypes.ENUMERATION];\n\n const transformedOptions: Record<string, string> = {};\n for (const [key, val] of Object.entries(options)) {\n if (key === '__intlayer_icu_var' || key === '__intlayer_icu_ordinal')\n continue;\n const childVal = next(val, props);\n transformedOptions[key] =\n typeof childVal === 'string' ? childVal : JSON.stringify(childVal);\n }\n\n let varName = options.__intlayer_icu_var || 'n';\n\n if (!options.__intlayer_icu_var) {\n const fallbackVal =\n transformedOptions.fallback ||\n transformedOptions.other ||\n Object.values(transformedOptions)[0];\n const match = fallbackVal.match(/\\{([a-zA-Z0-9_]+)\\}(?!,)/);\n if (match) {\n varName = match[1];\n }\n }\n\n // Ordinal enumerations round-trip back to `selectordinal`\n if (options.__intlayer_icu_ordinal === true) {\n const ordinalParts = [];\n\n for (const [key, val] of Object.entries(transformedOptions)) {\n let icuKey = key;\n if (key === 'fallback') icuKey = 'other';\n else if (/^\\d+$/.test(key)) icuKey = `=${key}`;\n\n let strVal = val;\n strVal = strVal.replace(new RegExp(`\\\\{${varName}\\\\}`, 'g'), '#');\n ordinalParts.push(`${icuKey} {${strVal}}`);\n }\n\n return `{${varName}, selectordinal, ${ordinalParts.join(' ')}}`;\n }\n\n const keys = Object.keys(transformedOptions);\n const pluralKeys = [\n '1',\n '2',\n '<=3',\n '>=4',\n 'fallback',\n 'other',\n 'zero',\n 'one',\n 'two',\n 'few',\n 'many',\n ];\n\n const isPlural = keys.every(\n (k) => pluralKeys.includes(k) || /^[<>=]?\\d+(\\.\\d+)?$/.test(k)\n );\n\n const parts = [];\n\n if (isPlural) {\n for (const [key, val] of Object.entries(transformedOptions)) {\n let icuKey = key;\n if (key === 'fallback') icuKey = 'other';\n else if (key === '<=3') icuKey = 'few';\n else if (key === '>=4') icuKey = 'many';\n else if (/^\\d+$/.test(key)) icuKey = `=${key}`;\n else if (['zero', 'few', 'many'].includes(key)) icuKey = key;\n else icuKey = 'other';\n\n let strVal = val;\n strVal = strVal.replace(new RegExp(`\\\\{${varName}\\\\}`, 'g'), '#');\n parts.push(`${icuKey} {${strVal}}`);\n }\n return `{${varName}, plural, ${parts.join(' ')}}`;\n } else {\n const entries = Object.entries(transformedOptions).sort(\n ([keyA], [keyB]) => {\n if (keyA === 'fallback' || keyA === 'other') return 1;\n if (keyB === 'fallback' || keyB === 'other') return -1;\n return 0;\n }\n );\n\n for (const [key, val] of entries) {\n let icuKey = key;\n if (key === 'fallback') icuKey = 'other';\n parts.push(`${icuKey} {${val}}`);\n }\n return `{${varName}, select, ${parts.join(' ')}}`;\n }\n }\n\n if (node.nodeType === NodeTypes.GENDER) {\n const options = node[NodeTypes.GENDER];\n const varName = 'gender';\n const parts = [];\n\n const entries = Object.entries(options).sort(([keyA], [keyB]) => {\n if (keyA === 'fallback') return 1;\n if (keyB === 'fallback') return -1;\n return 0;\n });\n\n for (const [key, val] of entries) {\n let icuKey = key;\n if (key === 'fallback') icuKey = 'other';\n\n const childVal = next(val, props);\n const strVal =\n typeof childVal === 'string' ? childVal : JSON.stringify(childVal);\n\n parts.push(`${icuKey} {${strVal}}`);\n }\n return `{${varName}, select, ${parts.join(' ')}}`;\n }\n\n if (\n Array.isArray(node) ||\n (node.nodeType === 'composite' && Array.isArray(node.composite))\n ) {\n // handle array/composite strings that passed canHandle\n const arr = Array.isArray(node) ? node : node.composite;\n const items = arr.map((item: any) => next(item, props));\n return items.join('');\n }\n\n return next(node, props);\n },\n};\n\nexport const intlayerToICUFormatter = (\n message: Dictionary['content']\n): JsonValue => {\n return deepTransformNode(message, {\n dictionaryKey: 'icu',\n keyPath: [],\n plugins: [{ id: 'icu', ...intlayerToIcuPlugin }],\n });\n};\n\nexport const icuToIntlayerFormatter = (\n message: Dictionary['content']\n): JsonValue => {\n return deepTransformNode(message, {\n dictionaryKey: 'icu',\n keyPath: [],\n plugins: [{ id: 'icu', ...icuToIntlayerPlugin }],\n });\n};\n"],"mappings":"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"}
@@ -180,18 +180,22 @@ const i18nextNodesToIntlayer = (nodes) => {
180
180
  else if (key === "few") newKey = "<=3";
181
181
  else if (key === "many") newKey = ">=4";
182
182
  else if (key === "other") newKey = "fallback";
183
- options[newKey] = i18nextNodesToIntlayer(val.map((v) => {
183
+ const replacedVal = val.map((v) => {
184
184
  if (typeof v === "string") return v.replace(/#/g, `{{${node.name}}}`);
185
185
  return v;
186
- }));
186
+ });
187
+ options[newKey] = i18nextNodesToIntlayer(replacedVal);
187
188
  }
188
189
  options.__intlayer_icu_var = node.name;
189
190
  return enumeration(options);
190
191
  } else {
191
- for (const [key, val] of Object.entries(node.options)) options[key] = i18nextNodesToIntlayer(val.map((v) => {
192
- if (typeof v === "string") return v.replace(/#/g, `{{${node.name}}}`);
193
- return v;
194
- }));
192
+ for (const [key, val] of Object.entries(node.options)) {
193
+ const replacedVal = val.map((v) => {
194
+ if (typeof v === "string") return v.replace(/#/g, `{{${node.name}}}`);
195
+ return v;
196
+ });
197
+ options[key] = i18nextNodesToIntlayer(replacedVal);
198
+ }
195
199
  return plural(options);
196
200
  }
197
201
  }
@@ -219,7 +223,8 @@ const i18nextToIntlayerPlugin = {
219
223
  canHandle: (node) => typeof node === "string" && (node.includes("{") || node.includes("}") || /<[a-zA-Z0-9-]+[^>]*>/.test(node)),
220
224
  transform: (node) => {
221
225
  try {
222
- return i18nextNodesToIntlayer(parseI18Next(node));
226
+ const ast = parseI18Next(node);
227
+ return i18nextNodesToIntlayer(ast);
223
228
  } catch {
224
229
  return node;
225
230
  }
@@ -1 +1 @@
1
- {"version":3,"file":"i18next.mjs","names":["insert","enu"],"sources":["../../../src/messageFormat/i18next.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/types/dictionary';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport { deepTransformNode } from '../interpreter';\nimport { enu, gender, html, insert, plural } from '../transpiler';\nimport type { JsonValue } from './ICU';\n\n// Types for our AST\ntype I18NextNode =\n | string\n | {\n type: 'argument';\n name: string;\n format?: { type: string; style?: string };\n }\n | { type: 'plural'; name: string; options: Record<string, I18NextNode[]> }\n | { type: 'select'; name: string; options: Record<string, I18NextNode[]> };\n\nconst parseI18Next = (text: string): I18NextNode[] => {\n let index = 0;\n\n const parseNodes = (): I18NextNode[] => {\n const nodes: I18NextNode[] = [];\n let currentText = '';\n\n while (index < text.length) {\n const char = text[index];\n\n // Standard i18next variable: {{var}}\n if (char === '{' && text[index + 1] === '{') {\n if (currentText) {\n nodes.push(currentText);\n currentText = '';\n }\n index += 2; // skip {{\n nodes.push(parseStandardArgument());\n }\n // ICU syntax: {var} or {var, plural, ...}\n else if (char === '{') {\n if (currentText) {\n nodes.push(currentText);\n currentText = '';\n }\n index++; // skip {\n nodes.push(parseICUArgument());\n } else if (char === '}') {\n // End of current block (likely ICU block end)\n break;\n } else {\n currentText += char;\n index++;\n }\n }\n\n if (currentText) {\n nodes.push(currentText);\n }\n return nodes;\n };\n\n const parseStandardArgument = (): I18NextNode => {\n // We are past '{{'\n let name = '';\n while (index < text.length) {\n // Check for closing }}\n if (text[index] === '}' && text[index + 1] === '}') {\n index += 2; // skip }}\n return { type: 'argument', name: name.trim() };\n }\n name += text[index];\n index++;\n }\n throw new Error('Unclosed i18next variable');\n };\n\n const parseICUArgument = (): I18NextNode => {\n // We are past '{'\n let name = '';\n while (index < text.length && /[^,}]/.test(text[index])) {\n name += text[index];\n index++;\n }\n name = name.trim();\n\n if (index >= text.length) throw new Error('Unclosed argument');\n\n if (text[index] === '}') {\n index++;\n return { type: 'argument', name };\n }\n\n // Must be comma\n if (text[index] === ',') {\n index++;\n // Parse type\n let type = '';\n while (index < text.length && /[^,}]/.test(text[index])) {\n type += text[index];\n index++;\n }\n type = type.trim();\n\n if (index >= text.length) throw new Error('Unclosed argument');\n\n if (text[index] === '}') {\n index++;\n return { type: 'argument', name, format: { type } };\n }\n\n if (text[index] === ',') {\n index++;\n\n // If plural or select, parse options\n if (type === 'plural' || type === 'select') {\n const options: Record<string, I18NextNode[]> = {};\n\n while (index < text.length && text[index] !== '}') {\n while (index < text.length && /\\s/.test(text[index])) index++;\n\n let key = '';\n while (index < text.length && /[^{\\s]/.test(text[index])) {\n key += text[index];\n index++;\n }\n\n while (index < text.length && /\\s/.test(text[index])) index++;\n\n if (text[index] !== '{')\n throw new Error('Expected { after option key');\n index++; // skip {\n\n const value = parseNodes();\n\n if (text[index] !== '}')\n throw new Error('Expected } after option value');\n index++; // skip }\n\n options[key] = value;\n\n while (index < text.length && /\\s/.test(text[index])) index++;\n }\n\n index++; // skip closing argument }\n\n if (type === 'plural') {\n return { type: 'plural', name, options };\n } else if (type === 'select') {\n return { type: 'select', name, options };\n }\n } else {\n // Parse style for number/date/time\n let style = '';\n while (index < text.length && text[index] !== '}') {\n style += text[index];\n index++;\n }\n if (index >= text.length) throw new Error('Unclosed argument');\n\n style = style.trim();\n index++; // skip }\n\n return { type: 'argument', name, format: { type, style } };\n }\n }\n }\n\n throw new Error('Malformed argument');\n };\n\n return parseNodes();\n};\n\nconst i18nextNodesToIntlayer = (nodes: I18NextNode[]): any => {\n if (nodes.length === 0) return '';\n if (nodes.length === 1 && typeof nodes[0] === 'string') {\n const node = nodes[0];\n if (/<[a-zA-Z0-9-]+[^>]*>/.test(node)) {\n return html(node);\n }\n return node;\n }\n\n const canFlatten = nodes.every(\n (node) => typeof node === 'string' || node.type === 'argument'\n );\n\n if (canFlatten) {\n let str = '';\n for (const node of nodes) {\n if (typeof node === 'string') {\n str += node;\n } else if (typeof node !== 'string' && node.type === 'argument') {\n if (node.format) {\n // For formatted arguments, use ICU syntax: {name, type, style}\n str += `{${node.name}, ${node.format.type}${\n node.format.style ? `, ${node.format.style}` : ''\n }}`;\n } else {\n // For simple arguments, use standard i18next: {{name}}\n str += `{{${node.name}}}`;\n }\n }\n }\n if (/<[a-zA-Z0-9-]+[^>]*>/.test(str)) {\n return html(str);\n }\n return insert(str);\n }\n\n if (nodes.length === 1) {\n const node = nodes[0];\n if (typeof node === 'string') {\n if (/<[a-zA-Z0-9-]+[^>]*>/.test(node)) {\n return html(node);\n }\n return node;\n }\n\n if (node.type === 'argument') {\n if (node.format) {\n return insert(\n `{${node.name}, ${node.format.type}${\n node.format.style ? `, ${node.format.style}` : ''\n }}`\n );\n }\n return insert(`{{${node.name}}}`);\n }\n\n if (node.type === 'plural') {\n const options: Record<string, any> = {};\n let hasExactMatch = false;\n\n for (const key of Object.keys(node.options)) {\n if (key.startsWith('=')) {\n hasExactMatch = true;\n break;\n }\n }\n\n if (hasExactMatch) {\n for (const [key, val] of Object.entries(node.options)) {\n let newKey = key;\n if (key.startsWith('=')) {\n newKey = key.substring(1);\n } else if (key === 'one') {\n newKey = '1';\n } else if (key === 'two') {\n newKey = '2';\n } else if (key === 'few') {\n newKey = '<=3';\n } else if (key === 'many') {\n newKey = '>=4';\n } else if (key === 'other') {\n newKey = 'fallback';\n }\n // Handle # replacement\n const replacedVal = val.map((v) => {\n if (typeof v === 'string') {\n // In ICU plural, # is replaced by the number\n // In i18next, if using ICU plugin, it behaves same.\n // We map it to {{varName}} in Intlayer\n return v.replace(/#/g, `{{${node.name}}}`);\n }\n return v;\n });\n\n options[newKey] = i18nextNodesToIntlayer(replacedVal);\n }\n\n // Preserve variable name\n options.__intlayer_icu_var = node.name;\n\n return enu(options);\n } else {\n for (const [key, val] of Object.entries(node.options)) {\n // Handle # replacement\n const replacedVal = val.map((v) => {\n if (typeof v === 'string') {\n return v.replace(/#/g, `{{${node.name}}}`);\n }\n return v;\n });\n\n options[key] = i18nextNodesToIntlayer(replacedVal);\n }\n\n return plural(options as any);\n }\n }\n\n if (node.type === 'select') {\n const options: Record<string, any> = {};\n for (const [key, val] of Object.entries(node.options)) {\n options[key] = i18nextNodesToIntlayer(val);\n }\n\n // Check for gender\n const optionKeys = Object.keys(options);\n const isGender =\n (options.male || options.female) &&\n optionKeys.every((k) =>\n ['male', 'female', 'other', 'fallback'].includes(k)\n );\n\n if (isGender) {\n return gender({\n fallback: options.other,\n male: options.male,\n female: options.female,\n });\n }\n\n // Preserve variable name for generic select\n options.__intlayer_icu_var = node.name;\n\n return enu(options);\n }\n }\n\n return nodes.map((node) => i18nextNodesToIntlayer([node]));\n};\n\nconst i18nextToIntlayerPlugin = {\n canHandle: (node: any) =>\n typeof node === 'string' &&\n (node.includes('{') ||\n node.includes('}') ||\n /<[a-zA-Z0-9-]+[^>]*>/.test(node)),\n transform: (node: any) => {\n try {\n const ast = parseI18Next(node);\n return i18nextNodesToIntlayer(ast);\n } catch {\n return node;\n }\n },\n};\n\nconst intlayerToI18nextPlugin = {\n canHandle: (node: any) => {\n if (typeof node === 'string') return true;\n\n if (\n node &&\n typeof node === 'object' &&\n (node.nodeType === NodeTypes.INSERTION ||\n node.nodeType === NodeTypes.HTML ||\n node.nodeType === NodeTypes.ENUMERATION ||\n node.nodeType === NodeTypes.PLURAL ||\n node.nodeType === NodeTypes.GENDER ||\n node.nodeType === 'composite')\n ) {\n return true;\n }\n\n if (Array.isArray(node)) {\n if (node.length === 0) return false;\n\n let hasNode = false;\n let hasPlainObjectOrArray = false;\n\n for (const item of node) {\n if (typeof item === 'string') {\n } else if (\n item &&\n typeof item === 'object' &&\n (item.nodeType === NodeTypes.INSERTION ||\n item.nodeType === NodeTypes.HTML ||\n item.nodeType === NodeTypes.ENUMERATION ||\n item.nodeType === NodeTypes.GENDER ||\n item.nodeType === 'composite')\n ) {\n hasNode = true;\n } else {\n hasPlainObjectOrArray = true;\n }\n }\n\n // If it contains plain objects or nested arrays, it's a structural array\n if (hasPlainObjectOrArray) return false;\n // If it contains ONLY strings, it's a structural array, not a composite string\n if (!hasNode) return false;\n\n return true;\n }\n\n return false;\n },\n transform: (node: any, props: any, next: any) => {\n if (typeof node === 'string') {\n return node;\n }\n\n if (node.nodeType === NodeTypes.INSERTION) {\n if (node[NodeTypes.INSERTION].match(/\\{[^}]*,[^}]*\\}/)) {\n return node[NodeTypes.INSERTION];\n }\n return node[NodeTypes.INSERTION];\n }\n\n if (node.nodeType === NodeTypes.HTML) {\n return node[NodeTypes.HTML];\n }\n\n if (node.nodeType === NodeTypes.PLURAL) {\n const options = node[NodeTypes.PLURAL];\n\n const transformedOptions: Record<string, string> = {};\n for (const [key, val] of Object.entries(options)) {\n const childVal = next(val, props);\n transformedOptions[key] =\n typeof childVal === 'string' ? childVal : JSON.stringify(childVal);\n }\n\n let varName = 'count';\n\n const fallbackVal =\n transformedOptions.other || Object.values(transformedOptions)[0];\n\n if (fallbackVal) {\n const match =\n fallbackVal.match(/\\{\\{([a-zA-Z0-9_]+)\\}\\}/) ||\n fallbackVal.match(/\\{([a-zA-Z0-9_]+)\\}(?!,)/);\n if (match) {\n varName = match[1];\n }\n }\n\n const parts = [];\n\n for (const [key, val] of Object.entries(transformedOptions)) {\n const icuKey = key;\n let strVal = val;\n\n strVal = strVal.replace(/\\{\\{([^}]+)\\}\\}/g, '{$1}');\n strVal = strVal.replace(new RegExp(`\\\\{${varName}\\\\}`, 'g'), '#');\n\n parts.push(`${icuKey} {${strVal}}`);\n }\n return `{${varName}, plural, ${parts.join(' ')}}`;\n }\n\n if (node.nodeType === NodeTypes.ENUMERATION) {\n const options = node[NodeTypes.ENUMERATION];\n\n const transformedOptions: Record<string, string> = {};\n for (const [key, val] of Object.entries(options)) {\n if (key === '__intlayer_icu_var' || key === '__intlayer_icu_ordinal')\n continue;\n const childVal = next(val, props);\n transformedOptions[key] =\n typeof childVal === 'string' ? childVal : JSON.stringify(childVal);\n }\n\n let varName = options.__intlayer_icu_var || 'count';\n\n if (!options.__intlayer_icu_var) {\n const fallbackVal =\n transformedOptions.fallback ||\n transformedOptions.other ||\n Object.values(transformedOptions)[0];\n\n const match =\n fallbackVal.match(/\\{\\{([a-zA-Z0-9_]+)\\}\\}/) ||\n fallbackVal.match(/\\{([a-zA-Z0-9_]+)\\}(?!,)/);\n if (match) {\n varName = match[1];\n }\n }\n\n const keys = Object.keys(transformedOptions);\n const pluralKeys = [\n '1',\n '2',\n '<=3',\n '>=4',\n 'fallback',\n 'other',\n 'zero',\n 'one',\n 'two',\n 'few',\n 'many',\n ];\n const isPlural = keys.every(\n (k) => pluralKeys.includes(k) || /^[<>=]?\\d+(\\.\\d+)?$/.test(k)\n );\n\n const parts = [];\n\n if (isPlural) {\n for (const [key, val] of Object.entries(transformedOptions)) {\n let icuKey = key;\n if (key === 'fallback') icuKey = 'other';\n else if (key === '<=3') icuKey = 'few';\n else if (key === '>=4') icuKey = 'many';\n else if (/^\\d+$/.test(key)) icuKey = `=${key}`;\n\n let strVal = val;\n\n strVal = strVal.replace(/\\{\\{([^}]+)\\}\\}/g, '{$1}');\n strVal = strVal.replace(new RegExp(`\\\\{${varName}\\\\}`, 'g'), '#');\n\n parts.push(`${icuKey} {${strVal}}`);\n }\n return `{${varName}, plural, ${parts.join(' ')}}`;\n } else {\n const entries = Object.entries(transformedOptions).sort(\n ([keyA], [keyB]) => {\n if (keyA === 'fallback' || keyA === 'other') return 1;\n if (keyB === 'fallback' || keyB === 'other') return -1;\n return 0;\n }\n );\n\n for (const [key, val] of entries) {\n let icuKey = key;\n if (key === 'fallback') icuKey = 'other';\n\n let strVal = val;\n strVal = strVal.replace(/\\{\\{([^}]+)\\}\\}/g, '{$1}');\n\n parts.push(`${icuKey} {${strVal}}`);\n }\n return `{${varName}, select, ${parts.join(' ')}}`;\n }\n }\n\n if (node.nodeType === NodeTypes.GENDER) {\n const options = node[NodeTypes.GENDER];\n const varName = 'gender';\n const parts = [];\n\n const entries = Object.entries(options).sort(([keyA], [keyB]) => {\n if (keyA === 'fallback') return 1;\n if (keyB === 'fallback') return -1;\n return 0;\n });\n\n for (const [key, val] of entries) {\n let icuKey = key;\n if (key === 'fallback') icuKey = 'other';\n\n const childVal = next(val, props);\n let strVal =\n typeof childVal === 'string' ? childVal : JSON.stringify(childVal);\n\n strVal = strVal.replace(/\\{\\{([^}]+)\\}\\}/g, '{$1}');\n parts.push(`${icuKey} {${strVal}}`);\n }\n return `{${varName}, select, ${parts.join(' ')}}`;\n }\n\n if (\n Array.isArray(node) ||\n (node.nodeType === 'composite' && Array.isArray(node.composite))\n ) {\n const arr = Array.isArray(node) ? node : node.composite;\n const items = arr.map((item: any) => next(item, props));\n return items.join('');\n }\n\n return next(node, props);\n },\n};\n\nexport const intlayerToI18nextFormatter = (\n message: Dictionary['content']\n): JsonValue => {\n return deepTransformNode(message, {\n dictionaryKey: 'i18next',\n keyPath: [],\n plugins: [{ id: 'i18next', ...intlayerToI18nextPlugin }],\n });\n};\n\nexport const i18nextToIntlayerFormatter = (\n message: JsonValue\n): Dictionary['content'] => {\n return deepTransformNode(message, {\n dictionaryKey: 'i18next',\n keyPath: [],\n plugins: [{ id: 'i18next', ...i18nextToIntlayerPlugin }],\n });\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"i18next.mjs","names":["insert","enu"],"sources":["../../../src/messageFormat/i18next.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/types/dictionary';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport { deepTransformNode } from '../interpreter';\nimport { enu, gender, html, insert, plural } from '../transpiler';\nimport type { JsonValue } from './ICU';\n\n// Types for our AST\ntype I18NextNode =\n | string\n | {\n type: 'argument';\n name: string;\n format?: { type: string; style?: string };\n }\n | { type: 'plural'; name: string; options: Record<string, I18NextNode[]> }\n | { type: 'select'; name: string; options: Record<string, I18NextNode[]> };\n\nconst parseI18Next = (text: string): I18NextNode[] => {\n let index = 0;\n\n const parseNodes = (): I18NextNode[] => {\n const nodes: I18NextNode[] = [];\n let currentText = '';\n\n while (index < text.length) {\n const char = text[index];\n\n // Standard i18next variable: {{var}}\n if (char === '{' && text[index + 1] === '{') {\n if (currentText) {\n nodes.push(currentText);\n currentText = '';\n }\n index += 2; // skip {{\n nodes.push(parseStandardArgument());\n }\n // ICU syntax: {var} or {var, plural, ...}\n else if (char === '{') {\n if (currentText) {\n nodes.push(currentText);\n currentText = '';\n }\n index++; // skip {\n nodes.push(parseICUArgument());\n } else if (char === '}') {\n // End of current block (likely ICU block end)\n break;\n } else {\n currentText += char;\n index++;\n }\n }\n\n if (currentText) {\n nodes.push(currentText);\n }\n return nodes;\n };\n\n const parseStandardArgument = (): I18NextNode => {\n // We are past '{{'\n let name = '';\n while (index < text.length) {\n // Check for closing }}\n if (text[index] === '}' && text[index + 1] === '}') {\n index += 2; // skip }}\n return { type: 'argument', name: name.trim() };\n }\n name += text[index];\n index++;\n }\n throw new Error('Unclosed i18next variable');\n };\n\n const parseICUArgument = (): I18NextNode => {\n // We are past '{'\n let name = '';\n while (index < text.length && /[^,}]/.test(text[index])) {\n name += text[index];\n index++;\n }\n name = name.trim();\n\n if (index >= text.length) throw new Error('Unclosed argument');\n\n if (text[index] === '}') {\n index++;\n return { type: 'argument', name };\n }\n\n // Must be comma\n if (text[index] === ',') {\n index++;\n // Parse type\n let type = '';\n while (index < text.length && /[^,}]/.test(text[index])) {\n type += text[index];\n index++;\n }\n type = type.trim();\n\n if (index >= text.length) throw new Error('Unclosed argument');\n\n if (text[index] === '}') {\n index++;\n return { type: 'argument', name, format: { type } };\n }\n\n if (text[index] === ',') {\n index++;\n\n // If plural or select, parse options\n if (type === 'plural' || type === 'select') {\n const options: Record<string, I18NextNode[]> = {};\n\n while (index < text.length && text[index] !== '}') {\n while (index < text.length && /\\s/.test(text[index])) index++;\n\n let key = '';\n while (index < text.length && /[^{\\s]/.test(text[index])) {\n key += text[index];\n index++;\n }\n\n while (index < text.length && /\\s/.test(text[index])) index++;\n\n if (text[index] !== '{')\n throw new Error('Expected { after option key');\n index++; // skip {\n\n const value = parseNodes();\n\n if (text[index] !== '}')\n throw new Error('Expected } after option value');\n index++; // skip }\n\n options[key] = value;\n\n while (index < text.length && /\\s/.test(text[index])) index++;\n }\n\n index++; // skip closing argument }\n\n if (type === 'plural') {\n return { type: 'plural', name, options };\n } else if (type === 'select') {\n return { type: 'select', name, options };\n }\n } else {\n // Parse style for number/date/time\n let style = '';\n while (index < text.length && text[index] !== '}') {\n style += text[index];\n index++;\n }\n if (index >= text.length) throw new Error('Unclosed argument');\n\n style = style.trim();\n index++; // skip }\n\n return { type: 'argument', name, format: { type, style } };\n }\n }\n }\n\n throw new Error('Malformed argument');\n };\n\n return parseNodes();\n};\n\nconst i18nextNodesToIntlayer = (nodes: I18NextNode[]): any => {\n if (nodes.length === 0) return '';\n if (nodes.length === 1 && typeof nodes[0] === 'string') {\n const node = nodes[0];\n if (/<[a-zA-Z0-9-]+[^>]*>/.test(node)) {\n return html(node);\n }\n return node;\n }\n\n const canFlatten = nodes.every(\n (node) => typeof node === 'string' || node.type === 'argument'\n );\n\n if (canFlatten) {\n let str = '';\n for (const node of nodes) {\n if (typeof node === 'string') {\n str += node;\n } else if (typeof node !== 'string' && node.type === 'argument') {\n if (node.format) {\n // For formatted arguments, use ICU syntax: {name, type, style}\n str += `{${node.name}, ${node.format.type}${\n node.format.style ? `, ${node.format.style}` : ''\n }}`;\n } else {\n // For simple arguments, use standard i18next: {{name}}\n str += `{{${node.name}}}`;\n }\n }\n }\n if (/<[a-zA-Z0-9-]+[^>]*>/.test(str)) {\n return html(str);\n }\n return insert(str);\n }\n\n if (nodes.length === 1) {\n const node = nodes[0];\n if (typeof node === 'string') {\n if (/<[a-zA-Z0-9-]+[^>]*>/.test(node)) {\n return html(node);\n }\n return node;\n }\n\n if (node.type === 'argument') {\n if (node.format) {\n return insert(\n `{${node.name}, ${node.format.type}${\n node.format.style ? `, ${node.format.style}` : ''\n }}`\n );\n }\n return insert(`{{${node.name}}}`);\n }\n\n if (node.type === 'plural') {\n const options: Record<string, any> = {};\n let hasExactMatch = false;\n\n for (const key of Object.keys(node.options)) {\n if (key.startsWith('=')) {\n hasExactMatch = true;\n break;\n }\n }\n\n if (hasExactMatch) {\n for (const [key, val] of Object.entries(node.options)) {\n let newKey = key;\n if (key.startsWith('=')) {\n newKey = key.substring(1);\n } else if (key === 'one') {\n newKey = '1';\n } else if (key === 'two') {\n newKey = '2';\n } else if (key === 'few') {\n newKey = '<=3';\n } else if (key === 'many') {\n newKey = '>=4';\n } else if (key === 'other') {\n newKey = 'fallback';\n }\n // Handle # replacement\n const replacedVal = val.map((v) => {\n if (typeof v === 'string') {\n // In ICU plural, # is replaced by the number\n // In i18next, if using ICU plugin, it behaves same.\n // We map it to {{varName}} in Intlayer\n return v.replace(/#/g, `{{${node.name}}}`);\n }\n return v;\n });\n\n options[newKey] = i18nextNodesToIntlayer(replacedVal);\n }\n\n // Preserve variable name\n options.__intlayer_icu_var = node.name;\n\n return enu(options);\n } else {\n for (const [key, val] of Object.entries(node.options)) {\n // Handle # replacement\n const replacedVal = val.map((v) => {\n if (typeof v === 'string') {\n return v.replace(/#/g, `{{${node.name}}}`);\n }\n return v;\n });\n\n options[key] = i18nextNodesToIntlayer(replacedVal);\n }\n\n return plural(options as any);\n }\n }\n\n if (node.type === 'select') {\n const options: Record<string, any> = {};\n for (const [key, val] of Object.entries(node.options)) {\n options[key] = i18nextNodesToIntlayer(val);\n }\n\n // Check for gender\n const optionKeys = Object.keys(options);\n const isGender =\n (options.male || options.female) &&\n optionKeys.every((k) =>\n ['male', 'female', 'other', 'fallback'].includes(k)\n );\n\n if (isGender) {\n return gender({\n fallback: options.other,\n male: options.male,\n female: options.female,\n });\n }\n\n // Preserve variable name for generic select\n options.__intlayer_icu_var = node.name;\n\n return enu(options);\n }\n }\n\n return nodes.map((node) => i18nextNodesToIntlayer([node]));\n};\n\nconst i18nextToIntlayerPlugin = {\n canHandle: (node: any) =>\n typeof node === 'string' &&\n (node.includes('{') ||\n node.includes('}') ||\n /<[a-zA-Z0-9-]+[^>]*>/.test(node)),\n transform: (node: any) => {\n try {\n const ast = parseI18Next(node);\n return i18nextNodesToIntlayer(ast);\n } catch {\n return node;\n }\n },\n};\n\nconst intlayerToI18nextPlugin = {\n canHandle: (node: any) => {\n if (typeof node === 'string') return true;\n\n if (\n node &&\n typeof node === 'object' &&\n (node.nodeType === NodeTypes.INSERTION ||\n node.nodeType === NodeTypes.HTML ||\n node.nodeType === NodeTypes.ENUMERATION ||\n node.nodeType === NodeTypes.PLURAL ||\n node.nodeType === NodeTypes.GENDER ||\n node.nodeType === 'composite')\n ) {\n return true;\n }\n\n if (Array.isArray(node)) {\n if (node.length === 0) return false;\n\n let hasNode = false;\n let hasPlainObjectOrArray = false;\n\n for (const item of node) {\n if (typeof item === 'string') {\n } else if (\n item &&\n typeof item === 'object' &&\n (item.nodeType === NodeTypes.INSERTION ||\n item.nodeType === NodeTypes.HTML ||\n item.nodeType === NodeTypes.ENUMERATION ||\n item.nodeType === NodeTypes.GENDER ||\n item.nodeType === 'composite')\n ) {\n hasNode = true;\n } else {\n hasPlainObjectOrArray = true;\n }\n }\n\n // If it contains plain objects or nested arrays, it's a structural array\n if (hasPlainObjectOrArray) return false;\n // If it contains ONLY strings, it's a structural array, not a composite string\n if (!hasNode) return false;\n\n return true;\n }\n\n return false;\n },\n transform: (node: any, props: any, next: any) => {\n if (typeof node === 'string') {\n return node;\n }\n\n if (node.nodeType === NodeTypes.INSERTION) {\n if (node[NodeTypes.INSERTION].match(/\\{[^}]*,[^}]*\\}/)) {\n return node[NodeTypes.INSERTION];\n }\n return node[NodeTypes.INSERTION];\n }\n\n if (node.nodeType === NodeTypes.HTML) {\n return node[NodeTypes.HTML];\n }\n\n if (node.nodeType === NodeTypes.PLURAL) {\n const options = node[NodeTypes.PLURAL];\n\n const transformedOptions: Record<string, string> = {};\n for (const [key, val] of Object.entries(options)) {\n const childVal = next(val, props);\n transformedOptions[key] =\n typeof childVal === 'string' ? childVal : JSON.stringify(childVal);\n }\n\n let varName = 'count';\n\n const fallbackVal =\n transformedOptions.other || Object.values(transformedOptions)[0];\n\n if (fallbackVal) {\n const match =\n fallbackVal.match(/\\{\\{([a-zA-Z0-9_]+)\\}\\}/) ||\n fallbackVal.match(/\\{([a-zA-Z0-9_]+)\\}(?!,)/);\n if (match) {\n varName = match[1];\n }\n }\n\n const parts = [];\n\n for (const [key, val] of Object.entries(transformedOptions)) {\n const icuKey = key;\n let strVal = val;\n\n strVal = strVal.replace(/\\{\\{([^}]+)\\}\\}/g, '{$1}');\n strVal = strVal.replace(new RegExp(`\\\\{${varName}\\\\}`, 'g'), '#');\n\n parts.push(`${icuKey} {${strVal}}`);\n }\n return `{${varName}, plural, ${parts.join(' ')}}`;\n }\n\n if (node.nodeType === NodeTypes.ENUMERATION) {\n const options = node[NodeTypes.ENUMERATION];\n\n const transformedOptions: Record<string, string> = {};\n for (const [key, val] of Object.entries(options)) {\n if (key === '__intlayer_icu_var' || key === '__intlayer_icu_ordinal')\n continue;\n const childVal = next(val, props);\n transformedOptions[key] =\n typeof childVal === 'string' ? childVal : JSON.stringify(childVal);\n }\n\n let varName = options.__intlayer_icu_var || 'count';\n\n if (!options.__intlayer_icu_var) {\n const fallbackVal =\n transformedOptions.fallback ||\n transformedOptions.other ||\n Object.values(transformedOptions)[0];\n\n const match =\n fallbackVal.match(/\\{\\{([a-zA-Z0-9_]+)\\}\\}/) ||\n fallbackVal.match(/\\{([a-zA-Z0-9_]+)\\}(?!,)/);\n if (match) {\n varName = match[1];\n }\n }\n\n const keys = Object.keys(transformedOptions);\n const pluralKeys = [\n '1',\n '2',\n '<=3',\n '>=4',\n 'fallback',\n 'other',\n 'zero',\n 'one',\n 'two',\n 'few',\n 'many',\n ];\n const isPlural = keys.every(\n (k) => pluralKeys.includes(k) || /^[<>=]?\\d+(\\.\\d+)?$/.test(k)\n );\n\n const parts = [];\n\n if (isPlural) {\n for (const [key, val] of Object.entries(transformedOptions)) {\n let icuKey = key;\n if (key === 'fallback') icuKey = 'other';\n else if (key === '<=3') icuKey = 'few';\n else if (key === '>=4') icuKey = 'many';\n else if (/^\\d+$/.test(key)) icuKey = `=${key}`;\n\n let strVal = val;\n\n strVal = strVal.replace(/\\{\\{([^}]+)\\}\\}/g, '{$1}');\n strVal = strVal.replace(new RegExp(`\\\\{${varName}\\\\}`, 'g'), '#');\n\n parts.push(`${icuKey} {${strVal}}`);\n }\n return `{${varName}, plural, ${parts.join(' ')}}`;\n } else {\n const entries = Object.entries(transformedOptions).sort(\n ([keyA], [keyB]) => {\n if (keyA === 'fallback' || keyA === 'other') return 1;\n if (keyB === 'fallback' || keyB === 'other') return -1;\n return 0;\n }\n );\n\n for (const [key, val] of entries) {\n let icuKey = key;\n if (key === 'fallback') icuKey = 'other';\n\n let strVal = val;\n strVal = strVal.replace(/\\{\\{([^}]+)\\}\\}/g, '{$1}');\n\n parts.push(`${icuKey} {${strVal}}`);\n }\n return `{${varName}, select, ${parts.join(' ')}}`;\n }\n }\n\n if (node.nodeType === NodeTypes.GENDER) {\n const options = node[NodeTypes.GENDER];\n const varName = 'gender';\n const parts = [];\n\n const entries = Object.entries(options).sort(([keyA], [keyB]) => {\n if (keyA === 'fallback') return 1;\n if (keyB === 'fallback') return -1;\n return 0;\n });\n\n for (const [key, val] of entries) {\n let icuKey = key;\n if (key === 'fallback') icuKey = 'other';\n\n const childVal = next(val, props);\n let strVal =\n typeof childVal === 'string' ? childVal : JSON.stringify(childVal);\n\n strVal = strVal.replace(/\\{\\{([^}]+)\\}\\}/g, '{$1}');\n parts.push(`${icuKey} {${strVal}}`);\n }\n return `{${varName}, select, ${parts.join(' ')}}`;\n }\n\n if (\n Array.isArray(node) ||\n (node.nodeType === 'composite' && Array.isArray(node.composite))\n ) {\n const arr = Array.isArray(node) ? node : node.composite;\n const items = arr.map((item: any) => next(item, props));\n return items.join('');\n }\n\n return next(node, props);\n },\n};\n\nexport const intlayerToI18nextFormatter = (\n message: Dictionary['content']\n): JsonValue => {\n return deepTransformNode(message, {\n dictionaryKey: 'i18next',\n keyPath: [],\n plugins: [{ id: 'i18next', ...intlayerToI18nextPlugin }],\n });\n};\n\nexport const i18nextToIntlayerFormatter = (\n message: JsonValue\n): Dictionary['content'] => {\n return deepTransformNode(message, {\n dictionaryKey: 'i18next',\n keyPath: [],\n plugins: [{ id: 'i18next', ...i18nextToIntlayerPlugin }],\n });\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"navigatePath.mjs","names":[],"sources":["../../../src/messageFormat/navigatePath.ts"],"sourcesContent":["/**\n * Reads a dotted `path` (e.g. `counter.label`) out of a nested content value.\n *\n * The full path is first tried as a *flat* property, supporting catalogs that\n * use dotted keys as literal field names (i18next flat JSON files, lingui\n * catalogs: `{ \"section.title\": \"value\" }`). When that misses, the path is\n * split on `keySeparator` and walked segment by segment.\n *\n * Shared by every compat adapter's translation lookup — do not re-implement\n * it locally.\n *\n * @param contentValue - The object (dictionary content) to read from.\n * @param path - Separator-delimited path. An empty path returns `contentValue`.\n * @param keySeparator - Segment separator; `false` disables nested traversal\n * (flat lookup only), mirroring i18next's `keySeparator: false`.\n * @returns The value found at `path`, or `undefined` when any segment is absent.\n */\nexport const navigatePath = (\n contentValue: unknown,\n path: string,\n keySeparator: string | false = '.'\n): unknown => {\n if (!path) return contentValue;\n\n if (\n contentValue !== null &&\n contentValue !== undefined &&\n typeof contentValue === 'object'\n ) {\n const flatValue = (contentValue as Record<string, unknown>)[path];\n if (flatValue !== undefined) return flatValue;\n }\n\n if (keySeparator === false || !path.includes(keySeparator)) {\n return undefined;\n }\n\n let current: unknown = contentValue;\n for (const part of path.split(keySeparator)) {\n if (\n current === null ||\n current === undefined ||\n typeof current !== 'object'\n ) {\n return undefined;\n }\n current = (current as Record<string, unknown>)[part];\n }\n return current;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAiBA,MAAa,gBACX,cACA,MACA,eAA+B,QACnB;AACZ,KAAI,CAAC,KAAM,QAAO;AAElB,KACE,iBAAiB,QACjB,iBAAiB,UACjB,OAAO,iBAAiB,UACxB;EACA,MAAM,YAAa,aAAyC;AAC5D,MAAI,cAAc,OAAW,QAAO;;AAGtC,KAAI,iBAAiB,SAAS,CAAC,KAAK,SAAS,aAAa,CACxD;CAGF,IAAI,UAAmB;AACvB,MAAK,MAAM,QAAQ,KAAK,MAAM,aAAa,EAAE;AAC3C,MACE,YAAY,QACZ,YAAY,UACZ,OAAO,YAAY,SAEnB;AAEF,YAAW,QAAoC;;AAEjD,QAAO"}
1
+ {"version":3,"file":"navigatePath.mjs","names":[],"sources":["../../../src/messageFormat/navigatePath.ts"],"sourcesContent":["/**\n * Reads a dotted `path` (e.g. `counter.label`) out of a nested content value.\n *\n * The full path is first tried as a *flat* property, supporting catalogs that\n * use dotted keys as literal field names (i18next flat JSON files, lingui\n * catalogs: `{ \"section.title\": \"value\" }`). When that misses, the path is\n * split on `keySeparator` and walked segment by segment.\n *\n * Shared by every compat adapter's translation lookup — do not re-implement\n * it locally.\n *\n * @param contentValue - The object (dictionary content) to read from.\n * @param path - Separator-delimited path. An empty path returns `contentValue`.\n * @param keySeparator - Segment separator; `false` disables nested traversal\n * (flat lookup only), mirroring i18next's `keySeparator: false`.\n * @returns The value found at `path`, or `undefined` when any segment is absent.\n */\nexport const navigatePath = (\n contentValue: unknown,\n path: string,\n keySeparator: string | false = '.'\n): unknown => {\n if (!path) return contentValue;\n\n if (\n contentValue !== null &&\n contentValue !== undefined &&\n typeof contentValue === 'object'\n ) {\n const flatValue = (contentValue as Record<string, unknown>)[path];\n if (flatValue !== undefined) return flatValue;\n }\n\n if (keySeparator === false || !path.includes(keySeparator)) {\n return undefined;\n }\n\n let current: unknown = contentValue;\n for (const part of path.split(keySeparator)) {\n if (\n current === null ||\n current === undefined ||\n typeof current !== 'object'\n ) {\n return undefined;\n }\n current = (current as Record<string, unknown>)[part];\n }\n return current;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAiBA,MAAa,gBACX,cACA,MACA,eAA+B,QACnB;CACZ,IAAI,CAAC,MAAM,OAAO;CAElB,IACE,iBAAiB,QACjB,iBAAiB,UACjB,OAAO,iBAAiB,UACxB;EACA,MAAM,YAAa,aAAyC;EAC5D,IAAI,cAAc,QAAW,OAAO;CACtC;CAEA,IAAI,iBAAiB,SAAS,CAAC,KAAK,SAAS,YAAY,GACvD;CAGF,IAAI,UAAmB;CACvB,KAAK,MAAM,QAAQ,KAAK,MAAM,YAAY,GAAG;EAC3C,IACE,YAAY,QACZ,YAAY,UACZ,OAAO,YAAY,UAEnB;EAEF,UAAW,QAAoC;CACjD;CACA,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"po.mjs","names":["insert","enu"],"sources":["../../../src/messageFormat/po.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/types/dictionary';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport { deepTransformNode } from '../interpreter';\nimport { enu, gender, html, insert, plural } from '../transpiler';\nimport type { JsonValue } from './ICU';\n\nexport type PortableObject = {\n msgid: string;\n msgctxt?: string;\n msgid_plural?: string;\n msgstr: string[];\n};\n\n/**\n * Extracts the string value from a transformed AST node or generic object.\n */\nconst extractStringValue = (val: any): string => {\n if (typeof val === 'string') return val;\n if (val && typeof val === 'object' && 'msgstr' in val) {\n return val.msgstr[0] || '';\n }\n return JSON.stringify(val);\n};\n\nconst intlayerToPoPlugin = {\n canHandle: (node: any) => {\n if (typeof node === 'string') return true;\n\n if (\n node &&\n typeof node === 'object' &&\n (node.nodeType === NodeTypes.INSERTION ||\n node.nodeType === NodeTypes.HTML ||\n node.nodeType === NodeTypes.ENUMERATION ||\n node.nodeType === NodeTypes.PLURAL ||\n node.nodeType === NodeTypes.GENDER ||\n node.nodeType === 'composite')\n ) {\n return true;\n }\n\n // Handle structural string arrays (composite phrases)\n if (Array.isArray(node)) {\n if (node.length === 0) return false;\n let hasNode = false;\n let hasPlainObjectOrArray = false;\n\n for (const item of node) {\n if (typeof item === 'string') {\n } else if (\n item &&\n typeof item === 'object' &&\n (item.nodeType === NodeTypes.INSERTION ||\n item.nodeType === NodeTypes.HTML ||\n item.nodeType === NodeTypes.ENUMERATION ||\n item.nodeType === NodeTypes.PLURAL ||\n item.nodeType === NodeTypes.GENDER ||\n item.nodeType === 'composite')\n ) {\n hasNode = true;\n } else {\n hasPlainObjectOrArray = true;\n }\n }\n\n if (hasPlainObjectOrArray) return false;\n if (!hasNode) return false;\n return true;\n }\n\n return false;\n },\n transform: (node: any, props: any, next: any): PortableObject => {\n // 1. Strings\n if (typeof node === 'string') {\n const poVal = node.replace(/\\{\\{([^}]+)\\}\\}/g, '%($1)s');\n return { msgid: poVal, msgstr: [poVal] };\n }\n\n // 2. Insertions & Variables\n if (node.nodeType === NodeTypes.INSERTION) {\n return next(node[NodeTypes.INSERTION], props);\n }\n\n // 3. HTML\n if (node.nodeType === NodeTypes.HTML) {\n const val = node[NodeTypes.HTML];\n return { msgid: val, msgstr: [val] };\n }\n\n // 4. Plurals & Enumerations\n if (\n node.nodeType === NodeTypes.PLURAL ||\n node.nodeType === NodeTypes.ENUMERATION\n ) {\n const isPlural = node.nodeType === NodeTypes.PLURAL;\n const options = isPlural\n ? node[NodeTypes.PLURAL]\n : node[NodeTypes.ENUMERATION];\n\n const rawMsgid = isPlural\n ? options.one || options.other || options.fallback\n : options.fallback || options['0'];\n\n const msgid = extractStringValue(next(rawMsgid, props));\n const msgid_plural = isPlural\n ? extractStringValue(\n next(options.other || options.fallback || rawMsgid, props)\n )\n : extractStringValue(next(options.fallback || rawMsgid, props));\n\n const msgstr: string[] = [];\n\n if (isPlural) {\n // Standard CLDR/Gettext mapping fallback\n if ('zero' in options)\n msgstr.push(extractStringValue(next(options.zero, props)));\n msgstr.push(\n extractStringValue(next(options.one || options.fallback, props))\n );\n if ('two' in options)\n msgstr.push(extractStringValue(next(options.two, props)));\n if ('few' in options)\n msgstr.push(extractStringValue(next(options.few, props)));\n if ('many' in options)\n msgstr.push(extractStringValue(next(options.many, props)));\n\n // Ensure 'other' is always the last fallback if others are missing\n const otherVal = extractStringValue(\n next(options.other || options.fallback, props)\n );\n if (!msgstr.includes(otherVal)) msgstr.push(otherVal);\n } else {\n // Enums don't have standard PO mapping, pack linearly\n msgstr[0] = extractStringValue(\n next(options.fallback || options['0'], props)\n );\n msgstr[1] = msgstr[0];\n }\n\n return {\n msgctxt: isPlural ? undefined : 'enumeration',\n msgid,\n msgid_plural,\n msgstr,\n };\n }\n\n // 5. Gender (mapped to PO via msgctxt)\n if (node.nodeType === NodeTypes.GENDER) {\n const options = node[NodeTypes.GENDER];\n const fallback = extractStringValue(next(options.fallback, props));\n return {\n msgctxt: 'gender',\n msgid: fallback,\n msgstr: [\n extractStringValue(next(options.male || options.fallback, props)),\n extractStringValue(next(options.female || options.fallback, props)),\n fallback,\n ],\n };\n }\n\n // 6. Arrays / Composites\n if (\n Array.isArray(node) ||\n (node.nodeType === 'composite' && Array.isArray(node.composite))\n ) {\n const arr = Array.isArray(node) ? node : node.composite;\n const combined = arr\n .map((item: any) => extractStringValue(next(item, props)))\n .join('');\n return { msgid: combined, msgstr: [combined] };\n }\n\n return node;\n },\n};\n\nconst poToIntlayerPlugin = {\n canHandle: (node: any) =>\n node && typeof node === 'object' && 'msgid' in node && 'msgstr' in node,\n\n transform: (node: PortableObject) => {\n const msgstr = node.msgstr || [];\n const isPlural = Boolean(node.msgid_plural) || msgstr.length > 1;\n\n const processString = (str: string) => {\n if (!str) return '';\n // Convert Python/C-style gettext variables %(name)s or %(name)d -> {{name}}\n const parsed = str.replace(/%\\(([a-zA-Z0-9_-]+)\\)[sdf]/g, '{{$1}}');\n\n if (/<[a-zA-Z0-9-]+[^>]*>/.test(parsed)) return html(parsed);\n if (parsed.includes('{{')) return insert(parsed);\n return parsed;\n };\n\n // Fast-path: Single string translation\n if (!isPlural) {\n return processString(msgstr[0] || node.msgid || '');\n }\n\n // Handle Plural/Enum/Gender matrix\n const options: Record<string, any> = {};\n\n if (node.msgctxt === 'gender') {\n return gender({\n male: processString(msgstr[0] || node.msgid),\n female: processString(msgstr[1] || msgstr[0]),\n fallback: processString(msgstr[2] || msgstr[msgstr.length - 1]),\n });\n }\n\n if (node.msgctxt === 'enumeration') {\n return enu({\n '0': processString(msgstr[0]),\n fallback: processString(msgstr[msgstr.length - 1]),\n });\n }\n\n // Plural Form Mapping based on array length (Gettext Plural-Forms approximation)\n if (msgstr.length === 2) {\n options.one = processString(msgstr[0]);\n options.other = processString(msgstr[1]);\n } else if (msgstr.length === 3) {\n // E.g., Polish/Russian: one, few, many/other\n options.one = processString(msgstr[0]);\n options.few = processString(msgstr[1]);\n options.other = processString(msgstr[2]);\n } else if (msgstr.length === 6) {\n // E.g., Arabic: zero, one, two, few, many, other\n options.zero = processString(msgstr[0]);\n options.one = processString(msgstr[1]);\n options.two = processString(msgstr[2]);\n options.few = processString(msgstr[3]);\n options.many = processString(msgstr[4]);\n options.other = processString(msgstr[5]);\n } else {\n // Generic arbitrary length mapping\n options.one = processString(msgstr[0]);\n options.other = processString(msgstr[msgstr.length - 1]);\n for (let i = 1; i < msgstr.length - 1; i++) {\n options[`${i + 1}`] = processString(msgstr[i]);\n }\n }\n\n return plural(options as any);\n },\n};\n\nexport const intlayerToPortableObjectFormatter = (\n dictionary: Dictionary['content']\n): JsonValue => {\n return deepTransformNode(dictionary, {\n dictionaryKey: 'po',\n keyPath: [],\n plugins: [{ id: 'po', ...intlayerToPoPlugin }],\n });\n};\n\nexport const portableObjectToIntlayerFormatter = (\n message: JsonValue\n): Dictionary['content'] => {\n return deepTransformNode(message, {\n dictionaryKey: 'po',\n keyPath: [],\n plugins: [{ id: 'po', ...poToIntlayerPlugin }],\n });\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"po.mjs","names":["insert","enu"],"sources":["../../../src/messageFormat/po.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/types/dictionary';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport { deepTransformNode } from '../interpreter';\nimport { enu, gender, html, insert, plural } from '../transpiler';\nimport type { JsonValue } from './ICU';\n\nexport type PortableObject = {\n msgid: string;\n msgctxt?: string;\n msgid_plural?: string;\n msgstr: string[];\n};\n\n/**\n * Extracts the string value from a transformed AST node or generic object.\n */\nconst extractStringValue = (val: any): string => {\n if (typeof val === 'string') return val;\n if (val && typeof val === 'object' && 'msgstr' in val) {\n return val.msgstr[0] || '';\n }\n return JSON.stringify(val);\n};\n\nconst intlayerToPoPlugin = {\n canHandle: (node: any) => {\n if (typeof node === 'string') return true;\n\n if (\n node &&\n typeof node === 'object' &&\n (node.nodeType === NodeTypes.INSERTION ||\n node.nodeType === NodeTypes.HTML ||\n node.nodeType === NodeTypes.ENUMERATION ||\n node.nodeType === NodeTypes.PLURAL ||\n node.nodeType === NodeTypes.GENDER ||\n node.nodeType === 'composite')\n ) {\n return true;\n }\n\n // Handle structural string arrays (composite phrases)\n if (Array.isArray(node)) {\n if (node.length === 0) return false;\n let hasNode = false;\n let hasPlainObjectOrArray = false;\n\n for (const item of node) {\n if (typeof item === 'string') {\n } else if (\n item &&\n typeof item === 'object' &&\n (item.nodeType === NodeTypes.INSERTION ||\n item.nodeType === NodeTypes.HTML ||\n item.nodeType === NodeTypes.ENUMERATION ||\n item.nodeType === NodeTypes.PLURAL ||\n item.nodeType === NodeTypes.GENDER ||\n item.nodeType === 'composite')\n ) {\n hasNode = true;\n } else {\n hasPlainObjectOrArray = true;\n }\n }\n\n if (hasPlainObjectOrArray) return false;\n if (!hasNode) return false;\n return true;\n }\n\n return false;\n },\n transform: (node: any, props: any, next: any): PortableObject => {\n // 1. Strings\n if (typeof node === 'string') {\n const poVal = node.replace(/\\{\\{([^}]+)\\}\\}/g, '%($1)s');\n return { msgid: poVal, msgstr: [poVal] };\n }\n\n // 2. Insertions & Variables\n if (node.nodeType === NodeTypes.INSERTION) {\n return next(node[NodeTypes.INSERTION], props);\n }\n\n // 3. HTML\n if (node.nodeType === NodeTypes.HTML) {\n const val = node[NodeTypes.HTML];\n return { msgid: val, msgstr: [val] };\n }\n\n // 4. Plurals & Enumerations\n if (\n node.nodeType === NodeTypes.PLURAL ||\n node.nodeType === NodeTypes.ENUMERATION\n ) {\n const isPlural = node.nodeType === NodeTypes.PLURAL;\n const options = isPlural\n ? node[NodeTypes.PLURAL]\n : node[NodeTypes.ENUMERATION];\n\n const rawMsgid = isPlural\n ? options.one || options.other || options.fallback\n : options.fallback || options['0'];\n\n const msgid = extractStringValue(next(rawMsgid, props));\n const msgid_plural = isPlural\n ? extractStringValue(\n next(options.other || options.fallback || rawMsgid, props)\n )\n : extractStringValue(next(options.fallback || rawMsgid, props));\n\n const msgstr: string[] = [];\n\n if (isPlural) {\n // Standard CLDR/Gettext mapping fallback\n if ('zero' in options)\n msgstr.push(extractStringValue(next(options.zero, props)));\n msgstr.push(\n extractStringValue(next(options.one || options.fallback, props))\n );\n if ('two' in options)\n msgstr.push(extractStringValue(next(options.two, props)));\n if ('few' in options)\n msgstr.push(extractStringValue(next(options.few, props)));\n if ('many' in options)\n msgstr.push(extractStringValue(next(options.many, props)));\n\n // Ensure 'other' is always the last fallback if others are missing\n const otherVal = extractStringValue(\n next(options.other || options.fallback, props)\n );\n if (!msgstr.includes(otherVal)) msgstr.push(otherVal);\n } else {\n // Enums don't have standard PO mapping, pack linearly\n msgstr[0] = extractStringValue(\n next(options.fallback || options['0'], props)\n );\n msgstr[1] = msgstr[0];\n }\n\n return {\n msgctxt: isPlural ? undefined : 'enumeration',\n msgid,\n msgid_plural,\n msgstr,\n };\n }\n\n // 5. Gender (mapped to PO via msgctxt)\n if (node.nodeType === NodeTypes.GENDER) {\n const options = node[NodeTypes.GENDER];\n const fallback = extractStringValue(next(options.fallback, props));\n return {\n msgctxt: 'gender',\n msgid: fallback,\n msgstr: [\n extractStringValue(next(options.male || options.fallback, props)),\n extractStringValue(next(options.female || options.fallback, props)),\n fallback,\n ],\n };\n }\n\n // 6. Arrays / Composites\n if (\n Array.isArray(node) ||\n (node.nodeType === 'composite' && Array.isArray(node.composite))\n ) {\n const arr = Array.isArray(node) ? node : node.composite;\n const combined = arr\n .map((item: any) => extractStringValue(next(item, props)))\n .join('');\n return { msgid: combined, msgstr: [combined] };\n }\n\n return node;\n },\n};\n\nconst poToIntlayerPlugin = {\n canHandle: (node: any) =>\n node && typeof node === 'object' && 'msgid' in node && 'msgstr' in node,\n\n transform: (node: PortableObject) => {\n const msgstr = node.msgstr || [];\n const isPlural = Boolean(node.msgid_plural) || msgstr.length > 1;\n\n const processString = (str: string) => {\n if (!str) return '';\n // Convert Python/C-style gettext variables %(name)s or %(name)d -> {{name}}\n const parsed = str.replace(/%\\(([a-zA-Z0-9_-]+)\\)[sdf]/g, '{{$1}}');\n\n if (/<[a-zA-Z0-9-]+[^>]*>/.test(parsed)) return html(parsed);\n if (parsed.includes('{{')) return insert(parsed);\n return parsed;\n };\n\n // Fast-path: Single string translation\n if (!isPlural) {\n return processString(msgstr[0] || node.msgid || '');\n }\n\n // Handle Plural/Enum/Gender matrix\n const options: Record<string, any> = {};\n\n if (node.msgctxt === 'gender') {\n return gender({\n male: processString(msgstr[0] || node.msgid),\n female: processString(msgstr[1] || msgstr[0]),\n fallback: processString(msgstr[2] || msgstr[msgstr.length - 1]),\n });\n }\n\n if (node.msgctxt === 'enumeration') {\n return enu({\n '0': processString(msgstr[0]),\n fallback: processString(msgstr[msgstr.length - 1]),\n });\n }\n\n // Plural Form Mapping based on array length (Gettext Plural-Forms approximation)\n if (msgstr.length === 2) {\n options.one = processString(msgstr[0]);\n options.other = processString(msgstr[1]);\n } else if (msgstr.length === 3) {\n // E.g., Polish/Russian: one, few, many/other\n options.one = processString(msgstr[0]);\n options.few = processString(msgstr[1]);\n options.other = processString(msgstr[2]);\n } else if (msgstr.length === 6) {\n // E.g., Arabic: zero, one, two, few, many, other\n options.zero = processString(msgstr[0]);\n options.one = processString(msgstr[1]);\n options.two = processString(msgstr[2]);\n options.few = processString(msgstr[3]);\n options.many = processString(msgstr[4]);\n options.other = processString(msgstr[5]);\n } else {\n // Generic arbitrary length mapping\n options.one = processString(msgstr[0]);\n options.other = processString(msgstr[msgstr.length - 1]);\n for (let i = 1; i < msgstr.length - 1; i++) {\n options[`${i + 1}`] = processString(msgstr[i]);\n }\n }\n\n return plural(options as any);\n },\n};\n\nexport const intlayerToPortableObjectFormatter = (\n dictionary: Dictionary['content']\n): JsonValue => {\n return deepTransformNode(dictionary, {\n dictionaryKey: 'po',\n keyPath: [],\n plugins: [{ id: 'po', ...intlayerToPoPlugin }],\n });\n};\n\nexport const portableObjectToIntlayerFormatter = (\n message: JsonValue\n): Dictionary['content'] => {\n return deepTransformNode(message, {\n dictionaryKey: 'po',\n keyPath: [],\n plugins: [{ id: 'po', ...poToIntlayerPlugin }],\n });\n};\n"],"mappings":"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"}
@@ -30,9 +30,9 @@ const formatArgument = (value, type, style, locale) => {
30
30
  try {
31
31
  if (type === "number") {
32
32
  const numberValue = Number(value);
33
- if (style === "percent") return getCachedIntl(Intl.NumberFormat, locale, { style: "percent" }).format(numberValue);
34
- if (style === "integer") return getCachedIntl(Intl.NumberFormat, locale, { maximumFractionDigits: 0 }).format(numberValue);
35
- return getCachedIntl(Intl.NumberFormat, locale).format(numberValue);
33
+ if (style === "percent") return getCachedIntl("NumberFormat", locale, { style: "percent" }).format(numberValue);
34
+ if (style === "integer") return getCachedIntl("NumberFormat", locale, { maximumFractionDigits: 0 }).format(numberValue);
35
+ return getCachedIntl("NumberFormat", locale).format(numberValue);
36
36
  }
37
37
  if (type === "date" || type === "time") {
38
38
  const dateValue = value instanceof Date ? value : new Date(value);
@@ -42,7 +42,7 @@ const formatArgument = (value, type, style, locale) => {
42
42
  "long",
43
43
  "full"
44
44
  ].includes(style ?? "") ? style : type === "date" ? "medium" : "short";
45
- return getCachedIntl(Intl.DateTimeFormat, locale, type === "date" ? { dateStyle: dateTimeStyle } : { timeStyle: dateTimeStyle }).format(dateValue);
45
+ return getCachedIntl("DateTimeFormat", locale, type === "date" ? { dateStyle: dateTimeStyle } : { timeStyle: dateTimeStyle }).format(dateValue);
46
46
  }
47
47
  } catch {}
48
48
  return String(value);
@@ -91,7 +91,8 @@ const resolveMessageNode = (node, values = {}, locale = "en") => {
91
91
  if (typedNode.nodeType === NodeTypes.HTML) return resolveMessageNode(typedNode[NodeTypes.HTML], values, locale);
92
92
  if (typedNode.nodeType === NodeTypes.PLURAL) {
93
93
  const pluralState = typedNode[NodeTypes.PLURAL];
94
- return resolveMessageNode(getPlural(pluralState, Number(getSelectorValue(values, "count") ?? 1), locale), values, locale);
94
+ const selected = getPlural(pluralState, Number(getSelectorValue(values, "count") ?? 1), locale);
95
+ return resolveMessageNode(selected, values, locale);
95
96
  }
96
97
  if (typedNode.nodeType === NodeTypes.ENUMERATION) {
97
98
  const enumerationState = typedNode[NodeTypes.ENUMERATION];
@@ -103,7 +104,7 @@ const resolveMessageNode = (node, values = {}, locale = "en") => {
103
104
  let selected;
104
105
  if (isOrdinal && !Number.isNaN(Number(selector))) {
105
106
  const ordinalCount = Number(selector);
106
- const ordinalCategory = getCachedIntl(Intl.PluralRules, locale, { type: "ordinal" }).select(ordinalCount);
107
+ const ordinalCategory = getCachedIntl("PluralRules", locale, { type: "ordinal" }).select(ordinalCount);
107
108
  selected = options[String(ordinalCount)] ?? options[ordinalCategory] ?? options.fallback ?? options.other;
108
109
  } else if (typeof selector === "number" || !Number.isNaN(Number(selector))) selected = getEnumeration(options, Number(selector));
109
110
  else selected = options[String(selector)] ?? options.fallback ?? options.other;
@@ -111,7 +112,8 @@ const resolveMessageNode = (node, values = {}, locale = "en") => {
111
112
  }
112
113
  if (typedNode.nodeType === NodeTypes.GENDER) {
113
114
  const genderState = typedNode[NodeTypes.GENDER];
114
- return resolveMessageNode(genderState[String(values.gender ?? "")] ?? genderState.fallback ?? genderState.other, values, locale);
115
+ const selected = genderState[String(values.gender ?? "")] ?? genderState.fallback ?? genderState.other;
116
+ return resolveMessageNode(selected, values, locale);
115
117
  }
116
118
  return node;
117
119
  };
@@ -139,7 +141,8 @@ const DIALECT_FORMATTERS = {
139
141
  * ```
140
142
  */
141
143
  const resolveMessage = (message, values = {}, locale = "en", dialect = "icu") => {
142
- const resolved = resolveMessageNode(typeof message === "string" ? DIALECT_FORMATTERS[dialect](message) : message, values, locale);
144
+ const node = typeof message === "string" ? DIALECT_FORMATTERS[dialect](message) : message;
145
+ const resolved = resolveMessageNode(node, values, locale);
143
146
  return typeof resolved === "string" ? resolved : String(resolved ?? "");
144
147
  };
145
148
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"resolveMessage.mjs","names":[],"sources":["../../../src/messageFormat/resolveMessage.ts"],"sourcesContent":["import type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport { getCachedIntl } from '../formatters';\nimport { getEnumeration } from '../interpreter/getEnumeration';\nimport { getPlural } from '../interpreter/getPlural';\nimport type { PluralContentState } from '../transpiler/plural/plural';\nimport { icuToIntlayerFormatter } from './ICU';\nimport { i18nextToIntlayerFormatter } from './i18next';\nimport { vueI18nToIntlayerFormatter } from './vue-i18n';\n\n/**\n * Runtime counterpart of the `messageFormat` converters.\n *\n * The converters (`icuToIntlayerFormatter`, `i18nextToIntlayerFormatter`,\n * `vueI18nToIntlayerFormatter`) turn library-specific message syntax into\n * intlayer nodes (`insert`, `plural`, `enu`, `gender`, `html`). This module\n * resolves those nodes — or raw message strings — into a final string using\n * the provided interpolation values and locale.\n *\n * It is the mutualized resolution engine used by the compat adapter packages\n * (`@intlayer/i18next`, `@intlayer/next-intl`, `@intlayer/vue-i18n`, …).\n */\n\n/** Message syntax dialect of the source i18n library. */\nexport type MessageFormatDialect = 'icu' | 'i18next' | 'vue-i18n';\n\n/** Interpolation values passed alongside a translation lookup. */\nexport type MessageValues = Record<string, unknown>;\n\n/** Internal enumeration metadata keys injected by the converters. */\nconst ENUMERATION_METADATA_KEYS = [\n '__intlayer_icu_var',\n '__intlayer_icu_ordinal',\n '__intlayer_vue_i18n_var',\n] as const;\n\n/**\n * Resolves a possibly-dotted path (`user.name`) inside the values object.\n */\nconst resolveValuePath = (values: MessageValues, path: string): unknown => {\n if (path in values) return values[path];\n\n let current: unknown = values;\n for (const part of path.split('.')) {\n if (\n current === null ||\n current === undefined ||\n typeof current !== 'object'\n ) {\n return undefined;\n }\n current = (current as Record<string, unknown>)[part];\n }\n return current;\n};\n\n/** Formats an ICU-style formatted argument (`{value, number, percent}`). */\nconst formatArgument = (\n value: unknown,\n type: string,\n style: string | undefined,\n locale: LocalesValues\n): string => {\n try {\n if (type === 'number') {\n const numberValue = Number(value);\n if (style === 'percent') {\n return getCachedIntl(Intl.NumberFormat, locale, {\n style: 'percent',\n }).format(numberValue);\n }\n if (style === 'integer') {\n return getCachedIntl(Intl.NumberFormat, locale, {\n maximumFractionDigits: 0,\n }).format(numberValue);\n }\n return getCachedIntl(Intl.NumberFormat, locale).format(numberValue);\n }\n\n if (type === 'date' || type === 'time') {\n const dateValue =\n value instanceof Date ? value : new Date(value as string | number);\n const dateTimeStyle = (\n ['short', 'medium', 'long', 'full'].includes(style ?? '')\n ? style\n : type === 'date'\n ? 'medium'\n : 'short'\n ) as 'short' | 'medium' | 'long' | 'full';\n\n return getCachedIntl(\n Intl.DateTimeFormat,\n locale,\n type === 'date'\n ? { dateStyle: dateTimeStyle }\n : { timeStyle: dateTimeStyle }\n ).format(dateValue);\n }\n } catch {\n // Fall through to the raw string representation below\n }\n\n return String(value);\n};\n\n/**\n * Interpolates a message template with values.\n *\n * Handles, in order:\n * 1. Intlayer insertions `{{name}}` (whitespace-tolerant, dotted paths)\n * 2. ICU formatted arguments `{value, number}` / `{ts, date, long}`\n * 3. Bare single-brace arguments `{name}` (ICU / vue-i18n simple args)\n */\nexport const interpolateMessage = (\n template: string,\n values: MessageValues = {},\n locale: LocalesValues = 'en' as LocalesValues\n): string =>\n template\n .replace(/\\{\\{\\s*([^{}]+?)\\s*\\}\\}/g, (match, path: string) => {\n const value = resolveValuePath(values, path);\n return value === undefined ? match : String(value);\n })\n .replace(\n /\\{\\s*([\\w.]+)\\s*,\\s*(\\w+)\\s*(?:,\\s*([^}]+?)\\s*)?\\}/g,\n (match, path: string, type: string, style: string | undefined) => {\n const value = resolveValuePath(values, path);\n if (value === undefined) return match;\n return formatArgument(value, type, style, locale);\n }\n )\n .replace(/\\{\\s*([\\w.]+)\\s*\\}/g, (match, path: string) => {\n const value = resolveValuePath(values, path);\n return value === undefined ? match : String(value);\n });\n\n/** Reads the selector value of an enumeration/plural node from the values. */\nconst getSelectorValue = (\n values: MessageValues,\n variableName: string\n): unknown => values[variableName] ?? values.count ?? values.n;\n\n/**\n * Resolves an intlayer message node tree (as produced by the\n * `*ToIntlayerFormatter` converters, or already present in a built\n * dictionary) into its final value using interpolation values and locale.\n *\n * Function nodes (produced by the interpreter plugins for `insertion`,\n * `enumeration` and `plural` content) are invoked with the values.\n */\nexport const resolveMessageNode = (\n node: unknown,\n values: MessageValues = {},\n locale: LocalesValues = 'en' as LocalesValues\n): unknown => {\n if (node === null || node === undefined) return node;\n\n if (typeof node === 'string') {\n return interpolateMessage(node, values, locale);\n }\n\n if (typeof node === 'number' || typeof node === 'boolean') {\n return String(node);\n }\n\n // Interpreter-transformed nodes (insertion/enumeration/plural plugins)\n // are exposed as callables taking the interpolation values.\n if (typeof node === 'function') {\n try {\n return resolveMessageNode(\n (node as (arg: MessageValues) => unknown)(values),\n values,\n locale\n );\n } catch {\n return undefined;\n }\n }\n\n if (Array.isArray(node)) {\n return node\n .map((item) => String(resolveMessageNode(item, values, locale) ?? ''))\n .join('');\n }\n\n const typedNode = node as Record<string, unknown> & { nodeType?: string };\n\n if (typedNode.nodeType === NodeTypes.INSERTION) {\n return resolveMessageNode(typedNode[NodeTypes.INSERTION], values, locale);\n }\n\n if (typedNode.nodeType === NodeTypes.HTML) {\n // Tags are kept intact — rich rendering is handled by the caller\n return resolveMessageNode(typedNode[NodeTypes.HTML], values, locale);\n }\n\n if (typedNode.nodeType === NodeTypes.PLURAL) {\n const pluralState = typedNode[\n NodeTypes.PLURAL\n ] as PluralContentState<unknown>;\n const count = Number(getSelectorValue(values, 'count') ?? 1);\n const selected = getPlural(\n pluralState as PluralContentState<string>,\n count,\n locale\n );\n return resolveMessageNode(selected, values, locale);\n }\n\n if (typedNode.nodeType === NodeTypes.ENUMERATION) {\n const enumerationState = typedNode[NodeTypes.ENUMERATION] as Record<\n string,\n unknown\n >;\n\n const variableName = (ENUMERATION_METADATA_KEYS.map(\n (metadataKey) => enumerationState[metadataKey]\n ).find((name) => typeof name === 'string') ?? 'count') as string;\n\n const isOrdinal = enumerationState.__intlayer_icu_ordinal === true;\n\n const options: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(enumerationState)) {\n if (!(ENUMERATION_METADATA_KEYS as readonly string[]).includes(key)) {\n options[key] = value;\n }\n }\n\n const selector = getSelectorValue(values, variableName);\n\n let selected: unknown;\n if (isOrdinal && !Number.isNaN(Number(selector))) {\n // ICU `selectordinal` — exact numeric match first, then the CLDR\n // ordinal category, then the fallback\n const ordinalCount = Number(selector);\n const ordinalCategory = getCachedIntl(Intl.PluralRules, locale, {\n type: 'ordinal',\n }).select(ordinalCount);\n selected =\n options[String(ordinalCount)] ??\n options[ordinalCategory] ??\n options.fallback ??\n options.other;\n } else if (\n typeof selector === 'number' ||\n !Number.isNaN(Number(selector))\n ) {\n selected = getEnumeration(options, Number(selector));\n } else {\n // String selector — ICU `select` converted to an enumeration\n selected = options[String(selector)] ?? options.fallback ?? options.other;\n }\n\n return resolveMessageNode(selected, values, locale);\n }\n\n if (typedNode.nodeType === NodeTypes.GENDER) {\n const genderState = typedNode[NodeTypes.GENDER] as Record<string, unknown>;\n const genderValue = String(values.gender ?? '');\n const selected =\n genderState[genderValue] ?? genderState.fallback ?? genderState.other;\n return resolveMessageNode(selected, values, locale);\n }\n\n return node;\n};\n\nconst DIALECT_FORMATTERS: Record<\n MessageFormatDialect,\n (message: string) => unknown\n> = {\n icu: (message) => icuToIntlayerFormatter(message),\n i18next: (message) => i18nextToIntlayerFormatter(message),\n 'vue-i18n': (message) => vueI18nToIntlayerFormatter(message),\n};\n\n/**\n * Resolves a raw message — string in a library dialect, or an intlayer node\n * tree — into a final string using interpolation values and locale.\n *\n * @example\n * ```ts\n * resolveMessage('Hello {name}', { name: 'John' }, 'en', 'icu');\n * // 'Hello John'\n *\n * resolveMessage(\n * '{count, plural, one {# item} other {# items}}',\n * { count: 3 },\n * 'en',\n * 'icu'\n * );\n * // '3 items'\n * ```\n */\nexport const resolveMessage = (\n message: unknown,\n values: MessageValues = {},\n locale: LocalesValues = 'en' as LocalesValues,\n dialect: MessageFormatDialect = 'icu'\n): string => {\n const node =\n typeof message === 'string'\n ? DIALECT_FORMATTERS[dialect](message)\n : message;\n\n const resolved = resolveMessageNode(node, values, locale);\n\n return typeof resolved === 'string' ? resolved : String(resolved ?? '');\n};\n\n/** A parsed token of a tagged message: plain text or a tag with children. */\nexport type TaggedMessageToken =\n | string\n | { tag: string; children: TaggedMessageToken[] };\n\n/**\n * Tokenizes a message containing XML-like tags (`'Visit <link>the docs</link>'`,\n * `'hello <1>{{name}}</1>'`, `'line<br/>break'`) into a token tree.\n *\n * Used by rich-text renderers (`t.rich`, `<Trans components>`,\n * `<i18n-t>` slots) to map tags to framework elements.\n */\nexport const parseTaggedMessage = (message: string): TaggedMessageToken[] => {\n const tokens: TaggedMessageToken[] = [];\n const tagRegex = /<([\\w-]+)\\s*\\/>|<([\\w-]+)[^>]*>([\\s\\S]*?)<\\/\\2>/g;\n let lastIndex = 0;\n let match = tagRegex.exec(message);\n\n while (match !== null) {\n if (match.index > lastIndex) {\n tokens.push(message.slice(lastIndex, match.index));\n }\n\n const [, selfClosingTag, tag, inner] = match;\n\n if (selfClosingTag) {\n tokens.push({ tag: selfClosingTag, children: [] });\n } else {\n tokens.push({ tag, children: parseTaggedMessage(inner) });\n }\n\n lastIndex = match.index + match[0].length;\n match = tagRegex.exec(message);\n }\n\n if (lastIndex < message.length) {\n tokens.push(message.slice(lastIndex));\n }\n\n return tokens;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"resolveMessage.mjs","names":[],"sources":["../../../src/messageFormat/resolveMessage.ts"],"sourcesContent":["import type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport { getCachedIntl } from '../formatters';\nimport { getEnumeration } from '../interpreter/getEnumeration';\nimport { getPlural } from '../interpreter/getPlural';\nimport type { PluralContentState } from '../transpiler/plural/plural';\nimport { icuToIntlayerFormatter } from './ICU';\nimport { i18nextToIntlayerFormatter } from './i18next';\nimport { vueI18nToIntlayerFormatter } from './vue-i18n';\n\n/**\n * Runtime counterpart of the `messageFormat` converters.\n *\n * The converters (`icuToIntlayerFormatter`, `i18nextToIntlayerFormatter`,\n * `vueI18nToIntlayerFormatter`) turn library-specific message syntax into\n * intlayer nodes (`insert`, `plural`, `enu`, `gender`, `html`). This module\n * resolves those nodes — or raw message strings — into a final string using\n * the provided interpolation values and locale.\n *\n * It is the mutualized resolution engine used by the compat adapter packages\n * (`@intlayer/i18next`, `@intlayer/next-intl`, `@intlayer/vue-i18n`, …).\n */\n\n/** Message syntax dialect of the source i18n library. */\nexport type MessageFormatDialect = 'icu' | 'i18next' | 'vue-i18n';\n\n/** Interpolation values passed alongside a translation lookup. */\nexport type MessageValues = Record<string, unknown>;\n\n/** Internal enumeration metadata keys injected by the converters. */\nconst ENUMERATION_METADATA_KEYS = [\n '__intlayer_icu_var',\n '__intlayer_icu_ordinal',\n '__intlayer_vue_i18n_var',\n] as const;\n\n/**\n * Resolves a possibly-dotted path (`user.name`) inside the values object.\n */\nconst resolveValuePath = (values: MessageValues, path: string): unknown => {\n if (path in values) return values[path];\n\n let current: unknown = values;\n for (const part of path.split('.')) {\n if (\n current === null ||\n current === undefined ||\n typeof current !== 'object'\n ) {\n return undefined;\n }\n current = (current as Record<string, unknown>)[part];\n }\n return current;\n};\n\n/** Formats an ICU-style formatted argument (`{value, number, percent}`). */\nconst formatArgument = (\n value: unknown,\n type: string,\n style: string | undefined,\n locale: LocalesValues\n): string => {\n try {\n if (type === 'number') {\n const numberValue = Number(value);\n if (style === 'percent') {\n return getCachedIntl('NumberFormat', locale, {\n style: 'percent',\n }).format(numberValue);\n }\n if (style === 'integer') {\n return getCachedIntl('NumberFormat', locale, {\n maximumFractionDigits: 0,\n }).format(numberValue);\n }\n return getCachedIntl('NumberFormat', locale).format(numberValue);\n }\n\n if (type === 'date' || type === 'time') {\n const dateValue =\n value instanceof Date ? value : new Date(value as string | number);\n const dateTimeStyle = (\n ['short', 'medium', 'long', 'full'].includes(style ?? '')\n ? style\n : type === 'date'\n ? 'medium'\n : 'short'\n ) as 'short' | 'medium' | 'long' | 'full';\n\n return getCachedIntl(\n 'DateTimeFormat',\n locale,\n type === 'date'\n ? { dateStyle: dateTimeStyle }\n : { timeStyle: dateTimeStyle }\n ).format(dateValue);\n }\n } catch {\n // Fall through to the raw string representation below\n }\n\n return String(value);\n};\n\n/**\n * Interpolates a message template with values.\n *\n * Handles, in order:\n * 1. Intlayer insertions `{{name}}` (whitespace-tolerant, dotted paths)\n * 2. ICU formatted arguments `{value, number}` / `{ts, date, long}`\n * 3. Bare single-brace arguments `{name}` (ICU / vue-i18n simple args)\n */\nexport const interpolateMessage = (\n template: string,\n values: MessageValues = {},\n locale: LocalesValues = 'en' as LocalesValues\n): string =>\n template\n .replace(/\\{\\{\\s*([^{}]+?)\\s*\\}\\}/g, (match, path: string) => {\n const value = resolveValuePath(values, path);\n return value === undefined ? match : String(value);\n })\n .replace(\n /\\{\\s*([\\w.]+)\\s*,\\s*(\\w+)\\s*(?:,\\s*([^}]+?)\\s*)?\\}/g,\n (match, path: string, type: string, style: string | undefined) => {\n const value = resolveValuePath(values, path);\n if (value === undefined) return match;\n return formatArgument(value, type, style, locale);\n }\n )\n .replace(/\\{\\s*([\\w.]+)\\s*\\}/g, (match, path: string) => {\n const value = resolveValuePath(values, path);\n return value === undefined ? match : String(value);\n });\n\n/** Reads the selector value of an enumeration/plural node from the values. */\nconst getSelectorValue = (\n values: MessageValues,\n variableName: string\n): unknown => values[variableName] ?? values.count ?? values.n;\n\n/**\n * Resolves an intlayer message node tree (as produced by the\n * `*ToIntlayerFormatter` converters, or already present in a built\n * dictionary) into its final value using interpolation values and locale.\n *\n * Function nodes (produced by the interpreter plugins for `insertion`,\n * `enumeration` and `plural` content) are invoked with the values.\n */\nexport const resolveMessageNode = (\n node: unknown,\n values: MessageValues = {},\n locale: LocalesValues = 'en' as LocalesValues\n): unknown => {\n if (node === null || node === undefined) return node;\n\n if (typeof node === 'string') {\n return interpolateMessage(node, values, locale);\n }\n\n if (typeof node === 'number' || typeof node === 'boolean') {\n return String(node);\n }\n\n // Interpreter-transformed nodes (insertion/enumeration/plural plugins)\n // are exposed as callables taking the interpolation values.\n if (typeof node === 'function') {\n try {\n return resolveMessageNode(\n (node as (arg: MessageValues) => unknown)(values),\n values,\n locale\n );\n } catch {\n return undefined;\n }\n }\n\n if (Array.isArray(node)) {\n return node\n .map((item) => String(resolveMessageNode(item, values, locale) ?? ''))\n .join('');\n }\n\n const typedNode = node as Record<string, unknown> & { nodeType?: string };\n\n if (typedNode.nodeType === NodeTypes.INSERTION) {\n return resolveMessageNode(typedNode[NodeTypes.INSERTION], values, locale);\n }\n\n if (typedNode.nodeType === NodeTypes.HTML) {\n // Tags are kept intact — rich rendering is handled by the caller\n return resolveMessageNode(typedNode[NodeTypes.HTML], values, locale);\n }\n\n if (typedNode.nodeType === NodeTypes.PLURAL) {\n const pluralState = typedNode[\n NodeTypes.PLURAL\n ] as PluralContentState<unknown>;\n const count = Number(getSelectorValue(values, 'count') ?? 1);\n const selected = getPlural(\n pluralState as PluralContentState<string>,\n count,\n locale\n );\n return resolveMessageNode(selected, values, locale);\n }\n\n if (typedNode.nodeType === NodeTypes.ENUMERATION) {\n const enumerationState = typedNode[NodeTypes.ENUMERATION] as Record<\n string,\n unknown\n >;\n\n const variableName = (ENUMERATION_METADATA_KEYS.map(\n (metadataKey) => enumerationState[metadataKey]\n ).find((name) => typeof name === 'string') ?? 'count') as string;\n\n const isOrdinal = enumerationState.__intlayer_icu_ordinal === true;\n\n const options: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(enumerationState)) {\n if (!(ENUMERATION_METADATA_KEYS as readonly string[]).includes(key)) {\n options[key] = value;\n }\n }\n\n const selector = getSelectorValue(values, variableName);\n\n let selected: unknown;\n if (isOrdinal && !Number.isNaN(Number(selector))) {\n // ICU `selectordinal` — exact numeric match first, then the CLDR\n // ordinal category, then the fallback\n const ordinalCount = Number(selector);\n const ordinalCategory = getCachedIntl('PluralRules', locale, {\n type: 'ordinal',\n }).select(ordinalCount);\n selected =\n options[String(ordinalCount)] ??\n options[ordinalCategory] ??\n options.fallback ??\n options.other;\n } else if (\n typeof selector === 'number' ||\n !Number.isNaN(Number(selector))\n ) {\n selected = getEnumeration(options, Number(selector));\n } else {\n // String selector — ICU `select` converted to an enumeration\n selected = options[String(selector)] ?? options.fallback ?? options.other;\n }\n\n return resolveMessageNode(selected, values, locale);\n }\n\n if (typedNode.nodeType === NodeTypes.GENDER) {\n const genderState = typedNode[NodeTypes.GENDER] as Record<string, unknown>;\n const genderValue = String(values.gender ?? '');\n const selected =\n genderState[genderValue] ?? genderState.fallback ?? genderState.other;\n return resolveMessageNode(selected, values, locale);\n }\n\n return node;\n};\n\nconst DIALECT_FORMATTERS: Record<\n MessageFormatDialect,\n (message: string) => unknown\n> = {\n icu: (message) => icuToIntlayerFormatter(message),\n i18next: (message) => i18nextToIntlayerFormatter(message),\n 'vue-i18n': (message) => vueI18nToIntlayerFormatter(message),\n};\n\n/**\n * Resolves a raw message — string in a library dialect, or an intlayer node\n * tree — into a final string using interpolation values and locale.\n *\n * @example\n * ```ts\n * resolveMessage('Hello {name}', { name: 'John' }, 'en', 'icu');\n * // 'Hello John'\n *\n * resolveMessage(\n * '{count, plural, one {# item} other {# items}}',\n * { count: 3 },\n * 'en',\n * 'icu'\n * );\n * // '3 items'\n * ```\n */\nexport const resolveMessage = (\n message: unknown,\n values: MessageValues = {},\n locale: LocalesValues = 'en' as LocalesValues,\n dialect: MessageFormatDialect = 'icu'\n): string => {\n const node =\n typeof message === 'string'\n ? DIALECT_FORMATTERS[dialect](message)\n : message;\n\n const resolved = resolveMessageNode(node, values, locale);\n\n return typeof resolved === 'string' ? resolved : String(resolved ?? '');\n};\n\n/** A parsed token of a tagged message: plain text or a tag with children. */\nexport type TaggedMessageToken =\n | string\n | { tag: string; children: TaggedMessageToken[] };\n\n/**\n * Tokenizes a message containing XML-like tags (`'Visit <link>the docs</link>'`,\n * `'hello <1>{{name}}</1>'`, `'line<br/>break'`) into a token tree.\n *\n * Used by rich-text renderers (`t.rich`, `<Trans components>`,\n * `<i18n-t>` slots) to map tags to framework elements.\n */\nexport const parseTaggedMessage = (message: string): TaggedMessageToken[] => {\n const tokens: TaggedMessageToken[] = [];\n const tagRegex = /<([\\w-]+)\\s*\\/>|<([\\w-]+)[^>]*>([\\s\\S]*?)<\\/\\2>/g;\n let lastIndex = 0;\n let match = tagRegex.exec(message);\n\n while (match !== null) {\n if (match.index > lastIndex) {\n tokens.push(message.slice(lastIndex, match.index));\n }\n\n const [, selfClosingTag, tag, inner] = match;\n\n if (selfClosingTag) {\n tokens.push({ tag: selfClosingTag, children: [] });\n } else {\n tokens.push({ tag, children: parseTaggedMessage(inner) });\n }\n\n lastIndex = match.index + match[0].length;\n match = tagRegex.exec(message);\n }\n\n if (lastIndex < message.length) {\n tokens.push(message.slice(lastIndex));\n }\n\n return tokens;\n};\n"],"mappings":"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"}