lingo.dev 0.80.1 → 0.82.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/cli.cjs +509 -276
- package/build/cli.cjs.map +1 -1
- package/build/cli.mjs +426 -193
- package/build/cli.mjs.map +1 -1
- package/package.json +3 -3
package/build/cli.mjs
CHANGED
|
@@ -621,9 +621,9 @@ function makeGitlabInitializer(spinner) {
|
|
|
621
621
|
|
|
622
622
|
// src/cli/cmd/init.ts
|
|
623
623
|
import open2 from "open";
|
|
624
|
-
var openUrl = (
|
|
624
|
+
var openUrl = (path18) => {
|
|
625
625
|
const settings = getSettings(void 0);
|
|
626
|
-
open2(`${settings.auth.webUrl}${
|
|
626
|
+
open2(`${settings.auth.webUrl}${path18}`, { wait: false });
|
|
627
627
|
};
|
|
628
628
|
var throwHelpError = (option, value) => {
|
|
629
629
|
if (value === "help") {
|
|
@@ -862,6 +862,9 @@ function getBuckets(i18nConfig) {
|
|
|
862
862
|
if (bucketEntry.injectLocale) {
|
|
863
863
|
config.injectLocale = bucketEntry.injectLocale;
|
|
864
864
|
}
|
|
865
|
+
if (bucketEntry.lockedKeys) {
|
|
866
|
+
config.lockedKeys = bucketEntry.lockedKeys;
|
|
867
|
+
}
|
|
865
868
|
return config;
|
|
866
869
|
});
|
|
867
870
|
return result;
|
|
@@ -967,8 +970,8 @@ var files_default = new Command4().command("files").description("Print out the l
|
|
|
967
970
|
} else if (type.target) {
|
|
968
971
|
result.push(...targetPaths);
|
|
969
972
|
}
|
|
970
|
-
result.forEach((
|
|
971
|
-
console.log(
|
|
973
|
+
result.forEach((path18) => {
|
|
974
|
+
console.log(path18);
|
|
972
975
|
});
|
|
973
976
|
}
|
|
974
977
|
}
|
|
@@ -990,8 +993,9 @@ var show_default = new Command5().command("show").description("Prints out the cu
|
|
|
990
993
|
// src/cli/cmd/i18n.ts
|
|
991
994
|
import { bucketTypeSchema, localeCodeSchema, resolveOverriddenLocale as resolveOverriddenLocale3 } from "@lingo.dev/_spec";
|
|
992
995
|
import { Command as Command6 } from "interactive-commander";
|
|
993
|
-
import
|
|
994
|
-
import
|
|
996
|
+
import Z3 from "zod";
|
|
997
|
+
import _21 from "lodash";
|
|
998
|
+
import * as path15 from "path";
|
|
995
999
|
import Ora5 from "ora";
|
|
996
1000
|
|
|
997
1001
|
// src/cli/loaders/_utils.ts
|
|
@@ -1198,7 +1202,7 @@ function createTextFileLoader(pathPattern) {
|
|
|
1198
1202
|
const trimmedResult = result.trim();
|
|
1199
1203
|
return trimmedResult;
|
|
1200
1204
|
},
|
|
1201
|
-
async push(locale, data,
|
|
1205
|
+
async push(locale, data, _24, originalLocale) {
|
|
1202
1206
|
const draftPath = pathPattern.replaceAll("[locale]", locale);
|
|
1203
1207
|
const finalPath = path10.resolve(draftPath);
|
|
1204
1208
|
const dirPath = path10.dirname(finalPath);
|
|
@@ -1535,9 +1539,9 @@ function createHtmlLoader() {
|
|
|
1535
1539
|
const bDepth = b.split("/").length;
|
|
1536
1540
|
return aDepth - bDepth;
|
|
1537
1541
|
});
|
|
1538
|
-
paths.forEach((
|
|
1539
|
-
const value = data[
|
|
1540
|
-
const [nodePath, attribute] =
|
|
1542
|
+
paths.forEach((path18) => {
|
|
1543
|
+
const value = data[path18];
|
|
1544
|
+
const [nodePath, attribute] = path18.split("#");
|
|
1541
1545
|
const [rootTag, ...indices] = nodePath.split("/");
|
|
1542
1546
|
let parent = rootTag === "head" ? document.head : document.body;
|
|
1543
1547
|
let current = parent;
|
|
@@ -1640,7 +1644,7 @@ function createPropertiesLoader() {
|
|
|
1640
1644
|
return result;
|
|
1641
1645
|
},
|
|
1642
1646
|
async push(locale, payload) {
|
|
1643
|
-
const result = Object.entries(payload).filter(([
|
|
1647
|
+
const result = Object.entries(payload).filter(([_24, value]) => value != null).map(([key, value]) => `${key}=${value}`).join("\n");
|
|
1644
1648
|
return result;
|
|
1645
1649
|
}
|
|
1646
1650
|
});
|
|
@@ -1889,10 +1893,10 @@ function createUnlocalizableLoader(isCacheRestore = false, returnUnlocalizedKeys
|
|
|
1889
1893
|
}
|
|
1890
1894
|
}
|
|
1891
1895
|
return false;
|
|
1892
|
-
}).map(([key,
|
|
1893
|
-
const result = _10.omitBy(input2, (
|
|
1896
|
+
}).map(([key, _24]) => key);
|
|
1897
|
+
const result = _10.omitBy(input2, (_24, key) => passthroughKeys.includes(key));
|
|
1894
1898
|
if (returnUnlocalizedKeys) {
|
|
1895
|
-
result.unlocalizable = _10.omitBy(input2, (
|
|
1899
|
+
result.unlocalizable = _10.omitBy(input2, (_24, key) => !passthroughKeys.includes(key));
|
|
1896
1900
|
}
|
|
1897
1901
|
return result;
|
|
1898
1902
|
},
|
|
@@ -2583,18 +2587,18 @@ function createRawDatoValue(parsedDatoValue, originalRawDatoValue, isClean = fal
|
|
|
2583
2587
|
}
|
|
2584
2588
|
function serializeStructuredText(rawStructuredText) {
|
|
2585
2589
|
return serializeStructuredTextNode(rawStructuredText);
|
|
2586
|
-
function serializeStructuredTextNode(node,
|
|
2590
|
+
function serializeStructuredTextNode(node, path18 = [], acc = {}) {
|
|
2587
2591
|
if ("document" in node) {
|
|
2588
|
-
return serializeStructuredTextNode(node.document, [...
|
|
2592
|
+
return serializeStructuredTextNode(node.document, [...path18, "document"], acc);
|
|
2589
2593
|
}
|
|
2590
2594
|
if (!_15.isNil(node.value)) {
|
|
2591
|
-
acc[[...
|
|
2595
|
+
acc[[...path18, "value"].join(".")] = node.value;
|
|
2592
2596
|
} else if (_15.get(node, "type") === "block") {
|
|
2593
|
-
acc[[...
|
|
2597
|
+
acc[[...path18, "item"].join(".")] = serializeBlock(node.item);
|
|
2594
2598
|
}
|
|
2595
2599
|
if (node.children) {
|
|
2596
2600
|
for (let i = 0; i < node.children.length; i++) {
|
|
2597
|
-
serializeStructuredTextNode(node.children[i], [...
|
|
2601
|
+
serializeStructuredTextNode(node.children[i], [...path18, i.toString()], acc);
|
|
2598
2602
|
}
|
|
2599
2603
|
}
|
|
2600
2604
|
return acc;
|
|
@@ -2653,8 +2657,8 @@ function deserializeBlockList(parsedBlockList, originalRawBlockList, isClean = f
|
|
|
2653
2657
|
}
|
|
2654
2658
|
function deserializeStructuredText(parsedStructuredText, originalRawStructuredText) {
|
|
2655
2659
|
const result = _15.cloneDeep(originalRawStructuredText);
|
|
2656
|
-
for (const [
|
|
2657
|
-
const realPath = _15.chain(
|
|
2660
|
+
for (const [path18, value] of _15.entries(parsedStructuredText)) {
|
|
2661
|
+
const realPath = _15.chain(path18.split(".")).flatMap((s) => !_15.isNaN(_15.toNumber(s)) ? ["children", s] : s).value();
|
|
2658
2662
|
const deserializedValue = createRawDatoValue(value, _15.get(originalRawStructuredText, realPath), true);
|
|
2659
2663
|
_15.set(result, realPath, deserializedValue);
|
|
2660
2664
|
}
|
|
@@ -3005,8 +3009,24 @@ function createInjectLocaleLoader(injectLocaleKeys) {
|
|
|
3005
3009
|
});
|
|
3006
3010
|
}
|
|
3007
3011
|
|
|
3012
|
+
// src/cli/loaders/locked-keys.ts
|
|
3013
|
+
import _19 from "lodash";
|
|
3014
|
+
function createLockedKeysLoader(lockedKeys, isCacheRestore = false) {
|
|
3015
|
+
return createLoader({
|
|
3016
|
+
pull: async (locale, data) => _19.chain(data).pickBy((value, key) => !lockedKeys.includes(key)).value(),
|
|
3017
|
+
push: async (locale, data, originalInput) => {
|
|
3018
|
+
const lockedSubObject = _19.chain(originalInput).pickBy((value, key) => lockedKeys.includes(key)).value();
|
|
3019
|
+
if (isCacheRestore) {
|
|
3020
|
+
return _19.merge({}, data, lockedSubObject);
|
|
3021
|
+
} else {
|
|
3022
|
+
return _19.merge({}, originalInput, data, lockedSubObject);
|
|
3023
|
+
}
|
|
3024
|
+
}
|
|
3025
|
+
});
|
|
3026
|
+
}
|
|
3027
|
+
|
|
3008
3028
|
// src/cli/loaders/index.ts
|
|
3009
|
-
function createBucketLoader(bucketType, bucketPathPattern, options) {
|
|
3029
|
+
function createBucketLoader(bucketType, bucketPathPattern, options, lockedKeys) {
|
|
3010
3030
|
switch (bucketType) {
|
|
3011
3031
|
default:
|
|
3012
3032
|
throw new Error(`Unsupported bucket type: ${bucketType}`);
|
|
@@ -3041,6 +3061,7 @@ function createBucketLoader(bucketType, bucketPathPattern, options) {
|
|
|
3041
3061
|
createJsonLoader(),
|
|
3042
3062
|
createInjectLocaleLoader(options.injectLocale),
|
|
3043
3063
|
createFlatLoader(),
|
|
3064
|
+
createLockedKeysLoader(lockedKeys || [], options.isCacheRestore),
|
|
3044
3065
|
createSyncLoader(),
|
|
3045
3066
|
createUnlocalizableLoader(options.isCacheRestore, options.returnUnlocalizedKeys)
|
|
3046
3067
|
);
|
|
@@ -3100,6 +3121,7 @@ function createBucketLoader(bucketType, bucketPathPattern, options) {
|
|
|
3100
3121
|
createPrettierLoader({ parser: "yaml", bucketPathPattern }),
|
|
3101
3122
|
createYamlLoader(),
|
|
3102
3123
|
createFlatLoader(),
|
|
3124
|
+
createLockedKeysLoader(lockedKeys || [], options.isCacheRestore),
|
|
3103
3125
|
createSyncLoader(),
|
|
3104
3126
|
createUnlocalizableLoader(options.isCacheRestore, options.returnUnlocalizedKeys)
|
|
3105
3127
|
);
|
|
@@ -3179,75 +3201,6 @@ function createBucketLoader(bucketType, bucketPathPattern, options) {
|
|
|
3179
3201
|
}
|
|
3180
3202
|
}
|
|
3181
3203
|
|
|
3182
|
-
// src/cli/utils/lockfile.ts
|
|
3183
|
-
import fs10 from "fs";
|
|
3184
|
-
import path12 from "path";
|
|
3185
|
-
import Z3 from "zod";
|
|
3186
|
-
import YAML3 from "yaml";
|
|
3187
|
-
import { MD5 } from "object-hash";
|
|
3188
|
-
import _19 from "lodash";
|
|
3189
|
-
function createLockfileHelper() {
|
|
3190
|
-
return {
|
|
3191
|
-
isLockfileExists: () => {
|
|
3192
|
-
const lockfilePath = _getLockfilePath();
|
|
3193
|
-
return fs10.existsSync(lockfilePath);
|
|
3194
|
-
},
|
|
3195
|
-
registerSourceData: (pathPattern, sourceData) => {
|
|
3196
|
-
const lockfile = _loadLockfile();
|
|
3197
|
-
const sectionKey = MD5(pathPattern);
|
|
3198
|
-
const sectionChecksums = _19.mapValues(sourceData, (value) => MD5(value));
|
|
3199
|
-
lockfile.checksums[sectionKey] = sectionChecksums;
|
|
3200
|
-
_saveLockfile(lockfile);
|
|
3201
|
-
},
|
|
3202
|
-
registerPartialSourceData: (pathPattern, partialSourceData) => {
|
|
3203
|
-
const lockfile = _loadLockfile();
|
|
3204
|
-
const sectionKey = MD5(pathPattern);
|
|
3205
|
-
const sectionChecksums = _19.mapValues(partialSourceData, (value) => MD5(value));
|
|
3206
|
-
lockfile.checksums[sectionKey] = _19.merge({}, lockfile.checksums[sectionKey] ?? {}, sectionChecksums);
|
|
3207
|
-
_saveLockfile(lockfile);
|
|
3208
|
-
},
|
|
3209
|
-
extractUpdatedData: (pathPattern, sourceData) => {
|
|
3210
|
-
const lockfile = _loadLockfile();
|
|
3211
|
-
const sectionKey = MD5(pathPattern);
|
|
3212
|
-
const currentChecksums = _19.mapValues(sourceData, (value) => MD5(value));
|
|
3213
|
-
const savedChecksums = lockfile.checksums[sectionKey] || {};
|
|
3214
|
-
const updatedData = _19.pickBy(sourceData, (value, key) => savedChecksums[key] !== currentChecksums[key]);
|
|
3215
|
-
return updatedData;
|
|
3216
|
-
}
|
|
3217
|
-
};
|
|
3218
|
-
function _loadLockfile() {
|
|
3219
|
-
const lockfilePath = _getLockfilePath();
|
|
3220
|
-
if (!fs10.existsSync(lockfilePath)) {
|
|
3221
|
-
return LockfileSchema.parse({});
|
|
3222
|
-
}
|
|
3223
|
-
const content = fs10.readFileSync(lockfilePath, "utf-8");
|
|
3224
|
-
const result = LockfileSchema.parse(YAML3.parse(content));
|
|
3225
|
-
return result;
|
|
3226
|
-
}
|
|
3227
|
-
function _saveLockfile(lockfile) {
|
|
3228
|
-
const lockfilePath = _getLockfilePath();
|
|
3229
|
-
const content = YAML3.stringify(lockfile);
|
|
3230
|
-
fs10.writeFileSync(lockfilePath, content);
|
|
3231
|
-
}
|
|
3232
|
-
function _getLockfilePath() {
|
|
3233
|
-
return path12.join(process.cwd(), "i18n.lock");
|
|
3234
|
-
}
|
|
3235
|
-
}
|
|
3236
|
-
var LockfileSchema = Z3.object({
|
|
3237
|
-
version: Z3.literal(1).default(1),
|
|
3238
|
-
checksums: Z3.record(
|
|
3239
|
-
Z3.string(),
|
|
3240
|
-
// localizable files' keys
|
|
3241
|
-
Z3.record(
|
|
3242
|
-
// checksums hashmap
|
|
3243
|
-
Z3.string(),
|
|
3244
|
-
// key
|
|
3245
|
-
Z3.string()
|
|
3246
|
-
// checksum of the key's value in the source locale
|
|
3247
|
-
).default({})
|
|
3248
|
-
).default({})
|
|
3249
|
-
});
|
|
3250
|
-
|
|
3251
3204
|
// src/cli/cmd/i18n.ts
|
|
3252
3205
|
import chalk from "chalk";
|
|
3253
3206
|
import { createTwoFilesPatch } from "diff";
|
|
@@ -3255,8 +3208,8 @@ import inquirer2 from "inquirer";
|
|
|
3255
3208
|
import externalEditor from "external-editor";
|
|
3256
3209
|
|
|
3257
3210
|
// src/cli/utils/cache.ts
|
|
3258
|
-
import
|
|
3259
|
-
import
|
|
3211
|
+
import path12 from "path";
|
|
3212
|
+
import fs10 from "fs";
|
|
3260
3213
|
var cacheChunk = (targetLocale, sourceChunk, processedChunk) => {
|
|
3261
3214
|
const rows = Object.entries(sourceChunk).map(([key, source]) => ({
|
|
3262
3215
|
targetLocale,
|
|
@@ -3286,26 +3239,26 @@ function getNormalizedCache() {
|
|
|
3286
3239
|
function deleteCache() {
|
|
3287
3240
|
const cacheFilePath = _getCacheFilePath();
|
|
3288
3241
|
try {
|
|
3289
|
-
|
|
3242
|
+
fs10.unlinkSync(cacheFilePath);
|
|
3290
3243
|
} catch (e) {
|
|
3291
3244
|
}
|
|
3292
3245
|
}
|
|
3293
3246
|
function _loadCache() {
|
|
3294
3247
|
const cacheFilePath = _getCacheFilePath();
|
|
3295
|
-
if (!
|
|
3248
|
+
if (!fs10.existsSync(cacheFilePath)) {
|
|
3296
3249
|
return [];
|
|
3297
3250
|
}
|
|
3298
|
-
const content =
|
|
3251
|
+
const content = fs10.readFileSync(cacheFilePath, "utf-8");
|
|
3299
3252
|
const result = _parseJSONLines(content);
|
|
3300
3253
|
return result;
|
|
3301
3254
|
}
|
|
3302
3255
|
function _appendToCache(rows) {
|
|
3303
3256
|
const cacheFilePath = _getCacheFilePath();
|
|
3304
3257
|
const lines = _buildJSONLines(rows);
|
|
3305
|
-
|
|
3258
|
+
fs10.appendFileSync(cacheFilePath, lines);
|
|
3306
3259
|
}
|
|
3307
3260
|
function _getCacheFilePath() {
|
|
3308
|
-
return
|
|
3261
|
+
return path12.join(process.cwd(), "i18n.cache");
|
|
3309
3262
|
}
|
|
3310
3263
|
function _buildJSONLines(rows) {
|
|
3311
3264
|
return rows.map((row) => JSON.stringify(row)).join("\n") + "\n";
|
|
@@ -3325,6 +3278,9 @@ function _tryParseJSON(line) {
|
|
|
3325
3278
|
import { LingoDotDevEngine } from "@lingo.dev/_sdk";
|
|
3326
3279
|
function createLingoLocalizer(params) {
|
|
3327
3280
|
return async (input2, onProgress) => {
|
|
3281
|
+
if (!Object.keys(input2.processableData).length) {
|
|
3282
|
+
return input2.processableData;
|
|
3283
|
+
}
|
|
3328
3284
|
const lingo = new LingoDotDevEngine({
|
|
3329
3285
|
apiKey: params.apiKey,
|
|
3330
3286
|
apiUrl: params.apiUrl
|
|
@@ -3345,10 +3301,13 @@ function createLingoLocalizer(params) {
|
|
|
3345
3301
|
};
|
|
3346
3302
|
}
|
|
3347
3303
|
|
|
3348
|
-
// src/cli/processor/
|
|
3304
|
+
// src/cli/processor/basic.ts
|
|
3349
3305
|
import { generateText } from "ai";
|
|
3350
3306
|
function createBasicTranslator(model, systemPrompt) {
|
|
3351
3307
|
return async (input2, onProgress) => {
|
|
3308
|
+
if (!Object.keys(input2.processableData).length) {
|
|
3309
|
+
return input2.processableData;
|
|
3310
|
+
}
|
|
3352
3311
|
if (!process.env.OPENAI_API_KEY) {
|
|
3353
3312
|
throw new Error("OPENAI_API_KEY is not set");
|
|
3354
3313
|
}
|
|
@@ -3393,7 +3352,7 @@ function createBasicTranslator(model, systemPrompt) {
|
|
|
3393
3352
|
]
|
|
3394
3353
|
});
|
|
3395
3354
|
const result = JSON.parse(response.text);
|
|
3396
|
-
return result;
|
|
3355
|
+
return result?.data || {};
|
|
3397
3356
|
};
|
|
3398
3357
|
}
|
|
3399
3358
|
|
|
@@ -3454,20 +3413,141 @@ async function trackEvent(distinctId, event, properties) {
|
|
|
3454
3413
|
if (process.env.DO_NOT_TRACK) {
|
|
3455
3414
|
return;
|
|
3456
3415
|
}
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3416
|
+
try {
|
|
3417
|
+
const posthog = new PostHog("phc_eR0iSoQufBxNY36k0f0T15UvHJdTfHlh8rJcxsfhfXk", {
|
|
3418
|
+
host: "https://eu.i.posthog.com",
|
|
3419
|
+
flushAt: 1,
|
|
3420
|
+
flushInterval: 0
|
|
3421
|
+
});
|
|
3422
|
+
await posthog.capture({
|
|
3423
|
+
distinctId,
|
|
3424
|
+
event,
|
|
3425
|
+
properties: {
|
|
3426
|
+
...properties,
|
|
3427
|
+
meta: {
|
|
3428
|
+
version: process.env.npm_package_version,
|
|
3429
|
+
isCi: process.env.CI === "true"
|
|
3430
|
+
}
|
|
3431
|
+
}
|
|
3432
|
+
});
|
|
3433
|
+
await posthog.shutdown();
|
|
3434
|
+
} catch (error) {
|
|
3435
|
+
if (process.env.DEBUG) {
|
|
3436
|
+
console.error(error);
|
|
3437
|
+
}
|
|
3438
|
+
}
|
|
3439
|
+
}
|
|
3440
|
+
|
|
3441
|
+
// src/cli/utils/delta.ts
|
|
3442
|
+
import _20 from "lodash";
|
|
3443
|
+
import z from "zod";
|
|
3444
|
+
import { MD5 } from "object-hash";
|
|
3445
|
+
|
|
3446
|
+
// src/cli/utils/fs.ts
|
|
3447
|
+
import * as fs11 from "fs";
|
|
3448
|
+
import * as path13 from "path";
|
|
3449
|
+
function tryReadFile(filePath, defaultValue = null) {
|
|
3450
|
+
try {
|
|
3451
|
+
const content = fs11.readFileSync(filePath, "utf-8");
|
|
3452
|
+
return content;
|
|
3453
|
+
} catch (error) {
|
|
3454
|
+
return defaultValue;
|
|
3455
|
+
}
|
|
3456
|
+
}
|
|
3457
|
+
function writeFile(filePath, content) {
|
|
3458
|
+
const dir = path13.dirname(filePath);
|
|
3459
|
+
if (!fs11.existsSync(dir)) {
|
|
3460
|
+
fs11.mkdirSync(dir, { recursive: true });
|
|
3461
|
+
}
|
|
3462
|
+
fs11.writeFileSync(filePath, content);
|
|
3463
|
+
}
|
|
3464
|
+
function checkIfFileExists(filePath) {
|
|
3465
|
+
return fs11.existsSync(filePath);
|
|
3466
|
+
}
|
|
3467
|
+
|
|
3468
|
+
// src/cli/utils/delta.ts
|
|
3469
|
+
import * as path14 from "path";
|
|
3470
|
+
import YAML3 from "yaml";
|
|
3471
|
+
var LockSchema = z.object({
|
|
3472
|
+
version: z.literal(1).default(1),
|
|
3473
|
+
checksums: z.record(
|
|
3474
|
+
z.string(),
|
|
3475
|
+
// localizable files' keys
|
|
3476
|
+
// checksums hashmap
|
|
3477
|
+
z.record(
|
|
3478
|
+
// key
|
|
3479
|
+
z.string(),
|
|
3480
|
+
// checksum of the key's value in the source locale
|
|
3481
|
+
z.string()
|
|
3482
|
+
).default({})
|
|
3483
|
+
).default({})
|
|
3484
|
+
});
|
|
3485
|
+
function createDeltaProcessor(fileKey) {
|
|
3486
|
+
const lockfilePath = path14.join(process.cwd(), "i18n.lock");
|
|
3487
|
+
return {
|
|
3488
|
+
async checkIfLockExists() {
|
|
3489
|
+
return checkIfFileExists(lockfilePath);
|
|
3490
|
+
},
|
|
3491
|
+
async calculateDelta(params) {
|
|
3492
|
+
let added = _20.difference(Object.keys(params.sourceData), Object.keys(params.targetData));
|
|
3493
|
+
let removed = _20.difference(Object.keys(params.targetData), Object.keys(params.sourceData));
|
|
3494
|
+
const updated = _20.filter(Object.keys(params.sourceData), (key) => {
|
|
3495
|
+
return MD5(params.sourceData[key]) !== params.checksums[key] && params.checksums[key];
|
|
3496
|
+
});
|
|
3497
|
+
const renamed = [];
|
|
3498
|
+
for (const addedKey of added) {
|
|
3499
|
+
const addedHash = MD5(params.sourceData[addedKey]);
|
|
3500
|
+
for (const removedKey of removed) {
|
|
3501
|
+
if (params.checksums[removedKey] === addedHash) {
|
|
3502
|
+
renamed.push([removedKey, addedKey]);
|
|
3503
|
+
break;
|
|
3504
|
+
}
|
|
3505
|
+
}
|
|
3506
|
+
}
|
|
3507
|
+
added = added.filter((key) => !renamed.some(([oldKey, newKey]) => newKey === key));
|
|
3508
|
+
removed = removed.filter((key) => !renamed.some(([oldKey, newKey]) => oldKey === key));
|
|
3509
|
+
const hasChanges = [added.length > 0, removed.length > 0, updated.length > 0, renamed.length > 0].some((v) => v);
|
|
3510
|
+
return {
|
|
3511
|
+
added,
|
|
3512
|
+
removed,
|
|
3513
|
+
updated,
|
|
3514
|
+
renamed,
|
|
3515
|
+
hasChanges
|
|
3516
|
+
};
|
|
3517
|
+
},
|
|
3518
|
+
async loadLock() {
|
|
3519
|
+
const lockfileContent = tryReadFile(lockfilePath, null);
|
|
3520
|
+
const lockfileYaml = lockfileContent ? YAML3.parse(lockfileContent) : null;
|
|
3521
|
+
const lockfileData = lockfileYaml ? LockSchema.parse(lockfileYaml) : {
|
|
3522
|
+
version: 1,
|
|
3523
|
+
checksums: {}
|
|
3524
|
+
};
|
|
3525
|
+
return lockfileData;
|
|
3526
|
+
},
|
|
3527
|
+
async saveLock(lockData) {
|
|
3528
|
+
const lockfileYaml = YAML3.stringify(lockData);
|
|
3529
|
+
writeFile(lockfilePath, lockfileYaml);
|
|
3530
|
+
},
|
|
3531
|
+
async loadChecksums() {
|
|
3532
|
+
const id = MD5(fileKey);
|
|
3533
|
+
const lockfileData = await this.loadLock();
|
|
3534
|
+
return lockfileData.checksums[id] || {};
|
|
3535
|
+
},
|
|
3536
|
+
async saveChecksums(checksums) {
|
|
3537
|
+
const id = MD5(fileKey);
|
|
3538
|
+
const lockfileData = await this.loadLock();
|
|
3539
|
+
lockfileData.checksums[id] = checksums;
|
|
3540
|
+
await this.saveLock(lockfileData);
|
|
3541
|
+
},
|
|
3542
|
+
async createChecksums(sourceData) {
|
|
3543
|
+
const checksums = _20.mapValues(sourceData, (value) => MD5(value));
|
|
3544
|
+
return checksums;
|
|
3545
|
+
}
|
|
3546
|
+
};
|
|
3468
3547
|
}
|
|
3469
3548
|
|
|
3470
3549
|
// src/cli/cmd/i18n.ts
|
|
3550
|
+
import { flatten as flatten2, unflatten as unflatten2 } from "flat";
|
|
3471
3551
|
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(
|
|
3472
3552
|
"--key <key>",
|
|
3473
3553
|
"Key to process. Process only a specific translation key, useful for debugging or updating a single entry"
|
|
@@ -3515,7 +3595,7 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
|
|
|
3515
3595
|
ora.succeed("Buckets retrieved");
|
|
3516
3596
|
if (flags.file?.length) {
|
|
3517
3597
|
buckets = buckets.map((bucket) => {
|
|
3518
|
-
const paths = bucket.paths.filter((
|
|
3598
|
+
const paths = bucket.paths.filter((path18) => flags.file.find((file) => path18.pathPattern?.match(file)));
|
|
3519
3599
|
return { ...bucket, paths };
|
|
3520
3600
|
}).filter((bucket) => bucket.paths.length > 0);
|
|
3521
3601
|
if (buckets.length === 0) {
|
|
@@ -3525,34 +3605,94 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
|
|
|
3525
3605
|
ora.info(`\x1B[36mProcessing only filtered buckets:\x1B[0m`);
|
|
3526
3606
|
buckets.map((bucket) => {
|
|
3527
3607
|
ora.info(` ${bucket.type}:`);
|
|
3528
|
-
bucket.paths.forEach((
|
|
3529
|
-
ora.info(` - ${
|
|
3608
|
+
bucket.paths.forEach((path18) => {
|
|
3609
|
+
ora.info(` - ${path18.pathPattern}`);
|
|
3530
3610
|
});
|
|
3531
3611
|
});
|
|
3532
3612
|
}
|
|
3533
3613
|
}
|
|
3534
3614
|
const targetLocales = flags.locale?.length ? flags.locale : i18nConfig.locale.targets;
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3615
|
+
ora.start("Setting up localization cache...");
|
|
3616
|
+
const checkLockfileProcessor = createDeltaProcessor("");
|
|
3617
|
+
const lockfileExists = await checkLockfileProcessor.checkIfLockExists();
|
|
3618
|
+
if (!lockfileExists) {
|
|
3538
3619
|
ora.start("Creating i18n.lock...");
|
|
3539
3620
|
for (const bucket of buckets) {
|
|
3540
3621
|
for (const bucketPath of bucket.paths) {
|
|
3541
3622
|
const sourceLocale = resolveOverriddenLocale3(i18nConfig.locale.source, bucketPath.delimiter);
|
|
3542
|
-
const bucketLoader = createBucketLoader(
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3623
|
+
const bucketLoader = createBucketLoader(
|
|
3624
|
+
bucket.type,
|
|
3625
|
+
bucketPath.pathPattern,
|
|
3626
|
+
{
|
|
3627
|
+
isCacheRestore: false,
|
|
3628
|
+
defaultLocale: sourceLocale,
|
|
3629
|
+
injectLocale: bucket.injectLocale
|
|
3630
|
+
},
|
|
3631
|
+
bucket.lockedKeys
|
|
3632
|
+
);
|
|
3547
3633
|
bucketLoader.setDefaultLocale(sourceLocale);
|
|
3548
3634
|
await bucketLoader.init();
|
|
3549
3635
|
const sourceData = await bucketLoader.pull(i18nConfig.locale.source);
|
|
3550
|
-
|
|
3636
|
+
const deltaProcessor = createDeltaProcessor(bucketPath.pathPattern);
|
|
3637
|
+
const checksums = await deltaProcessor.createChecksums(sourceData);
|
|
3638
|
+
await deltaProcessor.saveChecksums(checksums);
|
|
3551
3639
|
}
|
|
3552
3640
|
}
|
|
3553
|
-
ora.succeed("
|
|
3641
|
+
ora.succeed("Localization cache initialized");
|
|
3554
3642
|
} else {
|
|
3555
|
-
ora.succeed("
|
|
3643
|
+
ora.succeed("Localization cache loaded");
|
|
3644
|
+
}
|
|
3645
|
+
for (const bucket of buckets) {
|
|
3646
|
+
if (bucket.type !== "json") {
|
|
3647
|
+
continue;
|
|
3648
|
+
}
|
|
3649
|
+
ora.start("Validating localization state...");
|
|
3650
|
+
for (const bucketPath of bucket.paths) {
|
|
3651
|
+
const sourceLocale = resolveOverriddenLocale3(i18nConfig.locale.source, bucketPath.delimiter);
|
|
3652
|
+
const deltaProcessor = createDeltaProcessor(bucketPath.pathPattern);
|
|
3653
|
+
const sourcePath = path15.join(process.cwd(), bucketPath.pathPattern.replace("[locale]", sourceLocale));
|
|
3654
|
+
const sourceContent = tryReadFile(sourcePath, null);
|
|
3655
|
+
const sourceData = JSON.parse(sourceContent || "{}");
|
|
3656
|
+
const sourceFlattenedData = flatten2(sourceData, {
|
|
3657
|
+
delimiter: "/",
|
|
3658
|
+
transformKey(key) {
|
|
3659
|
+
return encodeURIComponent(key);
|
|
3660
|
+
}
|
|
3661
|
+
});
|
|
3662
|
+
for (const _targetLocale of targetLocales) {
|
|
3663
|
+
const targetLocale = resolveOverriddenLocale3(_targetLocale, bucketPath.delimiter);
|
|
3664
|
+
const targetPath = path15.join(process.cwd(), bucketPath.pathPattern.replace("[locale]", targetLocale));
|
|
3665
|
+
const targetContent = tryReadFile(targetPath, null);
|
|
3666
|
+
const targetData = JSON.parse(targetContent || "{}");
|
|
3667
|
+
const targetFlattenedData = flatten2(targetData, {
|
|
3668
|
+
delimiter: "/",
|
|
3669
|
+
transformKey(key) {
|
|
3670
|
+
return encodeURIComponent(key);
|
|
3671
|
+
}
|
|
3672
|
+
});
|
|
3673
|
+
const checksums = await deltaProcessor.loadChecksums();
|
|
3674
|
+
const delta = await deltaProcessor.calculateDelta({
|
|
3675
|
+
sourceData: sourceFlattenedData,
|
|
3676
|
+
targetData: targetFlattenedData,
|
|
3677
|
+
checksums
|
|
3678
|
+
});
|
|
3679
|
+
if (!delta.hasChanges) {
|
|
3680
|
+
continue;
|
|
3681
|
+
}
|
|
3682
|
+
for (const [oldKey, newKey] of delta.renamed) {
|
|
3683
|
+
targetFlattenedData[newKey] = targetFlattenedData[oldKey];
|
|
3684
|
+
delete targetFlattenedData[oldKey];
|
|
3685
|
+
}
|
|
3686
|
+
const updatedTargetData = unflatten2(targetFlattenedData, {
|
|
3687
|
+
delimiter: "/",
|
|
3688
|
+
transformKey(key) {
|
|
3689
|
+
return decodeURIComponent(key);
|
|
3690
|
+
}
|
|
3691
|
+
});
|
|
3692
|
+
await writeFile(targetPath, JSON.stringify(updatedTargetData, null, 2));
|
|
3693
|
+
}
|
|
3694
|
+
}
|
|
3695
|
+
ora.succeed("Localization state check completed");
|
|
3556
3696
|
}
|
|
3557
3697
|
const cache = getNormalizedCache();
|
|
3558
3698
|
if (cache) {
|
|
@@ -3565,11 +3705,16 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
|
|
|
3565
3705
|
const bucketOra = Ora5({ indent: 4 });
|
|
3566
3706
|
bucketOra.info(`Processing path: ${bucketPath.pathPattern}`);
|
|
3567
3707
|
const sourceLocale = resolveOverriddenLocale3(i18nConfig.locale.source, bucketPath.delimiter);
|
|
3568
|
-
const bucketLoader = createBucketLoader(
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3708
|
+
const bucketLoader = createBucketLoader(
|
|
3709
|
+
bucket.type,
|
|
3710
|
+
bucketPath.pathPattern,
|
|
3711
|
+
{
|
|
3712
|
+
isCacheRestore: true,
|
|
3713
|
+
defaultLocale: sourceLocale,
|
|
3714
|
+
injectLocale: bucket.injectLocale
|
|
3715
|
+
},
|
|
3716
|
+
bucket.lockedKeys
|
|
3717
|
+
);
|
|
3573
3718
|
bucketLoader.setDefaultLocale(sourceLocale);
|
|
3574
3719
|
await bucketLoader.init();
|
|
3575
3720
|
const sourceData = await bucketLoader.pull(sourceLocale);
|
|
@@ -3584,7 +3729,9 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
|
|
|
3584
3729
|
}
|
|
3585
3730
|
}
|
|
3586
3731
|
await bucketLoader.push(targetLocale, targetData);
|
|
3587
|
-
|
|
3732
|
+
const deltaProcessor = createDeltaProcessor(bucketPath.pathPattern);
|
|
3733
|
+
const checksums = await deltaProcessor.createChecksums(cachedSourceData);
|
|
3734
|
+
await deltaProcessor.saveChecksums(checksums);
|
|
3588
3735
|
bucketOra.succeed(
|
|
3589
3736
|
`[${sourceLocale} -> ${targetLocale}] Recovered ${Object.keys(cachedSourceData).length} entries from cache`
|
|
3590
3737
|
);
|
|
@@ -3604,18 +3751,29 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
|
|
|
3604
3751
|
bucketLoop: for (const bucket of buckets) {
|
|
3605
3752
|
for (const bucketPath of bucket.paths) {
|
|
3606
3753
|
const sourceLocale = resolveOverriddenLocale3(i18nConfig.locale.source, bucketPath.delimiter);
|
|
3607
|
-
const bucketLoader = createBucketLoader(
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3754
|
+
const bucketLoader = createBucketLoader(
|
|
3755
|
+
bucket.type,
|
|
3756
|
+
bucketPath.pathPattern,
|
|
3757
|
+
{
|
|
3758
|
+
isCacheRestore: false,
|
|
3759
|
+
defaultLocale: sourceLocale,
|
|
3760
|
+
returnUnlocalizedKeys: true,
|
|
3761
|
+
injectLocale: bucket.injectLocale
|
|
3762
|
+
},
|
|
3763
|
+
bucket.lockedKeys
|
|
3764
|
+
);
|
|
3613
3765
|
bucketLoader.setDefaultLocale(sourceLocale);
|
|
3614
3766
|
await bucketLoader.init();
|
|
3615
3767
|
const { unlocalizable: sourceUnlocalizable, ...sourceData } = await bucketLoader.pull(
|
|
3616
3768
|
i18nConfig.locale.source
|
|
3617
3769
|
);
|
|
3618
|
-
const
|
|
3770
|
+
const deltaProcessor = createDeltaProcessor(bucketPath.pathPattern);
|
|
3771
|
+
const sourceChecksums = await deltaProcessor.createChecksums(sourceData);
|
|
3772
|
+
const savedChecksums = await deltaProcessor.loadChecksums();
|
|
3773
|
+
const updatedSourceData = _21.pickBy(
|
|
3774
|
+
sourceData,
|
|
3775
|
+
(value, key) => sourceChecksums[key] !== savedChecksums[key]
|
|
3776
|
+
);
|
|
3619
3777
|
if (Object.keys(updatedSourceData).length > 0) {
|
|
3620
3778
|
requiresUpdate = "updated";
|
|
3621
3779
|
break bucketLoop;
|
|
@@ -3623,9 +3781,9 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
|
|
|
3623
3781
|
for (const _targetLocale of targetLocales) {
|
|
3624
3782
|
const targetLocale = resolveOverriddenLocale3(_targetLocale, bucketPath.delimiter);
|
|
3625
3783
|
const { unlocalizable: targetUnlocalizable, ...targetData } = await bucketLoader.pull(targetLocale);
|
|
3626
|
-
const missingKeys =
|
|
3627
|
-
const extraKeys =
|
|
3628
|
-
const unlocalizableDataDiff = !
|
|
3784
|
+
const missingKeys = _21.difference(Object.keys(sourceData), Object.keys(targetData));
|
|
3785
|
+
const extraKeys = _21.difference(Object.keys(targetData), Object.keys(sourceData));
|
|
3786
|
+
const unlocalizableDataDiff = !_21.isEqual(sourceUnlocalizable, targetUnlocalizable);
|
|
3629
3787
|
if (missingKeys.length > 0) {
|
|
3630
3788
|
requiresUpdate = "missing";
|
|
3631
3789
|
break bucketLoop;
|
|
@@ -3662,11 +3820,16 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
|
|
|
3662
3820
|
for (const bucketPath of bucket.paths) {
|
|
3663
3821
|
const bucketOra = Ora5({ indent: 2 }).info(`Processing path: ${bucketPath.pathPattern}`);
|
|
3664
3822
|
const sourceLocale = resolveOverriddenLocale3(i18nConfig.locale.source, bucketPath.delimiter);
|
|
3665
|
-
const bucketLoader = createBucketLoader(
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3823
|
+
const bucketLoader = createBucketLoader(
|
|
3824
|
+
bucket.type,
|
|
3825
|
+
bucketPath.pathPattern,
|
|
3826
|
+
{
|
|
3827
|
+
isCacheRestore: false,
|
|
3828
|
+
defaultLocale: sourceLocale,
|
|
3829
|
+
injectLocale: bucket.injectLocale
|
|
3830
|
+
},
|
|
3831
|
+
bucket.lockedKeys
|
|
3832
|
+
);
|
|
3670
3833
|
bucketLoader.setDefaultLocale(sourceLocale);
|
|
3671
3834
|
await bucketLoader.init();
|
|
3672
3835
|
let sourceData = await bucketLoader.pull(sourceLocale);
|
|
@@ -3675,15 +3838,17 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
|
|
|
3675
3838
|
try {
|
|
3676
3839
|
bucketOra.start(`[${sourceLocale} -> ${targetLocale}] (0%) Localization in progress...`);
|
|
3677
3840
|
sourceData = await bucketLoader.pull(sourceLocale);
|
|
3678
|
-
const updatedSourceData = flags.force ? sourceData : lockfileHelper.extractUpdatedData(bucketPath.pathPattern, sourceData);
|
|
3679
3841
|
const targetData = await bucketLoader.pull(targetLocale);
|
|
3680
|
-
|
|
3842
|
+
const deltaProcessor2 = createDeltaProcessor(bucketPath.pathPattern);
|
|
3843
|
+
const checksums2 = await deltaProcessor2.loadChecksums();
|
|
3844
|
+
const delta = await deltaProcessor2.calculateDelta({
|
|
3681
3845
|
sourceData,
|
|
3682
|
-
|
|
3683
|
-
|
|
3846
|
+
targetData,
|
|
3847
|
+
checksums: checksums2
|
|
3684
3848
|
});
|
|
3849
|
+
let processableData = _21.chain(sourceData).entries().filter(([key, value]) => delta.added.includes(key) || delta.updated.includes(key) || !!flags.force).fromPairs().value();
|
|
3685
3850
|
if (flags.key) {
|
|
3686
|
-
processableData =
|
|
3851
|
+
processableData = _21.pickBy(processableData, (_24, key) => key === flags.key);
|
|
3687
3852
|
}
|
|
3688
3853
|
if (flags.verbose) {
|
|
3689
3854
|
bucketOra.info(JSON.stringify(processableData, null, 2));
|
|
@@ -3720,7 +3885,7 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
|
|
|
3720
3885
|
if (flags.verbose) {
|
|
3721
3886
|
bucketOra.info(JSON.stringify(processedTargetData, null, 2));
|
|
3722
3887
|
}
|
|
3723
|
-
let finalTargetData =
|
|
3888
|
+
let finalTargetData = _21.merge({}, sourceData, targetData, processedTargetData);
|
|
3724
3889
|
if (flags.interactive) {
|
|
3725
3890
|
bucketOra.stop();
|
|
3726
3891
|
const reviewedData = await reviewChanges({
|
|
@@ -3734,7 +3899,7 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
|
|
|
3734
3899
|
finalTargetData = reviewedData;
|
|
3735
3900
|
bucketOra.start(`Applying changes to ${bucketPath} (${targetLocale})`);
|
|
3736
3901
|
}
|
|
3737
|
-
const finalDiffSize =
|
|
3902
|
+
const finalDiffSize = _21.chain(finalTargetData).omitBy((value, key) => value === targetData[key]).size().value();
|
|
3738
3903
|
await bucketLoader.push(targetLocale, finalTargetData);
|
|
3739
3904
|
if (finalDiffSize > 0 || flags.force) {
|
|
3740
3905
|
bucketOra.succeed(`[${sourceLocale} -> ${targetLocale}] Localization completed`);
|
|
@@ -3751,7 +3916,9 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
|
|
|
3751
3916
|
}
|
|
3752
3917
|
}
|
|
3753
3918
|
}
|
|
3754
|
-
|
|
3919
|
+
const deltaProcessor = createDeltaProcessor(bucketPath.pathPattern);
|
|
3920
|
+
const checksums = await deltaProcessor.createChecksums(sourceData);
|
|
3921
|
+
await deltaProcessor.saveChecksums(checksums);
|
|
3755
3922
|
}
|
|
3756
3923
|
} catch (_error) {
|
|
3757
3924
|
const error = new Error(`Failed to process bucket ${bucket.type}: ${_error.message}`);
|
|
@@ -3786,25 +3953,19 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
|
|
|
3786
3953
|
process.exit(1);
|
|
3787
3954
|
}
|
|
3788
3955
|
});
|
|
3789
|
-
function calculateDataDelta(args) {
|
|
3790
|
-
const newKeys = _20.difference(Object.keys(args.sourceData), Object.keys(args.targetData));
|
|
3791
|
-
const updatedKeys = Object.keys(args.updatedSourceData);
|
|
3792
|
-
const result = _20.chain(args.sourceData).pickBy((value, key) => newKeys.includes(key) || updatedKeys.includes(key)).value();
|
|
3793
|
-
return result;
|
|
3794
|
-
}
|
|
3795
3956
|
function parseFlags(options) {
|
|
3796
|
-
return
|
|
3797
|
-
apiKey:
|
|
3798
|
-
locale:
|
|
3799
|
-
bucket:
|
|
3800
|
-
force:
|
|
3801
|
-
frozen:
|
|
3802
|
-
verbose:
|
|
3803
|
-
strict:
|
|
3804
|
-
key:
|
|
3805
|
-
file:
|
|
3806
|
-
interactive:
|
|
3807
|
-
debug:
|
|
3957
|
+
return Z3.object({
|
|
3958
|
+
apiKey: Z3.string().optional(),
|
|
3959
|
+
locale: Z3.array(localeCodeSchema).optional(),
|
|
3960
|
+
bucket: Z3.array(bucketTypeSchema).optional(),
|
|
3961
|
+
force: Z3.boolean().optional(),
|
|
3962
|
+
frozen: Z3.boolean().optional(),
|
|
3963
|
+
verbose: Z3.boolean().optional(),
|
|
3964
|
+
strict: Z3.boolean().optional(),
|
|
3965
|
+
key: Z3.string().optional(),
|
|
3966
|
+
file: Z3.array(Z3.string()).optional(),
|
|
3967
|
+
interactive: Z3.boolean().default(false),
|
|
3968
|
+
debug: Z3.boolean().default(false)
|
|
3808
3969
|
}).parse(options);
|
|
3809
3970
|
}
|
|
3810
3971
|
async function validateAuth(settings) {
|
|
@@ -3898,7 +4059,7 @@ Reviewing changes for ${chalk.blue(args.pathPattern)} (${chalk.yellow(args.targe
|
|
|
3898
4059
|
return args.currentData;
|
|
3899
4060
|
}
|
|
3900
4061
|
const customData = { ...args.currentData };
|
|
3901
|
-
const changes =
|
|
4062
|
+
const changes = _21.reduce(
|
|
3902
4063
|
args.proposedData,
|
|
3903
4064
|
(result, value, key) => {
|
|
3904
4065
|
if (args.currentData[key] !== value) {
|
|
@@ -3950,6 +4111,77 @@ Editing value for: ${chalk.cyan(key)}`);
|
|
|
3950
4111
|
import { Command as Command7 } from "interactive-commander";
|
|
3951
4112
|
import Z5 from "zod";
|
|
3952
4113
|
import Ora6 from "ora";
|
|
4114
|
+
|
|
4115
|
+
// src/cli/utils/lockfile.ts
|
|
4116
|
+
import fs12 from "fs";
|
|
4117
|
+
import path16 from "path";
|
|
4118
|
+
import Z4 from "zod";
|
|
4119
|
+
import YAML4 from "yaml";
|
|
4120
|
+
import { MD5 as MD52 } from "object-hash";
|
|
4121
|
+
import _22 from "lodash";
|
|
4122
|
+
function createLockfileHelper() {
|
|
4123
|
+
return {
|
|
4124
|
+
isLockfileExists: () => {
|
|
4125
|
+
const lockfilePath = _getLockfilePath();
|
|
4126
|
+
return fs12.existsSync(lockfilePath);
|
|
4127
|
+
},
|
|
4128
|
+
registerSourceData: (pathPattern, sourceData) => {
|
|
4129
|
+
const lockfile = _loadLockfile();
|
|
4130
|
+
const sectionKey = MD52(pathPattern);
|
|
4131
|
+
const sectionChecksums = _22.mapValues(sourceData, (value) => MD52(value));
|
|
4132
|
+
lockfile.checksums[sectionKey] = sectionChecksums;
|
|
4133
|
+
_saveLockfile(lockfile);
|
|
4134
|
+
},
|
|
4135
|
+
registerPartialSourceData: (pathPattern, partialSourceData) => {
|
|
4136
|
+
const lockfile = _loadLockfile();
|
|
4137
|
+
const sectionKey = MD52(pathPattern);
|
|
4138
|
+
const sectionChecksums = _22.mapValues(partialSourceData, (value) => MD52(value));
|
|
4139
|
+
lockfile.checksums[sectionKey] = _22.merge({}, lockfile.checksums[sectionKey] ?? {}, sectionChecksums);
|
|
4140
|
+
_saveLockfile(lockfile);
|
|
4141
|
+
},
|
|
4142
|
+
extractUpdatedData: (pathPattern, sourceData) => {
|
|
4143
|
+
const lockfile = _loadLockfile();
|
|
4144
|
+
const sectionKey = MD52(pathPattern);
|
|
4145
|
+
const currentChecksums = _22.mapValues(sourceData, (value) => MD52(value));
|
|
4146
|
+
const savedChecksums = lockfile.checksums[sectionKey] || {};
|
|
4147
|
+
const updatedData = _22.pickBy(sourceData, (value, key) => savedChecksums[key] !== currentChecksums[key]);
|
|
4148
|
+
return updatedData;
|
|
4149
|
+
}
|
|
4150
|
+
};
|
|
4151
|
+
function _loadLockfile() {
|
|
4152
|
+
const lockfilePath = _getLockfilePath();
|
|
4153
|
+
if (!fs12.existsSync(lockfilePath)) {
|
|
4154
|
+
return LockfileSchema.parse({});
|
|
4155
|
+
}
|
|
4156
|
+
const content = fs12.readFileSync(lockfilePath, "utf-8");
|
|
4157
|
+
const result = LockfileSchema.parse(YAML4.parse(content));
|
|
4158
|
+
return result;
|
|
4159
|
+
}
|
|
4160
|
+
function _saveLockfile(lockfile) {
|
|
4161
|
+
const lockfilePath = _getLockfilePath();
|
|
4162
|
+
const content = YAML4.stringify(lockfile);
|
|
4163
|
+
fs12.writeFileSync(lockfilePath, content);
|
|
4164
|
+
}
|
|
4165
|
+
function _getLockfilePath() {
|
|
4166
|
+
return path16.join(process.cwd(), "i18n.lock");
|
|
4167
|
+
}
|
|
4168
|
+
}
|
|
4169
|
+
var LockfileSchema = Z4.object({
|
|
4170
|
+
version: Z4.literal(1).default(1),
|
|
4171
|
+
checksums: Z4.record(
|
|
4172
|
+
Z4.string(),
|
|
4173
|
+
// localizable files' keys
|
|
4174
|
+
Z4.record(
|
|
4175
|
+
// checksums hashmap
|
|
4176
|
+
Z4.string(),
|
|
4177
|
+
// key
|
|
4178
|
+
Z4.string()
|
|
4179
|
+
// checksum of the key's value in the source locale
|
|
4180
|
+
).default({})
|
|
4181
|
+
).default({})
|
|
4182
|
+
});
|
|
4183
|
+
|
|
4184
|
+
// src/cli/cmd/lockfile.ts
|
|
3953
4185
|
import { resolveOverriddenLocale as resolveOverriddenLocale4 } from "@lingo.dev/_spec";
|
|
3954
4186
|
var lockfile_default = new Command7().command("lockfile").description("Create a lockfile if it does not exist").helpOption("-h, --help", "Show help").option("-f, --force", "Force create a lockfile").action(async (options) => {
|
|
3955
4187
|
const flags = flagsSchema.parse(options);
|
|
@@ -3982,7 +4214,7 @@ var flagsSchema = Z5.object({
|
|
|
3982
4214
|
// src/cli/cmd/cleanup.ts
|
|
3983
4215
|
import { resolveOverriddenLocale as resolveOverriddenLocale5 } from "@lingo.dev/_spec";
|
|
3984
4216
|
import { Command as Command8 } from "interactive-commander";
|
|
3985
|
-
import
|
|
4217
|
+
import _23 from "lodash";
|
|
3986
4218
|
import Ora7 from "ora";
|
|
3987
4219
|
var cleanup_default = new Command8().command("cleanup").description("Remove keys from target files that do not exist in the source file").helpOption("-h, --help", "Show help").option("--locale <locale>", "Specific locale to cleanup").option("--bucket <bucket>", "Specific bucket to cleanup").option("--dry-run", "Show what would be removed without making changes").option(
|
|
3988
4220
|
"--verbose",
|
|
@@ -4018,7 +4250,7 @@ var cleanup_default = new Command8().command("cleanup").description("Remove keys
|
|
|
4018
4250
|
try {
|
|
4019
4251
|
const targetData = await bucketLoader.pull(targetLocale);
|
|
4020
4252
|
const targetKeys = Object.keys(targetData);
|
|
4021
|
-
const keysToRemove =
|
|
4253
|
+
const keysToRemove = _23.difference(targetKeys, sourceKeys);
|
|
4022
4254
|
if (keysToRemove.length === 0) {
|
|
4023
4255
|
bucketOra.succeed(`[${targetLocale}] No keys to remove`);
|
|
4024
4256
|
continue;
|
|
@@ -4027,7 +4259,7 @@ var cleanup_default = new Command8().command("cleanup").description("Remove keys
|
|
|
4027
4259
|
bucketOra.info(`[${targetLocale}] Keys to remove: ${JSON.stringify(keysToRemove, null, 2)}`);
|
|
4028
4260
|
}
|
|
4029
4261
|
if (!options.dryRun) {
|
|
4030
|
-
const cleanedData =
|
|
4262
|
+
const cleanedData = _23.pick(targetData, sourceKeys);
|
|
4031
4263
|
await bucketLoader.push(targetLocale, cleanedData);
|
|
4032
4264
|
bucketOra.succeed(`[${targetLocale}] Removed ${keysToRemove.length} keys`);
|
|
4033
4265
|
} else {
|
|
@@ -4082,7 +4314,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
4082
4314
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4083
4315
|
import Z6 from "zod";
|
|
4084
4316
|
import { ReplexicaEngine } from "@lingo.dev/_sdk";
|
|
4085
|
-
var mcp_default = new Command9().command("mcp").description("Use Lingo.dev model context provider with your AI agent").helpOption("-h, --help", "Show help").action(async (
|
|
4317
|
+
var mcp_default = new Command9().command("mcp").description("Use Lingo.dev model context provider with your AI agent").helpOption("-h, --help", "Show help").action(async (_24, program) => {
|
|
4086
4318
|
const apiKey = program.args[0];
|
|
4087
4319
|
const settings = getSettings(apiKey);
|
|
4088
4320
|
if (!settings.auth.apiKey) {
|
|
@@ -4140,7 +4372,7 @@ import { execSync as execSync2 } from "child_process";
|
|
|
4140
4372
|
|
|
4141
4373
|
// ../../action/src/flows/in-branch.ts
|
|
4142
4374
|
import { execSync } from "child_process";
|
|
4143
|
-
import
|
|
4375
|
+
import path17 from "path";
|
|
4144
4376
|
|
|
4145
4377
|
// ../../action/src/flows/_base.ts
|
|
4146
4378
|
var IntegrationFlow = class {
|
|
@@ -4218,7 +4450,7 @@ var InBranchFlow = class extends IntegrationFlow {
|
|
|
4218
4450
|
return false;
|
|
4219
4451
|
}
|
|
4220
4452
|
}
|
|
4221
|
-
const workingDir =
|
|
4453
|
+
const workingDir = path17.resolve(process.cwd(), this.platformKit.config.workingDir);
|
|
4222
4454
|
if (workingDir !== process.cwd()) {
|
|
4223
4455
|
this.ora.info(`Changing to working directory: ${this.platformKit.config.workingDir}`);
|
|
4224
4456
|
process.chdir(workingDir);
|
|
@@ -4387,15 +4619,21 @@ Hey team,
|
|
|
4387
4619
|
};
|
|
4388
4620
|
|
|
4389
4621
|
// ../../action/src/platforms/bitbucket.ts
|
|
4390
|
-
import { execSync as
|
|
4622
|
+
import { execSync as execSync4 } from "child_process";
|
|
4391
4623
|
import bbLib from "bitbucket";
|
|
4392
4624
|
import Z8 from "zod";
|
|
4393
4625
|
|
|
4394
4626
|
// ../../action/src/platforms/_base.ts
|
|
4627
|
+
import { execSync as execSync3 } from "child_process";
|
|
4395
4628
|
import Z7 from "zod";
|
|
4396
4629
|
var defaultMessage = "feat: update translations via @lingodotdev";
|
|
4397
4630
|
var PlatformKit = class {
|
|
4398
|
-
gitConfig() {
|
|
4631
|
+
gitConfig(token, repoUrl) {
|
|
4632
|
+
if (token && repoUrl) {
|
|
4633
|
+
execSync3(`git remote set-url origin ${repoUrl}`, {
|
|
4634
|
+
stdio: "inherit"
|
|
4635
|
+
});
|
|
4636
|
+
}
|
|
4399
4637
|
}
|
|
4400
4638
|
get config() {
|
|
4401
4639
|
const env = Z7.object({
|
|
@@ -4479,10 +4717,10 @@ var BitbucketPlatformKit = class extends PlatformKit {
|
|
|
4479
4717
|
});
|
|
4480
4718
|
}
|
|
4481
4719
|
async gitConfig() {
|
|
4482
|
-
|
|
4720
|
+
execSync4("git config --unset http.${BITBUCKET_GIT_HTTP_ORIGIN}.proxy", {
|
|
4483
4721
|
stdio: "inherit"
|
|
4484
4722
|
});
|
|
4485
|
-
|
|
4723
|
+
execSync4("git config http.${BITBUCKET_GIT_HTTP_ORIGIN}.proxy http://host.docker.internal:29418/", {
|
|
4486
4724
|
stdio: "inherit"
|
|
4487
4725
|
});
|
|
4488
4726
|
}
|
|
@@ -4509,7 +4747,6 @@ var BitbucketPlatformKit = class extends PlatformKit {
|
|
|
4509
4747
|
// ../../action/src/platforms/github.ts
|
|
4510
4748
|
import { Octokit } from "octokit";
|
|
4511
4749
|
import Z9 from "zod";
|
|
4512
|
-
import { execSync as execSync4 } from "child_process";
|
|
4513
4750
|
var GitHubPlatformKit = class extends PlatformKit {
|
|
4514
4751
|
_octokit;
|
|
4515
4752
|
get octokit() {
|
|
@@ -4566,9 +4803,7 @@ var GitHubPlatformKit = class extends PlatformKit {
|
|
|
4566
4803
|
if (ghToken && processOwnCommits) {
|
|
4567
4804
|
console.log("Using provided GH_TOKEN. This will trigger your CI/CD pipeline to run again.");
|
|
4568
4805
|
const url = `https://${ghToken}@github.com/${repositoryOwner}/${repositoryName}.git`;
|
|
4569
|
-
|
|
4570
|
-
stdio: "inherit"
|
|
4571
|
-
});
|
|
4806
|
+
super.gitConfig(ghToken, url);
|
|
4572
4807
|
}
|
|
4573
4808
|
}
|
|
4574
4809
|
get platformConfig() {
|
|
@@ -4596,7 +4831,6 @@ var GitHubPlatformKit = class extends PlatformKit {
|
|
|
4596
4831
|
// ../../action/src/platforms/gitlab.ts
|
|
4597
4832
|
import { Gitlab } from "@gitbeaker/rest";
|
|
4598
4833
|
import Z10 from "zod";
|
|
4599
|
-
import { execSync as execSync5 } from "child_process";
|
|
4600
4834
|
var gl = new Gitlab({ token: "" });
|
|
4601
4835
|
var GitlabPlatformKit = class extends PlatformKit {
|
|
4602
4836
|
_gitlab;
|
|
@@ -4671,10 +4905,9 @@ var GitlabPlatformKit = class extends PlatformKit {
|
|
|
4671
4905
|
await this.gitlab.MergeRequestNotes.create(this.platformConfig.gitlabProjectId, pullRequestNumber, body);
|
|
4672
4906
|
}
|
|
4673
4907
|
gitConfig() {
|
|
4674
|
-
const
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
});
|
|
4908
|
+
const glToken = this.platformConfig.glToken;
|
|
4909
|
+
const url = `https://oauth2:${glToken}@gitlab.com/${this.platformConfig.repositoryOwner}/${this.platformConfig.repositoryName}.git`;
|
|
4910
|
+
super.gitConfig(glToken, url);
|
|
4678
4911
|
}
|
|
4679
4912
|
buildPullRequestUrl(pullRequestNumber) {
|
|
4680
4913
|
return `https://gitlab.com/${this.platformConfig.repositoryOwner}/${this.platformConfig.repositoryName}/-/merge_requests/${pullRequestNumber}`;
|
|
@@ -4745,7 +4978,7 @@ var ci_default = new Command10().command("ci").description("Run Lingo.dev CI/CD
|
|
|
4745
4978
|
// package.json
|
|
4746
4979
|
var package_default = {
|
|
4747
4980
|
name: "lingo.dev",
|
|
4748
|
-
version: "0.
|
|
4981
|
+
version: "0.82.0",
|
|
4749
4982
|
description: "Lingo.dev CLI",
|
|
4750
4983
|
private: false,
|
|
4751
4984
|
publishConfig: {
|