@parhelia/localization 0.1.12906 → 0.1.12909
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/LocalizeItemCommand.d.ts +7 -1
- package/dist/LocalizeItemCommand.d.ts.map +1 -1
- package/dist/LocalizeItemCommand.js +31 -18
- package/dist/LocalizeItemDialog.d.ts.map +1 -1
- package/dist/LocalizeItemDialog.js +97 -35
- package/dist/LocalizeItemUtils.d.ts +1 -2
- package/dist/LocalizeItemUtils.d.ts.map +1 -1
- package/dist/LocalizeItemUtils.js +78 -36
- package/dist/api/discovery.d.ts +25 -0
- package/dist/api/discovery.d.ts.map +1 -1
- package/dist/api/discovery.js +106 -2
- package/dist/hooks/useTranslationWizard.d.ts.map +1 -1
- package/dist/hooks/useTranslationWizard.js +3 -3
- package/dist/index.d.ts +10 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +36 -32
- package/dist/services/translationService.d.ts +41 -10
- package/dist/services/translationService.d.ts.map +1 -1
- package/dist/services/translationService.js +48 -6
- package/dist/settings/TranslationServicesPanel.d.ts.map +1 -1
- package/dist/settings/TranslationServicesPanel.js +21 -36
- package/dist/setup/LocalizationSetupStep.d.ts.map +1 -1
- package/dist/setup/LocalizationSetupStep.js +29 -18
- package/dist/sidebar/TranslationSidebar.d.ts.map +1 -1
- package/dist/sidebar/TranslationSidebar.js +20 -10
- package/dist/steps/ItemSelectionStep.d.ts +3 -0
- package/dist/steps/ItemSelectionStep.d.ts.map +1 -0
- package/dist/steps/ItemSelectionStep.js +24 -0
- package/dist/steps/ItemSelectionTree.d.ts +13 -0
- package/dist/steps/ItemSelectionTree.d.ts.map +1 -0
- package/dist/steps/ItemSelectionTree.js +327 -0
- package/dist/steps/PromptCustomizationStep.d.ts +1 -1
- package/dist/steps/PromptCustomizationStep.d.ts.map +1 -1
- package/dist/steps/PromptCustomizationStep.js +159 -56
- package/dist/steps/ServiceLanguageSelectionStep.d.ts +6 -1
- package/dist/steps/ServiceLanguageSelectionStep.d.ts.map +1 -1
- package/dist/steps/ServiceLanguageSelectionStep.js +92 -165
- package/dist/steps/WizardStepShell.d.ts +17 -0
- package/dist/steps/WizardStepShell.d.ts.map +1 -0
- package/dist/steps/WizardStepShell.js +11 -0
- package/dist/steps/types.d.ts +17 -1
- package/dist/steps/types.d.ts.map +1 -1
- package/dist/translation-center/TranslationBatches.d.ts +2 -0
- package/dist/translation-center/TranslationBatches.d.ts.map +1 -0
- package/dist/translation-center/TranslationBatches.js +1180 -0
- package/dist/translation-center/TranslationManagement.d.ts.map +1 -1
- package/dist/translation-center/TranslationManagement.js +25 -15
- package/dist/translation-center/TranslationsTitlebar.d.ts +6 -0
- package/dist/translation-center/TranslationsTitlebar.d.ts.map +1 -0
- package/dist/translation-center/TranslationsTitlebar.js +25 -0
- package/dist/translationEvents.d.ts +6 -0
- package/dist/translationEvents.d.ts.map +1 -0
- package/dist/translationEvents.js +4 -0
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/constants.d.ts +0 -15
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js +0 -21
- package/dist/steps/MetadataInputStep.d.ts +0 -4
- package/dist/steps/MetadataInputStep.d.ts.map +0 -1
- package/dist/steps/MetadataInputStep.js +0 -41
- package/dist/steps/SubitemDiscoveryStep.d.ts +0 -3
- package/dist/steps/SubitemDiscoveryStep.d.ts.map +0 -1
- package/dist/steps/SubitemDiscoveryStep.js +0 -313
- package/dist/steps/index.d.ts +0 -5
- package/dist/steps/index.d.ts.map +0 -1
- package/dist/steps/index.js +0 -4
- package/dist/translation-center/BatchTranslationView.d.ts +0 -8
- package/dist/translation-center/BatchTranslationView.d.ts.map +0 -1
- package/dist/translation-center/BatchTranslationView.js +0 -870
- package/dist/translation-center/RecentTranslations.d.ts +0 -2
- package/dist/translation-center/RecentTranslations.d.ts.map +0 -1
- package/dist/translation-center/RecentTranslations.js +0 -309
- package/dist/utils/createVersions.d.ts +0 -14
- package/dist/utils/createVersions.d.ts.map +0 -1
- package/dist/utils/createVersions.js +0 -26
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
import { Command, CommandContext, CommandData, FullItem } from "@parhelia/core";
|
|
1
|
+
import { Command, CommandContext, CommandData, EditContextType, FullItem } from "@parhelia/core";
|
|
2
|
+
import { TranslationDialogResult } from "./steps/types";
|
|
2
3
|
export type LocalizeItemCommandData = CommandData & {
|
|
3
4
|
items: FullItem[];
|
|
4
5
|
};
|
|
5
6
|
export type LocalizeItemCommandContext = CommandContext<LocalizeItemCommandData>;
|
|
6
7
|
export type LocalizeItemCommand = Command<LocalizeItemCommandData>;
|
|
8
|
+
export declare function openLocalizeItemDialog({ editContext, openDialog, items, }: {
|
|
9
|
+
editContext: EditContextType;
|
|
10
|
+
openDialog?: EditContextType["openDialog"];
|
|
11
|
+
items: FullItem[];
|
|
12
|
+
}): Promise<TranslationDialogResult | null>;
|
|
7
13
|
export declare const localizeItemCommand: LocalizeItemCommand;
|
|
8
14
|
//# sourceMappingURL=LocalizeItemCommand.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LocalizeItemCommand.d.ts","sourceRoot":"","sources":["../src/LocalizeItemCommand.tsx"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"LocalizeItemCommand.d.ts","sourceRoot":"","sources":["../src/LocalizeItemCommand.tsx"],"names":[],"mappings":"AACA,OAAO,EACL,OAAO,EACP,cAAc,EACd,WAAW,EACX,eAAe,EACf,QAAQ,EACT,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAEL,uBAAuB,EACxB,MAAM,eAAe,CAAC;AAQvB,MAAM,MAAM,uBAAuB,GAAG,WAAW,GAAG;IAClD,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GACpC,cAAc,CAAC,uBAAuB,CAAC,CAAC;AAC1C,MAAM,MAAM,mBAAmB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC;AAEnE,wBAAsB,sBAAsB,CAAC,EAC3C,WAAW,EACX,UAAmC,EACnC,KAAK,GACN,EAAE;IACD,WAAW,EAAE,eAAe,CAAC;IAC7B,UAAU,CAAC,EAAE,eAAe,CAAC,YAAY,CAAC,CAAC;IAC3C,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB,2CAiCA;AAED,eAAO,MAAM,mBAAmB,EAAE,mBA6BjC,CAAC"}
|
|
@@ -2,9 +2,35 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import React from "react";
|
|
3
3
|
import { Globe as LucideGlobe } from "lucide-react";
|
|
4
4
|
import { LocalizeItemDialog } from "./LocalizeItemDialog";
|
|
5
|
+
import { dispatchTranslationBatchStarted } from "./translationEvents";
|
|
5
6
|
// Icon wrapper to avoid React 19 JSX type issues with forwardRef components.
|
|
6
7
|
// Use React.createElement so we don't call the forwardRef objects as functions.
|
|
7
8
|
const GlobeIcon = (props) => React.createElement(LucideGlobe, props);
|
|
9
|
+
export async function openLocalizeItemDialog({ editContext, openDialog = editContext.openDialog, items, }) {
|
|
10
|
+
const result = await openDialog(LocalizeItemDialog, {
|
|
11
|
+
items,
|
|
12
|
+
editContext,
|
|
13
|
+
});
|
|
14
|
+
// If translation was started (result contains batchId), navigate to the batch view
|
|
15
|
+
if (result?.batchId) {
|
|
16
|
+
const translationManagementEnabled = editContext?.configuration?.localization
|
|
17
|
+
?.translationManagement !== false;
|
|
18
|
+
if (translationManagementEnabled) {
|
|
19
|
+
// Synchronous URL update to avoid race with workspace URL sync
|
|
20
|
+
const params = new URLSearchParams(window.location.search);
|
|
21
|
+
params.set("workspace", "translation-management");
|
|
22
|
+
params.set("batchId", result.batchId);
|
|
23
|
+
const newUrl = `${window.location.pathname}?${params.toString()}`;
|
|
24
|
+
window.history.pushState(null, "", newUrl);
|
|
25
|
+
// Now switch the workspace; URL already contains batchId
|
|
26
|
+
editContext.switchWorkspace("translation-management");
|
|
27
|
+
window.setTimeout(() => {
|
|
28
|
+
dispatchTranslationBatchStarted(result.batchId);
|
|
29
|
+
}, 0);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
8
34
|
export const localizeItemCommand = {
|
|
9
35
|
id: "localizeItem",
|
|
10
36
|
label: "Translate",
|
|
@@ -14,7 +40,8 @@ export const localizeItemCommand = {
|
|
|
14
40
|
return true;
|
|
15
41
|
}
|
|
16
42
|
// Check if multi-item is disabled and multiple items are selected
|
|
17
|
-
const multiItemEnabled = context.editContext?.configuration?.localization?.multiItem !==
|
|
43
|
+
const multiItemEnabled = context.editContext?.configuration?.localization?.multiItem !==
|
|
44
|
+
false;
|
|
18
45
|
if (!multiItemEnabled && context.data.items.length > 1) {
|
|
19
46
|
return true; // Disable command when multiple items selected in single-item mode
|
|
20
47
|
}
|
|
@@ -25,24 +52,10 @@ export const localizeItemCommand = {
|
|
|
25
52
|
if (!items || !items?.length) {
|
|
26
53
|
return;
|
|
27
54
|
}
|
|
28
|
-
|
|
29
|
-
items: items,
|
|
55
|
+
return openLocalizeItemDialog({
|
|
30
56
|
editContext: context.editContext,
|
|
57
|
+
openDialog: context.openDialog,
|
|
58
|
+
items,
|
|
31
59
|
});
|
|
32
|
-
// If translation was started (result contains batchId), navigate to the batch view
|
|
33
|
-
if (result?.batchId) {
|
|
34
|
-
const translationManagementEnabled = context.editContext?.configuration?.localization?.translationManagement !== false;
|
|
35
|
-
if (translationManagementEnabled) {
|
|
36
|
-
// Synchronous URL update to avoid race with workspace URL sync
|
|
37
|
-
const params = new URLSearchParams(window.location.search);
|
|
38
|
-
params.set("workspace", "translation-management");
|
|
39
|
-
params.set("batchId", result.batchId);
|
|
40
|
-
const newUrl = `${window.location.pathname}?${params.toString()}`;
|
|
41
|
-
window.history.pushState(null, "", newUrl);
|
|
42
|
-
// Now switch the workspace; URL already contains batchId
|
|
43
|
-
context.editContext.switchWorkspace("translation-management");
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return result;
|
|
47
60
|
},
|
|
48
61
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LocalizeItemDialog.d.ts","sourceRoot":"","sources":["../src/LocalizeItemDialog.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"LocalizeItemDialog.d.ts","sourceRoot":"","sources":["../src/LocalizeItemDialog.tsx"],"names":[],"mappings":"AA8BA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EAExB,MAAM,eAAe,CAAC;AAqCvB,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,uBAAuB,GAAG,WAAW,CAAC,uBAAuB,CAAC,2CAugBtE"}
|
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
import { jsx as _jsx,
|
|
2
|
-
import { Dialog, DialogContent,
|
|
3
|
-
import {
|
|
4
|
-
import { AlertTriangle as LucideAlertTriangle } from "lucide-react";
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Dialog, DialogContent, StyledDialogTitle, Button, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@parhelia/core";
|
|
3
|
+
import { useCallback, useEffect, useMemo, useRef, useState, } from "react";
|
|
4
|
+
import { AlertTriangle as LucideAlertTriangle, ArrowRight as LucideArrowRight, Globe as LucideGlobe, } from "lucide-react";
|
|
5
5
|
import { useTranslationWizard } from "./hooks/useTranslationWizard";
|
|
6
|
-
import { performDefaultTranslation,
|
|
6
|
+
import { performDefaultTranslation, } from "./LocalizeItemUtils";
|
|
7
7
|
const AlertTriangleIcon = LucideAlertTriangle;
|
|
8
|
+
const GlobeIcon = LucideGlobe;
|
|
9
|
+
const ArrowRightIcon = LucideArrowRight;
|
|
8
10
|
// Threshold for warning about large batch translations
|
|
9
11
|
const LARGE_BATCH_WARNING_THRESHOLD = 100;
|
|
12
|
+
const getNextButtonLabel = (step) => step?.nextButtonLabel || step?.name || "Next";
|
|
10
13
|
// Note: DialogButtons is an internal component that might need to be added to core exports
|
|
11
14
|
// For now, we'll implement it inline
|
|
12
|
-
const DialogButtons = ({ children, ...props }) => (_jsx("div", { className: "mt-auto flex shrink-0 items-center gap-3 border-t border-
|
|
15
|
+
const DialogButtons = ({ children, ...props }) => (_jsx("div", { className: "mt-auto flex shrink-0 items-center gap-3 border-t border-border-default bg-white px-6 py-4", ...props, children: children }));
|
|
13
16
|
export function LocalizeItemDialog(props) {
|
|
14
17
|
const editContext = props.editContext;
|
|
15
18
|
const configuration = editContext.configuration.translationWizard;
|
|
@@ -33,7 +36,12 @@ export function LocalizeItemDialog(props) {
|
|
|
33
36
|
// Provide stable callbacks to steps to avoid update loops
|
|
34
37
|
const lastActionsSigRef = useRef("");
|
|
35
38
|
const provideFooterActions = useCallback((actions) => {
|
|
36
|
-
const normalized = (actions || []).map(a => ({
|
|
39
|
+
const normalized = (actions || []).map((a) => ({
|
|
40
|
+
key: a.key,
|
|
41
|
+
label: a.label,
|
|
42
|
+
disabled: !!a.disabled,
|
|
43
|
+
signature: a.signature || "",
|
|
44
|
+
}));
|
|
37
45
|
const signature = JSON.stringify(normalized);
|
|
38
46
|
if (signature === lastActionsSigRef.current)
|
|
39
47
|
return;
|
|
@@ -45,7 +53,6 @@ export function LocalizeItemDialog(props) {
|
|
|
45
53
|
}, [props.onClose]);
|
|
46
54
|
// Memoize activeSteps to prevent unnecessary recalculations and new object references
|
|
47
55
|
// This prevents infinite loops when wizardData changes but skip conditions don't
|
|
48
|
-
// The skip condition for subitem-discovery step checks includeSubitems
|
|
49
56
|
// The skip condition for prompt-customization step checks serviceCustomData and translationProvider
|
|
50
57
|
const activeSteps = useMemo(() => {
|
|
51
58
|
const steps = configuration.steps.filter((step) => !step.skipCondition || !step.skipCondition(wizardData));
|
|
@@ -54,13 +61,13 @@ export function LocalizeItemDialog(props) {
|
|
|
54
61
|
configuration.steps,
|
|
55
62
|
wizardData.includeSubitems,
|
|
56
63
|
wizardData.serviceCustomData,
|
|
57
|
-
wizardData.translationProvider
|
|
64
|
+
wizardData.translationProvider,
|
|
58
65
|
]); // Depend on what affects skip conditions
|
|
59
66
|
const currentStep = activeSteps[currentStepIndex];
|
|
60
67
|
// Refs for stable callbacks - updated during render to avoid dependency issues
|
|
61
68
|
const currentStepIdRef = useRef(currentStep?.id);
|
|
62
69
|
const currentStepIndexRef = useRef(currentStepIndex);
|
|
63
|
-
const lastSetWizardDataRef = useRef(
|
|
70
|
+
const lastSetWizardDataRef = useRef("");
|
|
64
71
|
// Track step changes for logging
|
|
65
72
|
if (currentStepIdRef.current !== currentStep?.id) {
|
|
66
73
|
currentStepIdRef.current = currentStep?.id;
|
|
@@ -84,7 +91,7 @@ export function LocalizeItemDialog(props) {
|
|
|
84
91
|
const isLastStep = currentStepIndex === activeSteps.length - 1;
|
|
85
92
|
const canProceed = stepCompleted >= currentStepIndex;
|
|
86
93
|
const handleNext = async () => {
|
|
87
|
-
if (beforeNextCallback && typeof beforeNextCallback ===
|
|
94
|
+
if (beforeNextCallback && typeof beforeNextCallback === "function") {
|
|
88
95
|
const canProceed = await beforeNextCallback();
|
|
89
96
|
if (!canProceed)
|
|
90
97
|
return;
|
|
@@ -106,13 +113,40 @@ export function LocalizeItemDialog(props) {
|
|
|
106
113
|
switchStep(currentStepIndex - 1);
|
|
107
114
|
}
|
|
108
115
|
};
|
|
109
|
-
// Calculate translation counts for
|
|
116
|
+
// Calculate translation counts for the Start Translation button and
|
|
117
|
+
// the large-batch warning. Sums each selected item plus its streamed
|
|
118
|
+
// subitem count (when includeSubitems is on). `isStreaming` is true
|
|
119
|
+
// while any selected-and-flagged item is still being counted, so the
|
|
120
|
+
// UI can append a "+" to indicate the total is not yet final.
|
|
110
121
|
const calculateTranslationCounts = useCallback((data) => {
|
|
111
|
-
const itemsToTranslate = data.includeSubitems ? data.discoveredItems : data.items;
|
|
112
|
-
const itemCount = itemsToTranslate.length;
|
|
113
122
|
const languageCount = data.targetLanguages.length;
|
|
123
|
+
const subitemCounts = data.subitemCounts ?? {};
|
|
124
|
+
let itemCount = 0;
|
|
125
|
+
let isStreaming = false;
|
|
126
|
+
if (data.selectionTreeItems && data.selectionTreeItems.length > 0) {
|
|
127
|
+
for (const entry of data.selectionTreeItems) {
|
|
128
|
+
itemCount += 1;
|
|
129
|
+
if (!entry.includeSubitems)
|
|
130
|
+
continue;
|
|
131
|
+
const c = subitemCounts[entry.descriptor.id];
|
|
132
|
+
if (c === undefined || c === "loading") {
|
|
133
|
+
isStreaming = true;
|
|
134
|
+
}
|
|
135
|
+
else if (c !== "error") {
|
|
136
|
+
itemCount += c.count;
|
|
137
|
+
if (!c.complete)
|
|
138
|
+
isStreaming = true;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
const baseItems = data.discoveredItems && data.discoveredItems.length > 0
|
|
144
|
+
? data.discoveredItems
|
|
145
|
+
: data.items;
|
|
146
|
+
itemCount = baseItems.length;
|
|
147
|
+
}
|
|
114
148
|
const totalTranslations = itemCount * languageCount;
|
|
115
|
-
return { itemCount, languageCount, totalTranslations };
|
|
149
|
+
return { itemCount, languageCount, totalTranslations, isStreaming };
|
|
116
150
|
}, []);
|
|
117
151
|
const executeTranslation = useCallback(async () => {
|
|
118
152
|
setIsSubmitting(true);
|
|
@@ -124,33 +158,36 @@ export function LocalizeItemDialog(props) {
|
|
|
124
158
|
targetLanguages: currentWizardData.targetLanguages,
|
|
125
159
|
includeSubitems: currentWizardData.includeSubitems,
|
|
126
160
|
discoveredItems: currentWizardData.discoveredItems,
|
|
161
|
+
selectionTreeItems: currentWizardData.selectionTreeItems,
|
|
127
162
|
};
|
|
128
163
|
try {
|
|
129
|
-
const
|
|
130
|
-
const translationResult = await performDefaultTranslation(currentWizardData, editContext, batchId);
|
|
164
|
+
const translationResult = await performDefaultTranslation(currentWizardData, editContext);
|
|
131
165
|
// Include batchId in result for navigation to translation management
|
|
132
|
-
const resultWithBatch = {
|
|
166
|
+
const resultWithBatch = {
|
|
167
|
+
...result,
|
|
168
|
+
batchId: translationResult.batchId,
|
|
169
|
+
};
|
|
133
170
|
// Close dialog and let parent component handle navigation to translation management
|
|
134
171
|
props.onClose?.(resultWithBatch);
|
|
135
172
|
}
|
|
136
173
|
catch (error) {
|
|
137
174
|
// Handle specific error types
|
|
138
|
-
if (error.name ===
|
|
175
|
+
if (error.name === "NoTranslationsNeededError") {
|
|
139
176
|
// Show user-friendly message via toast and close dialog
|
|
140
|
-
editContext.showToast?.(
|
|
177
|
+
editContext.showToast?.("No translations needed. All selected target languages match the source languages of the items.");
|
|
141
178
|
props.onClose?.(result);
|
|
142
179
|
return;
|
|
143
180
|
}
|
|
144
181
|
// For other errors, show toast and stay in dialog
|
|
145
|
-
console.error(
|
|
146
|
-
const errorMessage = error.message ||
|
|
182
|
+
console.error("Translation failed:", error);
|
|
183
|
+
const errorMessage = error.message || "Translation request failed. Please try again.";
|
|
147
184
|
editContext.showToast?.(errorMessage);
|
|
148
185
|
// Don't close the dialog - let user try again or cancel
|
|
149
186
|
}
|
|
150
187
|
}
|
|
151
188
|
catch (error) {
|
|
152
|
-
console.error(
|
|
153
|
-
editContext.showToast?.(
|
|
189
|
+
console.error("Unexpected error in translation:", error);
|
|
190
|
+
editContext.showToast?.("An unexpected error occurred. Please try again.");
|
|
154
191
|
// Don't close the dialog on error
|
|
155
192
|
}
|
|
156
193
|
finally {
|
|
@@ -181,18 +218,40 @@ export function LocalizeItemDialog(props) {
|
|
|
181
218
|
: null;
|
|
182
219
|
// Serialize metadata for comparison (supports both string and object formats)
|
|
183
220
|
const metadataKey = newData.metadata
|
|
184
|
-
?
|
|
221
|
+
? typeof newData.metadata === "string"
|
|
185
222
|
? newData.metadata
|
|
186
|
-
: JSON.stringify(newData.metadata)
|
|
223
|
+
: JSON.stringify(newData.metadata)
|
|
187
224
|
: null;
|
|
188
225
|
const dataKey = JSON.stringify({
|
|
189
226
|
translationProvider: newData.translationProvider,
|
|
190
227
|
targetLanguages: [...newData.targetLanguages].sort(),
|
|
191
228
|
includeSubitems: newData.includeSubitems,
|
|
192
|
-
|
|
229
|
+
discoveredItemIds: (newData.discoveredItems || [])
|
|
230
|
+
.map((item) => item?.descriptor?.id || item?.id)
|
|
231
|
+
.filter(Boolean)
|
|
232
|
+
.sort(),
|
|
193
233
|
itemsCount: newData.items?.length || 0,
|
|
194
234
|
serviceCustomData: serviceCustomDataKey,
|
|
195
235
|
metadata: metadataKey,
|
|
236
|
+
// batchName must be part of the key — otherwise the PromptCustomizationStep's
|
|
237
|
+
// setData({...prev, batchName}) call sees an "unchanged" key here and the
|
|
238
|
+
// update is silently dropped, so the user-entered name never reaches submit.
|
|
239
|
+
batchName: newData.batchName ?? "",
|
|
240
|
+
// subitemCounts must be part of the key — otherwise live count
|
|
241
|
+
// updates from the subitem-count stream are silently dropped and
|
|
242
|
+
// the Start Translation button can't reflect them.
|
|
243
|
+
subitemCounts: newData.subitemCounts
|
|
244
|
+
? Object.keys(newData.subitemCounts)
|
|
245
|
+
.sort()
|
|
246
|
+
.map((id) => {
|
|
247
|
+
const c = newData.subitemCounts[id];
|
|
248
|
+
if (c === undefined)
|
|
249
|
+
return [id, "missing"];
|
|
250
|
+
if (c === "loading" || c === "error")
|
|
251
|
+
return [id, c];
|
|
252
|
+
return [id, c.count, c.complete];
|
|
253
|
+
})
|
|
254
|
+
: null,
|
|
196
255
|
});
|
|
197
256
|
// Skip if data hasn't actually changed
|
|
198
257
|
if (lastSetWizardDataRef.current === dataKey) {
|
|
@@ -223,18 +282,21 @@ export function LocalizeItemDialog(props) {
|
|
|
223
282
|
}, children: [_jsxs(DialogContent, { className: "flex h-[85vh] max-h-[900px] min-h-0 w-[90vw] max-w-5xl flex-col overflow-hidden md:min-h-[700px]", "data-testid": "translation-wizard-dialog", onPointerDownOutside: (e) => e.preventDefault(), onEscapeKeyDown: (e) => e.preventDefault(), "aria-describedby": "translation-wizard-description", style: {
|
|
224
283
|
width: "min(90vw, 1280px)",
|
|
225
284
|
height: "min(85vh, 900px)",
|
|
226
|
-
}, children: [_jsx(
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
return (_jsxs(Fragment, { children: [_jsxs("div", { className: "flex shrink-0 items-center gap-2", "data-testid": `step-indicator-${step.id}`, "aria-current": isCurrent ? "step" : undefined, children: [_jsx("div", { className: cn("flex h-7 w-7 shrink-0 items-center justify-center rounded-full border text-sm font-medium transition-colors", isCurrent && "border-theme-secondary bg-theme-secondary-light text-theme-secondary", isCompleted && "border-theme-secondary bg-theme-secondary text-white", !isCurrent && !isCompleted && "border-gray-3 bg-background text-gray-2"), "data-testid": `step-indicator-circle-${step.id}`, "aria-label": step.name, children: isCompleted ? "✓" : index + 1 }), _jsx("span", { className: cn("whitespace-nowrap text-sm transition-colors", isCurrent && "font-medium text-theme-secondary", isCompleted && "text-theme-secondary", !isCurrent && !isCompleted && "text-gray-2"), "data-testid": `step-indicator-label-${step.id}`, children: step.name })] }), index < activeSteps.length - 1 && (_jsx("div", { className: cn("mx-3 h-px w-8 shrink-0 transition-colors", currentStepIndex > index ? "bg-theme-secondary" : "bg-gray-3") }))] }, step.id));
|
|
230
|
-
}) }) }) }), _jsxs("div", { className: "flex flex-1 flex-col min-h-0", children: [_jsx("div", { className: "flex-1 overflow-y-auto min-h-0 bg-[var(--color-gray-5)]", "data-testid": "translation-wizard-step-content", children: _jsx("div", { className: "h-full relative", children: activeSteps.map((step, index) => {
|
|
285
|
+
}, children: [_jsx(StyledDialogTitle, { icon: _jsx(GlobeIcon, { strokeWidth: 1.5 }), title: `Translate · ${currentStep?.name ?? ""}`, subtitle: currentStep?.description ||
|
|
286
|
+
"Configure and start translation for your content" }), _jsx("div", { id: "translation-wizard-description", className: "sr-only", children: currentStep?.description ||
|
|
287
|
+
"Configure and start translation for your content." }), _jsxs("div", { className: "flex flex-1 flex-col min-h-0", children: [_jsx("div", { className: "flex-1 overflow-y-auto min-h-0 ", "data-testid": "translation-wizard-step-content", children: _jsx("div", { className: "h-full relative", children: activeSteps.map((step, index) => {
|
|
231
288
|
const StepComponent = step.component;
|
|
232
289
|
const isActive = index === currentStepIndex;
|
|
233
290
|
if (!StepComponent)
|
|
234
291
|
return null;
|
|
235
|
-
return (_jsx("div", { className: "h-full", style: { display: isActive ?
|
|
236
|
-
}) }) }), _jsxs(DialogButtons, { "data-testid": "translation-wizard-dialog-buttons", children: [_jsx(Button, { onClick: () => props.onClose?.(null), variant: "outline", size: "
|
|
292
|
+
return (_jsx("div", { className: "h-full", style: { display: isActive ? "block" : "none" }, "aria-hidden": !isActive, "data-testid": `step-content-${step.id}`, children: _jsx(StepComponent, { stepIndex: index, isActive: isActive, data: wizardData, setData: setWizardDataStable, editContext: editContext, onStepCompleted: (completed) => handleStepCompleted(completed, index), setBeforeNextCallback: isActive ? setBeforeNextCallbackStable : undefined, setFooterActions: isActive ? provideFooterActions : undefined, requestClose: isActive ? requestCloseCb : undefined }) }, step.id));
|
|
293
|
+
}) }) }), _jsxs(DialogButtons, { "data-testid": "translation-wizard-dialog-buttons", children: [_jsx(Button, { onClick: () => props.onClose?.(null), variant: "outline", size: "lg", className: "w-auto min-w-24 flex-none", "data-testid": "translation-wizard-cancel-button", children: "Cancel" }), _jsxs("div", { className: "ml-auto flex min-w-0 flex-wrap items-center justify-end gap-3", children: [currentStepIndex > 0 && (_jsx(Button, { onClick: handlePrevious, variant: "outline", size: "lg", className: "w-auto min-w-32 flex-none", "data-testid": "translation-wizard-previous-button", children: "Previous" })), footerActions.map((a) => (_jsx(Button, { onClick: a.onClick, disabled: !!a.disabled, variant: "default", size: "lg", className: "w-auto min-w-32 flex-none", "data-testid": `translation-wizard-footer-action-${a.key}`, children: a.label }, a.key))), _jsx(Button, { onClick: handleNext, disabled: !canProceed || isSubmitting, variant: "default", size: "lg", className: "w-auto min-w-40 flex-none gap-2", "data-testid": "translation-wizard-next-button", children: isSubmitting ? ("Starting...") : isLastStep ? ((() => {
|
|
294
|
+
const { totalTranslations, isStreaming } = calculateTranslationCounts(wizardData);
|
|
295
|
+
if (totalTranslations <= 0)
|
|
296
|
+
return "Start Translation";
|
|
297
|
+
return `Start Translation (${totalTranslations}${isStreaming ? "+" : ""})`;
|
|
298
|
+
})()) : (_jsxs(_Fragment, { children: [getNextButtonLabel(activeSteps[currentStepIndex + 1]), _jsx(ArrowRightIcon, { className: "h-4 w-4", strokeWidth: 2 })] })) })] })] })] })] }), _jsx(AlertDialog, { open: showLargeBatchWarning, onOpenChange: setShowLargeBatchWarning, children: _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsxs(AlertDialogTitle, { className: "flex items-center gap-2", children: [_jsx(AlertTriangleIcon, { className: "h-5 w-5 text-feedback-orange" }), "Large Translation Batch"] }), _jsx(AlertDialogDescription, { children: (() => {
|
|
237
299
|
const { itemCount, languageCount, totalTranslations } = calculateTranslationCounts(wizardData);
|
|
238
|
-
return (_jsxs(_Fragment, { children: ["You are about to start ", _jsxs("strong", { children: [totalTranslations, " translations"] }), " (", itemCount, " items \u00D7 ", languageCount, " languages). Large batches may take a significant amount of time to process.", _jsx("br", {}), _jsx("br", {}), "Are you sure you want to continue?"] }));
|
|
300
|
+
return (_jsxs(_Fragment, { children: ["You are about to start", " ", _jsxs("strong", { children: [totalTranslations, " translations"] }), " (", itemCount, " items \u00D7 ", languageCount, " languages). Large batches may take a significant amount of time to process.", _jsx("br", {}), _jsx("br", {}), "Are you sure you want to continue?"] }));
|
|
239
301
|
})() })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { disabled: isSubmitting, children: "Cancel" }), _jsx(AlertDialogAction, { onClick: handleLargeBatchConfirm, disabled: isSubmitting, children: isSubmitting ? "Starting..." : "Continue" })] })] }) })] }));
|
|
240
302
|
}
|
|
@@ -2,7 +2,6 @@ import { TranslationStatus } from "./types";
|
|
|
2
2
|
import { FullItem } from "@parhelia/core";
|
|
3
3
|
import { TranslationWizardData } from "./steps/types";
|
|
4
4
|
import { EditContextType } from "@parhelia/core";
|
|
5
|
-
export declare function generateBatchId(): string;
|
|
6
5
|
export type StartedTranslation = {
|
|
7
6
|
itemId: string;
|
|
8
7
|
targetLanguage: string;
|
|
@@ -12,6 +11,6 @@ export type TranslationResult = {
|
|
|
12
11
|
started: StartedTranslation[];
|
|
13
12
|
batchId?: string;
|
|
14
13
|
};
|
|
15
|
-
export declare function performDefaultTranslation(wizardData: TranslationWizardData, editContext: EditContextType
|
|
14
|
+
export declare function performDefaultTranslation(wizardData: TranslationWizardData, editContext: EditContextType): Promise<TranslationResult>;
|
|
16
15
|
export declare const defaultTranslateAll: (languageCodes: string[], translationStatus: TranslationStatus[], sessionId: string, item: FullItem, translationProvider: string) => Promise<TranslationResult>;
|
|
17
16
|
//# sourceMappingURL=LocalizeItemUtils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LocalizeItemUtils.d.ts","sourceRoot":"","sources":["../src/LocalizeItemUtils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"LocalizeItemUtils.d.ts","sourceRoot":"","sources":["../src/LocalizeItemUtils.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAsDjD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAIF,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,qBAAqB,EACjC,WAAW,EAAE,eAAe,GAC3B,OAAO,CAAC,iBAAiB,CAAC,CA0I5B;AAGD,eAAO,MAAM,mBAAmB,GAC9B,eAAe,MAAM,EAAE,EACvB,mBAAmB,iBAAiB,EAAE,EACtC,WAAW,MAAM,EACjB,MAAM,QAAQ,EACd,qBAAqB,MAAM,+BAkC5B,CAAC"}
|
|
@@ -1,15 +1,43 @@
|
|
|
1
|
-
import { requestBatchTranslation } from "./services/translationService";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { requestBatchTranslation, } from "./services/translationService";
|
|
2
|
+
import { discoverItemsTree, flattenSelectableItemsFromBackendTrees, } from "./api/discovery";
|
|
3
|
+
/**
|
|
4
|
+
* Resolve the final list of item IDs to translate, expanding subitems for
|
|
5
|
+
* any selection-tree item whose includeSubitems flag is true.
|
|
6
|
+
*
|
|
7
|
+
* Selection priority:
|
|
8
|
+
* 1. `selectionTreeItems` (new model) - per-item flags drive expansion
|
|
9
|
+
* 2. `discoveredItems` (legacy fallback) - used as-is
|
|
10
|
+
* 3. `items` (initial wizard input) - used as-is
|
|
11
|
+
*/
|
|
12
|
+
async function resolveItemIdsToTranslate(wizardData, sessionId) {
|
|
13
|
+
if (wizardData.selectionTreeItems &&
|
|
14
|
+
wizardData.selectionTreeItems.length > 0) {
|
|
15
|
+
const directIds = [];
|
|
16
|
+
const rootsToExpand = [];
|
|
17
|
+
for (const entry of wizardData.selectionTreeItems) {
|
|
18
|
+
if (entry.includeSubitems) {
|
|
19
|
+
rootsToExpand.push(entry.descriptor.id);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
directIds.push(entry.descriptor.id);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const expandedIds = [];
|
|
26
|
+
if (rootsToExpand.length > 0) {
|
|
27
|
+
const language = wizardData.selectionTreeItems[0]?.descriptor.language;
|
|
28
|
+
const tree = await discoverItemsTree({ rootItemIds: rootsToExpand, language }, sessionId);
|
|
29
|
+
expandedIds.push(...flattenSelectableItemsFromBackendTrees(tree.trees).map((n) => n.id));
|
|
30
|
+
}
|
|
31
|
+
return Array.from(new Set([...directIds, ...expandedIds]));
|
|
32
|
+
}
|
|
33
|
+
const fallback = wizardData.discoveredItems && wizardData.discoveredItems.length > 0
|
|
34
|
+
? wizardData.discoveredItems
|
|
35
|
+
: wizardData.items;
|
|
36
|
+
return fallback.map((item) => item.descriptor.id);
|
|
5
37
|
}
|
|
6
38
|
// Unified translation function that handles both single and batch translations
|
|
7
39
|
// Now always uses batch logic for traceability in recentTranslation view
|
|
8
|
-
export async function performDefaultTranslation(wizardData, editContext
|
|
9
|
-
const batchId = predefinedBatchId || generateBatchId();
|
|
10
|
-
const itemsToTranslate = wizardData.includeSubitems
|
|
11
|
-
? wizardData.discoveredItems
|
|
12
|
-
: wizardData.items;
|
|
40
|
+
export async function performDefaultTranslation(wizardData, editContext) {
|
|
13
41
|
// Build language mappings (source -> target) from the wizard data
|
|
14
42
|
// The source language is consistent for each target language across all items
|
|
15
43
|
const languageMappings = [];
|
|
@@ -24,19 +52,19 @@ export async function performDefaultTranslation(wizardData, editContext, predefi
|
|
|
24
52
|
targetLanguage: language,
|
|
25
53
|
});
|
|
26
54
|
}
|
|
27
|
-
//
|
|
28
|
-
const itemIds =
|
|
55
|
+
// Resolve item IDs, expanding subitems per-item-flag where applicable.
|
|
56
|
+
const itemIds = await resolveItemIdsToTranslate(wizardData, editContext.sessionId);
|
|
29
57
|
// Validate that we have translation requests to process
|
|
30
58
|
if (languageMappings.length === 0 || itemIds.length === 0) {
|
|
31
|
-
const error = new Error(
|
|
32
|
-
error.name =
|
|
59
|
+
const error = new Error("No translations needed. All selected target languages match the source languages of the items.");
|
|
60
|
+
error.name = "NoTranslationsNeededError";
|
|
33
61
|
throw error;
|
|
34
62
|
}
|
|
35
63
|
// Prepare batch metadata including service-specific custom data
|
|
36
64
|
// Start with wizardData.metadata as an object
|
|
37
65
|
let metadataObj = {};
|
|
38
66
|
if (wizardData.metadata) {
|
|
39
|
-
if (typeof wizardData.metadata ===
|
|
67
|
+
if (typeof wizardData.metadata === "string") {
|
|
40
68
|
try {
|
|
41
69
|
metadataObj = JSON.parse(wizardData.metadata);
|
|
42
70
|
}
|
|
@@ -44,19 +72,27 @@ export async function performDefaultTranslation(wizardData, editContext, predefi
|
|
|
44
72
|
// Invalid JSON, ignore
|
|
45
73
|
}
|
|
46
74
|
}
|
|
47
|
-
else if (typeof wizardData.metadata ===
|
|
75
|
+
else if (typeof wizardData.metadata === "object") {
|
|
48
76
|
metadataObj = { ...wizardData.metadata };
|
|
49
77
|
}
|
|
50
78
|
}
|
|
51
|
-
//
|
|
79
|
+
// Embed the user/AI-provided batch name so it surfaces in Recent
|
|
80
|
+
// Translations and the batch detail view.
|
|
81
|
+
const trimmedName = wizardData.batchName?.trim();
|
|
82
|
+
if (trimmedName) {
|
|
83
|
+
metadataObj.name = trimmedName;
|
|
84
|
+
}
|
|
85
|
+
// Merge service-specific custom data (e.g., custom prompts for AI providers)
|
|
52
86
|
if (wizardData.serviceCustomData && wizardData.serviceCustomData.size > 0) {
|
|
53
87
|
const serviceData = wizardData.serviceCustomData.get(wizardData.translationProvider);
|
|
54
88
|
if (serviceData && serviceData.enableCustomPrompt) {
|
|
55
|
-
const provider = wizardData.translationProviders.find(p => p.name === wizardData.translationProvider);
|
|
89
|
+
const provider = wizardData.translationProviders.find((p) => p.name === wizardData.translationProvider);
|
|
56
90
|
const defaultPrompt = provider?.defaultPrompt && provider.defaultPrompt.trim()
|
|
57
91
|
? provider.defaultPrompt
|
|
58
92
|
: null;
|
|
59
|
-
const customizationType = serviceData.promptCustomizationType === "replace"
|
|
93
|
+
const customizationType = serviceData.promptCustomizationType === "replace"
|
|
94
|
+
? "replace"
|
|
95
|
+
: "extend";
|
|
60
96
|
const rawCustomPrompt = (serviceData.customPrompt || "").trim();
|
|
61
97
|
let finalCustomPrompt = "";
|
|
62
98
|
if (rawCustomPrompt) {
|
|
@@ -70,34 +106,37 @@ export async function performDefaultTranslation(wizardData, editContext, predefi
|
|
|
70
106
|
metadataObj.serviceCustomData = {
|
|
71
107
|
[wizardData.translationProvider]: {
|
|
72
108
|
enableCustomPrompt: serviceData.enableCustomPrompt,
|
|
73
|
-
customPrompt: finalCustomPrompt
|
|
74
|
-
}
|
|
109
|
+
customPrompt: finalCustomPrompt,
|
|
110
|
+
},
|
|
75
111
|
};
|
|
76
112
|
}
|
|
77
113
|
}
|
|
78
114
|
// Serialize metadata to JSON string (or undefined if empty)
|
|
79
|
-
const batchMetadata = Object.keys(metadataObj).length > 0
|
|
115
|
+
const batchMetadata = Object.keys(metadataObj).length > 0
|
|
116
|
+
? JSON.stringify(metadataObj)
|
|
117
|
+
: undefined;
|
|
80
118
|
const batchResult = await requestBatchTranslation({
|
|
81
119
|
sessionId: editContext.sessionId,
|
|
82
|
-
batchId,
|
|
83
120
|
provider: wizardData.translationProvider,
|
|
84
121
|
batchMetadata,
|
|
85
122
|
languageMappings,
|
|
86
123
|
itemIds,
|
|
87
124
|
});
|
|
88
125
|
if (batchResult.type === "error") {
|
|
89
|
-
console.error(
|
|
126
|
+
console.error("Translation request failed:", batchResult);
|
|
90
127
|
// Throw an error so the caller can handle it (e.g., show a toast)
|
|
91
|
-
const errorMessage = batchResult.details ||
|
|
128
|
+
const errorMessage = batchResult.details ||
|
|
129
|
+
batchResult.summary ||
|
|
130
|
+
"Translation request failed";
|
|
92
131
|
const error = new Error(errorMessage);
|
|
93
|
-
error.name =
|
|
132
|
+
error.name = "TranslationRequestError";
|
|
94
133
|
throw error;
|
|
95
134
|
}
|
|
96
135
|
const batchResponse = batchResult.data;
|
|
97
136
|
if (!batchResponse) {
|
|
98
|
-
console.error(
|
|
99
|
-
const error = new Error(
|
|
100
|
-
error.name =
|
|
137
|
+
console.error("Batch response is undefined");
|
|
138
|
+
const error = new Error("Server returned an empty response");
|
|
139
|
+
error.name = "TranslationRequestError";
|
|
101
140
|
throw error;
|
|
102
141
|
}
|
|
103
142
|
const started = batchResponse.started?.map((result) => ({
|
|
@@ -106,9 +145,9 @@ export async function performDefaultTranslation(wizardData, editContext, predefi
|
|
|
106
145
|
jobId: result.jobId,
|
|
107
146
|
})) || [];
|
|
108
147
|
if (batchResponse.skipped && batchResponse.skipped.length > 0) {
|
|
109
|
-
console.warn(
|
|
148
|
+
console.warn("Some translations were skipped:", batchResponse.skipped);
|
|
110
149
|
}
|
|
111
|
-
return { started, batchId };
|
|
150
|
+
return { started, batchId: batchResponse.id };
|
|
112
151
|
}
|
|
113
152
|
// Legacy function for backward compatibility
|
|
114
153
|
export const defaultTranslateAll = async (languageCodes, translationStatus, sessionId, item, translationProvider) => {
|
|
@@ -116,21 +155,24 @@ export const defaultTranslateAll = async (languageCodes, translationStatus, sess
|
|
|
116
155
|
const wizardData = {
|
|
117
156
|
items: [item],
|
|
118
157
|
targetLanguages: languageCodes,
|
|
119
|
-
languageData: new Map(languageCodes.map(lang => {
|
|
120
|
-
const status = translationStatus?.find(x => x.targetLanguage === lang);
|
|
121
|
-
return [
|
|
158
|
+
languageData: new Map(languageCodes.map((lang) => {
|
|
159
|
+
const status = translationStatus?.find((x) => x.targetLanguage === lang);
|
|
160
|
+
return [
|
|
161
|
+
lang,
|
|
162
|
+
{
|
|
122
163
|
name: lang,
|
|
123
164
|
languageCode: lang,
|
|
124
165
|
items: [item.descriptor],
|
|
125
|
-
translationStatus: status
|
|
126
|
-
}
|
|
166
|
+
translationStatus: status,
|
|
167
|
+
},
|
|
168
|
+
];
|
|
127
169
|
})),
|
|
128
170
|
translationProvider,
|
|
129
171
|
includeSubitems: false,
|
|
130
172
|
discoveredItems: [],
|
|
131
173
|
itemMetadata: new Map(),
|
|
132
174
|
metadata: null,
|
|
133
|
-
translationProviders: []
|
|
175
|
+
translationProviders: [],
|
|
134
176
|
};
|
|
135
177
|
const editContext = { sessionId };
|
|
136
178
|
const result = await performDefaultTranslation(wizardData, editContext);
|
package/dist/api/discovery.d.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
export declare function suggestBatchName(req: {
|
|
2
|
+
itemIds: string[];
|
|
3
|
+
targetLanguages: string[];
|
|
4
|
+
includeSubitems?: boolean;
|
|
5
|
+
}, sessionId?: string): Promise<string | null>;
|
|
1
6
|
export type DiscoveredItem = {
|
|
2
7
|
id: string;
|
|
3
8
|
name: string;
|
|
@@ -31,4 +36,24 @@ export type DiscoverItemsTreeResponse = {
|
|
|
31
36
|
export declare function discoverItemsTree(req: DiscoverItemsTreeRequest, sessionId?: string): Promise<DiscoverItemsTreeResponse>;
|
|
32
37
|
export declare function convertBackendTreeToTreeNodes(trees: BackendTreeNode[]): TreeNode[];
|
|
33
38
|
export declare function flattenSelectableItemsFromBackendTrees(trees: BackendTreeNode[]): DiscoveredItem[];
|
|
39
|
+
export type SubitemCountUpdate = {
|
|
40
|
+
count: number;
|
|
41
|
+
complete: boolean;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Streams the running subitem count for a given root item from the
|
|
45
|
+
* backend. The endpoint returns newline-delimited JSON; each parsed line
|
|
46
|
+
* triggers `onProgress` so the UI can show the count climbing. Filtered
|
|
47
|
+
* server-side via IItemExportFilter + excluded templates.
|
|
48
|
+
*
|
|
49
|
+
* Pass an `AbortSignal` to cancel mid-stream (e.g. user toggles the
|
|
50
|
+
* subitems flag off again).
|
|
51
|
+
*/
|
|
52
|
+
export declare function streamSubitemCount(req: {
|
|
53
|
+
itemId: string;
|
|
54
|
+
language?: string;
|
|
55
|
+
}, onProgress: (update: SubitemCountUpdate) => void, options?: {
|
|
56
|
+
sessionId?: string;
|
|
57
|
+
signal?: AbortSignal;
|
|
58
|
+
}): Promise<number>;
|
|
34
59
|
//# sourceMappingURL=discovery.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/api/discovery.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;
|
|
1
|
+
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/api/discovery.ts"],"names":[],"mappings":"AAEA,wBAAsB,gBAAgB,CACpC,GAAG,EAAE;IACH,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,EACD,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAaxB;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,cAAc,CAAC;IACrB,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;CACvB,CAAC;AAIF,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,KAAK,EAAE,eAAe,EAAE,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,wBAAwB,EAC7B,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,yBAAyB,CAAC,CAYpC;AAED,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,eAAe,EAAE,GACvB,QAAQ,EAAE,CAgBZ;AAED,wBAAgB,sCAAsC,CACpD,KAAK,EAAE,eAAe,EAAE,GACvB,cAAc,EAAE,CAclB;AAED,MAAM,MAAM,kBAAkB,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC;AAEtE;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,EAC1C,UAAU,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,EAChD,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAAE,GACrD,OAAO,CAAC,MAAM,CAAC,CAsEjB"}
|