UNPKG

@ui5/task-adaptation

Version:

Custom task for ui5-builder which allows building UI5 Flexibility Adaptation Projects for SAP BTP, Cloud Foundry environment

99 lines 5.98 kB
import { dotToUnderscore, escapeRegex, removePropertiesExtension } from "./commonUtil.js"; import ResourceUtil from "./resourceUtil.js"; import { posix as path } from "path"; export default class I18NMerger { static analyzeAppVariantManifestChanges(rootFolder, tranlsationRegexPattern, { changes }) { // check which files need to be copied and which files need to be merged and copied // this is necessary because lrep does not support multiple enhanceWith with multiple locations const mergePaths = new Set(); const copyPaths = new Set(); changes.forEach((change) => { const i18nPathWithExtension = change.content?.bundleUrl || change.texts?.i18n; if (i18nPathWithExtension) { // build regex to match specific + language related files const i18nPath = removePropertiesExtension(i18nPathWithExtension); const resourcePath = path.join(rootFolder, i18nPath); const regex = new RegExp(escapeRegex(resourcePath) + tranlsationRegexPattern); if (change.changeType.includes("addNewModelEnhanceWith")) { copyPaths.add(regex); } else { mergePaths.add(regex); } } }); return { mergePathsRegex: [...mergePaths.values()], copyPathsRegex: [...copyPaths.values()] }; } static async mergeI18NFiles(baseAppResources, appVariantResources, projectNamespace, baseAppManifestI18NPath, appVariantInfo, taskUtil) { const aggregatedResourceFilesMap = new Map(baseAppResources.map(baseAppResource => [baseAppResource.getPath(), baseAppResource])); const i18nTargetFolder = dotToUnderscore(appVariantInfo.id); const rootFolder = ResourceUtil.getRootFolder(projectNamespace); const tranlsationRegexPattern = "((_[a-z]{2,3})?(_[a-zA-Z]{2,3}(_[a-zA-Z]{2,20})?)?)\.properties$"; const { copyPathsRegex: copyPathsValues, mergePathsRegex: mergePathsValues } = this.analyzeAppVariantManifestChanges(rootFolder, tranlsationRegexPattern, appVariantInfo); for (const appVariantResource of appVariantResources) { const appVariantResourcePath = appVariantResource.getPath(); if (appVariantResourcePath.endsWith(".properties")) { // merge/copy logic // check if file matches with regex in merge/copy const mergePathMatch = mergePathsValues.map(path => appVariantResourcePath.match(path)).find(match => match); const shouldMergeFile = !!mergePathMatch; const shouldCopyFile = copyPathsValues.map(path => appVariantResourcePath.match(path)).find(match => match); if (shouldMergeFile) { let baseAppI18NPath = `${rootFolder}/${baseAppManifestI18NPath}${mergePathMatch[1] || ""}.properties`; await this.mergePropertiesFiles(aggregatedResourceFilesMap, appVariantResource, baseAppI18NPath); } // Resource for to be copied file already exists so we only have to adjust path // Otherwise we have to omit it. We always change the path to avoid omitting a base app file this.moveToAppVarSubfolder(appVariantResource, rootFolder, i18nTargetFolder); if (!shouldCopyFile) { taskUtil.setTag(appVariantResource, taskUtil.STANDARD_TAGS.OmitFromBuildResult, true); } } aggregatedResourceFilesMap.set(appVariantResource.getPath(), appVariantResource); } return Array.from(aggregatedResourceFilesMap.values()); } /** * Merge/Append base property file with property file from app variant * FIXME Currently merge could duplicate keys which causes undefined * behavior => Existing keys which are in merge content must be removed => * Actually only descriptor texts are relevant for merge which always have * app variant Id as prefix => If we filter on them we do not need to remove * existing overwritten keys (as there should be none) */ static async mergePropertiesFiles(aggregatedResourceFilesMap, variantResource, baseAppI18NPath) { const baseAppI18NFile = aggregatedResourceFilesMap.get(baseAppI18NPath); if (baseAppI18NFile) { await this.mergeFiles(baseAppI18NFile, variantResource); } else { // create the merge target file if it missing in base app. Maybe the language does not exist in the base app. // Since the file might also be copied we do not just change the path of it but create another resource await this.createFile(aggregatedResourceFilesMap, baseAppI18NPath, variantResource); } } /** * update the path of app variant property file so it will be copied into <app_variant_id> folder */ static moveToAppVarSubfolder(variantResource, rootFolder, i18nBundleName) { const relativeFilePath = variantResource.getPath().substring(rootFolder.length); const newResourcePath = path.join(rootFolder, i18nBundleName, relativeFilePath); variantResource.setPath(newResourcePath); } /** * create new i18n file in case e.g. translation file does not exist in base * app but in variant and copy of translation file is needed */ static async createFile(aggregatedResourceFilesMap, path, resource) { const createdFile = await resource.clone(); createdFile.setPath(path); aggregatedResourceFilesMap.set(path, createdFile); } static async mergeFiles(baseFile, variantFile) { const variantFileContent = await variantFile.getString(); const mergedFileContent = await baseFile.getString(); baseFile.setString(`${mergedFileContent}\n\n#App variant specific text file\n\n${variantFileContent}`); } } //# sourceMappingURL=i18nMerger.js.map