UNPKG

generator-begcode

Version:

Spring Boot + Angular/React/Vue in one handy generator

176 lines (175 loc) 9.45 kB
import { extname } from 'node:path'; import { passthrough } from '@yeoman/transform'; import { Minimatch } from 'minimatch'; import { createJhiTransformTranslateReplacer, createJhiTransformTranslateStringifyReplacer, createJhiTranslateReplacer, escapeHtmlTranslationValue, escapeTsTranslationValue, } from '../../languages/support/index.js'; const PLACEHOLDER_REGEX = /(?:placeholder|title)=['|"](\{\{\s?['|"]([a-zA-Z0-9.\-_]+)['|"]\s?\|\s?translate\s?\}\})['|"]/.source; const JHI_TRANSLATE_REGEX = /(\n?\s*[a-z][a-zA-Z]*Translate="[a-zA-Z0-9 +{}'_!?.]+")/.source; const TRANSLATE_VALUES_REGEX = /(\n?\s*\[translateValues\]="\{(?:(?!\}").)*?\}")/.source; const TRANSLATE_REGEX = [JHI_TRANSLATE_REGEX, TRANSLATE_VALUES_REGEX].join('|'); function replaceTranslationKeysWithText(getWebappTranslation, content, regexSource, { keyIndex = 1, replacementIndex = 1, escape, } = {}) { const regex = new RegExp(regexSource, 'g'); const allMatches = content.matchAll(regex); for (const match of allMatches) { const key = match[keyIndex]; const target = match[replacementIndex]; let translation = getWebappTranslation(key); if (escape) { translation = escape(translation, match); } content = content.replace(target, translation); } return content; } function replaceJSTranslation(getWebappTranslation, content, jsKey) { return replaceTranslationKeysWithText(getWebappTranslation, content, `${jsKey}\\s?:\\s?['|"]([a-zA-Z0-9.\\-_]+\\.[a-zA-Z0-9.\\-_]+)['|"]`, { escape: (translation, match) => translation.replaceAll(match[0].slice(-1), `\\${match[0].slice(-1)}`), }); } function replacePageTitles(getWebappTranslation, content) { return replaceJSTranslation(getWebappTranslation, content, 'title'); } function replacePlaceholders(getWebappTranslation, content) { return replaceTranslationKeysWithText(getWebappTranslation, content, PLACEHOLDER_REGEX, { keyIndex: 2 }); } function replaceErrorMessage(getWebappTranslation, content) { return replaceJSTranslation(getWebappTranslation, content, 'errorMessage'); } const tagTranslation = (getWebappTranslation, { enableTranslation, jhiPrefix }, { key, parsedInterpolate, prefix, suffix }) => { const translatedValueInterpolate = parsedInterpolate ? Object.fromEntries(Object.entries(parsedInterpolate).map(([key, value]) => [key, `{{ ${value} }}`])) : undefined; const translatedValue = escapeHtmlTranslationValue(getWebappTranslation(key, translatedValueInterpolate)); if (enableTranslation) { const translateValuesAttr = parsedInterpolate ? ` [translateValues]="{ ${Object.entries(parsedInterpolate) .map(([key, value]) => `${key}: ${value}`) .join(', ')} }"` : ''; return ` ${jhiPrefix}Translate="${key}"${translateValuesAttr}${prefix}${translatedValue}${suffix}`; } return `${prefix}${translatedValue}${suffix}`; }; const validationTagTranslation = (getWebappTranslation, { enableTranslation, jhiPrefix }, { key, parsedInterpolate, prefix, suffix }) => { if (!parsedInterpolate || Object.keys(parsedInterpolate).length === 0) { throw new Error(`No interpolation values found for translation key ${key}, use __jhiTranslateTag__ instead.`); } const translatedValue = escapeHtmlTranslationValue(getWebappTranslation(key, parsedInterpolate)); if (enableTranslation) { const translateValuesAttr = parsedInterpolate ? ` [translateValues]="{ ${Object.entries(parsedInterpolate) .map(([key, value]) => `${key}: '${value}'`) .join(', ')} }"` : ''; return ` ${jhiPrefix}Translate="${key}"${translateValuesAttr}${prefix}${translatedValue}${suffix}`; } return `${prefix}${translatedValue}${suffix}`; }; const tagPipeTranslation = (getWebappTranslation, { enableTranslation, jhiPrefix }, { key, parsedInterpolate, prefix, suffix }) => { if (!parsedInterpolate || Object.keys(parsedInterpolate).length === 0) { throw new Error(`No interpolation values found for translation key ${key}, use __jhiTranslateTag__ instead.`); } const translatedValueInterpolate = Object.fromEntries(Object.entries(parsedInterpolate).map(([key, value]) => [key, getWebappTranslation(value)])); const translatedValue = escapeHtmlTranslationValue(getWebappTranslation(key, translatedValueInterpolate)); if (enableTranslation) { const translateValuesAttr = ` [translateValues]="{ ${Object.entries(parsedInterpolate) .map(([key, value]) => `${key}: ('${value}' | translate)`) .join(', ')} }"`; return ` ${jhiPrefix}Translate="${key}"${translateValuesAttr}${prefix}${translatedValue}${suffix}`; } return `${prefix}${translatedValue}${suffix}`; }; const tagEnumTranslation = (getWebappTranslation, { enableTranslation, jhiPrefix }, { key, parsedInterpolate, prefix, suffix }) => { if (!parsedInterpolate?.value) { throw new Error(`Value is required for TagEnum ${key}.`); } const { value, fallback } = parsedInterpolate; const translatedValue = `{{ ${JSON.stringify(getWebappTranslation(key))}[${value}]${fallback ? ` || ${fallback}` : ''} }}`; if (enableTranslation) { return ` [${jhiPrefix}Translate]="'${key}.' + (${parsedInterpolate?.value})"${prefix}${translatedValue}${suffix}`; } return `${prefix}${translatedValue}${suffix}`; }; const pipeTranslation = (getWebappTranslation, { enableTranslation }, { key, prefix, suffix }) => { if (enableTranslation) { return `${prefix}{{ '${key}' | translate }}${suffix}`; } return `${prefix}${escapeHtmlTranslationValue(getWebappTranslation(key))}${suffix}`; }; const valueTranslation = (getWebappTranslation, _replacerOptions, { filePath, key, prefix, suffix }) => { let translationValue = getWebappTranslation(key); const fileExtension = extname(filePath); if (fileExtension === '.html') { translationValue = escapeHtmlTranslationValue(translationValue); } else if (fileExtension === '.ts') { translationValue = escapeTsTranslationValue(translationValue); } return `${prefix}${translationValue}${suffix}`; }; const pipeEnumTranslation = (getWebappTranslation, { enableTranslation }, { key, parsedInterpolate, prefix, suffix }) => { if (!parsedInterpolate?.value) { throw new Error(`Value is required for TagEnum ${key}.`); } const { value, fallback } = parsedInterpolate; if (enableTranslation) { return `${prefix}{{ '${key}.' + ${value} | translate }}${suffix}`; } const translatedValue = `{{ ${JSON.stringify(getWebappTranslation(key))}[${value}]${fallback ? ` ?? ${fallback}` : ''} }}`; return `${prefix}${translatedValue}${suffix}`; }; const replaceImplementations = { Tag: tagTranslation, TagPipe: tagPipeTranslation, TagEnum: tagEnumTranslation, ValidationTag: validationTagTranslation, Pipe: pipeTranslation, PipeEnum: pipeEnumTranslation, Value: valueTranslation, }; export const createTranslationReplacer = (getWebappTranslation, opts) => { const htmlJhiTranslateReplacer = createJhiTransformTranslateReplacer(getWebappTranslation, { escapeHtml: true }); const htmlJhiTranslateStringifyReplacer = createJhiTransformTranslateStringifyReplacer(getWebappTranslation); let translationReplacer; const enableTranslation = typeof opts === 'boolean' ? opts : opts.enableTranslation; if (typeof opts !== 'boolean') { translationReplacer = createJhiTranslateReplacer(optsReplacer => { const replacer = replaceImplementations[optsReplacer.type] ?? (() => { throw new Error(`Translation type not supported ${optsReplacer.type}`); }); return replacer(getWebappTranslation, opts, optsReplacer); }, { prefixPattern: '>\\s*', suffixPattern: '\\s*<' }); } return function replaceAngularTranslations(content, filePath) { if (filePath.endsWith('.html')) { if (!enableTranslation) { content = content.replace(new RegExp(TRANSLATE_REGEX, 'g'), ''); content = replacePlaceholders(getWebappTranslation, content); } } if (/(:?\.html|component\.ts)$/.test(filePath)) { content = htmlJhiTranslateReplacer(content); content = htmlJhiTranslateStringifyReplacer(content); } if (/(:?\.html|.ts)$/.test(filePath)) { content = translationReplacer ? translationReplacer?.(content, filePath) : content; } if (!enableTranslation) { if (/(:?route|module)\.ts$/.test(filePath)) { content = replacePageTitles(getWebappTranslation, content); } if (filePath.endsWith('error.route.ts')) { content = replaceErrorMessage(getWebappTranslation, content); } } return content; }; }; const minimatch = new Minimatch('**/*{.html,.ts}'); export const isTranslatedAngularFile = file => minimatch.match(file.path); export const translateAngularFilesTransform = (getWebappTranslation, opts) => { const translate = createTranslationReplacer(getWebappTranslation, opts); return passthrough(file => { file.contents = Buffer.from(translate(file.contents.toString(), file.path)); }); };