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 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 { ClipboardIcon, CheckmarkCircleIcon, DownloadIcon, TranslateIcon, RefreshIcon, UploadIcon, LinkIcon, PublishIcon } from "@sanity/icons";
8
- import { ThemeProvider, ToastProvider, Box, Flex, Spinner, Card, Text, useToast, Dialog, Stack, Button, Code, Badge, Grid, Checkbox, Switch, Tooltip, Container, Heading } from "@sanity/ui";
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: "2025-09-15" });
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: `${file.branchId}:${file.fileId}:${file.versionId}:${file.locale}`
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), setPendingTranslations((prev) => {
2069
- const next = new Set(prev);
2070
- for (const { info } of transformedDocuments)
2071
- for (const localeId of availableLocaleIds)
2072
- next.add(
2073
- createTranslationStatusKey(
2074
- branchId,
2075
- info.documentId,
2076
- info.versionId ?? "",
2077
- localeId
2078
- )
2079
- );
2080
- return next;
2081
- }), toast.push({
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 sourceLocale = pluginConfig.getSourceLocale(), sourceDocumentIds = documents.map(getDocumentPublishedId), publishedDocumentIds = await client.fetch(
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
- _type == 'translation.metadata' &&
2556
- translations[language == $sourceLocale][0].value._ref in $publishedDocumentIds
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
- if (translationMetadata.forEach((metadata) => {
2605
+ translationMetadata.forEach((metadata) => {
2568
2606
  metadata.translationDocs?.forEach((translation) => {
2569
2607
  translation.docId && translationDocIds.add(translation.docId);
2570
2608
  });
2571
- }), translationDocIds.size === 0)
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
- Array.from(translationDocIds),
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, { space: 4, children: [
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, { space: 3, children: [
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 = "3.1.7-iris.0";
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, { space: 4, children: /* @__PURE__ */ jsx(
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 [isBusy, setIsBusy] = useState(!1), handleImport = useCallback(async () => {
2912
- setIsBusy(!0);
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
- setIsBusy(!1);
2958
+ setIsSelfImporting(!1);
2917
2959
  }
2918
2960
  }, [importFile]);
2919
- return /* @__PURE__ */ jsxs(Grid, { columns: 5, gap: 3, paddingX: 3, paddingY: 2, children: [
2920
- /* @__PURE__ */ jsx(Flex, { columnStart: 1, columnEnd: 3, align: "center", children: /* @__PURE__ */ jsx(LocaleLabel, { localeId }) }),
2921
- /* @__PURE__ */ jsxs(Flex, { columnStart: 3, columnEnd: 5, align: "center", gap: 2, children: [
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(Flex, { columnStart: 5, columnEnd: 6, align: "center", justify: "flex-end", children: state === "imported" ? /* @__PURE__ */ jsx(Badge, { tone: "positive", fontSize: 0, radius: 2, children: /* @__PURE__ */ jsxs(Flex, { align: "center", gap: 1, children: [
2926
- /* @__PURE__ */ jsx(CheckmarkCircleIcon, {}),
2927
- /* @__PURE__ */ jsx(Box, { children: "Imported" })
2928
- ] }) }) : /* @__PURE__ */ jsx(
2929
- Button,
2967
+ /* @__PURE__ */ jsx(
2968
+ Flex,
2930
2969
  {
2931
- style: { width: "100%" },
2932
- mode: "ghost",
2933
- fontSize: 1,
2934
- padding: 2,
2935
- onClick: handleImport,
2936
- text: "Import",
2937
- loading: isBusy,
2938
- icon: DownloadIcon,
2939
- disabled: isBusy || state !== "ready"
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, { space: 6, padding: 4, children: [
3096
- /* @__PURE__ */ jsxs(Stack, { space: 4, children: [
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, { space: 3, children: [
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, { columns: [1, 1, 2, 3], gap: 1, children: locales.filter(
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, { space: 4, children: [
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, { space: 3, children: [
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, { space: 1, children: enabledLocales.map((locale) => {
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, { space: 2, children: documents.map((document2) => /* @__PURE__ */ jsx(DocumentRow, { document: document2 }, document2._id)) }) });
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, { space: 4, children: [
3526
- /* @__PURE__ */ jsxs(Stack, { space: 3, children: [
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, { space: 2, flex: 1, children: [
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, { space: 3, children: [
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, { space: 3, children: [
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, { space: 3, children: [
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, { space: 5, children: [
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, { space: 3, children: [
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, { space: 3, children: [
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, { space: 3, children: [
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
  ])