gt-sanity 3.1.7-iris.0 → 4.0.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/dist/index.js +149 -93
- package/dist/index.js.map +1 -1
- package/package.json +20 -15
- package/src/actions/translateAction.tsx +1 -1
- package/src/components/TranslateButton.tsx +1 -1
- package/src/components/TranslationsProvider.tsx +74 -35
- package/src/components/page/DebugInfoDialog.tsx +4 -3
- package/src/components/page/ImportAllDialog.tsx +1 -1
- package/src/components/page/ImportMissingDialog.tsx +1 -1
- package/src/components/page/SaveLocalTranslationsDialog.tsx +2 -2
- package/src/components/page/TranslateAllDialog.tsx +3 -3
- package/src/components/page/TranslationsTable.tsx +4 -2
- package/src/components/page/TranslationsTool.tsx +25 -17
- package/src/components/page/UploadExistingDialog.tsx +1 -1
- package/src/components/shared/BaseTranslationWrapper.tsx +2 -9
- package/src/components/shared/LanguageStatus.tsx +28 -11
- package/src/components/shared/SingleDocumentView.tsx +3 -3
- package/src/components/tab/TranslationView.tsx +17 -25
- package/src/hooks/useClient.ts +2 -1
- package/src/sanity-api/__tests__/publishDocuments.test.ts +172 -0
- package/src/sanity-api/publishDocuments.ts +36 -0
- package/src/structure/localizedStructure.ts +3 -0
- package/src/utils/__tests__/importUtils.test.ts +84 -0
- package/src/utils/importUtils.ts +28 -1
- package/src/utils/shared.ts +7 -0
- package/dist/index.cjs +0 -4206
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -499
package/dist/index.js
CHANGED
|
@@ -4,8 +4,9 @@ import { useClient as useClient$1, useSchema, Preview, definePlugin } from "sani
|
|
|
4
4
|
import { useIntentLink, Link, route } from "sanity/router";
|
|
5
5
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
6
6
|
import React, { useState, useEffect, createContext, useRef, useCallback, useContext, useMemo } from "react";
|
|
7
|
-
import {
|
|
8
|
-
import { ThemeProvider,
|
|
7
|
+
import { TranslateIcon } from "@sanity/icons/Translate";
|
|
8
|
+
import { ThemeProvider, Box, Flex, Spinner, Card, Text, Dialog, Stack, Button, Badge, Grid, Checkbox, Switch, Container, Heading } from "@sanity/ui";
|
|
9
|
+
import { ToastProvider, useToast } from "@sanity/ui/toast";
|
|
9
10
|
import { buildTheme } from "@sanity/ui/theme";
|
|
10
11
|
import { extractWithPath, arrayToJSONMatchPath } from "@sanity/mutator";
|
|
11
12
|
import { JSONPath } from "jsonpath-plus";
|
|
@@ -14,11 +15,20 @@ import { htmlToBlocks } from "@portabletext/block-tools";
|
|
|
14
15
|
import { Schema } from "@sanity/schema";
|
|
15
16
|
import { toHTML } from "@portabletext/to-html";
|
|
16
17
|
import merge from "lodash.merge";
|
|
18
|
+
import { Tooltip } from "@sanity/ui/tooltip";
|
|
19
|
+
import { Code } from "@sanity/ui/code";
|
|
20
|
+
import { ClipboardIcon } from "@sanity/icons/Clipboard";
|
|
21
|
+
import { CheckmarkCircleIcon } from "@sanity/icons/CheckmarkCircle";
|
|
22
|
+
import { DownloadIcon } from "@sanity/icons/Download";
|
|
23
|
+
import { LinkIcon } from "@sanity/icons/Link";
|
|
24
|
+
import { PublishIcon } from "@sanity/icons/Publish";
|
|
25
|
+
import { RefreshIcon } from "@sanity/icons/Refresh";
|
|
26
|
+
import { UploadIcon } from "@sanity/icons/Upload";
|
|
17
27
|
import { internationalizedArray } from "sanity-plugin-internationalized-array";
|
|
18
28
|
import { internationalizedArray as internationalizedArray2, internationalizedArrayLanguageFilter, isInternationalizedArrayItemType } from "sanity-plugin-internationalized-array";
|
|
19
29
|
import { documentInternationalization } from "@sanity/document-internationalization";
|
|
20
30
|
import { DocumentInternationalizationMenu, documentInternationalization as documentInternationalization2, useDeleteTranslationAction, useDocumentInternationalizationContext, useDuplicateWithTranslationsAction } from "@sanity/document-internationalization";
|
|
21
|
-
const SECRETS_NAMESPACE = "generaltranslation.secrets", gt = new GT(), DEFAULT_TRANSLATION_PREFERENCES = {
|
|
31
|
+
const SECRETS_NAMESPACE = "generaltranslation.secrets", SANITY_API_VERSION = "2025-09-15", gt = new GT(), DEFAULT_TRANSLATION_PREFERENCES = {
|
|
22
32
|
autoRefresh: !0,
|
|
23
33
|
autoImport: !0,
|
|
24
34
|
autoPatchReferences: !1,
|
|
@@ -156,7 +166,7 @@ function formatLocalePropertiesLabel(code, properties, mapping) {
|
|
|
156
166
|
);
|
|
157
167
|
return verbatim ? name : [emoji, `${name} (${code})`].filter(Boolean).join(" ");
|
|
158
168
|
}
|
|
159
|
-
const useClient = () => useClient$1({ apiVersion:
|
|
169
|
+
const useClient = () => useClient$1({ apiVersion: SANITY_API_VERSION });
|
|
160
170
|
function useSecrets(id) {
|
|
161
171
|
const [loading, setLoading] = useState(!0), [secrets, setSecrets] = useState(null), client = useClient();
|
|
162
172
|
return useEffect(() => {
|
|
@@ -1745,10 +1755,11 @@ async function processImportBatch(items, options = {}) {
|
|
|
1745
1755
|
};
|
|
1746
1756
|
}
|
|
1747
1757
|
async function getReadyFilesForImport(translationStatuses, options = {}) {
|
|
1748
|
-
const { filterReadyFiles = () => !0 } = options, readyFilesByDocumentLocale = /* @__PURE__ */ new Map();
|
|
1758
|
+
const { filterReadyFiles = () => !0 } = options, readyFilesByDocumentLocale = /* @__PURE__ */ new Map(), selectedStatusKeys = [];
|
|
1749
1759
|
for (const [key, status] of translationStatuses.entries()) {
|
|
1750
1760
|
const readyStatus = status.isReady && status.fileData ? { ...status, fileData: status.fileData } : null;
|
|
1751
1761
|
if (readyStatus && filterReadyFiles(key, readyStatus)) {
|
|
1762
|
+
selectedStatusKeys.push(key);
|
|
1752
1763
|
const fileData = {
|
|
1753
1764
|
fileId: getPublishedId(readyStatus.fileData.fileId),
|
|
1754
1765
|
versionId: readyStatus.fileData.versionId,
|
|
@@ -1765,7 +1776,10 @@ async function getReadyFilesForImport(translationStatuses, options = {}) {
|
|
|
1765
1776
|
);
|
|
1766
1777
|
}
|
|
1767
1778
|
}
|
|
1768
|
-
return Array.from(readyFilesByDocumentLocale.values());
|
|
1779
|
+
return options.onSelectedKeys?.(selectedStatusKeys), Array.from(readyFilesByDocumentLocale.values());
|
|
1780
|
+
}
|
|
1781
|
+
function importKeyFor(file) {
|
|
1782
|
+
return `${file.branchId}:${file.fileId}:${file.versionId}:${file.locale}`;
|
|
1769
1783
|
}
|
|
1770
1784
|
async function importTranslations(readyFiles, secrets, translationContext, options = {}) {
|
|
1771
1785
|
if (readyFiles.length === 0)
|
|
@@ -1780,7 +1794,7 @@ async function importTranslations(readyFiles, secrets, translationContext, optio
|
|
|
1780
1794
|
locale: file.locale,
|
|
1781
1795
|
data,
|
|
1782
1796
|
translationContext,
|
|
1783
|
-
key:
|
|
1797
|
+
key: importKeyFor(file)
|
|
1784
1798
|
};
|
|
1785
1799
|
}), result = await processImportBatch(importItems, {
|
|
1786
1800
|
onProgress: options.onProgress,
|
|
@@ -1794,6 +1808,17 @@ async function importTranslations(readyFiles, secrets, translationContext, optio
|
|
|
1794
1808
|
successfulImports: result.successfulImports
|
|
1795
1809
|
};
|
|
1796
1810
|
}
|
|
1811
|
+
const TRANSLATION_DOCS_FOR_PUBLISH_QUERY = `*[
|
|
1812
|
+
_type == 'translation.metadata' &&
|
|
1813
|
+
count(translations[defined(value._ref) && value._ref in $publishedDocumentIds]) > 0
|
|
1814
|
+
] {
|
|
1815
|
+
'translationDocs': translations[
|
|
1816
|
+
defined(value._ref) && !(value._ref in $sourceDocumentIds)
|
|
1817
|
+
]{
|
|
1818
|
+
_key,
|
|
1819
|
+
'docId': value._ref
|
|
1820
|
+
}
|
|
1821
|
+
}`;
|
|
1797
1822
|
async function publishDocument(documentId, client) {
|
|
1798
1823
|
try {
|
|
1799
1824
|
documentId.startsWith("drafts.") && await client.action(
|
|
@@ -1900,7 +1925,7 @@ const useTranslations = () => {
|
|
|
1900
1925
|
skipped: /* @__PURE__ */ new Set()
|
|
1901
1926
|
}), downloadStatusRef = useRef(downloadStatus), [translationStatuses, setTranslationStatuses] = useState(/* @__PURE__ */ new Map()), [pendingTranslations, setPendingTranslations] = useState(
|
|
1902
1927
|
/* @__PURE__ */ new Set()
|
|
1903
|
-
), [isRefreshing, setIsRefreshing] = useState(!1), client = useClient(), { projectId, dataset } = client.config(), uploadedVersionsStorageKey = getUploadedVersionsStorageKey(
|
|
1928
|
+
), [importingTranslations, setImportingTranslations] = useState(/* @__PURE__ */ new Set()), [isRefreshing, setIsRefreshing] = useState(!1), client = useClient(), { projectId, dataset } = client.config(), uploadedVersionsStorageKey = getUploadedVersionsStorageKey(
|
|
1904
1929
|
projectId,
|
|
1905
1930
|
dataset
|
|
1906
1931
|
), [uploadedVersions, setUploadedVersions] = useState(
|
|
@@ -2065,20 +2090,39 @@ const useTranslations = () => {
|
|
|
2065
2090
|
const nextUploadedVersions = new Map(uploadedVersions);
|
|
2066
2091
|
for (const { info } of transformedDocuments)
|
|
2067
2092
|
info.versionId && nextUploadedVersions.set(info.documentId, info.versionId);
|
|
2068
|
-
writeUploadedVersions(uploadedVersionsStorageKey, nextUploadedVersions), setUploadedVersions(nextUploadedVersions)
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2093
|
+
writeUploadedVersions(uploadedVersionsStorageKey, nextUploadedVersions), setUploadedVersions(nextUploadedVersions);
|
|
2094
|
+
const enqueuedStatusKeys = /* @__PURE__ */ new Set(), enqueuedStableKeys = /* @__PURE__ */ new Set();
|
|
2095
|
+
for (const { info } of transformedDocuments)
|
|
2096
|
+
for (const localeId of availableLocaleIds)
|
|
2097
|
+
enqueuedStatusKeys.add(
|
|
2098
|
+
createTranslationStatusKey(
|
|
2099
|
+
branchId,
|
|
2100
|
+
info.documentId,
|
|
2101
|
+
info.versionId ?? "",
|
|
2102
|
+
localeId
|
|
2103
|
+
)
|
|
2104
|
+
), enqueuedStableKeys.add(
|
|
2105
|
+
createStableTranslationKey(branchId, info.documentId, localeId)
|
|
2106
|
+
);
|
|
2107
|
+
setDownloadStatus((prev) => ({
|
|
2108
|
+
downloaded: new Set(
|
|
2109
|
+
[...prev.downloaded].filter(
|
|
2110
|
+
(key) => !enqueuedStatusKeys.has(key) && !enqueuedStableKeys.has(key)
|
|
2111
|
+
)
|
|
2112
|
+
),
|
|
2113
|
+
failed: new Set(
|
|
2114
|
+
[...prev.failed].filter(
|
|
2115
|
+
(key) => !enqueuedStatusKeys.has(key) && !enqueuedStableKeys.has(key)
|
|
2116
|
+
)
|
|
2117
|
+
),
|
|
2118
|
+
skipped: new Set(
|
|
2119
|
+
[...prev.skipped].filter(
|
|
2120
|
+
(key) => !enqueuedStatusKeys.has(key) && !enqueuedStableKeys.has(key)
|
|
2121
|
+
)
|
|
2122
|
+
)
|
|
2123
|
+
})), setPendingTranslations(
|
|
2124
|
+
(prev) => /* @__PURE__ */ new Set([...prev, ...enqueuedStatusKeys])
|
|
2125
|
+
), toast.push({
|
|
2082
2126
|
title: force ? `Retranslating ${documents.length} documents from scratch` : `Translation tasks created for ${documents.length} documents`,
|
|
2083
2127
|
status: "success",
|
|
2084
2128
|
closable: !0
|
|
@@ -2139,7 +2183,9 @@ const useTranslations = () => {
|
|
|
2139
2183
|
if (!(!secrets || documents.length === 0 || !branchId)) {
|
|
2140
2184
|
setIsBusy(!0);
|
|
2141
2185
|
try {
|
|
2142
|
-
const readyFiles = await getReadyFilesForImport(translationStatuses
|
|
2186
|
+
const readyFiles = await getReadyFilesForImport(translationStatuses, {
|
|
2187
|
+
onSelectedKeys: (keys) => setImportingTranslations(new Set(keys))
|
|
2188
|
+
});
|
|
2143
2189
|
if (readyFiles.length === 0) {
|
|
2144
2190
|
toast.push({
|
|
2145
2191
|
title: "No ready translations to import",
|
|
@@ -2188,7 +2234,7 @@ const useTranslations = () => {
|
|
|
2188
2234
|
closable: !0
|
|
2189
2235
|
});
|
|
2190
2236
|
} finally {
|
|
2191
|
-
setIsBusy(!1), setImportProgress({ current: 0, total: 0, isImporting: !1 });
|
|
2237
|
+
setIsBusy(!1), setImportProgress({ current: 0, total: 0, isImporting: !1 }), setImportingTranslations(/* @__PURE__ */ new Set());
|
|
2192
2238
|
}
|
|
2193
2239
|
}
|
|
2194
2240
|
}, [
|
|
@@ -2234,6 +2280,7 @@ const useTranslations = () => {
|
|
|
2234
2280
|
availableLocaleIds,
|
|
2235
2281
|
branchId
|
|
2236
2282
|
), readyFiles = await getReadyFilesForImport(translationStatuses, {
|
|
2283
|
+
onSelectedKeys: (keys) => setImportingTranslations(new Set(keys)),
|
|
2237
2284
|
filterReadyFiles: (_key, status) => !existingTranslations2.has(
|
|
2238
2285
|
createStableTranslationKey(
|
|
2239
2286
|
branchId,
|
|
@@ -2290,7 +2337,7 @@ const useTranslations = () => {
|
|
|
2290
2337
|
closable: !0
|
|
2291
2338
|
});
|
|
2292
2339
|
} finally {
|
|
2293
|
-
setIsBusy(!1), setImportProgress({ current: 0, total: 0, isImporting: !1 });
|
|
2340
|
+
setIsBusy(!1), setImportProgress({ current: 0, total: 0, isImporting: !1 }), setImportingTranslations(/* @__PURE__ */ new Set());
|
|
2294
2341
|
}
|
|
2295
2342
|
}
|
|
2296
2343
|
}, [
|
|
@@ -2541,7 +2588,7 @@ const useTranslations = () => {
|
|
|
2541
2588
|
if (!secrets || documents.length === 0) return 0;
|
|
2542
2589
|
setIsBusy(!0);
|
|
2543
2590
|
try {
|
|
2544
|
-
const
|
|
2591
|
+
const sourceDocumentIds = documents.map(getDocumentPublishedId), publishedDocumentIds = await client.fetch(
|
|
2545
2592
|
"*[_id in $sourceDocumentIds]._id",
|
|
2546
2593
|
{ sourceDocumentIds }
|
|
2547
2594
|
);
|
|
@@ -2551,31 +2598,24 @@ const useTranslations = () => {
|
|
|
2551
2598
|
status: "warning",
|
|
2552
2599
|
closable: !0
|
|
2553
2600
|
}), 0;
|
|
2554
|
-
const translationMetadata = await client.fetch(
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
] {
|
|
2558
|
-
'sourceDocId': translations[language == $sourceLocale][0].value._ref,
|
|
2559
|
-
'translationDocs': translations[language != $sourceLocale && defined(value._ref)]{
|
|
2560
|
-
_key,
|
|
2561
|
-
'docId': value._ref
|
|
2562
|
-
}
|
|
2563
|
-
}`, {
|
|
2564
|
-
sourceLocale,
|
|
2565
|
-
publishedDocumentIds
|
|
2601
|
+
const translationMetadata = await client.fetch(TRANSLATION_DOCS_FOR_PUBLISH_QUERY, {
|
|
2602
|
+
publishedDocumentIds,
|
|
2603
|
+
sourceDocumentIds
|
|
2566
2604
|
}), translationDocIds = /* @__PURE__ */ new Set();
|
|
2567
|
-
|
|
2605
|
+
translationMetadata.forEach((metadata) => {
|
|
2568
2606
|
metadata.translationDocs?.forEach((translation) => {
|
|
2569
2607
|
translation.docId && translationDocIds.add(translation.docId);
|
|
2570
2608
|
});
|
|
2571
|
-
})
|
|
2609
|
+
});
|
|
2610
|
+
const publishableIds = Array.from(translationDocIds);
|
|
2611
|
+
if (publishableIds.length === 0)
|
|
2572
2612
|
return toast.push({
|
|
2573
2613
|
title: "No translation documents found to publish",
|
|
2574
2614
|
status: "warning",
|
|
2575
2615
|
closable: !0
|
|
2576
2616
|
}), 0;
|
|
2577
2617
|
const translatedDocumentIds = await publishTranslations(
|
|
2578
|
-
|
|
2618
|
+
publishableIds,
|
|
2579
2619
|
client
|
|
2580
2620
|
);
|
|
2581
2621
|
return toast.push({
|
|
@@ -2636,6 +2676,7 @@ const useTranslations = () => {
|
|
|
2636
2676
|
downloadStatus,
|
|
2637
2677
|
translationStatuses,
|
|
2638
2678
|
pendingTranslations,
|
|
2679
|
+
importingTranslations,
|
|
2639
2680
|
isRefreshing,
|
|
2640
2681
|
loadingSecrets,
|
|
2641
2682
|
secrets,
|
|
@@ -2668,9 +2709,9 @@ const useTranslations = () => {
|
|
|
2668
2709
|
/* @__PURE__ */ jsx(Button, { text: "Cancel", mode: "ghost", onClick: onClose }),
|
|
2669
2710
|
/* @__PURE__ */ jsx(Button, { text: "Turn on", tone: "primary", onClick: onConfirm })
|
|
2670
2711
|
] }) }),
|
|
2671
|
-
children: /* @__PURE__ */ jsx(Box, { padding: 4, children: /* @__PURE__ */ jsxs(Stack, {
|
|
2712
|
+
children: /* @__PURE__ */ jsx(Box, { padding: 4, children: /* @__PURE__ */ jsxs(Stack, { gap: 4, children: [
|
|
2672
2713
|
/* @__PURE__ */ jsx(Text, { children: "Before each translation run, the translations currently in Sanity are sent to General Translation. Content whose source text has not changed is then reused from Sanity instead of being translated again, so edits made here are kept." }),
|
|
2673
|
-
/* @__PURE__ */ jsx(Card, { padding: 3, radius: 2, tone: "caution", border: !0, children: /* @__PURE__ */ jsxs(Stack, {
|
|
2714
|
+
/* @__PURE__ */ jsx(Card, { padding: 3, radius: 2, tone: "caution", border: !0, children: /* @__PURE__ */ jsxs(Stack, { gap: 3, children: [
|
|
2674
2715
|
/* @__PURE__ */ jsx(Text, { size: 1, weight: "medium", children: "Sanity becomes the source of truth" }),
|
|
2675
2716
|
/* @__PURE__ */ jsx(Text, { size: 1, children: "What is in Sanity replaces whatever General Translation holds for that version of the document \u2014 including a translation that has finished but has not been imported yet. Import any pending translations before turning this on." })
|
|
2676
2717
|
] }) }),
|
|
@@ -2678,7 +2719,7 @@ const useTranslations = () => {
|
|
|
2678
2719
|
] }) })
|
|
2679
2720
|
}
|
|
2680
2721
|
) : null;
|
|
2681
|
-
var version = "
|
|
2722
|
+
var version = "4.0.0";
|
|
2682
2723
|
function buildDebugInfo({
|
|
2683
2724
|
secrets,
|
|
2684
2725
|
preferences,
|
|
@@ -2873,7 +2914,7 @@ const DebugInfoDialog = ({
|
|
|
2873
2914
|
),
|
|
2874
2915
|
/* @__PURE__ */ jsx(Button, { text: "Close", mode: "ghost", onClick: onClose })
|
|
2875
2916
|
] }) }),
|
|
2876
|
-
children: /* @__PURE__ */ jsx(Box, { padding: 4, children: /* @__PURE__ */ jsx(Stack, {
|
|
2917
|
+
children: /* @__PURE__ */ jsx(Box, { padding: 4, children: /* @__PURE__ */ jsx(Stack, { gap: 4, children: /* @__PURE__ */ jsx(
|
|
2877
2918
|
Card,
|
|
2878
2919
|
{
|
|
2879
2920
|
padding: 3,
|
|
@@ -2906,39 +2947,49 @@ const DebugInfoDialog = ({
|
|
|
2906
2947
|
}, LanguageStatus = ({
|
|
2907
2948
|
localeId,
|
|
2908
2949
|
state,
|
|
2909
|
-
importFile
|
|
2950
|
+
importFile,
|
|
2951
|
+
isImporting = !1
|
|
2910
2952
|
}) => {
|
|
2911
|
-
const [
|
|
2912
|
-
|
|
2953
|
+
const [isSelfImporting, setIsSelfImporting] = useState(!1), isBusy = (isSelfImporting || isImporting) && state !== "imported", handleImport = useCallback(async () => {
|
|
2954
|
+
setIsSelfImporting(!0);
|
|
2913
2955
|
try {
|
|
2914
2956
|
await importFile();
|
|
2915
2957
|
} finally {
|
|
2916
|
-
|
|
2958
|
+
setIsSelfImporting(!1);
|
|
2917
2959
|
}
|
|
2918
2960
|
}, [importFile]);
|
|
2919
|
-
return /* @__PURE__ */ jsxs(Grid, {
|
|
2920
|
-
/* @__PURE__ */ jsx(Flex, {
|
|
2921
|
-
/* @__PURE__ */ jsxs(Flex, {
|
|
2922
|
-
state === "translating" && /* @__PURE__ */ jsx(Spinner, { size: 1, muted: !0 }),
|
|
2923
|
-
/* @__PURE__ */ jsx(Text, { size: 1, muted: state !== "ready", children: STATE_LABEL[state] })
|
|
2961
|
+
return /* @__PURE__ */ jsxs(Grid, { gridTemplateColumns: 5, gap: 3, paddingX: 3, paddingY: 2, children: [
|
|
2962
|
+
/* @__PURE__ */ jsx(Flex, { gridColumnStart: 1, gridColumnEnd: 3, align: "center", children: /* @__PURE__ */ jsx(LocaleLabel, { localeId }) }),
|
|
2963
|
+
/* @__PURE__ */ jsxs(Flex, { gridColumnStart: 3, gridColumnEnd: 5, align: "center", gap: 2, children: [
|
|
2964
|
+
(state === "translating" || isBusy) && /* @__PURE__ */ jsx(Spinner, { size: 1, muted: !0 }),
|
|
2965
|
+
/* @__PURE__ */ jsx(Text, { size: 1, muted: state !== "ready", children: isBusy ? "Importing\u2026" : STATE_LABEL[state] })
|
|
2924
2966
|
] }),
|
|
2925
|
-
/* @__PURE__ */ jsx(
|
|
2926
|
-
|
|
2927
|
-
/* @__PURE__ */ jsx(Box, { children: "Imported" })
|
|
2928
|
-
] }) }) : /* @__PURE__ */ jsx(
|
|
2929
|
-
Button,
|
|
2967
|
+
/* @__PURE__ */ jsx(
|
|
2968
|
+
Flex,
|
|
2930
2969
|
{
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2970
|
+
gridColumnStart: 5,
|
|
2971
|
+
gridColumnEnd: 6,
|
|
2972
|
+
align: "center",
|
|
2973
|
+
justify: "flex-end",
|
|
2974
|
+
children: state === "imported" ? /* @__PURE__ */ jsx(Badge, { tone: "positive", fontSize: 0, radius: 2, children: /* @__PURE__ */ jsxs(Flex, { align: "center", gap: 1, children: [
|
|
2975
|
+
/* @__PURE__ */ jsx(CheckmarkCircleIcon, {}),
|
|
2976
|
+
/* @__PURE__ */ jsx(Box, { children: "Imported" })
|
|
2977
|
+
] }) }) : /* @__PURE__ */ jsx(
|
|
2978
|
+
Button,
|
|
2979
|
+
{
|
|
2980
|
+
style: { width: "100%" },
|
|
2981
|
+
mode: "ghost",
|
|
2982
|
+
fontSize: 1,
|
|
2983
|
+
padding: 2,
|
|
2984
|
+
onClick: handleImport,
|
|
2985
|
+
text: isBusy ? "Importing\u2026" : "Import",
|
|
2986
|
+
loading: isBusy,
|
|
2987
|
+
icon: DownloadIcon,
|
|
2988
|
+
disabled: isBusy || state !== "ready"
|
|
2989
|
+
}
|
|
2990
|
+
)
|
|
2940
2991
|
}
|
|
2941
|
-
)
|
|
2992
|
+
)
|
|
2942
2993
|
] });
|
|
2943
2994
|
};
|
|
2944
2995
|
function resolveLanguageStatusState({
|
|
@@ -2983,6 +3034,7 @@ const LocaleCheckbox = ({
|
|
|
2983
3034
|
locales,
|
|
2984
3035
|
translationStatuses,
|
|
2985
3036
|
pendingTranslations,
|
|
3037
|
+
importingTranslations,
|
|
2986
3038
|
branchId,
|
|
2987
3039
|
isBusy,
|
|
2988
3040
|
handleTranslateAll,
|
|
@@ -3092,10 +3144,10 @@ const LocaleCheckbox = ({
|
|
|
3092
3144
|
);
|
|
3093
3145
|
setLocales(updatedLocales);
|
|
3094
3146
|
}, [locales, setLocales]);
|
|
3095
|
-
return shouldShowTranslationComponents ? /* @__PURE__ */ jsxs(Stack, {
|
|
3096
|
-
/* @__PURE__ */ jsxs(Stack, {
|
|
3147
|
+
return shouldShowTranslationComponents ? /* @__PURE__ */ jsxs(Stack, { gap: 6, padding: 4, children: [
|
|
3148
|
+
/* @__PURE__ */ jsxs(Stack, { gap: 4, children: [
|
|
3097
3149
|
/* @__PURE__ */ jsx(Text, { as: "h2", weight: "semibold", size: 2, children: "Translate" }),
|
|
3098
|
-
/* @__PURE__ */ jsxs(Stack, {
|
|
3150
|
+
/* @__PURE__ */ jsxs(Stack, { gap: 3, children: [
|
|
3099
3151
|
/* @__PURE__ */ jsxs(Flex, { align: "center", justify: "space-between", children: [
|
|
3100
3152
|
/* @__PURE__ */ jsx(Text, { weight: "semibold", size: 1, children: availableLocales.length === 1 ? "Select locale" : "Select locales" }),
|
|
3101
3153
|
/* @__PURE__ */ jsx(
|
|
@@ -3109,7 +3161,7 @@ const LocaleCheckbox = ({
|
|
|
3109
3161
|
}
|
|
3110
3162
|
)
|
|
3111
3163
|
] }),
|
|
3112
|
-
/* @__PURE__ */ jsx(Grid, {
|
|
3164
|
+
/* @__PURE__ */ jsx(Grid, { gridTemplateColumns: [1, 1, 2, 3], gap: 1, children: locales.filter(
|
|
3113
3165
|
(locale) => locale.localeId !== pluginConfig.getSourceLocale()
|
|
3114
3166
|
).map((locale) => /* @__PURE__ */ jsx(
|
|
3115
3167
|
LocaleCheckbox,
|
|
@@ -3144,7 +3196,7 @@ const LocaleCheckbox = ({
|
|
|
3144
3196
|
}
|
|
3145
3197
|
}
|
|
3146
3198
|
),
|
|
3147
|
-
documentId && versionId && statusLocales.length > 0 && /* @__PURE__ */ jsxs(Stack, {
|
|
3199
|
+
documentId && versionId && statusLocales.length > 0 && /* @__PURE__ */ jsxs(Stack, { gap: 4, children: [
|
|
3148
3200
|
/* @__PURE__ */ jsxs(Flex, { align: "center", justify: "space-between", children: [
|
|
3149
3201
|
/* @__PURE__ */ jsx(Text, { as: "h2", weight: "semibold", size: 2, children: "Translation Status" }),
|
|
3150
3202
|
/* @__PURE__ */ jsxs(Flex, { gap: 3, align: "center", children: [
|
|
@@ -3189,6 +3241,7 @@ const LocaleCheckbox = ({
|
|
|
3189
3241
|
isImported,
|
|
3190
3242
|
isPending: pendingTranslations.has(key)
|
|
3191
3243
|
}),
|
|
3244
|
+
isImporting: importingTranslations.has(key),
|
|
3192
3245
|
importFile: async () => {
|
|
3193
3246
|
!isImported && status?.isReady && await handleImportDocument(
|
|
3194
3247
|
documentId,
|
|
@@ -3200,7 +3253,7 @@ const LocaleCheckbox = ({
|
|
|
3200
3253
|
key
|
|
3201
3254
|
);
|
|
3202
3255
|
}) }),
|
|
3203
|
-
/* @__PURE__ */ jsxs(Stack, {
|
|
3256
|
+
/* @__PURE__ */ jsxs(Stack, { gap: 3, children: [
|
|
3204
3257
|
/* @__PURE__ */ jsxs(Flex, { gap: 2, align: "center", justify: "flex-start", children: [
|
|
3205
3258
|
/* @__PURE__ */ jsx(
|
|
3206
3259
|
Button,
|
|
@@ -3438,6 +3491,7 @@ const DocumentRow = ({ document: document2 }) => {
|
|
|
3438
3491
|
locales,
|
|
3439
3492
|
translationStatuses,
|
|
3440
3493
|
pendingTranslations,
|
|
3494
|
+
importingTranslations,
|
|
3441
3495
|
downloadStatus,
|
|
3442
3496
|
importedTranslations,
|
|
3443
3497
|
handleImportDocument,
|
|
@@ -3465,7 +3519,7 @@ const DocumentRow = ({ document: document2 }) => {
|
|
|
3465
3519
|
] })
|
|
3466
3520
|
}
|
|
3467
3521
|
),
|
|
3468
|
-
/* @__PURE__ */ jsx(Box, { paddingY: 1, children: enabledLocales.length > 0 ? /* @__PURE__ */ jsx(Stack, {
|
|
3522
|
+
/* @__PURE__ */ jsx(Box, { paddingY: 1, children: enabledLocales.length > 0 ? /* @__PURE__ */ jsx(Stack, { gap: 1, children: enabledLocales.map((locale) => {
|
|
3469
3523
|
const versionId = getVersionId(document2), key = createTranslationStatusKey(
|
|
3470
3524
|
branchId,
|
|
3471
3525
|
publishedId,
|
|
@@ -3481,6 +3535,7 @@ const DocumentRow = ({ document: document2 }) => {
|
|
|
3481
3535
|
isImported: isImported || isDownloaded,
|
|
3482
3536
|
isPending: pendingTranslations.has(key)
|
|
3483
3537
|
}),
|
|
3538
|
+
isImporting: importingTranslations.has(key),
|
|
3484
3539
|
importFile: async () => {
|
|
3485
3540
|
await handleImportDocument(
|
|
3486
3541
|
publishedId,
|
|
@@ -3495,7 +3550,7 @@ const DocumentRow = ({ document: document2 }) => {
|
|
|
3495
3550
|
] });
|
|
3496
3551
|
}, TranslationsTable = () => {
|
|
3497
3552
|
const { documents, loadingDocuments } = useTranslations();
|
|
3498
|
-
return loadingDocuments ? /* @__PURE__ */ jsx(Flex, { align: "center", justify: "center", padding: 4, children: /* @__PURE__ */ jsx(Spinner, {}) }) : /* @__PURE__ */ jsx(Box, { style: { maxHeight: "60vh", overflowY: "auto" }, children: /* @__PURE__ */ jsx(Stack, {
|
|
3553
|
+
return loadingDocuments ? /* @__PURE__ */ jsx(Flex, { align: "center", justify: "center", padding: 4, children: /* @__PURE__ */ jsx(Spinner, {}) }) : /* @__PURE__ */ jsx(Box, { style: { maxHeight: "60vh", overflowY: "auto" }, children: /* @__PURE__ */ jsx(Stack, { gap: 2, children: documents.map((document2) => /* @__PURE__ */ jsx(DocumentRow, { document: document2 }, document2._id)) }) });
|
|
3499
3554
|
}, TranslateAllDialog = ({
|
|
3500
3555
|
isOpen,
|
|
3501
3556
|
onClose
|
|
@@ -3522,8 +3577,8 @@ const DocumentRow = ({ document: document2 }) => {
|
|
|
3522
3577
|
}
|
|
3523
3578
|
)
|
|
3524
3579
|
] }) }),
|
|
3525
|
-
children: /* @__PURE__ */ jsx(Box, { padding: 4, children: /* @__PURE__ */ jsxs(Stack, {
|
|
3526
|
-
/* @__PURE__ */ jsxs(Stack, {
|
|
3580
|
+
children: /* @__PURE__ */ jsx(Box, { padding: 4, children: /* @__PURE__ */ jsxs(Stack, { gap: 4, children: [
|
|
3581
|
+
/* @__PURE__ */ jsxs(Stack, { gap: 3, children: [
|
|
3527
3582
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
3528
3583
|
"Are you sure you want to create translations for all",
|
|
3529
3584
|
" ",
|
|
@@ -3548,7 +3603,7 @@ const DocumentRow = ({ document: document2 }) => {
|
|
|
3548
3603
|
onChange: (event) => setForce(event.currentTarget.checked)
|
|
3549
3604
|
}
|
|
3550
3605
|
),
|
|
3551
|
-
/* @__PURE__ */ jsxs(Stack, {
|
|
3606
|
+
/* @__PURE__ */ jsxs(Stack, { gap: 2, flex: 1, children: [
|
|
3552
3607
|
/* @__PURE__ */ jsx(Text, { size: 1, weight: "medium", children: /* @__PURE__ */ jsx("label", { htmlFor: "translate-all-force", children: "Retranslate from scratch" }) }),
|
|
3553
3608
|
/* @__PURE__ */ jsx(Text, { size: 1, muted: !0, children: force ? "Existing translations will be discarded and regenerated. Edits made to translated documents will be lost." : "Leave unchecked to reuse existing translations, including edits made to translated documents in the Studio." })
|
|
3554
3609
|
] })
|
|
@@ -3575,7 +3630,7 @@ const DocumentRow = ({ document: document2 }) => {
|
|
|
3575
3630
|
onClose(), await handleImportAll();
|
|
3576
3631
|
} })
|
|
3577
3632
|
] }) }),
|
|
3578
|
-
children: /* @__PURE__ */ jsx(Box, { padding: 4, children: /* @__PURE__ */ jsxs(Stack, {
|
|
3633
|
+
children: /* @__PURE__ */ jsx(Box, { padding: 4, children: /* @__PURE__ */ jsxs(Stack, { gap: 3, children: [
|
|
3579
3634
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
3580
3635
|
"Are you sure you want to import translations for all",
|
|
3581
3636
|
" ",
|
|
@@ -3603,7 +3658,7 @@ const DocumentRow = ({ document: document2 }) => {
|
|
|
3603
3658
|
onClose(), await handleImportMissing();
|
|
3604
3659
|
} })
|
|
3605
3660
|
] }) }),
|
|
3606
|
-
children: /* @__PURE__ */ jsx(Box, { padding: 4, children: /* @__PURE__ */ jsxs(Stack, {
|
|
3661
|
+
children: /* @__PURE__ */ jsx(Box, { padding: 4, children: /* @__PURE__ */ jsxs(Stack, { gap: 3, children: [
|
|
3607
3662
|
/* @__PURE__ */ jsx(Text, { children: "Import only the missing translations (translations that are ready but haven't been imported to Sanity yet)?" }),
|
|
3608
3663
|
/* @__PURE__ */ jsx(Text, { size: 1, muted: !0, children: "This will check existing translation metadata and only import translations that don't already exist in your dataset." })
|
|
3609
3664
|
] }) })
|
|
@@ -3626,7 +3681,7 @@ const DocumentRow = ({ document: document2 }) => {
|
|
|
3626
3681
|
onClose(), await handleUploadExistingTranslations();
|
|
3627
3682
|
} })
|
|
3628
3683
|
] }) }),
|
|
3629
|
-
children: /* @__PURE__ */ jsx(Box, { padding: 4, children: /* @__PURE__ */ jsxs(Stack, {
|
|
3684
|
+
children: /* @__PURE__ */ jsx(Box, { padding: 4, children: /* @__PURE__ */ jsxs(Stack, { gap: 3, children: [
|
|
3630
3685
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
3631
3686
|
"Save the translations currently in Sanity for all ",
|
|
3632
3687
|
documents.length,
|
|
@@ -3661,6 +3716,7 @@ const DocumentRow = ({ document: document2 }) => {
|
|
|
3661
3716
|
loadingDocuments,
|
|
3662
3717
|
importProgress,
|
|
3663
3718
|
importedTranslations,
|
|
3719
|
+
pendingTranslations,
|
|
3664
3720
|
isRefreshing,
|
|
3665
3721
|
setAutoRefresh,
|
|
3666
3722
|
preserveExistingTranslations,
|
|
@@ -3687,11 +3743,11 @@ const DocumentRow = ({ document: document2 }) => {
|
|
|
3687
3743
|
React.useEffect(() => {
|
|
3688
3744
|
!isBusy && !importProgress.isImporting && setCurrentOperation(null);
|
|
3689
3745
|
}, [isBusy, importProgress.isImporting]);
|
|
3690
|
-
const enabledLocaleCount = locales.filter((l) => l.enabled !== !1).length, totalTranslations = documents.length * enabledLocaleCount, actionsDisabled = isBusy || loadingDocuments || documents.length === 0;
|
|
3746
|
+
const isWaitingOnTranslations = pendingTranslations.size > 0, enabledLocaleCount = locales.filter((l) => l.enabled !== !1).length, totalTranslations = documents.length * enabledLocaleCount, actionsDisabled = isBusy || loadingDocuments || documents.length === 0;
|
|
3691
3747
|
return /* @__PURE__ */ jsxs(Container, { width: 2, children: [
|
|
3692
|
-
/* @__PURE__ */ jsx(Box, { padding: 4, marginTop: 5, children: /* @__PURE__ */ jsxs(Stack, {
|
|
3748
|
+
/* @__PURE__ */ jsx(Box, { padding: 4, marginTop: 5, children: /* @__PURE__ */ jsxs(Stack, { gap: 5, children: [
|
|
3693
3749
|
/* @__PURE__ */ jsxs(Flex, { align: "flex-start", justify: "space-between", gap: 4, children: [
|
|
3694
|
-
/* @__PURE__ */ jsxs(Stack, {
|
|
3750
|
+
/* @__PURE__ */ jsxs(Stack, { gap: 3, children: [
|
|
3695
3751
|
/* @__PURE__ */ jsx(Heading, { as: "h2", size: 3, children: "Translations" }),
|
|
3696
3752
|
/* @__PURE__ */ jsx(Text, { size: 1, muted: !0, children: "Manage your document translations from this centralized location." })
|
|
3697
3753
|
] }),
|
|
@@ -3699,16 +3755,16 @@ const DocumentRow = ({ document: document2 }) => {
|
|
|
3699
3755
|
Button,
|
|
3700
3756
|
{
|
|
3701
3757
|
icon: TranslateIcon,
|
|
3702
|
-
text: "Translate All",
|
|
3703
|
-
loading: isBusy && currentOperation === "Translate All",
|
|
3758
|
+
text: isWaitingOnTranslations ? "Translating\u2026" : "Translate All",
|
|
3759
|
+
loading: isBusy && currentOperation === "Translate All" || isWaitingOnTranslations,
|
|
3704
3760
|
onClick: () => {
|
|
3705
3761
|
setCurrentOperation("Translate All"), setIsTranslateAllDialogOpen(!0);
|
|
3706
3762
|
},
|
|
3707
|
-
disabled: actionsDisabled
|
|
3763
|
+
disabled: actionsDisabled || isWaitingOnTranslations
|
|
3708
3764
|
}
|
|
3709
3765
|
)
|
|
3710
3766
|
] }),
|
|
3711
|
-
/* @__PURE__ */ jsxs(Stack, {
|
|
3767
|
+
/* @__PURE__ */ jsxs(Stack, { gap: 3, children: [
|
|
3712
3768
|
/* @__PURE__ */ jsxs(Flex, { align: "center", justify: "space-between", gap: 3, children: [
|
|
3713
3769
|
/* @__PURE__ */ jsx(Text, { size: 1, muted: !0, children: loadingDocuments ? "Loading documents..." : `${documents.length} ${documents.length === 1 ? "document" : "documents"} available for translation` }),
|
|
3714
3770
|
/* @__PURE__ */ jsxs(Flex, { gap: 3, align: "center", children: [
|
|
@@ -3751,7 +3807,7 @@ const DocumentRow = ({ document: document2 }) => {
|
|
|
3751
3807
|
] }),
|
|
3752
3808
|
/* @__PURE__ */ jsx(TranslationsTable, {})
|
|
3753
3809
|
] }),
|
|
3754
|
-
/* @__PURE__ */ jsxs(Stack, {
|
|
3810
|
+
/* @__PURE__ */ jsxs(Stack, { gap: 3, children: [
|
|
3755
3811
|
/* @__PURE__ */ jsxs(Flex, { gap: 2, align: "center", justify: "space-between", children: [
|
|
3756
3812
|
/* @__PURE__ */ jsxs(Flex, { gap: 2, align: "center", wrap: "wrap", children: [
|
|
3757
3813
|
/* @__PURE__ */ jsx(
|
|
@@ -3997,13 +4053,13 @@ function gtStructureItems(S, context, options = {}) {
|
|
|
3997
4053
|
return S.listItem().id(`gt-${type}`).title(title).child(
|
|
3998
4054
|
S.list().id(`gt-${type}-locales`).title(title).items([
|
|
3999
4055
|
S.listItem().id(`gt-${type}-${sourceLocale}`).title(options.sourceTitle ?? localeLabel(sourceLocale)).child(
|
|
4000
|
-
S.documentList().id(`gt-${type}-${sourceLocale}-list`).title(options.sourceTitle ?? localeLabel(sourceLocale)).schemaType(type).filter(sourceFilter).params({ type, locale: sourceLocale })
|
|
4056
|
+
S.documentList().id(`gt-${type}-${sourceLocale}-list`).title(options.sourceTitle ?? localeLabel(sourceLocale)).schemaType(type).apiVersion(SANITY_API_VERSION).filter(sourceFilter).params({ type, locale: sourceLocale })
|
|
4001
4057
|
),
|
|
4002
4058
|
S.divider(),
|
|
4003
4059
|
...targetLocales.map((locale) => {
|
|
4004
4060
|
const paneTitle = titleFor(title, locale, localeLabel(locale));
|
|
4005
4061
|
return S.listItem().id(`gt-${type}-${locale}`).title(paneTitle).child(
|
|
4006
|
-
S.documentList().id(`gt-${type}-${locale}-list`).title(paneTitle).schemaType(type).filter(localeFilter).params({ type, locale })
|
|
4062
|
+
S.documentList().id(`gt-${type}-${locale}-list`).title(paneTitle).schemaType(type).apiVersion(SANITY_API_VERSION).filter(localeFilter).params({ type, locale })
|
|
4007
4063
|
);
|
|
4008
4064
|
})
|
|
4009
4065
|
])
|