@braze/sanity-plugin-ai-translation 0.2.79 → 0.2.80
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +90 -40
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getPublishedId, pathToString, useClient, useValidationStatus, defineType, defineField, definePlugin } from "sanity";
|
|
2
2
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { WarningOutlineIcon, ErrorOutlineIcon, CheckmarkIcon, CloseIcon,
|
|
3
|
+
import { WarningOutlineIcon, ErrorOutlineIcon, CheckmarkIcon, CloseIcon, SyncIcon, PanelRightIcon, SearchIcon, CircleIcon, ArrowRightIcon, ResetIcon, TranslateIcon } from "@sanity/icons";
|
|
4
4
|
import { createContext, useReducer, useRef, useEffect, useContext, useMemo, useState, useCallback } from "react";
|
|
5
5
|
import defaults from "lodash.defaults";
|
|
6
6
|
import { Card, Stack, Flex, Text, Box, Heading, Button, Spinner, Badge, Inline, Radio, Checkbox, Grid, TextInput, Select, Label, Code, Tooltip } from "@sanity/ui";
|
|
@@ -385,32 +385,63 @@ const isLoggingEnabled = () => process.env.NEXT_PUBLIC_SANITY_STUDIO_AI_TRANSLAT
|
|
|
385
385
|
return devLog.debug("Source references with unpublished changes", {
|
|
386
386
|
count: results.length
|
|
387
387
|
}), results;
|
|
388
|
-
}, getExistingTranslationId = (translationMetadata, targetLanguage) => translationMetadata?.translations?.length && translationMetadata.translations.find(
|
|
388
|
+
}, TRANSLATION_METADATA_TYPE = "translation.metadata", getExistingTranslationId = (translationMetadata, targetLanguage) => translationMetadata?.translations?.length && translationMetadata.translations.find(
|
|
389
389
|
(translation) => translation._key === targetLanguage
|
|
390
390
|
)?.value._ref || null, checkTargetDrafts = async ({
|
|
391
391
|
client,
|
|
392
392
|
translationMetadata,
|
|
393
393
|
selectedTargetLanguages,
|
|
394
|
-
sourceDocumentId
|
|
394
|
+
sourceDocumentId,
|
|
395
|
+
references
|
|
395
396
|
}) => {
|
|
396
|
-
if (!translationMetadata?.translations?.length)
|
|
397
|
-
return devLog.debug("No translation metadata \u2014 skipping draft check", {
|
|
398
|
-
sourceDocumentId
|
|
399
|
-
}), [];
|
|
400
397
|
const targetEntries = [];
|
|
401
|
-
|
|
402
|
-
const
|
|
403
|
-
|
|
398
|
+
if (translationMetadata?.translations?.length)
|
|
399
|
+
for (const lang of selectedTargetLanguages) {
|
|
400
|
+
const targetId = getExistingTranslationId(translationMetadata, lang);
|
|
401
|
+
targetId && targetEntries.push({ targetId, targetLanguage: lang, sourceDocumentId, isReference: !1 });
|
|
402
|
+
}
|
|
403
|
+
else
|
|
404
|
+
devLog.debug("No translation metadata \u2014 skipping main document draft check", {
|
|
405
|
+
sourceDocumentId
|
|
406
|
+
});
|
|
407
|
+
if (references && references.length > 0) {
|
|
408
|
+
const refIds = references.map((r) => r._id), refMetadataDocs = await client.fetch(
|
|
409
|
+
"*[_type == $metadataType && array::intersects(translations[].value._ref, $refIds)] { translations }",
|
|
410
|
+
{ metadataType: TRANSLATION_METADATA_TYPE, refIds }
|
|
411
|
+
);
|
|
412
|
+
devLog.debug("Fetched reference metadata for draft check", {
|
|
413
|
+
refCount: refIds.length,
|
|
414
|
+
metadataDocsFound: refMetadataDocs.length
|
|
415
|
+
});
|
|
416
|
+
const refIdSet = new Set(refIds);
|
|
417
|
+
for (const metadataDoc of refMetadataDocs) {
|
|
418
|
+
if (!metadataDoc.translations?.length) continue;
|
|
419
|
+
const matchingRefId = metadataDoc.translations.find(
|
|
420
|
+
(t) => t.value?._ref && refIdSet.has(t.value._ref)
|
|
421
|
+
)?.value._ref;
|
|
422
|
+
if (matchingRefId)
|
|
423
|
+
for (const lang of selectedTargetLanguages) {
|
|
424
|
+
const targetId = getExistingTranslationId(metadataDoc, lang);
|
|
425
|
+
targetId && targetEntries.push({
|
|
426
|
+
targetId,
|
|
427
|
+
targetLanguage: lang,
|
|
428
|
+
sourceDocumentId: matchingRefId,
|
|
429
|
+
isReference: !0
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
}
|
|
404
433
|
}
|
|
405
|
-
|
|
434
|
+
const seen = /* @__PURE__ */ new Set(), deduped = targetEntries.filter((e) => seen.has(e.targetId) ? !1 : (seen.add(e.targetId), !0));
|
|
435
|
+
if (deduped.length === 0)
|
|
406
436
|
return devLog.debug("No existing translations found for selected languages", {
|
|
407
437
|
sourceDocumentId,
|
|
408
438
|
selectedTargetLanguages
|
|
409
439
|
}), [];
|
|
410
|
-
const draftIds =
|
|
440
|
+
const draftIds = deduped.map((e) => `drafts.${e.targetId}`);
|
|
411
441
|
devLog.debug("Checking for stale drafts on target documents", {
|
|
412
442
|
sourceDocumentId,
|
|
413
|
-
draftIdsToCheck: draftIds.length
|
|
443
|
+
draftIdsToCheck: draftIds.length,
|
|
444
|
+
referenceTargets: deduped.filter((e) => e.isReference).length
|
|
414
445
|
});
|
|
415
446
|
const drafts = await client.fetch(
|
|
416
447
|
"*[_id in $draftIds]{ _id, _type, title, name }",
|
|
@@ -419,23 +450,25 @@ const isLoggingEnabled = () => process.env.NEXT_PUBLIC_SANITY_STUDIO_AI_TRANSLAT
|
|
|
419
450
|
if (drafts.length === 0)
|
|
420
451
|
return devLog.debug("No stale drafts found", { sourceDocumentId }), [];
|
|
421
452
|
const draftMap = new Map(drafts.map((d) => [d._id, d])), results = [];
|
|
422
|
-
for (const entry of
|
|
453
|
+
for (const entry of deduped) {
|
|
423
454
|
const draftId = `drafts.${entry.targetId}`, draft = draftMap.get(draftId);
|
|
424
455
|
draft && results.push({
|
|
425
456
|
targetId: entry.targetId,
|
|
426
457
|
draftId,
|
|
427
458
|
_type: draft._type,
|
|
428
459
|
title: draft.title || draft.name,
|
|
429
|
-
sourceDocumentId,
|
|
430
|
-
targetLanguage: entry.targetLanguage
|
|
460
|
+
sourceDocumentId: entry.sourceDocumentId,
|
|
461
|
+
targetLanguage: entry.targetLanguage,
|
|
462
|
+
isReference: entry.isReference || void 0
|
|
431
463
|
});
|
|
432
464
|
}
|
|
433
465
|
return devLog.info("Stale drafts detected on target documents", {
|
|
434
466
|
sourceDocumentId,
|
|
435
467
|
staleDraftCount: results.length,
|
|
468
|
+
referenceDraftCount: results.filter((r) => r.isReference).length,
|
|
436
469
|
affectedLanguages: results.map((r) => r.targetLanguage)
|
|
437
470
|
}), results;
|
|
438
|
-
},
|
|
471
|
+
}, getTranslationMetadata = async ({
|
|
439
472
|
client,
|
|
440
473
|
sourceDocument,
|
|
441
474
|
sourceLanguage
|
|
@@ -3379,15 +3412,16 @@ ${protectedPhrases.join(", ")}`, buildStyleGuideSection = (globalPrompt, localeP
|
|
|
3379
3412
|
}
|
|
3380
3413
|
);
|
|
3381
3414
|
}, VALIDATION_TIMEOUT_MS = 2e3, DocumentValidator = ({ documentId, documentType, onResult }) => {
|
|
3382
|
-
const publishedId = getPublishedId(documentId), { isValidating, validation } = useValidationStatus(publishedId, documentType), hasReceivedRealResult = useRef(!1), [timedOut, setTimedOut] = useState(!1);
|
|
3415
|
+
const publishedId = getPublishedId(documentId), { isValidating, validation } = useValidationStatus(publishedId, documentType), hasReceivedRealResult = useRef(!1), hasSettled = useRef(!1), [timedOut, setTimedOut] = useState(!1);
|
|
3383
3416
|
return useEffect(() => {
|
|
3384
3417
|
const timer = setTimeout(() => setTimedOut(!0), VALIDATION_TIMEOUT_MS);
|
|
3385
3418
|
return () => clearTimeout(timer);
|
|
3386
3419
|
}, []), useEffect(() => {
|
|
3420
|
+
if (hasSettled.current) return;
|
|
3387
3421
|
(isValidating || validation.length > 0) && (hasReceivedRealResult.current = !0);
|
|
3388
|
-
const stillWaitingForFirstResult = !hasReceivedRealResult.current && !timedOut, errors = validation.filter((v) => v.level === "error");
|
|
3389
|
-
onResult(documentId, {
|
|
3390
|
-
isValidating:
|
|
3422
|
+
const stillWaitingForFirstResult = !hasReceivedRealResult.current && !timedOut, errors = validation.filter((v) => v.level === "error"), computedIsValidating = isValidating || stillWaitingForFirstResult;
|
|
3423
|
+
!computedIsValidating && hasReceivedRealResult.current && (hasSettled.current = !0), onResult(documentId, {
|
|
3424
|
+
isValidating: computedIsValidating,
|
|
3391
3425
|
errors
|
|
3392
3426
|
});
|
|
3393
3427
|
}, [isValidating, validation, documentId, onResult, timedOut]), null;
|
|
@@ -3404,7 +3438,7 @@ ${protectedPhrases.join(", ")}`, buildStyleGuideSection = (globalPrompt, localeP
|
|
|
3404
3438
|
translationMode,
|
|
3405
3439
|
releaseConfig,
|
|
3406
3440
|
documentSource
|
|
3407
|
-
} = useTranslationContext(), client = useClient({ apiVersion: "vX" }), [validationResults, setValidationResults] = useState(/* @__PURE__ */ new Map()), [sourceRefsWithDrafts, setSourceRefsWithDrafts] = useState([]), [isSourceDraftCheckLoading, setIsSourceDraftCheckLoading] = useState(!0), [staleDrafts, setStaleDrafts] = useState([]), [isDraftCheckLoading, setIsDraftCheckLoading] = useState(!0), [draftAction, setDraftAction] = useState("none"), [isDraftActionInProgress, setIsDraftActionInProgress] = useState(!1), [conflictContext, setConflictContext] = useState(null), [isCheckingConflicts, setIsCheckingConflicts] = useState(!0), filteredReferences = references.filter((ref) => selectedReferenceIds.has(ref._id)), documentsToValidate = useMemo(() => {
|
|
3441
|
+
} = useTranslationContext(), client = useClient({ apiVersion: "vX" }), [scanKey, setScanKey] = useState(0), [validationResults, setValidationResults] = useState(/* @__PURE__ */ new Map()), [sourceRefsWithDrafts, setSourceRefsWithDrafts] = useState([]), [isSourceDraftCheckLoading, setIsSourceDraftCheckLoading] = useState(!0), [staleDrafts, setStaleDrafts] = useState([]), [isDraftCheckLoading, setIsDraftCheckLoading] = useState(!0), [draftAction, setDraftAction] = useState("none"), [isDraftActionInProgress, setIsDraftActionInProgress] = useState(!1), [conflictContext, setConflictContext] = useState(null), [isCheckingConflicts, setIsCheckingConflicts] = useState(!0), filteredReferences = references.filter((ref) => selectedReferenceIds.has(ref._id)), documentsToValidate = useMemo(() => {
|
|
3408
3442
|
const docs = [
|
|
3409
3443
|
{
|
|
3410
3444
|
_id: document._id,
|
|
@@ -3460,7 +3494,8 @@ ${protectedPhrases.join(", ")}`, buildStyleGuideSection = (globalPrompt, localeP
|
|
|
3460
3494
|
client,
|
|
3461
3495
|
translationMetadata,
|
|
3462
3496
|
selectedTargetLanguages,
|
|
3463
|
-
sourceDocumentId: document._id
|
|
3497
|
+
sourceDocumentId: document._id,
|
|
3498
|
+
references: shouldTranslateReferences ? filteredReferences : void 0
|
|
3464
3499
|
});
|
|
3465
3500
|
setStaleDrafts(drafts), drafts.length === 0 && setDraftAction("none");
|
|
3466
3501
|
} catch (error) {
|
|
@@ -3471,7 +3506,7 @@ ${protectedPhrases.join(", ")}`, buildStyleGuideSection = (globalPrompt, localeP
|
|
|
3471
3506
|
} finally {
|
|
3472
3507
|
setIsDraftCheckLoading(!1);
|
|
3473
3508
|
}
|
|
3474
|
-
}, [client, translationMetadata, selectedTargetLanguages, document._id]), runConflictCheck = useCallback(async () => {
|
|
3509
|
+
}, [client, translationMetadata, selectedTargetLanguages, document._id, shouldTranslateReferences, filteredReferences]), runConflictCheck = useCallback(async () => {
|
|
3475
3510
|
if (releaseConfig.mode === "new") {
|
|
3476
3511
|
setIsCheckingConflicts(!1), setConflictContext(null);
|
|
3477
3512
|
return;
|
|
@@ -3488,10 +3523,10 @@ ${protectedPhrases.join(", ")}`, buildStyleGuideSection = (globalPrompt, localeP
|
|
|
3488
3523
|
});
|
|
3489
3524
|
foundConflicts.length > 0 ? setConflictContext({ releaseId: checkedReleaseId, conflicts: foundConflicts }) : setConflictContext(null), setIsCheckingConflicts(!1);
|
|
3490
3525
|
}
|
|
3491
|
-
}, [releaseConfig, client, document, selectedTargetLanguages, config.languageFieldName, filteredReferences])
|
|
3526
|
+
}, [releaseConfig, client, document, selectedTargetLanguages, config.languageFieldName, filteredReferences]);
|
|
3492
3527
|
useEffect(() => {
|
|
3493
|
-
|
|
3494
|
-
}, [
|
|
3528
|
+
runSourceDraftCheck(), runDraftCheck(), runConflictCheck();
|
|
3529
|
+
}, [scanKey]);
|
|
3495
3530
|
const handleDiscardDrafts = useCallback(async () => {
|
|
3496
3531
|
setIsDraftActionInProgress(!0);
|
|
3497
3532
|
try {
|
|
@@ -3584,7 +3619,9 @@ ${protectedPhrases.join(", ")}`, buildStyleGuideSection = (globalPrompt, localeP
|
|
|
3584
3619
|
conflictContext || startTranslation(!1);
|
|
3585
3620
|
}, [conflictContext, startTranslation]), handleBack = useCallback(() => {
|
|
3586
3621
|
dispatch({ type: "SET_OVERALL_STATUS", payload: "idle" });
|
|
3587
|
-
}, [dispatch]),
|
|
3622
|
+
}, [dispatch]), handleRescan = useCallback(() => {
|
|
3623
|
+
setValidationResults(/* @__PURE__ */ new Map()), setSourceRefsWithDrafts([]), setIsSourceDraftCheckLoading(!0), setStaleDrafts([]), setIsDraftCheckLoading(!0), setDraftAction("none"), setConflictContext(null), setIsCheckingConflicts(!0), setScanKey((k) => k + 1);
|
|
3624
|
+
}, []), sourceRefDraftIds = useMemo(
|
|
3588
3625
|
() => new Set(sourceRefsWithDrafts.map((d) => d.publishedId)),
|
|
3589
3626
|
[sourceRefsWithDrafts]
|
|
3590
3627
|
), isLoading = someStillValidating || isSourceDraftCheckLoading || isDraftCheckLoading || isCheckingConflicts, hasStaleDrafts = staleDrafts.length > 0, draftsDismissed = draftAction === "continue", canStartTranslation = !isLoading && !hasValidationErrors && !conflictContext && (!hasStaleDrafts || draftsDismissed), handleCancelConflict = useCallback(() => {
|
|
@@ -3611,7 +3648,7 @@ ${protectedPhrases.join(", ")}`, buildStyleGuideSection = (globalPrompt, localeP
|
|
|
3611
3648
|
documentType: doc._type,
|
|
3612
3649
|
onResult: handleValidationResult
|
|
3613
3650
|
},
|
|
3614
|
-
doc._id
|
|
3651
|
+
`${doc._id}-${scanKey}`
|
|
3615
3652
|
)),
|
|
3616
3653
|
/* @__PURE__ */ jsx(Text, { weight: "semibold", size: 2, children: "Pre-flight Checks" }),
|
|
3617
3654
|
/* @__PURE__ */ jsxs(Text, { size: 1, muted: !0, children: [
|
|
@@ -3687,7 +3724,8 @@ ${protectedPhrases.join(", ")}`, buildStyleGuideSection = (globalPrompt, localeP
|
|
|
3687
3724
|
/* @__PURE__ */ jsx(Card, { padding: 3, border: !0, radius: 2, children: /* @__PURE__ */ jsx(Box, { style: { maxHeight: "300px", overflowY: "auto" }, children: /* @__PURE__ */ jsx(Stack, { space: 3, children: staleDrafts.map((draft) => /* @__PURE__ */ jsxs(Flex, { align: "center", justify: "space-between", gap: 2, children: [
|
|
3688
3725
|
/* @__PURE__ */ jsxs(Flex, { align: "center", gap: 2, flex: 1, style: { minWidth: 0 }, children: [
|
|
3689
3726
|
/* @__PURE__ */ jsx(Text, { size: 1, children: draft.title || draft.targetId }),
|
|
3690
|
-
/* @__PURE__ */ jsx(Badge, { tone: "primary", fontSize: 0, children: draft.targetLanguage })
|
|
3727
|
+
/* @__PURE__ */ jsx(Badge, { tone: "primary", fontSize: 0, children: draft.targetLanguage }),
|
|
3728
|
+
draft.isReference && /* @__PURE__ */ jsx(Badge, { fontSize: 0, children: "reference" })
|
|
3691
3729
|
] }),
|
|
3692
3730
|
/* @__PURE__ */ jsx(DocumentOpenerButton, { documentId: draft.targetId, documentType: draft._type })
|
|
3693
3731
|
] }, draft.draftId)) }) }) }),
|
|
@@ -3731,16 +3769,28 @@ ${protectedPhrases.join(", ")}`, buildStyleGuideSection = (globalPrompt, localeP
|
|
|
3731
3769
|
] }) }),
|
|
3732
3770
|
/* @__PURE__ */ jsxs(Flex, { justify: "space-between", gap: 2, children: [
|
|
3733
3771
|
/* @__PURE__ */ jsx(Button, { mode: "ghost", text: "Back", onClick: handleBack }),
|
|
3734
|
-
/* @__PURE__ */
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3772
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
|
3773
|
+
/* @__PURE__ */ jsx(
|
|
3774
|
+
Button,
|
|
3775
|
+
{
|
|
3776
|
+
mode: "ghost",
|
|
3777
|
+
text: "Rescan",
|
|
3778
|
+
icon: SyncIcon,
|
|
3779
|
+
onClick: handleRescan,
|
|
3780
|
+
disabled: isLoading
|
|
3781
|
+
}
|
|
3782
|
+
),
|
|
3783
|
+
/* @__PURE__ */ jsx(
|
|
3784
|
+
Button,
|
|
3785
|
+
{
|
|
3786
|
+
mode: "ghost",
|
|
3787
|
+
tone: "positive",
|
|
3788
|
+
text: isLoading ? "Checking\u2026" : "Start Translation",
|
|
3789
|
+
onClick: handleStartTranslation,
|
|
3790
|
+
disabled: !canStartTranslation
|
|
3791
|
+
}
|
|
3792
|
+
)
|
|
3793
|
+
] })
|
|
3744
3794
|
] })
|
|
3745
3795
|
] });
|
|
3746
3796
|
}, ActionButtonBar = ({ setIsDialogOpen }) => {
|