@intlayer/core 8.9.4-canary.0 → 8.9.4

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 (34) hide show
  1. package/dist/cjs/dictionaryManipulator/orderDictionaries.cjs +2 -2
  2. package/dist/cjs/dictionaryManipulator/orderDictionaries.cjs.map +1 -1
  3. package/dist/cjs/index.cjs +3 -0
  4. package/dist/cjs/messageFormat/ICU.cjs +47 -12
  5. package/dist/cjs/messageFormat/ICU.cjs.map +1 -1
  6. package/dist/cjs/messageFormat/i18next.cjs +49 -12
  7. package/dist/cjs/messageFormat/i18next.cjs.map +1 -1
  8. package/dist/cjs/messageFormat/index.cjs +3 -0
  9. package/dist/cjs/messageFormat/po.cjs +171 -0
  10. package/dist/cjs/messageFormat/po.cjs.map +1 -0
  11. package/dist/cjs/messageFormat/vue-i18n.cjs +23 -9
  12. package/dist/cjs/messageFormat/vue-i18n.cjs.map +1 -1
  13. package/dist/esm/dictionaryManipulator/orderDictionaries.mjs +2 -2
  14. package/dist/esm/dictionaryManipulator/orderDictionaries.mjs.map +1 -1
  15. package/dist/esm/index.mjs +2 -1
  16. package/dist/esm/messageFormat/ICU.mjs +47 -12
  17. package/dist/esm/messageFormat/ICU.mjs.map +1 -1
  18. package/dist/esm/messageFormat/i18next.mjs +49 -12
  19. package/dist/esm/messageFormat/i18next.mjs.map +1 -1
  20. package/dist/esm/messageFormat/index.mjs +2 -1
  21. package/dist/esm/messageFormat/po.mjs +167 -0
  22. package/dist/esm/messageFormat/po.mjs.map +1 -0
  23. package/dist/esm/messageFormat/vue-i18n.mjs +23 -9
  24. package/dist/esm/messageFormat/vue-i18n.mjs.map +1 -1
  25. package/dist/types/dictionaryManipulator/orderDictionaries.d.ts +5 -1
  26. package/dist/types/dictionaryManipulator/orderDictionaries.d.ts.map +1 -1
  27. package/dist/types/index.d.ts +2 -1
  28. package/dist/types/messageFormat/ICU.d.ts.map +1 -1
  29. package/dist/types/messageFormat/i18next.d.ts.map +1 -1
  30. package/dist/types/messageFormat/index.d.ts +2 -1
  31. package/dist/types/messageFormat/po.d.ts +15 -0
  32. package/dist/types/messageFormat/po.d.ts.map +1 -0
  33. package/dist/types/messageFormat/vue-i18n.d.ts.map +1 -1
  34. package/package.json +6 -6
@@ -10,8 +10,8 @@ let _intlayer_config_built = require("@intlayer/config/built");
10
10
  * @param priorityStrategy - The priority strategy ('local_first' or 'distant_first')
11
11
  * @returns Ordered array of dictionaries
12
12
  */
13
- const orderDictionaries = (dictionaries) => {
14
- const { dictionaryPriorityStrategy } = _intlayer_config_built.editor;
13
+ const orderDictionaries = (dictionaries, config) => {
14
+ const dictionaryPriorityStrategy = config?.editor?.dictionaryPriorityStrategy ?? _intlayer_config_built.editor.dictionaryPriorityStrategy;
15
15
  if (dictionaries.length <= 1) return dictionaries;
16
16
  const withIndex = dictionaries.map((dictionary, index) => ({
17
17
  dictionary,
@@ -1 +1 @@
1
- {"version":3,"file":"orderDictionaries.cjs","names":["editor"],"sources":["../../../src/dictionaryManipulator/orderDictionaries.ts"],"sourcesContent":["import { editor } from '@intlayer/config/built';\nimport type { Dictionary } from '@intlayer/types/dictionary';\n\n/**\n * Orders dictionaries based on the dictionary priority strategy.\n *\n * @param dictionaries - Array of dictionaries to order\n * @param priorityStrategy - The priority strategy ('local_first' or 'distant_first')\n * @returns Ordered array of dictionaries\n */\nexport const orderDictionaries = (dictionaries: Dictionary[]): Dictionary[] => {\n const { dictionaryPriorityStrategy } = editor;\n\n if (dictionaries.length <= 1) {\n return dictionaries;\n }\n\n // Stabilize original indices to preserve relative order for complete ties\n const withIndex = dictionaries.map((dictionary, index) => ({\n dictionary,\n index,\n }));\n\n const getPriority = (dictionary: Dictionary): number => {\n const p = dictionary.priority ?? 0;\n\n return Number.isFinite(p) ? p : 0;\n };\n\n const getLocationWeight = (d: Dictionary): number => {\n const location = d.location;\n\n // undefined location should always be last\n if (location === undefined) {\n return 2;\n }\n\n if (dictionaryPriorityStrategy === 'distant_first') {\n // distant should come first\n return location === 'remote' ? 0 : 1;\n }\n // default: local_first\n return location === 'local' ? 0 : 1;\n };\n\n withIndex.sort((a, b) => {\n // 1) Non-autoFilled before autoFilled (autoFilled have lower precedence)\n const aAuto = a.dictionary.filled ? 1 : 0;\n const bAuto = b.dictionary.filled ? 1 : 0;\n if (aAuto !== bAuto) return aAuto - bAuto; // 0 before 1\n\n // 2) Higher priority first (larger number wins)\n const aP = getPriority(a.dictionary);\n const bP = getPriority(b.dictionary);\n if (aP !== bP) return bP - aP; // descending\n\n // 3) Location according to strategy\n const aLocation = getLocationWeight(a.dictionary);\n const bLocation = getLocationWeight(b.dictionary);\n if (aLocation !== bLocation) return aLocation - bLocation;\n\n // 4) Stable fallback by original index\n return a.index - b.index;\n });\n\n return withIndex.map(({ dictionary }) => dictionary);\n};\n"],"mappings":";;;;;;;;;;;;AAUA,MAAa,qBAAqB,iBAA6C;CAC7E,MAAM,EAAE,+BAA+BA;CAEvC,IAAI,aAAa,UAAU,GACzB,OAAO;CAIT,MAAM,YAAY,aAAa,KAAK,YAAY,WAAW;EACzD;EACA;EACD,EAAE;CAEH,MAAM,eAAe,eAAmC;EACtD,MAAM,IAAI,WAAW,YAAY;EAEjC,OAAO,OAAO,SAAS,EAAE,GAAG,IAAI;;CAGlC,MAAM,qBAAqB,MAA0B;EACnD,MAAM,WAAW,EAAE;EAGnB,IAAI,aAAa,QACf,OAAO;EAGT,IAAI,+BAA+B,iBAEjC,OAAO,aAAa,WAAW,IAAI;EAGrC,OAAO,aAAa,UAAU,IAAI;;CAGpC,UAAU,MAAM,GAAG,MAAM;EAEvB,MAAM,QAAQ,EAAE,WAAW,SAAS,IAAI;EACxC,MAAM,QAAQ,EAAE,WAAW,SAAS,IAAI;EACxC,IAAI,UAAU,OAAO,OAAO,QAAQ;EAGpC,MAAM,KAAK,YAAY,EAAE,WAAW;EACpC,MAAM,KAAK,YAAY,EAAE,WAAW;EACpC,IAAI,OAAO,IAAI,OAAO,KAAK;EAG3B,MAAM,YAAY,kBAAkB,EAAE,WAAW;EACjD,MAAM,YAAY,kBAAkB,EAAE,WAAW;EACjD,IAAI,cAAc,WAAW,OAAO,YAAY;EAGhD,OAAO,EAAE,QAAQ,EAAE;GACnB;CAEF,OAAO,UAAU,KAAK,EAAE,iBAAiB,WAAW"}
1
+ {"version":3,"file":"orderDictionaries.cjs","names":["editor"],"sources":["../../../src/dictionaryManipulator/orderDictionaries.ts"],"sourcesContent":["import { editor } from '@intlayer/config/built';\nimport type { Dictionary } from '@intlayer/types/dictionary';\n\n/**\n * Orders dictionaries based on the dictionary priority strategy.\n *\n * @param dictionaries - Array of dictionaries to order\n * @param priorityStrategy - The priority strategy ('local_first' or 'distant_first')\n * @returns Ordered array of dictionaries\n */\nexport const orderDictionaries = (\n dictionaries: Dictionary[],\n config?: {\n editor: {\n dictionaryPriorityStrategy: 'local_first' | 'distant_first';\n };\n }\n): Dictionary[] => {\n const dictionaryPriorityStrategy =\n config?.editor?.dictionaryPriorityStrategy ??\n editor.dictionaryPriorityStrategy;\n\n if (dictionaries.length <= 1) {\n return dictionaries;\n }\n\n // Stabilize original indices to preserve relative order for complete ties\n const withIndex = dictionaries.map((dictionary, index) => ({\n dictionary,\n index,\n }));\n\n const getPriority = (dictionary: Dictionary): number => {\n const p = dictionary.priority ?? 0;\n\n return Number.isFinite(p) ? p : 0;\n };\n\n const getLocationWeight = (d: Dictionary): number => {\n const location = d.location;\n\n // undefined location should always be last\n if (location === undefined) {\n return 2;\n }\n\n if (dictionaryPriorityStrategy === 'distant_first') {\n // distant should come first\n return location === 'remote' ? 0 : 1;\n }\n // default: local_first\n return location === 'local' ? 0 : 1;\n };\n\n withIndex.sort((a, b) => {\n // 1) Non-autoFilled before autoFilled (autoFilled have lower precedence)\n const aAuto = a.dictionary.filled ? 1 : 0;\n const bAuto = b.dictionary.filled ? 1 : 0;\n if (aAuto !== bAuto) return aAuto - bAuto; // 0 before 1\n\n // 2) Higher priority first (larger number wins)\n const aP = getPriority(a.dictionary);\n const bP = getPriority(b.dictionary);\n if (aP !== bP) return bP - aP; // descending\n\n // 3) Location according to strategy\n const aLocation = getLocationWeight(a.dictionary);\n const bLocation = getLocationWeight(b.dictionary);\n if (aLocation !== bLocation) return aLocation - bLocation;\n\n // 4) Stable fallback by original index\n return a.index - b.index;\n });\n\n return withIndex.map(({ dictionary }) => dictionary);\n};\n"],"mappings":";;;;;;;;;;;;AAUA,MAAa,qBACX,cACA,WAKiB;CACjB,MAAM,6BACJ,QAAQ,QAAQ,8BAChBA,8BAAO;CAET,IAAI,aAAa,UAAU,GACzB,OAAO;CAIT,MAAM,YAAY,aAAa,KAAK,YAAY,WAAW;EACzD;EACA;EACD,EAAE;CAEH,MAAM,eAAe,eAAmC;EACtD,MAAM,IAAI,WAAW,YAAY;EAEjC,OAAO,OAAO,SAAS,EAAE,GAAG,IAAI;;CAGlC,MAAM,qBAAqB,MAA0B;EACnD,MAAM,WAAW,EAAE;EAGnB,IAAI,aAAa,QACf,OAAO;EAGT,IAAI,+BAA+B,iBAEjC,OAAO,aAAa,WAAW,IAAI;EAGrC,OAAO,aAAa,UAAU,IAAI;;CAGpC,UAAU,MAAM,GAAG,MAAM;EAEvB,MAAM,QAAQ,EAAE,WAAW,SAAS,IAAI;EACxC,MAAM,QAAQ,EAAE,WAAW,SAAS,IAAI;EACxC,IAAI,UAAU,OAAO,OAAO,QAAQ;EAGpC,MAAM,KAAK,YAAY,EAAE,WAAW;EACpC,MAAM,KAAK,YAAY,EAAE,WAAW;EACpC,IAAI,OAAO,IAAI,OAAO,KAAK;EAG3B,MAAM,YAAY,kBAAkB,EAAE,WAAW;EACjD,MAAM,YAAY,kBAAkB,EAAE,WAAW;EACjD,IAAI,cAAc,WAAW,OAAO,YAAY;EAGhD,OAAO,EAAE,QAAQ,EAAE;GACnB;CAEF,OAAO,UAAU,KAAK,EAAE,iBAAiB,WAAW"}
@@ -84,6 +84,7 @@ const require_markdown_renderer = require('./markdown/renderer.cjs');
84
84
  const require_markdown_compiler = require('./markdown/compiler.cjs');
85
85
  const require_messageFormat_ICU = require('./messageFormat/ICU.cjs');
86
86
  const require_messageFormat_i18next = require('./messageFormat/i18next.cjs');
87
+ const require_messageFormat_po = require('./messageFormat/po.cjs');
87
88
  const require_messageFormat_vue_i18n = require('./messageFormat/vue-i18n.cjs');
88
89
  const require_utils_isSameKeyPath = require('./utils/isSameKeyPath.cjs');
89
90
 
@@ -265,6 +266,7 @@ exports.insertContentInDictionary = require_deepTransformPlugins_insertContentIn
265
266
  exports.insertionPlugin = require_interpreter_getContent_plugins.insertionPlugin;
266
267
  exports.intlayerToI18nextFormatter = require_messageFormat_i18next.intlayerToI18nextFormatter;
267
268
  exports.intlayerToICUFormatter = require_messageFormat_ICU.intlayerToICUFormatter;
269
+ exports.intlayerToPortableObjectFormatter = require_messageFormat_po.intlayerToPortableObjectFormatter;
268
270
  exports.intlayerToVueI18nFormatter = require_messageFormat_vue_i18n.intlayerToVueI18nFormatter;
269
271
  exports.isSameKeyPath = require_utils_isSameKeyPath.isSameKeyPath;
270
272
  exports.isValidElement = require_utils_isValidReactElement.isValidElement;
@@ -299,6 +301,7 @@ exports.parserFor = require_markdown_parser.parserFor;
299
301
  exports.percentage = require_formatters_percentage.percentage;
300
302
  exports.plural = require_transpiler_plural_plural.plural;
301
303
  exports.pluralPlugin = require_interpreter_getContent_plugins.pluralPlugin;
304
+ exports.portableObjectToIntlayerFormatter = require_messageFormat_po.portableObjectToIntlayerFormatter;
302
305
  exports.presets = require_formatters_date.presets;
303
306
  exports.qualifies = require_markdown_utils.qualifies;
304
307
  exports.relativeTime = require_formatters_relativeTime.relativeTime;
@@ -5,6 +5,7 @@ const require_transpiler_enumeration_enumeration = require('../transpiler/enumer
5
5
  const require_transpiler_gender_gender = require('../transpiler/gender/gender.cjs');
6
6
  const require_transpiler_html_html = require('../transpiler/html/html.cjs');
7
7
  const require_transpiler_insertion_insertion = require('../transpiler/insertion/insertion.cjs');
8
+ const require_transpiler_plural_plural = require('../transpiler/plural/plural.cjs');
8
9
  let _intlayer_types_nodeType = require("@intlayer/types/nodeType");
9
10
  _intlayer_types_nodeType = require_runtime.__toESM(_intlayer_types_nodeType);
10
11
 
@@ -159,21 +160,34 @@ const icuNodesToIntlayer = (nodes) => {
159
160
  }
160
161
  if (node.type === "plural") {
161
162
  const options = {};
162
- for (const [key, val] of Object.entries(node.options)) {
163
- let newKey = key;
164
- if (key.startsWith("=")) newKey = key.substring(1);
165
- else if (key === "one") newKey = "1";
166
- else if (key === "two") newKey = "2";
167
- else if (key === "few") newKey = "<=3";
168
- else if (key === "many") newKey = ">=4";
169
- else if (key === "other") newKey = "fallback";
170
- options[newKey] = icuNodesToIntlayer(val.map((v) => {
163
+ let hasExactMatch = false;
164
+ for (const key of Object.keys(node.options)) if (key.startsWith("=")) {
165
+ hasExactMatch = true;
166
+ break;
167
+ }
168
+ if (hasExactMatch) {
169
+ for (const [key, val] of Object.entries(node.options)) {
170
+ let newKey = key;
171
+ if (key.startsWith("=")) newKey = key.substring(1);
172
+ else if (key === "one") newKey = "1";
173
+ else if (key === "two") newKey = "2";
174
+ else if (key === "few") newKey = "<=3";
175
+ else if (key === "many") newKey = ">=4";
176
+ else if (key === "other") newKey = "fallback";
177
+ options[newKey] = icuNodesToIntlayer(val.map((v) => {
178
+ if (typeof v === "string") return v.replace(/#/g, `{{${node.name}}}`);
179
+ return v;
180
+ }));
181
+ }
182
+ options.__intlayer_icu_var = node.name;
183
+ return require_transpiler_enumeration_enumeration.enu(options);
184
+ } else {
185
+ for (const [key, val] of Object.entries(node.options)) options[key] = icuNodesToIntlayer(val.map((v) => {
171
186
  if (typeof v === "string") return v.replace(/#/g, `{{${node.name}}}`);
172
187
  return v;
173
188
  }));
189
+ return require_transpiler_plural_plural.plural(options);
174
190
  }
175
- options.__intlayer_icu_var = node.name;
176
- return require_transpiler_enumeration_enumeration.enu(options);
177
191
  }
178
192
  if (node.type === "select") {
179
193
  const options = {};
@@ -208,7 +222,7 @@ const icuToIntlayerPlugin = {
208
222
  const intlayerToIcuPlugin = {
209
223
  canHandle: (node) => {
210
224
  if (typeof node === "string" && (node.includes("{") || node.includes("}"))) return true;
211
- if (node && typeof node === "object" && (node.nodeType === _intlayer_types_nodeType.INSERTION || node.nodeType === _intlayer_types_nodeType.HTML || node.nodeType === _intlayer_types_nodeType.ENUMERATION || node.nodeType === _intlayer_types_nodeType.GENDER || node.nodeType === "composite")) return true;
225
+ if (node && typeof node === "object" && (node.nodeType === _intlayer_types_nodeType.INSERTION || node.nodeType === _intlayer_types_nodeType.HTML || node.nodeType === _intlayer_types_nodeType.ENUMERATION || node.nodeType === _intlayer_types_nodeType.PLURAL || node.nodeType === _intlayer_types_nodeType.GENDER || node.nodeType === "composite")) return true;
212
226
  if (Array.isArray(node)) {
213
227
  if (node.length === 0) return false;
214
228
  let hasNode = false;
@@ -225,6 +239,27 @@ const intlayerToIcuPlugin = {
225
239
  if (typeof node === "string") return node.replace(/\{\{([^}]+)\}\}/g, "{$1}");
226
240
  if (node.nodeType === _intlayer_types_nodeType.INSERTION) return node[_intlayer_types_nodeType.INSERTION].replace(/\{\{([^}]+)\}\}/g, "{$1}");
227
241
  if (node.nodeType === _intlayer_types_nodeType.HTML) return node[_intlayer_types_nodeType.HTML];
242
+ if (node.nodeType === _intlayer_types_nodeType.PLURAL) {
243
+ const options = node[_intlayer_types_nodeType.PLURAL];
244
+ const transformedOptions = {};
245
+ for (const [key, val] of Object.entries(options)) {
246
+ const childVal = next(val, props);
247
+ transformedOptions[key] = typeof childVal === "string" ? childVal : JSON.stringify(childVal);
248
+ }
249
+ let varName = "count";
250
+ const fallbackVal = transformedOptions.other || Object.values(transformedOptions)[0];
251
+ if (fallbackVal) {
252
+ const match = fallbackVal.match(/\{([a-zA-Z0-9_]+)\}(?!,)/);
253
+ if (match) varName = match[1];
254
+ }
255
+ const parts = [];
256
+ for (const [key, val] of Object.entries(transformedOptions)) {
257
+ let strVal = val;
258
+ strVal = strVal.replace(new RegExp(`\\{${varName}\\}`, "g"), "#");
259
+ parts.push(`${key} {${strVal}}`);
260
+ }
261
+ return `{${varName}, plural, ${parts.join(" ")}}`;
262
+ }
228
263
  if (node.nodeType === _intlayer_types_nodeType.ENUMERATION) {
229
264
  const options = node[_intlayer_types_nodeType.ENUMERATION];
230
265
  const transformedOptions = {};
@@ -1 +1 @@
1
- {"version":3,"file":"ICU.cjs","names":["html","insert","enu","gender","NodeTypes","deepTransformNode"],"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 } 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\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 or select, parse options\n if (type === 'plural' || type === 'select') {\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 }\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\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 }\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\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.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.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') 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 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.cjs","names":["html","insert","enu","plural","gender","NodeTypes","deepTransformNode"],"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\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 or select, parse options\n if (type === 'plural' || type === 'select') {\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 }\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\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') 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 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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"}
@@ -5,6 +5,7 @@ const require_transpiler_enumeration_enumeration = require('../transpiler/enumer
5
5
  const require_transpiler_gender_gender = require('../transpiler/gender/gender.cjs');
6
6
  const require_transpiler_html_html = require('../transpiler/html/html.cjs');
7
7
  const require_transpiler_insertion_insertion = require('../transpiler/insertion/insertion.cjs');
8
+ const require_transpiler_plural_plural = require('../transpiler/plural/plural.cjs');
8
9
  let _intlayer_types_nodeType = require("@intlayer/types/nodeType");
9
10
  _intlayer_types_nodeType = require_runtime.__toESM(_intlayer_types_nodeType);
10
11
 
@@ -168,21 +169,34 @@ const i18nextNodesToIntlayer = (nodes) => {
168
169
  }
169
170
  if (node.type === "plural") {
170
171
  const options = {};
171
- for (const [key, val] of Object.entries(node.options)) {
172
- let newKey = key;
173
- if (key.startsWith("=")) newKey = key.substring(1);
174
- else if (key === "one") newKey = "1";
175
- else if (key === "two") newKey = "2";
176
- else if (key === "few") newKey = "<=3";
177
- else if (key === "many") newKey = ">=4";
178
- else if (key === "other") newKey = "fallback";
179
- options[newKey] = i18nextNodesToIntlayer(val.map((v) => {
172
+ let hasExactMatch = false;
173
+ for (const key of Object.keys(node.options)) if (key.startsWith("=")) {
174
+ hasExactMatch = true;
175
+ break;
176
+ }
177
+ if (hasExactMatch) {
178
+ for (const [key, val] of Object.entries(node.options)) {
179
+ let newKey = key;
180
+ if (key.startsWith("=")) newKey = key.substring(1);
181
+ else if (key === "one") newKey = "1";
182
+ else if (key === "two") newKey = "2";
183
+ else if (key === "few") newKey = "<=3";
184
+ else if (key === "many") newKey = ">=4";
185
+ else if (key === "other") newKey = "fallback";
186
+ options[newKey] = i18nextNodesToIntlayer(val.map((v) => {
187
+ if (typeof v === "string") return v.replace(/#/g, `{{${node.name}}}`);
188
+ return v;
189
+ }));
190
+ }
191
+ options.__intlayer_icu_var = node.name;
192
+ return require_transpiler_enumeration_enumeration.enu(options);
193
+ } else {
194
+ for (const [key, val] of Object.entries(node.options)) options[key] = i18nextNodesToIntlayer(val.map((v) => {
180
195
  if (typeof v === "string") return v.replace(/#/g, `{{${node.name}}}`);
181
196
  return v;
182
197
  }));
198
+ return require_transpiler_plural_plural.plural(options);
183
199
  }
184
- options.__intlayer_icu_var = node.name;
185
- return require_transpiler_enumeration_enumeration.enu(options);
186
200
  }
187
201
  if (node.type === "select") {
188
202
  const options = {};
@@ -217,7 +231,7 @@ const i18nextToIntlayerPlugin = {
217
231
  const intlayerToI18nextPlugin = {
218
232
  canHandle: (node) => {
219
233
  if (typeof node === "string") return true;
220
- if (node && typeof node === "object" && (node.nodeType === _intlayer_types_nodeType.INSERTION || node.nodeType === _intlayer_types_nodeType.HTML || node.nodeType === _intlayer_types_nodeType.ENUMERATION || node.nodeType === _intlayer_types_nodeType.GENDER || node.nodeType === "composite")) return true;
234
+ if (node && typeof node === "object" && (node.nodeType === _intlayer_types_nodeType.INSERTION || node.nodeType === _intlayer_types_nodeType.HTML || node.nodeType === _intlayer_types_nodeType.ENUMERATION || node.nodeType === _intlayer_types_nodeType.PLURAL || node.nodeType === _intlayer_types_nodeType.GENDER || node.nodeType === "composite")) return true;
221
235
  if (Array.isArray(node)) {
222
236
  if (node.length === 0) return false;
223
237
  let hasNode = false;
@@ -237,6 +251,29 @@ const intlayerToI18nextPlugin = {
237
251
  return node[_intlayer_types_nodeType.INSERTION];
238
252
  }
239
253
  if (node.nodeType === _intlayer_types_nodeType.HTML) return node[_intlayer_types_nodeType.HTML];
254
+ if (node.nodeType === _intlayer_types_nodeType.PLURAL) {
255
+ const options = node[_intlayer_types_nodeType.PLURAL];
256
+ const transformedOptions = {};
257
+ for (const [key, val] of Object.entries(options)) {
258
+ const childVal = next(val, props);
259
+ transformedOptions[key] = typeof childVal === "string" ? childVal : JSON.stringify(childVal);
260
+ }
261
+ let varName = "count";
262
+ const fallbackVal = transformedOptions.other || Object.values(transformedOptions)[0];
263
+ if (fallbackVal) {
264
+ const match = fallbackVal.match(/\{\{([a-zA-Z0-9_]+)\}\}/) || fallbackVal.match(/\{([a-zA-Z0-9_]+)\}(?!,)/);
265
+ if (match) varName = match[1];
266
+ }
267
+ const parts = [];
268
+ for (const [key, val] of Object.entries(transformedOptions)) {
269
+ const icuKey = key;
270
+ let strVal = val;
271
+ strVal = strVal.replace(/\{\{([^}]+)\}\}/g, "{$1}");
272
+ strVal = strVal.replace(new RegExp(`\\{${varName}\\}`, "g"), "#");
273
+ parts.push(`${icuKey} {${strVal}}`);
274
+ }
275
+ return `{${varName}, plural, ${parts.join(" ")}}`;
276
+ }
240
277
  if (node.nodeType === _intlayer_types_nodeType.ENUMERATION) {
241
278
  const options = node[_intlayer_types_nodeType.ENUMERATION];
242
279
  const transformedOptions = {};
@@ -1 +1 @@
1
- {"version":3,"file":"i18next.cjs","names":["html","insert","enu","gender","NodeTypes","deepTransformNode"],"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 } 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 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 }\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.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.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') 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.cjs","names":["html","insert","enu","plural","gender","NodeTypes","deepTransformNode"],"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') 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,11 +1,14 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_messageFormat_ICU = require('./ICU.cjs');
3
3
  const require_messageFormat_i18next = require('./i18next.cjs');
4
+ const require_messageFormat_po = require('./po.cjs');
4
5
  const require_messageFormat_vue_i18n = require('./vue-i18n.cjs');
5
6
 
6
7
  exports.i18nextToIntlayerFormatter = require_messageFormat_i18next.i18nextToIntlayerFormatter;
7
8
  exports.icuToIntlayerFormatter = require_messageFormat_ICU.icuToIntlayerFormatter;
8
9
  exports.intlayerToI18nextFormatter = require_messageFormat_i18next.intlayerToI18nextFormatter;
9
10
  exports.intlayerToICUFormatter = require_messageFormat_ICU.intlayerToICUFormatter;
11
+ exports.intlayerToPortableObjectFormatter = require_messageFormat_po.intlayerToPortableObjectFormatter;
10
12
  exports.intlayerToVueI18nFormatter = require_messageFormat_vue_i18n.intlayerToVueI18nFormatter;
13
+ exports.portableObjectToIntlayerFormatter = require_messageFormat_po.portableObjectToIntlayerFormatter;
11
14
  exports.vueI18nToIntlayerFormatter = require_messageFormat_vue_i18n.vueI18nToIntlayerFormatter;