1 | #!/usr/bin/env node
|
2 |
|
3 |
|
4 |
|
5 | const fs = require("fs-extra");
|
6 | const path = require("path");
|
7 | const chalk = require("chalk");
|
8 | const yargs = require("yargs");
|
9 | const R = require("ramda");
|
10 |
|
11 | const collectKeys = require("./scripts/collectKeys");
|
12 | const fetchBrandConfig = require("./scripts/fetchBrandConfig");
|
13 | const fetchSpreadsheet = require("./scripts/fetchSpreadsheet");
|
14 | const { getTranslations, getTranslationsGranular } = require("./scripts/getTranslations");
|
15 | const missingKeys = require("./scripts/missingKeys");
|
16 | const { mapLanguages, mapLanguagesGran } = require("./scripts/mapLanguages");
|
17 |
|
18 | const command = process.argv[2];
|
19 |
|
20 | const OUT = path.join(process.cwd(), "data");
|
21 | const TKEYS = path.join(OUT, "tkeys.json");
|
22 |
|
23 | function log(what) {
|
24 | console.log(`${chalk.bold.green(">")} ${what}`);
|
25 | }
|
26 |
|
27 | function error(what) {
|
28 | console.log(`${chalk.bold.red(">")} ${what}`);
|
29 | }
|
30 |
|
31 |
|
32 | const sortKeys = obj =>
|
33 | Object.keys(obj)
|
34 | .sort()
|
35 | .reduce((acc, key) => ({ ...acc, [key]: obj[key] }), {});
|
36 |
|
37 | const resolve = glob => path.join(process.cwd(), glob);
|
38 |
|
39 | const commands = {
|
40 | keys: "keys",
|
41 | "keys-check": "keys-check",
|
42 | translations: "translations",
|
43 | fetch: "fetch",
|
44 | };
|
45 |
|
46 | const commandOptionsMap = {
|
47 | keys: {
|
48 | "--no-nitro": "nitro",
|
49 | },
|
50 | };
|
51 |
|
52 | log(chalk.bold.green("NITRO"));
|
53 | if (!commands[command]) {
|
54 | log("Available commands:");
|
55 | log(` ${chalk.underline.bold("keys")} [...globs] - collects translation keys`);
|
56 | log(` ${chalk.underline("...globs")} - where to collect keys from`);
|
57 | log("");
|
58 | log(` ${chalk.underline.bold("keys-check")} - checks missing translations`);
|
59 | log("");
|
60 | log(` ${chalk.underline.bold("translations")} [--path] - fetches translations`);
|
61 | log(` ${chalk.underline("--path")} (optional) - where to take translations from`);
|
62 | log("");
|
63 | log(` ${chalk.underline.bold("fetch")} - fetches production data`);
|
64 | log("");
|
65 | log("See CLI docs for details at https://github.com/kiwicom/nitrolib");
|
66 | }
|
67 |
|
68 | function keys(globs, shouldExcludeNitroTranslations) {
|
69 | const ours = shouldExcludeNitroTranslations
|
70 | ? []
|
71 | : JSON.parse(fs.readFileSync(path.join(__dirname, "../tkeys.json")));
|
72 |
|
73 | const collected = collectKeys(globs.map(resolve));
|
74 |
|
75 | const data = sortKeys(R.merge(ours, collected));
|
76 | fs.outputJsonSync(path.join(OUT, "tkeys.json"), data, {
|
77 | spaces: 2,
|
78 | });
|
79 |
|
80 | log(
|
81 | `DONE! Collected ${Object.keys(data).length} keys, out of which ${
|
82 | Object.keys(collected).length
|
83 | } are your own.`,
|
84 | );
|
85 | }
|
86 |
|
87 | function keysCheck() {
|
88 | const TFILES = path.join(OUT, "translationsFiles.json");
|
89 | if (!fs.existsSync(TFILES)) {
|
90 | error(
|
91 | "Key checking requires the 'data/translationsFiles.json' file. Run 'nitro translations'.",
|
92 | );
|
93 | process.exit(1);
|
94 | return;
|
95 | }
|
96 |
|
97 | if (!fs.existsSync(TKEYS)) {
|
98 | error(
|
99 | "'fetch' requires collecting translation keys to a 'data/tkeys.json' file! This can be done using the 'nitro keys <globs>' command.",
|
100 | );
|
101 | process.exit(1);
|
102 | return;
|
103 | }
|
104 |
|
105 | const missing = missingKeys(OUT, TKEYS, TFILES);
|
106 | if (missing.length > 0) {
|
107 | missing.forEach(error);
|
108 | process.exit(1);
|
109 | }
|
110 |
|
111 | log("All good.");
|
112 | }
|
113 |
|
114 | const TRANSLATIONS_NEEDS = [
|
115 | path.join(OUT, "brands.json"),
|
116 | path.join(OUT, "languages.json"),
|
117 | path.join(OUT, "countries.json"),
|
118 | path.join(OUT, "tkeys.json"),
|
119 | ];
|
120 |
|
121 | const TRANSLATION_GRANS = [
|
122 | path.join(OUT, "brands"),
|
123 | path.join(OUT, "languages"),
|
124 | path.join(OUT, "countries"),
|
125 | path.join(OUT, "tkeys.json"),
|
126 | ];
|
127 |
|
128 | function translations(tFile, granular) {
|
129 | if (tFile && !fs.existsSync(tFile)) {
|
130 | error(`Translations not found at '${tFile}'`);
|
131 | process.exit(1);
|
132 | return;
|
133 | }
|
134 | if (!tFile) {
|
135 | try {
|
136 |
|
137 | const kiwiTranslations = require("@kiwicom/translations");
|
138 | } catch (err) {
|
139 | error(`'@kiwicom/translations' is not installed and you don't provide path param!`);
|
140 | process.exit(1);
|
141 | return;
|
142 | }
|
143 | }
|
144 |
|
145 | const good = granular
|
146 | ? TRANSLATION_GRANS.reduce((ok, need) => {
|
147 | if (!fs.existsSync(need)) {
|
148 | error(
|
149 | `Task 'translations' requires running the 'keys' and 'fetch' commands first! Missing file: ${need}`,
|
150 | );
|
151 | return false;
|
152 | }
|
153 | return ok;
|
154 | }, true)
|
155 | : TRANSLATIONS_NEEDS.reduce((ok, need) => {
|
156 | if (!fs.existsSync(need)) {
|
157 | error(
|
158 | `Task 'translations' requires running the 'keys' and 'fetch' commands first! Missing file: ${need}`,
|
159 | );
|
160 | return false;
|
161 | }
|
162 | return ok;
|
163 | }, true);
|
164 |
|
165 | if (!good) {
|
166 | process.exit(1);
|
167 | return;
|
168 | }
|
169 |
|
170 | if (granular) {
|
171 | getTranslationsGranular(TKEYS, tFile)
|
172 | .then(mapLanguagesGran)
|
173 | .then(() => {
|
174 | log("DONE!");
|
175 | })
|
176 | .catch(err => {
|
177 | log(chalk.bold.red("ERROR"));
|
178 | error(err);
|
179 | });
|
180 | } else {
|
181 | getTranslations(TKEYS, tFile)
|
182 | .then(mapLanguages)
|
183 | .then(() => {
|
184 | log("DONE!");
|
185 | })
|
186 | .catch(err => {
|
187 | log(chalk.bold.red("ERROR"));
|
188 | error(err);
|
189 | });
|
190 | }
|
191 | }
|
192 |
|
193 | function fetch(granular) {
|
194 | Promise.all([fetchSpreadsheet(granular), fetchBrandConfig(granular)])
|
195 | .then(() => {
|
196 | log("DONE!");
|
197 | })
|
198 | .catch(err => {
|
199 | log(chalk.bold.red("ERROR"));
|
200 | error(err);
|
201 | });
|
202 | }
|
203 |
|
204 | if (command === commands.keys) {
|
205 | const globs = process.argv.slice(3).filter(a => !commandOptionsMap.keys[a]);
|
206 |
|
207 | const shouldExcludeNitroTranslations = commandOptionsMap.keys["--no-nitro"] in yargs.argv;
|
208 |
|
209 | keys(globs, shouldExcludeNitroTranslations);
|
210 | }
|
211 |
|
212 | if (command === commands["keys-check"]) {
|
213 | keysCheck();
|
214 | }
|
215 |
|
216 | if (command === commands.translations) {
|
217 | translations(yargs.argv.path, yargs.argv.granular);
|
218 | }
|
219 |
|
220 | if (command === commands.fetch) {
|
221 | fetch(yargs.argv.granular);
|
222 | }
|