@intlayer/core 8.3.0-canary.0 → 8.3.0-canary.2
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.
- package/dist/cjs/messageFormat/ICU.cjs +1 -1
- package/dist/cjs/messageFormat/ICU.cjs.map +1 -1
- package/dist/cjs/messageFormat/i18next.cjs +1 -1
- package/dist/cjs/messageFormat/i18next.cjs.map +1 -1
- package/dist/cjs/messageFormat/vue-i18n.cjs +1 -1
- package/dist/cjs/messageFormat/vue-i18n.cjs.map +1 -1
- package/dist/esm/messageFormat/ICU.mjs +1 -1
- package/dist/esm/messageFormat/ICU.mjs.map +1 -1
- package/dist/esm/messageFormat/i18next.mjs +1 -1
- package/dist/esm/messageFormat/i18next.mjs.map +1 -1
- package/dist/esm/messageFormat/vue-i18n.mjs +1 -1
- package/dist/esm/messageFormat/vue-i18n.mjs.map +1 -1
- package/dist/types/messageFormat/ICU.d.ts.map +1 -1
- package/dist/types/messageFormat/i18next.d.ts.map +1 -1
- package/dist/types/messageFormat/vue-i18n.d.ts.map +1 -1
- package/package.json +8 -8
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../interpreter/getContent/deepTransform.cjs`),t=require(`../transpiler/enumeration/enumeration.cjs`),n=require(`../transpiler/gender/gender.cjs`),r=require(`../transpiler/html/html.cjs`),i=require(`../transpiler/insertion/insertion.cjs`);let a=require(`@intlayer/types/nodeType`);const o=e=>{let t=0,n=()=>{let n=[],i=``;for(;t<e.length;){let a=e[t];if(a===`{`)i&&=(n.push(i),``),t++,n.push(r());else if(a===`}`)break;else if(a===`'`)if(t+1<e.length&&e[t+1]===`'`)i+=`'`,t+=2;else{let n=e.indexOf(`'`,t+1);n===-1?(i+=`'`,t++):(i+=e.substring(t+1,n),t=n+1)}else i+=a,t++}return i&&n.push(i),n},r=()=>{let r=``;for(;t<e.length&&/[^,}]/.test(e[t]);)r+=e[t],t++;if(r=r.trim(),t>=e.length)throw Error(`Unclosed argument`);if(e[t]===`}`)return t++,{type:`argument`,name:r};if(e[t]===`,`){t++;let i=``;for(;t<e.length&&/[^,}]/.test(e[t]);)i+=e[t],t++;if(i=i.trim(),t>=e.length)throw Error(`Unclosed argument`);if(e[t]===`}`)return t++,{type:`argument`,name:r,format:{type:i}};if(e[t]===`,`)if(t++,i===`plural`||i===`select`){let a={};for(;t<e.length&&e[t]!==`}`;){for(;t<e.length&&/\s/.test(e[t]);)t++;let r=``;for(;t<e.length&&/[^{\s]/.test(e[t]);)r+=e[t],t++;for(;t<e.length&&/\s/.test(e[t]);)t++;if(e[t]!==`{`)throw Error(`Expected { after option key`);t++;let i=n();if(e[t]!==`}`)throw Error(`Expected } after option value`);for(t++,a[r]=i;t<e.length&&/\s/.test(e[t]);)t++}if(t++,i===`plural`)return{type:`plural`,name:r,options:a};if(i===`select`)return{type:`select`,name:r,options:a}}else{let n=``;for(;t<e.length&&e[t]!==`}`;)n+=e[t],t++;if(t>=e.length)throw Error(`Unclosed argument`);return n=n.trim(),t++,{type:`argument`,name:r,format:{type:i,style:n}}}}throw Error(`Malformed argument`)};return n()},s=e=>{if(e.length===0)return``;if(e.length===1&&typeof e[0]==`string`){let t=e[0];return/<[a-zA-Z0-9-]+[^>]*>/.test(t)?r.html(t):t}if(e.every(e=>typeof e==`string`||e.type===`argument`)){let t=``;for(let n of e)typeof n==`string`?t+=n:typeof n!=`string`&&n.type===`argument`&&(n.format?t+=`{${n.name}, ${n.format.type}${n.format.style?`, ${n.format.style}`:``}}`:t+=`{{${n.name}}}`);return/<[a-zA-Z0-9-]+[^>]*>/.test(t)?r.html(t):i.insert(t)}if(e.length===1){let a=e[0];if(typeof a==`string`)return/<[a-zA-Z0-9-]+[^>]*>/.test(a)?r.html(a):a;if(a.type===`argument`)return a.format?i.insert(`{${a.name}, ${a.format.type}${a.format.style?`, ${a.format.style}`:``}}`):i.insert(`{{${a.name}}}`);if(a.type===`plural`){let e={};for(let[t,n]of Object.entries(a.options)){let r=t;t.startsWith(`=`)?r=t.substring(1):t===`one`?r=`1`:t===`two`?r=`2`:t===`few`?r=`<=3`:t===`many`?r=`>=4`:t===`other`&&(r=`fallback`),e[r]=s(n.map(e=>typeof e==`string`?e.replace(/#/g,`{{${a.name}}}`):e))}return e.__intlayer_icu_var=a.name,t.enu(e)}if(a.type===`select`){let e={};for(let[t,n]of Object.entries(a.options))e[t]=s(n);let r=Object.keys(e);return(e.male||e.female)&&r.every(e=>[`male`,`female`,`other`,`fallback`].includes(e))?n.gender({fallback:e.other,male:e.male,female:e.female}):(e.__intlayer_icu_var=a.name,t.enu(e))}}return e.map(e=>s([e]))},c={canHandle:e=>typeof e==`string`&&(e.includes(`{`)||e.includes(`}`)||/<[a-zA-Z0-9-]+[^>]*>/.test(e)),transform:e=>{try{return s(o(e))}catch{return e}}},l={canHandle:e=>typeof e==`string`&&(e.includes(`{`)||e.includes(`}`))||e&&typeof e==`object`&&(e.nodeType===a.NodeType.Insertion||e.nodeType===a.NodeType.HTML||e.nodeType===a.NodeType.Enumeration||e.nodeType===a.NodeType.Gender||e.nodeType===`composite`)
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../interpreter/getContent/deepTransform.cjs`),t=require(`../transpiler/enumeration/enumeration.cjs`),n=require(`../transpiler/gender/gender.cjs`),r=require(`../transpiler/html/html.cjs`),i=require(`../transpiler/insertion/insertion.cjs`);let a=require(`@intlayer/types/nodeType`);const o=e=>{let t=0,n=()=>{let n=[],i=``;for(;t<e.length;){let a=e[t];if(a===`{`)i&&=(n.push(i),``),t++,n.push(r());else if(a===`}`)break;else if(a===`'`)if(t+1<e.length&&e[t+1]===`'`)i+=`'`,t+=2;else{let n=e.indexOf(`'`,t+1);n===-1?(i+=`'`,t++):(i+=e.substring(t+1,n),t=n+1)}else i+=a,t++}return i&&n.push(i),n},r=()=>{let r=``;for(;t<e.length&&/[^,}]/.test(e[t]);)r+=e[t],t++;if(r=r.trim(),t>=e.length)throw Error(`Unclosed argument`);if(e[t]===`}`)return t++,{type:`argument`,name:r};if(e[t]===`,`){t++;let i=``;for(;t<e.length&&/[^,}]/.test(e[t]);)i+=e[t],t++;if(i=i.trim(),t>=e.length)throw Error(`Unclosed argument`);if(e[t]===`}`)return t++,{type:`argument`,name:r,format:{type:i}};if(e[t]===`,`)if(t++,i===`plural`||i===`select`){let a={};for(;t<e.length&&e[t]!==`}`;){for(;t<e.length&&/\s/.test(e[t]);)t++;let r=``;for(;t<e.length&&/[^{\s]/.test(e[t]);)r+=e[t],t++;for(;t<e.length&&/\s/.test(e[t]);)t++;if(e[t]!==`{`)throw Error(`Expected { after option key`);t++;let i=n();if(e[t]!==`}`)throw Error(`Expected } after option value`);for(t++,a[r]=i;t<e.length&&/\s/.test(e[t]);)t++}if(t++,i===`plural`)return{type:`plural`,name:r,options:a};if(i===`select`)return{type:`select`,name:r,options:a}}else{let n=``;for(;t<e.length&&e[t]!==`}`;)n+=e[t],t++;if(t>=e.length)throw Error(`Unclosed argument`);return n=n.trim(),t++,{type:`argument`,name:r,format:{type:i,style:n}}}}throw Error(`Malformed argument`)};return n()},s=e=>{if(e.length===0)return``;if(e.length===1&&typeof e[0]==`string`){let t=e[0];return/<[a-zA-Z0-9-]+[^>]*>/.test(t)?r.html(t):t}if(e.every(e=>typeof e==`string`||e.type===`argument`)){let t=``;for(let n of e)typeof n==`string`?t+=n:typeof n!=`string`&&n.type===`argument`&&(n.format?t+=`{${n.name}, ${n.format.type}${n.format.style?`, ${n.format.style}`:``}}`:t+=`{{${n.name}}}`);return/<[a-zA-Z0-9-]+[^>]*>/.test(t)?r.html(t):i.insert(t)}if(e.length===1){let a=e[0];if(typeof a==`string`)return/<[a-zA-Z0-9-]+[^>]*>/.test(a)?r.html(a):a;if(a.type===`argument`)return a.format?i.insert(`{${a.name}, ${a.format.type}${a.format.style?`, ${a.format.style}`:``}}`):i.insert(`{{${a.name}}}`);if(a.type===`plural`){let e={};for(let[t,n]of Object.entries(a.options)){let r=t;t.startsWith(`=`)?r=t.substring(1):t===`one`?r=`1`:t===`two`?r=`2`:t===`few`?r=`<=3`:t===`many`?r=`>=4`:t===`other`&&(r=`fallback`),e[r]=s(n.map(e=>typeof e==`string`?e.replace(/#/g,`{{${a.name}}}`):e))}return e.__intlayer_icu_var=a.name,t.enu(e)}if(a.type===`select`){let e={};for(let[t,n]of Object.entries(a.options))e[t]=s(n);let r=Object.keys(e);return(e.male||e.female)&&r.every(e=>[`male`,`female`,`other`,`fallback`].includes(e))?n.gender({fallback:e.other,male:e.male,female:e.female}):(e.__intlayer_icu_var=a.name,t.enu(e))}}return e.map(e=>s([e]))},c={canHandle:e=>typeof e==`string`&&(e.includes(`{`)||e.includes(`}`)||/<[a-zA-Z0-9-]+[^>]*>/.test(e)),transform:e=>{try{return s(o(e))}catch{return e}}},l={canHandle:e=>{if(typeof e==`string`&&(e.includes(`{`)||e.includes(`}`))||e&&typeof e==`object`&&(e.nodeType===a.NodeType.Insertion||e.nodeType===a.NodeType.HTML||e.nodeType===a.NodeType.Enumeration||e.nodeType===a.NodeType.Gender||e.nodeType===`composite`))return!0;if(Array.isArray(e)){if(e.length===0)return!1;let t=!1,n=!1;for(let r of e)typeof r==`string`||(r&&typeof r==`object`&&(r.nodeType===a.NodeType.Insertion||r.nodeType===a.NodeType.HTML||r.nodeType===a.NodeType.Enumeration||r.nodeType===a.NodeType.Gender||r.nodeType===`composite`)?t=!0:n=!0);return!(n||!t)}return!1},transform:(e,t,n)=>{if(typeof e==`string`)return e.replace(/\{\{([^}]+)\}\}/g,`{$1}`);if(e.nodeType===a.NodeType.Insertion)return e.insertion.replace(/\{\{([^}]+)\}\}/g,`{$1}`);if(e.nodeType===a.NodeType.HTML)return e.html;if(e.nodeType===a.NodeType.Enumeration){let r=e.enumeration,i={};for(let[e,a]of Object.entries(r)){if(e===`__intlayer_icu_var`)continue;let r=n(a,t);i[e]=typeof r==`string`?r:JSON.stringify(r)}let a=r.__intlayer_icu_var||`n`;if(!r.__intlayer_icu_var){let e=(i.fallback||i.other||Object.values(i)[0]).match(/\{([a-zA-Z0-9_]+)\}(?!,)/);e&&(a=e[1])}let o=Object.keys(i),s=[`1`,`2`,`<=3`,`>=4`,`fallback`,`other`,`zero`,`one`,`two`,`few`,`many`],c=o.every(e=>s.includes(e)||/^[<>=]?\d+(\.\d+)?$/.test(e)),l=[];if(c){for(let[e,t]of Object.entries(i)){let n=e;n=e===`fallback`?`other`:e===`<=3`?`few`:e===`>=4`?`many`:/^\d+$/.test(e)?`=${e}`:[`zero`,`few`,`many`].includes(e)?e:`other`;let r=t;r=r.replace(RegExp(`\\{${a}\\}`,`g`),`#`),l.push(`${n} {${r}}`)}return`{${a}, plural, ${l.join(` `)}}`}else{let e=Object.entries(i).sort(([e],[t])=>e===`fallback`||e===`other`?1:t===`fallback`||t===`other`?-1:0);for(let[t,n]of e){let e=t;t===`fallback`&&(e=`other`),l.push(`${e} {${n}}`)}return`{${a}, select, ${l.join(` `)}}`}}if(e.nodeType===a.NodeType.Gender){let r=e.gender,i=[],a=Object.entries(r).sort(([e],[t])=>e===`fallback`?1:t===`fallback`?-1:0);for(let[e,r]of a){let a=e;e===`fallback`&&(a=`other`);let o=n(r,t),s=typeof o==`string`?o:JSON.stringify(o);i.push(`${a} {${s}}`)}return`{gender, select, ${i.join(` `)}}`}return Array.isArray(e)||e.nodeType===`composite`&&Array.isArray(e.composite)?(Array.isArray(e)?e:e.composite).map(e=>n(e,t)).join(``):n(e,t)}},u=t=>e.deepTransformNode(t,{dictionaryKey:`icu`,keyPath:[],plugins:[{id:`icu`,...l}]}),d=t=>e.deepTransformNode(t,{dictionaryKey:`icu`,keyPath:[],plugins:[{id:`icu`,...c}]});exports.icuToIntlayerFormatter=d,exports.intlayerToICUFormatter=u;
|
|
2
2
|
//# sourceMappingURL=ICU.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ICU.cjs","names":["html","insert","enu","gender","NodeType","deepTransformNode"],"sources":["../../../src/messageFormat/ICU.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/types/dictionary';;\nimport { NodeType } 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 (typeof node === 'string' && (node.includes('{') || node.includes('}'))) ||\n (node &&\n typeof node === 'object' &&\n (node.nodeType === NodeType.Insertion ||\n node.nodeType === NodeType.HTML ||\n node.nodeType === NodeType.Enumeration ||\n node.nodeType === NodeType.Gender ||\n node.nodeType === 'composite')) ||\n Array.isArray(node),\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 === NodeType.Insertion) {\n // Convert Intlayer format to ICU format:\n // - {{name}} → {name} (simple variable)\n // - {amount, number, currency} → {amount, number, currency} (formatted variable, already in ICU format)\n return node.insertion.replace(/\\{\\{([^}]+)\\}\\}/g, '{$1}');\n }\n\n if (node.nodeType === NodeType.HTML) {\n return node.html;\n }\n\n if (node.nodeType === NodeType.Enumeration) {\n const options = node.enumeration;\n\n // Transform all values first\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 // Infer variable name\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 // Match {variable} but avoid {variable, ...} (which are nested ICUs)\n // Actually nested ICU starts with {var, ...\n // Simple variable is {var}\n // We look for {var} that is NOT followed by ,\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 // Also check for numbers\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\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\n // Replace {varName} with #\n // Note: next() has already converted {{var}} -> {var}\n strVal = strVal.replace(new RegExp(`\\\\{${varName}\\\\}`, 'g'), '#');\n\n parts.push(`${icuKey} {${strVal}}`);\n }\n\n return `{${varName}, plural, ${parts.join(' ')}}`;\n } else {\n // Select\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 // Do NOT map other keys to 'other'. Keep 'active', 'inactive', etc.\n\n parts.push(`${icuKey} {${val}}`);\n }\n return `{${varName}, select, ${parts.join(' ')}}`;\n }\n }\n\n if (node.nodeType === NodeType.Gender) {\n const options = node.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\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","gender","NodeType","deepTransformNode"],"sources":["../../../src/messageFormat/ICU.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/types/dictionary';\n\nimport { NodeType } 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 === NodeType.Insertion ||\n node.nodeType === NodeType.HTML ||\n node.nodeType === NodeType.Enumeration ||\n node.nodeType === NodeType.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 === NodeType.Insertion ||\n item.nodeType === NodeType.HTML ||\n item.nodeType === NodeType.Enumeration ||\n item.nodeType === NodeType.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 === NodeType.Insertion) {\n return node.insertion.replace(/\\{\\{([^}]+)\\}\\}/g, '{$1}');\n }\n\n if (node.nodeType === NodeType.HTML) {\n return node.html;\n }\n\n if (node.nodeType === NodeType.Enumeration) {\n const options = node.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 === NodeType.Gender) {\n const options = node.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,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../interpreter/getContent/deepTransform.cjs`),t=require(`../transpiler/enumeration/enumeration.cjs`),n=require(`../transpiler/gender/gender.cjs`),r=require(`../transpiler/html/html.cjs`),i=require(`../transpiler/insertion/insertion.cjs`);let a=require(`@intlayer/types/nodeType`);const o=e=>{let t=0,n=()=>{let n=[],a=``;for(;t<e.length;){let o=e[t];if(o===`{`&&e[t+1]===`{`)a&&=(n.push(a),``),t+=2,n.push(r());else if(o===`{`)a&&=(n.push(a),``),t++,n.push(i());else if(o===`}`)break;else a+=o,t++}return a&&n.push(a),n},r=()=>{let n=``;for(;t<e.length;){if(e[t]===`}`&&e[t+1]===`}`)return t+=2,{type:`argument`,name:n.trim()};n+=e[t],t++}throw Error(`Unclosed i18next variable`)},i=()=>{let r=``;for(;t<e.length&&/[^,}]/.test(e[t]);)r+=e[t],t++;if(r=r.trim(),t>=e.length)throw Error(`Unclosed argument`);if(e[t]===`}`)return t++,{type:`argument`,name:r};if(e[t]===`,`){t++;let i=``;for(;t<e.length&&/[^,}]/.test(e[t]);)i+=e[t],t++;if(i=i.trim(),t>=e.length)throw Error(`Unclosed argument`);if(e[t]===`}`)return t++,{type:`argument`,name:r,format:{type:i}};if(e[t]===`,`)if(t++,i===`plural`||i===`select`){let a={};for(;t<e.length&&e[t]!==`}`;){for(;t<e.length&&/\s/.test(e[t]);)t++;let r=``;for(;t<e.length&&/[^{\s]/.test(e[t]);)r+=e[t],t++;for(;t<e.length&&/\s/.test(e[t]);)t++;if(e[t]!==`{`)throw Error(`Expected { after option key`);t++;let i=n();if(e[t]!==`}`)throw Error(`Expected } after option value`);for(t++,a[r]=i;t<e.length&&/\s/.test(e[t]);)t++}if(t++,i===`plural`)return{type:`plural`,name:r,options:a};if(i===`select`)return{type:`select`,name:r,options:a}}else{let n=``;for(;t<e.length&&e[t]!==`}`;)n+=e[t],t++;if(t>=e.length)throw Error(`Unclosed argument`);return n=n.trim(),t++,{type:`argument`,name:r,format:{type:i,style:n}}}}throw Error(`Malformed argument`)};return n()},s=e=>{if(e.length===0)return``;if(e.length===1&&typeof e[0]==`string`){let t=e[0];return/<[a-zA-Z0-9-]+[^>]*>/.test(t)?r.html(t):t}if(e.every(e=>typeof e==`string`||e.type===`argument`)){let t=``;for(let n of e)typeof n==`string`?t+=n:typeof n!=`string`&&n.type===`argument`&&(n.format?t+=`{${n.name}, ${n.format.type}${n.format.style?`, ${n.format.style}`:``}}`:t+=`{{${n.name}}}`);return/<[a-zA-Z0-9-]+[^>]*>/.test(t)?r.html(t):i.insert(t)}if(e.length===1){let a=e[0];if(typeof a==`string`)return/<[a-zA-Z0-9-]+[^>]*>/.test(a)?r.html(a):a;if(a.type===`argument`)return a.format?i.insert(`{${a.name}, ${a.format.type}${a.format.style?`, ${a.format.style}`:``}}`):i.insert(`{{${a.name}}}`);if(a.type===`plural`){let e={};for(let[t,n]of Object.entries(a.options)){let r=t;t.startsWith(`=`)?r=t.substring(1):t===`one`?r=`1`:t===`two`?r=`2`:t===`few`?r=`<=3`:t===`many`?r=`>=4`:t===`other`&&(r=`fallback`),e[r]=s(n.map(e=>typeof e==`string`?e.replace(/#/g,`{{${a.name}}}`):e))}return e.__intlayer_icu_var=a.name,t.enu(e)}if(a.type===`select`){let e={};for(let[t,n]of Object.entries(a.options))e[t]=s(n);let r=Object.keys(e);return(e.male||e.female)&&r.every(e=>[`male`,`female`,`other`,`fallback`].includes(e))?n.gender({fallback:e.other,male:e.male,female:e.female}):(e.__intlayer_icu_var=a.name,t.enu(e))}}return e.map(e=>s([e]))},c={canHandle:e=>typeof e==`string`&&(e.includes(`{`)||e.includes(`}`)||/<[a-zA-Z0-9-]+[^>]*>/.test(e)),transform:e=>{try{return s(o(e))}catch{return e}}},l={canHandle:e=>typeof e==`string`||e&&typeof e==`object`&&(e.nodeType===a.NodeType.Insertion||e.nodeType===a.NodeType.HTML||e.nodeType===a.NodeType.Enumeration||e.nodeType===a.NodeType.Gender||e.nodeType===`composite`)
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../interpreter/getContent/deepTransform.cjs`),t=require(`../transpiler/enumeration/enumeration.cjs`),n=require(`../transpiler/gender/gender.cjs`),r=require(`../transpiler/html/html.cjs`),i=require(`../transpiler/insertion/insertion.cjs`);let a=require(`@intlayer/types/nodeType`);const o=e=>{let t=0,n=()=>{let n=[],a=``;for(;t<e.length;){let o=e[t];if(o===`{`&&e[t+1]===`{`)a&&=(n.push(a),``),t+=2,n.push(r());else if(o===`{`)a&&=(n.push(a),``),t++,n.push(i());else if(o===`}`)break;else a+=o,t++}return a&&n.push(a),n},r=()=>{let n=``;for(;t<e.length;){if(e[t]===`}`&&e[t+1]===`}`)return t+=2,{type:`argument`,name:n.trim()};n+=e[t],t++}throw Error(`Unclosed i18next variable`)},i=()=>{let r=``;for(;t<e.length&&/[^,}]/.test(e[t]);)r+=e[t],t++;if(r=r.trim(),t>=e.length)throw Error(`Unclosed argument`);if(e[t]===`}`)return t++,{type:`argument`,name:r};if(e[t]===`,`){t++;let i=``;for(;t<e.length&&/[^,}]/.test(e[t]);)i+=e[t],t++;if(i=i.trim(),t>=e.length)throw Error(`Unclosed argument`);if(e[t]===`}`)return t++,{type:`argument`,name:r,format:{type:i}};if(e[t]===`,`)if(t++,i===`plural`||i===`select`){let a={};for(;t<e.length&&e[t]!==`}`;){for(;t<e.length&&/\s/.test(e[t]);)t++;let r=``;for(;t<e.length&&/[^{\s]/.test(e[t]);)r+=e[t],t++;for(;t<e.length&&/\s/.test(e[t]);)t++;if(e[t]!==`{`)throw Error(`Expected { after option key`);t++;let i=n();if(e[t]!==`}`)throw Error(`Expected } after option value`);for(t++,a[r]=i;t<e.length&&/\s/.test(e[t]);)t++}if(t++,i===`plural`)return{type:`plural`,name:r,options:a};if(i===`select`)return{type:`select`,name:r,options:a}}else{let n=``;for(;t<e.length&&e[t]!==`}`;)n+=e[t],t++;if(t>=e.length)throw Error(`Unclosed argument`);return n=n.trim(),t++,{type:`argument`,name:r,format:{type:i,style:n}}}}throw Error(`Malformed argument`)};return n()},s=e=>{if(e.length===0)return``;if(e.length===1&&typeof e[0]==`string`){let t=e[0];return/<[a-zA-Z0-9-]+[^>]*>/.test(t)?r.html(t):t}if(e.every(e=>typeof e==`string`||e.type===`argument`)){let t=``;for(let n of e)typeof n==`string`?t+=n:typeof n!=`string`&&n.type===`argument`&&(n.format?t+=`{${n.name}, ${n.format.type}${n.format.style?`, ${n.format.style}`:``}}`:t+=`{{${n.name}}}`);return/<[a-zA-Z0-9-]+[^>]*>/.test(t)?r.html(t):i.insert(t)}if(e.length===1){let a=e[0];if(typeof a==`string`)return/<[a-zA-Z0-9-]+[^>]*>/.test(a)?r.html(a):a;if(a.type===`argument`)return a.format?i.insert(`{${a.name}, ${a.format.type}${a.format.style?`, ${a.format.style}`:``}}`):i.insert(`{{${a.name}}}`);if(a.type===`plural`){let e={};for(let[t,n]of Object.entries(a.options)){let r=t;t.startsWith(`=`)?r=t.substring(1):t===`one`?r=`1`:t===`two`?r=`2`:t===`few`?r=`<=3`:t===`many`?r=`>=4`:t===`other`&&(r=`fallback`),e[r]=s(n.map(e=>typeof e==`string`?e.replace(/#/g,`{{${a.name}}}`):e))}return e.__intlayer_icu_var=a.name,t.enu(e)}if(a.type===`select`){let e={};for(let[t,n]of Object.entries(a.options))e[t]=s(n);let r=Object.keys(e);return(e.male||e.female)&&r.every(e=>[`male`,`female`,`other`,`fallback`].includes(e))?n.gender({fallback:e.other,male:e.male,female:e.female}):(e.__intlayer_icu_var=a.name,t.enu(e))}}return e.map(e=>s([e]))},c={canHandle:e=>typeof e==`string`&&(e.includes(`{`)||e.includes(`}`)||/<[a-zA-Z0-9-]+[^>]*>/.test(e)),transform:e=>{try{return s(o(e))}catch{return e}}},l={canHandle:e=>{if(typeof e==`string`||e&&typeof e==`object`&&(e.nodeType===a.NodeType.Insertion||e.nodeType===a.NodeType.HTML||e.nodeType===a.NodeType.Enumeration||e.nodeType===a.NodeType.Gender||e.nodeType===`composite`))return!0;if(Array.isArray(e)){if(e.length===0)return!1;let t=!1,n=!1;for(let r of e)typeof r==`string`||(r&&typeof r==`object`&&(r.nodeType===a.NodeType.Insertion||r.nodeType===a.NodeType.HTML||r.nodeType===a.NodeType.Enumeration||r.nodeType===a.NodeType.Gender||r.nodeType===`composite`)?t=!0:n=!0);return!(n||!t)}return!1},transform:(e,t,n)=>{if(typeof e==`string`)return e;if(e.nodeType===a.NodeType.Insertion)return e.insertion.match(/\{[^}]*,[^}]*\}/),e.insertion;if(e.nodeType===a.NodeType.HTML)return e.html;if(e.nodeType===a.NodeType.Enumeration){let r=e.enumeration,i={};for(let[e,a]of Object.entries(r)){if(e===`__intlayer_icu_var`)continue;let r=n(a,t);i[e]=typeof r==`string`?r:JSON.stringify(r)}let a=r.__intlayer_icu_var||`count`;if(!r.__intlayer_icu_var){let e=i.fallback||i.other||Object.values(i)[0],t=e.match(/\{\{([a-zA-Z0-9_]+)\}\}/)||e.match(/\{([a-zA-Z0-9_]+)\}(?!,)/);t&&(a=t[1])}let o=Object.keys(i),s=[`1`,`2`,`<=3`,`>=4`,`fallback`,`other`,`zero`,`one`,`two`,`few`,`many`],c=o.every(e=>s.includes(e)||/^[<>=]?\d+(\.\d+)?$/.test(e)),l=[];if(c){for(let[e,t]of Object.entries(i)){let n=e;e===`fallback`?n=`other`:e===`<=3`?n=`few`:e===`>=4`?n=`many`:/^\d+$/.test(e)&&(n=`=${e}`);let r=t;r=r.replace(/\{\{([^}]+)\}\}/g,`{$1}`),r=r.replace(RegExp(`\\{${a}\\}`,`g`),`#`),l.push(`${n} {${r}}`)}return`{${a}, plural, ${l.join(` `)}}`}else{let e=Object.entries(i).sort(([e],[t])=>e===`fallback`||e===`other`?1:t===`fallback`||t===`other`?-1:0);for(let[t,n]of e){let e=t;t===`fallback`&&(e=`other`);let r=n;r=r.replace(/\{\{([^}]+)\}\}/g,`{$1}`),l.push(`${e} {${r}}`)}return`{${a}, select, ${l.join(` `)}}`}}if(e.nodeType===a.NodeType.Gender){let r=e.gender,i=[],a=Object.entries(r).sort(([e],[t])=>e===`fallback`?1:t===`fallback`?-1:0);for(let[e,r]of a){let a=e;e===`fallback`&&(a=`other`);let o=n(r,t),s=typeof o==`string`?o:JSON.stringify(o);s=s.replace(/\{\{([^}]+)\}\}/g,`{$1}`),i.push(`${a} {${s}}`)}return`{gender, select, ${i.join(` `)}}`}return Array.isArray(e)||e.nodeType===`composite`&&Array.isArray(e.composite)?(Array.isArray(e)?e:e.composite).map(e=>n(e,t)).join(``):n(e,t)}},u=t=>e.deepTransformNode(t,{dictionaryKey:`i18next`,keyPath:[],plugins:[{id:`i18next`,...l}]}),d=t=>e.deepTransformNode(t,{dictionaryKey:`i18next`,keyPath:[],plugins:[{id:`i18next`,...c}]});exports.i18nextToIntlayerFormatter=d,exports.intlayerToI18nextFormatter=u;
|
|
2
2
|
//# sourceMappingURL=i18next.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"i18next.cjs","names":["html","insert","enu","gender","NodeType","deepTransformNode"],"sources":["../../../src/messageFormat/i18next.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/types/dictionary';\nimport { NodeType } 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 typeof node === 'string' ||\n (node &&\n typeof node === 'object' &&\n (node.nodeType === NodeType.Insertion ||\n node.nodeType === NodeType.HTML ||\n node.nodeType === NodeType.Enumeration ||\n node.nodeType === NodeType.Gender ||\n node.nodeType === 'composite')) ||\n Array.isArray(node),\n transform: (node: any, props: any, next: any) => {\n if (typeof node === 'string') {\n return node;\n }\n\n if (node.nodeType === NodeType.Insertion) {\n // If it contains ICU format syntax (curly braces but not double curly), keep it as is\n // But standard insert creates {{var}}.\n // Check if the original string was formatted (e.g. {val, number})\n if (node.insertion.match(/\\{[^}]*,[^}]*\\}/)) {\n // It's likely an ICU format string like {val, number}\n // We might need to ensure variables inside are not double-braced if they are part of the format\n // But wait, our parser outputs {val, number} as string for insertion.\n return node.insertion;\n }\n\n // Otherwise keep {{name}} for i18next\n return node.insertion;\n }\n\n if (node.nodeType === NodeType.HTML) {\n return node.html;\n }\n\n if (node.nodeType === NodeType.Enumeration) {\n const options = node.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 // Infer variable name\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 // Search for {{var}} or {var}\n // Match {variable} but avoid {variable, ...} (which are nested ICUs)\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 // Check if it is a plural\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 // Convert {{var}} to {var} inside ICU string\n // Also replace {varName} with # if it matches\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 // Select\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 === NodeType.Gender) {\n const options = node.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","gender","NodeType","deepTransformNode"],"sources":["../../../src/messageFormat/i18next.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/types/dictionary';\nimport { NodeType } 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 === NodeType.Insertion ||\n node.nodeType === NodeType.HTML ||\n node.nodeType === NodeType.Enumeration ||\n node.nodeType === NodeType.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 === NodeType.Insertion ||\n item.nodeType === NodeType.HTML ||\n item.nodeType === NodeType.Enumeration ||\n item.nodeType === NodeType.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 === NodeType.Insertion) {\n if (node.insertion.match(/\\{[^}]*,[^}]*\\}/)) {\n return node.insertion;\n }\n return node.insertion;\n }\n\n if (node.nodeType === NodeType.HTML) {\n return node.html;\n }\n\n if (node.nodeType === NodeType.Enumeration) {\n const options = node.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 === NodeType.Gender) {\n const options = node.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,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../interpreter/getContent/deepTransform.cjs`),t=require(`../transpiler/enumeration/enumeration.cjs`),n=require(`../transpiler/insertion/insertion.cjs`);let r=require(`@intlayer/types/nodeType`);const i=e=>{let t=0,n=[],r=``;for(;t<e.length;){let i=e[t];if(i===`{`){r&&=(n.push(r),``),t++;let i=``;for(;t<e.length&&e[t]!==`}`;)i+=e[t],t++;t<e.length&&t++,n.push({type:`argument`,name:i.trim()})}else r+=i,t++}return r&&n.push(r),n},a=e=>{let t=[],n=``,r=0;for(;r<e.length;){let i=e[r];i===`\\`&&r+1<e.length&&e[r+1]===`|`?(n+=`|`,r+=2):i===`|`?(t.push(n.trim()),n=``,r++):(n+=i,r++)}return t.push(n.trim()),t.map(i)},o=e=>{if(e.length===0)return``;if(e.length===1&&typeof e[0]==`string`)return e[0];let t=``;for(let n of e)typeof n==`string`?t+=n:t+=`{{${n.name}}}`;return n.insert(t)},s=e=>{if(e.length===1)return o(e[0]);let n={};return e.length===2?(n[1]=o(e[0]),n.fallback=o(e[1])):e.length===3?(n[0]=o(e[0]),n[1]=o(e[1]),n.fallback=o(e[2])):e.forEach((t,r)=>{r===e.length-1?n.fallback=o(t):n[r.toString()]=o(t)}),n.__intlayer_vue_i18n_var=`count`,t.enu(n)},c={canHandle:e=>typeof e==`string`&&(e.includes(`{`)||e.includes(`|`)),transform:e=>{try{return s(a(e))}catch{return e}}},l={canHandle:e=>typeof e==`string`||e&&typeof e==`object`&&(e.nodeType===r.NodeType.Insertion||e.nodeType===r.NodeType.Enumeration||e.nodeType===r.NodeType.Gender||e.nodeType===`composite`)
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../interpreter/getContent/deepTransform.cjs`),t=require(`../transpiler/enumeration/enumeration.cjs`),n=require(`../transpiler/insertion/insertion.cjs`);let r=require(`@intlayer/types/nodeType`);const i=e=>{let t=0,n=[],r=``;for(;t<e.length;){let i=e[t];if(i===`{`){r&&=(n.push(r),``),t++;let i=``;for(;t<e.length&&e[t]!==`}`;)i+=e[t],t++;t<e.length&&t++,n.push({type:`argument`,name:i.trim()})}else r+=i,t++}return r&&n.push(r),n},a=e=>{let t=[],n=``,r=0;for(;r<e.length;){let i=e[r];i===`\\`&&r+1<e.length&&e[r+1]===`|`?(n+=`|`,r+=2):i===`|`?(t.push(n.trim()),n=``,r++):(n+=i,r++)}return t.push(n.trim()),t.map(i)},o=e=>{if(e.length===0)return``;if(e.length===1&&typeof e[0]==`string`)return e[0];let t=``;for(let n of e)typeof n==`string`?t+=n:t+=`{{${n.name}}}`;return n.insert(t)},s=e=>{if(e.length===1)return o(e[0]);let n={};return e.length===2?(n[1]=o(e[0]),n.fallback=o(e[1])):e.length===3?(n[0]=o(e[0]),n[1]=o(e[1]),n.fallback=o(e[2])):e.forEach((t,r)=>{r===e.length-1?n.fallback=o(t):n[r.toString()]=o(t)}),n.__intlayer_vue_i18n_var=`count`,t.enu(n)},c={canHandle:e=>typeof e==`string`&&(e.includes(`{`)||e.includes(`|`)),transform:e=>{try{return s(a(e))}catch{return e}}},l={canHandle:e=>{if(typeof e==`string`||e&&typeof e==`object`&&(e.nodeType===r.NodeType.Insertion||e.nodeType===r.NodeType.Enumeration||e.nodeType===r.NodeType.Gender||e.nodeType===`composite`))return!0;if(Array.isArray(e)){if(e.length===0)return!1;let t=!1,n=!1;for(let i of e)typeof i==`string`||(i&&typeof i==`object`&&(i.nodeType===r.NodeType.Insertion||i.nodeType===r.NodeType.Enumeration||i.nodeType===r.NodeType.Gender||i.nodeType===`composite`)?t=!0:n=!0);return!(n||!t)}return!1},transform:(e,t,n)=>{if(typeof e==`string`)return e.replace(/\{\{([^}]+)\}\}/g,`{$1}`);if(e.nodeType===r.NodeType.Insertion)return e.insertion.replace(/\{\{([^}]+)\}\}/g,`{$1}`);if(e.nodeType===r.NodeType.Enumeration){let r=e.enumeration,i={};for(let[e,a]of Object.entries(r)){if(e===`__intlayer_vue_i18n_var`)continue;let r=n(a,t);i[e]=typeof r==`string`?r:JSON.stringify(r)}let a=Object.keys(i);if(a.includes(`0`)){let e=a.filter(e=>/^\d+$/.test(e)).map(Number),t=Math.max(...e),n=i.fallback||i.other,r=[];if(t<=1&&!a.includes(`2`))return`${i[0]||``} | ${i[1]||``} | ${n}`;let o=Math.max(1,t);for(let e=0;e<=o;e++){let t=e.toString();i[t]?r.push(i[t]):r.push(``)}return r.push(n),r.join(` | `).replace(/ \| {2}\| /g,` | | `)}return a.includes(`1`)&&(a.includes(`fallback`)||a.includes(`other`))?`${i[1]} | ${i.fallback||i.other}`:a.length===1&&(a.includes(`fallback`)||a.includes(`other`))?i.fallback||i.other:i.fallback||Object.values(i)[0]}if(e.nodeType===r.NodeType.Gender){let r=e.gender,i={};for(let[e,a]of Object.entries(r)){let r=e;e===`fallback`&&(r=`other`),i[r]=n(a,t)}return i}return Array.isArray(e)||e.nodeType===`composite`&&Array.isArray(e.composite)?(Array.isArray(e)?e:e.composite).map(e=>n(e,t)).join(``):n(e,t)}},u=t=>e.deepTransformNode(t,{dictionaryKey:`vue-i18n`,keyPath:[],plugins:[{id:`vue-i18n`,...l}]}),d=t=>e.deepTransformNode(t,{dictionaryKey:`vue-i18n`,keyPath:[],plugins:[{id:`vue-i18n`,...c}]});exports.intlayerToVueI18nFormatter=u,exports.vueI18nToIntlayerFormatter=d;
|
|
2
2
|
//# sourceMappingURL=vue-i18n.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vue-i18n.cjs","names":["insert","enu","NodeType","deepTransformNode"],"sources":["../../../src/messageFormat/vue-i18n.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/types/dictionary';;\nimport { NodeType } from '@intlayer/types/nodeType';\nimport { deepTransformNode } from '../interpreter';\nimport { enu, insert } from '../transpiler';\nimport type { JsonValue } from './ICU';\n\n// Types for our AST\ntype VueI18nNode =\n | string\n | {\n type: 'argument';\n name: string;\n };\n\nconst parseVueI18nPart = (text: string): VueI18nNode[] => {\n let index = 0;\n const nodes: VueI18nNode[] = [];\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 let name = '';\n while (index < text.length && text[index] !== '}') {\n name += text[index];\n index++;\n }\n if (index < text.length) {\n index++; // skip }\n }\n nodes.push({ type: 'argument', name: name.trim() });\n } else {\n currentText += char;\n index++;\n }\n }\n\n if (currentText) {\n nodes.push(currentText);\n }\n\n return nodes;\n};\n\nconst parseVueI18n = (text: string): VueI18nNode[][] => {\n // Split by | but handle escaped \\|\n const parts: string[] = [];\n let currentPart = '';\n let index = 0;\n\n while (index < text.length) {\n const char = text[index];\n if (char === '\\\\' && index + 1 < text.length && text[index + 1] === '|') {\n currentPart += '|';\n index += 2;\n } else if (char === '|') {\n parts.push(currentPart.trim()); // Trim to remove surrounding spaces\n currentPart = '';\n index++;\n } else {\n currentPart += char;\n index++;\n }\n }\n parts.push(currentPart.trim()); // Trim last part too\n\n return parts.map(parseVueI18nPart);\n};\n\nconst vueI18nPartToIntlayer = (nodes: VueI18nNode[]): any => {\n if (nodes.length === 0) return '';\n if (nodes.length === 1 && typeof nodes[0] === 'string') return nodes[0];\n\n let str = '';\n for (const node of nodes) {\n if (typeof node === 'string') {\n str += node;\n } else {\n str += `{{${node.name}}}`;\n }\n }\n return insert(str);\n};\n\nconst vueI18nNodesToIntlayer = (parts: VueI18nNode[][]): any => {\n if (parts.length === 1) {\n return vueI18nPartToIntlayer(parts[0]);\n }\n\n // Handle pluralization (choice)\n const options: Record<string, any> = {};\n const varName = 'count'; // Default variable for vue-i18n choices\n\n if (parts.length === 2) {\n // 2 choices: 1 | other\n options['1'] = vueI18nPartToIntlayer(parts[0]);\n options.fallback = vueI18nPartToIntlayer(parts[1]);\n } else if (parts.length === 3) {\n // 3 choices: 0 | 1 | other\n options['0'] = vueI18nPartToIntlayer(parts[0]);\n options['1'] = vueI18nPartToIntlayer(parts[1]);\n options.fallback = vueI18nPartToIntlayer(parts[2]);\n } else {\n // > 3 choices: 0 | 1 | 2 | ... | other\n parts.forEach((part, index) => {\n if (index === parts.length - 1) {\n options.fallback = vueI18nPartToIntlayer(part);\n } else {\n options[index.toString()] = vueI18nPartToIntlayer(part);\n }\n });\n }\n\n // Preserve variable name\n options.__intlayer_vue_i18n_var = varName;\n\n return enu(options);\n};\n\nconst vueI18nToIntlayerPlugin = {\n canHandle: (node: any) =>\n typeof node === 'string' && (node.includes('{') || node.includes('|')),\n transform: (node: any) => {\n try {\n const ast = parseVueI18n(node);\n return vueI18nNodesToIntlayer(ast);\n } catch {\n return node;\n }\n },\n};\n\nconst intlayerToVueI18nPlugin = {\n canHandle: (node: any) =>\n typeof node === 'string' ||\n (node &&\n typeof node === 'object' &&\n (node.nodeType === NodeType.Insertion ||\n node.nodeType === NodeType.Enumeration ||\n node.nodeType === NodeType.Gender ||\n node.nodeType === 'composite')) ||\n Array.isArray(node),\n transform: (node: any, props: any, next: any) => {\n if (typeof node === 'string') {\n // replace {{...}} with {...} even in strings\n return node.replace(/\\{\\{([^}]+)\\}\\}/g, '{$1}');\n }\n\n if (node.nodeType === NodeType.Insertion) {\n // {{name}} -> {name}\n return node.insertion.replace(/\\{\\{([^}]+)\\}\\}/g, '{$1}');\n }\n\n if (node.nodeType === NodeType.Enumeration) {\n const options = node.enumeration;\n\n const transformedOptions: Record<string, string> = {};\n for (const [key, val] of Object.entries(options)) {\n if (key === '__intlayer_vue_i18n_var') continue;\n const childVal = next(val, props);\n transformedOptions[key] =\n typeof childVal === 'string' ? childVal : JSON.stringify(childVal);\n }\n\n // We need to reconstruct the pipe-separated string.\n // 2 parts: 1, fallback\n // 3 parts: 0, 1, fallback\n\n const keys = Object.keys(transformedOptions);\n\n // Heuristic to decide format\n // Use loose condition for 3 parts: if 0 exists, OR if 2 exists, etc.\n // But typically 0, 1, 2...\n // If '0' is present, we likely want the 3+ parts format.\n if (keys.includes('0')) {\n const indices = keys.filter((key) => /^\\d+$/.test(key)).map(Number);\n const maxIndex = Math.max(...indices);\n\n const fallback =\n transformedOptions.fallback || transformedOptions.other;\n const resultParts = [];\n\n // Check if we can use simple 3-part: 0 | 1 | fallback\n // Only if maxIndex <= 1\n if (maxIndex <= 1 && !keys.includes('2')) {\n const zero = transformedOptions['0'] || '';\n const one = transformedOptions['1'] || ''; // Gap handling?\n return `${zero} | ${one} | ${fallback}`;\n }\n\n // General case: loop until maxIndex\n const limit = Math.max(1, maxIndex);\n\n for (let i = 0; i <= limit; i++) {\n const key = i.toString();\n if (transformedOptions[key]) {\n resultParts.push(transformedOptions[key]);\n } else {\n resultParts.push(''); // Empty string for gaps\n }\n }\n resultParts.push(fallback);\n return resultParts.join(' | ').replace(/ \\| {2}\\| /g, ' | | ');\n }\n\n // 2 parts: 1 | fallback\n if (\n keys.includes('1') &&\n (keys.includes('fallback') || keys.includes('other'))\n ) {\n return `${transformedOptions['1']} | ${transformedOptions.fallback || transformedOptions.other}`;\n }\n\n // Fallback for only fallback?\n if (\n keys.length === 1 &&\n (keys.includes('fallback') || keys.includes('other'))\n ) {\n return transformedOptions.fallback || transformedOptions.other;\n }\n\n // Default fallback\n return (\n transformedOptions.fallback || Object.values(transformedOptions)[0]\n );\n }\n\n // Gender not supported by vue-i18n string format, return object\n if (node.nodeType === NodeType.Gender) {\n const options = node.gender;\n const transformedOptions: Record<string, any> = {};\n\n // Just map values\n for (const [key, val] of Object.entries(options)) {\n let newKey = key;\n if (key === 'fallback') newKey = 'other'; // vue-i18n doesn't strictly have 'other' for gender objects but standard convention often uses similar keys\n\n const childVal = next(val, props);\n transformedOptions[newKey] = childVal;\n }\n return transformedOptions;\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 intlayerToVueI18nFormatter = (\n message: Dictionary['content']\n): JsonValue => {\n return deepTransformNode(message, {\n dictionaryKey: 'vue-i18n',\n keyPath: [],\n plugins: [{ id: 'vue-i18n', ...intlayerToVueI18nPlugin }],\n });\n};\n\nexport const vueI18nToIntlayerFormatter = (\n message: JsonValue\n): Dictionary['content'] => {\n return deepTransformNode(message, {\n dictionaryKey: 'vue-i18n',\n keyPath: [],\n plugins: [{ id: 'vue-i18n', ...vueI18nToIntlayerPlugin }],\n });\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"vue-i18n.cjs","names":["insert","enu","NodeType","deepTransformNode"],"sources":["../../../src/messageFormat/vue-i18n.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/types/dictionary';\n\nimport { NodeType } from '@intlayer/types/nodeType';\nimport { deepTransformNode } from '../interpreter';\nimport { enu, insert } from '../transpiler';\nimport type { JsonValue } from './ICU';\n\n// Types for our AST\ntype VueI18nNode =\n | string\n | {\n type: 'argument';\n name: string;\n };\n\nconst parseVueI18nPart = (text: string): VueI18nNode[] => {\n let index = 0;\n const nodes: VueI18nNode[] = [];\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 let name = '';\n while (index < text.length && text[index] !== '}') {\n name += text[index];\n index++;\n }\n if (index < text.length) {\n index++; // skip }\n }\n nodes.push({ type: 'argument', name: name.trim() });\n } else {\n currentText += char;\n index++;\n }\n }\n\n if (currentText) {\n nodes.push(currentText);\n }\n\n return nodes;\n};\n\nconst parseVueI18n = (text: string): VueI18nNode[][] => {\n // Split by | but handle escaped \\|\n const parts: string[] = [];\n let currentPart = '';\n let index = 0;\n\n while (index < text.length) {\n const char = text[index];\n if (char === '\\\\' && index + 1 < text.length && text[index + 1] === '|') {\n currentPart += '|';\n index += 2;\n } else if (char === '|') {\n parts.push(currentPart.trim()); // Trim to remove surrounding spaces\n currentPart = '';\n index++;\n } else {\n currentPart += char;\n index++;\n }\n }\n parts.push(currentPart.trim()); // Trim last part too\n\n return parts.map(parseVueI18nPart);\n};\n\nconst vueI18nPartToIntlayer = (nodes: VueI18nNode[]): any => {\n if (nodes.length === 0) return '';\n if (nodes.length === 1 && typeof nodes[0] === 'string') return nodes[0];\n\n let str = '';\n for (const node of nodes) {\n if (typeof node === 'string') {\n str += node;\n } else {\n str += `{{${node.name}}}`;\n }\n }\n return insert(str);\n};\n\nconst vueI18nNodesToIntlayer = (parts: VueI18nNode[][]): any => {\n if (parts.length === 1) {\n return vueI18nPartToIntlayer(parts[0]);\n }\n\n // Handle pluralization (choice)\n const options: Record<string, any> = {};\n const varName = 'count'; // Default variable for vue-i18n choices\n\n if (parts.length === 2) {\n // 2 choices: 1 | other\n options['1'] = vueI18nPartToIntlayer(parts[0]);\n options.fallback = vueI18nPartToIntlayer(parts[1]);\n } else if (parts.length === 3) {\n // 3 choices: 0 | 1 | other\n options['0'] = vueI18nPartToIntlayer(parts[0]);\n options['1'] = vueI18nPartToIntlayer(parts[1]);\n options.fallback = vueI18nPartToIntlayer(parts[2]);\n } else {\n // > 3 choices: 0 | 1 | 2 | ... | other\n parts.forEach((part, index) => {\n if (index === parts.length - 1) {\n options.fallback = vueI18nPartToIntlayer(part);\n } else {\n options[index.toString()] = vueI18nPartToIntlayer(part);\n }\n });\n }\n\n // Preserve variable name\n options.__intlayer_vue_i18n_var = varName;\n\n return enu(options);\n};\n\nconst vueI18nToIntlayerPlugin = {\n canHandle: (node: any) =>\n typeof node === 'string' && (node.includes('{') || node.includes('|')),\n transform: (node: any) => {\n try {\n const ast = parseVueI18n(node);\n return vueI18nNodesToIntlayer(ast);\n } catch {\n return node;\n }\n },\n};\n\nconst intlayerToVueI18nPlugin = {\n canHandle: (node: any) => {\n if (typeof node === 'string') return true;\n\n if (\n node &&\n typeof node === 'object' &&\n (node.nodeType === NodeType.Insertion ||\n node.nodeType === NodeType.Enumeration ||\n node.nodeType === NodeType.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 === NodeType.Insertion ||\n item.nodeType === NodeType.Enumeration ||\n item.nodeType === NodeType.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 // replace {{...}} with {...} even in strings\n return node.replace(/\\{\\{([^}]+)\\}\\}/g, '{$1}');\n }\n\n if (node.nodeType === NodeType.Insertion) {\n // {{name}} -> {name}\n return node.insertion.replace(/\\{\\{([^}]+)\\}\\}/g, '{$1}');\n }\n\n if (node.nodeType === NodeType.Enumeration) {\n const options = node.enumeration;\n\n const transformedOptions: Record<string, string> = {};\n for (const [key, val] of Object.entries(options)) {\n if (key === '__intlayer_vue_i18n_var') continue;\n const childVal = next(val, props);\n transformedOptions[key] =\n typeof childVal === 'string' ? childVal : JSON.stringify(childVal);\n }\n\n const keys = Object.keys(transformedOptions);\n\n if (keys.includes('0')) {\n const indices = keys.filter((key) => /^\\d+$/.test(key)).map(Number);\n const maxIndex = Math.max(...indices);\n\n const fallback =\n transformedOptions.fallback || transformedOptions.other;\n const resultParts = [];\n\n if (maxIndex <= 1 && !keys.includes('2')) {\n const zero = transformedOptions['0'] || '';\n const one = transformedOptions['1'] || '';\n return `${zero} | ${one} | ${fallback}`;\n }\n\n const limit = Math.max(1, maxIndex);\n\n for (let i = 0; i <= limit; i++) {\n const key = i.toString();\n if (transformedOptions[key]) {\n resultParts.push(transformedOptions[key]);\n } else {\n resultParts.push('');\n }\n }\n resultParts.push(fallback);\n return resultParts.join(' | ').replace(/ \\| {2}\\| /g, ' | | ');\n }\n\n if (\n keys.includes('1') &&\n (keys.includes('fallback') || keys.includes('other'))\n ) {\n return `${transformedOptions['1']} | ${transformedOptions.fallback || transformedOptions.other}`;\n }\n\n if (\n keys.length === 1 &&\n (keys.includes('fallback') || keys.includes('other'))\n ) {\n return transformedOptions.fallback || transformedOptions.other;\n }\n\n return (\n transformedOptions.fallback || Object.values(transformedOptions)[0]\n );\n }\n\n if (node.nodeType === NodeType.Gender) {\n const options = node.gender;\n const transformedOptions: Record<string, any> = {};\n\n for (const [key, val] of Object.entries(options)) {\n let newKey = key;\n if (key === 'fallback') newKey = 'other';\n\n const childVal = next(val, props);\n transformedOptions[newKey] = childVal;\n }\n return transformedOptions;\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 intlayerToVueI18nFormatter = (\n message: Dictionary['content']\n): JsonValue => {\n return deepTransformNode(message, {\n dictionaryKey: 'vue-i18n',\n keyPath: [],\n plugins: [{ id: 'vue-i18n', ...intlayerToVueI18nPlugin }],\n });\n};\n\nexport const vueI18nToIntlayerFormatter = (\n message: JsonValue\n): Dictionary['content'] => {\n return deepTransformNode(message, {\n dictionaryKey: 'vue-i18n',\n keyPath: [],\n plugins: [{ id: 'vue-i18n', ...vueI18nToIntlayerPlugin }],\n });\n};\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{deepTransformNode as e}from"../interpreter/getContent/deepTransform.mjs";import{enu as t}from"../transpiler/enumeration/enumeration.mjs";import{gender as n}from"../transpiler/gender/gender.mjs";import{html as r}from"../transpiler/html/html.mjs";import{insert as i}from"../transpiler/insertion/insertion.mjs";import{NodeType as a}from"@intlayer/types/nodeType";const o=e=>{let t=0,n=()=>{let n=[],i=``;for(;t<e.length;){let a=e[t];if(a===`{`)i&&=(n.push(i),``),t++,n.push(r());else if(a===`}`)break;else if(a===`'`)if(t+1<e.length&&e[t+1]===`'`)i+=`'`,t+=2;else{let n=e.indexOf(`'`,t+1);n===-1?(i+=`'`,t++):(i+=e.substring(t+1,n),t=n+1)}else i+=a,t++}return i&&n.push(i),n},r=()=>{let r=``;for(;t<e.length&&/[^,}]/.test(e[t]);)r+=e[t],t++;if(r=r.trim(),t>=e.length)throw Error(`Unclosed argument`);if(e[t]===`}`)return t++,{type:`argument`,name:r};if(e[t]===`,`){t++;let i=``;for(;t<e.length&&/[^,}]/.test(e[t]);)i+=e[t],t++;if(i=i.trim(),t>=e.length)throw Error(`Unclosed argument`);if(e[t]===`}`)return t++,{type:`argument`,name:r,format:{type:i}};if(e[t]===`,`)if(t++,i===`plural`||i===`select`){let a={};for(;t<e.length&&e[t]!==`}`;){for(;t<e.length&&/\s/.test(e[t]);)t++;let r=``;for(;t<e.length&&/[^{\s]/.test(e[t]);)r+=e[t],t++;for(;t<e.length&&/\s/.test(e[t]);)t++;if(e[t]!==`{`)throw Error(`Expected { after option key`);t++;let i=n();if(e[t]!==`}`)throw Error(`Expected } after option value`);for(t++,a[r]=i;t<e.length&&/\s/.test(e[t]);)t++}if(t++,i===`plural`)return{type:`plural`,name:r,options:a};if(i===`select`)return{type:`select`,name:r,options:a}}else{let n=``;for(;t<e.length&&e[t]!==`}`;)n+=e[t],t++;if(t>=e.length)throw Error(`Unclosed argument`);return n=n.trim(),t++,{type:`argument`,name:r,format:{type:i,style:n}}}}throw Error(`Malformed argument`)};return n()},s=e=>{if(e.length===0)return``;if(e.length===1&&typeof e[0]==`string`){let t=e[0];return/<[a-zA-Z0-9-]+[^>]*>/.test(t)?r(t):t}if(e.every(e=>typeof e==`string`||e.type===`argument`)){let t=``;for(let n of e)typeof n==`string`?t+=n:typeof n!=`string`&&n.type===`argument`&&(n.format?t+=`{${n.name}, ${n.format.type}${n.format.style?`, ${n.format.style}`:``}}`:t+=`{{${n.name}}}`);return/<[a-zA-Z0-9-]+[^>]*>/.test(t)?r(t):i(t)}if(e.length===1){let a=e[0];if(typeof a==`string`)return/<[a-zA-Z0-9-]+[^>]*>/.test(a)?r(a):a;if(a.type===`argument`)return a.format?i(`{${a.name}, ${a.format.type}${a.format.style?`, ${a.format.style}`:``}}`):i(`{{${a.name}}}`);if(a.type===`plural`){let e={};for(let[t,n]of Object.entries(a.options)){let r=t;t.startsWith(`=`)?r=t.substring(1):t===`one`?r=`1`:t===`two`?r=`2`:t===`few`?r=`<=3`:t===`many`?r=`>=4`:t===`other`&&(r=`fallback`),e[r]=s(n.map(e=>typeof e==`string`?e.replace(/#/g,`{{${a.name}}}`):e))}return e.__intlayer_icu_var=a.name,t(e)}if(a.type===`select`){let e={};for(let[t,n]of Object.entries(a.options))e[t]=s(n);let r=Object.keys(e);return(e.male||e.female)&&r.every(e=>[`male`,`female`,`other`,`fallback`].includes(e))?n({fallback:e.other,male:e.male,female:e.female}):(e.__intlayer_icu_var=a.name,t(e))}}return e.map(e=>s([e]))},c={canHandle:e=>typeof e==`string`&&(e.includes(`{`)||e.includes(`}`)||/<[a-zA-Z0-9-]+[^>]*>/.test(e)),transform:e=>{try{return s(o(e))}catch{return e}}},l={canHandle:e=>typeof e==`string`&&(e.includes(`{`)||e.includes(`}`))||e&&typeof e==`object`&&(e.nodeType===a.Insertion||e.nodeType===a.HTML||e.nodeType===a.Enumeration||e.nodeType===a.Gender||e.nodeType===`composite`)
|
|
1
|
+
import{deepTransformNode as e}from"../interpreter/getContent/deepTransform.mjs";import{enu as t}from"../transpiler/enumeration/enumeration.mjs";import{gender as n}from"../transpiler/gender/gender.mjs";import{html as r}from"../transpiler/html/html.mjs";import{insert as i}from"../transpiler/insertion/insertion.mjs";import{NodeType as a}from"@intlayer/types/nodeType";const o=e=>{let t=0,n=()=>{let n=[],i=``;for(;t<e.length;){let a=e[t];if(a===`{`)i&&=(n.push(i),``),t++,n.push(r());else if(a===`}`)break;else if(a===`'`)if(t+1<e.length&&e[t+1]===`'`)i+=`'`,t+=2;else{let n=e.indexOf(`'`,t+1);n===-1?(i+=`'`,t++):(i+=e.substring(t+1,n),t=n+1)}else i+=a,t++}return i&&n.push(i),n},r=()=>{let r=``;for(;t<e.length&&/[^,}]/.test(e[t]);)r+=e[t],t++;if(r=r.trim(),t>=e.length)throw Error(`Unclosed argument`);if(e[t]===`}`)return t++,{type:`argument`,name:r};if(e[t]===`,`){t++;let i=``;for(;t<e.length&&/[^,}]/.test(e[t]);)i+=e[t],t++;if(i=i.trim(),t>=e.length)throw Error(`Unclosed argument`);if(e[t]===`}`)return t++,{type:`argument`,name:r,format:{type:i}};if(e[t]===`,`)if(t++,i===`plural`||i===`select`){let a={};for(;t<e.length&&e[t]!==`}`;){for(;t<e.length&&/\s/.test(e[t]);)t++;let r=``;for(;t<e.length&&/[^{\s]/.test(e[t]);)r+=e[t],t++;for(;t<e.length&&/\s/.test(e[t]);)t++;if(e[t]!==`{`)throw Error(`Expected { after option key`);t++;let i=n();if(e[t]!==`}`)throw Error(`Expected } after option value`);for(t++,a[r]=i;t<e.length&&/\s/.test(e[t]);)t++}if(t++,i===`plural`)return{type:`plural`,name:r,options:a};if(i===`select`)return{type:`select`,name:r,options:a}}else{let n=``;for(;t<e.length&&e[t]!==`}`;)n+=e[t],t++;if(t>=e.length)throw Error(`Unclosed argument`);return n=n.trim(),t++,{type:`argument`,name:r,format:{type:i,style:n}}}}throw Error(`Malformed argument`)};return n()},s=e=>{if(e.length===0)return``;if(e.length===1&&typeof e[0]==`string`){let t=e[0];return/<[a-zA-Z0-9-]+[^>]*>/.test(t)?r(t):t}if(e.every(e=>typeof e==`string`||e.type===`argument`)){let t=``;for(let n of e)typeof n==`string`?t+=n:typeof n!=`string`&&n.type===`argument`&&(n.format?t+=`{${n.name}, ${n.format.type}${n.format.style?`, ${n.format.style}`:``}}`:t+=`{{${n.name}}}`);return/<[a-zA-Z0-9-]+[^>]*>/.test(t)?r(t):i(t)}if(e.length===1){let a=e[0];if(typeof a==`string`)return/<[a-zA-Z0-9-]+[^>]*>/.test(a)?r(a):a;if(a.type===`argument`)return a.format?i(`{${a.name}, ${a.format.type}${a.format.style?`, ${a.format.style}`:``}}`):i(`{{${a.name}}}`);if(a.type===`plural`){let e={};for(let[t,n]of Object.entries(a.options)){let r=t;t.startsWith(`=`)?r=t.substring(1):t===`one`?r=`1`:t===`two`?r=`2`:t===`few`?r=`<=3`:t===`many`?r=`>=4`:t===`other`&&(r=`fallback`),e[r]=s(n.map(e=>typeof e==`string`?e.replace(/#/g,`{{${a.name}}}`):e))}return e.__intlayer_icu_var=a.name,t(e)}if(a.type===`select`){let e={};for(let[t,n]of Object.entries(a.options))e[t]=s(n);let r=Object.keys(e);return(e.male||e.female)&&r.every(e=>[`male`,`female`,`other`,`fallback`].includes(e))?n({fallback:e.other,male:e.male,female:e.female}):(e.__intlayer_icu_var=a.name,t(e))}}return e.map(e=>s([e]))},c={canHandle:e=>typeof e==`string`&&(e.includes(`{`)||e.includes(`}`)||/<[a-zA-Z0-9-]+[^>]*>/.test(e)),transform:e=>{try{return s(o(e))}catch{return e}}},l={canHandle:e=>{if(typeof e==`string`&&(e.includes(`{`)||e.includes(`}`))||e&&typeof e==`object`&&(e.nodeType===a.Insertion||e.nodeType===a.HTML||e.nodeType===a.Enumeration||e.nodeType===a.Gender||e.nodeType===`composite`))return!0;if(Array.isArray(e)){if(e.length===0)return!1;let t=!1,n=!1;for(let r of e)typeof r==`string`||(r&&typeof r==`object`&&(r.nodeType===a.Insertion||r.nodeType===a.HTML||r.nodeType===a.Enumeration||r.nodeType===a.Gender||r.nodeType===`composite`)?t=!0:n=!0);return!(n||!t)}return!1},transform:(e,t,n)=>{if(typeof e==`string`)return e.replace(/\{\{([^}]+)\}\}/g,`{$1}`);if(e.nodeType===a.Insertion)return e.insertion.replace(/\{\{([^}]+)\}\}/g,`{$1}`);if(e.nodeType===a.HTML)return e.html;if(e.nodeType===a.Enumeration){let r=e.enumeration,i={};for(let[e,a]of Object.entries(r)){if(e===`__intlayer_icu_var`)continue;let r=n(a,t);i[e]=typeof r==`string`?r:JSON.stringify(r)}let a=r.__intlayer_icu_var||`n`;if(!r.__intlayer_icu_var){let e=(i.fallback||i.other||Object.values(i)[0]).match(/\{([a-zA-Z0-9_]+)\}(?!,)/);e&&(a=e[1])}let o=Object.keys(i),s=[`1`,`2`,`<=3`,`>=4`,`fallback`,`other`,`zero`,`one`,`two`,`few`,`many`],c=o.every(e=>s.includes(e)||/^[<>=]?\d+(\.\d+)?$/.test(e)),l=[];if(c){for(let[e,t]of Object.entries(i)){let n=e;n=e===`fallback`?`other`:e===`<=3`?`few`:e===`>=4`?`many`:/^\d+$/.test(e)?`=${e}`:[`zero`,`few`,`many`].includes(e)?e:`other`;let r=t;r=r.replace(RegExp(`\\{${a}\\}`,`g`),`#`),l.push(`${n} {${r}}`)}return`{${a}, plural, ${l.join(` `)}}`}else{let e=Object.entries(i).sort(([e],[t])=>e===`fallback`||e===`other`?1:t===`fallback`||t===`other`?-1:0);for(let[t,n]of e){let e=t;t===`fallback`&&(e=`other`),l.push(`${e} {${n}}`)}return`{${a}, select, ${l.join(` `)}}`}}if(e.nodeType===a.Gender){let r=e.gender,i=[],a=Object.entries(r).sort(([e],[t])=>e===`fallback`?1:t===`fallback`?-1:0);for(let[e,r]of a){let a=e;e===`fallback`&&(a=`other`);let o=n(r,t),s=typeof o==`string`?o:JSON.stringify(o);i.push(`${a} {${s}}`)}return`{gender, select, ${i.join(` `)}}`}return Array.isArray(e)||e.nodeType===`composite`&&Array.isArray(e.composite)?(Array.isArray(e)?e:e.composite).map(e=>n(e,t)).join(``):n(e,t)}},u=t=>e(t,{dictionaryKey:`icu`,keyPath:[],plugins:[{id:`icu`,...l}]}),d=t=>e(t,{dictionaryKey:`icu`,keyPath:[],plugins:[{id:`icu`,...c}]});export{d as icuToIntlayerFormatter,u as intlayerToICUFormatter};
|
|
2
2
|
//# sourceMappingURL=ICU.mjs.map
|
|
@@ -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 { NodeType } 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 (typeof node === 'string' && (node.includes('{') || node.includes('}'))) ||\n (node &&\n typeof node === 'object' &&\n (node.nodeType === NodeType.Insertion ||\n node.nodeType === NodeType.HTML ||\n node.nodeType === NodeType.Enumeration ||\n node.nodeType === NodeType.Gender ||\n node.nodeType === 'composite')) ||\n Array.isArray(node),\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 === NodeType.Insertion) {\n // Convert Intlayer format to ICU format:\n // - {{name}} → {name} (simple variable)\n // - {amount, number, currency} → {amount, number, currency} (formatted variable, already in ICU format)\n return node.insertion.replace(/\\{\\{([^}]+)\\}\\}/g, '{$1}');\n }\n\n if (node.nodeType === NodeType.HTML) {\n return node.html;\n }\n\n if (node.nodeType === NodeType.Enumeration) {\n const options = node.enumeration;\n\n // Transform all values first\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 // Infer variable name\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 // Match {variable} but avoid {variable, ...} (which are nested ICUs)\n // Actually nested ICU starts with {var, ...\n // Simple variable is {var}\n // We look for {var} that is NOT followed by ,\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 // Also check for numbers\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\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\n // Replace {varName} with #\n // Note: next() has already converted {{var}} -> {var}\n strVal = strVal.replace(new RegExp(`\\\\{${varName}\\\\}`, 'g'), '#');\n\n parts.push(`${icuKey} {${strVal}}`);\n }\n\n return `{${varName}, plural, ${parts.join(' ')}}`;\n } else {\n // Select\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 // Do NOT map other keys to 'other'. Keep 'active', 'inactive', etc.\n\n parts.push(`${icuKey} {${val}}`);\n }\n return `{${varName}, select, ${parts.join(' ')}}`;\n }\n }\n\n if (node.nodeType === NodeType.Gender) {\n const options = node.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\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';\n\nimport { NodeType } 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 === NodeType.Insertion ||\n node.nodeType === NodeType.HTML ||\n node.nodeType === NodeType.Enumeration ||\n node.nodeType === NodeType.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 === NodeType.Insertion ||\n item.nodeType === NodeType.HTML ||\n item.nodeType === NodeType.Enumeration ||\n item.nodeType === NodeType.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 === NodeType.Insertion) {\n return node.insertion.replace(/\\{\\{([^}]+)\\}\\}/g, '{$1}');\n }\n\n if (node.nodeType === NodeType.HTML) {\n return node.html;\n }\n\n if (node.nodeType === NodeType.Enumeration) {\n const options = node.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 === NodeType.Gender) {\n const options = node.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,2 +1,2 @@
|
|
|
1
|
-
import{deepTransformNode as e}from"../interpreter/getContent/deepTransform.mjs";import{enu as t}from"../transpiler/enumeration/enumeration.mjs";import{gender as n}from"../transpiler/gender/gender.mjs";import{html as r}from"../transpiler/html/html.mjs";import{insert as i}from"../transpiler/insertion/insertion.mjs";import{NodeType as a}from"@intlayer/types/nodeType";const o=e=>{let t=0,n=()=>{let n=[],a=``;for(;t<e.length;){let o=e[t];if(o===`{`&&e[t+1]===`{`)a&&=(n.push(a),``),t+=2,n.push(r());else if(o===`{`)a&&=(n.push(a),``),t++,n.push(i());else if(o===`}`)break;else a+=o,t++}return a&&n.push(a),n},r=()=>{let n=``;for(;t<e.length;){if(e[t]===`}`&&e[t+1]===`}`)return t+=2,{type:`argument`,name:n.trim()};n+=e[t],t++}throw Error(`Unclosed i18next variable`)},i=()=>{let r=``;for(;t<e.length&&/[^,}]/.test(e[t]);)r+=e[t],t++;if(r=r.trim(),t>=e.length)throw Error(`Unclosed argument`);if(e[t]===`}`)return t++,{type:`argument`,name:r};if(e[t]===`,`){t++;let i=``;for(;t<e.length&&/[^,}]/.test(e[t]);)i+=e[t],t++;if(i=i.trim(),t>=e.length)throw Error(`Unclosed argument`);if(e[t]===`}`)return t++,{type:`argument`,name:r,format:{type:i}};if(e[t]===`,`)if(t++,i===`plural`||i===`select`){let a={};for(;t<e.length&&e[t]!==`}`;){for(;t<e.length&&/\s/.test(e[t]);)t++;let r=``;for(;t<e.length&&/[^{\s]/.test(e[t]);)r+=e[t],t++;for(;t<e.length&&/\s/.test(e[t]);)t++;if(e[t]!==`{`)throw Error(`Expected { after option key`);t++;let i=n();if(e[t]!==`}`)throw Error(`Expected } after option value`);for(t++,a[r]=i;t<e.length&&/\s/.test(e[t]);)t++}if(t++,i===`plural`)return{type:`plural`,name:r,options:a};if(i===`select`)return{type:`select`,name:r,options:a}}else{let n=``;for(;t<e.length&&e[t]!==`}`;)n+=e[t],t++;if(t>=e.length)throw Error(`Unclosed argument`);return n=n.trim(),t++,{type:`argument`,name:r,format:{type:i,style:n}}}}throw Error(`Malformed argument`)};return n()},s=e=>{if(e.length===0)return``;if(e.length===1&&typeof e[0]==`string`){let t=e[0];return/<[a-zA-Z0-9-]+[^>]*>/.test(t)?r(t):t}if(e.every(e=>typeof e==`string`||e.type===`argument`)){let t=``;for(let n of e)typeof n==`string`?t+=n:typeof n!=`string`&&n.type===`argument`&&(n.format?t+=`{${n.name}, ${n.format.type}${n.format.style?`, ${n.format.style}`:``}}`:t+=`{{${n.name}}}`);return/<[a-zA-Z0-9-]+[^>]*>/.test(t)?r(t):i(t)}if(e.length===1){let a=e[0];if(typeof a==`string`)return/<[a-zA-Z0-9-]+[^>]*>/.test(a)?r(a):a;if(a.type===`argument`)return a.format?i(`{${a.name}, ${a.format.type}${a.format.style?`, ${a.format.style}`:``}}`):i(`{{${a.name}}}`);if(a.type===`plural`){let e={};for(let[t,n]of Object.entries(a.options)){let r=t;t.startsWith(`=`)?r=t.substring(1):t===`one`?r=`1`:t===`two`?r=`2`:t===`few`?r=`<=3`:t===`many`?r=`>=4`:t===`other`&&(r=`fallback`),e[r]=s(n.map(e=>typeof e==`string`?e.replace(/#/g,`{{${a.name}}}`):e))}return e.__intlayer_icu_var=a.name,t(e)}if(a.type===`select`){let e={};for(let[t,n]of Object.entries(a.options))e[t]=s(n);let r=Object.keys(e);return(e.male||e.female)&&r.every(e=>[`male`,`female`,`other`,`fallback`].includes(e))?n({fallback:e.other,male:e.male,female:e.female}):(e.__intlayer_icu_var=a.name,t(e))}}return e.map(e=>s([e]))},c={canHandle:e=>typeof e==`string`&&(e.includes(`{`)||e.includes(`}`)||/<[a-zA-Z0-9-]+[^>]*>/.test(e)),transform:e=>{try{return s(o(e))}catch{return e}}},l={canHandle:e=>typeof e==`string`||e&&typeof e==`object`&&(e.nodeType===a.Insertion||e.nodeType===a.HTML||e.nodeType===a.Enumeration||e.nodeType===a.Gender||e.nodeType===`composite`)
|
|
1
|
+
import{deepTransformNode as e}from"../interpreter/getContent/deepTransform.mjs";import{enu as t}from"../transpiler/enumeration/enumeration.mjs";import{gender as n}from"../transpiler/gender/gender.mjs";import{html as r}from"../transpiler/html/html.mjs";import{insert as i}from"../transpiler/insertion/insertion.mjs";import{NodeType as a}from"@intlayer/types/nodeType";const o=e=>{let t=0,n=()=>{let n=[],a=``;for(;t<e.length;){let o=e[t];if(o===`{`&&e[t+1]===`{`)a&&=(n.push(a),``),t+=2,n.push(r());else if(o===`{`)a&&=(n.push(a),``),t++,n.push(i());else if(o===`}`)break;else a+=o,t++}return a&&n.push(a),n},r=()=>{let n=``;for(;t<e.length;){if(e[t]===`}`&&e[t+1]===`}`)return t+=2,{type:`argument`,name:n.trim()};n+=e[t],t++}throw Error(`Unclosed i18next variable`)},i=()=>{let r=``;for(;t<e.length&&/[^,}]/.test(e[t]);)r+=e[t],t++;if(r=r.trim(),t>=e.length)throw Error(`Unclosed argument`);if(e[t]===`}`)return t++,{type:`argument`,name:r};if(e[t]===`,`){t++;let i=``;for(;t<e.length&&/[^,}]/.test(e[t]);)i+=e[t],t++;if(i=i.trim(),t>=e.length)throw Error(`Unclosed argument`);if(e[t]===`}`)return t++,{type:`argument`,name:r,format:{type:i}};if(e[t]===`,`)if(t++,i===`plural`||i===`select`){let a={};for(;t<e.length&&e[t]!==`}`;){for(;t<e.length&&/\s/.test(e[t]);)t++;let r=``;for(;t<e.length&&/[^{\s]/.test(e[t]);)r+=e[t],t++;for(;t<e.length&&/\s/.test(e[t]);)t++;if(e[t]!==`{`)throw Error(`Expected { after option key`);t++;let i=n();if(e[t]!==`}`)throw Error(`Expected } after option value`);for(t++,a[r]=i;t<e.length&&/\s/.test(e[t]);)t++}if(t++,i===`plural`)return{type:`plural`,name:r,options:a};if(i===`select`)return{type:`select`,name:r,options:a}}else{let n=``;for(;t<e.length&&e[t]!==`}`;)n+=e[t],t++;if(t>=e.length)throw Error(`Unclosed argument`);return n=n.trim(),t++,{type:`argument`,name:r,format:{type:i,style:n}}}}throw Error(`Malformed argument`)};return n()},s=e=>{if(e.length===0)return``;if(e.length===1&&typeof e[0]==`string`){let t=e[0];return/<[a-zA-Z0-9-]+[^>]*>/.test(t)?r(t):t}if(e.every(e=>typeof e==`string`||e.type===`argument`)){let t=``;for(let n of e)typeof n==`string`?t+=n:typeof n!=`string`&&n.type===`argument`&&(n.format?t+=`{${n.name}, ${n.format.type}${n.format.style?`, ${n.format.style}`:``}}`:t+=`{{${n.name}}}`);return/<[a-zA-Z0-9-]+[^>]*>/.test(t)?r(t):i(t)}if(e.length===1){let a=e[0];if(typeof a==`string`)return/<[a-zA-Z0-9-]+[^>]*>/.test(a)?r(a):a;if(a.type===`argument`)return a.format?i(`{${a.name}, ${a.format.type}${a.format.style?`, ${a.format.style}`:``}}`):i(`{{${a.name}}}`);if(a.type===`plural`){let e={};for(let[t,n]of Object.entries(a.options)){let r=t;t.startsWith(`=`)?r=t.substring(1):t===`one`?r=`1`:t===`two`?r=`2`:t===`few`?r=`<=3`:t===`many`?r=`>=4`:t===`other`&&(r=`fallback`),e[r]=s(n.map(e=>typeof e==`string`?e.replace(/#/g,`{{${a.name}}}`):e))}return e.__intlayer_icu_var=a.name,t(e)}if(a.type===`select`){let e={};for(let[t,n]of Object.entries(a.options))e[t]=s(n);let r=Object.keys(e);return(e.male||e.female)&&r.every(e=>[`male`,`female`,`other`,`fallback`].includes(e))?n({fallback:e.other,male:e.male,female:e.female}):(e.__intlayer_icu_var=a.name,t(e))}}return e.map(e=>s([e]))},c={canHandle:e=>typeof e==`string`&&(e.includes(`{`)||e.includes(`}`)||/<[a-zA-Z0-9-]+[^>]*>/.test(e)),transform:e=>{try{return s(o(e))}catch{return e}}},l={canHandle:e=>{if(typeof e==`string`||e&&typeof e==`object`&&(e.nodeType===a.Insertion||e.nodeType===a.HTML||e.nodeType===a.Enumeration||e.nodeType===a.Gender||e.nodeType===`composite`))return!0;if(Array.isArray(e)){if(e.length===0)return!1;let t=!1,n=!1;for(let r of e)typeof r==`string`||(r&&typeof r==`object`&&(r.nodeType===a.Insertion||r.nodeType===a.HTML||r.nodeType===a.Enumeration||r.nodeType===a.Gender||r.nodeType===`composite`)?t=!0:n=!0);return!(n||!t)}return!1},transform:(e,t,n)=>{if(typeof e==`string`)return e;if(e.nodeType===a.Insertion)return e.insertion.match(/\{[^}]*,[^}]*\}/),e.insertion;if(e.nodeType===a.HTML)return e.html;if(e.nodeType===a.Enumeration){let r=e.enumeration,i={};for(let[e,a]of Object.entries(r)){if(e===`__intlayer_icu_var`)continue;let r=n(a,t);i[e]=typeof r==`string`?r:JSON.stringify(r)}let a=r.__intlayer_icu_var||`count`;if(!r.__intlayer_icu_var){let e=i.fallback||i.other||Object.values(i)[0],t=e.match(/\{\{([a-zA-Z0-9_]+)\}\}/)||e.match(/\{([a-zA-Z0-9_]+)\}(?!,)/);t&&(a=t[1])}let o=Object.keys(i),s=[`1`,`2`,`<=3`,`>=4`,`fallback`,`other`,`zero`,`one`,`two`,`few`,`many`],c=o.every(e=>s.includes(e)||/^[<>=]?\d+(\.\d+)?$/.test(e)),l=[];if(c){for(let[e,t]of Object.entries(i)){let n=e;e===`fallback`?n=`other`:e===`<=3`?n=`few`:e===`>=4`?n=`many`:/^\d+$/.test(e)&&(n=`=${e}`);let r=t;r=r.replace(/\{\{([^}]+)\}\}/g,`{$1}`),r=r.replace(RegExp(`\\{${a}\\}`,`g`),`#`),l.push(`${n} {${r}}`)}return`{${a}, plural, ${l.join(` `)}}`}else{let e=Object.entries(i).sort(([e],[t])=>e===`fallback`||e===`other`?1:t===`fallback`||t===`other`?-1:0);for(let[t,n]of e){let e=t;t===`fallback`&&(e=`other`);let r=n;r=r.replace(/\{\{([^}]+)\}\}/g,`{$1}`),l.push(`${e} {${r}}`)}return`{${a}, select, ${l.join(` `)}}`}}if(e.nodeType===a.Gender){let r=e.gender,i=[],a=Object.entries(r).sort(([e],[t])=>e===`fallback`?1:t===`fallback`?-1:0);for(let[e,r]of a){let a=e;e===`fallback`&&(a=`other`);let o=n(r,t),s=typeof o==`string`?o:JSON.stringify(o);s=s.replace(/\{\{([^}]+)\}\}/g,`{$1}`),i.push(`${a} {${s}}`)}return`{gender, select, ${i.join(` `)}}`}return Array.isArray(e)||e.nodeType===`composite`&&Array.isArray(e.composite)?(Array.isArray(e)?e:e.composite).map(e=>n(e,t)).join(``):n(e,t)}},u=t=>e(t,{dictionaryKey:`i18next`,keyPath:[],plugins:[{id:`i18next`,...l}]}),d=t=>e(t,{dictionaryKey:`i18next`,keyPath:[],plugins:[{id:`i18next`,...c}]});export{d as i18nextToIntlayerFormatter,u as intlayerToI18nextFormatter};
|
|
2
2
|
//# sourceMappingURL=i18next.mjs.map
|
|
@@ -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 { NodeType } 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 typeof node === 'string' ||\n (node &&\n typeof node === 'object' &&\n (node.nodeType === NodeType.Insertion ||\n node.nodeType === NodeType.HTML ||\n node.nodeType === NodeType.Enumeration ||\n node.nodeType === NodeType.Gender ||\n node.nodeType === 'composite')) ||\n Array.isArray(node),\n transform: (node: any, props: any, next: any) => {\n if (typeof node === 'string') {\n return node;\n }\n\n if (node.nodeType === NodeType.Insertion) {\n // If it contains ICU format syntax (curly braces but not double curly), keep it as is\n // But standard insert creates {{var}}.\n // Check if the original string was formatted (e.g. {val, number})\n if (node.insertion.match(/\\{[^}]*,[^}]*\\}/)) {\n // It's likely an ICU format string like {val, number}\n // We might need to ensure variables inside are not double-braced if they are part of the format\n // But wait, our parser outputs {val, number} as string for insertion.\n return node.insertion;\n }\n\n // Otherwise keep {{name}} for i18next\n return node.insertion;\n }\n\n if (node.nodeType === NodeType.HTML) {\n return node.html;\n }\n\n if (node.nodeType === NodeType.Enumeration) {\n const options = node.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 // Infer variable name\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 // Search for {{var}} or {var}\n // Match {variable} but avoid {variable, ...} (which are nested ICUs)\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 // Check if it is a plural\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 // Convert {{var}} to {var} inside ICU string\n // Also replace {varName} with # if it matches\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 // Select\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 === NodeType.Gender) {\n const options = node.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 { NodeType } 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 === NodeType.Insertion ||\n node.nodeType === NodeType.HTML ||\n node.nodeType === NodeType.Enumeration ||\n node.nodeType === NodeType.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 === NodeType.Insertion ||\n item.nodeType === NodeType.HTML ||\n item.nodeType === NodeType.Enumeration ||\n item.nodeType === NodeType.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 === NodeType.Insertion) {\n if (node.insertion.match(/\\{[^}]*,[^}]*\\}/)) {\n return node.insertion;\n }\n return node.insertion;\n }\n\n if (node.nodeType === NodeType.HTML) {\n return node.html;\n }\n\n if (node.nodeType === NodeType.Enumeration) {\n const options = node.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 === NodeType.Gender) {\n const options = node.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,2 +1,2 @@
|
|
|
1
|
-
import{deepTransformNode as e}from"../interpreter/getContent/deepTransform.mjs";import{enu as t}from"../transpiler/enumeration/enumeration.mjs";import{insert as n}from"../transpiler/insertion/insertion.mjs";import{NodeType as r}from"@intlayer/types/nodeType";const i=e=>{let t=0,n=[],r=``;for(;t<e.length;){let i=e[t];if(i===`{`){r&&=(n.push(r),``),t++;let i=``;for(;t<e.length&&e[t]!==`}`;)i+=e[t],t++;t<e.length&&t++,n.push({type:`argument`,name:i.trim()})}else r+=i,t++}return r&&n.push(r),n},a=e=>{let t=[],n=``,r=0;for(;r<e.length;){let i=e[r];i===`\\`&&r+1<e.length&&e[r+1]===`|`?(n+=`|`,r+=2):i===`|`?(t.push(n.trim()),n=``,r++):(n+=i,r++)}return t.push(n.trim()),t.map(i)},o=e=>{if(e.length===0)return``;if(e.length===1&&typeof e[0]==`string`)return e[0];let t=``;for(let n of e)typeof n==`string`?t+=n:t+=`{{${n.name}}}`;return n(t)},s=e=>{if(e.length===1)return o(e[0]);let n={};return e.length===2?(n[1]=o(e[0]),n.fallback=o(e[1])):e.length===3?(n[0]=o(e[0]),n[1]=o(e[1]),n.fallback=o(e[2])):e.forEach((t,r)=>{r===e.length-1?n.fallback=o(t):n[r.toString()]=o(t)}),n.__intlayer_vue_i18n_var=`count`,t(n)},c={canHandle:e=>typeof e==`string`&&(e.includes(`{`)||e.includes(`|`)),transform:e=>{try{return s(a(e))}catch{return e}}},l={canHandle:e=>typeof e==`string`||e&&typeof e==`object`&&(e.nodeType===r.Insertion||e.nodeType===r.Enumeration||e.nodeType===r.Gender||e.nodeType===`composite`)
|
|
1
|
+
import{deepTransformNode as e}from"../interpreter/getContent/deepTransform.mjs";import{enu as t}from"../transpiler/enumeration/enumeration.mjs";import{insert as n}from"../transpiler/insertion/insertion.mjs";import{NodeType as r}from"@intlayer/types/nodeType";const i=e=>{let t=0,n=[],r=``;for(;t<e.length;){let i=e[t];if(i===`{`){r&&=(n.push(r),``),t++;let i=``;for(;t<e.length&&e[t]!==`}`;)i+=e[t],t++;t<e.length&&t++,n.push({type:`argument`,name:i.trim()})}else r+=i,t++}return r&&n.push(r),n},a=e=>{let t=[],n=``,r=0;for(;r<e.length;){let i=e[r];i===`\\`&&r+1<e.length&&e[r+1]===`|`?(n+=`|`,r+=2):i===`|`?(t.push(n.trim()),n=``,r++):(n+=i,r++)}return t.push(n.trim()),t.map(i)},o=e=>{if(e.length===0)return``;if(e.length===1&&typeof e[0]==`string`)return e[0];let t=``;for(let n of e)typeof n==`string`?t+=n:t+=`{{${n.name}}}`;return n(t)},s=e=>{if(e.length===1)return o(e[0]);let n={};return e.length===2?(n[1]=o(e[0]),n.fallback=o(e[1])):e.length===3?(n[0]=o(e[0]),n[1]=o(e[1]),n.fallback=o(e[2])):e.forEach((t,r)=>{r===e.length-1?n.fallback=o(t):n[r.toString()]=o(t)}),n.__intlayer_vue_i18n_var=`count`,t(n)},c={canHandle:e=>typeof e==`string`&&(e.includes(`{`)||e.includes(`|`)),transform:e=>{try{return s(a(e))}catch{return e}}},l={canHandle:e=>{if(typeof e==`string`||e&&typeof e==`object`&&(e.nodeType===r.Insertion||e.nodeType===r.Enumeration||e.nodeType===r.Gender||e.nodeType===`composite`))return!0;if(Array.isArray(e)){if(e.length===0)return!1;let t=!1,n=!1;for(let i of e)typeof i==`string`||(i&&typeof i==`object`&&(i.nodeType===r.Insertion||i.nodeType===r.Enumeration||i.nodeType===r.Gender||i.nodeType===`composite`)?t=!0:n=!0);return!(n||!t)}return!1},transform:(e,t,n)=>{if(typeof e==`string`)return e.replace(/\{\{([^}]+)\}\}/g,`{$1}`);if(e.nodeType===r.Insertion)return e.insertion.replace(/\{\{([^}]+)\}\}/g,`{$1}`);if(e.nodeType===r.Enumeration){let r=e.enumeration,i={};for(let[e,a]of Object.entries(r)){if(e===`__intlayer_vue_i18n_var`)continue;let r=n(a,t);i[e]=typeof r==`string`?r:JSON.stringify(r)}let a=Object.keys(i);if(a.includes(`0`)){let e=a.filter(e=>/^\d+$/.test(e)).map(Number),t=Math.max(...e),n=i.fallback||i.other,r=[];if(t<=1&&!a.includes(`2`))return`${i[0]||``} | ${i[1]||``} | ${n}`;let o=Math.max(1,t);for(let e=0;e<=o;e++){let t=e.toString();i[t]?r.push(i[t]):r.push(``)}return r.push(n),r.join(` | `).replace(/ \| {2}\| /g,` | | `)}return a.includes(`1`)&&(a.includes(`fallback`)||a.includes(`other`))?`${i[1]} | ${i.fallback||i.other}`:a.length===1&&(a.includes(`fallback`)||a.includes(`other`))?i.fallback||i.other:i.fallback||Object.values(i)[0]}if(e.nodeType===r.Gender){let r=e.gender,i={};for(let[e,a]of Object.entries(r)){let r=e;e===`fallback`&&(r=`other`),i[r]=n(a,t)}return i}return Array.isArray(e)||e.nodeType===`composite`&&Array.isArray(e.composite)?(Array.isArray(e)?e:e.composite).map(e=>n(e,t)).join(``):n(e,t)}},u=t=>e(t,{dictionaryKey:`vue-i18n`,keyPath:[],plugins:[{id:`vue-i18n`,...l}]}),d=t=>e(t,{dictionaryKey:`vue-i18n`,keyPath:[],plugins:[{id:`vue-i18n`,...c}]});export{u as intlayerToVueI18nFormatter,d as vueI18nToIntlayerFormatter};
|
|
2
2
|
//# sourceMappingURL=vue-i18n.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vue-i18n.mjs","names":["insert","enu"],"sources":["../../../src/messageFormat/vue-i18n.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/types/dictionary';;\nimport { NodeType } from '@intlayer/types/nodeType';\nimport { deepTransformNode } from '../interpreter';\nimport { enu, insert } from '../transpiler';\nimport type { JsonValue } from './ICU';\n\n// Types for our AST\ntype VueI18nNode =\n | string\n | {\n type: 'argument';\n name: string;\n };\n\nconst parseVueI18nPart = (text: string): VueI18nNode[] => {\n let index = 0;\n const nodes: VueI18nNode[] = [];\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 let name = '';\n while (index < text.length && text[index] !== '}') {\n name += text[index];\n index++;\n }\n if (index < text.length) {\n index++; // skip }\n }\n nodes.push({ type: 'argument', name: name.trim() });\n } else {\n currentText += char;\n index++;\n }\n }\n\n if (currentText) {\n nodes.push(currentText);\n }\n\n return nodes;\n};\n\nconst parseVueI18n = (text: string): VueI18nNode[][] => {\n // Split by | but handle escaped \\|\n const parts: string[] = [];\n let currentPart = '';\n let index = 0;\n\n while (index < text.length) {\n const char = text[index];\n if (char === '\\\\' && index + 1 < text.length && text[index + 1] === '|') {\n currentPart += '|';\n index += 2;\n } else if (char === '|') {\n parts.push(currentPart.trim()); // Trim to remove surrounding spaces\n currentPart = '';\n index++;\n } else {\n currentPart += char;\n index++;\n }\n }\n parts.push(currentPart.trim()); // Trim last part too\n\n return parts.map(parseVueI18nPart);\n};\n\nconst vueI18nPartToIntlayer = (nodes: VueI18nNode[]): any => {\n if (nodes.length === 0) return '';\n if (nodes.length === 1 && typeof nodes[0] === 'string') return nodes[0];\n\n let str = '';\n for (const node of nodes) {\n if (typeof node === 'string') {\n str += node;\n } else {\n str += `{{${node.name}}}`;\n }\n }\n return insert(str);\n};\n\nconst vueI18nNodesToIntlayer = (parts: VueI18nNode[][]): any => {\n if (parts.length === 1) {\n return vueI18nPartToIntlayer(parts[0]);\n }\n\n // Handle pluralization (choice)\n const options: Record<string, any> = {};\n const varName = 'count'; // Default variable for vue-i18n choices\n\n if (parts.length === 2) {\n // 2 choices: 1 | other\n options['1'] = vueI18nPartToIntlayer(parts[0]);\n options.fallback = vueI18nPartToIntlayer(parts[1]);\n } else if (parts.length === 3) {\n // 3 choices: 0 | 1 | other\n options['0'] = vueI18nPartToIntlayer(parts[0]);\n options['1'] = vueI18nPartToIntlayer(parts[1]);\n options.fallback = vueI18nPartToIntlayer(parts[2]);\n } else {\n // > 3 choices: 0 | 1 | 2 | ... | other\n parts.forEach((part, index) => {\n if (index === parts.length - 1) {\n options.fallback = vueI18nPartToIntlayer(part);\n } else {\n options[index.toString()] = vueI18nPartToIntlayer(part);\n }\n });\n }\n\n // Preserve variable name\n options.__intlayer_vue_i18n_var = varName;\n\n return enu(options);\n};\n\nconst vueI18nToIntlayerPlugin = {\n canHandle: (node: any) =>\n typeof node === 'string' && (node.includes('{') || node.includes('|')),\n transform: (node: any) => {\n try {\n const ast = parseVueI18n(node);\n return vueI18nNodesToIntlayer(ast);\n } catch {\n return node;\n }\n },\n};\n\nconst intlayerToVueI18nPlugin = {\n canHandle: (node: any) =>\n typeof node === 'string' ||\n (node &&\n typeof node === 'object' &&\n (node.nodeType === NodeType.Insertion ||\n node.nodeType === NodeType.Enumeration ||\n node.nodeType === NodeType.Gender ||\n node.nodeType === 'composite')) ||\n Array.isArray(node),\n transform: (node: any, props: any, next: any) => {\n if (typeof node === 'string') {\n // replace {{...}} with {...} even in strings\n return node.replace(/\\{\\{([^}]+)\\}\\}/g, '{$1}');\n }\n\n if (node.nodeType === NodeType.Insertion) {\n // {{name}} -> {name}\n return node.insertion.replace(/\\{\\{([^}]+)\\}\\}/g, '{$1}');\n }\n\n if (node.nodeType === NodeType.Enumeration) {\n const options = node.enumeration;\n\n const transformedOptions: Record<string, string> = {};\n for (const [key, val] of Object.entries(options)) {\n if (key === '__intlayer_vue_i18n_var') continue;\n const childVal = next(val, props);\n transformedOptions[key] =\n typeof childVal === 'string' ? childVal : JSON.stringify(childVal);\n }\n\n // We need to reconstruct the pipe-separated string.\n // 2 parts: 1, fallback\n // 3 parts: 0, 1, fallback\n\n const keys = Object.keys(transformedOptions);\n\n // Heuristic to decide format\n // Use loose condition for 3 parts: if 0 exists, OR if 2 exists, etc.\n // But typically 0, 1, 2...\n // If '0' is present, we likely want the 3+ parts format.\n if (keys.includes('0')) {\n const indices = keys.filter((key) => /^\\d+$/.test(key)).map(Number);\n const maxIndex = Math.max(...indices);\n\n const fallback =\n transformedOptions.fallback || transformedOptions.other;\n const resultParts = [];\n\n // Check if we can use simple 3-part: 0 | 1 | fallback\n // Only if maxIndex <= 1\n if (maxIndex <= 1 && !keys.includes('2')) {\n const zero = transformedOptions['0'] || '';\n const one = transformedOptions['1'] || ''; // Gap handling?\n return `${zero} | ${one} | ${fallback}`;\n }\n\n // General case: loop until maxIndex\n const limit = Math.max(1, maxIndex);\n\n for (let i = 0; i <= limit; i++) {\n const key = i.toString();\n if (transformedOptions[key]) {\n resultParts.push(transformedOptions[key]);\n } else {\n resultParts.push(''); // Empty string for gaps\n }\n }\n resultParts.push(fallback);\n return resultParts.join(' | ').replace(/ \\| {2}\\| /g, ' | | ');\n }\n\n // 2 parts: 1 | fallback\n if (\n keys.includes('1') &&\n (keys.includes('fallback') || keys.includes('other'))\n ) {\n return `${transformedOptions['1']} | ${transformedOptions.fallback || transformedOptions.other}`;\n }\n\n // Fallback for only fallback?\n if (\n keys.length === 1 &&\n (keys.includes('fallback') || keys.includes('other'))\n ) {\n return transformedOptions.fallback || transformedOptions.other;\n }\n\n // Default fallback\n return (\n transformedOptions.fallback || Object.values(transformedOptions)[0]\n );\n }\n\n // Gender not supported by vue-i18n string format, return object\n if (node.nodeType === NodeType.Gender) {\n const options = node.gender;\n const transformedOptions: Record<string, any> = {};\n\n // Just map values\n for (const [key, val] of Object.entries(options)) {\n let newKey = key;\n if (key === 'fallback') newKey = 'other'; // vue-i18n doesn't strictly have 'other' for gender objects but standard convention often uses similar keys\n\n const childVal = next(val, props);\n transformedOptions[newKey] = childVal;\n }\n return transformedOptions;\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 intlayerToVueI18nFormatter = (\n message: Dictionary['content']\n): JsonValue => {\n return deepTransformNode(message, {\n dictionaryKey: 'vue-i18n',\n keyPath: [],\n plugins: [{ id: 'vue-i18n', ...intlayerToVueI18nPlugin }],\n });\n};\n\nexport const vueI18nToIntlayerFormatter = (\n message: JsonValue\n): Dictionary['content'] => {\n return deepTransformNode(message, {\n dictionaryKey: 'vue-i18n',\n keyPath: [],\n plugins: [{ id: 'vue-i18n', ...vueI18nToIntlayerPlugin }],\n });\n};\n"],"mappings":"mQAcA,MAAM,EAAoB,GAAgC,CACxD,IAAI,EAAQ,EACN,EAAuB,EAAE,CAC3B,EAAc,GAElB,KAAO,EAAQ,EAAK,QAAQ,CAC1B,IAAM,EAAO,EAAK,GAElB,GAAI,IAAS,IAAK,CAChB,AAEE,KADA,EAAM,KAAK,EAAY,CACT,IAEhB,IACA,IAAI,EAAO,GACX,KAAO,EAAQ,EAAK,QAAU,EAAK,KAAW,KAC5C,GAAQ,EAAK,GACb,IAEE,EAAQ,EAAK,QACf,IAEF,EAAM,KAAK,CAAE,KAAM,WAAY,KAAM,EAAK,MAAM,CAAE,CAAC,MAEnD,GAAe,EACf,IAQJ,OAJI,GACF,EAAM,KAAK,EAAY,CAGlB,GAGH,EAAgB,GAAkC,CAEtD,IAAM,EAAkB,EAAE,CACtB,EAAc,GACd,EAAQ,EAEZ,KAAO,EAAQ,EAAK,QAAQ,CAC1B,IAAM,EAAO,EAAK,GACd,IAAS,MAAQ,EAAQ,EAAI,EAAK,QAAU,EAAK,EAAQ,KAAO,KAClE,GAAe,IACf,GAAS,GACA,IAAS,KAClB,EAAM,KAAK,EAAY,MAAM,CAAC,CAC9B,EAAc,GACd,MAEA,GAAe,EACf,KAKJ,OAFA,EAAM,KAAK,EAAY,MAAM,CAAC,CAEvB,EAAM,IAAI,EAAiB,EAG9B,EAAyB,GAA8B,CAC3D,GAAI,EAAM,SAAW,EAAG,MAAO,GAC/B,GAAI,EAAM,SAAW,GAAK,OAAO,EAAM,IAAO,SAAU,OAAO,EAAM,GAErE,IAAI,EAAM,GACV,IAAK,IAAM,KAAQ,EACb,OAAO,GAAS,SAClB,GAAO,EAEP,GAAO,KAAK,EAAK,KAAK,IAG1B,OAAOA,EAAO,EAAI,EAGd,EAA0B,GAAgC,CAC9D,GAAI,EAAM,SAAW,EACnB,OAAO,EAAsB,EAAM,GAAG,CAIxC,IAAM,EAA+B,EAAE,CA0BvC,OAvBI,EAAM,SAAW,GAEnB,EAAQ,GAAO,EAAsB,EAAM,GAAG,CAC9C,EAAQ,SAAW,EAAsB,EAAM,GAAG,EACzC,EAAM,SAAW,GAE1B,EAAQ,GAAO,EAAsB,EAAM,GAAG,CAC9C,EAAQ,GAAO,EAAsB,EAAM,GAAG,CAC9C,EAAQ,SAAW,EAAsB,EAAM,GAAG,EAGlD,EAAM,SAAS,EAAM,IAAU,CACzB,IAAU,EAAM,OAAS,EAC3B,EAAQ,SAAW,EAAsB,EAAK,CAE9C,EAAQ,EAAM,UAAU,EAAI,EAAsB,EAAK,EAEzD,CAIJ,EAAQ,wBAA0B,QAE3BC,EAAI,EAAQ,EAGf,EAA0B,CAC9B,UAAY,GACV,OAAO,GAAS,WAAa,EAAK,SAAS,IAAI,EAAI,EAAK,SAAS,IAAI,EACvE,UAAY,GAAc,CACxB,GAAI,CAEF,OAAO,EADK,EAAa,EAAK,CACI,MAC5B,CACN,OAAO,IAGZ,CAEK,EAA0B,CAC9B,UAAY,GACV,OAAO,GAAS,UACf,GACC,OAAO,GAAS,WACf,EAAK,WAAa,EAAS,WAC1B,EAAK,WAAa,EAAS,aAC3B,EAAK,WAAa,EAAS,QAC3B,EAAK,WAAa,cACtB,MAAM,QAAQ,EAAK,CACrB,WAAY,EAAW,EAAY,IAAc,CAC/C,GAAI,OAAO,GAAS,SAElB,OAAO,EAAK,QAAQ,mBAAoB,OAAO,CAGjD,GAAI,EAAK,WAAa,EAAS,UAE7B,OAAO,EAAK,UAAU,QAAQ,mBAAoB,OAAO,CAG3D,GAAI,EAAK,WAAa,EAAS,YAAa,CAC1C,IAAM,EAAU,EAAK,YAEf,EAA6C,EAAE,CACrD,IAAK,GAAM,CAAC,EAAK,KAAQ,OAAO,QAAQ,EAAQ,CAAE,CAChD,GAAI,IAAQ,0BAA2B,SACvC,IAAM,EAAW,EAAK,EAAK,EAAM,CACjC,EAAmB,GACjB,OAAO,GAAa,SAAW,EAAW,KAAK,UAAU,EAAS,CAOtE,IAAM,EAAO,OAAO,KAAK,EAAmB,CAM5C,GAAI,EAAK,SAAS,IAAI,CAAE,CACtB,IAAM,EAAU,EAAK,OAAQ,GAAQ,QAAQ,KAAK,EAAI,CAAC,CAAC,IAAI,OAAO,CAC7D,EAAW,KAAK,IAAI,GAAG,EAAQ,CAE/B,EACJ,EAAmB,UAAY,EAAmB,MAC9C,EAAc,EAAE,CAItB,GAAI,GAAY,GAAK,CAAC,EAAK,SAAS,IAAI,CAGtC,MAAO,GAFM,EAAmB,IAAQ,GAEzB,KADH,EAAmB,IAAQ,GACf,KAAK,IAI/B,IAAM,EAAQ,KAAK,IAAI,EAAG,EAAS,CAEnC,IAAK,IAAI,EAAI,EAAG,GAAK,EAAO,IAAK,CAC/B,IAAM,EAAM,EAAE,UAAU,CACpB,EAAmB,GACrB,EAAY,KAAK,EAAmB,GAAK,CAEzC,EAAY,KAAK,GAAG,CAIxB,OADA,EAAY,KAAK,EAAS,CACnB,EAAY,KAAK,MAAM,CAAC,QAAQ,cAAe,QAAQ,CAoBhE,OAfE,EAAK,SAAS,IAAI,GACjB,EAAK,SAAS,WAAW,EAAI,EAAK,SAAS,QAAQ,EAE7C,GAAG,EAAmB,GAAK,KAAK,EAAmB,UAAY,EAAmB,QAKzF,EAAK,SAAW,IACf,EAAK,SAAS,WAAW,EAAI,EAAK,SAAS,QAAQ,EAE7C,EAAmB,UAAY,EAAmB,MAKzD,EAAmB,UAAY,OAAO,OAAO,EAAmB,CAAC,GAKrE,GAAI,EAAK,WAAa,EAAS,OAAQ,CACrC,IAAM,EAAU,EAAK,OACf,EAA0C,EAAE,CAGlD,IAAK,GAAM,CAAC,EAAK,KAAQ,OAAO,QAAQ,EAAQ,CAAE,CAChD,IAAI,EAAS,EACT,IAAQ,aAAY,EAAS,SAGjC,EAAmB,GADF,EAAK,EAAK,EAAM,CAGnC,OAAO,EAYT,OARE,MAAM,QAAQ,EAAK,EAClB,EAAK,WAAa,aAAe,MAAM,QAAQ,EAAK,UAAU,EAEnD,MAAM,QAAQ,EAAK,CAAG,EAAO,EAAK,WAC5B,IAAK,GAAc,EAAK,EAAM,EAAM,CAAC,CAC1C,KAAK,GAAG,CAGhB,EAAK,EAAM,EAAM,EAE3B,CAEY,EACX,GAEO,EAAkB,EAAS,CAChC,cAAe,WACf,QAAS,EAAE,CACX,QAAS,CAAC,CAAE,GAAI,WAAY,GAAG,EAAyB,CAAC,CAC1D,CAAC,CAGS,EACX,GAEO,EAAkB,EAAS,CAChC,cAAe,WACf,QAAS,EAAE,CACX,QAAS,CAAC,CAAE,GAAI,WAAY,GAAG,EAAyB,CAAC,CAC1D,CAAC"}
|
|
1
|
+
{"version":3,"file":"vue-i18n.mjs","names":["insert","enu"],"sources":["../../../src/messageFormat/vue-i18n.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/types/dictionary';\n\nimport { NodeType } from '@intlayer/types/nodeType';\nimport { deepTransformNode } from '../interpreter';\nimport { enu, insert } from '../transpiler';\nimport type { JsonValue } from './ICU';\n\n// Types for our AST\ntype VueI18nNode =\n | string\n | {\n type: 'argument';\n name: string;\n };\n\nconst parseVueI18nPart = (text: string): VueI18nNode[] => {\n let index = 0;\n const nodes: VueI18nNode[] = [];\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 let name = '';\n while (index < text.length && text[index] !== '}') {\n name += text[index];\n index++;\n }\n if (index < text.length) {\n index++; // skip }\n }\n nodes.push({ type: 'argument', name: name.trim() });\n } else {\n currentText += char;\n index++;\n }\n }\n\n if (currentText) {\n nodes.push(currentText);\n }\n\n return nodes;\n};\n\nconst parseVueI18n = (text: string): VueI18nNode[][] => {\n // Split by | but handle escaped \\|\n const parts: string[] = [];\n let currentPart = '';\n let index = 0;\n\n while (index < text.length) {\n const char = text[index];\n if (char === '\\\\' && index + 1 < text.length && text[index + 1] === '|') {\n currentPart += '|';\n index += 2;\n } else if (char === '|') {\n parts.push(currentPart.trim()); // Trim to remove surrounding spaces\n currentPart = '';\n index++;\n } else {\n currentPart += char;\n index++;\n }\n }\n parts.push(currentPart.trim()); // Trim last part too\n\n return parts.map(parseVueI18nPart);\n};\n\nconst vueI18nPartToIntlayer = (nodes: VueI18nNode[]): any => {\n if (nodes.length === 0) return '';\n if (nodes.length === 1 && typeof nodes[0] === 'string') return nodes[0];\n\n let str = '';\n for (const node of nodes) {\n if (typeof node === 'string') {\n str += node;\n } else {\n str += `{{${node.name}}}`;\n }\n }\n return insert(str);\n};\n\nconst vueI18nNodesToIntlayer = (parts: VueI18nNode[][]): any => {\n if (parts.length === 1) {\n return vueI18nPartToIntlayer(parts[0]);\n }\n\n // Handle pluralization (choice)\n const options: Record<string, any> = {};\n const varName = 'count'; // Default variable for vue-i18n choices\n\n if (parts.length === 2) {\n // 2 choices: 1 | other\n options['1'] = vueI18nPartToIntlayer(parts[0]);\n options.fallback = vueI18nPartToIntlayer(parts[1]);\n } else if (parts.length === 3) {\n // 3 choices: 0 | 1 | other\n options['0'] = vueI18nPartToIntlayer(parts[0]);\n options['1'] = vueI18nPartToIntlayer(parts[1]);\n options.fallback = vueI18nPartToIntlayer(parts[2]);\n } else {\n // > 3 choices: 0 | 1 | 2 | ... | other\n parts.forEach((part, index) => {\n if (index === parts.length - 1) {\n options.fallback = vueI18nPartToIntlayer(part);\n } else {\n options[index.toString()] = vueI18nPartToIntlayer(part);\n }\n });\n }\n\n // Preserve variable name\n options.__intlayer_vue_i18n_var = varName;\n\n return enu(options);\n};\n\nconst vueI18nToIntlayerPlugin = {\n canHandle: (node: any) =>\n typeof node === 'string' && (node.includes('{') || node.includes('|')),\n transform: (node: any) => {\n try {\n const ast = parseVueI18n(node);\n return vueI18nNodesToIntlayer(ast);\n } catch {\n return node;\n }\n },\n};\n\nconst intlayerToVueI18nPlugin = {\n canHandle: (node: any) => {\n if (typeof node === 'string') return true;\n\n if (\n node &&\n typeof node === 'object' &&\n (node.nodeType === NodeType.Insertion ||\n node.nodeType === NodeType.Enumeration ||\n node.nodeType === NodeType.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 === NodeType.Insertion ||\n item.nodeType === NodeType.Enumeration ||\n item.nodeType === NodeType.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 // replace {{...}} with {...} even in strings\n return node.replace(/\\{\\{([^}]+)\\}\\}/g, '{$1}');\n }\n\n if (node.nodeType === NodeType.Insertion) {\n // {{name}} -> {name}\n return node.insertion.replace(/\\{\\{([^}]+)\\}\\}/g, '{$1}');\n }\n\n if (node.nodeType === NodeType.Enumeration) {\n const options = node.enumeration;\n\n const transformedOptions: Record<string, string> = {};\n for (const [key, val] of Object.entries(options)) {\n if (key === '__intlayer_vue_i18n_var') continue;\n const childVal = next(val, props);\n transformedOptions[key] =\n typeof childVal === 'string' ? childVal : JSON.stringify(childVal);\n }\n\n const keys = Object.keys(transformedOptions);\n\n if (keys.includes('0')) {\n const indices = keys.filter((key) => /^\\d+$/.test(key)).map(Number);\n const maxIndex = Math.max(...indices);\n\n const fallback =\n transformedOptions.fallback || transformedOptions.other;\n const resultParts = [];\n\n if (maxIndex <= 1 && !keys.includes('2')) {\n const zero = transformedOptions['0'] || '';\n const one = transformedOptions['1'] || '';\n return `${zero} | ${one} | ${fallback}`;\n }\n\n const limit = Math.max(1, maxIndex);\n\n for (let i = 0; i <= limit; i++) {\n const key = i.toString();\n if (transformedOptions[key]) {\n resultParts.push(transformedOptions[key]);\n } else {\n resultParts.push('');\n }\n }\n resultParts.push(fallback);\n return resultParts.join(' | ').replace(/ \\| {2}\\| /g, ' | | ');\n }\n\n if (\n keys.includes('1') &&\n (keys.includes('fallback') || keys.includes('other'))\n ) {\n return `${transformedOptions['1']} | ${transformedOptions.fallback || transformedOptions.other}`;\n }\n\n if (\n keys.length === 1 &&\n (keys.includes('fallback') || keys.includes('other'))\n ) {\n return transformedOptions.fallback || transformedOptions.other;\n }\n\n return (\n transformedOptions.fallback || Object.values(transformedOptions)[0]\n );\n }\n\n if (node.nodeType === NodeType.Gender) {\n const options = node.gender;\n const transformedOptions: Record<string, any> = {};\n\n for (const [key, val] of Object.entries(options)) {\n let newKey = key;\n if (key === 'fallback') newKey = 'other';\n\n const childVal = next(val, props);\n transformedOptions[newKey] = childVal;\n }\n return transformedOptions;\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 intlayerToVueI18nFormatter = (\n message: Dictionary['content']\n): JsonValue => {\n return deepTransformNode(message, {\n dictionaryKey: 'vue-i18n',\n keyPath: [],\n plugins: [{ id: 'vue-i18n', ...intlayerToVueI18nPlugin }],\n });\n};\n\nexport const vueI18nToIntlayerFormatter = (\n message: JsonValue\n): Dictionary['content'] => {\n return deepTransformNode(message, {\n dictionaryKey: 'vue-i18n',\n keyPath: [],\n plugins: [{ id: 'vue-i18n', ...vueI18nToIntlayerPlugin }],\n });\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ICU.d.ts","names":[],"sources":["../../../src/messageFormat/ICU.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"ICU.d.ts","names":[],"sources":["../../../src/messageFormat/ICU.ts"],"mappings":";;;KA8CY,SAAA,sCAKR,SAAA;EAAA,CACG,GAAA,WAAc,SAAA;AAAA;AAAA,cAyeR,sBAAA,GACX,OAAA,EAAS,UAAA,gBACR,SAAA;AAAA,cAQU,sBAAA,GACX,OAAA,EAAS,UAAA,gBACR,SAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"i18next.d.ts","names":[],"sources":["../../../src/messageFormat/i18next.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"i18next.d.ts","names":[],"sources":["../../../src/messageFormat/i18next.ts"],"mappings":";;;;cAqfa,0BAAA,GACX,OAAA,EAAS,UAAA,gBACR,SAAA;AAAA,cAQU,0BAAA,GACX,OAAA,EAAS,SAAA,KACR,UAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vue-i18n.d.ts","names":[],"sources":["../../../src/messageFormat/vue-i18n.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"vue-i18n.d.ts","names":[],"sources":["../../../src/messageFormat/vue-i18n.ts"],"mappings":";;;;cA4Ra,0BAAA,GACX,OAAA,EAAS,UAAA,gBACR,SAAA;AAAA,cAQU,0BAAA,GACX,OAAA,EAAS,SAAA,KACR,UAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intlayer/core",
|
|
3
|
-
"version": "8.3.0-canary.
|
|
3
|
+
"version": "8.3.0-canary.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Includes core Intlayer functions like translation, dictionary, and utility functions shared across multiple packages.",
|
|
6
6
|
"keywords": [
|
|
@@ -168,20 +168,20 @@
|
|
|
168
168
|
"typecheck": "tsc --noEmit --project tsconfig.types.json"
|
|
169
169
|
},
|
|
170
170
|
"dependencies": {
|
|
171
|
-
"@intlayer/api": "8.3.0-canary.
|
|
172
|
-
"@intlayer/config": "8.3.0-canary.
|
|
173
|
-
"@intlayer/dictionaries-entry": "8.3.0-canary.
|
|
174
|
-
"@intlayer/types": "8.3.0-canary.
|
|
175
|
-
"@intlayer/unmerged-dictionaries-entry": "8.3.0-canary.
|
|
171
|
+
"@intlayer/api": "8.3.0-canary.2",
|
|
172
|
+
"@intlayer/config": "8.3.0-canary.2",
|
|
173
|
+
"@intlayer/dictionaries-entry": "8.3.0-canary.2",
|
|
174
|
+
"@intlayer/types": "8.3.0-canary.2",
|
|
175
|
+
"@intlayer/unmerged-dictionaries-entry": "8.3.0-canary.2",
|
|
176
176
|
"defu": "6.1.4"
|
|
177
177
|
},
|
|
178
178
|
"devDependencies": {
|
|
179
|
-
"@types/node": "25.
|
|
179
|
+
"@types/node": "25.4.0",
|
|
180
180
|
"@utils/ts-config": "1.0.4",
|
|
181
181
|
"@utils/ts-config-types": "1.0.4",
|
|
182
182
|
"@utils/tsdown-config": "1.0.4",
|
|
183
183
|
"rimraf": "6.1.3",
|
|
184
|
-
"tsdown": "0.21.
|
|
184
|
+
"tsdown": "0.21.2",
|
|
185
185
|
"typescript": "5.9.3",
|
|
186
186
|
"vitest": "4.0.18"
|
|
187
187
|
},
|