lingo.dev 0.70.4 → 0.72.0
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/build/{chunk-DTGLPBE5.cjs → chunk-BCCNAFJB.cjs} +1 -0
- package/build/chunk-BCCNAFJB.cjs.map +1 -0
- package/build/{chunk-MNP3B6L4.cjs → chunk-HODTYTE5.cjs} +8 -7
- package/build/chunk-HODTYTE5.cjs.map +1 -0
- package/build/{chunk-3TBVVQ2O.mjs → chunk-NF6GBJ2R.mjs} +1 -0
- package/build/chunk-NF6GBJ2R.mjs.map +1 -0
- package/build/{chunk-FAB4HZX7.mjs → chunk-NUMPOGXY.mjs} +5 -4
- package/build/chunk-NUMPOGXY.mjs.map +1 -0
- package/build/cli.cjs +327 -77
- package/build/cli.cjs.map +1 -0
- package/build/cli.mjs +301 -51
- package/build/cli.mjs.map +1 -0
- package/build/sdk.cjs +4 -3
- package/build/sdk.cjs.map +1 -0
- package/build/sdk.mjs +3 -2
- package/build/sdk.mjs.map +1 -0
- package/build/spec.cjs +3 -2
- package/build/spec.cjs.map +1 -0
- package/build/spec.mjs +2 -1
- package/build/spec.mjs.map +1 -0
- package/package.json +6 -2
package/build/cli.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ReplexicaEngine
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-NUMPOGXY.mjs";
|
|
4
4
|
import {
|
|
5
5
|
bucketTypeSchema,
|
|
6
6
|
bucketTypes,
|
|
@@ -10,13 +10,15 @@ import {
|
|
|
10
10
|
parseI18nConfig,
|
|
11
11
|
resolveLocaleCode,
|
|
12
12
|
resolveOverridenLocale
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-NF6GBJ2R.mjs";
|
|
14
14
|
|
|
15
15
|
// src/cli/index.ts
|
|
16
16
|
import dotenv from "dotenv";
|
|
17
17
|
import { InteractiveCommand as InteractiveCommand2 } from "interactive-commander";
|
|
18
|
+
import figlet from "figlet";
|
|
19
|
+
import { vice } from "gradient-string";
|
|
18
20
|
|
|
19
|
-
// src/cli/
|
|
21
|
+
// src/cli/cmd/auth.ts
|
|
20
22
|
import { Command } from "interactive-commander";
|
|
21
23
|
import Ora from "ora";
|
|
22
24
|
import express from "express";
|
|
@@ -34,11 +36,12 @@ function getSettings(explicitApiKey) {
|
|
|
34
36
|
const env = _loadEnv();
|
|
35
37
|
const systemFile = _loadSystemFile();
|
|
36
38
|
const defaults = _loadDefaults();
|
|
39
|
+
_legacyEnvVarWarning();
|
|
37
40
|
return {
|
|
38
41
|
auth: {
|
|
39
|
-
apiKey: explicitApiKey || env.
|
|
40
|
-
apiUrl: env.
|
|
41
|
-
webUrl: env.
|
|
42
|
+
apiKey: explicitApiKey || env.LINGODOTDEV_API_KEY || systemFile.auth?.apiKey || defaults.auth.apiKey,
|
|
43
|
+
apiUrl: env.LINGODOTDEV_API_URL || systemFile.auth?.apiUrl || defaults.auth.apiUrl,
|
|
44
|
+
webUrl: env.LINGODOTDEV_WEB_URL || systemFile.auth?.webUrl || defaults.auth.webUrl
|
|
42
45
|
}
|
|
43
46
|
};
|
|
44
47
|
}
|
|
@@ -63,9 +66,9 @@ function _loadDefaults() {
|
|
|
63
66
|
}
|
|
64
67
|
function _loadEnv() {
|
|
65
68
|
return Z.object({
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
+
LINGODOTDEV_API_KEY: Z.string().optional(),
|
|
70
|
+
LINGODOTDEV_API_URL: Z.string().optional(),
|
|
71
|
+
LINGODOTDEV_WEB_URL: Z.string().optional()
|
|
69
72
|
}).passthrough().parse(process.env);
|
|
70
73
|
}
|
|
71
74
|
function _loadSystemFile() {
|
|
@@ -91,6 +94,21 @@ function _getSettingsFilePath() {
|
|
|
91
94
|
const settingsFilePath = path.join(homedir, settingsFile);
|
|
92
95
|
return settingsFilePath;
|
|
93
96
|
}
|
|
97
|
+
function _legacyEnvVarWarning() {
|
|
98
|
+
const env = _loadEnv();
|
|
99
|
+
if (env.REPLEXICA_API_KEY && !env.LINGODOTDEV_API_KEY) {
|
|
100
|
+
console.warn(
|
|
101
|
+
"\x1B[33m%s\x1B[0m",
|
|
102
|
+
`
|
|
103
|
+
\u26A0\uFE0F WARNING: REPLEXICA_API_KEY env var is deprecated \u26A0\uFE0F
|
|
104
|
+
===========================================================
|
|
105
|
+
|
|
106
|
+
Please use LINGODOTDEV_API_KEY instead.
|
|
107
|
+
===========================================================
|
|
108
|
+
`
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
94
112
|
|
|
95
113
|
// src/cli/utils/errors.ts
|
|
96
114
|
var docLinks = {
|
|
@@ -156,7 +174,7 @@ function createAuthenticator(params) {
|
|
|
156
174
|
};
|
|
157
175
|
}
|
|
158
176
|
|
|
159
|
-
// src/cli/
|
|
177
|
+
// src/cli/cmd/auth.ts
|
|
160
178
|
var auth_default = new Command().command("auth").description("Authenticate with Lingo.dev API").helpOption("-h, --help", "Show help").option("--logout", "Delete existing authentication").option("--login", "Authenticate with Lingo.dev API").action(async (options) => {
|
|
161
179
|
try {
|
|
162
180
|
let settings = await getSettings(void 0);
|
|
@@ -195,7 +213,7 @@ Press Enter to open the browser for authentication.
|
|
|
195
213
|
|
|
196
214
|
---
|
|
197
215
|
|
|
198
|
-
Having issues? Put
|
|
216
|
+
Having issues? Put LINGODOTDEV_API_KEY in your .env file instead.
|
|
199
217
|
`.trim() + "\n"
|
|
200
218
|
);
|
|
201
219
|
const spinner = Ora().start("Waiting for the API key");
|
|
@@ -224,7 +242,7 @@ async function waitForApiKey(cb) {
|
|
|
224
242
|
});
|
|
225
243
|
}
|
|
226
244
|
|
|
227
|
-
// src/cli/
|
|
245
|
+
// src/cli/cmd/init.ts
|
|
228
246
|
import { InteractiveCommand, InteractiveOption } from "interactive-commander";
|
|
229
247
|
import Ora2 from "ora";
|
|
230
248
|
|
|
@@ -257,14 +275,14 @@ function _getConfigFilePath() {
|
|
|
257
275
|
return path2.join(process.cwd(), "i18n.json");
|
|
258
276
|
}
|
|
259
277
|
|
|
260
|
-
// src/cli/
|
|
278
|
+
// src/cli/cmd/init.ts
|
|
261
279
|
import fs3 from "fs";
|
|
262
280
|
import { spawn } from "child_process";
|
|
263
281
|
import _2 from "lodash";
|
|
264
282
|
import { confirm } from "@inquirer/prompts";
|
|
265
|
-
var openUrl = (
|
|
283
|
+
var openUrl = (path8) => {
|
|
266
284
|
const settings = getSettings(void 0);
|
|
267
|
-
spawn("open", [`${settings.auth.webUrl}${
|
|
285
|
+
spawn("open", [`${settings.auth.webUrl}${path8}`]);
|
|
268
286
|
};
|
|
269
287
|
var throwHelpError = (option, value) => {
|
|
270
288
|
if (value === "help") {
|
|
@@ -307,14 +325,14 @@ var init_default = new InteractiveCommand().command("init").description("Initial
|
|
|
307
325
|
).addOption(
|
|
308
326
|
new InteractiveOption("-p, --paths <path...>", "List of paths for the bucket").argParser((value) => {
|
|
309
327
|
const values = value.includes(",") ? value.split(",") : value.split(" ");
|
|
310
|
-
for (const
|
|
328
|
+
for (const path8 of values) {
|
|
311
329
|
try {
|
|
312
|
-
const stats = fs3.statSync(
|
|
330
|
+
const stats = fs3.statSync(path8);
|
|
313
331
|
if (!stats.isDirectory()) {
|
|
314
|
-
throw new Error(`${
|
|
332
|
+
throw new Error(`${path8} is not a directory`);
|
|
315
333
|
}
|
|
316
334
|
} catch (err) {
|
|
317
|
-
throw new Error(`Invalid directory path: ${
|
|
335
|
+
throw new Error(`Invalid directory path: ${path8}`);
|
|
318
336
|
}
|
|
319
337
|
}
|
|
320
338
|
return values;
|
|
@@ -378,10 +396,10 @@ var init_default = new InteractiveCommand().command("init").description("Initial
|
|
|
378
396
|
}
|
|
379
397
|
});
|
|
380
398
|
|
|
381
|
-
// src/cli/
|
|
399
|
+
// src/cli/cmd/show/index.ts
|
|
382
400
|
import { Command as Command5 } from "interactive-commander";
|
|
383
401
|
|
|
384
|
-
// src/cli/
|
|
402
|
+
// src/cli/cmd/show/config.ts
|
|
385
403
|
import { Command as Command2 } from "interactive-commander";
|
|
386
404
|
import _3 from "lodash";
|
|
387
405
|
import fs4 from "fs";
|
|
@@ -402,7 +420,7 @@ function loadReplexicaFileConfig() {
|
|
|
402
420
|
return replexicaFileConfig;
|
|
403
421
|
}
|
|
404
422
|
|
|
405
|
-
// src/cli/
|
|
423
|
+
// src/cli/cmd/show/locale.ts
|
|
406
424
|
import { Command as Command3 } from "interactive-commander";
|
|
407
425
|
import Ora3 from "ora";
|
|
408
426
|
var locale_default = new Command3().command("locale").description("Print out the list of locales").helpOption("-h, --help", "Show help").argument("<type>", 'Type of locales to show, either "sources" or "targets"').action(async (type) => {
|
|
@@ -427,7 +445,7 @@ var locale_default = new Command3().command("locale").description("Print out the
|
|
|
427
445
|
}
|
|
428
446
|
});
|
|
429
447
|
|
|
430
|
-
// src/cli/
|
|
448
|
+
// src/cli/cmd/show/files.ts
|
|
431
449
|
import { Command as Command4 } from "interactive-commander";
|
|
432
450
|
import Ora4 from "ora";
|
|
433
451
|
|
|
@@ -511,7 +529,7 @@ function resolveBucketItem(bucketItem) {
|
|
|
511
529
|
return bucketItem;
|
|
512
530
|
}
|
|
513
531
|
|
|
514
|
-
// src/cli/
|
|
532
|
+
// src/cli/cmd/show/files.ts
|
|
515
533
|
var files_default = new Command4().command("files").description("Print out the list of files managed by Lingo.dev").option("--source", "Only show source files").option("--target", "Only show target files").helpOption("-h, --help", "Show help").action(async (type) => {
|
|
516
534
|
const ora = Ora4();
|
|
517
535
|
try {
|
|
@@ -540,8 +558,8 @@ var files_default = new Command4().command("files").description("Print out the l
|
|
|
540
558
|
} else if (type.target) {
|
|
541
559
|
result.push(...targetPaths);
|
|
542
560
|
}
|
|
543
|
-
result.forEach((
|
|
544
|
-
console.log(
|
|
561
|
+
result.forEach((path8) => {
|
|
562
|
+
console.log(path8);
|
|
545
563
|
});
|
|
546
564
|
}
|
|
547
565
|
}
|
|
@@ -557,10 +575,10 @@ var files_default = new Command4().command("files").description("Print out the l
|
|
|
557
575
|
}
|
|
558
576
|
});
|
|
559
577
|
|
|
560
|
-
// src/cli/
|
|
578
|
+
// src/cli/cmd/show/index.ts
|
|
561
579
|
var show_default = new Command5().command("show").description("Prints out the current configuration").helpOption("-h, --help", "Show help").addCommand(config_default).addCommand(locale_default).addCommand(files_default);
|
|
562
580
|
|
|
563
|
-
// src/cli/
|
|
581
|
+
// src/cli/cmd/i18n.ts
|
|
564
582
|
import { Command as Command6 } from "interactive-commander";
|
|
565
583
|
import Z4 from "zod";
|
|
566
584
|
import _17 from "lodash";
|
|
@@ -706,7 +724,7 @@ function createTextFileLoader(pathPattern) {
|
|
|
706
724
|
const finalPath = path5.resolve(draftPath);
|
|
707
725
|
const dirPath = path5.dirname(finalPath);
|
|
708
726
|
await fs5.mkdir(dirPath, { recursive: true });
|
|
709
|
-
const finalPayload = data.trim()
|
|
727
|
+
const finalPayload = data.trim();
|
|
710
728
|
await fs5.writeFile(finalPath, finalPayload, {
|
|
711
729
|
encoding: "utf-8",
|
|
712
730
|
flag: "w"
|
|
@@ -979,9 +997,9 @@ function createHtmlLoader() {
|
|
|
979
997
|
const bDepth = b.split("/").length;
|
|
980
998
|
return aDepth - bDepth;
|
|
981
999
|
});
|
|
982
|
-
paths.forEach((
|
|
983
|
-
const value = data[
|
|
984
|
-
const [nodePath, attribute] =
|
|
1000
|
+
paths.forEach((path8) => {
|
|
1001
|
+
const value = data[path8];
|
|
1002
|
+
const [nodePath, attribute] = path8.split("#");
|
|
985
1003
|
const [rootTag, ...indices] = nodePath.split("/");
|
|
986
1004
|
let parent = rootTag === "head" ? document.head : document.body;
|
|
987
1005
|
let current = parent;
|
|
@@ -1253,7 +1271,7 @@ function createPrettierLoader(options) {
|
|
|
1253
1271
|
return data;
|
|
1254
1272
|
}
|
|
1255
1273
|
const result = prettier.format(data, {
|
|
1256
|
-
...prettierConfig || { printWidth: 2500 },
|
|
1274
|
+
...prettierConfig || { printWidth: 2500, bracketSameLine: false },
|
|
1257
1275
|
parser: options.parser,
|
|
1258
1276
|
// For HTML parser, preserve comments and quotes
|
|
1259
1277
|
...options.parser === "html" ? {
|
|
@@ -1979,18 +1997,18 @@ function createRawDatoValue(parsedDatoValue, originalRawDatoValue, isClean = fal
|
|
|
1979
1997
|
}
|
|
1980
1998
|
function serializeStructuredText(rawStructuredText) {
|
|
1981
1999
|
return serializeStructuredTextNode(rawStructuredText);
|
|
1982
|
-
function serializeStructuredTextNode(node,
|
|
2000
|
+
function serializeStructuredTextNode(node, path8 = [], acc = {}) {
|
|
1983
2001
|
if ("document" in node) {
|
|
1984
|
-
return serializeStructuredTextNode(node.document, [...
|
|
2002
|
+
return serializeStructuredTextNode(node.document, [...path8, "document"], acc);
|
|
1985
2003
|
}
|
|
1986
2004
|
if (!_13.isNil(node.value)) {
|
|
1987
|
-
acc[[...
|
|
2005
|
+
acc[[...path8, "value"].join(".")] = node.value;
|
|
1988
2006
|
} else if (_13.get(node, "type") === "block") {
|
|
1989
|
-
acc[[...
|
|
2007
|
+
acc[[...path8, "item"].join(".")] = serializeBlock(node.item);
|
|
1990
2008
|
}
|
|
1991
2009
|
if (node.children) {
|
|
1992
2010
|
for (let i = 0; i < node.children.length; i++) {
|
|
1993
|
-
serializeStructuredTextNode(node.children[i], [...
|
|
2011
|
+
serializeStructuredTextNode(node.children[i], [...path8, i.toString()], acc);
|
|
1994
2012
|
}
|
|
1995
2013
|
}
|
|
1996
2014
|
return acc;
|
|
@@ -2049,8 +2067,8 @@ function deserializeBlockList(parsedBlockList, originalRawBlockList, isClean = f
|
|
|
2049
2067
|
}
|
|
2050
2068
|
function deserializeStructuredText(parsedStructuredText, originalRawStructuredText) {
|
|
2051
2069
|
const result = _13.cloneDeep(originalRawStructuredText);
|
|
2052
|
-
for (const [
|
|
2053
|
-
const realPath = _13.chain(
|
|
2070
|
+
for (const [path8, value] of _13.entries(parsedStructuredText)) {
|
|
2071
|
+
const realPath = _13.chain(path8.split(".")).flatMap((s) => !_13.isNaN(_13.toNumber(s)) ? ["children", s] : s).value();
|
|
2054
2072
|
const deserializedValue = createRawDatoValue(value, _13.get(originalRawStructuredText, realPath), true);
|
|
2055
2073
|
_13.set(result, realPath, deserializedValue);
|
|
2056
2074
|
}
|
|
@@ -2118,7 +2136,6 @@ function createVttLoader() {
|
|
|
2118
2136
|
text
|
|
2119
2137
|
};
|
|
2120
2138
|
});
|
|
2121
|
-
console.log(payload, output);
|
|
2122
2139
|
const input = {
|
|
2123
2140
|
valid: true,
|
|
2124
2141
|
strict: true,
|
|
@@ -2218,6 +2235,76 @@ function createSyncLoader() {
|
|
|
2218
2235
|
});
|
|
2219
2236
|
}
|
|
2220
2237
|
|
|
2238
|
+
// src/cli/utils/plutil-formatter.ts
|
|
2239
|
+
function formatPlutilStyle(jsonData, existingJson) {
|
|
2240
|
+
const indent = existingJson ? detectIndentation(existingJson) : " ";
|
|
2241
|
+
function format(data, level = 0) {
|
|
2242
|
+
const currentIndent = indent.repeat(level);
|
|
2243
|
+
const nextIndent = indent.repeat(level + 1);
|
|
2244
|
+
if (typeof data !== "object" || data === null) {
|
|
2245
|
+
return JSON.stringify(data);
|
|
2246
|
+
}
|
|
2247
|
+
if (Array.isArray(data)) {
|
|
2248
|
+
if (data.length === 0) return "[]";
|
|
2249
|
+
const items2 = data.map((item) => `${nextIndent}${format(item, level + 1)}`);
|
|
2250
|
+
return `[
|
|
2251
|
+
${items2.join(",\n")}
|
|
2252
|
+
${currentIndent}]`;
|
|
2253
|
+
}
|
|
2254
|
+
const keys = Object.keys(data);
|
|
2255
|
+
if (keys.length === 0) {
|
|
2256
|
+
return `{
|
|
2257
|
+
|
|
2258
|
+
${currentIndent}}`;
|
|
2259
|
+
}
|
|
2260
|
+
const items = keys.map((key) => {
|
|
2261
|
+
const value = data[key];
|
|
2262
|
+
return `${nextIndent}${JSON.stringify(key)} : ${format(value, level + 1)}`;
|
|
2263
|
+
});
|
|
2264
|
+
return `{
|
|
2265
|
+
${items.join(",\n")}
|
|
2266
|
+
${currentIndent}}`;
|
|
2267
|
+
}
|
|
2268
|
+
return format(jsonData);
|
|
2269
|
+
}
|
|
2270
|
+
function detectIndentation(jsonStr) {
|
|
2271
|
+
const match = jsonStr.match(/\n(\s+)/);
|
|
2272
|
+
return match ? match[1] : " ";
|
|
2273
|
+
}
|
|
2274
|
+
|
|
2275
|
+
// src/cli/loaders/plutil-json-loader.ts
|
|
2276
|
+
function createPlutilJsonTextLoader() {
|
|
2277
|
+
return createLoader({
|
|
2278
|
+
async pull(locale, data) {
|
|
2279
|
+
return data;
|
|
2280
|
+
},
|
|
2281
|
+
async push(locale, data, originalInput) {
|
|
2282
|
+
const jsonData = JSON.parse(data);
|
|
2283
|
+
const result = formatPlutilStyle(jsonData, originalInput || "");
|
|
2284
|
+
console.log(result[result.length - 1]);
|
|
2285
|
+
return result;
|
|
2286
|
+
}
|
|
2287
|
+
});
|
|
2288
|
+
}
|
|
2289
|
+
|
|
2290
|
+
// src/cli/loaders/new-line.ts
|
|
2291
|
+
function createNewLineLoader() {
|
|
2292
|
+
return createLoader({
|
|
2293
|
+
async pull(locale, input) {
|
|
2294
|
+
return input;
|
|
2295
|
+
},
|
|
2296
|
+
async push(locale, data, originalInput) {
|
|
2297
|
+
if (!data) return "";
|
|
2298
|
+
const trimmed = data.replace(/[\r\n]+$/, "");
|
|
2299
|
+
if (originalInput?.match(/[\r\n]$/)) {
|
|
2300
|
+
const ending = originalInput?.includes("\r\n") ? "\r\n" : originalInput?.includes("\r") ? "\r" : "\n";
|
|
2301
|
+
return trimmed + ending;
|
|
2302
|
+
}
|
|
2303
|
+
return trimmed;
|
|
2304
|
+
}
|
|
2305
|
+
});
|
|
2306
|
+
}
|
|
2307
|
+
|
|
2221
2308
|
// src/cli/loaders/index.ts
|
|
2222
2309
|
function createBucketLoader(bucketType, bucketPathPattern) {
|
|
2223
2310
|
switch (bucketType) {
|
|
@@ -2226,6 +2313,7 @@ function createBucketLoader(bucketType, bucketPathPattern) {
|
|
|
2226
2313
|
case "android":
|
|
2227
2314
|
return composeLoaders(
|
|
2228
2315
|
createTextFileLoader(bucketPathPattern),
|
|
2316
|
+
createNewLineLoader(),
|
|
2229
2317
|
createAndroidLoader(),
|
|
2230
2318
|
createFlatLoader(),
|
|
2231
2319
|
createSyncLoader(),
|
|
@@ -2234,6 +2322,7 @@ function createBucketLoader(bucketType, bucketPathPattern) {
|
|
|
2234
2322
|
case "csv":
|
|
2235
2323
|
return composeLoaders(
|
|
2236
2324
|
createTextFileLoader(bucketPathPattern),
|
|
2325
|
+
createNewLineLoader(),
|
|
2237
2326
|
createCsvLoader(),
|
|
2238
2327
|
createFlatLoader(),
|
|
2239
2328
|
createSyncLoader(),
|
|
@@ -2242,6 +2331,7 @@ function createBucketLoader(bucketType, bucketPathPattern) {
|
|
|
2242
2331
|
case "html":
|
|
2243
2332
|
return composeLoaders(
|
|
2244
2333
|
createTextFileLoader(bucketPathPattern),
|
|
2334
|
+
createNewLineLoader(),
|
|
2245
2335
|
createPrettierLoader({ parser: "html", alwaysFormat: true }),
|
|
2246
2336
|
createHtmlLoader(),
|
|
2247
2337
|
createSyncLoader(),
|
|
@@ -2250,6 +2340,7 @@ function createBucketLoader(bucketType, bucketPathPattern) {
|
|
|
2250
2340
|
case "json":
|
|
2251
2341
|
return composeLoaders(
|
|
2252
2342
|
createTextFileLoader(bucketPathPattern),
|
|
2343
|
+
createNewLineLoader(),
|
|
2253
2344
|
createPrettierLoader({ parser: "json" }),
|
|
2254
2345
|
createJsonLoader(),
|
|
2255
2346
|
createFlatLoader(),
|
|
@@ -2259,6 +2350,7 @@ function createBucketLoader(bucketType, bucketPathPattern) {
|
|
|
2259
2350
|
case "markdown":
|
|
2260
2351
|
return composeLoaders(
|
|
2261
2352
|
createTextFileLoader(bucketPathPattern),
|
|
2353
|
+
createNewLineLoader(),
|
|
2262
2354
|
createPrettierLoader({ parser: "markdown" }),
|
|
2263
2355
|
createMarkdownLoader(),
|
|
2264
2356
|
createSyncLoader(),
|
|
@@ -2267,6 +2359,7 @@ function createBucketLoader(bucketType, bucketPathPattern) {
|
|
|
2267
2359
|
case "po":
|
|
2268
2360
|
return composeLoaders(
|
|
2269
2361
|
createTextFileLoader(bucketPathPattern),
|
|
2362
|
+
createNewLineLoader(),
|
|
2270
2363
|
createPoLoader(),
|
|
2271
2364
|
createFlatLoader(),
|
|
2272
2365
|
createSyncLoader(),
|
|
@@ -2276,6 +2369,7 @@ function createBucketLoader(bucketType, bucketPathPattern) {
|
|
|
2276
2369
|
case "properties":
|
|
2277
2370
|
return composeLoaders(
|
|
2278
2371
|
createTextFileLoader(bucketPathPattern),
|
|
2372
|
+
createNewLineLoader(),
|
|
2279
2373
|
createPropertiesLoader(),
|
|
2280
2374
|
createSyncLoader(),
|
|
2281
2375
|
createUnlocalizableLoader()
|
|
@@ -2283,6 +2377,7 @@ function createBucketLoader(bucketType, bucketPathPattern) {
|
|
|
2283
2377
|
case "xcode-strings":
|
|
2284
2378
|
return composeLoaders(
|
|
2285
2379
|
createTextFileLoader(bucketPathPattern),
|
|
2380
|
+
createNewLineLoader(),
|
|
2286
2381
|
createXcodeStringsLoader(),
|
|
2287
2382
|
createSyncLoader(),
|
|
2288
2383
|
createUnlocalizableLoader()
|
|
@@ -2290,6 +2385,7 @@ function createBucketLoader(bucketType, bucketPathPattern) {
|
|
|
2290
2385
|
case "xcode-stringsdict":
|
|
2291
2386
|
return composeLoaders(
|
|
2292
2387
|
createTextFileLoader(bucketPathPattern),
|
|
2388
|
+
createNewLineLoader(),
|
|
2293
2389
|
createXcodeStringsdictLoader(),
|
|
2294
2390
|
createFlatLoader(),
|
|
2295
2391
|
createSyncLoader(),
|
|
@@ -2298,7 +2394,8 @@ function createBucketLoader(bucketType, bucketPathPattern) {
|
|
|
2298
2394
|
case "xcode-xcstrings":
|
|
2299
2395
|
return composeLoaders(
|
|
2300
2396
|
createTextFileLoader(bucketPathPattern),
|
|
2301
|
-
|
|
2397
|
+
createNewLineLoader(),
|
|
2398
|
+
createPlutilJsonTextLoader(),
|
|
2302
2399
|
createJsonLoader(),
|
|
2303
2400
|
createXcodeXcstringsLoader(),
|
|
2304
2401
|
createFlatLoader(),
|
|
@@ -2309,6 +2406,7 @@ function createBucketLoader(bucketType, bucketPathPattern) {
|
|
|
2309
2406
|
case "yaml":
|
|
2310
2407
|
return composeLoaders(
|
|
2311
2408
|
createTextFileLoader(bucketPathPattern),
|
|
2409
|
+
createNewLineLoader(),
|
|
2312
2410
|
createPrettierLoader({ parser: "yaml" }),
|
|
2313
2411
|
createYamlLoader(),
|
|
2314
2412
|
createFlatLoader(),
|
|
@@ -2318,6 +2416,7 @@ function createBucketLoader(bucketType, bucketPathPattern) {
|
|
|
2318
2416
|
case "yaml-root-key":
|
|
2319
2417
|
return composeLoaders(
|
|
2320
2418
|
createTextFileLoader(bucketPathPattern),
|
|
2419
|
+
createNewLineLoader(),
|
|
2321
2420
|
createPrettierLoader({ parser: "yaml" }),
|
|
2322
2421
|
createYamlLoader(),
|
|
2323
2422
|
createRootKeyLoader(true),
|
|
@@ -2328,6 +2427,7 @@ function createBucketLoader(bucketType, bucketPathPattern) {
|
|
|
2328
2427
|
case "flutter":
|
|
2329
2428
|
return composeLoaders(
|
|
2330
2429
|
createTextFileLoader(bucketPathPattern),
|
|
2430
|
+
createNewLineLoader(),
|
|
2331
2431
|
createPrettierLoader({ parser: "json" }),
|
|
2332
2432
|
createJsonLoader(),
|
|
2333
2433
|
createFlutterLoader(),
|
|
@@ -2338,6 +2438,7 @@ function createBucketLoader(bucketType, bucketPathPattern) {
|
|
|
2338
2438
|
case "xliff":
|
|
2339
2439
|
return composeLoaders(
|
|
2340
2440
|
createTextFileLoader(bucketPathPattern),
|
|
2441
|
+
createNewLineLoader(),
|
|
2341
2442
|
createXliffLoader(),
|
|
2342
2443
|
createFlatLoader(),
|
|
2343
2444
|
createSyncLoader(),
|
|
@@ -2346,6 +2447,7 @@ function createBucketLoader(bucketType, bucketPathPattern) {
|
|
|
2346
2447
|
case "xml":
|
|
2347
2448
|
return composeLoaders(
|
|
2348
2449
|
createTextFileLoader(bucketPathPattern),
|
|
2450
|
+
createNewLineLoader(),
|
|
2349
2451
|
createXmlLoader(),
|
|
2350
2452
|
createFlatLoader(),
|
|
2351
2453
|
createSyncLoader(),
|
|
@@ -2354,6 +2456,7 @@ function createBucketLoader(bucketType, bucketPathPattern) {
|
|
|
2354
2456
|
case "srt":
|
|
2355
2457
|
return composeLoaders(
|
|
2356
2458
|
createTextFileLoader(bucketPathPattern),
|
|
2459
|
+
createNewLineLoader(),
|
|
2357
2460
|
createSrtLoader(),
|
|
2358
2461
|
createSyncLoader(),
|
|
2359
2462
|
createUnlocalizableLoader()
|
|
@@ -2361,6 +2464,7 @@ function createBucketLoader(bucketType, bucketPathPattern) {
|
|
|
2361
2464
|
case "dato":
|
|
2362
2465
|
return composeLoaders(
|
|
2363
2466
|
createDatoLoader(bucketPathPattern),
|
|
2467
|
+
createNewLineLoader(),
|
|
2364
2468
|
createSyncLoader(),
|
|
2365
2469
|
createFlatLoader(),
|
|
2366
2470
|
createUnlocalizableLoader()
|
|
@@ -2368,6 +2472,7 @@ function createBucketLoader(bucketType, bucketPathPattern) {
|
|
|
2368
2472
|
case "vtt":
|
|
2369
2473
|
return composeLoaders(
|
|
2370
2474
|
createTextFileLoader(bucketPathPattern),
|
|
2475
|
+
createNewLineLoader(),
|
|
2371
2476
|
createVttLoader(),
|
|
2372
2477
|
createSyncLoader(),
|
|
2373
2478
|
createUnlocalizableLoader()
|
|
@@ -2395,6 +2500,13 @@ function createLockfileHelper() {
|
|
|
2395
2500
|
lockfile.checksums[sectionKey] = sectionChecksums;
|
|
2396
2501
|
_saveLockfile(lockfile);
|
|
2397
2502
|
},
|
|
2503
|
+
registerPartialSourceData: (pathPattern, partialSourceData) => {
|
|
2504
|
+
const lockfile = _loadLockfile();
|
|
2505
|
+
const sectionKey = MD5(pathPattern);
|
|
2506
|
+
const sectionChecksums = _16.mapValues(partialSourceData, (value) => MD5(value));
|
|
2507
|
+
lockfile.checksums[sectionKey] = _16.merge({}, lockfile.checksums[sectionKey] ?? {}, sectionChecksums);
|
|
2508
|
+
_saveLockfile(lockfile);
|
|
2509
|
+
},
|
|
2398
2510
|
extractUpdatedData: (pathPattern, sourceData) => {
|
|
2399
2511
|
const lockfile = _loadLockfile();
|
|
2400
2512
|
const sectionKey = MD5(pathPattern);
|
|
@@ -2437,11 +2549,80 @@ var LockfileSchema = Z3.object({
|
|
|
2437
2549
|
).default({})
|
|
2438
2550
|
});
|
|
2439
2551
|
|
|
2440
|
-
// src/cli/
|
|
2552
|
+
// src/cli/cmd/i18n.ts
|
|
2441
2553
|
import chalk from "chalk";
|
|
2442
2554
|
import { createTwoFilesPatch } from "diff";
|
|
2443
2555
|
import inquirer2 from "inquirer";
|
|
2444
2556
|
import externalEditor from "external-editor";
|
|
2557
|
+
|
|
2558
|
+
// src/cli/utils/cache.ts
|
|
2559
|
+
import path7 from "path";
|
|
2560
|
+
import fs8 from "fs";
|
|
2561
|
+
var cacheChunk = (targetLocale, sourceChunk, processedChunk) => {
|
|
2562
|
+
const rows = Object.entries(sourceChunk).map(([key, source]) => ({
|
|
2563
|
+
targetLocale,
|
|
2564
|
+
key,
|
|
2565
|
+
source,
|
|
2566
|
+
processed: processedChunk[key]
|
|
2567
|
+
}));
|
|
2568
|
+
_appendToCache(rows);
|
|
2569
|
+
};
|
|
2570
|
+
function getNormalizedCache() {
|
|
2571
|
+
const rows = _loadCache();
|
|
2572
|
+
if (!rows.length) {
|
|
2573
|
+
return null;
|
|
2574
|
+
}
|
|
2575
|
+
const normalized = {};
|
|
2576
|
+
for (const row of rows) {
|
|
2577
|
+
if (!normalized[row.targetLocale]) {
|
|
2578
|
+
normalized[row.targetLocale] = {};
|
|
2579
|
+
}
|
|
2580
|
+
normalized[row.targetLocale][row.key] = {
|
|
2581
|
+
source: row.source,
|
|
2582
|
+
result: row.processed
|
|
2583
|
+
};
|
|
2584
|
+
}
|
|
2585
|
+
return normalized;
|
|
2586
|
+
}
|
|
2587
|
+
function deleteCache() {
|
|
2588
|
+
const cacheFilePath = _getCacheFilePath();
|
|
2589
|
+
try {
|
|
2590
|
+
fs8.unlinkSync(cacheFilePath);
|
|
2591
|
+
} catch (e) {
|
|
2592
|
+
}
|
|
2593
|
+
}
|
|
2594
|
+
function _loadCache() {
|
|
2595
|
+
const cacheFilePath = _getCacheFilePath();
|
|
2596
|
+
if (!fs8.existsSync(cacheFilePath)) {
|
|
2597
|
+
return [];
|
|
2598
|
+
}
|
|
2599
|
+
const content = fs8.readFileSync(cacheFilePath, "utf-8");
|
|
2600
|
+
const result = _parseJSONLines(content);
|
|
2601
|
+
return result;
|
|
2602
|
+
}
|
|
2603
|
+
function _appendToCache(rows) {
|
|
2604
|
+
const cacheFilePath = _getCacheFilePath();
|
|
2605
|
+
const lines = _buildJSONLines(rows);
|
|
2606
|
+
fs8.appendFileSync(cacheFilePath, lines);
|
|
2607
|
+
}
|
|
2608
|
+
function _getCacheFilePath() {
|
|
2609
|
+
return path7.join(process.cwd(), "i18n.cache");
|
|
2610
|
+
}
|
|
2611
|
+
function _buildJSONLines(rows) {
|
|
2612
|
+
return rows.map((row) => JSON.stringify(row)).join("\n") + "\n";
|
|
2613
|
+
}
|
|
2614
|
+
function _parseJSONLines(lines) {
|
|
2615
|
+
return lines.split("\n").map(_tryParseJSON).filter((line) => line !== null);
|
|
2616
|
+
}
|
|
2617
|
+
function _tryParseJSON(line) {
|
|
2618
|
+
try {
|
|
2619
|
+
return JSON.parse(line);
|
|
2620
|
+
} catch (e) {
|
|
2621
|
+
return null;
|
|
2622
|
+
}
|
|
2623
|
+
}
|
|
2624
|
+
|
|
2625
|
+
// src/cli/cmd/i18n.ts
|
|
2445
2626
|
var i18n_default = new Command6().command("i18n").description("Run Localization engine").helpOption("-h, --help", "Show help").option("--locale <locale>", "Locale to process", (val, prev) => prev ? [...prev, val] : [val]).option("--bucket <bucket>", "Bucket to process", (val, prev) => prev ? [...prev, val] : [val]).option("--key <key>", "Key to process").option("--frozen", `Don't update the translations and fail if an update is needed`).option("--force", "Ignore lockfile and process all keys").option("--verbose", "Show verbose output").option("--interactive", "Interactive mode").option("--api-key <api-key>", "Explicitly set the API key to use").option("--debug", "Debug mode").option("--strict", "Stop on first error").action(async function(options) {
|
|
2446
2627
|
const ora = Ora5();
|
|
2447
2628
|
const flags = parseFlags(options);
|
|
@@ -2490,6 +2671,45 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
|
|
|
2490
2671
|
} else {
|
|
2491
2672
|
ora.succeed("i18n.lock loaded");
|
|
2492
2673
|
}
|
|
2674
|
+
const cache = getNormalizedCache();
|
|
2675
|
+
if (cache) {
|
|
2676
|
+
console.log();
|
|
2677
|
+
ora.succeed(`Cache loaded. Attempting recovery...`);
|
|
2678
|
+
const cacheOra = Ora5({ indent: 2 });
|
|
2679
|
+
for (const bucket of buckets) {
|
|
2680
|
+
cacheOra.info(`Processing bucket: ${bucket.type}`);
|
|
2681
|
+
for (const bucketConfig of bucket.config) {
|
|
2682
|
+
const bucketOra = ora.info(`Processing path: ${bucketConfig.pathPattern}`);
|
|
2683
|
+
const sourceLocale = resolveOverridenLocale(i18nConfig.locale.source, bucketConfig.delimiter);
|
|
2684
|
+
const bucketLoader = createBucketLoader(bucket.type, bucketConfig.pathPattern);
|
|
2685
|
+
bucketLoader.setDefaultLocale(sourceLocale);
|
|
2686
|
+
await bucketLoader.init();
|
|
2687
|
+
const sourceData = await bucketLoader.pull(sourceLocale);
|
|
2688
|
+
const cachedSourceData = {};
|
|
2689
|
+
for (const targetLocale in cache) {
|
|
2690
|
+
const targetData = await bucketLoader.pull(targetLocale);
|
|
2691
|
+
for (const key in cache[targetLocale]) {
|
|
2692
|
+
const { source, result } = cache[targetLocale][key];
|
|
2693
|
+
if (sourceData[key] === source && targetData[key] !== result) {
|
|
2694
|
+
targetData[key] = result;
|
|
2695
|
+
cachedSourceData[key] = source;
|
|
2696
|
+
}
|
|
2697
|
+
}
|
|
2698
|
+
await bucketLoader.push(targetLocale, targetData);
|
|
2699
|
+
lockfileHelper.registerPartialSourceData(bucketConfig.pathPattern, cachedSourceData);
|
|
2700
|
+
bucketOra.succeed(
|
|
2701
|
+
`[${sourceLocale} -> ${targetLocale}] Recovered ${Object.keys(cachedSourceData).length} entries from cache`
|
|
2702
|
+
);
|
|
2703
|
+
}
|
|
2704
|
+
}
|
|
2705
|
+
}
|
|
2706
|
+
deleteCache();
|
|
2707
|
+
if (flags.verbose) {
|
|
2708
|
+
cacheOra.info("Cache file deleted.");
|
|
2709
|
+
}
|
|
2710
|
+
} else if (flags.verbose) {
|
|
2711
|
+
ora.info("Cache file not found. Skipping recovery.");
|
|
2712
|
+
}
|
|
2493
2713
|
if (flags.frozen) {
|
|
2494
2714
|
ora.start("Checking for lockfile updates...");
|
|
2495
2715
|
let requiresUpdate = false;
|
|
@@ -2559,8 +2779,17 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
|
|
|
2559
2779
|
targetLocale,
|
|
2560
2780
|
targetData
|
|
2561
2781
|
},
|
|
2562
|
-
(progress) => {
|
|
2563
|
-
|
|
2782
|
+
(progress, sourceChunk, processedChunk) => {
|
|
2783
|
+
cacheChunk(targetLocale, sourceChunk, processedChunk);
|
|
2784
|
+
const progressLog = `[${sourceLocale} -> ${targetLocale}] [${Object.keys(processableData).length} entries] (${progress}%) AI localization in progress...`;
|
|
2785
|
+
if (flags.verbose) {
|
|
2786
|
+
ora.info(progressLog);
|
|
2787
|
+
ora.info(
|
|
2788
|
+
`Caching chunk ${JSON.stringify(sourceChunk, null, 2)} -> ${JSON.stringify(processedChunk, null, 2)}`
|
|
2789
|
+
);
|
|
2790
|
+
} else {
|
|
2791
|
+
ora.text = progressLog;
|
|
2792
|
+
}
|
|
2564
2793
|
}
|
|
2565
2794
|
);
|
|
2566
2795
|
if (flags.verbose) {
|
|
@@ -2612,6 +2841,10 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
|
|
|
2612
2841
|
console.log();
|
|
2613
2842
|
if (!hasErrors) {
|
|
2614
2843
|
ora.succeed("Localization completed.");
|
|
2844
|
+
deleteCache();
|
|
2845
|
+
if (flags.verbose) {
|
|
2846
|
+
ora.info("Cache file deleted.");
|
|
2847
|
+
}
|
|
2615
2848
|
} else {
|
|
2616
2849
|
ora.warn("Localization completed with errors.");
|
|
2617
2850
|
}
|
|
@@ -2812,7 +3045,7 @@ Editing value for: ${chalk.cyan(key)}`);
|
|
|
2812
3045
|
return customData;
|
|
2813
3046
|
}
|
|
2814
3047
|
|
|
2815
|
-
// src/cli/
|
|
3048
|
+
// src/cli/cmd/lockfile.ts
|
|
2816
3049
|
import { Command as Command7 } from "interactive-commander";
|
|
2817
3050
|
import Z5 from "zod";
|
|
2818
3051
|
import Ora6 from "ora";
|
|
@@ -2841,7 +3074,7 @@ var flagsSchema = Z5.object({
|
|
|
2841
3074
|
force: Z5.boolean().default(false)
|
|
2842
3075
|
});
|
|
2843
3076
|
|
|
2844
|
-
// src/cli/
|
|
3077
|
+
// src/cli/cmd/cleanup.ts
|
|
2845
3078
|
import { Command as Command8 } from "interactive-commander";
|
|
2846
3079
|
import _18 from "lodash";
|
|
2847
3080
|
import Ora7 from "ora";
|
|
@@ -2934,7 +3167,7 @@ function displaySummary(results) {
|
|
|
2934
3167
|
// package.json
|
|
2935
3168
|
var package_default = {
|
|
2936
3169
|
name: "lingo.dev",
|
|
2937
|
-
version: "0.
|
|
3170
|
+
version: "0.72.0",
|
|
2938
3171
|
description: "Lingo.dev CLI",
|
|
2939
3172
|
private: false,
|
|
2940
3173
|
type: "module",
|
|
@@ -2964,7 +3197,7 @@ var package_default = {
|
|
|
2964
3197
|
"build"
|
|
2965
3198
|
],
|
|
2966
3199
|
scripts: {
|
|
2967
|
-
"lingo.dev": "node ./bin/cli.mjs",
|
|
3200
|
+
"lingo.dev": "node --inspect=9229 ./bin/cli.mjs",
|
|
2968
3201
|
dev: "tsup --watch",
|
|
2969
3202
|
build: "tsc --noEmit && tsup",
|
|
2970
3203
|
test: "vitest run",
|
|
@@ -2986,9 +3219,12 @@ var package_default = {
|
|
|
2986
3219
|
dotenv: "^16.4.7",
|
|
2987
3220
|
express: "^4.21.2",
|
|
2988
3221
|
"external-editor": "^3.1.0",
|
|
3222
|
+
figlet: "^1.8.0",
|
|
3223
|
+
"figlet-cli": "^0.2.0",
|
|
2989
3224
|
flat: "^6.0.1",
|
|
2990
3225
|
"gettext-parser": "^8.0.0",
|
|
2991
3226
|
glob: "<11.0.0",
|
|
3227
|
+
"gradient-string": "^3.0.0",
|
|
2992
3228
|
"gray-matter": "^4.0.3",
|
|
2993
3229
|
ini: "^5.0.0",
|
|
2994
3230
|
inquirer: "^12.3.0",
|
|
@@ -3026,6 +3262,7 @@ var package_default = {
|
|
|
3026
3262
|
"@types/cors": "^2.8.17",
|
|
3027
3263
|
"@types/diff": "^6.0.0",
|
|
3028
3264
|
"@types/express": "^5.0.0",
|
|
3265
|
+
"@types/figlet": "^1.7.0",
|
|
3029
3266
|
"@types/gettext-parser": "^4.0.4",
|
|
3030
3267
|
"@types/glob": "^8.1.0",
|
|
3031
3268
|
"@types/ini": "^4.1.1",
|
|
@@ -3052,10 +3289,23 @@ dotenv.config();
|
|
|
3052
3289
|
var cli_default = new InteractiveCommand2().name("lingo.dev").description("Lingo.dev CLI").helpOption("-h, --help", "Show help").addHelpText(
|
|
3053
3290
|
"beforeAll",
|
|
3054
3291
|
`
|
|
3055
|
-
|
|
3292
|
+
${vice(
|
|
3293
|
+
figlet.textSync("LINGO.DEV", {
|
|
3294
|
+
font: "ANSI Shadow",
|
|
3295
|
+
horizontalLayout: "default",
|
|
3296
|
+
verticalLayout: "default"
|
|
3297
|
+
})
|
|
3298
|
+
)}
|
|
3299
|
+
|
|
3056
3300
|
Website: https://lingo.dev
|
|
3057
3301
|
`
|
|
3058
|
-
).version(`v${package_default.version}`, "-v, --version", "Show version").addCommand(init_default).interactive("-y, --no-interactive", "Disable interactive mode").addCommand(i18n_default).addCommand(auth_default).addCommand(show_default).addCommand(lockfile_default).addCommand(cleanup_default)
|
|
3302
|
+
).version(`v${package_default.version}`, "-v, --version", "Show version").addCommand(init_default).interactive("-y, --no-interactive", "Disable interactive mode").addCommand(i18n_default).addCommand(auth_default).addCommand(show_default).addCommand(lockfile_default).addCommand(cleanup_default).exitOverride((err) => {
|
|
3303
|
+
if (err.code === "commander.helpDisplayed" || err.code === "commander.version" || err.code === "commander.help") {
|
|
3304
|
+
process.exit(0);
|
|
3305
|
+
}
|
|
3306
|
+
throw err;
|
|
3307
|
+
});
|
|
3059
3308
|
export {
|
|
3060
3309
|
cli_default as default
|
|
3061
3310
|
};
|
|
3311
|
+
//# sourceMappingURL=cli.mjs.map
|