auto-lang 1.0.2 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -1,19 +1,22 @@
1
1
  # Auto Lang
2
2
 
3
- Generate translation files for multiple languages
3
+ Generate translation files for multiple languages.
4
+
5
+ Write once for a single language and automatically get translated json files for others.
4
6
  ## Installation
5
- ### npm
6
- ```npm i auto-lang```
7
- ### yarn
8
- ```yarn install auto-lang```
7
+ ### Using npm
8
+ $ npm install auto-lang
9
+ ### Using yarn
10
+ $ yarn add auto-lang
9
11
 
10
12
  ## Usage
11
13
  Run `auto-lang [options]`
12
14
 
13
15
  ### Options
14
16
 
15
- -V, --version output the version number
16
- -f, --from <lang> language to translate from
17
- -t, --to <lang...> Languages to translate to (Seperated by space)
18
- -g, --gen-types generate typescript declaration file
19
- -h, --help display help for command
17
+ -V, --version output the version number
18
+ -f, --from <lang> language to translate from
19
+ -t, --to <lang...> languages to translate to (seperated by space)
20
+ -d, --dir <directory> directory containing the language files (default: "translations")
21
+ -g, --gen-type <lang> generate types from language file
22
+ -h, --help display help for command
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "auto-lang",
3
- "version": "1.0.2",
3
+ "version": "1.0.5",
4
4
  "description": "Automatically create language json files for internationalization",
5
5
  "main": "./src/index.js",
6
6
  "scripts": {
7
7
  "test": "echo \"Error: no test specified\" && exit 1"
8
8
  },
9
- "keywords": ["Internationalization", "node", "i18n"],
9
+ "keywords": ["Internationalization", "node", "i18n", "translate"],
10
10
  "author": "Lafen Lesley <lesleytech6@gmail.com> (https://github.com/lesleytech/)",
11
11
  "homepage": "https://github.com/lesleytech/auto-lang#readme",
12
12
  "repository": {
package/src/index.js CHANGED
@@ -11,6 +11,10 @@ import JsonToTS from 'json-to-ts';
11
11
  import prettier from 'prettier';
12
12
 
13
13
  import { Logger } from './utils/Logger.mjs';
14
+ import chalk from 'chalk';
15
+ import { validateOptions } from './utils/validation.mjs';
16
+
17
+ const APP_VERSION = '1.0.5';
14
18
 
15
19
  const program = new Command();
16
20
  const nodeMajVer = parseInt(process.version.substring(1).split('.')[0]);
@@ -23,24 +27,28 @@ if (nodeMajVer < 14) {
23
27
 
24
28
  program
25
29
  .name('auto-lang')
26
- .description('Generate translation files for multiple languages')
27
- .version('1.0.2')
28
- .requiredOption('-f, --from <lang>', 'language to translate from')
29
- .requiredOption(
30
+ .description('Generate translation files for multiple languages (i18n)')
31
+ .version(APP_VERSION)
32
+ .option('-f, --from <lang>', 'language to translate from')
33
+ .option(
30
34
  '-t, --to <lang...>',
31
- 'Languages to translate to (Seperated by space)'
35
+ 'languages to translate to (seperated by space)'
36
+ )
37
+ .option(
38
+ '-d, --dir <directory>',
39
+ 'directory containing the language files',
40
+ 'translations'
32
41
  )
33
- .option('-g, --gen-types', 'generate typescript declaration file')
42
+ .option('-g, --gen-type <lang>', 'generate types from language file')
34
43
  .parse();
35
44
 
36
- const { from, to, genTypes } = program.opts();
37
-
38
- const inputFile = path.join(process.cwd(), 'translations', `${from}.json`);
45
+ const { from, to, genType, inputFile, genTypeFile, dir } = validateOptions(
46
+ program.opts()
47
+ );
39
48
 
40
- if (!existsSync(inputFile)) {
41
- Logger.error(`File 'translations/${from}.json' not found`);
42
- exit(1);
43
- }
49
+ const inputJson = JSON.parse(
50
+ await fs.readFile(inputFile, { encoding: 'utf-8' })
51
+ );
44
52
 
45
53
  async function makeTranslatedCopy(obj1, obj2, options) {
46
54
  for (let [key, value] of Object.entries(obj1)) {
@@ -48,12 +56,18 @@ async function makeTranslatedCopy(obj1, obj2, options) {
48
56
  obj2[key] = {};
49
57
  await makeTranslatedCopy(value, obj2[key], options);
50
58
  } else {
51
- obj2[key] = await translate(value, { from, to: options.to });
59
+ try {
60
+ obj2[key] = await translate(value, { from, to: options.to });
61
+ } catch (err) {
62
+ console.log('\n');
63
+ Logger.error(err.message);
64
+ exit(1);
65
+ }
52
66
  }
53
67
  }
54
68
  }
55
69
 
56
- const getTranslation = (inputJson, language) =>
70
+ const getTranslation = (language) =>
57
71
  new Promise(async (resolve, reject) => {
58
72
  const translatedObj = {};
59
73
 
@@ -62,58 +76,58 @@ const getTranslation = (inputJson, language) =>
62
76
  resolve(JSON.stringify(translatedObj, null, 4));
63
77
  });
64
78
 
65
- async function createDeclarationFile(json) {
66
- const spinner = createSpinner('Creating typescript declaration file').start();
79
+ async function createDeclarationFile() {
80
+ const spinner = createSpinner('Creating language type file').start();
67
81
 
68
- const interfaces = JsonToTS(json, { rootName: 'GlobalTranslation' });
69
- const typesDir = path.join(process.cwd(), 'translations', 'types');
82
+ const interfaces = JsonToTS(inputJson, { rootName: 'GlobalTranslationType' });
83
+ const typesDir = path.join(process.cwd(), dir, 'types');
70
84
 
71
85
  if (!existsSync(typesDir)) {
72
86
  fs.mkdir(typesDir);
73
87
  }
74
88
 
75
- const declarationFile = path.join(typesDir, 'index.d.ts');
89
+ const declarationFile = path.join(typesDir, 'index.ts');
76
90
 
77
91
  const result = `
78
92
  /* eslint-disable no-var */
79
93
 
80
- declare global {
81
- ${interfaces[0]}\n\n
82
- }
83
-
84
- ${interfaces.slice(1).join('\n\n')}
94
+ type NestedKeyOf<ObjectType extends object> = {
95
+ [Key in keyof ObjectType & string]: ObjectType[Key] extends object
96
+ ? // @ts-ignore
97
+ \`$\{Key}.$\{NestedKeyOf<ObjectType[Key]>}\`
98
+ : \`$\{Key}\`
99
+ }[keyof ObjectType & string]
85
100
 
86
- export {};
101
+ export type GlobalTranslation = NestedKeyOf<GlobalTranslationType>;
102
+
103
+ ${interfaces.join('\n\n')}
87
104
  `;
88
105
 
89
106
  const formattedResult = prettier.format(result, { parser: 'typescript' });
90
107
 
91
108
  fs.writeFile(declarationFile, formattedResult);
92
- spinner.success({ text: 'TS declaration file created' });
109
+ spinner.success({ text: 'Language type file created' });
93
110
  }
94
111
 
95
- async function translateFile(inputFile) {
96
- const inputJson = JSON.parse(
97
- await fs.readFile(inputFile, { encoding: 'utf-8' })
98
- );
112
+ async function translateFile() {
99
113
  let spinner, langFile, tranlatedJson;
100
114
 
101
115
  for (let lang of to) {
102
- langFile = path.join(process.cwd(), 'translations', `${lang}.json`);
116
+ langFile = path.join(process.cwd(), dir, `${lang}.json`);
103
117
  spinner = createSpinner(`Translating to ${lang}...`).start();
104
118
 
105
- tranlatedJson = await getTranslation(inputJson, lang);
119
+ tranlatedJson = await getTranslation(lang);
106
120
  // await sleep(1000);
107
121
  await fs.writeFile(langFile, tranlatedJson);
108
122
 
109
123
  spinner.success({ text: `Complete` });
110
124
  }
111
-
112
- return inputJson;
113
125
  }
114
126
 
115
- const json = await translateFile(inputFile);
127
+ if (from && to) {
128
+ await translateFile();
129
+ }
116
130
 
117
- if (genTypes) {
118
- await createDeclarationFile(json);
131
+ if (genType) {
132
+ await createDeclarationFile();
119
133
  }
package/src/test.ts ADDED
@@ -0,0 +1,3 @@
1
+ import { GlobalTranslation } from './translations/types';
2
+
3
+ const t = (key: GlobalTranslation) => {};
@@ -0,0 +1,37 @@
1
+ import chalk from 'chalk';
2
+ import { existsSync } from 'fs';
3
+ import path from 'path';
4
+
5
+ import { Logger } from './Logger.mjs';
6
+
7
+ export function validateOptions(opts) {
8
+ if (!Object.keys(opts).length) {
9
+ Logger.error(`Invalid arguments. Use ${chalk.gray('--help')} for usage`);
10
+
11
+ exit(1);
12
+ }
13
+
14
+ const { to, from, dir, genType } = opts;
15
+
16
+ if ((from && !to) || (to && !from)) {
17
+ Logger.error(
18
+ `${chalk.gray('--from')} and ${chalk.gray('--to')} are dependent options`
19
+ );
20
+ exit(1);
21
+ }
22
+
23
+ const inputFile = path.join(process.cwd(), dir, `${from}.json`);
24
+ const genTypeFile = path.join(process.cwd(), dir, `${genType}.json`);
25
+
26
+ if (!existsSync(inputFile) && from) {
27
+ Logger.error(`File "${inputFile}" not found`);
28
+ exit(1);
29
+ }
30
+
31
+ if (!existsSync(genTypeFile) && genType) {
32
+ Logger.error(`File "${genType}" not found`);
33
+ exit(1);
34
+ }
35
+
36
+ return { ...opts, inputFile, genTypeFile };
37
+ }