@ngneat/transloco
Version:
The internationalization (i18n) library for Angular
161 lines • 7.49 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const ora = require('ora');
const replace = require('replace-in-file');
const p = require('path');
// Example: `./src/ng2/**/*.html`;
function run(path) {
console.log('\x1b[4m%s\x1b[0m', '\nStarting migration script');
const dir = p.resolve(process.cwd());
path = p.join(dir, path, '/**/*');
const noSpecFiles = { ignore: `${path}spec.ts`, files: `${path}.ts` };
const pipeContent = `\\s*([^}\\r\\n]*?\\|)\\s*(translate)\\s*(?::\\s*{[^}\\r\\n]+})?\\s*(\\s*\\|[\\s\\r\\t\\n]*\\w*)*\\s*`;
const [directive, pipe, pipeInBinding] = [
/(translate|\[translate(?:Params)?\])=("|')[^"']*\2/gm,
new RegExp(`{{${pipeContent}}}`, 'gm'),
new RegExp(`\\]=('|")${pipeContent}\\1`, 'gm')
].map(regex => ({
files: `${path}.html`,
from: regex,
to: match => match.replace('translate', 'transloco')
}));
const moduleMultiImport = {
files: `${path}.ts`,
from: /import\s*{((([^,}]*,)+\s*(TranslateModule)\s*(,[^}]*)*)|(([^,{}]*,)*\s*(TranslateModule)\s*,\s*[a-zA-Z0-9]+(,[^}]*)*))\s*}\s*from\s*('|").?ngx-translate(\/[^'"]+)?('|");?/g,
to: match => match
.replace('TranslateModule', '')
.replace(/,\s*,/, ',')
.replace(/{\s*,/, '{')
.replace(/,\s*}/, '}')
.concat(`\nimport { TranslocoModule } from '@ngneat/transloco';`)
};
const moduleSingleImport = {
files: `${path}.ts`,
from: /import\s*{\s*(TranslateModule),?\s*}\s*from\s*('|").?ngx-translate(\/[^'"]+)?('|");?/g,
to: `import { TranslocoModule } from '@ngneat/transloco';`
};
const modules = {
files: `${path}.ts`,
from: /(?<![a-zA-Z])TranslateModule(?![^]*from)(\.(forRoot|forChild)\(({[^}]*})*[^)]*\))?/g,
to: 'TranslocoModule'
};
const serviceMultiImport = {
files: `${path}.ts`,
from: /import\s*{((([^,}]*,)+\s*(TranslateService)\s*(,[^}]*)*)|(([^,{}]*,)*\s*(TranslateService)\s*,\s*[a-zA-Z0-9]+(,[^}]*)*))\s*}\s*from\s*('|").?ngx-translate(\/[^'"]+)?('|");?/g,
to: match => match
.replace('TranslateService', '')
.replace(/,\s*,/, ',')
.replace(/{\s*,/, '{')
.replace(/,\s*}/, '}')
.concat(`\nimport { TranslocoService } from '@ngneat/transloco';`)
};
const [serviceSingleImport, pipeImport] = [
/import\s*{\s*(TranslateService),?\s*}\s*from\s*('|").?ngx-translate(\/[^'"]+)?('|");?/g,
/import\s*{\s*(TranslatePipe),?\s*}\s*from\s*('|")[^'"]+('|");?/g
].map(regex => (Object.assign({}, noSpecFiles, { from: regex, to: `import { TranslocoService } from '@ngneat/transloco';` })));
const constructorInjection = Object.assign({}, noSpecFiles, { from: /(?:private|protected|public)\s+(.*?)\s*:\s*(?:TranslateService|TranslatePipe\s*(?:,|\)))/g, to: match => match.replace(/TranslateService|TranslatePipe/g, 'TranslocoService') });
const serviceUsage = Object.assign({}, noSpecFiles, { from: /(?=([^]+(?:private|protected|public)\s+([^,:()]+)\s*:\s*(?:TranslocoService\s*(?:,|\)))))\1[^]*/gm, to: (match, _, serviceName) => {
const sanitizedName = serviceName
.split('')
.map(char => (['$', '^'].includes(char) ? `\\${char}` : char))
.join('');
const functionsMap = {
instant: 'translate',
transform: 'translate',
get: 'selectTranslate',
stream: 'selectTranslate',
use: 'setActiveLang',
set: 'setTranslation'
};
const propsMap = {
currentLang: 'getActiveLang()',
onLangChange: 'langChanges$'
};
const serviceCallRgx = ({ map, func }) => new RegExp(`(?:(?:\\s*|this\\.)${sanitizedName})(?:\\s*\\t*\\r*\\n*)*\\.(?:\\s*\\t*\\r*\\n*)*(${getTarget(map)})[\\r\\t\\n\\s]*${func ? '\\(' : '(?!\\()'}`, 'g');
const getTarget = t => Object.keys(t).join('|');
return [{ func: true, map: functionsMap }, { func: false, map: propsMap }].reduce((acc, curr) => {
return acc.replace(serviceCallRgx(curr), str => str.replace(new RegExp(getTarget(curr.map)), func => curr.map[func]));
}, match);
} });
const specs = {
files: `${path}spec.ts`,
from: /TranslateService|TranslatePipe/g,
to: 'TranslocoService'
};
const htmlReplacements = [
{
matchers: [directive],
step: 'directives'
},
{
matchers: [pipe, pipeInBinding],
step: 'pipes'
}
];
const tsReplacements = [
{
matchers: [modules, moduleMultiImport, moduleSingleImport],
step: 'modules'
},
{
matchers: [serviceMultiImport, serviceSingleImport, pipeImport],
step: 'service imports'
},
{
matchers: [constructorInjection],
step: 'constructor injections'
},
{
matchers: [serviceUsage],
step: 'service usage'
},
{
matchers: [specs],
step: 'specs'
}
];
function migrate(matchersArr, filesType) {
return __awaiter(this, void 0, void 0, function* () {
console.log(`\nMigrating ${filesType} files 📜`);
let spinner;
for (let i = 0; i < matchersArr.length; i++) {
let { step, matchers } = matchersArr[i];
const msg = `Step ${i + 1}/${matchersArr.length}: Migrating ${step}`;
spinner = ora().start(msg);
const noFilesFound = [];
for (let matcher of matchers) {
try {
yield replace(matcher);
}
catch (e) {
if (e.message.includes('No files match the pattern')) {
noFilesFound.push(e.message);
}
else {
throw e;
}
}
}
spinner.succeed(msg);
noFilesFound.forEach(pattern => console.log('\x1b[33m%s\x1b[0m', `⚠️ ${pattern}`));
}
});
}
return migrate(htmlReplacements, 'HTML')
.then(() => migrate(tsReplacements, 'TS'))
.then(() => {
console.log('\n 🌵 Done! 🌵');
console.log('Welcome to a better translation experience 🌐');
console.log('\nFor more information about this script please visit 👉 https://ngneat.github.io/transloco/docs/migration/ngx\n');
});
}
exports.run = run;
//# sourceMappingURL=ngx-translate-migration.js.map