lingo.dev 0.111.15 → 0.112.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/README.md +7 -1
- package/build/cli.cjs +365 -153
- package/build/cli.cjs.map +1 -1
- package/build/cli.mjs +263 -51
- package/build/cli.mjs.map +1 -1
- package/package.json +5 -4
package/build/cli.mjs
CHANGED
|
@@ -569,26 +569,49 @@ async function pauseIfDebug(debug) {
|
|
|
569
569
|
}
|
|
570
570
|
async function renderSummary(results) {
|
|
571
571
|
console.log(chalk.hex(colors.green)("[Done]"));
|
|
572
|
-
const
|
|
572
|
+
const skippedResults = Array.from(results.values()).filter(
|
|
573
573
|
(r) => r.status === "skipped"
|
|
574
|
-
)
|
|
575
|
-
|
|
576
|
-
const succeededTasksCount = Array.from(results.values()).filter(
|
|
574
|
+
);
|
|
575
|
+
const succeededResults = Array.from(results.values()).filter(
|
|
577
576
|
(r) => r.status === "success"
|
|
578
|
-
)
|
|
579
|
-
|
|
580
|
-
const failedTasksCount = Array.from(results.values()).filter(
|
|
577
|
+
);
|
|
578
|
+
const failedResults = Array.from(results.values()).filter(
|
|
581
579
|
(r) => r.status === "error"
|
|
582
|
-
)
|
|
583
|
-
console.log(
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
580
|
+
);
|
|
581
|
+
console.log(
|
|
582
|
+
`\u2022 ${chalk.hex(colors.yellow)(skippedResults.length)} from cache`
|
|
583
|
+
);
|
|
584
|
+
console.log(
|
|
585
|
+
`\u2022 ${chalk.hex(colors.yellow)(succeededResults.length)} processed`
|
|
586
|
+
);
|
|
587
|
+
console.log(`\u2022 ${chalk.hex(colors.yellow)(failedResults.length)} failed`);
|
|
588
|
+
if (succeededResults.length > 0) {
|
|
589
|
+
console.log(chalk.hex(colors.green)("\n[Processed Files]"));
|
|
590
|
+
for (const result of succeededResults) {
|
|
591
|
+
const displayPath = result.pathPattern?.replace("[locale]", result.targetLocale) || "unknown";
|
|
589
592
|
console.log(
|
|
590
|
-
|
|
591
|
-
|
|
593
|
+
` \u2713 ${chalk.dim(displayPath)} ${chalk.hex(colors.yellow)(`(${result.sourceLocale} \u2192 ${result.targetLocale})`)}`
|
|
594
|
+
);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
if (skippedResults.length > 0) {
|
|
598
|
+
console.log(chalk.hex(colors.blue)("\n[Cached Files]"));
|
|
599
|
+
for (const result of skippedResults) {
|
|
600
|
+
const displayPath = result.pathPattern?.replace("[locale]", result.targetLocale) || "unknown";
|
|
601
|
+
console.log(
|
|
602
|
+
` \u26A1 ${chalk.dim(displayPath)} ${chalk.hex(colors.yellow)(`(${result.sourceLocale} \u2192 ${result.targetLocale})`)}`
|
|
603
|
+
);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
if (failedResults.length > 0) {
|
|
607
|
+
console.log(chalk.hex(colors.orange)("\n[Failed Files]"));
|
|
608
|
+
for (const result of failedResults) {
|
|
609
|
+
const displayPath = result.pathPattern?.replace("[locale]", result.targetLocale) || "unknown";
|
|
610
|
+
console.log(
|
|
611
|
+
` \u274C ${chalk.dim(displayPath)} ${chalk.hex(colors.yellow)(`(${result.sourceLocale} \u2192 ${result.targetLocale})`)}`
|
|
612
|
+
);
|
|
613
|
+
console.log(
|
|
614
|
+
` ${chalk.hex(colors.white)(String(result.error?.message || "Unknown error"))}`
|
|
592
615
|
);
|
|
593
616
|
}
|
|
594
617
|
}
|
|
@@ -2690,6 +2713,133 @@ ${content}`;
|
|
|
2690
2713
|
});
|
|
2691
2714
|
}
|
|
2692
2715
|
|
|
2716
|
+
// src/cli/loaders/markdoc.ts
|
|
2717
|
+
import Markdoc from "@markdoc/markdoc";
|
|
2718
|
+
import YAML3 from "yaml";
|
|
2719
|
+
var FM_ATTR_PREFIX2 = "fm-attr-";
|
|
2720
|
+
function createMarkdocLoader() {
|
|
2721
|
+
return createLoader({
|
|
2722
|
+
async pull(locale, input2) {
|
|
2723
|
+
const ast = Markdoc.parse(input2);
|
|
2724
|
+
const result = {};
|
|
2725
|
+
const counters = {};
|
|
2726
|
+
traverseAndExtract(ast, "", result, counters);
|
|
2727
|
+
if (ast.attributes?.frontmatter) {
|
|
2728
|
+
const frontmatter = YAML3.parse(ast.attributes.frontmatter);
|
|
2729
|
+
Object.entries(frontmatter).forEach(([key, value]) => {
|
|
2730
|
+
if (typeof value === "string") {
|
|
2731
|
+
result[`${FM_ATTR_PREFIX2}${key}`] = value;
|
|
2732
|
+
}
|
|
2733
|
+
});
|
|
2734
|
+
}
|
|
2735
|
+
return result;
|
|
2736
|
+
},
|
|
2737
|
+
async push(locale, data, originalInput) {
|
|
2738
|
+
if (!originalInput) {
|
|
2739
|
+
throw new Error("Original input is required for push");
|
|
2740
|
+
}
|
|
2741
|
+
const ast = Markdoc.parse(originalInput);
|
|
2742
|
+
const counters = {};
|
|
2743
|
+
const pathMap = {};
|
|
2744
|
+
buildPathMap(ast, "", counters, pathMap);
|
|
2745
|
+
const frontmatterEntries = Object.entries(data).filter(([key]) => key.startsWith(FM_ATTR_PREFIX2)).map(([key, value]) => [key.replace(FM_ATTR_PREFIX2, ""), value]);
|
|
2746
|
+
if (frontmatterEntries.length > 0 && ast.attributes) {
|
|
2747
|
+
const frontmatter = Object.fromEntries(frontmatterEntries);
|
|
2748
|
+
ast.attributes.frontmatter = YAML3.stringify(frontmatter, {
|
|
2749
|
+
defaultStringType: "PLAIN"
|
|
2750
|
+
}).trim();
|
|
2751
|
+
}
|
|
2752
|
+
const contentData = Object.fromEntries(
|
|
2753
|
+
Object.entries(data).filter(([key]) => !key.startsWith(FM_ATTR_PREFIX2))
|
|
2754
|
+
);
|
|
2755
|
+
applyTranslations(ast, "", contentData, pathMap);
|
|
2756
|
+
return Markdoc.format(ast);
|
|
2757
|
+
}
|
|
2758
|
+
});
|
|
2759
|
+
}
|
|
2760
|
+
function getSemanticNodeType(node) {
|
|
2761
|
+
if (node.type === "tag") return node.tag || "tag";
|
|
2762
|
+
return node.type;
|
|
2763
|
+
}
|
|
2764
|
+
function traverseAndExtract(node, path19, result, counters, parentType) {
|
|
2765
|
+
if (!node || typeof node !== "object") {
|
|
2766
|
+
return;
|
|
2767
|
+
}
|
|
2768
|
+
let semanticType = parentType;
|
|
2769
|
+
const nodeSemanticType = getSemanticNodeType(node);
|
|
2770
|
+
if (nodeSemanticType && !["text", "strong", "em", "inline", "link"].includes(nodeSemanticType)) {
|
|
2771
|
+
semanticType = nodeSemanticType;
|
|
2772
|
+
}
|
|
2773
|
+
if (node.type === "text" && node.attributes?.content) {
|
|
2774
|
+
const content = node.attributes.content;
|
|
2775
|
+
if (typeof content === "string" && content.trim()) {
|
|
2776
|
+
if (semanticType) {
|
|
2777
|
+
const index = counters[semanticType] || 0;
|
|
2778
|
+
counters[semanticType] = index + 1;
|
|
2779
|
+
const semanticKey = `${semanticType}-${index}`;
|
|
2780
|
+
result[semanticKey] = content;
|
|
2781
|
+
}
|
|
2782
|
+
}
|
|
2783
|
+
}
|
|
2784
|
+
if (Array.isArray(node.children)) {
|
|
2785
|
+
node.children.forEach((child, index) => {
|
|
2786
|
+
const childPath = path19 ? `${path19}/children/${index}` : `children/${index}`;
|
|
2787
|
+
traverseAndExtract(child, childPath, result, counters, semanticType);
|
|
2788
|
+
});
|
|
2789
|
+
}
|
|
2790
|
+
}
|
|
2791
|
+
function buildPathMap(node, path19, counters, pathMap, parentType) {
|
|
2792
|
+
if (!node || typeof node !== "object") {
|
|
2793
|
+
return;
|
|
2794
|
+
}
|
|
2795
|
+
let semanticType = parentType;
|
|
2796
|
+
const nodeSemanticType = getSemanticNodeType(node);
|
|
2797
|
+
if (nodeSemanticType && !["text", "strong", "em", "inline", "link"].includes(nodeSemanticType)) {
|
|
2798
|
+
semanticType = nodeSemanticType;
|
|
2799
|
+
}
|
|
2800
|
+
if (node.type === "text" && node.attributes?.content) {
|
|
2801
|
+
const content = node.attributes.content;
|
|
2802
|
+
if (typeof content === "string" && content.trim()) {
|
|
2803
|
+
if (semanticType) {
|
|
2804
|
+
const index = counters[semanticType] || 0;
|
|
2805
|
+
counters[semanticType] = index + 1;
|
|
2806
|
+
const semanticKey = `${semanticType}-${index}`;
|
|
2807
|
+
const contentPath = path19 ? `${path19}/attributes/content` : "attributes/content";
|
|
2808
|
+
pathMap[semanticKey] = contentPath;
|
|
2809
|
+
}
|
|
2810
|
+
}
|
|
2811
|
+
}
|
|
2812
|
+
if (Array.isArray(node.children)) {
|
|
2813
|
+
node.children.forEach((child, index) => {
|
|
2814
|
+
const childPath = path19 ? `${path19}/children/${index}` : `children/${index}`;
|
|
2815
|
+
buildPathMap(child, childPath, counters, pathMap, semanticType);
|
|
2816
|
+
});
|
|
2817
|
+
}
|
|
2818
|
+
}
|
|
2819
|
+
function applyTranslations(node, path19, data, pathMap) {
|
|
2820
|
+
if (!node || typeof node !== "object") {
|
|
2821
|
+
return;
|
|
2822
|
+
}
|
|
2823
|
+
if (node.type === "text" && node.attributes?.content) {
|
|
2824
|
+
const content = node.attributes.content;
|
|
2825
|
+
if (typeof content === "string") {
|
|
2826
|
+
const contentPath = path19 ? `${path19}/attributes/content` : "attributes/content";
|
|
2827
|
+
const semanticKey = Object.keys(pathMap).find(
|
|
2828
|
+
(key) => pathMap[key] === contentPath
|
|
2829
|
+
);
|
|
2830
|
+
if (semanticKey && data[semanticKey] !== void 0) {
|
|
2831
|
+
node.attributes.content = data[semanticKey];
|
|
2832
|
+
}
|
|
2833
|
+
}
|
|
2834
|
+
}
|
|
2835
|
+
if (Array.isArray(node.children)) {
|
|
2836
|
+
node.children.forEach((child, index) => {
|
|
2837
|
+
const childPath = path19 ? `${path19}/children/${index}` : `children/${index}`;
|
|
2838
|
+
applyTranslations(child, childPath, data, pathMap);
|
|
2839
|
+
});
|
|
2840
|
+
}
|
|
2841
|
+
}
|
|
2842
|
+
|
|
2693
2843
|
// src/cli/loaders/properties.ts
|
|
2694
2844
|
function createPropertiesLoader() {
|
|
2695
2845
|
return createLoader({
|
|
@@ -6633,7 +6783,7 @@ function _isLockedKey(key, lockedKeys) {
|
|
|
6633
6783
|
|
|
6634
6784
|
// src/cli/loaders/mdx2/frontmatter-split.ts
|
|
6635
6785
|
import matter2 from "gray-matter";
|
|
6636
|
-
import
|
|
6786
|
+
import YAML4 from "yaml";
|
|
6637
6787
|
function createMdxFrontmatterSplitLoader() {
|
|
6638
6788
|
const fmEngine = createFmEngine();
|
|
6639
6789
|
return createLoader({
|
|
@@ -6654,8 +6804,8 @@ function createMdxFrontmatterSplitLoader() {
|
|
|
6654
6804
|
}
|
|
6655
6805
|
function createFmEngine() {
|
|
6656
6806
|
const yamlEngine2 = {
|
|
6657
|
-
parse: (str) =>
|
|
6658
|
-
stringify: (obj) =>
|
|
6807
|
+
parse: (str) => YAML4.parse(str),
|
|
6808
|
+
stringify: (obj) => YAML4.stringify(obj, { defaultStringType: "PLAIN" })
|
|
6659
6809
|
};
|
|
6660
6810
|
return {
|
|
6661
6811
|
parse: (input2) => matter2(input2, {
|
|
@@ -7263,6 +7413,15 @@ function createBucketLoader(bucketType, bucketPathPattern, options, lockedKeys,
|
|
|
7263
7413
|
createSyncLoader(),
|
|
7264
7414
|
createUnlocalizableLoader(options.returnUnlocalizedKeys)
|
|
7265
7415
|
);
|
|
7416
|
+
case "markdoc":
|
|
7417
|
+
return composeLoaders(
|
|
7418
|
+
createTextFileLoader(bucketPathPattern),
|
|
7419
|
+
createMarkdocLoader(),
|
|
7420
|
+
createFlatLoader(),
|
|
7421
|
+
createEnsureKeyOrderLoader(),
|
|
7422
|
+
createSyncLoader(),
|
|
7423
|
+
createUnlocalizableLoader(options.returnUnlocalizedKeys)
|
|
7424
|
+
);
|
|
7266
7425
|
case "mdx":
|
|
7267
7426
|
return composeLoaders(
|
|
7268
7427
|
createTextFileLoader(bucketPathPattern),
|
|
@@ -7494,7 +7653,7 @@ function createLingoLocalizer(params) {
|
|
|
7494
7653
|
// src/cli/processor/basic.ts
|
|
7495
7654
|
import { generateText } from "ai";
|
|
7496
7655
|
import _29 from "lodash";
|
|
7497
|
-
function createBasicTranslator(model, systemPrompt) {
|
|
7656
|
+
function createBasicTranslator(model, systemPrompt, settings = {}) {
|
|
7498
7657
|
return async (input2, onProgress) => {
|
|
7499
7658
|
const chunks = extractPayloadChunks(input2.processableData);
|
|
7500
7659
|
const subResults = [];
|
|
@@ -7516,6 +7675,7 @@ function createBasicTranslator(model, systemPrompt) {
|
|
|
7516
7675
|
}
|
|
7517
7676
|
const response = await generateText({
|
|
7518
7677
|
model,
|
|
7678
|
+
...settings,
|
|
7519
7679
|
messages: [
|
|
7520
7680
|
{
|
|
7521
7681
|
role: "system",
|
|
@@ -7606,7 +7766,8 @@ function createProcessor(provider, params) {
|
|
|
7606
7766
|
return result;
|
|
7607
7767
|
} else {
|
|
7608
7768
|
const model = getPureModelProvider(provider);
|
|
7609
|
-
const
|
|
7769
|
+
const settings = provider.settings || {};
|
|
7770
|
+
const result = createBasicTranslator(model, provider.prompt, settings);
|
|
7610
7771
|
return result;
|
|
7611
7772
|
}
|
|
7612
7773
|
}
|
|
@@ -7809,7 +7970,7 @@ function checkIfFileExists(filePath) {
|
|
|
7809
7970
|
|
|
7810
7971
|
// src/cli/utils/delta.ts
|
|
7811
7972
|
import * as path15 from "path";
|
|
7812
|
-
import
|
|
7973
|
+
import YAML5 from "yaml";
|
|
7813
7974
|
var LockSchema = z.object({
|
|
7814
7975
|
version: z.literal(1).default(1),
|
|
7815
7976
|
checksums: z.record(
|
|
@@ -7874,7 +8035,7 @@ function createDeltaProcessor(fileKey) {
|
|
|
7874
8035
|
},
|
|
7875
8036
|
async loadLock() {
|
|
7876
8037
|
const lockfileContent = tryReadFile(lockfilePath, null);
|
|
7877
|
-
const lockfileYaml = lockfileContent ?
|
|
8038
|
+
const lockfileYaml = lockfileContent ? YAML5.parse(lockfileContent) : null;
|
|
7878
8039
|
const lockfileData = lockfileYaml ? LockSchema.parse(lockfileYaml) : {
|
|
7879
8040
|
version: 1,
|
|
7880
8041
|
checksums: {}
|
|
@@ -7882,7 +8043,7 @@ function createDeltaProcessor(fileKey) {
|
|
|
7882
8043
|
return lockfileData;
|
|
7883
8044
|
},
|
|
7884
8045
|
async saveLock(lockData) {
|
|
7885
|
-
const lockfileYaml =
|
|
8046
|
+
const lockfileYaml = YAML5.stringify(lockData);
|
|
7886
8047
|
writeFile(lockfilePath, lockfileYaml);
|
|
7887
8048
|
},
|
|
7888
8049
|
async loadChecksums() {
|
|
@@ -8564,7 +8725,7 @@ import Ora8 from "ora";
|
|
|
8564
8725
|
import fs12 from "fs";
|
|
8565
8726
|
import path16 from "path";
|
|
8566
8727
|
import Z4 from "zod";
|
|
8567
|
-
import
|
|
8728
|
+
import YAML6 from "yaml";
|
|
8568
8729
|
import { MD5 as MD52 } from "object-hash";
|
|
8569
8730
|
import _32 from "lodash";
|
|
8570
8731
|
function createLockfileHelper() {
|
|
@@ -8612,12 +8773,12 @@ function createLockfileHelper() {
|
|
|
8612
8773
|
return LockfileSchema.parse({});
|
|
8613
8774
|
}
|
|
8614
8775
|
const content = fs12.readFileSync(lockfilePath, "utf-8");
|
|
8615
|
-
const result = LockfileSchema.parse(
|
|
8776
|
+
const result = LockfileSchema.parse(YAML6.parse(content));
|
|
8616
8777
|
return result;
|
|
8617
8778
|
}
|
|
8618
8779
|
function _saveLockfile(lockfile) {
|
|
8619
8780
|
const lockfilePath = _getLockfilePath();
|
|
8620
|
-
const content =
|
|
8781
|
+
const content = YAML6.stringify(lockfile);
|
|
8621
8782
|
fs12.writeFileSync(lockfilePath, content);
|
|
8622
8783
|
}
|
|
8623
8784
|
function _getLockfilePath() {
|
|
@@ -8958,8 +9119,9 @@ function createLingoDotDevLocalizer(explicitApiKey) {
|
|
|
8958
9119
|
authenticated: !!response,
|
|
8959
9120
|
username: response?.email
|
|
8960
9121
|
};
|
|
8961
|
-
} catch {
|
|
8962
|
-
|
|
9122
|
+
} catch (error) {
|
|
9123
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
9124
|
+
return { authenticated: false, error: errorMessage };
|
|
8963
9125
|
}
|
|
8964
9126
|
},
|
|
8965
9127
|
localize: async (input2, onProgress) => {
|
|
@@ -8996,6 +9158,7 @@ import { generateText as generateText2 } from "ai";
|
|
|
8996
9158
|
import { jsonrepair as jsonrepair3 } from "jsonrepair";
|
|
8997
9159
|
import { createOllama as createOllama2 } from "ollama-ai-provider";
|
|
8998
9160
|
function createExplicitLocalizer(provider) {
|
|
9161
|
+
const settings = provider.settings || {};
|
|
8999
9162
|
switch (provider.id) {
|
|
9000
9163
|
default:
|
|
9001
9164
|
throw new Error(
|
|
@@ -9019,7 +9182,8 @@ function createExplicitLocalizer(provider) {
|
|
|
9019
9182
|
id: provider.id,
|
|
9020
9183
|
prompt: provider.prompt,
|
|
9021
9184
|
apiKeyName: "OPENAI_API_KEY",
|
|
9022
|
-
baseUrl: provider.baseUrl
|
|
9185
|
+
baseUrl: provider.baseUrl,
|
|
9186
|
+
settings
|
|
9023
9187
|
});
|
|
9024
9188
|
case "anthropic":
|
|
9025
9189
|
return createAiSdkLocalizer({
|
|
@@ -9027,7 +9191,8 @@ function createExplicitLocalizer(provider) {
|
|
|
9027
9191
|
id: provider.id,
|
|
9028
9192
|
prompt: provider.prompt,
|
|
9029
9193
|
apiKeyName: "ANTHROPIC_API_KEY",
|
|
9030
|
-
baseUrl: provider.baseUrl
|
|
9194
|
+
baseUrl: provider.baseUrl,
|
|
9195
|
+
settings
|
|
9031
9196
|
});
|
|
9032
9197
|
case "google":
|
|
9033
9198
|
return createAiSdkLocalizer({
|
|
@@ -9035,7 +9200,8 @@ function createExplicitLocalizer(provider) {
|
|
|
9035
9200
|
id: provider.id,
|
|
9036
9201
|
prompt: provider.prompt,
|
|
9037
9202
|
apiKeyName: "GOOGLE_API_KEY",
|
|
9038
|
-
baseUrl: provider.baseUrl
|
|
9203
|
+
baseUrl: provider.baseUrl,
|
|
9204
|
+
settings
|
|
9039
9205
|
});
|
|
9040
9206
|
case "openrouter":
|
|
9041
9207
|
return createAiSdkLocalizer({
|
|
@@ -9043,14 +9209,16 @@ function createExplicitLocalizer(provider) {
|
|
|
9043
9209
|
id: provider.id,
|
|
9044
9210
|
prompt: provider.prompt,
|
|
9045
9211
|
apiKeyName: "OPENROUTER_API_KEY",
|
|
9046
|
-
baseUrl: provider.baseUrl
|
|
9212
|
+
baseUrl: provider.baseUrl,
|
|
9213
|
+
settings
|
|
9047
9214
|
});
|
|
9048
9215
|
case "ollama":
|
|
9049
9216
|
return createAiSdkLocalizer({
|
|
9050
9217
|
factory: (_params) => createOllama2().languageModel(provider.model),
|
|
9051
9218
|
id: provider.id,
|
|
9052
9219
|
prompt: provider.prompt,
|
|
9053
|
-
skipAuth: true
|
|
9220
|
+
skipAuth: true,
|
|
9221
|
+
settings
|
|
9054
9222
|
});
|
|
9055
9223
|
case "mistral":
|
|
9056
9224
|
return createAiSdkLocalizer({
|
|
@@ -9058,7 +9226,8 @@ function createExplicitLocalizer(provider) {
|
|
|
9058
9226
|
id: provider.id,
|
|
9059
9227
|
prompt: provider.prompt,
|
|
9060
9228
|
apiKeyName: "MISTRAL_API_KEY",
|
|
9061
|
-
baseUrl: provider.baseUrl
|
|
9229
|
+
baseUrl: provider.baseUrl,
|
|
9230
|
+
settings
|
|
9062
9231
|
});
|
|
9063
9232
|
}
|
|
9064
9233
|
}
|
|
@@ -9092,9 +9261,13 @@ function createAiSdkLocalizer(params) {
|
|
|
9092
9261
|
return {
|
|
9093
9262
|
id: params.id,
|
|
9094
9263
|
checkAuth: async () => {
|
|
9264
|
+
return { authenticated: true, username: "anonymous" };
|
|
9265
|
+
},
|
|
9266
|
+
validateSettings: async () => {
|
|
9095
9267
|
try {
|
|
9096
9268
|
await generateText2({
|
|
9097
9269
|
model,
|
|
9270
|
+
...params.settings,
|
|
9098
9271
|
messages: [
|
|
9099
9272
|
{ role: "system", content: "You are an echo server" },
|
|
9100
9273
|
{ role: "user", content: "OK" },
|
|
@@ -9102,9 +9275,10 @@ function createAiSdkLocalizer(params) {
|
|
|
9102
9275
|
{ role: "user", content: "OK" }
|
|
9103
9276
|
]
|
|
9104
9277
|
});
|
|
9105
|
-
return {
|
|
9278
|
+
return { valid: true };
|
|
9106
9279
|
} catch (error) {
|
|
9107
|
-
|
|
9280
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
9281
|
+
return { valid: false, error: errorMessage };
|
|
9108
9282
|
}
|
|
9109
9283
|
},
|
|
9110
9284
|
localize: async (input2) => {
|
|
@@ -9134,6 +9308,7 @@ function createAiSdkLocalizer(params) {
|
|
|
9134
9308
|
};
|
|
9135
9309
|
const response = await generateText2({
|
|
9136
9310
|
model,
|
|
9311
|
+
...params.settings,
|
|
9137
9312
|
messages: [
|
|
9138
9313
|
{ role: "system", content: systemPrompt },
|
|
9139
9314
|
{ role: "user", content: "OK" },
|
|
@@ -9147,6 +9322,9 @@ function createAiSdkLocalizer(params) {
|
|
|
9147
9322
|
]
|
|
9148
9323
|
});
|
|
9149
9324
|
const result = JSON.parse(response.text);
|
|
9325
|
+
if (typeof result.data === "object" && result.data !== null) {
|
|
9326
|
+
return result.data;
|
|
9327
|
+
}
|
|
9150
9328
|
const index = result.data.indexOf("{");
|
|
9151
9329
|
const lastIndex = result.data.lastIndexOf("}");
|
|
9152
9330
|
const trimmed = result.data.slice(index, lastIndex + 1);
|
|
@@ -9216,20 +9394,30 @@ async function setup(input2) {
|
|
|
9216
9394
|
},
|
|
9217
9395
|
{
|
|
9218
9396
|
title: "Checking authentication",
|
|
9397
|
+
enabled: (ctx) => ctx.localizer?.id === "Lingo.dev",
|
|
9219
9398
|
task: async (ctx, task) => {
|
|
9220
9399
|
const authStatus = await ctx.localizer.checkAuth();
|
|
9221
9400
|
if (!authStatus.authenticated) {
|
|
9222
|
-
throw new Error(
|
|
9223
|
-
`Failed to authenticate with ${chalk10.hex(colors.yellow)(
|
|
9224
|
-
ctx.localizer.id
|
|
9225
|
-
)} provider. Please check your API key and try again.`
|
|
9226
|
-
);
|
|
9401
|
+
throw new Error(authStatus.error || "Authentication failed");
|
|
9227
9402
|
}
|
|
9228
9403
|
task.title = `Authenticated as ${chalk10.hex(colors.yellow)(
|
|
9229
9404
|
authStatus.username
|
|
9230
9405
|
)}`;
|
|
9231
9406
|
}
|
|
9232
9407
|
},
|
|
9408
|
+
{
|
|
9409
|
+
title: "Validating configuration",
|
|
9410
|
+
enabled: (ctx) => ctx.localizer?.id !== "Lingo.dev",
|
|
9411
|
+
task: async (ctx, task) => {
|
|
9412
|
+
const validationStatus = await ctx.localizer.validateSettings();
|
|
9413
|
+
if (!validationStatus.valid) {
|
|
9414
|
+
throw new Error(
|
|
9415
|
+
validationStatus.error || "Configuration validation failed"
|
|
9416
|
+
);
|
|
9417
|
+
}
|
|
9418
|
+
task.title = `Configuration validated`;
|
|
9419
|
+
}
|
|
9420
|
+
},
|
|
9233
9421
|
{
|
|
9234
9422
|
title: "Initializing localization provider",
|
|
9235
9423
|
async task(ctx, task) {
|
|
@@ -9407,12 +9595,21 @@ async function execute(input2) {
|
|
|
9407
9595
|
title: `Processing localization tasks ${chalk12.dim(
|
|
9408
9596
|
`(tasks: ${input2.tasks.length}, concurrency: ${effectiveConcurrency})`
|
|
9409
9597
|
)}`,
|
|
9410
|
-
task: (ctx, task) => {
|
|
9598
|
+
task: async (ctx, task) => {
|
|
9411
9599
|
if (input2.tasks.length < 1) {
|
|
9412
9600
|
task.title = `Skipping, nothing to localize.`;
|
|
9413
9601
|
task.skip();
|
|
9414
9602
|
return;
|
|
9415
9603
|
}
|
|
9604
|
+
const initialChecksumsMap = /* @__PURE__ */ new Map();
|
|
9605
|
+
const uniqueBucketPatterns = _34.uniq(
|
|
9606
|
+
ctx.tasks.map((t2) => t2.bucketPathPattern)
|
|
9607
|
+
);
|
|
9608
|
+
for (const bucketPathPattern of uniqueBucketPatterns) {
|
|
9609
|
+
const deltaProcessor = createDeltaProcessor(bucketPathPattern);
|
|
9610
|
+
const checksums = await deltaProcessor.loadChecksums();
|
|
9611
|
+
initialChecksumsMap.set(bucketPathPattern, checksums);
|
|
9612
|
+
}
|
|
9416
9613
|
const i18nLimiter = pLimit(effectiveConcurrency);
|
|
9417
9614
|
const ioLimiter = pLimit(1);
|
|
9418
9615
|
const workersCount = effectiveConcurrency;
|
|
@@ -9427,6 +9624,7 @@ async function execute(input2) {
|
|
|
9427
9624
|
assignedTasks,
|
|
9428
9625
|
ioLimiter,
|
|
9429
9626
|
i18nLimiter,
|
|
9627
|
+
initialChecksumsMap,
|
|
9430
9628
|
onDone() {
|
|
9431
9629
|
task.title = createExecutionProgressMessage(ctx);
|
|
9432
9630
|
}
|
|
@@ -9506,6 +9704,7 @@ function createWorkerTask(args) {
|
|
|
9506
9704
|
const deltaProcessor = createDeltaProcessor(
|
|
9507
9705
|
assignedTask.bucketPathPattern
|
|
9508
9706
|
);
|
|
9707
|
+
const initialChecksums = args.initialChecksumsMap.get(assignedTask.bucketPathPattern) || {};
|
|
9509
9708
|
const taskResult = await args.i18nLimiter(async () => {
|
|
9510
9709
|
try {
|
|
9511
9710
|
const sourceData = await bucketLoader.pull(
|
|
@@ -9515,11 +9714,10 @@ function createWorkerTask(args) {
|
|
|
9515
9714
|
const targetData = await bucketLoader.pull(
|
|
9516
9715
|
assignedTask.targetLocale
|
|
9517
9716
|
);
|
|
9518
|
-
const checksums = await deltaProcessor.loadChecksums();
|
|
9519
9717
|
const delta = await deltaProcessor.calculateDelta({
|
|
9520
9718
|
sourceData,
|
|
9521
9719
|
targetData,
|
|
9522
|
-
checksums
|
|
9720
|
+
checksums: initialChecksums
|
|
9523
9721
|
});
|
|
9524
9722
|
const processableData = _34.chain(sourceData).entries().filter(
|
|
9525
9723
|
([key, value]) => delta.added.includes(key) || delta.updated.includes(key) || !!args.ctx.flags.force
|
|
@@ -9532,7 +9730,12 @@ function createWorkerTask(args) {
|
|
|
9532
9730
|
await args.ioLimiter(async () => {
|
|
9533
9731
|
await bucketLoader.push(assignedTask.targetLocale, targetData);
|
|
9534
9732
|
});
|
|
9535
|
-
return {
|
|
9733
|
+
return {
|
|
9734
|
+
status: "skipped",
|
|
9735
|
+
pathPattern: assignedTask.bucketPathPattern,
|
|
9736
|
+
sourceLocale: assignedTask.sourceLocale,
|
|
9737
|
+
targetLocale: assignedTask.targetLocale
|
|
9738
|
+
};
|
|
9536
9739
|
}
|
|
9537
9740
|
const relevantHints = _34.pick(hints, Object.keys(processableData));
|
|
9538
9741
|
const processedTargetData = await args.ctx.localizer.localize(
|
|
@@ -9586,16 +9789,24 @@ function createWorkerTask(args) {
|
|
|
9586
9789
|
assignedTask.targetLocale,
|
|
9587
9790
|
finalRenamedTargetData
|
|
9588
9791
|
);
|
|
9589
|
-
const
|
|
9792
|
+
const checksums = await deltaProcessor.createChecksums(sourceData);
|
|
9590
9793
|
if (!args.ctx.flags.targetLocale?.length) {
|
|
9591
|
-
await deltaProcessor.saveChecksums(
|
|
9794
|
+
await deltaProcessor.saveChecksums(checksums);
|
|
9592
9795
|
}
|
|
9593
9796
|
});
|
|
9594
|
-
return {
|
|
9797
|
+
return {
|
|
9798
|
+
status: "success",
|
|
9799
|
+
pathPattern: assignedTask.bucketPathPattern,
|
|
9800
|
+
sourceLocale: assignedTask.sourceLocale,
|
|
9801
|
+
targetLocale: assignedTask.targetLocale
|
|
9802
|
+
};
|
|
9595
9803
|
} catch (error) {
|
|
9596
9804
|
return {
|
|
9597
9805
|
status: "error",
|
|
9598
|
-
error
|
|
9806
|
+
error,
|
|
9807
|
+
pathPattern: assignedTask.bucketPathPattern,
|
|
9808
|
+
sourceLocale: assignedTask.sourceLocale,
|
|
9809
|
+
targetLocale: assignedTask.targetLocale
|
|
9599
9810
|
};
|
|
9600
9811
|
}
|
|
9601
9812
|
});
|
|
@@ -11273,7 +11484,7 @@ async function renderHero2() {
|
|
|
11273
11484
|
// package.json
|
|
11274
11485
|
var package_default = {
|
|
11275
11486
|
name: "lingo.dev",
|
|
11276
|
-
version: "0.
|
|
11487
|
+
version: "0.112.0",
|
|
11277
11488
|
description: "Lingo.dev CLI",
|
|
11278
11489
|
private: false,
|
|
11279
11490
|
publishConfig: {
|
|
@@ -11414,6 +11625,7 @@ var package_default = {
|
|
|
11414
11625
|
"@lingo.dev/_react": "workspace:*",
|
|
11415
11626
|
"@lingo.dev/_sdk": "workspace:*",
|
|
11416
11627
|
"@lingo.dev/_spec": "workspace:*",
|
|
11628
|
+
"@markdoc/markdoc": "^0.5.4",
|
|
11417
11629
|
"@modelcontextprotocol/sdk": "^1.5.0",
|
|
11418
11630
|
"@openrouter/ai-sdk-provider": "^0.7.1",
|
|
11419
11631
|
"@paralleldrive/cuid2": "^2.2.2",
|