@intlayer/cli 6.1.6 → 7.0.0-canary.1
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/IntlayerEventListener.cjs +187 -239
- package/dist/cjs/IntlayerEventListener.cjs.map +1 -1
- package/dist/cjs/_virtual/_utils_asset.cjs +104 -0
- package/dist/cjs/_virtual/rolldown_runtime.cjs +25 -0
- package/dist/cjs/build.cjs +23 -42
- package/dist/cjs/build.cjs.map +1 -1
- package/dist/cjs/cli.cjs +370 -431
- package/dist/cjs/cli.cjs.map +1 -1
- package/dist/cjs/config.cjs +10 -35
- package/dist/cjs/config.cjs.map +1 -1
- package/dist/cjs/editor.cjs +51 -66
- package/dist/cjs/editor.cjs.map +1 -1
- package/dist/cjs/fill/fill.cjs +73 -301
- package/dist/cjs/fill/fill.cjs.map +1 -1
- package/dist/cjs/fill/formatAutoFillData.cjs +48 -106
- package/dist/cjs/fill/formatAutoFillData.cjs.map +1 -1
- package/dist/cjs/fill/formatAutoFilledFilePath.cjs +27 -43
- package/dist/cjs/fill/formatAutoFilledFilePath.cjs.map +1 -1
- package/dist/cjs/fill/formatFillData.cjs +50 -0
- package/dist/cjs/fill/formatFillData.cjs.map +1 -0
- package/dist/cjs/fill/groupLimiter.cjs +42 -0
- package/dist/cjs/fill/groupLimiter.cjs.map +1 -0
- package/dist/cjs/fill/index.cjs +5 -25
- package/dist/cjs/fill/listTranslationsTasks.cjs +77 -0
- package/dist/cjs/fill/listTranslationsTasks.cjs.map +1 -0
- package/dist/cjs/fill/test-original-case.cjs +10 -0
- package/dist/cjs/fill/test-original-case.cjs.map +1 -0
- package/dist/cjs/fill/translateDictionary.cjs +148 -0
- package/dist/cjs/fill/translateDictionary.cjs.map +1 -0
- package/dist/cjs/fill/writeAutoFill.cjs +48 -0
- package/dist/cjs/fill/writeAutoFill.cjs.map +1 -0
- package/dist/cjs/fill/writeFill.cjs +50 -0
- package/dist/cjs/fill/writeFill.cjs.map +1 -0
- package/dist/cjs/getTargetDictionary.cjs +36 -76
- package/dist/cjs/getTargetDictionary.cjs.map +1 -1
- package/dist/cjs/index.cjs +31 -45
- package/dist/cjs/listContentDeclaration.cjs +36 -64
- package/dist/cjs/listContentDeclaration.cjs.map +1 -1
- package/dist/cjs/liveSync.cjs +146 -221
- package/dist/cjs/liveSync.cjs.map +1 -1
- package/dist/cjs/pull.cjs +132 -195
- package/dist/cjs/pull.cjs.map +1 -1
- package/dist/cjs/push/pullLog.cjs +101 -144
- package/dist/cjs/push/pullLog.cjs.map +1 -1
- package/dist/cjs/push/push.cjs +159 -249
- package/dist/cjs/push/push.cjs.map +1 -1
- package/dist/cjs/pushConfig.cjs +18 -45
- package/dist/cjs/pushConfig.cjs.map +1 -1
- package/dist/cjs/pushLog.cjs +87 -128
- package/dist/cjs/pushLog.cjs.map +1 -1
- package/dist/cjs/reviewDoc.cjs +183 -291
- package/dist/cjs/reviewDoc.cjs.map +1 -1
- package/dist/cjs/test/index.cjs +52 -91
- package/dist/cjs/test/index.cjs.map +1 -1
- package/dist/cjs/test/listMissingTranslations.cjs +35 -62
- package/dist/cjs/test/listMissingTranslations.cjs.map +1 -1
- package/dist/cjs/translateDoc.cjs +127 -221
- package/dist/cjs/translateDoc.cjs.map +1 -1
- package/dist/cjs/utils/calculateChunks.cjs +85 -115
- package/dist/cjs/utils/calculateChunks.cjs.map +1 -1
- package/dist/cjs/utils/checkAccess.cjs +33 -72
- package/dist/cjs/utils/checkAccess.cjs.map +1 -1
- package/dist/cjs/utils/checkFileModifiedRange.cjs +75 -91
- package/dist/cjs/utils/checkFileModifiedRange.cjs.map +1 -1
- package/dist/cjs/utils/checkLastUpdateTime.cjs +17 -30
- package/dist/cjs/utils/checkLastUpdateTime.cjs.map +1 -1
- package/dist/cjs/utils/chunkInference.cjs +28 -47
- package/dist/cjs/utils/chunkInference.cjs.map +1 -1
- package/dist/cjs/utils/fixChunkStartEndChars.cjs +23 -42
- package/dist/cjs/utils/fixChunkStartEndChars.cjs.map +1 -1
- package/dist/cjs/utils/formatTimeDiff.cjs +17 -43
- package/dist/cjs/utils/formatTimeDiff.cjs.map +1 -1
- package/dist/cjs/utils/getIsFileUpdatedRecently.cjs +13 -32
- package/dist/cjs/utils/getIsFileUpdatedRecently.cjs.map +1 -1
- package/dist/cjs/utils/getOutputFilePath.cjs +71 -86
- package/dist/cjs/utils/getOutputFilePath.cjs.map +1 -1
- package/dist/cjs/utils/getParentPackageJSON.cjs +19 -44
- package/dist/cjs/utils/getParentPackageJSON.cjs.map +1 -1
- package/dist/cjs/utils/listSpecialChars.cjs +49 -73
- package/dist/cjs/utils/listSpecialChars.cjs.map +1 -1
- package/dist/cjs/utils/mapChunksBetweenFiles.cjs +90 -132
- package/dist/cjs/utils/mapChunksBetweenFiles.cjs.map +1 -1
- package/dist/cjs/utils/reorderParagraphs.cjs +86 -118
- package/dist/cjs/utils/reorderParagraphs.cjs.map +1 -1
- package/dist/cjs/watch.cjs +21 -39
- package/dist/cjs/watch.cjs.map +1 -1
- package/dist/esm/IntlayerEventListener.mjs +178 -201
- package/dist/esm/IntlayerEventListener.mjs.map +1 -1
- package/dist/esm/_virtual/_utils_asset.mjs +100 -0
- package/dist/esm/_virtual/rolldown_runtime.mjs +8 -0
- package/dist/esm/build.mjs +20 -23
- package/dist/esm/build.mjs.map +1 -1
- package/dist/esm/cli.mjs +349 -380
- package/dist/esm/cli.mjs.map +1 -1
- package/dist/esm/config.mjs +8 -14
- package/dist/esm/config.mjs.map +1 -1
- package/dist/esm/editor.mjs +47 -41
- package/dist/esm/editor.mjs.map +1 -1
- package/dist/esm/fill/fill.mjs +68 -300
- package/dist/esm/fill/fill.mjs.map +1 -1
- package/dist/esm/fill/formatAutoFillData.mjs +47 -81
- package/dist/esm/fill/formatAutoFillData.mjs.map +1 -1
- package/dist/esm/fill/formatAutoFilledFilePath.mjs +25 -19
- package/dist/esm/fill/formatAutoFilledFilePath.mjs.map +1 -1
- package/dist/esm/fill/formatFillData.mjs +50 -0
- package/dist/esm/fill/formatFillData.mjs.map +1 -0
- package/dist/esm/fill/groupLimiter.mjs +40 -0
- package/dist/esm/fill/groupLimiter.mjs.map +1 -0
- package/dist/esm/fill/index.mjs +4 -3
- package/dist/esm/fill/listTranslationsTasks.mjs +70 -0
- package/dist/esm/fill/listTranslationsTasks.mjs.map +1 -0
- package/dist/esm/fill/test-original-case.mjs +10 -0
- package/dist/esm/fill/test-original-case.mjs.map +1 -0
- package/dist/esm/fill/translateDictionary.mjs +141 -0
- package/dist/esm/fill/translateDictionary.mjs.map +1 -0
- package/dist/esm/fill/writeAutoFill.mjs +44 -0
- package/dist/esm/fill/writeAutoFill.mjs.map +1 -0
- package/dist/esm/fill/writeFill.mjs +45 -0
- package/dist/esm/fill/writeFill.mjs.map +1 -0
- package/dist/esm/getTargetDictionary.mjs +27 -48
- package/dist/esm/getTargetDictionary.mjs.map +1 -1
- package/dist/esm/index.mjs +15 -13
- package/dist/esm/listContentDeclaration.mjs +28 -43
- package/dist/esm/listContentDeclaration.mjs.map +1 -1
- package/dist/esm/liveSync.mjs +135 -187
- package/dist/esm/liveSync.mjs.map +1 -1
- package/dist/esm/pull.mjs +125 -178
- package/dist/esm/pull.mjs.map +1 -1
- package/dist/esm/push/pullLog.mjs +99 -125
- package/dist/esm/push/pullLog.mjs.map +1 -1
- package/dist/esm/push/push.mjs +149 -221
- package/dist/esm/push/push.mjs.map +1 -1
- package/dist/esm/pushConfig.mjs +14 -23
- package/dist/esm/pushConfig.mjs.map +1 -1
- package/dist/esm/pushLog.mjs +85 -109
- package/dist/esm/pushLog.mjs.map +1 -1
- package/dist/esm/reviewDoc.mjs +167 -264
- package/dist/esm/reviewDoc.mjs.map +1 -1
- package/dist/esm/test/index.mjs +47 -73
- package/dist/esm/test/index.mjs.map +1 -1
- package/dist/esm/test/listMissingTranslations.mjs +30 -41
- package/dist/esm/test/listMissingTranslations.mjs.map +1 -1
- package/dist/esm/translateDoc.mjs +114 -193
- package/dist/esm/translateDoc.mjs.map +1 -1
- package/dist/esm/utils/calculateChunks.mjs +83 -91
- package/dist/esm/utils/calculateChunks.mjs.map +1 -1
- package/dist/esm/utils/checkAccess.mjs +28 -46
- package/dist/esm/utils/checkAccess.mjs.map +1 -1
- package/dist/esm/utils/checkFileModifiedRange.mjs +73 -65
- package/dist/esm/utils/checkFileModifiedRange.mjs.map +1 -1
- package/dist/esm/utils/checkLastUpdateTime.mjs +15 -6
- package/dist/esm/utils/checkLastUpdateTime.mjs.map +1 -1
- package/dist/esm/utils/chunkInference.mjs +24 -24
- package/dist/esm/utils/chunkInference.mjs.map +1 -1
- package/dist/esm/utils/fixChunkStartEndChars.mjs +22 -18
- package/dist/esm/utils/fixChunkStartEndChars.mjs.map +1 -1
- package/dist/esm/utils/formatTimeDiff.mjs +16 -19
- package/dist/esm/utils/formatTimeDiff.mjs.map +1 -1
- package/dist/esm/utils/getIsFileUpdatedRecently.mjs +11 -8
- package/dist/esm/utils/getIsFileUpdatedRecently.mjs.map +1 -1
- package/dist/esm/utils/getOutputFilePath.mjs +70 -62
- package/dist/esm/utils/getOutputFilePath.mjs.map +1 -1
- package/dist/esm/utils/getParentPackageJSON.mjs +16 -20
- package/dist/esm/utils/getParentPackageJSON.mjs.map +1 -1
- package/dist/esm/utils/listSpecialChars.mjs +48 -49
- package/dist/esm/utils/listSpecialChars.mjs.map +1 -1
- package/dist/esm/utils/mapChunksBetweenFiles.mjs +87 -107
- package/dist/esm/utils/mapChunksBetweenFiles.mjs.map +1 -1
- package/dist/esm/utils/reorderParagraphs.mjs +85 -93
- package/dist/esm/utils/reorderParagraphs.mjs.map +1 -1
- package/dist/esm/watch.mjs +17 -17
- package/dist/esm/watch.mjs.map +1 -1
- package/dist/types/IntlayerEventListener.d.ts +63 -59
- package/dist/types/IntlayerEventListener.d.ts.map +1 -1
- package/dist/types/build.d.ts +10 -7
- package/dist/types/build.d.ts.map +1 -1
- package/dist/types/cli.d.ts +13 -10
- package/dist/types/cli.d.ts.map +1 -1
- package/dist/types/config.d.ts +7 -4
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/editor.d.ts +6 -4
- package/dist/types/editor.d.ts.map +1 -1
- package/dist/types/fill/fill.d.ts +20 -14
- package/dist/types/fill/fill.d.ts.map +1 -1
- package/dist/types/fill/formatAutoFillData.d.ts +10 -7
- package/dist/types/fill/formatAutoFillData.d.ts.map +1 -1
- package/dist/types/fill/formatAutoFilledFilePath.d.ts +6 -2
- package/dist/types/fill/formatAutoFilledFilePath.d.ts.map +1 -1
- package/dist/types/fill/formatFillData.d.ts +12 -0
- package/dist/types/fill/formatFillData.d.ts.map +1 -0
- package/dist/types/fill/groupLimiter.d.ts +15 -0
- package/dist/types/fill/groupLimiter.d.ts.map +1 -0
- package/dist/types/fill/index.d.ts +3 -3
- package/dist/types/fill/listTranslationsTasks.d.ts +15 -0
- package/dist/types/fill/listTranslationsTasks.d.ts.map +1 -0
- package/dist/types/fill/test-original-case.d.ts +1 -0
- package/dist/types/fill/translateDictionary.d.ts +19 -0
- package/dist/types/fill/translateDictionary.d.ts.map +1 -0
- package/dist/types/fill/writeAutoFill.d.ts +7 -0
- package/dist/types/fill/writeAutoFill.d.ts.map +1 -0
- package/dist/types/fill/writeFill.d.ts +7 -0
- package/dist/types/fill/writeFill.d.ts.map +1 -0
- package/dist/types/getTargetDictionary.d.ts +17 -13
- package/dist/types/getTargetDictionary.d.ts.map +1 -1
- package/dist/types/index.d.ts +15 -14
- package/dist/types/listContentDeclaration.d.ts +10 -7
- package/dist/types/listContentDeclaration.d.ts.map +1 -1
- package/dist/types/liveSync.d.ts +8 -3
- package/dist/types/liveSync.d.ts.map +1 -1
- package/dist/types/pull.d.ts +9 -6
- package/dist/types/pull.d.ts.map +1 -1
- package/dist/types/push/pullLog.d.ts +25 -21
- package/dist/types/push/pullLog.d.ts.map +1 -1
- package/dist/types/push/push.d.ts +13 -9
- package/dist/types/push/push.d.ts.map +1 -1
- package/dist/types/pushConfig.d.ts +7 -4
- package/dist/types/pushConfig.d.ts.map +1 -1
- package/dist/types/pushLog.d.ts +23 -20
- package/dist/types/pushLog.d.ts.map +1 -1
- package/dist/types/reviewDoc.d.ts +34 -17
- package/dist/types/reviewDoc.d.ts.map +1 -1
- package/dist/types/test/index.d.ts +9 -5
- package/dist/types/test/index.d.ts.map +1 -1
- package/dist/types/test/listMissingTranslations.d.ts +14 -10
- package/dist/types/test/listMissingTranslations.d.ts.map +1 -1
- package/dist/types/translateDoc.d.ts +34 -17
- package/dist/types/translateDoc.d.ts.map +1 -1
- package/dist/types/utils/calculateChunks.d.ts +10 -7
- package/dist/types/utils/calculateChunks.d.ts.map +1 -1
- package/dist/types/utils/checkAccess.d.ts +8 -4
- package/dist/types/utils/checkAccess.d.ts.map +1 -1
- package/dist/types/utils/checkFileModifiedRange.d.ts +8 -6
- package/dist/types/utils/checkFileModifiedRange.d.ts.map +1 -1
- package/dist/types/utils/checkLastUpdateTime.d.ts +4 -1
- package/dist/types/utils/checkLastUpdateTime.d.ts.map +1 -1
- package/dist/types/utils/chunkInference.d.ts +9 -6
- package/dist/types/utils/chunkInference.d.ts.map +1 -1
- package/dist/types/utils/fixChunkStartEndChars.d.ts +4 -1
- package/dist/types/utils/fixChunkStartEndChars.d.ts.map +1 -1
- package/dist/types/utils/formatTimeDiff.d.ts +4 -1
- package/dist/types/utils/formatTimeDiff.d.ts.map +1 -1
- package/dist/types/utils/getIsFileUpdatedRecently.d.ts +4 -1
- package/dist/types/utils/getIsFileUpdatedRecently.d.ts.map +1 -1
- package/dist/types/utils/getOutputFilePath.d.ts +7 -2
- package/dist/types/utils/getOutputFilePath.d.ts.map +1 -1
- package/dist/types/utils/getParentPackageJSON.d.ts +30 -28
- package/dist/types/utils/getParentPackageJSON.d.ts.map +1 -1
- package/dist/types/utils/listSpecialChars.d.ts +9 -7
- package/dist/types/utils/listSpecialChars.d.ts.map +1 -1
- package/dist/types/utils/mapChunksBetweenFiles.d.ts +10 -6
- package/dist/types/utils/mapChunksBetweenFiles.d.ts.map +1 -1
- package/dist/types/utils/reorderParagraphs.d.ts +4 -1
- package/dist/types/utils/reorderParagraphs.d.ts.map +1 -1
- package/dist/types/watch.d.ts +9 -6
- package/dist/types/watch.d.ts.map +1 -1
- package/package.json +42 -47
- package/LICENSE +0 -202
- package/dist/cjs/fill/autoFill.cjs +0 -105
- package/dist/cjs/fill/autoFill.cjs.map +0 -1
- package/dist/cjs/fill/index.cjs.map +0 -1
- package/dist/cjs/index.cjs.map +0 -1
- package/dist/cjs/utils/getChunk.cjs +0 -77
- package/dist/cjs/utils/getChunk.cjs.map +0 -1
- package/dist/cjs/utils/splitTextByLine.cjs +0 -35
- package/dist/cjs/utils/splitTextByLine.cjs.map +0 -1
- package/dist/esm/fill/autoFill.mjs +0 -92
- package/dist/esm/fill/autoFill.mjs.map +0 -1
- package/dist/esm/fill/index.mjs.map +0 -1
- package/dist/esm/index.mjs.map +0 -1
- package/dist/esm/prompts/REVIEW_PROMPT.md +0 -37
- package/dist/esm/prompts/TRANSLATE_PROMPT.md +0 -38
- package/dist/esm/utils/calculrateChunkTest.md +0 -9
- package/dist/esm/utils/getChunk.mjs +0 -53
- package/dist/esm/utils/getChunk.mjs.map +0 -1
- package/dist/esm/utils/splitTextByLine.mjs +0 -11
- package/dist/esm/utils/splitTextByLine.mjs.map +0 -1
- package/dist/types/fill/autoFill.d.ts +0 -4
- package/dist/types/fill/autoFill.d.ts.map +0 -1
- package/dist/types/fill/index.d.ts.map +0 -1
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/utils/getChunk.d.ts +0 -9
- package/dist/types/utils/getChunk.d.ts.map +0 -1
- package/dist/types/utils/splitTextByLine.d.ts +0 -2
- package/dist/types/utils/splitTextByLine.d.ts.map +0 -1
- /package/dist/{cjs → assets}/prompts/REVIEW_PROMPT.md +0 -0
- /package/dist/{cjs → assets}/prompts/TRANSLATE_PROMPT.md +0 -0
- /package/dist/{cjs/utils/calculrateChunkTest.md → assets/utils/_calculateChunkTest.md} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/fill/formatAutoFilledFilePath.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"formatAutoFilledFilePath.mjs","names":["result: string"],"sources":["../../../src/fill/formatAutoFilledFilePath.ts"],"sourcesContent":["import {\n basename,\n dirname,\n isAbsolute,\n normalize,\n relative,\n resolve,\n} from 'node:path';\nimport type { LocalesValues } from '@intlayer/types';\n\nexport const formatAutoFilledFilePath = (\n autoFillField: string,\n dictionaryKey: string,\n dictionaryFilePath: string,\n baseDir: string,\n locale?: LocalesValues\n): string => {\n // Validate inputs\n if (!autoFillField || typeof autoFillField !== 'string') {\n throw new Error('autoFillField must be a non-empty string');\n }\n if (!dictionaryKey || typeof dictionaryKey !== 'string') {\n throw new Error('dictionaryKey must be a non-empty string');\n }\n if (!dictionaryFilePath || typeof dictionaryFilePath !== 'string') {\n throw new Error('dictionaryFilePath must be a non-empty string');\n }\n if (!baseDir || typeof baseDir !== 'string') {\n throw new Error('baseDir must be a non-empty string');\n }\n\n // Extract the original filename without extensions (.content.ts -> dictionaryFieldEditor)\n const originalFileName = basename(dictionaryFilePath)\n .split('.')\n .slice(0, -2) // Remove last 2 extensions (.content.tsx)\n .join('.');\n\n // Replace placeholders in autoFillField\n let result: string = autoFillField\n .replace(/\\{\\{key\\}\\}/g, originalFileName) // Use original filename, not dictionaryKey\n .replace(/\\{\\{fileName\\}\\}/g, originalFileName);\n\n if (locale) {\n result = result.replace(/\\{\\{locale\\}\\}/g, locale);\n }\n\n // Normalize the dictionary file path - if it's relative, make it absolute relative to baseDir\n const absoluteDictionaryPath = isAbsolute(dictionaryFilePath)\n ? dictionaryFilePath\n : resolve(baseDir, dictionaryFilePath);\n\n // Handle relative paths (starting with ./ or ../)\n if (result.startsWith('./') || result.startsWith('../')) {\n const fileDir = dirname(absoluteDictionaryPath);\n const resolvedPath = resolve(fileDir, result);\n\n return resolvedPath;\n }\n\n // Handle absolute paths\n if (isAbsolute(result)) {\n const normalizedResult = normalize(result);\n const normalizedBaseDir = normalize(baseDir);\n\n // Check if it's relative to baseDir (starts with /)\n // but not a system path (like /usr/local)\n if (\n result.startsWith('/') &&\n !normalizedResult.startsWith(normalizedBaseDir)\n ) {\n // Try to resolve it relative to baseDir first\n const relativeToBase = resolve(baseDir, result.substring(1));\n\n // If the path doesn't exist in common system directories, treat as relative to baseDir\n if (\n !result.startsWith('/usr/') &&\n !result.startsWith('/etc/') &&\n !result.startsWith('/var/') &&\n !result.startsWith('/home/') &&\n !result.startsWith('/Users/')\n ) {\n return relativeToBase;\n }\n }\n\n // It's a true system absolute path\n return normalizedResult;\n }\n\n // Default case: treat as relative to baseDir\n return normalize(result);\n};\n"],"mappings":";;;AAUA,MAAa,4BACX,eACA,eACA,oBACA,SACA,WACW;AAEX,KAAI,CAAC,iBAAiB,OAAO,kBAAkB,SAC7C,OAAM,IAAI,MAAM,2CAA2C;AAE7D,KAAI,CAAC,iBAAiB,OAAO,kBAAkB,SAC7C,OAAM,IAAI,MAAM,2CAA2C;AAE7D,KAAI,CAAC,sBAAsB,OAAO,uBAAuB,SACvD,OAAM,IAAI,MAAM,gDAAgD;AAElE,KAAI,CAAC,WAAW,OAAO,YAAY,SACjC,OAAM,IAAI,MAAM,qCAAqC;CAIvD,MAAM,mBAAmB,SAAS,mBAAmB,CAClD,MAAM,IAAI,CACV,MAAM,GAAG,GAAG,CACZ,KAAK,IAAI;CAGZ,IAAIA,SAAiB,cAClB,QAAQ,gBAAgB,iBAAiB,CACzC,QAAQ,qBAAqB,iBAAiB;AAEjD,KAAI,OACF,UAAS,OAAO,QAAQ,mBAAmB,OAAO;CAIpD,MAAM,yBAAyB,WAAW,mBAAmB,GACzD,qBACA,QAAQ,SAAS,mBAAmB;AAGxC,KAAI,OAAO,WAAW,KAAK,IAAI,OAAO,WAAW,MAAM,CAIrD,QAFqB,QADL,QAAQ,uBAAuB,EACT,OAAO;AAM/C,KAAI,WAAW,OAAO,EAAE;EACtB,MAAM,mBAAmB,UAAU,OAAO;EAC1C,MAAM,oBAAoB,UAAU,QAAQ;AAI5C,MACE,OAAO,WAAW,IAAI,IACtB,CAAC,iBAAiB,WAAW,kBAAkB,EAC/C;GAEA,MAAM,iBAAiB,QAAQ,SAAS,OAAO,UAAU,EAAE,CAAC;AAG5D,OACE,CAAC,OAAO,WAAW,QAAQ,IAC3B,CAAC,OAAO,WAAW,QAAQ,IAC3B,CAAC,OAAO,WAAW,QAAQ,IAC3B,CAAC,OAAO,WAAW,SAAS,IAC5B,CAAC,OAAO,WAAW,UAAU,CAE7B,QAAO;;AAKX,SAAO;;AAIT,QAAO,UAAU,OAAO"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { formatAutoFilledFilePath } from "./formatAutoFilledFilePath.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/fill/formatFillData.ts
|
|
4
|
+
const formatFillData = (autoFillField, localeList, filePath, dictionaryKey, configuration) => {
|
|
5
|
+
const outputContentDeclarationFile = [];
|
|
6
|
+
const baseDir = configuration.content.baseDir;
|
|
7
|
+
if (!autoFillField) return outputContentDeclarationFile;
|
|
8
|
+
if (typeof autoFillField === "string") {
|
|
9
|
+
if (autoFillField.includes("{{locale}}")) {
|
|
10
|
+
const output = localeList.map((locale) => {
|
|
11
|
+
const formattedFilePath = formatAutoFilledFilePath(autoFillField, dictionaryKey, filePath, baseDir, locale);
|
|
12
|
+
return {
|
|
13
|
+
localeList: [locale],
|
|
14
|
+
filePath: formattedFilePath,
|
|
15
|
+
isPerLocale: true
|
|
16
|
+
};
|
|
17
|
+
});
|
|
18
|
+
outputContentDeclarationFile.push(...output);
|
|
19
|
+
} else {
|
|
20
|
+
const formattedFilePath = formatAutoFilledFilePath(autoFillField, dictionaryKey, filePath, baseDir);
|
|
21
|
+
outputContentDeclarationFile.push({
|
|
22
|
+
localeList,
|
|
23
|
+
filePath: formattedFilePath,
|
|
24
|
+
isPerLocale: false
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
return outputContentDeclarationFile;
|
|
28
|
+
}
|
|
29
|
+
if (typeof autoFillField === "object") {
|
|
30
|
+
const groupedByFilePath = Object.keys(autoFillField).filter((locale) => typeof autoFillField[locale] === "string").filter((locale) => Boolean(autoFillField[locale])).map((locale) => {
|
|
31
|
+
const formattedFilePath = formatAutoFilledFilePath(autoFillField[locale], dictionaryKey, filePath, baseDir, locale);
|
|
32
|
+
return {
|
|
33
|
+
localeList: [locale],
|
|
34
|
+
filePath: formattedFilePath,
|
|
35
|
+
isPerLocale: true
|
|
36
|
+
};
|
|
37
|
+
}).reduce((acc, curr) => {
|
|
38
|
+
const existing = acc.find((item) => item.filePath === curr.filePath);
|
|
39
|
+
if (existing) existing.localeList.push(...curr.localeList);
|
|
40
|
+
else acc.push(curr);
|
|
41
|
+
return acc;
|
|
42
|
+
}, []);
|
|
43
|
+
outputContentDeclarationFile.push(...groupedByFilePath);
|
|
44
|
+
}
|
|
45
|
+
return outputContentDeclarationFile;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
//#endregion
|
|
49
|
+
export { formatFillData };
|
|
50
|
+
//# sourceMappingURL=formatFillData.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatFillData.mjs","names":["outputContentDeclarationFile: FillData[]"],"sources":["../../../src/fill/formatFillData.ts"],"sourcesContent":["import type { Fill, IntlayerConfig, LocalesValues } from '@intlayer/types';\nimport { formatAutoFilledFilePath } from './formatAutoFilledFilePath';\n\nexport type FillData = {\n localeList: LocalesValues[];\n filePath: string;\n isPerLocale: boolean;\n};\n\nexport const formatFillData = (\n autoFillField: Fill,\n localeList: LocalesValues[],\n filePath: string,\n dictionaryKey: string,\n configuration: IntlayerConfig\n): FillData[] => {\n const outputContentDeclarationFile: FillData[] = [];\n\n const baseDir = configuration.content.baseDir;\n\n if (!autoFillField) return outputContentDeclarationFile;\n\n if (typeof autoFillField === 'string') {\n if (autoFillField.includes('{{locale}}')) {\n const output = localeList.map((locale) => {\n const formattedFilePath = formatAutoFilledFilePath(\n autoFillField,\n dictionaryKey,\n filePath,\n baseDir,\n locale\n );\n\n return {\n localeList: [locale],\n filePath: formattedFilePath,\n isPerLocale: true,\n };\n });\n\n outputContentDeclarationFile.push(...output);\n } else {\n const formattedFilePath = formatAutoFilledFilePath(\n autoFillField,\n dictionaryKey,\n filePath,\n baseDir\n );\n\n outputContentDeclarationFile.push({\n localeList,\n filePath: formattedFilePath,\n isPerLocale: false,\n });\n }\n\n return outputContentDeclarationFile;\n }\n\n if (typeof autoFillField === 'object') {\n const localeList = Object.keys(autoFillField).filter(\n (locale) =>\n typeof autoFillField[locale as keyof typeof autoFillField] === 'string'\n ) as LocalesValues[];\n\n const output: FillData[] = localeList\n .filter((locale) =>\n Boolean(autoFillField[locale as keyof typeof autoFillField])\n )\n .map((locale) => {\n const formattedFilePath = formatAutoFilledFilePath(\n autoFillField[locale as keyof typeof autoFillField] as string,\n dictionaryKey,\n filePath,\n baseDir,\n locale\n );\n\n return {\n localeList: [locale],\n filePath: formattedFilePath,\n isPerLocale: true,\n };\n });\n\n // Group by filePath and merge localeList\n const groupedByFilePath = output.reduce((acc, curr) => {\n const existing = acc.find((item) => item.filePath === curr.filePath);\n if (existing) {\n existing.localeList.push(...curr.localeList);\n } else {\n acc.push(curr);\n }\n return acc;\n }, [] as FillData[]);\n\n outputContentDeclarationFile.push(...groupedByFilePath);\n }\n\n return outputContentDeclarationFile;\n};\n"],"mappings":";;;AASA,MAAa,kBACX,eACA,YACA,UACA,eACA,kBACe;CACf,MAAMA,+BAA2C,EAAE;CAEnD,MAAM,UAAU,cAAc,QAAQ;AAEtC,KAAI,CAAC,cAAe,QAAO;AAE3B,KAAI,OAAO,kBAAkB,UAAU;AACrC,MAAI,cAAc,SAAS,aAAa,EAAE;GACxC,MAAM,SAAS,WAAW,KAAK,WAAW;IACxC,MAAM,oBAAoB,yBACxB,eACA,eACA,UACA,SACA,OACD;AAED,WAAO;KACL,YAAY,CAAC,OAAO;KACpB,UAAU;KACV,aAAa;KACd;KACD;AAEF,gCAA6B,KAAK,GAAG,OAAO;SACvC;GACL,MAAM,oBAAoB,yBACxB,eACA,eACA,UACA,QACD;AAED,gCAA6B,KAAK;IAChC;IACA,UAAU;IACV,aAAa;IACd,CAAC;;AAGJ,SAAO;;AAGT,KAAI,OAAO,kBAAkB,UAAU;EA2BrC,MAAM,oBA1Ba,OAAO,KAAK,cAAc,CAAC,QAC3C,WACC,OAAO,cAAc,YAA0C,SAClE,CAGE,QAAQ,WACP,QAAQ,cAAc,QAAsC,CAC7D,CACA,KAAK,WAAW;GACf,MAAM,oBAAoB,yBACxB,cAAc,SACd,eACA,UACA,SACA,OACD;AAED,UAAO;IACL,YAAY,CAAC,OAAO;IACpB,UAAU;IACV,aAAa;IACd;IACD,CAG6B,QAAQ,KAAK,SAAS;GACrD,MAAM,WAAW,IAAI,MAAM,SAAS,KAAK,aAAa,KAAK,SAAS;AACpE,OAAI,SACF,UAAS,WAAW,KAAK,GAAG,KAAK,WAAW;OAE5C,KAAI,KAAK,KAAK;AAEhB,UAAO;KACN,EAAE,CAAe;AAEpB,+BAA6B,KAAK,GAAG,kBAAkB;;AAGzD,QAAO"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { pLimit } from "@intlayer/chokidar";
|
|
2
|
+
|
|
3
|
+
//#region src/fill/groupLimiter.ts
|
|
4
|
+
/**
|
|
5
|
+
* Creates a group limiter that controls concurrency and provides a sync point
|
|
6
|
+
* to wait for all scheduled tasks to complete.
|
|
7
|
+
*/
|
|
8
|
+
const makeGroupLimiter = (concurrency) => {
|
|
9
|
+
const limit = pLimit(concurrency);
|
|
10
|
+
let inflight = 0;
|
|
11
|
+
let resolveDone;
|
|
12
|
+
const donePromise = new Promise((r) => {
|
|
13
|
+
resolveDone = r;
|
|
14
|
+
});
|
|
15
|
+
let doneResolved = false;
|
|
16
|
+
const schedule = (fn) => {
|
|
17
|
+
inflight++;
|
|
18
|
+
limit(async () => {
|
|
19
|
+
await fn();
|
|
20
|
+
inflight--;
|
|
21
|
+
if (inflight === 0 && !doneResolved && limit.pendingCount === 0 && limit.activeCount === 0) {
|
|
22
|
+
doneResolved = true;
|
|
23
|
+
resolveDone();
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
const done = () => donePromise;
|
|
28
|
+
const activeCount = () => limit.activeCount;
|
|
29
|
+
const pendingCount = () => limit.pendingCount;
|
|
30
|
+
return {
|
|
31
|
+
schedule,
|
|
32
|
+
done,
|
|
33
|
+
activeCount,
|
|
34
|
+
pendingCount
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
//#endregion
|
|
39
|
+
export { makeGroupLimiter };
|
|
40
|
+
//# sourceMappingURL=groupLimiter.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"groupLimiter.mjs","names":["resolveDone!: () => void"],"sources":["../../../src/fill/groupLimiter.ts"],"sourcesContent":["import { pLimit } from '@intlayer/chokidar';\n\nexport type GroupLimiter = {\n schedule: <T>(fn: () => Promise<T>) => void;\n done: () => Promise<void>;\n activeCount: () => number;\n pendingCount: () => number;\n};\n\ntype PLimitFunction = {\n (...args: any[]): Promise<any>;\n activeCount: number;\n pendingCount: number;\n clearQueue: () => void;\n concurrency: number;\n};\n\n/**\n * Creates a group limiter that controls concurrency and provides a sync point\n * to wait for all scheduled tasks to complete.\n */\nexport const makeGroupLimiter = (concurrency: number): GroupLimiter => {\n const limit = pLimit(concurrency) as PLimitFunction;\n let inflight = 0;\n let resolveDone!: () => void;\n const donePromise = new Promise<void>((r) => {\n resolveDone = r;\n });\n let doneResolved = false;\n\n const schedule = <T>(fn: () => Promise<T>): void => {\n inflight++;\n limit(async () => {\n await fn();\n\n inflight--;\n if (\n inflight === 0 &&\n !doneResolved &&\n limit.pendingCount === 0 &&\n limit.activeCount === 0\n ) {\n doneResolved = true;\n resolveDone();\n }\n });\n };\n\n const done = (): Promise<void> => donePromise;\n\n const activeCount = (): number => limit.activeCount;\n const pendingCount = (): number => limit.pendingCount;\n\n return { schedule, done, activeCount, pendingCount };\n};\n"],"mappings":";;;;;;;AAqBA,MAAa,oBAAoB,gBAAsC;CACrE,MAAM,QAAQ,OAAO,YAAY;CACjC,IAAI,WAAW;CACf,IAAIA;CACJ,MAAM,cAAc,IAAI,SAAe,MAAM;AAC3C,gBAAc;GACd;CACF,IAAI,eAAe;CAEnB,MAAM,YAAe,OAA+B;AAClD;AACA,QAAM,YAAY;AAChB,SAAM,IAAI;AAEV;AACA,OACE,aAAa,KACb,CAAC,gBACD,MAAM,iBAAiB,KACvB,MAAM,gBAAgB,GACtB;AACA,mBAAe;AACf,iBAAa;;IAEf;;CAGJ,MAAM,aAA4B;CAElC,MAAM,oBAA4B,MAAM;CACxC,MAAM,qBAA6B,MAAM;AAEzC,QAAO;EAAE;EAAU;EAAM;EAAa;EAAc"}
|
package/dist/esm/fill/index.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { writeFill } from "./writeFill.mjs";
|
|
2
|
+
import { fill } from "./fill.mjs";
|
|
3
|
+
|
|
4
|
+
export { fill, writeFill };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { formatLocale } from "@intlayer/chokidar";
|
|
2
|
+
import { ANSIColors, colon, colorize, colorizeKey, colorizePath, getAppLogger } from "@intlayer/config";
|
|
3
|
+
import { basename } from "node:path";
|
|
4
|
+
import { getUnmergedDictionaries } from "@intlayer/unmerged-dictionaries-entry";
|
|
5
|
+
import { getFilterTranslationsOnlyDictionary, getMissingLocalesContent } from "@intlayer/core";
|
|
6
|
+
import { getDictionaries } from "@intlayer/dictionaries-entry";
|
|
7
|
+
|
|
8
|
+
//#region src/fill/listTranslationsTasks.ts
|
|
9
|
+
const listTranslationsTasks = (localIds, outputLocales, mode, baseLocale, configuration) => {
|
|
10
|
+
const appLogger = getAppLogger(configuration);
|
|
11
|
+
const mergedDictionariesRecord = getDictionaries(configuration);
|
|
12
|
+
const unmergedDictionariesRecord = getUnmergedDictionaries(configuration);
|
|
13
|
+
const dictionariesToProcess = Object.values(unmergedDictionariesRecord).flat().filter((dictionary) => localIds.includes(dictionary.localId));
|
|
14
|
+
const maxKeyLength = Math.max(...dictionariesToProcess.map((dict) => dict.key.length));
|
|
15
|
+
const translationTasks = [];
|
|
16
|
+
for (const targetUnmergedDictionary of dictionariesToProcess) {
|
|
17
|
+
const dictionaryPreset = colon([
|
|
18
|
+
" - ",
|
|
19
|
+
colorize("[", ANSIColors.GREY_DARK),
|
|
20
|
+
colorizeKey(targetUnmergedDictionary.key),
|
|
21
|
+
colorize("]", ANSIColors.GREY_DARK)
|
|
22
|
+
].join(""), { colSize: maxKeyLength + 6 });
|
|
23
|
+
const dictionaryKey = targetUnmergedDictionary.key;
|
|
24
|
+
const dictionaryLocalId = targetUnmergedDictionary.localId;
|
|
25
|
+
const mainDictionaryToProcess = mergedDictionariesRecord[dictionaryKey];
|
|
26
|
+
if ((targetUnmergedDictionary.fill ?? configuration.content.fill) === false) continue;
|
|
27
|
+
const sourceLocale = targetUnmergedDictionary.locale ?? baseLocale;
|
|
28
|
+
if (!mainDictionaryToProcess) {
|
|
29
|
+
appLogger(`${dictionaryPreset} Dictionary not found in dictionariesRecord. Skipping.`, { level: "warn" });
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
if (!targetUnmergedDictionary.filePath) {
|
|
33
|
+
appLogger(`${dictionaryPreset} Dictionary has no file path. Skipping.`, { level: "warn" });
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const sourceLocaleContent = getFilterTranslationsOnlyDictionary(mainDictionaryToProcess, sourceLocale);
|
|
37
|
+
if (Object.keys(sourceLocaleContent).length === 0) {
|
|
38
|
+
appLogger(`${dictionaryPreset} No content found for dictionary in source locale ${formatLocale(sourceLocale)}. Skipping translation for this dictionary.`, { level: "warn" });
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* In 'complete' mode, filter only the missing locales to translate
|
|
43
|
+
*
|
|
44
|
+
* Skip the dictionary if there are no missing locales to translate
|
|
45
|
+
*/
|
|
46
|
+
let outputLocalesList = outputLocales;
|
|
47
|
+
if (mode === "complete") outputLocalesList = getMissingLocalesContent(targetUnmergedDictionary, outputLocales, {
|
|
48
|
+
dictionaryKey: targetUnmergedDictionary.key,
|
|
49
|
+
keyPath: [],
|
|
50
|
+
plugins: []
|
|
51
|
+
});
|
|
52
|
+
if (outputLocalesList.length === 0) {
|
|
53
|
+
appLogger(`${dictionaryPreset} No locales to fill, Skipping ${colorizePath(basename(targetUnmergedDictionary.filePath))}`, { level: "warn" });
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
translationTasks.push({
|
|
57
|
+
dictionaryKey,
|
|
58
|
+
dictionaryLocalId,
|
|
59
|
+
sourceLocale,
|
|
60
|
+
targetLocales: outputLocalesList,
|
|
61
|
+
dictionaryPreset,
|
|
62
|
+
dictionaryFilePath: targetUnmergedDictionary.filePath
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
return translationTasks;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
//#endregion
|
|
69
|
+
export { listTranslationsTasks };
|
|
70
|
+
//# sourceMappingURL=listTranslationsTasks.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listTranslationsTasks.mjs","names":["translationTasks: TranslationTask[]","mainDictionaryToProcess: Dictionary","sourceLocale: Locale","outputLocalesList: Locale[]"],"sources":["../../../src/fill/listTranslationsTasks.ts"],"sourcesContent":["import { basename } from 'node:path';\nimport { formatLocale } from '@intlayer/chokidar';\nimport {\n ANSIColors,\n colon,\n colorize,\n colorizeKey,\n colorizePath,\n getAppLogger,\n} from '@intlayer/config';\nimport {\n getFilterTranslationsOnlyDictionary,\n getMissingLocalesContent,\n} from '@intlayer/core';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport type {\n ContentNode,\n Dictionary,\n IntlayerConfig,\n LocalDictionaryId,\n Locale,\n} from '@intlayer/types';\nimport { getUnmergedDictionaries } from '@intlayer/unmerged-dictionaries-entry';\n\nexport type TranslationTask = {\n dictionaryKey: string;\n dictionaryLocalId: LocalDictionaryId;\n sourceLocale: Locale;\n targetLocales: Locale[];\n dictionaryPreset: string;\n dictionaryFilePath: string;\n};\n\nexport const listTranslationsTasks = (\n localIds: LocalDictionaryId[],\n outputLocales: Locale[],\n mode: 'complete' | 'review',\n baseLocale: Locale,\n configuration: IntlayerConfig\n): TranslationTask[] => {\n const appLogger = getAppLogger(configuration);\n\n const mergedDictionariesRecord = getDictionaries(configuration);\n const unmergedDictionariesRecord = getUnmergedDictionaries(configuration);\n\n const allFlatDictionaries = Object.values(unmergedDictionariesRecord).flat();\n const dictionariesToProcess = allFlatDictionaries.filter((dictionary) =>\n localIds.includes(dictionary.localId!)\n );\n\n const maxKeyLength = Math.max(\n ...dictionariesToProcess.map((dict) => dict.key.length)\n );\n\n const translationTasks: TranslationTask[] = [];\n\n for (const targetUnmergedDictionary of dictionariesToProcess) {\n const dictionaryPreset = colon(\n [\n ' - ',\n colorize('[', ANSIColors.GREY_DARK),\n colorizeKey(targetUnmergedDictionary.key),\n colorize(']', ANSIColors.GREY_DARK),\n ].join(''),\n { colSize: maxKeyLength + 6 }\n );\n\n const dictionaryKey = targetUnmergedDictionary.key;\n const dictionaryLocalId = targetUnmergedDictionary.localId!;\n const mainDictionaryToProcess: Dictionary =\n mergedDictionariesRecord[dictionaryKey];\n const dictionaryFill =\n targetUnmergedDictionary.fill ?? configuration.content.fill;\n\n if (dictionaryFill === false) continue;\n\n const sourceLocale: Locale = (targetUnmergedDictionary.locale ??\n baseLocale) as Locale;\n\n if (!mainDictionaryToProcess) {\n appLogger(\n `${dictionaryPreset} Dictionary not found in dictionariesRecord. Skipping.`,\n {\n level: 'warn',\n }\n );\n continue;\n }\n\n if (!targetUnmergedDictionary.filePath) {\n appLogger(`${dictionaryPreset} Dictionary has no file path. Skipping.`, {\n level: 'warn',\n });\n continue;\n }\n\n const sourceLocaleContent = getFilterTranslationsOnlyDictionary(\n mainDictionaryToProcess,\n sourceLocale\n );\n\n if (\n Object.keys(sourceLocaleContent as Record<string, unknown>).length === 0\n ) {\n appLogger(\n `${dictionaryPreset} No content found for dictionary in source locale ${formatLocale(sourceLocale)}. Skipping translation for this dictionary.`,\n {\n level: 'warn',\n }\n );\n continue;\n }\n\n /**\n * In 'complete' mode, filter only the missing locales to translate\n *\n * Skip the dictionary if there are no missing locales to translate\n */\n let outputLocalesList: Locale[] = outputLocales as Locale[];\n\n if (mode === 'complete') {\n const missingLocales = getMissingLocalesContent(\n targetUnmergedDictionary as unknown as ContentNode,\n outputLocales,\n {\n dictionaryKey: targetUnmergedDictionary.key,\n keyPath: [],\n plugins: [],\n }\n );\n\n outputLocalesList = missingLocales;\n }\n\n if (outputLocalesList.length === 0) {\n appLogger(\n `${dictionaryPreset} No locales to fill, Skipping ${colorizePath(basename(targetUnmergedDictionary.filePath))}`,\n {\n level: 'warn',\n }\n );\n continue;\n }\n\n translationTasks.push({\n dictionaryKey,\n dictionaryLocalId,\n sourceLocale,\n targetLocales: outputLocalesList,\n dictionaryPreset,\n dictionaryFilePath: targetUnmergedDictionary.filePath,\n });\n }\n\n return translationTasks;\n};\n"],"mappings":";;;;;;;;AAiCA,MAAa,yBACX,UACA,eACA,MACA,YACA,kBACsB;CACtB,MAAM,YAAY,aAAa,cAAc;CAE7C,MAAM,2BAA2B,gBAAgB,cAAc;CAC/D,MAAM,6BAA6B,wBAAwB,cAAc;CAGzE,MAAM,wBADsB,OAAO,OAAO,2BAA2B,CAAC,MAAM,CAC1B,QAAQ,eACxD,SAAS,SAAS,WAAW,QAAS,CACvC;CAED,MAAM,eAAe,KAAK,IACxB,GAAG,sBAAsB,KAAK,SAAS,KAAK,IAAI,OAAO,CACxD;CAED,MAAMA,mBAAsC,EAAE;AAE9C,MAAK,MAAM,4BAA4B,uBAAuB;EAC5D,MAAM,mBAAmB,MACvB;GACE;GACA,SAAS,KAAK,WAAW,UAAU;GACnC,YAAY,yBAAyB,IAAI;GACzC,SAAS,KAAK,WAAW,UAAU;GACpC,CAAC,KAAK,GAAG,EACV,EAAE,SAAS,eAAe,GAAG,CAC9B;EAED,MAAM,gBAAgB,yBAAyB;EAC/C,MAAM,oBAAoB,yBAAyB;EACnD,MAAMC,0BACJ,yBAAyB;AAI3B,OAFE,yBAAyB,QAAQ,cAAc,QAAQ,UAElC,MAAO;EAE9B,MAAMC,eAAwB,yBAAyB,UACrD;AAEF,MAAI,CAAC,yBAAyB;AAC5B,aACE,GAAG,iBAAiB,yDACpB,EACE,OAAO,QACR,CACF;AACD;;AAGF,MAAI,CAAC,yBAAyB,UAAU;AACtC,aAAU,GAAG,iBAAiB,0CAA0C,EACtE,OAAO,QACR,CAAC;AACF;;EAGF,MAAM,sBAAsB,oCAC1B,yBACA,aACD;AAED,MACE,OAAO,KAAK,oBAA+C,CAAC,WAAW,GACvE;AACA,aACE,GAAG,iBAAiB,oDAAoD,aAAa,aAAa,CAAC,8CACnG,EACE,OAAO,QACR,CACF;AACD;;;;;;;EAQF,IAAIC,oBAA8B;AAElC,MAAI,SAAS,WAWX,qBAVuB,yBACrB,0BACA,eACA;GACE,eAAe,yBAAyB;GACxC,SAAS,EAAE;GACX,SAAS,EAAE;GACZ,CACF;AAKH,MAAI,kBAAkB,WAAW,GAAG;AAClC,aACE,GAAG,iBAAiB,gCAAgC,aAAa,SAAS,yBAAyB,SAAS,CAAC,IAC7G,EACE,OAAO,QACR,CACF;AACD;;AAGF,mBAAiB,KAAK;GACpB;GACA;GACA;GACA,eAAe;GACf;GACA,oBAAoB,yBAAyB;GAC9C,CAAC;;AAGJ,QAAO"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { formatAutoFilledFilePath } from "./formatAutoFilledFilePath.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/fill/test-original-case.ts
|
|
4
|
+
const result = formatAutoFilledFilePath("./{{key}}.content.json", "dictionary-field-editor", "../../packages/@intlayer/design-system/src/components/DictionaryFieldEditor/dictionaryFieldEditor.content.ts", "/Users/aymericpineau/Documents/intlayer/apps/website");
|
|
5
|
+
console.log("Result:", result);
|
|
6
|
+
console.log("Expected: ../../packages/@intlayer/design-system/src/components/DictionaryFieldEditor/dictionaryFieldEditor.content.json");
|
|
7
|
+
console.log("Match:", result === "../../packages/@intlayer/design-system/src/components/DictionaryFieldEditor/dictionaryFieldEditor.content.json");
|
|
8
|
+
|
|
9
|
+
//#endregion
|
|
10
|
+
//# sourceMappingURL=test-original-case.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-original-case.mjs","names":[],"sources":["../../../src/fill/test-original-case.ts"],"sourcesContent":["import { formatAutoFilledFilePath } from './formatAutoFilledFilePath';\n\n// Original use case from the user\nconst result = formatAutoFilledFilePath(\n './{{key}}.content.json',\n 'dictionary-field-editor',\n '../../packages/@intlayer/design-system/src/components/DictionaryFieldEditor/dictionaryFieldEditor.content.ts',\n '/Users/aymericpineau/Documents/intlayer/apps/website'\n);\n\nconsole.log('Result:', result);\nconsole.log('Expected: ../../packages/@intlayer/design-system/src/components/DictionaryFieldEditor/dictionaryFieldEditor.content.json');\nconsole.log('Match:', result === '../../packages/@intlayer/design-system/src/components/DictionaryFieldEditor/dictionaryFieldEditor.content.json');\n\n"],"mappings":";;;AAGA,MAAM,SAAS,yBACb,0BACA,2BACA,gHACA,uDACD;AAED,QAAQ,IAAI,WAAW,OAAO;AAC9B,QAAQ,IAAI,2HAA2H;AACvI,QAAQ,IAAI,UAAU,WAAW,iHAAiH"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { getIntlayerAPIProxy } from "@intlayer/api";
|
|
2
|
+
import { chunkJSON, formatLocale, reconstructFromSingleChunk, reduceObjectFormat, verifyIdenticObjectFormat } from "@intlayer/chokidar";
|
|
3
|
+
import { ANSIColors, colon, colorize, colorizeNumber, colorizePath, getAppLogger, retryManager } from "@intlayer/config";
|
|
4
|
+
import { basename } from "node:path";
|
|
5
|
+
import { getUnmergedDictionaries } from "@intlayer/unmerged-dictionaries-entry";
|
|
6
|
+
import { getFilterMissingTranslationsDictionary, getPerLocaleDictionary, insertContentInDictionary, mergeDictionaries } from "@intlayer/core";
|
|
7
|
+
|
|
8
|
+
//#region src/fill/translateDictionary.ts
|
|
9
|
+
const hasMissingMetadata = (dictionary) => !dictionary.description || !dictionary.title || !dictionary.tags;
|
|
10
|
+
const CHUNK_SIZE = 7e3;
|
|
11
|
+
const GLOBAL_MAX_RETRY = 2;
|
|
12
|
+
const MAX_RETRY = 3;
|
|
13
|
+
const RETRY_DELAY = 1e3 * 10;
|
|
14
|
+
const translateDictionary = async (task, configuration, options) => {
|
|
15
|
+
const appLogger = getAppLogger(configuration);
|
|
16
|
+
const intlayerAPI = getIntlayerAPIProxy(void 0, configuration);
|
|
17
|
+
const { mode, aiOptions, fillMetadata } = {
|
|
18
|
+
mode: "complete",
|
|
19
|
+
fillMetadata: true,
|
|
20
|
+
...options
|
|
21
|
+
};
|
|
22
|
+
return await retryManager(async () => {
|
|
23
|
+
const baseUnmergedDictionary = getUnmergedDictionaries(configuration)[task.dictionaryKey].find((dict) => dict.localId === task.dictionaryLocalId);
|
|
24
|
+
if (!baseUnmergedDictionary) {
|
|
25
|
+
appLogger(`${task.dictionaryPreset}Dictionary not found in unmergedDictionariesRecord. Skipping.`, { level: "warn" });
|
|
26
|
+
return {
|
|
27
|
+
...task,
|
|
28
|
+
dictionaryOutput: null
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
let metadata;
|
|
32
|
+
if (fillMetadata && (hasMissingMetadata(baseUnmergedDictionary) || mode === "review")) {
|
|
33
|
+
const defaultLocaleDictionary = getPerLocaleDictionary(baseUnmergedDictionary, configuration.internationalization.defaultLocale);
|
|
34
|
+
appLogger(`${task.dictionaryPreset} Filling missing metadata for ${colorizePath(basename(baseUnmergedDictionary.filePath))}`, { level: "info" });
|
|
35
|
+
const runAudit = async () => await intlayerAPI.ai.auditContentDeclarationMetadata({
|
|
36
|
+
fileContent: JSON.stringify(defaultLocaleDictionary),
|
|
37
|
+
aiOptions
|
|
38
|
+
});
|
|
39
|
+
metadata = (options?.onHandle ? await options.onHandle(runAudit) : await runAudit()).data?.fileContent;
|
|
40
|
+
}
|
|
41
|
+
let dictionaryToProcess = baseUnmergedDictionary;
|
|
42
|
+
const translatedContent = {};
|
|
43
|
+
for await (const targetLocale of task.targetLocales) {
|
|
44
|
+
/**
|
|
45
|
+
* In complete mode, for large dictionaries, we want to filter all content that is already translated
|
|
46
|
+
*
|
|
47
|
+
* targetLocale: fr
|
|
48
|
+
*
|
|
49
|
+
* { test1: t({ ar: 'Hello', en: 'Hello', fr: 'Bonjour' } }) -> {}
|
|
50
|
+
* { test2: t({ ar: 'Hello', en: 'Hello' }) } -> { test2: t({ ar: 'Hello', en: 'Hello' }) }
|
|
51
|
+
*
|
|
52
|
+
*/
|
|
53
|
+
if (mode === "complete") dictionaryToProcess = getFilterMissingTranslationsDictionary(dictionaryToProcess, targetLocale);
|
|
54
|
+
dictionaryToProcess = getPerLocaleDictionary(dictionaryToProcess, task.sourceLocale);
|
|
55
|
+
const targetLocaleDictionary = getPerLocaleDictionary(baseUnmergedDictionary, targetLocale);
|
|
56
|
+
const localePreset = colon([
|
|
57
|
+
colorize("[", ANSIColors.GREY_DARK),
|
|
58
|
+
formatLocale(targetLocale),
|
|
59
|
+
colorize("]", ANSIColors.GREY_DARK)
|
|
60
|
+
].join(""), { colSize: 10 });
|
|
61
|
+
const createChunkPreset = (chunkIndex, totalChunks) => {
|
|
62
|
+
if (totalChunks <= 1) return "";
|
|
63
|
+
return colon([
|
|
64
|
+
colorize("[", ANSIColors.GREY_DARK),
|
|
65
|
+
colorizeNumber(chunkIndex + 1),
|
|
66
|
+
colorize(`/${totalChunks}`, ANSIColors.GREY_DARK),
|
|
67
|
+
colorize("]", ANSIColors.GREY_DARK)
|
|
68
|
+
].join(""), { colSize: 5 });
|
|
69
|
+
};
|
|
70
|
+
appLogger(`${task.dictionaryPreset}${localePreset} Preparing ${colorizePath(basename(targetLocaleDictionary.filePath))}`, { level: "info" });
|
|
71
|
+
const chunkedJsonContent = chunkJSON(dictionaryToProcess.content, CHUNK_SIZE);
|
|
72
|
+
const nbOfChunks = chunkedJsonContent.length;
|
|
73
|
+
if (nbOfChunks > 1) appLogger(`${task.dictionaryPreset}${localePreset} Split into ${colorizeNumber(nbOfChunks)} chunks for translation`, { level: "info" });
|
|
74
|
+
const chunkResult = [];
|
|
75
|
+
const chunkPromises = chunkedJsonContent.map((chunk) => {
|
|
76
|
+
const chunkPreset = createChunkPreset(chunk.index, chunk.total);
|
|
77
|
+
if (nbOfChunks > 1) appLogger(`${task.dictionaryPreset}${localePreset}${chunkPreset} Translating chunk`, { level: "info" });
|
|
78
|
+
const chunkContent = reconstructFromSingleChunk(chunk);
|
|
79
|
+
const presetOutputContent = reduceObjectFormat(targetLocaleDictionary.content, chunkContent);
|
|
80
|
+
const executeTranslation = async () => {
|
|
81
|
+
return await retryManager(async () => {
|
|
82
|
+
const translationResult = await intlayerAPI.ai.translateJSON({
|
|
83
|
+
entryFileContent: chunkContent,
|
|
84
|
+
presetOutputContent,
|
|
85
|
+
dictionaryDescription: dictionaryToProcess.description ?? metadata?.description ?? "",
|
|
86
|
+
entryLocale: task.sourceLocale,
|
|
87
|
+
outputLocale: targetLocale,
|
|
88
|
+
mode,
|
|
89
|
+
aiOptions
|
|
90
|
+
});
|
|
91
|
+
if (!translationResult.data?.fileContent) throw new Error("No content result");
|
|
92
|
+
const { isIdentic } = verifyIdenticObjectFormat(translationResult.data.fileContent, chunkContent);
|
|
93
|
+
if (!isIdentic) throw new Error("Translation result does not match expected format");
|
|
94
|
+
return translationResult.data.fileContent;
|
|
95
|
+
}, {
|
|
96
|
+
maxRetry: MAX_RETRY,
|
|
97
|
+
delay: RETRY_DELAY,
|
|
98
|
+
onError: ({ error, attempt, maxRetry }) => {
|
|
99
|
+
const chunkPreset$1 = createChunkPreset(chunk.index, chunk.total);
|
|
100
|
+
appLogger(`${task.dictionaryPreset}${localePreset}${chunkPreset$1} ${colorize("Error filling:", ANSIColors.RED)} ${colorize(error, ANSIColors.GREY_DARK)} - Attempt ${colorizeNumber(attempt + 1)} of ${colorizeNumber(maxRetry)}`, { level: "error" });
|
|
101
|
+
}
|
|
102
|
+
})();
|
|
103
|
+
};
|
|
104
|
+
return (options?.onHandle ? options.onHandle(executeTranslation) : executeTranslation()).then((result) => ({
|
|
105
|
+
chunk,
|
|
106
|
+
result
|
|
107
|
+
}));
|
|
108
|
+
});
|
|
109
|
+
(await Promise.all(chunkPromises)).sort((a, b) => a.chunk.index - b.chunk.index).forEach(({ result }) => {
|
|
110
|
+
chunkResult.push(result);
|
|
111
|
+
});
|
|
112
|
+
translatedContent[targetLocale] = mergeDictionaries(chunkResult.map((chunk) => ({
|
|
113
|
+
...dictionaryToProcess,
|
|
114
|
+
content: chunk
|
|
115
|
+
}))).content;
|
|
116
|
+
}
|
|
117
|
+
let dictionaryOutput = {
|
|
118
|
+
...baseUnmergedDictionary,
|
|
119
|
+
...metadata
|
|
120
|
+
};
|
|
121
|
+
for (const targetLocale of task.targetLocales) if (translatedContent[targetLocale]) dictionaryOutput = insertContentInDictionary(dictionaryOutput, translatedContent[targetLocale], targetLocale);
|
|
122
|
+
appLogger(`${task.dictionaryPreset} ${colorize("Translation completed successfully", ANSIColors.GREEN)} for ${colorizePath(basename(dictionaryOutput.filePath))}`, { level: "info" });
|
|
123
|
+
return {
|
|
124
|
+
...task,
|
|
125
|
+
dictionaryOutput
|
|
126
|
+
};
|
|
127
|
+
}, {
|
|
128
|
+
maxRetry: GLOBAL_MAX_RETRY,
|
|
129
|
+
delay: RETRY_DELAY,
|
|
130
|
+
onError: ({ error, attempt, maxRetry }) => {
|
|
131
|
+
appLogger(`${task.dictionaryPreset} ${colorize("Error fill command:", ANSIColors.RED)} ${colorize(error, ANSIColors.GREY_DARK)} - Attempt ${colorizeNumber(attempt + 1)} of ${colorizeNumber(maxRetry)}`, { level: "error" });
|
|
132
|
+
},
|
|
133
|
+
onMaxTryReached: ({ error }) => {
|
|
134
|
+
appLogger(`${task.dictionaryPreset} ${colorize("Maximum number of retries reached:", ANSIColors.RED)} ${colorize(error, ANSIColors.GREY_DARK)}`, { level: "error" });
|
|
135
|
+
}
|
|
136
|
+
})();
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
//#endregion
|
|
140
|
+
export { translateDictionary };
|
|
141
|
+
//# sourceMappingURL=translateDictionary.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translateDictionary.mjs","names":["baseUnmergedDictionary: Dictionary | undefined","metadata:\n | Pick<Dictionary, 'description' | 'title' | 'tags'>\n | undefined","translatedContent: Partial<Record<Locale, Dictionary['content']>>","chunkedJsonContent: JsonChunk[]","chunkResult: JsonChunk[]","chunkPreset","dictionaryOutput: Dictionary"],"sources":["../../../src/fill/translateDictionary.ts"],"sourcesContent":["import { basename } from 'node:path';\nimport { type AIOptions, getIntlayerAPIProxy } from '@intlayer/api';\nimport {\n chunkJSON,\n formatLocale,\n type JsonChunk,\n reconstructFromSingleChunk,\n reduceObjectFormat,\n verifyIdenticObjectFormat,\n} from '@intlayer/chokidar';\nimport {\n ANSIColors,\n colon,\n colorize,\n colorizeNumber,\n colorizePath,\n getAppLogger,\n retryManager,\n} from '@intlayer/config';\nimport {\n getFilterMissingTranslationsDictionary,\n getPerLocaleDictionary,\n insertContentInDictionary,\n mergeDictionaries,\n} from '@intlayer/core';\nimport type { Dictionary, IntlayerConfig, Locale } from '@intlayer/types';\nimport { getUnmergedDictionaries } from '@intlayer/unmerged-dictionaries-entry';\nimport type { TranslationTask } from './listTranslationsTasks';\n\ntype TranslateDictionaryResult = TranslationTask & {\n dictionaryOutput: Dictionary | null;\n};\n\ntype TranslateDictionaryOptions = {\n mode: 'complete' | 'review';\n aiOptions?: AIOptions;\n fillMetadata?: boolean;\n onHandle?: ReturnType<typeof import('@intlayer/chokidar').getGlobalLimiter>;\n};\n\nconst hasMissingMetadata = (dictionary: Dictionary) =>\n !dictionary.description || !dictionary.title || !dictionary.tags;\n\nconst CHUNK_SIZE = 7000; // GPT-5 Mini safe input size\nconst GLOBAL_MAX_RETRY = 2;\nconst MAX_RETRY = 3;\nconst RETRY_DELAY = 1000 * 10; // 10 seconds\n\nexport const translateDictionary = async (\n task: TranslationTask,\n configuration: IntlayerConfig,\n options?: TranslateDictionaryOptions\n): Promise<TranslateDictionaryResult> => {\n const appLogger = getAppLogger(configuration);\n const intlayerAPI = getIntlayerAPIProxy(undefined, configuration);\n\n const { mode, aiOptions, fillMetadata } = {\n mode: 'complete',\n fillMetadata: true,\n ...options,\n };\n\n const result = await retryManager(\n async () => {\n const unmergedDictionariesRecord = getUnmergedDictionaries(configuration);\n\n const baseUnmergedDictionary: Dictionary | undefined =\n unmergedDictionariesRecord[task.dictionaryKey].find(\n (dict) => dict.localId === task.dictionaryLocalId\n );\n\n if (!baseUnmergedDictionary) {\n appLogger(\n `${task.dictionaryPreset}Dictionary not found in unmergedDictionariesRecord. Skipping.`,\n {\n level: 'warn',\n }\n );\n return { ...task, dictionaryOutput: null };\n }\n\n let metadata:\n | Pick<Dictionary, 'description' | 'title' | 'tags'>\n | undefined;\n\n if (\n fillMetadata &&\n (hasMissingMetadata(baseUnmergedDictionary) || mode === 'review')\n ) {\n const defaultLocaleDictionary = getPerLocaleDictionary(\n baseUnmergedDictionary,\n configuration.internationalization.defaultLocale\n );\n\n appLogger(\n `${task.dictionaryPreset} Filling missing metadata for ${colorizePath(basename(baseUnmergedDictionary.filePath!))}`,\n {\n level: 'info',\n }\n );\n\n const runAudit = async () =>\n await intlayerAPI.ai.auditContentDeclarationMetadata({\n fileContent: JSON.stringify(defaultLocaleDictionary),\n aiOptions,\n });\n\n const metadataResult = options?.onHandle\n ? await options.onHandle(runAudit)\n : await runAudit();\n\n metadata = metadataResult.data?.fileContent;\n }\n\n let dictionaryToProcess = baseUnmergedDictionary;\n\n const translatedContent: Partial<Record<Locale, Dictionary['content']>> =\n {};\n\n for await (const targetLocale of task.targetLocales) {\n /**\n * In complete mode, for large dictionaries, we want to filter all content that is already translated\n *\n * targetLocale: fr\n *\n * { test1: t({ ar: 'Hello', en: 'Hello', fr: 'Bonjour' } }) -> {}\n * { test2: t({ ar: 'Hello', en: 'Hello' }) } -> { test2: t({ ar: 'Hello', en: 'Hello' }) }\n *\n */\n if (mode === 'complete') {\n // Remove all nodes that don't have any content to translate\n dictionaryToProcess = getFilterMissingTranslationsDictionary(\n dictionaryToProcess,\n targetLocale\n );\n }\n\n dictionaryToProcess = getPerLocaleDictionary(\n dictionaryToProcess,\n task.sourceLocale\n );\n\n const targetLocaleDictionary = getPerLocaleDictionary(\n baseUnmergedDictionary,\n targetLocale\n );\n\n const localePreset = colon(\n [\n colorize('[', ANSIColors.GREY_DARK),\n formatLocale(targetLocale),\n colorize(']', ANSIColors.GREY_DARK),\n ].join(''),\n { colSize: 10 }\n );\n\n const createChunkPreset = (chunkIndex: number, totalChunks: number) => {\n if (totalChunks <= 1) return '';\n return colon(\n [\n colorize('[', ANSIColors.GREY_DARK),\n colorizeNumber(chunkIndex + 1),\n colorize(`/${totalChunks}`, ANSIColors.GREY_DARK),\n colorize(']', ANSIColors.GREY_DARK),\n ].join(''),\n { colSize: 5 }\n );\n };\n\n appLogger(\n `${task.dictionaryPreset}${localePreset} Preparing ${colorizePath(basename(targetLocaleDictionary.filePath!))}`,\n {\n level: 'info',\n }\n );\n\n const chunkedJsonContent: JsonChunk[] = chunkJSON(\n dictionaryToProcess.content,\n CHUNK_SIZE\n );\n\n const nbOfChunks = chunkedJsonContent.length;\n\n if (nbOfChunks > 1) {\n appLogger(\n `${task.dictionaryPreset}${localePreset} Split into ${colorizeNumber(nbOfChunks)} chunks for translation`,\n {\n level: 'info',\n }\n );\n }\n\n const chunkResult: JsonChunk[] = [];\n\n // Process chunks in parallel (globally throttled) to allow concurrent translation\n const chunkPromises = chunkedJsonContent.map((chunk) => {\n const chunkPreset = createChunkPreset(chunk.index, chunk.total);\n\n if (nbOfChunks > 1) {\n appLogger(\n `${task.dictionaryPreset}${localePreset}${chunkPreset} Translating chunk`,\n {\n level: 'info',\n }\n );\n }\n\n // Reconstruct partial JSON content from this chunk's patches\n const chunkContent = reconstructFromSingleChunk(chunk);\n const presetOutputContent = reduceObjectFormat(\n targetLocaleDictionary.content,\n chunkContent\n );\n\n const executeTranslation = async () => {\n return await retryManager(\n async () => {\n const translationResult = await intlayerAPI.ai.translateJSON({\n entryFileContent: chunkContent as unknown as JSON,\n presetOutputContent,\n dictionaryDescription:\n dictionaryToProcess.description ??\n metadata?.description ??\n '',\n entryLocale: task.sourceLocale,\n outputLocale: targetLocale,\n mode,\n aiOptions,\n });\n\n if (!translationResult.data?.fileContent) {\n throw new Error('No content result');\n }\n\n const { isIdentic } = verifyIdenticObjectFormat(\n translationResult.data.fileContent,\n chunkContent\n );\n if (!isIdentic) {\n throw new Error(\n 'Translation result does not match expected format'\n );\n }\n\n return translationResult.data.fileContent;\n },\n {\n maxRetry: MAX_RETRY,\n delay: RETRY_DELAY,\n onError: ({ error, attempt, maxRetry }) => {\n const chunkPreset = createChunkPreset(\n chunk.index,\n chunk.total\n );\n appLogger(\n `${task.dictionaryPreset}${localePreset}${chunkPreset} ${colorize('Error filling:', ANSIColors.RED)} ${colorize(error, ANSIColors.GREY_DARK)} - Attempt ${colorizeNumber(attempt + 1)} of ${colorizeNumber(maxRetry)}`,\n {\n level: 'error',\n }\n );\n },\n }\n )();\n };\n\n const wrapped = options?.onHandle\n ? options.onHandle(executeTranslation) // queued in global limiter\n : executeTranslation(); // no global limiter\n\n return wrapped.then((result) => ({ chunk, result }));\n });\n\n // Wait for all chunks for this locale in parallel (still capped by global limiter)\n const chunkResults = await Promise.all(chunkPromises);\n\n // Maintain order\n chunkResults\n .sort((a, b) => a.chunk.index - b.chunk.index)\n .forEach(({ result }) => {\n chunkResult.push(result);\n });\n\n // Merge partial JSON objects produced from each chunk into a single object\n const merged = mergeDictionaries(\n chunkResult.map((chunk) => ({\n ...dictionaryToProcess,\n content: chunk,\n }))\n );\n\n translatedContent[targetLocale] =\n merged.content as Dictionary['content'];\n }\n\n let dictionaryOutput: Dictionary = {\n ...baseUnmergedDictionary,\n ...metadata,\n };\n\n for (const targetLocale of task.targetLocales) {\n if (translatedContent[targetLocale]) {\n dictionaryOutput = insertContentInDictionary(\n dictionaryOutput,\n translatedContent[targetLocale],\n targetLocale\n );\n }\n }\n\n appLogger(\n `${task.dictionaryPreset} ${colorize('Translation completed successfully', ANSIColors.GREEN)} for ${colorizePath(basename(dictionaryOutput.filePath!))}`,\n {\n level: 'info',\n }\n );\n\n return {\n ...task,\n dictionaryOutput,\n };\n },\n {\n maxRetry: GLOBAL_MAX_RETRY,\n delay: RETRY_DELAY,\n onError: ({ error, attempt, maxRetry }) => {\n appLogger(\n `${task.dictionaryPreset} ${colorize('Error fill command:', ANSIColors.RED)} ${colorize(error, ANSIColors.GREY_DARK)} - Attempt ${colorizeNumber(attempt + 1)} of ${colorizeNumber(maxRetry)}`,\n {\n level: 'error',\n }\n );\n },\n onMaxTryReached: ({ error }) => {\n appLogger(\n `${task.dictionaryPreset} ${colorize('Maximum number of retries reached:', ANSIColors.RED)} ${colorize(error, ANSIColors.GREY_DARK)}`,\n {\n level: 'error',\n }\n );\n },\n }\n )();\n\n return result as TranslateDictionaryResult;\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { formatFillData } from "./formatFillData.mjs";
|
|
2
|
+
import { formatLocale, formatPath, reduceDictionaryContent, writeContentDeclaration } from "@intlayer/chokidar";
|
|
3
|
+
import { colorizeKey, getAppLogger } from "@intlayer/config";
|
|
4
|
+
import { getDictionaries } from "@intlayer/dictionaries-entry";
|
|
5
|
+
|
|
6
|
+
//#region src/fill/writeAutoFill.ts
|
|
7
|
+
const writeFill = async (contentDeclarationFile, outputLocales, parentLocales, configuration) => {
|
|
8
|
+
const appLogger = getAppLogger(configuration);
|
|
9
|
+
const fullDictionary = getDictionaries(configuration)[contentDeclarationFile.key];
|
|
10
|
+
const filePath = contentDeclarationFile.filePath;
|
|
11
|
+
if (!filePath) {
|
|
12
|
+
appLogger("No file path found for dictionary", { level: "error" });
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const autoFillOptions = fullDictionary.fill ?? configuration.content.fill;
|
|
16
|
+
if (typeof autoFillOptions === "boolean" && autoFillOptions === false) {
|
|
17
|
+
appLogger(`Auto fill is disabled for '${colorizeKey(fullDictionary.key)}'`, { level: "info" });
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const autoFillData = formatFillData(autoFillOptions, (outputLocales ?? configuration.internationalization.locales).filter((locale) => !parentLocales?.includes(locale)), filePath, fullDictionary.key, configuration);
|
|
21
|
+
for await (const output of autoFillData) {
|
|
22
|
+
if (!output.filePath) {
|
|
23
|
+
appLogger(`No file path found for auto filled content declaration for '${colorizeKey(fullDictionary.key)}'`, { level: "error" });
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
const reducedDictionaryContent = reduceDictionaryContent(fullDictionary, contentDeclarationFile);
|
|
27
|
+
await writeContentDeclaration({
|
|
28
|
+
...fullDictionary,
|
|
29
|
+
fill: void 0,
|
|
30
|
+
filled: true,
|
|
31
|
+
locale: output.isPerLocale ? output.localeList[0] : void 0,
|
|
32
|
+
content: reducedDictionaryContent.content,
|
|
33
|
+
filePath: output.filePath
|
|
34
|
+
}, configuration);
|
|
35
|
+
if (output.isPerLocale) {
|
|
36
|
+
const sourceLocale = output.localeList[0];
|
|
37
|
+
appLogger(`Auto filled per-locale content declaration for '${colorizeKey(fullDictionary.key)}' written to ${formatPath(output.filePath)} for locale ${formatLocale(sourceLocale)}`, { level: "info" });
|
|
38
|
+
} else appLogger(`Auto filled content declaration for '${colorizeKey(fullDictionary.key)}' written to ${formatPath(output.filePath)}`, { level: "info" });
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
//#endregion
|
|
43
|
+
export { writeFill };
|
|
44
|
+
//# sourceMappingURL=writeAutoFill.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writeAutoFill.mjs","names":["autoFillData: FillData[]"],"sources":["../../../src/fill/writeAutoFill.ts"],"sourcesContent":["import {\n formatLocale,\n formatPath,\n reduceDictionaryContent,\n writeContentDeclaration,\n} from '@intlayer/chokidar';\nimport { colorizeKey, getAppLogger } from '@intlayer/config';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport type { Dictionary, Fill, IntlayerConfig, Locale } from '@intlayer/types';\nimport { type FillData, formatFillData } from './formatFillData';\n\nexport const writeFill = async (\n contentDeclarationFile: Dictionary,\n outputLocales: Locale[],\n parentLocales: Locale[],\n configuration: IntlayerConfig\n) => {\n const appLogger = getAppLogger(configuration);\n const dictionaries = getDictionaries(configuration);\n\n const fullDictionary = dictionaries[contentDeclarationFile.key];\n\n const filePath = contentDeclarationFile.filePath;\n\n if (!filePath) {\n appLogger('No file path found for dictionary', {\n level: 'error',\n });\n return;\n }\n\n const autoFillOptions = fullDictionary.fill ?? configuration.content.fill;\n\n if (\n typeof autoFillOptions === 'boolean' &&\n (autoFillOptions as boolean) === false\n ) {\n appLogger(\n `Auto fill is disabled for '${colorizeKey(fullDictionary.key)}'`,\n {\n level: 'info',\n }\n );\n return;\n }\n\n const localeList: Locale[] = (\n outputLocales ?? configuration.internationalization.locales\n ).filter((locale) => !parentLocales?.includes(locale));\n\n const autoFillData: FillData[] = formatFillData(\n autoFillOptions as Fill,\n localeList,\n filePath,\n fullDictionary.key,\n configuration\n );\n\n for await (const output of autoFillData) {\n if (!output.filePath) {\n appLogger(\n `No file path found for auto filled content declaration for '${colorizeKey(fullDictionary.key)}'`,\n {\n level: 'error',\n }\n );\n continue;\n }\n\n const reducedDictionaryContent = reduceDictionaryContent(\n fullDictionary,\n contentDeclarationFile\n );\n\n // write file\n await writeContentDeclaration(\n {\n ...fullDictionary,\n fill: undefined,\n filled: true,\n locale: output.isPerLocale ? output.localeList[0] : undefined,\n content: reducedDictionaryContent.content,\n filePath: output.filePath,\n },\n configuration\n );\n\n if (output.isPerLocale) {\n const sourceLocale = output.localeList[0];\n\n appLogger(\n `Auto filled per-locale content declaration for '${colorizeKey(fullDictionary.key)}' written to ${formatPath(output.filePath)} for locale ${formatLocale(sourceLocale)}`,\n {\n level: 'info',\n }\n );\n } else {\n appLogger(\n `Auto filled content declaration for '${colorizeKey(fullDictionary.key)}' written to ${formatPath(output.filePath)}`,\n {\n level: 'info',\n }\n );\n }\n }\n};\n"],"mappings":";;;;;;AAWA,MAAa,YAAY,OACvB,wBACA,eACA,eACA,kBACG;CACH,MAAM,YAAY,aAAa,cAAc;CAG7C,MAAM,iBAFe,gBAAgB,cAAc,CAEf,uBAAuB;CAE3D,MAAM,WAAW,uBAAuB;AAExC,KAAI,CAAC,UAAU;AACb,YAAU,qCAAqC,EAC7C,OAAO,SACR,CAAC;AACF;;CAGF,MAAM,kBAAkB,eAAe,QAAQ,cAAc,QAAQ;AAErE,KACE,OAAO,oBAAoB,aAC1B,oBAAgC,OACjC;AACA,YACE,8BAA8B,YAAY,eAAe,IAAI,CAAC,IAC9D,EACE,OAAO,QACR,CACF;AACD;;CAOF,MAAMA,eAA2B,eAC/B,kBAJA,iBAAiB,cAAc,qBAAqB,SACpD,QAAQ,WAAW,CAAC,eAAe,SAAS,OAAO,CAAC,EAKpD,UACA,eAAe,KACf,cACD;AAED,YAAW,MAAM,UAAU,cAAc;AACvC,MAAI,CAAC,OAAO,UAAU;AACpB,aACE,+DAA+D,YAAY,eAAe,IAAI,CAAC,IAC/F,EACE,OAAO,SACR,CACF;AACD;;EAGF,MAAM,2BAA2B,wBAC/B,gBACA,uBACD;AAGD,QAAM,wBACJ;GACE,GAAG;GACH,MAAM;GACN,QAAQ;GACR,QAAQ,OAAO,cAAc,OAAO,WAAW,KAAK;GACpD,SAAS,yBAAyB;GAClC,UAAU,OAAO;GAClB,EACD,cACD;AAED,MAAI,OAAO,aAAa;GACtB,MAAM,eAAe,OAAO,WAAW;AAEvC,aACE,mDAAmD,YAAY,eAAe,IAAI,CAAC,eAAe,WAAW,OAAO,SAAS,CAAC,cAAc,aAAa,aAAa,IACtK,EACE,OAAO,QACR,CACF;QAED,WACE,wCAAwC,YAAY,eAAe,IAAI,CAAC,eAAe,WAAW,OAAO,SAAS,IAClH,EACE,OAAO,QACR,CACF"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { formatFillData } from "./formatFillData.mjs";
|
|
2
|
+
import { formatLocale, formatPath, writeContentDeclaration } from "@intlayer/chokidar";
|
|
3
|
+
import { colorizeKey, getAppLogger } from "@intlayer/config";
|
|
4
|
+
import { relative } from "node:path";
|
|
5
|
+
import { getDictionaries } from "@intlayer/dictionaries-entry";
|
|
6
|
+
|
|
7
|
+
//#region src/fill/writeFill.ts
|
|
8
|
+
const writeFill = async (contentDeclarationFile, outputLocales, parentLocales, configuration) => {
|
|
9
|
+
const appLogger = getAppLogger(configuration);
|
|
10
|
+
const fullDictionary = getDictionaries(configuration)[contentDeclarationFile.key];
|
|
11
|
+
const { filePath } = contentDeclarationFile;
|
|
12
|
+
if (!filePath) {
|
|
13
|
+
appLogger("No file path found for dictionary", { level: "error" });
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const autoFillOptions = contentDeclarationFile.fill ?? configuration.content.fill;
|
|
17
|
+
if (typeof autoFillOptions === "boolean" && autoFillOptions === false) {
|
|
18
|
+
appLogger(`Auto fill is disabled for '${colorizeKey(fullDictionary.key)}'`, { level: "info" });
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const autoFillData = formatFillData(autoFillOptions, (outputLocales ?? configuration.internationalization.locales).filter((locale) => !parentLocales?.includes(locale)), filePath, fullDictionary.key, configuration);
|
|
22
|
+
for await (const output of autoFillData) {
|
|
23
|
+
if (!output.filePath) {
|
|
24
|
+
appLogger(`No file path found for auto filled content declaration for '${colorizeKey(fullDictionary.key)}'`, { level: "error" });
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const { fill,...rest } = contentDeclarationFile;
|
|
28
|
+
const relativeFilePath = relative(configuration.content.baseDir, output.filePath);
|
|
29
|
+
await writeContentDeclaration({
|
|
30
|
+
...rest,
|
|
31
|
+
filled: true,
|
|
32
|
+
locale: output.isPerLocale ? output.localeList[0] : void 0,
|
|
33
|
+
localId: `${contentDeclarationFile.key}::local::${relativeFilePath}`,
|
|
34
|
+
filePath: relativeFilePath
|
|
35
|
+
}, configuration, { localeList: output.localeList });
|
|
36
|
+
if (output.isPerLocale) {
|
|
37
|
+
const sourceLocale = output.localeList[0];
|
|
38
|
+
appLogger(`Auto filled per-locale content declaration for '${colorizeKey(fullDictionary.key)}' written to ${formatPath(output.filePath)} for locale ${formatLocale(sourceLocale)}`, { level: "info" });
|
|
39
|
+
} else appLogger(`Auto filled content declaration for '${colorizeKey(fullDictionary.key)}' written to ${formatPath(output.filePath)}`, { level: "info" });
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
//#endregion
|
|
44
|
+
export { writeFill };
|
|
45
|
+
//# sourceMappingURL=writeFill.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writeFill.mjs","names":["autoFillData: FillData[]"],"sources":["../../../src/fill/writeFill.ts"],"sourcesContent":["import { relative } from 'node:path';\nimport {\n formatLocale,\n formatPath,\n writeContentDeclaration,\n} from '@intlayer/chokidar';\nimport { colorizeKey, getAppLogger } from '@intlayer/config';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport type { Dictionary, Fill, IntlayerConfig, Locale } from '@intlayer/types';\nimport { type FillData, formatFillData } from './formatFillData';\n\nexport const writeFill = async (\n contentDeclarationFile: Dictionary,\n outputLocales: Locale[],\n parentLocales: Locale[],\n configuration: IntlayerConfig\n) => {\n const appLogger = getAppLogger(configuration);\n const dictionaries = getDictionaries(configuration);\n\n const fullDictionary = dictionaries[contentDeclarationFile.key];\n\n const { filePath } = contentDeclarationFile;\n\n if (!filePath) {\n appLogger('No file path found for dictionary', {\n level: 'error',\n });\n return;\n }\n\n const autoFillOptions =\n contentDeclarationFile.fill ?? configuration.content.fill;\n\n if (\n typeof autoFillOptions === 'boolean' &&\n (autoFillOptions as boolean) === false\n ) {\n appLogger(\n `Auto fill is disabled for '${colorizeKey(fullDictionary.key)}'`,\n {\n level: 'info',\n }\n );\n return;\n }\n\n const localeList: Locale[] = (\n outputLocales ?? configuration.internationalization.locales\n ).filter((locale) => !parentLocales?.includes(locale));\n\n const autoFillData: FillData[] = formatFillData(\n autoFillOptions as Fill,\n localeList,\n filePath,\n fullDictionary.key,\n configuration\n );\n\n for await (const output of autoFillData) {\n if (!output.filePath) {\n appLogger(\n `No file path found for auto filled content declaration for '${colorizeKey(fullDictionary.key)}'`,\n {\n level: 'error',\n }\n );\n continue;\n }\n\n // biome-ignore lint/correctness/noUnusedVariables: Just filtering out the fill property\n const { fill, ...rest } = contentDeclarationFile;\n\n const relativeFilePath = relative(\n configuration.content.baseDir,\n output.filePath\n );\n\n // write file\n await writeContentDeclaration(\n {\n ...rest,\n filled: true,\n locale: output.isPerLocale ? output.localeList[0] : undefined,\n localId: `${contentDeclarationFile.key}::local::${relativeFilePath}`,\n filePath: relativeFilePath,\n },\n configuration,\n {\n localeList: output.localeList,\n }\n );\n\n if (output.isPerLocale) {\n const sourceLocale = output.localeList[0];\n\n appLogger(\n `Auto filled per-locale content declaration for '${colorizeKey(fullDictionary.key)}' written to ${formatPath(output.filePath)} for locale ${formatLocale(sourceLocale)}`,\n {\n level: 'info',\n }\n );\n } else {\n appLogger(\n `Auto filled content declaration for '${colorizeKey(fullDictionary.key)}' written to ${formatPath(output.filePath)}`,\n {\n level: 'info',\n }\n );\n }\n }\n};\n"],"mappings":";;;;;;;AAWA,MAAa,YAAY,OACvB,wBACA,eACA,eACA,kBACG;CACH,MAAM,YAAY,aAAa,cAAc;CAG7C,MAAM,iBAFe,gBAAgB,cAAc,CAEf,uBAAuB;CAE3D,MAAM,EAAE,aAAa;AAErB,KAAI,CAAC,UAAU;AACb,YAAU,qCAAqC,EAC7C,OAAO,SACR,CAAC;AACF;;CAGF,MAAM,kBACJ,uBAAuB,QAAQ,cAAc,QAAQ;AAEvD,KACE,OAAO,oBAAoB,aAC1B,oBAAgC,OACjC;AACA,YACE,8BAA8B,YAAY,eAAe,IAAI,CAAC,IAC9D,EACE,OAAO,QACR,CACF;AACD;;CAOF,MAAMA,eAA2B,eAC/B,kBAJA,iBAAiB,cAAc,qBAAqB,SACpD,QAAQ,WAAW,CAAC,eAAe,SAAS,OAAO,CAAC,EAKpD,UACA,eAAe,KACf,cACD;AAED,YAAW,MAAM,UAAU,cAAc;AACvC,MAAI,CAAC,OAAO,UAAU;AACpB,aACE,+DAA+D,YAAY,eAAe,IAAI,CAAC,IAC/F,EACE,OAAO,SACR,CACF;AACD;;EAIF,MAAM,EAAE,KAAM,GAAG,SAAS;EAE1B,MAAM,mBAAmB,SACvB,cAAc,QAAQ,SACtB,OAAO,SACR;AAGD,QAAM,wBACJ;GACE,GAAG;GACH,QAAQ;GACR,QAAQ,OAAO,cAAc,OAAO,WAAW,KAAK;GACpD,SAAS,GAAG,uBAAuB,IAAI,WAAW;GAClD,UAAU;GACX,EACD,eACA,EACE,YAAY,OAAO,YACpB,CACF;AAED,MAAI,OAAO,aAAa;GACtB,MAAM,eAAe,OAAO,WAAW;AAEvC,aACE,mDAAmD,YAAY,eAAe,IAAI,CAAC,eAAe,WAAW,OAAO,SAAS,CAAC,cAAc,aAAa,aAAa,IACtK,EACE,OAAO,QACR,CACF;QAED,WACE,wCAAwC,YAAY,eAAe,IAAI,CAAC,eAAe,WAAW,OAAO,SAAS,IAClH,EACE,OAAO,QACR,CACF"}
|
|
@@ -1,55 +1,34 @@
|
|
|
1
1
|
import { listGitFiles } from "@intlayer/chokidar";
|
|
2
2
|
import { getConfiguration } from "@intlayer/config";
|
|
3
|
+
import { join, relative } from "node:path";
|
|
3
4
|
import { getUnmergedDictionaries } from "@intlayer/unmerged-dictionaries-entry";
|
|
4
|
-
|
|
5
|
+
|
|
6
|
+
//#region src/getTargetDictionary.ts
|
|
5
7
|
const ensureArray = (value) => [value].flat();
|
|
6
8
|
const getTargetUnmergedDictionaries = async (options) => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
(dict) => !ensureArray(options.excludedKeys)?.includes(dict.key)
|
|
29
|
-
);
|
|
30
|
-
}
|
|
31
|
-
if (typeof options.pathFilter !== "undefined") {
|
|
32
|
-
result = result.filter(
|
|
33
|
-
(dict) => ensureArray(options.pathFilter)?.includes(dict.filePath ?? "")
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
if (typeof options.filter !== "undefined") {
|
|
37
|
-
result = result.filter(options.filter);
|
|
38
|
-
}
|
|
39
|
-
const gitOptions = options.gitOptions;
|
|
40
|
-
if (gitOptions) {
|
|
41
|
-
const gitChangedFiles = await listGitFiles(gitOptions);
|
|
42
|
-
if (gitChangedFiles) {
|
|
43
|
-
result = result.filter((dict) => {
|
|
44
|
-
if (!dict.filePath) return false;
|
|
45
|
-
return gitChangedFiles.some((gitFile) => dict.filePath === gitFile);
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
return result.filter((dict) => !dict.autoFilled);
|
|
50
|
-
};
|
|
51
|
-
export {
|
|
52
|
-
ensureArray,
|
|
53
|
-
getTargetUnmergedDictionaries
|
|
9
|
+
const configuration = getConfiguration(options?.configOptions);
|
|
10
|
+
const { baseDir } = configuration.content;
|
|
11
|
+
const unmergedDictionariesRecord = getUnmergedDictionaries(configuration);
|
|
12
|
+
let result = Object.values(unmergedDictionariesRecord).flat();
|
|
13
|
+
if (typeof options?.file !== "undefined") {
|
|
14
|
+
const relativeFilePaths = ensureArray(options?.file).map((file) => file.startsWith("/") ? relative(baseDir, file) : join("./", file));
|
|
15
|
+
result = result.filter((dict) => dict.filePath && relativeFilePaths.includes(dict.filePath));
|
|
16
|
+
}
|
|
17
|
+
if (typeof options?.keys !== "undefined") result = result.filter((dict) => ensureArray(options?.keys)?.includes(dict.key));
|
|
18
|
+
if (typeof options?.excludedKeys !== "undefined") result = result.filter((dict) => !ensureArray(options?.excludedKeys)?.includes(dict.key));
|
|
19
|
+
if (typeof options?.pathFilter !== "undefined") result = result.filter((dict) => ensureArray(options?.pathFilter)?.includes(dict.filePath ?? ""));
|
|
20
|
+
if (typeof options?.filter !== "undefined") result = result.filter(options?.filter);
|
|
21
|
+
const gitOptions = options?.gitOptions;
|
|
22
|
+
if (gitOptions) {
|
|
23
|
+
const gitChangedFiles = await listGitFiles(gitOptions);
|
|
24
|
+
if (gitChangedFiles) result = result.filter((dict) => {
|
|
25
|
+
if (!dict.filePath) return false;
|
|
26
|
+
return gitChangedFiles.some((gitFile) => dict.filePath === gitFile);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
return result.filter((dict) => !dict.filled);
|
|
54
30
|
};
|
|
31
|
+
|
|
32
|
+
//#endregion
|
|
33
|
+
export { ensureArray, getTargetUnmergedDictionaries };
|
|
55
34
|
//# sourceMappingURL=getTargetDictionary.mjs.map
|