@kopynator/cli 1.0.10 → 1.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +169 -3
- package/package.json +1 -1
- package/src/commands/sync.ts +244 -4
package/dist/index.js
CHANGED
|
@@ -202,11 +202,177 @@ async function checkCommand() {
|
|
|
202
202
|
|
|
203
203
|
// src/commands/sync.ts
|
|
204
204
|
var import_chalk3 = __toESM(require("chalk"));
|
|
205
|
+
var import_fs3 = __toESM(require("fs"));
|
|
206
|
+
var import_path3 = __toESM(require("path"));
|
|
207
|
+
var import_inquirer2 = __toESM(require("inquirer"));
|
|
208
|
+
function detectFramework() {
|
|
209
|
+
const angularJson = import_path3.default.join(process.cwd(), "angular.json");
|
|
210
|
+
const packageJson = import_path3.default.join(process.cwd(), "package.json");
|
|
211
|
+
if (import_fs3.default.existsSync(angularJson)) {
|
|
212
|
+
return "Angular";
|
|
213
|
+
}
|
|
214
|
+
if (import_fs3.default.existsSync(packageJson)) {
|
|
215
|
+
try {
|
|
216
|
+
const pkg = JSON.parse(import_fs3.default.readFileSync(packageJson, "utf-8"));
|
|
217
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
218
|
+
if (deps["@angular/core"]) return "Angular";
|
|
219
|
+
if (deps["react"]) return "React";
|
|
220
|
+
if (deps["vue"]) return "Vue";
|
|
221
|
+
} catch (e) {
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return "Other";
|
|
225
|
+
}
|
|
226
|
+
function getTranslationDir(framework) {
|
|
227
|
+
switch (framework) {
|
|
228
|
+
case "Angular":
|
|
229
|
+
return import_path3.default.join(process.cwd(), "src/assets/i18n");
|
|
230
|
+
case "React":
|
|
231
|
+
return import_path3.default.join(process.cwd(), "public/locales");
|
|
232
|
+
case "Vue":
|
|
233
|
+
return import_path3.default.join(process.cwd(), "public/locales");
|
|
234
|
+
default:
|
|
235
|
+
return import_path3.default.join(process.cwd(), "locales");
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
function extractApiKey() {
|
|
239
|
+
const appConfigPath = import_path3.default.join(process.cwd(), "src/app/app.config.ts");
|
|
240
|
+
const appModulePath = import_path3.default.join(process.cwd(), "src/app/app.module.ts");
|
|
241
|
+
const jsonConfigPath = import_path3.default.join(process.cwd(), "kopynator.config.json");
|
|
242
|
+
if (import_fs3.default.existsSync(appConfigPath)) {
|
|
243
|
+
const content = import_fs3.default.readFileSync(appConfigPath, "utf-8");
|
|
244
|
+
const apiKeyMatch = content.match(/apiKey:\s*['"]([^'"]+)['"]/);
|
|
245
|
+
if (apiKeyMatch) {
|
|
246
|
+
console.log(import_chalk3.default.blue("\u2139\uFE0F Found API key in app.config.ts"));
|
|
247
|
+
return { apiKey: apiKeyMatch[1] };
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
if (import_fs3.default.existsSync(appModulePath)) {
|
|
251
|
+
const content = import_fs3.default.readFileSync(appModulePath, "utf-8");
|
|
252
|
+
const apiKeyMatch = content.match(/apiKey:\s*['"]([^'"]+)['"]/);
|
|
253
|
+
if (apiKeyMatch) {
|
|
254
|
+
console.log(import_chalk3.default.blue("\u2139\uFE0F Found API key in app.module.ts"));
|
|
255
|
+
return { apiKey: apiKeyMatch[1] };
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
if (import_fs3.default.existsSync(jsonConfigPath)) {
|
|
259
|
+
try {
|
|
260
|
+
const config = JSON.parse(import_fs3.default.readFileSync(jsonConfigPath, "utf-8"));
|
|
261
|
+
if (config.apiKey) {
|
|
262
|
+
console.log(import_chalk3.default.blue("\u2139\uFE0F Found API key in kopynator.config.json"));
|
|
263
|
+
return { apiKey: config.apiKey, baseUrl: config.baseUrl };
|
|
264
|
+
}
|
|
265
|
+
} catch (e) {
|
|
266
|
+
console.log(import_chalk3.default.red("\u274C Error parsing kopynator.config.json"));
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
async function getSyncConfig() {
|
|
272
|
+
const configPath = import_path3.default.join(process.cwd(), "kopynator.sync.config.json");
|
|
273
|
+
if (import_fs3.default.existsSync(configPath)) {
|
|
274
|
+
try {
|
|
275
|
+
const config2 = JSON.parse(import_fs3.default.readFileSync(configPath, "utf-8"));
|
|
276
|
+
console.log(import_chalk3.default.blue("\u2139\uFE0F Using existing sync configuration"));
|
|
277
|
+
return config2;
|
|
278
|
+
} catch (e) {
|
|
279
|
+
console.log(import_chalk3.default.yellow("\u26A0\uFE0F Error reading sync config, creating new one"));
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
console.log(import_chalk3.default.blue("\n\u{1F4DD} First time sync! Let's configure your preferences:\n"));
|
|
283
|
+
const answers = await import_inquirer2.default.prompt([
|
|
284
|
+
{
|
|
285
|
+
type: "confirm",
|
|
286
|
+
name: "nested",
|
|
287
|
+
message: 'Use nested JSON structure? (e.g., {"nav": {"home": "Home"}})',
|
|
288
|
+
default: false
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
type: "confirm",
|
|
292
|
+
name: "includeLangKey",
|
|
293
|
+
message: 'Include language key in output? (e.g., {"en": {...}, "es": {...}})',
|
|
294
|
+
default: false
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
type: "confirm",
|
|
298
|
+
name: "pretty",
|
|
299
|
+
message: "Pretty print JSON?",
|
|
300
|
+
default: true
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
type: "list",
|
|
304
|
+
name: "indent",
|
|
305
|
+
message: "Indentation style:",
|
|
306
|
+
choices: [
|
|
307
|
+
{ name: "2 spaces", value: "2" },
|
|
308
|
+
{ name: "4 spaces", value: "4" },
|
|
309
|
+
{ name: "Tabs", value: "tab" }
|
|
310
|
+
],
|
|
311
|
+
default: "2"
|
|
312
|
+
}
|
|
313
|
+
]);
|
|
314
|
+
const config = {
|
|
315
|
+
nested: answers.nested,
|
|
316
|
+
includeLangKey: answers.includeLangKey,
|
|
317
|
+
pretty: answers.pretty,
|
|
318
|
+
indent: answers.indent
|
|
319
|
+
};
|
|
320
|
+
import_fs3.default.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
321
|
+
console.log(import_chalk3.default.green("\u2705 Configuration saved to kopynator.sync.config.json\n"));
|
|
322
|
+
return config;
|
|
323
|
+
}
|
|
205
324
|
async function syncCommand() {
|
|
206
325
|
console.log(import_chalk3.default.bold.blue("\n\u2601\uFE0F Syncing with Kopynator Cloud...\n"));
|
|
207
|
-
|
|
208
|
-
console.log(import_chalk3.default.
|
|
209
|
-
|
|
326
|
+
const framework = detectFramework();
|
|
327
|
+
console.log(import_chalk3.default.blue(`\u2139\uFE0F Detected ${framework} project`));
|
|
328
|
+
const config = extractApiKey();
|
|
329
|
+
if (!config) {
|
|
330
|
+
console.log(import_chalk3.default.red("\u274C Could not find API key in any config file."));
|
|
331
|
+
console.log(import_chalk3.default.yellow("Run `npx kopynator init` first or configure your API key manually."));
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
const syncConfig = await getSyncConfig();
|
|
335
|
+
const baseUrl = config.baseUrl || "http://localhost:7300/api/tokens";
|
|
336
|
+
const token = config.apiKey;
|
|
337
|
+
try {
|
|
338
|
+
console.log(import_chalk3.default.blue("\u{1F4E1} Fetching available languages..."));
|
|
339
|
+
const languagesUrl = `${baseUrl}/languages?token=${token}`;
|
|
340
|
+
const languagesResponse = await fetch(languagesUrl);
|
|
341
|
+
if (!languagesResponse.ok) {
|
|
342
|
+
console.log(import_chalk3.default.red(`\u274C Failed to fetch languages: ${languagesResponse.status} ${languagesResponse.statusText}`));
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
const languages = await languagesResponse.json();
|
|
346
|
+
console.log(import_chalk3.default.green(`\u2705 Found ${languages.length} language(s): ${languages.join(", ")}`));
|
|
347
|
+
const i18nDir = getTranslationDir(framework);
|
|
348
|
+
if (!import_fs3.default.existsSync(i18nDir)) {
|
|
349
|
+
import_fs3.default.mkdirSync(i18nDir, { recursive: true });
|
|
350
|
+
console.log(import_chalk3.default.blue(`\u{1F4C1} Created directory: ${i18nDir}`));
|
|
351
|
+
}
|
|
352
|
+
for (const locale of languages) {
|
|
353
|
+
console.log(import_chalk3.default.blue(`\u2B07\uFE0F Downloading ${locale}...`));
|
|
354
|
+
const fetchUrl = `${baseUrl}/fetch?token=${token}&langs=${locale}&nested=${syncConfig.nested}&includeLangKey=${syncConfig.includeLangKey}&pretty=${syncConfig.pretty}&indent=${syncConfig.indent}`;
|
|
355
|
+
const translationResponse = await fetch(fetchUrl);
|
|
356
|
+
if (!translationResponse.ok) {
|
|
357
|
+
console.log(import_chalk3.default.yellow(`\u26A0\uFE0F Failed to fetch ${locale}: ${translationResponse.status}`));
|
|
358
|
+
continue;
|
|
359
|
+
}
|
|
360
|
+
const translationData = await translationResponse.json();
|
|
361
|
+
const outputPath = import_path3.default.join(i18nDir, `${locale}.json`);
|
|
362
|
+
let jsonString;
|
|
363
|
+
if (syncConfig.pretty) {
|
|
364
|
+
const indentValue = syncConfig.indent === "tab" ? " " : Number(syncConfig.indent);
|
|
365
|
+
jsonString = JSON.stringify(translationData, null, indentValue);
|
|
366
|
+
} else {
|
|
367
|
+
jsonString = JSON.stringify(translationData);
|
|
368
|
+
}
|
|
369
|
+
import_fs3.default.writeFileSync(outputPath, jsonString);
|
|
370
|
+
console.log(import_chalk3.default.green(`\u2705 Saved ${locale}.json`));
|
|
371
|
+
}
|
|
372
|
+
console.log(import_chalk3.default.bold.green("\n\u{1F389} Sync completed successfully!\n"));
|
|
373
|
+
} catch (error) {
|
|
374
|
+
console.log(import_chalk3.default.red(`\u274C Sync failed: ${error instanceof Error ? error.message : "Unknown error"}`));
|
|
375
|
+
}
|
|
210
376
|
}
|
|
211
377
|
|
|
212
378
|
// src/index.ts
|
package/package.json
CHANGED
package/src/commands/sync.ts
CHANGED
|
@@ -1,10 +1,250 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import inquirer from 'inquirer';
|
|
5
|
+
|
|
6
|
+
interface KopyConfig {
|
|
7
|
+
apiKey: string;
|
|
8
|
+
baseUrl?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface SyncConfig {
|
|
12
|
+
nested: boolean;
|
|
13
|
+
includeLangKey: boolean;
|
|
14
|
+
pretty: boolean;
|
|
15
|
+
indent: '2' | '4' | 'tab';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Detect the framework being used in the current project
|
|
20
|
+
*/
|
|
21
|
+
function detectFramework(): 'Angular' | 'React' | 'Vue' | 'Other' {
|
|
22
|
+
const angularJson = path.join(process.cwd(), 'angular.json');
|
|
23
|
+
const packageJson = path.join(process.cwd(), 'package.json');
|
|
24
|
+
|
|
25
|
+
// Check for Angular
|
|
26
|
+
if (fs.existsSync(angularJson)) {
|
|
27
|
+
return 'Angular';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Check package.json for React/Vue
|
|
31
|
+
if (fs.existsSync(packageJson)) {
|
|
32
|
+
try {
|
|
33
|
+
const pkg = JSON.parse(fs.readFileSync(packageJson, 'utf-8'));
|
|
34
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
35
|
+
|
|
36
|
+
if (deps['@angular/core']) return 'Angular';
|
|
37
|
+
if (deps['react']) return 'React';
|
|
38
|
+
if (deps['vue']) return 'Vue';
|
|
39
|
+
} catch (e) {
|
|
40
|
+
// Ignore parse errors
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return 'Other';
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Get the translation directory path based on framework
|
|
49
|
+
*/
|
|
50
|
+
function getTranslationDir(framework: string): string {
|
|
51
|
+
switch (framework) {
|
|
52
|
+
case 'Angular':
|
|
53
|
+
return path.join(process.cwd(), 'src/assets/i18n');
|
|
54
|
+
case 'React':
|
|
55
|
+
// Common React patterns, can be customized later
|
|
56
|
+
return path.join(process.cwd(), 'public/locales');
|
|
57
|
+
case 'Vue':
|
|
58
|
+
// Common Vue patterns, can be customized later
|
|
59
|
+
return path.join(process.cwd(), 'public/locales');
|
|
60
|
+
default:
|
|
61
|
+
// Default fallback
|
|
62
|
+
return path.join(process.cwd(), 'locales');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Extract API key from Angular config files or JSON config
|
|
68
|
+
* Tries: app.config.ts -> app.module.ts -> kopynator.config.json
|
|
69
|
+
*/
|
|
70
|
+
function extractApiKey(): KopyConfig | null {
|
|
71
|
+
const appConfigPath = path.join(process.cwd(), 'src/app/app.config.ts');
|
|
72
|
+
const appModulePath = path.join(process.cwd(), 'src/app/app.module.ts');
|
|
73
|
+
const jsonConfigPath = path.join(process.cwd(), 'kopynator.config.json');
|
|
74
|
+
|
|
75
|
+
// Try app.config.ts
|
|
76
|
+
if (fs.existsSync(appConfigPath)) {
|
|
77
|
+
const content = fs.readFileSync(appConfigPath, 'utf-8');
|
|
78
|
+
const apiKeyMatch = content.match(/apiKey:\s*['"]([^'"]+)['"]/);
|
|
79
|
+
if (apiKeyMatch) {
|
|
80
|
+
console.log(chalk.blue('ℹ️ Found API key in app.config.ts'));
|
|
81
|
+
return { apiKey: apiKeyMatch[1] };
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Try app.module.ts
|
|
86
|
+
if (fs.existsSync(appModulePath)) {
|
|
87
|
+
const content = fs.readFileSync(appModulePath, 'utf-8');
|
|
88
|
+
const apiKeyMatch = content.match(/apiKey:\s*['"]([^'"]+)['"]/);
|
|
89
|
+
if (apiKeyMatch) {
|
|
90
|
+
console.log(chalk.blue('ℹ️ Found API key in app.module.ts'));
|
|
91
|
+
return { apiKey: apiKeyMatch[1] };
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Try kopynator.config.json
|
|
96
|
+
if (fs.existsSync(jsonConfigPath)) {
|
|
97
|
+
try {
|
|
98
|
+
const config = JSON.parse(fs.readFileSync(jsonConfigPath, 'utf-8'));
|
|
99
|
+
if (config.apiKey) {
|
|
100
|
+
console.log(chalk.blue('ℹ️ Found API key in kopynator.config.json'));
|
|
101
|
+
return { apiKey: config.apiKey, baseUrl: config.baseUrl };
|
|
102
|
+
}
|
|
103
|
+
} catch (e) {
|
|
104
|
+
console.log(chalk.red('❌ Error parsing kopynator.config.json'));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Load or create sync configuration
|
|
113
|
+
*/
|
|
114
|
+
async function getSyncConfig(): Promise<SyncConfig> {
|
|
115
|
+
const configPath = path.join(process.cwd(), 'kopynator.sync.config.json');
|
|
116
|
+
|
|
117
|
+
// If config exists, load it
|
|
118
|
+
if (fs.existsSync(configPath)) {
|
|
119
|
+
try {
|
|
120
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
121
|
+
console.log(chalk.blue('ℹ️ Using existing sync configuration'));
|
|
122
|
+
return config;
|
|
123
|
+
} catch (e) {
|
|
124
|
+
console.log(chalk.yellow('⚠️ Error reading sync config, creating new one'));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Ask user for preferences
|
|
129
|
+
console.log(chalk.blue('\n📝 First time sync! Let\'s configure your preferences:\n'));
|
|
130
|
+
|
|
131
|
+
const answers = await inquirer.prompt([
|
|
132
|
+
{
|
|
133
|
+
type: 'confirm',
|
|
134
|
+
name: 'nested',
|
|
135
|
+
message: 'Use nested JSON structure? (e.g., {"nav": {"home": "Home"}})',
|
|
136
|
+
default: false,
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
type: 'confirm',
|
|
140
|
+
name: 'includeLangKey',
|
|
141
|
+
message: 'Include language key in output? (e.g., {"en": {...}, "es": {...}})',
|
|
142
|
+
default: false,
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
type: 'confirm',
|
|
146
|
+
name: 'pretty',
|
|
147
|
+
message: 'Pretty print JSON?',
|
|
148
|
+
default: true,
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
type: 'list',
|
|
152
|
+
name: 'indent',
|
|
153
|
+
message: 'Indentation style:',
|
|
154
|
+
choices: [
|
|
155
|
+
{ name: '2 spaces', value: '2' },
|
|
156
|
+
{ name: '4 spaces', value: '4' },
|
|
157
|
+
{ name: 'Tabs', value: 'tab' },
|
|
158
|
+
],
|
|
159
|
+
default: '2',
|
|
160
|
+
},
|
|
161
|
+
]);
|
|
162
|
+
|
|
163
|
+
const config: SyncConfig = {
|
|
164
|
+
nested: answers.nested,
|
|
165
|
+
includeLangKey: answers.includeLangKey,
|
|
166
|
+
pretty: answers.pretty,
|
|
167
|
+
indent: answers.indent,
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
// Save config
|
|
171
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
172
|
+
console.log(chalk.green('✅ Configuration saved to kopynator.sync.config.json\n'));
|
|
173
|
+
|
|
174
|
+
return config;
|
|
175
|
+
}
|
|
2
176
|
|
|
3
177
|
export async function syncCommand() {
|
|
4
178
|
console.log(chalk.bold.blue('\n☁️ Syncing with Kopynator Cloud...\n'));
|
|
5
179
|
|
|
6
|
-
//
|
|
7
|
-
|
|
8
|
-
console.log(chalk.
|
|
9
|
-
|
|
180
|
+
// Detect framework
|
|
181
|
+
const framework = detectFramework();
|
|
182
|
+
console.log(chalk.blue(`ℹ️ Detected ${framework} project`));
|
|
183
|
+
|
|
184
|
+
// Extract API key
|
|
185
|
+
const config = extractApiKey();
|
|
186
|
+
if (!config) {
|
|
187
|
+
console.log(chalk.red('❌ Could not find API key in any config file.'));
|
|
188
|
+
console.log(chalk.yellow('Run `npx kopynator init` first or configure your API key manually.'));
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Get sync configuration
|
|
193
|
+
const syncConfig = await getSyncConfig();
|
|
194
|
+
|
|
195
|
+
const baseUrl = config.baseUrl || 'http://localhost:7300/api/tokens';
|
|
196
|
+
const token = config.apiKey;
|
|
197
|
+
|
|
198
|
+
try {
|
|
199
|
+
// 1. Fetch available languages
|
|
200
|
+
console.log(chalk.blue('📡 Fetching available languages...'));
|
|
201
|
+
const languagesUrl = `${baseUrl}/languages?token=${token}`;
|
|
202
|
+
const languagesResponse = await fetch(languagesUrl);
|
|
203
|
+
|
|
204
|
+
if (!languagesResponse.ok) {
|
|
205
|
+
console.log(chalk.red(`❌ Failed to fetch languages: ${languagesResponse.status} ${languagesResponse.statusText}`));
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const languages = await languagesResponse.json() as string[];
|
|
210
|
+
console.log(chalk.green(`✅ Found ${languages.length} language(s): ${languages.join(', ')}`));
|
|
211
|
+
|
|
212
|
+
// 2. Get translation directory based on framework
|
|
213
|
+
const i18nDir = getTranslationDir(framework);
|
|
214
|
+
if (!fs.existsSync(i18nDir)) {
|
|
215
|
+
fs.mkdirSync(i18nDir, { recursive: true });
|
|
216
|
+
console.log(chalk.blue(`📁 Created directory: ${i18nDir}`));
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// 3. Download translations for each language
|
|
220
|
+
for (const locale of languages) {
|
|
221
|
+
console.log(chalk.blue(`⬇️ Downloading ${locale}...`));
|
|
222
|
+
const fetchUrl = `${baseUrl}/fetch?token=${token}&langs=${locale}&nested=${syncConfig.nested}&includeLangKey=${syncConfig.includeLangKey}&pretty=${syncConfig.pretty}&indent=${syncConfig.indent}`;
|
|
223
|
+
const translationResponse = await fetch(fetchUrl);
|
|
224
|
+
|
|
225
|
+
if (!translationResponse.ok) {
|
|
226
|
+
console.log(chalk.yellow(`⚠️ Failed to fetch ${locale}: ${translationResponse.status}`));
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const translationData = await translationResponse.json();
|
|
231
|
+
const outputPath = path.join(i18nDir, `${locale}.json`);
|
|
232
|
+
|
|
233
|
+
// Format based on config
|
|
234
|
+
let jsonString: string;
|
|
235
|
+
if (syncConfig.pretty) {
|
|
236
|
+
const indentValue = syncConfig.indent === 'tab' ? '\t' : Number(syncConfig.indent);
|
|
237
|
+
jsonString = JSON.stringify(translationData, null, indentValue);
|
|
238
|
+
} else {
|
|
239
|
+
jsonString = JSON.stringify(translationData);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
fs.writeFileSync(outputPath, jsonString);
|
|
243
|
+
console.log(chalk.green(`✅ Saved ${locale}.json`));
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
console.log(chalk.bold.green('\n🎉 Sync completed successfully!\n'));
|
|
247
|
+
} catch (error) {
|
|
248
|
+
console.log(chalk.red(`❌ Sync failed: ${error instanceof Error ? error.message : 'Unknown error'}`));
|
|
249
|
+
}
|
|
10
250
|
}
|