Skip to content

Commit 28f1af9

Browse files
committed
feat: 🎸 add merge translation files command
1 parent 29e16fa commit 28f1af9

File tree

6 files changed

+209
-0
lines changed

6 files changed

+209
-0
lines changed

schematics/package-lock.json

Lines changed: 23 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

schematics/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,8 @@
2323
"ora": "^3.4.0",
2424
"replace-in-file": "^4.1.2",
2525
"typescript": "~3.4.3"
26+
},
27+
"devDependencies": {
28+
"@types/glob": "^7.1.1"
2629
}
2730
}

schematics/src/collection.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@
3131
"factory": "./upgrade/",
3232
"schema": "./upgrade/schema.json",
3333
"description": "Run an upgrade script."
34+
},
35+
"merge": {
36+
"factory": "./merge/",
37+
"schema": "./merge/schema.json",
38+
"description": "Merge the translation files into one."
3439
}
3540
}
3641
}

schematics/src/merge/index.ts

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import { PathFragment } from '@angular-devkit/core';
2+
import { Rule, Tree, SchematicContext, DirEntry, SchematicsException, EmptyTree } from '@angular-devkit/schematics';
3+
import { from } from 'rxjs';
4+
import { getProject } from '../utils/projects';
5+
import { SchemaOptions } from './schema';
6+
const glob = require('glob');
7+
8+
const p = require('path');
9+
10+
function getFileContent(fileName: PathFragment, dir: DirEntry) {
11+
return JSON.parse(dir.file(fileName).content.toString('utf-8'));
12+
}
13+
14+
function hasSubdirs(dir: DirEntry) {
15+
return dir.subdirs && dir.subdirs.length;
16+
}
17+
18+
function getTranslationKey(prefix = '', key) {
19+
return prefix ? `${prefix}.${key}` : key;
20+
}
21+
22+
function reduceTranslations(host: Tree, dir: DirEntry, translationJson, lang: string, prefix = '') {
23+
if (!hasSubdirs(dir)) return translationJson;
24+
dir.subdirs.forEach(subDirName => {
25+
const subDir = dir.dir(subDirName);
26+
const key = getTranslationKey(prefix, subDirName);
27+
subDir.subfiles
28+
.filter(fileName => fileName.includes(`${lang}.json`))
29+
.forEach(fileName => {
30+
if (translationJson[key]) {
31+
throw new SchematicsException(
32+
`key: ${key} is already exist in translation file, please rename it and rerun the command.`
33+
);
34+
}
35+
translationJson[key] = getFileContent(fileName, subDir);
36+
});
37+
if (hasSubdirs(subDir)) {
38+
reduceTranslations(host, subDir, translationJson, lang, key);
39+
}
40+
});
41+
42+
return translationJson;
43+
}
44+
45+
function reduceTranslations2(path: string, translationJson: object, lang: string, prefix = '') {
46+
glob(path, {}, function(er, files) {
47+
console.log(files);
48+
});
49+
}
50+
51+
function getTranslationsRoot(host: Tree, options: SchemaOptions): string {
52+
const project = getProject(host, options.project);
53+
const rootPath = (project && project.sourceRoot) || 'src';
54+
55+
return options.rootTranslationPath ? options.rootTranslationPath : p.join(rootPath, 'assets', 'i18n');
56+
}
57+
58+
function getRootTranslationFiles(host: Tree, root: string): { lang: string; translation: Object }[] {
59+
const rootDir = host.getDir(root);
60+
return rootDir.subfiles.map(fileName => ({
61+
lang: fileName.split('.')[0],
62+
translation: getFileContent(fileName, rootDir)
63+
}));
64+
}
65+
66+
function getTranslationEntryPaths(options: SchemaOptions, rootDir: string): string[] {
67+
if (Array.isArray(options.translationPaths)) {
68+
return options.translationPaths;
69+
} else if (typeof options.translationPaths === 'string') {
70+
return options.translationPaths.split(',');
71+
}
72+
73+
return [rootDir];
74+
}
75+
76+
export default function(options: SchemaOptions): Rule {
77+
return (host: Tree, context: SchematicContext) => {
78+
const path = process.cwd();
79+
// console.log(p.join(path, 'src/assets/**/*.json'));
80+
// console.log(glob);
81+
// const promise = new Promise((res, rej) => {
82+
//
83+
// glob(`**/*.ts`, {}, function(er, files) {
84+
// console.log(files);
85+
// console.log(er);
86+
// res();
87+
// });
88+
// });
89+
//console.log(a);
90+
const root = getTranslationsRoot(host, options);
91+
const rootTranslations = getRootTranslationFiles(host, root);
92+
const translationEntryPaths = getTranslationEntryPaths(options, root);
93+
94+
const output = rootTranslations.map(t => ({
95+
lang: t.lang,
96+
translation: translationEntryPaths.reduce((acc, path) => {
97+
return reduceTranslations(host, host.getDir(path), t.translation, t.lang);
98+
}, t.translation)
99+
}));
100+
101+
const treeSource = new EmptyTree();
102+
output.forEach(o => {
103+
treeSource.create(`${options.outDir}/${o.lang}.json`, JSON.stringify(o.translation, null, 2));
104+
});
105+
106+
// return from(promise) as any;
107+
return treeSource;
108+
};
109+
}

schematics/src/merge/schema.json

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"$schema": "http://json-schema.org/schema",
3+
"id": "SchematicsTranslocoScope",
4+
"title": "Add new transloco scope module, along with translation files.",
5+
"type": "object",
6+
"properties": {
7+
"rootTranslationPath": {
8+
"type": "string",
9+
"description": "The folder that contain the root translation files.",
10+
"x-prompt": "Enter the root translation files path",
11+
"default": "src/assets/i18n",
12+
"alias": "root"
13+
},
14+
"translationPaths": {
15+
"type": "string",
16+
"description": "A list of all the translation files Path.",
17+
"x-prompt": "Enter all the translation files path containing folder paths",
18+
"default": "src/assets/i18n",
19+
"alias": "paths"
20+
},
21+
"outDir": {
22+
"type": "string",
23+
"description": "The output directory.",
24+
"x-prompt": "Enter output directory path.",
25+
"default": "dist-i18n",
26+
"alias": "o"
27+
},
28+
"translateFormat": {
29+
"type": "string",
30+
"description": "The translation files format.",
31+
"default": "JSON",
32+
"enum": ["JSON", "Typescript"]
33+
},
34+
"project": {
35+
"type": "string",
36+
"description": "The root project name."
37+
}
38+
},
39+
"required": []
40+
}

schematics/src/merge/schema.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { Schema } from '@schematics/angular/module/schema';
2+
3+
export enum TranslationFileTypes {
4+
Typescript = 'Typescript',
5+
JSON = 'JSON'
6+
}
7+
8+
export interface SchemaOptions extends Schema {
9+
/**
10+
* The folder that contain the root translation files.
11+
*/
12+
rootTranslationPath: string;
13+
/**
14+
* A list of all the translation files Path.
15+
*/
16+
translationPaths: string | string[];
17+
/**
18+
* The output directory.
19+
*/
20+
outDir: string;
21+
/**
22+
* The translation files format.
23+
*/
24+
translateFormat: TranslationFileTypes;
25+
/**
26+
* The root project name.
27+
*/
28+
project: string;
29+
}

0 commit comments

Comments
 (0)