gt-sanity 2.0.7 → 2.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/dist/index.d.mts +13 -14
- package/dist/index.d.ts +13 -14
- package/dist/index.js +309 -101
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +310 -102
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/adapter/core.ts +10 -0
- package/src/adapter/types.ts +6 -5
- package/src/components/TranslationsProvider.tsx +86 -28
- package/src/components/page/TranslationsTable.tsx +12 -4
- package/src/components/shared/LanguageStatus.tsx +3 -2
- package/src/components/shared/SingleDocumentView.tsx +12 -4
- package/src/components/tab/TranslationView.tsx +35 -6
- package/src/configuration/baseDocumentLevelConfig/documentLevelPatch.test.ts +76 -0
- package/src/configuration/baseDocumentLevelConfig/documentLevelPatch.ts +27 -2
- package/src/configuration/baseDocumentLevelConfig/helpers/createI18nDocAndPatchMetadata.ts +12 -5
- package/src/configuration/baseDocumentLevelConfig/helpers/createTranslationMetadata.ts +2 -1
- package/src/configuration/baseDocumentLevelConfig/helpers/getOrCreateTranslationMetadata.ts +7 -4
- package/src/configuration/baseDocumentLevelConfig/helpers/getTranslationMetadata.ts +2 -1
- package/src/configuration/baseDocumentLevelConfig/helpers/patchI18nDoc.test.ts +52 -0
- package/src/configuration/baseDocumentLevelConfig/helpers/patchI18nDoc.ts +20 -2
- package/src/configuration/utils/findLatestDraft.ts +3 -1
- package/src/index.ts +4 -0
- package/src/sanity-api/findDocuments.ts +11 -5
- package/src/sanity-api/publishDocuments.ts +2 -1
- package/src/sanity-api/resolveRefs.ts +5 -4
- package/src/translation/checkTranslationStatus.ts +25 -6
- package/src/utils/__tests__/batchProcessor.test.ts +44 -0
- package/src/utils/__tests__/documentIds.test.ts +42 -0
- package/src/utils/__tests__/forEachMatchingField.test.ts +71 -1
- package/src/utils/__tests__/importUtils.test.ts +66 -0
- package/src/utils/applyDocuments.ts +56 -5
- package/src/utils/batchProcessor.ts +40 -1
- package/src/utils/documentIds.ts +49 -0
- package/src/utils/importUtils.ts +15 -7
- package/src/utils/serialize.ts +10 -6
package/dist/index.js
CHANGED
|
@@ -35,6 +35,7 @@ class GTConfig {
|
|
|
35
35
|
singletons;
|
|
36
36
|
singletonMapping;
|
|
37
37
|
ignoreFields;
|
|
38
|
+
dedupeFields;
|
|
38
39
|
skipFields;
|
|
39
40
|
translateDocuments;
|
|
40
41
|
additionalStopTypes;
|
|
@@ -42,8 +43,8 @@ class GTConfig {
|
|
|
42
43
|
additionalDeserializers;
|
|
43
44
|
additionalBlockDeserializers;
|
|
44
45
|
static instance;
|
|
45
|
-
constructor(secretsNamespace, languageField, sourceLocale, locales, singletons, singletonMapping, ignoreFields, skipFields, translateDocuments, additionalStopTypes = [], additionalSerializers = {}, additionalDeserializers = {}, additionalBlockDeserializers = []) {
|
|
46
|
-
this.secretsNamespace = secretsNamespace, this.languageField = languageField, this.sourceLocale = sourceLocale, this.locales = locales, this.singletons = singletons, this.singletonMapping = singletonMapping, this.ignoreFields = ignoreFields, this.skipFields = skipFields, this.translateDocuments = translateDocuments, this.additionalStopTypes = additionalStopTypes, this.additionalSerializers = additionalSerializers, this.additionalDeserializers = additionalDeserializers, this.additionalBlockDeserializers = additionalBlockDeserializers;
|
|
46
|
+
constructor(secretsNamespace, languageField, sourceLocale, locales, singletons, singletonMapping, ignoreFields, dedupeFields, skipFields, translateDocuments, additionalStopTypes = [], additionalSerializers = {}, additionalDeserializers = {}, additionalBlockDeserializers = []) {
|
|
47
|
+
this.secretsNamespace = secretsNamespace, this.languageField = languageField, this.sourceLocale = sourceLocale, this.locales = locales, this.singletons = singletons, this.singletonMapping = singletonMapping, this.ignoreFields = ignoreFields, this.dedupeFields = dedupeFields, this.skipFields = skipFields, this.translateDocuments = translateDocuments, this.additionalStopTypes = additionalStopTypes, this.additionalSerializers = additionalSerializers, this.additionalDeserializers = additionalDeserializers, this.additionalBlockDeserializers = additionalBlockDeserializers;
|
|
47
48
|
}
|
|
48
49
|
static getInstance() {
|
|
49
50
|
return this.instance || (this.instance = new GTConfig(
|
|
@@ -57,13 +58,14 @@ class GTConfig {
|
|
|
57
58
|
[],
|
|
58
59
|
[],
|
|
59
60
|
[],
|
|
61
|
+
[],
|
|
60
62
|
{},
|
|
61
63
|
{},
|
|
62
64
|
[]
|
|
63
65
|
)), this.instance;
|
|
64
66
|
}
|
|
65
|
-
init(secretsNamespace, languageField, sourceLocale, locales, singletons, singletonMapping, ignoreFields, skipFields, translateDocuments, additionalStopTypes = [], additionalSerializers = {}, additionalDeserializers = {}, additionalBlockDeserializers = []) {
|
|
66
|
-
this.secretsNamespace = secretsNamespace, this.languageField = languageField, this.sourceLocale = sourceLocale, this.locales = locales, this.singletons = singletons, this.singletonMapping = singletonMapping, this.ignoreFields = ignoreFields, this.skipFields = skipFields, this.translateDocuments = translateDocuments, this.additionalStopTypes = additionalStopTypes, this.additionalSerializers = additionalSerializers, this.additionalDeserializers = additionalDeserializers, this.additionalBlockDeserializers = additionalBlockDeserializers;
|
|
67
|
+
init(secretsNamespace, languageField, sourceLocale, locales, singletons, singletonMapping, ignoreFields, dedupeFields, skipFields, translateDocuments, additionalStopTypes = [], additionalSerializers = {}, additionalDeserializers = {}, additionalBlockDeserializers = []) {
|
|
68
|
+
this.secretsNamespace = secretsNamespace, this.languageField = languageField, this.sourceLocale = sourceLocale, this.locales = locales, this.singletons = singletons, this.singletonMapping = singletonMapping, this.ignoreFields = ignoreFields, this.dedupeFields = dedupeFields, this.skipFields = skipFields, this.translateDocuments = translateDocuments, this.additionalStopTypes = additionalStopTypes, this.additionalSerializers = additionalSerializers, this.additionalDeserializers = additionalDeserializers, this.additionalBlockDeserializers = additionalBlockDeserializers;
|
|
67
69
|
}
|
|
68
70
|
getSecretsNamespace() {
|
|
69
71
|
return this.secretsNamespace;
|
|
@@ -86,6 +88,9 @@ class GTConfig {
|
|
|
86
88
|
getIgnoreFields() {
|
|
87
89
|
return this.ignoreFields;
|
|
88
90
|
}
|
|
91
|
+
getDedupeFields() {
|
|
92
|
+
return this.dedupeFields;
|
|
93
|
+
}
|
|
89
94
|
getSkipFields() {
|
|
90
95
|
return this.skipFields;
|
|
91
96
|
}
|
|
@@ -629,14 +634,57 @@ function deleteMatchingFields(documentId, document2, fields) {
|
|
|
629
634
|
for (const { parent, index } of arrayRemovals)
|
|
630
635
|
parent.splice(index, 1);
|
|
631
636
|
}
|
|
632
|
-
function applyDocuments(documentId, sourceDocument, targetDocument, ignore, skip = []) {
|
|
637
|
+
function applyDocuments(documentId, sourceDocument, targetDocument, ignore, skip = [], dedupe = [], localeId) {
|
|
633
638
|
const mergedDocument = JSON.parse(JSON.stringify(sourceDocument)), clonedTarget = JSON.parse(JSON.stringify(targetDocument));
|
|
634
639
|
for (const [key, value] of Object.entries(clonedTarget))
|
|
635
640
|
mergedDocument[key] = value;
|
|
636
641
|
return forEachMatchingField(documentId, sourceDocument, ignore, (result) => {
|
|
637
642
|
JSONPointer__default.default.set(mergedDocument, result.pointer, result.value);
|
|
643
|
+
}), forEachMatchingField(documentId, sourceDocument, dedupe, (result) => {
|
|
644
|
+
JSONPointer__default.default.set(
|
|
645
|
+
mergedDocument,
|
|
646
|
+
result.pointer,
|
|
647
|
+
dedupeFieldValue(result.value, localeId)
|
|
648
|
+
);
|
|
638
649
|
}), deleteMatchingFields(documentId, mergedDocument, skip), mergedDocument;
|
|
639
650
|
}
|
|
651
|
+
function dedupeFieldValue(value, localeId) {
|
|
652
|
+
return localeId ? typeof value == "string" ? appendLocaleSuffix(value, localeId) : value && typeof value == "object" && !Array.isArray(value) && typeof value.current == "string" ? {
|
|
653
|
+
...value,
|
|
654
|
+
current: appendLocaleSuffix(value.current, localeId)
|
|
655
|
+
} : value : value;
|
|
656
|
+
}
|
|
657
|
+
function appendLocaleSuffix(value, localeId) {
|
|
658
|
+
if (!value) return value;
|
|
659
|
+
const suffix = createLocaleSuffix(localeId);
|
|
660
|
+
return !suffix || value.endsWith(suffix) ? value : `${value}${suffix}`;
|
|
661
|
+
}
|
|
662
|
+
function createLocaleSuffix(localeId) {
|
|
663
|
+
const normalized = localeId.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
664
|
+
return normalized ? `-${normalized}` : "";
|
|
665
|
+
}
|
|
666
|
+
function getPublishedId(documentId) {
|
|
667
|
+
return documentId.startsWith("drafts.") ? documentId.slice(7) : documentId;
|
|
668
|
+
}
|
|
669
|
+
function getDocumentPublishedId(document2) {
|
|
670
|
+
return getPublishedId(document2._id);
|
|
671
|
+
}
|
|
672
|
+
function dedupeDocumentsPreferDraft(documents) {
|
|
673
|
+
const byPublishedId = /* @__PURE__ */ new Map();
|
|
674
|
+
for (const document2 of documents) {
|
|
675
|
+
const publishedId = getDocumentPublishedId(document2);
|
|
676
|
+
(!byPublishedId.get(publishedId) || document2._id.startsWith("drafts.")) && byPublishedId.set(publishedId, document2);
|
|
677
|
+
}
|
|
678
|
+
return Array.from(byPublishedId.values());
|
|
679
|
+
}
|
|
680
|
+
function createTranslationStatusKey(branchId, documentId, versionId, localeId) {
|
|
681
|
+
const publishedId = getPublishedId(documentId);
|
|
682
|
+
return branchId ? `${branchId}:${publishedId}:${versionId}:${localeId}` : `${publishedId}:${versionId}:${localeId}`;
|
|
683
|
+
}
|
|
684
|
+
function createStableTranslationKey(branchId, documentId, localeId) {
|
|
685
|
+
const publishedId = getPublishedId(documentId);
|
|
686
|
+
return branchId ? `${branchId}:${publishedId}:${localeId}` : `${publishedId}:${localeId}`;
|
|
687
|
+
}
|
|
640
688
|
function deserializeDocument(document2) {
|
|
641
689
|
const deserializers = merge__default.default(
|
|
642
690
|
{ types: {} },
|
|
@@ -660,7 +708,8 @@ function serializeDocument(document2, schema2, baseLanguage) {
|
|
|
660
708
|
pluginConfig.getAdditionalSerializers()
|
|
661
709
|
), docToSerialize = stripIgnoredFields(
|
|
662
710
|
document2,
|
|
663
|
-
pluginConfig.getIgnoreFields()
|
|
711
|
+
pluginConfig.getIgnoreFields(),
|
|
712
|
+
pluginConfig.getDedupeFields()
|
|
664
713
|
);
|
|
665
714
|
return BaseDocumentSerializer(schema2).serializeDocument(
|
|
666
715
|
docToSerialize,
|
|
@@ -670,13 +719,14 @@ function serializeDocument(document2, schema2, baseLanguage) {
|
|
|
670
719
|
serializers
|
|
671
720
|
);
|
|
672
721
|
}
|
|
673
|
-
function stripIgnoredFields(document2, ignoreFields) {
|
|
674
|
-
|
|
722
|
+
function stripIgnoredFields(document2, ignoreFields, dedupeFields) {
|
|
723
|
+
const fieldsToStrip = [...ignoreFields, ...dedupeFields];
|
|
724
|
+
if (fieldsToStrip.length === 0) return document2;
|
|
675
725
|
const strippedDoc = JSON.parse(JSON.stringify(document2));
|
|
676
726
|
return deleteMatchingFields(
|
|
677
|
-
document2._id
|
|
727
|
+
getPublishedId(document2._id),
|
|
678
728
|
strippedDoc,
|
|
679
|
-
|
|
729
|
+
fieldsToStrip
|
|
680
730
|
), strippedDoc;
|
|
681
731
|
}
|
|
682
732
|
async function uploadFiles(documents, secrets) {
|
|
@@ -755,9 +805,19 @@ async function downloadTranslations(files, secrets, maxRetries = 3, retryDelay =
|
|
|
755
805
|
async function checkTranslationStatus(fileQueryData, downloadStatus, secrets) {
|
|
756
806
|
overrideConfig(secrets);
|
|
757
807
|
try {
|
|
758
|
-
const currentQueryData = fileQueryData.filter(
|
|
759
|
-
|
|
760
|
-
|
|
808
|
+
const currentQueryData = fileQueryData.filter((item) => {
|
|
809
|
+
const statusKey = createTranslationStatusKey(
|
|
810
|
+
item.branchId,
|
|
811
|
+
item.fileId,
|
|
812
|
+
item.versionId,
|
|
813
|
+
item.locale
|
|
814
|
+
), stableKey = createStableTranslationKey(
|
|
815
|
+
item.branchId,
|
|
816
|
+
item.fileId,
|
|
817
|
+
item.locale
|
|
818
|
+
);
|
|
819
|
+
return !downloadStatus.downloaded.has(statusKey) && !downloadStatus.downloaded.has(stableKey) && !downloadStatus.failed.has(statusKey) && !downloadStatus.failed.has(stableKey) && !downloadStatus.skipped.has(statusKey) && !downloadStatus.skipped.has(stableKey);
|
|
820
|
+
});
|
|
761
821
|
return currentQueryData.length === 0 ? !0 : ((await gt.queryFileData({
|
|
762
822
|
translatedFiles: currentQueryData
|
|
763
823
|
})).translatedFiles || []).filter(
|
|
@@ -768,7 +828,7 @@ async function checkTranslationStatus(fileQueryData, downloadStatus, secrets) {
|
|
|
768
828
|
}
|
|
769
829
|
}
|
|
770
830
|
const findLatestDraft = (documentId, client) => {
|
|
771
|
-
const query = "*[_id == $id || _id == $draftId]", params = { id:
|
|
831
|
+
const publishedId = getPublishedId(documentId), query = "*[_id == $id || _id == $draftId]", params = { id: publishedId, draftId: `drafts.${publishedId}` };
|
|
772
832
|
return client.fetch(query, params).then(
|
|
773
833
|
(docs) => docs.find((doc) => doc._id.startsWith("drafts.")) ?? docs[0]
|
|
774
834
|
);
|
|
@@ -780,19 +840,25 @@ function randomKey() {
|
|
|
780
840
|
return Math.random().toString(36).slice(2, 10);
|
|
781
841
|
}
|
|
782
842
|
async function createI18nDocAndPatchMetadata(sourceDocument, translatedDoc, localeId, client, translationMetadata, sourceDocumentId, languageField = "language") {
|
|
843
|
+
const publishedSourceDocumentId = getPublishedId(sourceDocumentId);
|
|
783
844
|
translatedDoc[languageField] = localeId;
|
|
784
845
|
const existingLocaleKey = translationMetadata.translations.find(
|
|
785
846
|
(translation) => translation.language === localeId
|
|
786
847
|
), operation = existingLocaleKey ? "replace" : "after", location = existingLocaleKey ? `translations[language == "${localeId}"]` : "translations[-1]", { _updatedAt, _createdAt, ...rest } = translatedDoc, appliedDocument = applyDocuments(
|
|
787
|
-
|
|
848
|
+
publishedSourceDocumentId,
|
|
788
849
|
sourceDocument,
|
|
789
850
|
rest,
|
|
790
851
|
pluginConfig.getIgnoreFields(),
|
|
791
|
-
pluginConfig.getSkipFields()
|
|
792
|
-
|
|
852
|
+
pluginConfig.getSkipFields(),
|
|
853
|
+
pluginConfig.getDedupeFields(),
|
|
854
|
+
localeId
|
|
855
|
+
), isSingleton = pluginConfig.getSingletons().includes(publishedSourceDocumentId);
|
|
793
856
|
let createDocumentPromise;
|
|
794
857
|
if (isSingleton) {
|
|
795
|
-
const translatedDocId = pluginConfig.getSingletonMapping()(
|
|
858
|
+
const translatedDocId = pluginConfig.getSingletonMapping()(
|
|
859
|
+
publishedSourceDocumentId,
|
|
860
|
+
localeId
|
|
861
|
+
);
|
|
796
862
|
createDocumentPromise = client.create({
|
|
797
863
|
...appliedDocument,
|
|
798
864
|
_type: rest._type,
|
|
@@ -804,7 +870,7 @@ async function createI18nDocAndPatchMetadata(sourceDocument, translatedDoc, loca
|
|
|
804
870
|
_type: rest._type,
|
|
805
871
|
_id: "drafts."
|
|
806
872
|
});
|
|
807
|
-
const doc = await createDocumentPromise, _ref = doc._id
|
|
873
|
+
const doc = await createDocumentPromise, _ref = getPublishedId(doc._id);
|
|
808
874
|
await client.transaction().patch(
|
|
809
875
|
translationMetadata._id,
|
|
810
876
|
(p) => p.insert(operation, location, [
|
|
@@ -825,12 +891,12 @@ async function createI18nDocAndPatchMetadata(sourceDocument, translatedDoc, loca
|
|
|
825
891
|
).commit();
|
|
826
892
|
}
|
|
827
893
|
const getOrCreateTranslationMetadata = async (documentId, baseDocument, client, baseLanguage) => {
|
|
828
|
-
const existingMetadata = await client.fetch(
|
|
894
|
+
const publishedId = getPublishedId(documentId), existingMetadata = await client.fetch(
|
|
829
895
|
`*[
|
|
830
896
|
_type == 'translation.metadata' &&
|
|
831
897
|
translations[language == $baseLanguage][0].value._ref == $id
|
|
832
898
|
][0]`,
|
|
833
|
-
{ baseLanguage, id:
|
|
899
|
+
{ baseLanguage, id: publishedId }
|
|
834
900
|
);
|
|
835
901
|
if (existingMetadata)
|
|
836
902
|
return existingMetadata;
|
|
@@ -840,7 +906,7 @@ const getOrCreateTranslationMetadata = async (documentId, baseDocument, client,
|
|
|
840
906
|
_type: "internationalizedArrayReferenceValue",
|
|
841
907
|
value: {
|
|
842
908
|
_type: "reference",
|
|
843
|
-
_ref: baseDocument._id
|
|
909
|
+
_ref: getPublishedId(baseDocument._id)
|
|
844
910
|
}
|
|
845
911
|
};
|
|
846
912
|
baseDocument._id.startsWith("drafts.") && (baseLangEntry.value = {
|
|
@@ -854,7 +920,7 @@ const getOrCreateTranslationMetadata = async (documentId, baseDocument, client,
|
|
|
854
920
|
});
|
|
855
921
|
try {
|
|
856
922
|
return await client.createIfNotExists({
|
|
857
|
-
_id: `translation.metadata.${
|
|
923
|
+
_id: `translation.metadata.${publishedId}`,
|
|
858
924
|
_type: "translation.metadata",
|
|
859
925
|
translations: [baseLangEntry]
|
|
860
926
|
});
|
|
@@ -864,14 +930,14 @@ const getOrCreateTranslationMetadata = async (documentId, baseDocument, client,
|
|
|
864
930
|
_type == 'translation.metadata' &&
|
|
865
931
|
translations[language == $baseLanguage][0].value._ref == $id
|
|
866
932
|
][0]`,
|
|
867
|
-
{ baseLanguage, id:
|
|
933
|
+
{ baseLanguage, id: publishedId }
|
|
868
934
|
);
|
|
869
935
|
if (metadata)
|
|
870
936
|
return metadata;
|
|
871
937
|
throw error;
|
|
872
938
|
}
|
|
873
939
|
}, SYSTEM_FIELDS = ["_id", "_rev", "_updatedAt", "language"], isSystemField = (field) => SYSTEM_FIELDS.includes(field);
|
|
874
|
-
async function patchI18nDoc(sourceDocumentId, i18nDocId, sourceDocument, mergedDocument, translatedFields, client) {
|
|
940
|
+
async function patchI18nDoc(sourceDocumentId, i18nDocId, sourceDocument, mergedDocument, translatedFields, client, existingDocument) {
|
|
875
941
|
const cleanedMerge = {};
|
|
876
942
|
Object.entries(mergedDocument).forEach(([key, value]) => {
|
|
877
943
|
key in translatedFields && //don't overwrite any existing system values on the i18n doc
|
|
@@ -887,8 +953,15 @@ async function patchI18nDoc(sourceDocumentId, i18nDocId, sourceDocument, mergedD
|
|
|
887
953
|
cleanedMerge,
|
|
888
954
|
pluginConfig.getIgnoreFields(),
|
|
889
955
|
pluginConfig.getSkipFields()
|
|
890
|
-
);
|
|
891
|
-
|
|
956
|
+
), dedupeFields = pluginConfig.getDedupeFields();
|
|
957
|
+
deleteMatchingFields(sourceDocumentId, appliedDocument, dedupeFields), existingDocument && forEachMatchingField(
|
|
958
|
+
sourceDocumentId,
|
|
959
|
+
existingDocument,
|
|
960
|
+
dedupeFields,
|
|
961
|
+
(result) => {
|
|
962
|
+
JSONPointer__default.default.set(appliedDocument, result.pointer, result.value);
|
|
963
|
+
}
|
|
964
|
+
), await client.patch(i18nDocId, { set: appliedDocument }).commit();
|
|
892
965
|
}
|
|
893
966
|
const documentLevelPatch = async (docInfo, translatedFields, localeId, client, languageField = "language", mergeWithTargetLocale = !1) => {
|
|
894
967
|
const baseLanguage = pluginConfig.getSourceLocale();
|
|
@@ -898,12 +971,12 @@ const documentLevelPatch = async (docInfo, translatedFields, localeId, client, l
|
|
|
898
971
|
docInfo.versionId,
|
|
899
972
|
client
|
|
900
973
|
)), baseDoc || (baseDoc = await findLatestDraft(docInfo.documentId, client));
|
|
901
|
-
const
|
|
974
|
+
const i18nDocId = (await getOrCreateTranslationMetadata(
|
|
902
975
|
docInfo.documentId,
|
|
903
976
|
baseDoc,
|
|
904
977
|
client,
|
|
905
978
|
baseLanguage
|
|
906
|
-
)
|
|
979
|
+
)).translations.find((translation) => translation.language === localeId)?.value?._ref;
|
|
907
980
|
i18nDocId && (i18nDoc = await findLatestDraft(i18nDocId, client)), mergeWithTargetLocale && i18nDoc ? baseDoc = i18nDoc : docInfo.documentId && docInfo.versionId && (baseDoc = await findDocumentAtRevision(
|
|
908
981
|
docInfo.documentId,
|
|
909
982
|
docInfo.versionId,
|
|
@@ -913,22 +986,46 @@ const documentLevelPatch = async (docInfo, translatedFields, localeId, client, l
|
|
|
913
986
|
translatedFields,
|
|
914
987
|
baseDoc
|
|
915
988
|
);
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
989
|
+
if (i18nDoc)
|
|
990
|
+
await patchI18nDoc(
|
|
991
|
+
docInfo.documentId,
|
|
992
|
+
i18nDoc._id,
|
|
993
|
+
baseDoc,
|
|
994
|
+
merged,
|
|
995
|
+
translatedFields,
|
|
996
|
+
client,
|
|
997
|
+
i18nDoc
|
|
998
|
+
);
|
|
999
|
+
else {
|
|
1000
|
+
const freshTranslationMetadata = await getOrCreateTranslationMetadata(
|
|
1001
|
+
docInfo.documentId,
|
|
1002
|
+
baseDoc,
|
|
1003
|
+
client,
|
|
1004
|
+
baseLanguage
|
|
1005
|
+
), freshI18nDocId = freshTranslationMetadata.translations.find((translation) => translation.language === localeId)?.value?._ref;
|
|
1006
|
+
if (freshI18nDocId) {
|
|
1007
|
+
const freshI18nDoc = await findLatestDraft(freshI18nDocId, client);
|
|
1008
|
+
await patchI18nDoc(
|
|
1009
|
+
docInfo.documentId,
|
|
1010
|
+
freshI18nDoc._id,
|
|
1011
|
+
baseDoc,
|
|
1012
|
+
merged,
|
|
1013
|
+
translatedFields,
|
|
1014
|
+
client,
|
|
1015
|
+
freshI18nDoc
|
|
1016
|
+
);
|
|
1017
|
+
return;
|
|
1018
|
+
}
|
|
1019
|
+
await createI18nDocAndPatchMetadata(
|
|
1020
|
+
baseDoc,
|
|
1021
|
+
merged,
|
|
1022
|
+
localeId,
|
|
1023
|
+
client,
|
|
1024
|
+
freshTranslationMetadata,
|
|
1025
|
+
docInfo.documentId,
|
|
1026
|
+
languageField
|
|
1027
|
+
);
|
|
1028
|
+
}
|
|
932
1029
|
};
|
|
933
1030
|
async function importDocument(docInfo, localeId, document2, context, mergeWithTargetLocale = !1) {
|
|
934
1031
|
const { client } = context, deserialized = deserializeDocument(document2);
|
|
@@ -969,10 +1066,12 @@ async function resolveTranslatedReferences(references, locale, client) {
|
|
|
969
1066
|
return translatedRefs;
|
|
970
1067
|
const sourceLocale = pluginConfig.getSourceLocale(), translationPairs = await client.fetch(`*[_type == "translation.metadata" && count(translations[language == $sourceLocale && value._ref in $refIds]) > 0] {
|
|
971
1068
|
"originalRef": translations[language == $sourceLocale][0].value._ref,
|
|
972
|
-
"
|
|
973
|
-
}[defined(originalRef) &&
|
|
974
|
-
for (const { originalRef,
|
|
1069
|
+
"translatedRefs": translations[language == $locale].value._ref
|
|
1070
|
+
}[defined(originalRef) && count(translatedRefs) > 0]`, { refIds, sourceLocale, locale });
|
|
1071
|
+
for (const { originalRef, translatedRefs: localeRefs } of translationPairs) {
|
|
1072
|
+
const translatedRef = localeRefs[localeRefs.length - 1];
|
|
975
1073
|
translatedRefs.set(originalRef, translatedRef);
|
|
1074
|
+
}
|
|
976
1075
|
return translatedRefs;
|
|
977
1076
|
}
|
|
978
1077
|
function updateDocumentReferences(doc, translatedRefs) {
|
|
@@ -994,34 +1093,50 @@ function updateReferencesRecursive(obj, translatedRefs) {
|
|
|
994
1093
|
}), updated;
|
|
995
1094
|
}
|
|
996
1095
|
async function findTranslatedDocumentForLocale(sourceDocumentId, localeId, client) {
|
|
997
|
-
const cleanDocId = sourceDocumentId.
|
|
998
|
-
return await client.fetch(`*[
|
|
1096
|
+
const cleanDocId = getPublishedId(sourceDocumentId), translatedDocIds = await client.fetch(`*[
|
|
999
1097
|
_type == "translation.metadata" &&
|
|
1000
1098
|
(
|
|
1001
1099
|
translations[language == $sourceLocale][0].value._ref == $cleanDocId
|
|
1002
1100
|
) &&
|
|
1003
1101
|
defined(translations[language == $localeId])
|
|
1004
|
-
][0].translations[language == $localeId]
|
|
1102
|
+
][0].translations[language == $localeId].value._ref`, {
|
|
1005
1103
|
sourceLocale: pluginConfig.getSourceLocale(),
|
|
1006
1104
|
cleanDocId,
|
|
1007
1105
|
localeId
|
|
1008
|
-
})
|
|
1106
|
+
}), translatedDocId = translatedDocIds?.[translatedDocIds.length - 1];
|
|
1107
|
+
return translatedDocId && await findLatestDraft(translatedDocId, client) || null;
|
|
1009
1108
|
}
|
|
1010
1109
|
async function findDocument(documentId, client) {
|
|
1011
1110
|
const query = "*[_id == $id]", params = { id: documentId };
|
|
1012
1111
|
return (await client.fetch(query, params))[0] || null;
|
|
1013
1112
|
}
|
|
1014
1113
|
async function processBatch(items, processor, options = {}) {
|
|
1015
|
-
const {
|
|
1114
|
+
const {
|
|
1115
|
+
batchSize = 20,
|
|
1116
|
+
getConcurrencyKey,
|
|
1117
|
+
onProgress,
|
|
1118
|
+
onItemSuccess,
|
|
1119
|
+
onItemFailure
|
|
1120
|
+
} = options;
|
|
1016
1121
|
let successCount = 0, failureCount = 0;
|
|
1017
1122
|
const successfulItems = [], failedItems = [];
|
|
1018
1123
|
for (let i = 0; i < items.length; i += batchSize) {
|
|
1019
|
-
const batch = items.slice(i, i + batchSize), batchPromises = batch.map(async (item) => {
|
|
1124
|
+
const batch = items.slice(i, i + batchSize), pendingByKey = /* @__PURE__ */ new Map(), batchPromises = batch.map(async (item) => {
|
|
1125
|
+
const concurrencyKey = getConcurrencyKey?.(item), pending = concurrencyKey ? pendingByKey.get(concurrencyKey) : void 0;
|
|
1126
|
+
let release = () => {
|
|
1127
|
+
};
|
|
1128
|
+
const current = new Promise((resolve) => {
|
|
1129
|
+
release = resolve;
|
|
1130
|
+
});
|
|
1131
|
+
concurrencyKey && pendingByKey.set(concurrencyKey, current);
|
|
1020
1132
|
try {
|
|
1133
|
+
pending && await pending;
|
|
1021
1134
|
const result = await processor(item);
|
|
1022
1135
|
return onItemSuccess?.(item, result), { success: !0, item, result };
|
|
1023
1136
|
} catch (error) {
|
|
1024
1137
|
return onItemFailure?.(item, error), { success: !1, item, error };
|
|
1138
|
+
} finally {
|
|
1139
|
+
release(), concurrencyKey && pendingByKey.get(concurrencyKey) === current && pendingByKey.delete(concurrencyKey);
|
|
1025
1140
|
}
|
|
1026
1141
|
});
|
|
1027
1142
|
(await Promise.all(batchPromises)).forEach((result) => {
|
|
@@ -1044,6 +1159,11 @@ async function processImportBatch(items, options = {}) {
|
|
|
1044
1159
|
), item.key),
|
|
1045
1160
|
{
|
|
1046
1161
|
...options,
|
|
1162
|
+
getConcurrencyKey: (item) => createStableTranslationKey(
|
|
1163
|
+
void 0,
|
|
1164
|
+
item.docInfo.documentId,
|
|
1165
|
+
item.locale
|
|
1166
|
+
),
|
|
1047
1167
|
onItemSuccess: (item, key) => {
|
|
1048
1168
|
successfulImports.push(key), options.onItemSuccess?.(item, key);
|
|
1049
1169
|
},
|
|
@@ -1059,15 +1179,25 @@ async function processImportBatch(items, options = {}) {
|
|
|
1059
1179
|
};
|
|
1060
1180
|
}
|
|
1061
1181
|
async function getReadyFilesForImport(translationStatuses, options = {}) {
|
|
1062
|
-
const { filterReadyFiles = () => !0 } = options,
|
|
1182
|
+
const { filterReadyFiles = () => !0 } = options, readyFilesByDocumentLocale = /* @__PURE__ */ new Map();
|
|
1063
1183
|
for (const [key, status] of translationStatuses.entries())
|
|
1064
|
-
status.isReady && filterReadyFiles(key, status)
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1184
|
+
if (status.isReady && status.fileData && filterReadyFiles(key, status)) {
|
|
1185
|
+
const fileData = {
|
|
1186
|
+
fileId: getPublishedId(status.fileData.fileId),
|
|
1187
|
+
versionId: status.fileData.versionId,
|
|
1188
|
+
branchId: status.fileData.branchId,
|
|
1189
|
+
locale: status.fileData.locale
|
|
1190
|
+
};
|
|
1191
|
+
readyFilesByDocumentLocale.set(
|
|
1192
|
+
createStableTranslationKey(
|
|
1193
|
+
fileData.branchId,
|
|
1194
|
+
fileData.fileId,
|
|
1195
|
+
fileData.locale
|
|
1196
|
+
),
|
|
1197
|
+
fileData
|
|
1198
|
+
);
|
|
1199
|
+
}
|
|
1200
|
+
return Array.from(readyFilesByDocumentLocale.values());
|
|
1071
1201
|
}
|
|
1072
1202
|
async function importTranslations(readyFiles, secrets, translationContext, options = {}) {
|
|
1073
1203
|
if (readyFiles.length === 0)
|
|
@@ -1099,7 +1229,7 @@ async function publishDocument(documentId, client) {
|
|
|
1099
1229
|
{
|
|
1100
1230
|
actionType: "sanity.action.document.publish",
|
|
1101
1231
|
draftId: documentId,
|
|
1102
|
-
publishedId: documentId
|
|
1232
|
+
publishedId: getPublishedId(documentId)
|
|
1103
1233
|
},
|
|
1104
1234
|
{}
|
|
1105
1235
|
);
|
|
@@ -1147,9 +1277,13 @@ const getLocales = async (secrets) => pluginConfig.getLocales().map((locale) =>
|
|
|
1147
1277
|
downloaded: /* @__PURE__ */ new Set(),
|
|
1148
1278
|
failed: /* @__PURE__ */ new Set(),
|
|
1149
1279
|
skipped: /* @__PURE__ */ new Set()
|
|
1150
|
-
}), [translationStatuses, setTranslationStatuses] = o.useState(/* @__PURE__ */ new Map()), [isRefreshing, setIsRefreshing] = o.useState(!1), client = useClient(), schema2 = sanity.useSchema(), translationContext = { client, schema: schema2 }, toast = ui.useToast(), { loading: loadingSecrets, secrets } = useSecrets(
|
|
1280
|
+
}), downloadStatusRef = o.useRef(downloadStatus), [translationStatuses, setTranslationStatuses] = o.useState(/* @__PURE__ */ new Map()), [isRefreshing, setIsRefreshing] = o.useState(!1), client = useClient(), schema2 = sanity.useSchema(), translationContext = { client, schema: schema2 }, toast = ui.useToast(), { loading: loadingSecrets, secrets } = useSecrets(
|
|
1151
1281
|
pluginConfig.getSecretsNamespace()
|
|
1152
|
-
), [branchId, setBranchId] = o.useState(void 0)
|
|
1282
|
+
), [branchId, setBranchId] = o.useState(void 0);
|
|
1283
|
+
o.useEffect(() => {
|
|
1284
|
+
downloadStatusRef.current = downloadStatus;
|
|
1285
|
+
}, [downloadStatus]);
|
|
1286
|
+
const fetchDocuments = o.useCallback(async () => {
|
|
1153
1287
|
setLoadingDocuments(!0);
|
|
1154
1288
|
try {
|
|
1155
1289
|
if (singleDocument) {
|
|
@@ -1160,7 +1294,7 @@ const getLocales = async (secrets) => pluginConfig.getLocales().map((locale) =>
|
|
|
1160
1294
|
let query;
|
|
1161
1295
|
filterConditions.length === 0 ? query = `*[!(_type in ["system.group"]) && !(_id in path("_.**")) && ${languageFilter}]` : query = `*[!(_type in ["system.group"]) && !(_id in path("_.**")) && (${filterConditions.join(" || ")}) && ${languageFilter}]`;
|
|
1162
1296
|
const docs = await client.fetch(query);
|
|
1163
|
-
setDocuments(docs);
|
|
1297
|
+
setDocuments(dedupeDocumentsPreferDraft(docs));
|
|
1164
1298
|
} catch {
|
|
1165
1299
|
toast.push({
|
|
1166
1300
|
title: "Error fetching documents",
|
|
@@ -1185,9 +1319,7 @@ const getLocales = async (secrets) => pluginConfig.getLocales().map((locale) =>
|
|
|
1185
1319
|
}, [secrets]), fetchExistingTranslations = o.useCallback(async () => {
|
|
1186
1320
|
if (!(!documents.length || !locales.length))
|
|
1187
1321
|
try {
|
|
1188
|
-
const sourceLocale = pluginConfig.getSourceLocale(), availableLocaleIds = locales.filter((locale) => locale.enabled !== !1).map((locale) => locale.localeId), documentIds = documents.map(
|
|
1189
|
-
(doc) => doc._id?.replace("drafts.", "") || doc._id
|
|
1190
|
-
), existingMetadata = await client.fetch(`*[
|
|
1322
|
+
const sourceLocale = pluginConfig.getSourceLocale(), availableLocaleIds = locales.filter((locale) => locale.enabled !== !1).map((locale) => locale.localeId), documentIds = documents.map(getDocumentPublishedId), existingMetadata = await client.fetch(`*[
|
|
1191
1323
|
_type == 'translation.metadata' &&
|
|
1192
1324
|
translations[language == $sourceLocale][0].value._ref in $documentIds
|
|
1193
1325
|
] {
|
|
@@ -1200,7 +1332,13 @@ const getLocales = async (secrets) => pluginConfig.getLocales().map((locale) =>
|
|
|
1200
1332
|
}), existing = /* @__PURE__ */ new Set();
|
|
1201
1333
|
existingMetadata.forEach((metadata) => {
|
|
1202
1334
|
metadata.existingTranslations?.forEach((localeId) => {
|
|
1203
|
-
localeId !== sourceLocale && existing.add(
|
|
1335
|
+
localeId !== sourceLocale && existing.add(
|
|
1336
|
+
createStableTranslationKey(
|
|
1337
|
+
void 0,
|
|
1338
|
+
metadata.sourceDocId,
|
|
1339
|
+
localeId
|
|
1340
|
+
)
|
|
1341
|
+
);
|
|
1204
1342
|
});
|
|
1205
1343
|
}), setExistingTranslations(existing);
|
|
1206
1344
|
} catch (error) {
|
|
@@ -1224,7 +1362,7 @@ const getLocales = async (secrets) => pluginConfig.getLocales().map((locale) =>
|
|
|
1224
1362
|
);
|
|
1225
1363
|
return {
|
|
1226
1364
|
info: {
|
|
1227
|
-
documentId: doc
|
|
1365
|
+
documentId: getDocumentPublishedId(doc),
|
|
1228
1366
|
versionId: doc._rev
|
|
1229
1367
|
},
|
|
1230
1368
|
serializedDocument: serialized
|
|
@@ -1329,7 +1467,11 @@ const getLocales = async (secrets) => pluginConfig.getLocales().map((locale) =>
|
|
|
1329
1467
|
return existingMetadata.forEach((metadata) => {
|
|
1330
1468
|
metadata.existingTranslations?.forEach((localeId) => {
|
|
1331
1469
|
localeId !== sourceLocale && existing.add(
|
|
1332
|
-
|
|
1470
|
+
createStableTranslationKey(
|
|
1471
|
+
branchId2,
|
|
1472
|
+
metadata.sourceDocId,
|
|
1473
|
+
localeId
|
|
1474
|
+
)
|
|
1333
1475
|
);
|
|
1334
1476
|
});
|
|
1335
1477
|
}), existing;
|
|
@@ -1339,14 +1481,18 @@ const getLocales = async (secrets) => pluginConfig.getLocales().map((locale) =>
|
|
|
1339
1481
|
if (!(!secrets || documents.length === 0 || !branchId)) {
|
|
1340
1482
|
setIsBusy(!0);
|
|
1341
1483
|
try {
|
|
1342
|
-
const availableLocaleIds = locales.filter((locale) => locale.enabled !== !1).map((locale) => locale.localeId), documentIds = documents.map(
|
|
1343
|
-
(doc) => doc._id?.replace("drafts.", "") || doc._id
|
|
1344
|
-
), existingTranslations2 = await getExistingTranslations(
|
|
1484
|
+
const availableLocaleIds = locales.filter((locale) => locale.enabled !== !1).map((locale) => locale.localeId), documentIds = documents.map(getDocumentPublishedId), existingTranslations2 = await getExistingTranslations(
|
|
1345
1485
|
documentIds,
|
|
1346
1486
|
availableLocaleIds,
|
|
1347
1487
|
branchId
|
|
1348
1488
|
), readyFiles = await getReadyFilesForImport(translationStatuses, {
|
|
1349
|
-
filterReadyFiles: (
|
|
1489
|
+
filterReadyFiles: (_key, status) => !existingTranslations2.has(
|
|
1490
|
+
createStableTranslationKey(
|
|
1491
|
+
branchId,
|
|
1492
|
+
status.fileData.fileId,
|
|
1493
|
+
status.fileData.locale
|
|
1494
|
+
)
|
|
1495
|
+
)
|
|
1350
1496
|
});
|
|
1351
1497
|
if (readyFiles.length === 0) {
|
|
1352
1498
|
toast.push({
|
|
@@ -1425,7 +1571,7 @@ const getLocales = async (secrets) => pluginConfig.getLocales().map((locale) =>
|
|
|
1425
1571
|
const availableLocaleIds = locales.filter((locale) => locale.enabled !== !1).map((locale) => locale.localeId), fileQueryData = [];
|
|
1426
1572
|
for (const doc of documents)
|
|
1427
1573
|
for (const localeId of availableLocaleIds) {
|
|
1428
|
-
const documentId = doc
|
|
1574
|
+
const documentId = getDocumentPublishedId(doc);
|
|
1429
1575
|
fileQueryData.push({
|
|
1430
1576
|
versionId: doc._rev,
|
|
1431
1577
|
fileId: documentId,
|
|
@@ -1435,19 +1581,29 @@ const getLocales = async (secrets) => pluginConfig.getLocales().map((locale) =>
|
|
|
1435
1581
|
}
|
|
1436
1582
|
const readyTranslations = await checkTranslationStatus(
|
|
1437
1583
|
fileQueryData,
|
|
1438
|
-
|
|
1584
|
+
downloadStatusRef.current,
|
|
1439
1585
|
secrets
|
|
1440
1586
|
);
|
|
1441
1587
|
setTranslationStatuses((prevStatuses) => {
|
|
1442
1588
|
const newStatuses = /* @__PURE__ */ new Map();
|
|
1443
1589
|
for (const doc of documents)
|
|
1444
1590
|
for (const localeId of availableLocaleIds) {
|
|
1445
|
-
const documentId = doc
|
|
1591
|
+
const documentId = getDocumentPublishedId(doc), versionId = doc._rev, key = createTranslationStatusKey(
|
|
1592
|
+
branchId,
|
|
1593
|
+
documentId,
|
|
1594
|
+
versionId,
|
|
1595
|
+
localeId
|
|
1596
|
+
);
|
|
1446
1597
|
newStatuses.set(key, { progress: 0, isReady: !1 });
|
|
1447
1598
|
}
|
|
1448
1599
|
if (Array.isArray(readyTranslations))
|
|
1449
1600
|
for (const translation of readyTranslations) {
|
|
1450
|
-
const key =
|
|
1601
|
+
const key = createTranslationStatusKey(
|
|
1602
|
+
branchId,
|
|
1603
|
+
translation.fileId,
|
|
1604
|
+
translation.versionId,
|
|
1605
|
+
translation.locale
|
|
1606
|
+
);
|
|
1451
1607
|
newStatuses.set(key, {
|
|
1452
1608
|
progress: 100,
|
|
1453
1609
|
isReady: !0,
|
|
@@ -1478,7 +1634,12 @@ const getLocales = async (secrets) => pluginConfig.getLocales().map((locale) =>
|
|
|
1478
1634
|
}, [secrets, documents, locales, branchId]), handleImportDocument = o.useCallback(
|
|
1479
1635
|
async (documentId, versionId, localeId) => {
|
|
1480
1636
|
if (!secrets) return;
|
|
1481
|
-
const key =
|
|
1637
|
+
const key = createTranslationStatusKey(
|
|
1638
|
+
branchId,
|
|
1639
|
+
documentId,
|
|
1640
|
+
versionId,
|
|
1641
|
+
localeId
|
|
1642
|
+
), status = translationStatuses.get(key);
|
|
1482
1643
|
if (!status?.isReady || !status.fileData) {
|
|
1483
1644
|
toast.push({
|
|
1484
1645
|
title: `Translation not ready for ${documentId} (${localeId})`,
|
|
@@ -1488,7 +1649,7 @@ const getLocales = async (secrets) => pluginConfig.getLocales().map((locale) =>
|
|
|
1488
1649
|
return;
|
|
1489
1650
|
}
|
|
1490
1651
|
const document2 = documents.find(
|
|
1491
|
-
(doc) => (doc
|
|
1652
|
+
(doc) => getDocumentPublishedId(doc) === getPublishedId(documentId)
|
|
1492
1653
|
);
|
|
1493
1654
|
if (!document2) {
|
|
1494
1655
|
toast.push({
|
|
@@ -1513,7 +1674,7 @@ const getLocales = async (secrets) => pluginConfig.getLocales().map((locale) =>
|
|
|
1513
1674
|
if (downloadedFiles.length > 0)
|
|
1514
1675
|
try {
|
|
1515
1676
|
const docInfo = {
|
|
1516
|
-
documentId,
|
|
1677
|
+
documentId: getPublishedId(documentId),
|
|
1517
1678
|
versionId: document2._rev
|
|
1518
1679
|
};
|
|
1519
1680
|
await importDocument(
|
|
@@ -1525,7 +1686,12 @@ const getLocales = async (secrets) => pluginConfig.getLocales().map((locale) =>
|
|
|
1525
1686
|
), setDownloadStatus((prev2) => ({
|
|
1526
1687
|
...prev2,
|
|
1527
1688
|
downloaded: /* @__PURE__ */ new Set([...prev2.downloaded, key])
|
|
1528
|
-
})), setImportedTranslations((prev2) => /* @__PURE__ */ new Set([...prev2, key])),
|
|
1689
|
+
})), setImportedTranslations((prev2) => /* @__PURE__ */ new Set([...prev2, key])), setExistingTranslations(
|
|
1690
|
+
(prev2) => /* @__PURE__ */ new Set([
|
|
1691
|
+
...prev2,
|
|
1692
|
+
createStableTranslationKey(branchId, documentId, localeId)
|
|
1693
|
+
])
|
|
1694
|
+
), toast.push({
|
|
1529
1695
|
title: `Successfully imported translation for ${documentId} (${localeId})`,
|
|
1530
1696
|
status: "success",
|
|
1531
1697
|
closable: !0
|
|
@@ -1630,7 +1796,10 @@ const getLocales = async (secrets) => pluginConfig.getLocales().map((locale) =>
|
|
|
1630
1796
|
if (!secrets || documents.length === 0) return 0;
|
|
1631
1797
|
setIsBusy(!0);
|
|
1632
1798
|
try {
|
|
1633
|
-
const sourceLocale = pluginConfig.getSourceLocale(),
|
|
1799
|
+
const sourceLocale = pluginConfig.getSourceLocale(), sourceDocumentIds = documents.map(getDocumentPublishedId), publishedDocumentIds = await client.fetch(
|
|
1800
|
+
"*[_id in $sourceDocumentIds]._id",
|
|
1801
|
+
{ sourceDocumentIds }
|
|
1802
|
+
);
|
|
1634
1803
|
if (publishedDocumentIds.length === 0)
|
|
1635
1804
|
return toast.push({
|
|
1636
1805
|
title: "No published source documents found to publish translations for",
|
|
@@ -1649,19 +1818,19 @@ const getLocales = async (secrets) => pluginConfig.getLocales().map((locale) =>
|
|
|
1649
1818
|
}`, {
|
|
1650
1819
|
sourceLocale,
|
|
1651
1820
|
publishedDocumentIds
|
|
1652
|
-
}), translationDocIds =
|
|
1821
|
+
}), translationDocIds = /* @__PURE__ */ new Set();
|
|
1653
1822
|
if (translationMetadata.forEach((metadata) => {
|
|
1654
1823
|
metadata.translationDocs?.forEach((translation) => {
|
|
1655
|
-
translation.docId && translationDocIds.
|
|
1824
|
+
translation.docId && translationDocIds.add(translation.docId);
|
|
1656
1825
|
});
|
|
1657
|
-
}), translationDocIds.
|
|
1826
|
+
}), translationDocIds.size === 0)
|
|
1658
1827
|
return toast.push({
|
|
1659
1828
|
title: "No translation documents found to publish",
|
|
1660
1829
|
status: "warning",
|
|
1661
1830
|
closable: !0
|
|
1662
1831
|
}), 0;
|
|
1663
1832
|
const translatedDocumentIds = await publishTranslations(
|
|
1664
|
-
translationDocIds,
|
|
1833
|
+
Array.from(translationDocIds),
|
|
1665
1834
|
client
|
|
1666
1835
|
);
|
|
1667
1836
|
return toast.push({
|
|
@@ -1686,8 +1855,15 @@ const getLocales = async (secrets) => pluginConfig.getLocales().map((locale) =>
|
|
|
1686
1855
|
}, [fetchLocales, secrets]), o.useEffect(() => {
|
|
1687
1856
|
documents.length > 0 && locales.length > 0 && fetchExistingTranslations();
|
|
1688
1857
|
}, [fetchExistingTranslations]), o.useEffect(() => {
|
|
1689
|
-
documents.length > 0 && locales.length > 0 && secrets && !loadingDocuments && handleRefreshAll();
|
|
1690
|
-
}, [
|
|
1858
|
+
documents.length > 0 && locales.length > 0 && secrets && !loadingDocuments && branchId && handleRefreshAll();
|
|
1859
|
+
}, [
|
|
1860
|
+
documents,
|
|
1861
|
+
locales,
|
|
1862
|
+
secrets,
|
|
1863
|
+
loadingDocuments,
|
|
1864
|
+
branchId,
|
|
1865
|
+
handleRefreshAll
|
|
1866
|
+
]), o.useEffect(() => {
|
|
1691
1867
|
if (!autoRefresh || documents.length === 0 || !secrets) return;
|
|
1692
1868
|
const interval = setInterval(async () => {
|
|
1693
1869
|
await handleRefreshAll();
|
|
@@ -1776,7 +1952,7 @@ const LanguageStatus = ({
|
|
|
1776
1952
|
importFile,
|
|
1777
1953
|
isImported = !1
|
|
1778
1954
|
}) => {
|
|
1779
|
-
const [isBusy, setIsBusy] = o.useState(!1), handleImport = o.useCallback(async () => {
|
|
1955
|
+
const [isBusy, setIsBusy] = o.useState(!1), displayedProgress = isImported && progress < 100 ? 100 : progress, handleImport = o.useCallback(async () => {
|
|
1780
1956
|
setIsBusy(!0);
|
|
1781
1957
|
try {
|
|
1782
1958
|
await importFile();
|
|
@@ -1786,7 +1962,7 @@ const LanguageStatus = ({
|
|
|
1786
1962
|
}, [importFile, setIsBusy]);
|
|
1787
1963
|
return /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { shadow: 1, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Grid, { columns: 5, gap: 3, padding: 3, children: [
|
|
1788
1964
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Flex, { columnStart: 1, columnEnd: 3, align: "center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "bold", size: 1, children: title }) }),
|
|
1789
|
-
typeof
|
|
1965
|
+
typeof displayedProgress == "number" ? /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, { columnStart: 3, columnEnd: 5, align: "center", children: /* @__PURE__ */ jsxRuntime.jsx(ProgressBar, { progress: displayedProgress }) }) : null,
|
|
1790
1966
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, { columnStart: 5, columnEnd: 6, children: isImported ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { align: "center", justify: "center", style: { color: "green" }, children: [
|
|
1791
1967
|
/* @__PURE__ */ jsxRuntime.jsx(icons.CheckmarkCircleIcon, {}),
|
|
1792
1968
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, style: { marginLeft: "4px" }, children: "Imported" })
|
|
@@ -3013,12 +3189,17 @@ const WrapText = dt(ui.Box)`
|
|
|
3013
3189
|
return locales.filter(
|
|
3014
3190
|
(locale) => locale.enabled !== !1 && locale.localeId !== sourceLocale
|
|
3015
3191
|
);
|
|
3016
|
-
}, [locales]), documentId = o.useMemo(() => document2 ? document2
|
|
3192
|
+
}, [locales]), documentId = o.useMemo(() => document2 ? getDocumentPublishedId(document2) : null, [document2]), handleImportTranslations = o.useCallback(
|
|
3017
3193
|
async (options = {}) => {
|
|
3018
3194
|
const { autoOnly = !1 } = options;
|
|
3019
3195
|
if (isImporting || !documentId || autoOnly && !autoImport) return;
|
|
3020
3196
|
const readyTranslations = availableLocales.filter((locale) => {
|
|
3021
|
-
const key =
|
|
3197
|
+
const key = createTranslationStatusKey(
|
|
3198
|
+
branchId,
|
|
3199
|
+
documentId,
|
|
3200
|
+
document2._rev,
|
|
3201
|
+
locale.localeId
|
|
3202
|
+
);
|
|
3022
3203
|
return translationStatuses.get(key)?.isReady && !importedTranslations.has(key);
|
|
3023
3204
|
});
|
|
3024
3205
|
if (readyTranslations.length !== 0) {
|
|
@@ -3139,7 +3320,12 @@ const WrapText = dt(ui.Box)`
|
|
|
3139
3320
|
] })
|
|
3140
3321
|
] }),
|
|
3141
3322
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, { children: availableLocales.map((locale) => {
|
|
3142
|
-
const key =
|
|
3323
|
+
const key = createTranslationStatusKey(
|
|
3324
|
+
branchId,
|
|
3325
|
+
documentId,
|
|
3326
|
+
document2._rev,
|
|
3327
|
+
locale.localeId
|
|
3328
|
+
), status = translationStatuses.get(key), progress = status?.progress || 0, isImported = importedTranslations.has(key);
|
|
3143
3329
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3144
3330
|
LanguageStatus,
|
|
3145
3331
|
{
|
|
@@ -3169,7 +3355,12 @@ const WrapText = dt(ui.Box)`
|
|
|
3169
3355
|
text: isImporting ? "Importing..." : "Import All",
|
|
3170
3356
|
icon: icons.DownloadIcon,
|
|
3171
3357
|
disabled: isImporting || availableLocales.every((locale) => {
|
|
3172
|
-
const key =
|
|
3358
|
+
const key = createTranslationStatusKey(
|
|
3359
|
+
branchId,
|
|
3360
|
+
documentId,
|
|
3361
|
+
document2._rev,
|
|
3362
|
+
locale.localeId
|
|
3363
|
+
);
|
|
3173
3364
|
return !translationStatuses.get(key)?.isReady || importedTranslations.has(key);
|
|
3174
3365
|
}),
|
|
3175
3366
|
style: { minWidth: "180px" }
|
|
@@ -3191,12 +3382,22 @@ const WrapText = dt(ui.Box)`
|
|
|
3191
3382
|
"Imported",
|
|
3192
3383
|
" ",
|
|
3193
3384
|
availableLocales.filter((locale) => {
|
|
3194
|
-
const key =
|
|
3385
|
+
const key = createTranslationStatusKey(
|
|
3386
|
+
branchId,
|
|
3387
|
+
documentId,
|
|
3388
|
+
document2._rev,
|
|
3389
|
+
locale.localeId
|
|
3390
|
+
);
|
|
3195
3391
|
return importedTranslations.has(key);
|
|
3196
3392
|
}).length,
|
|
3197
3393
|
"/",
|
|
3198
3394
|
availableLocales.filter((locale) => {
|
|
3199
|
-
const key =
|
|
3395
|
+
const key = createTranslationStatusKey(
|
|
3396
|
+
branchId,
|
|
3397
|
+
documentId,
|
|
3398
|
+
document2._rev,
|
|
3399
|
+
locale.localeId
|
|
3400
|
+
);
|
|
3200
3401
|
return translationStatuses.get(key)?.isReady;
|
|
3201
3402
|
}).length
|
|
3202
3403
|
] })
|
|
@@ -3312,11 +3513,16 @@ const WrapText = dt(ui.Box)`
|
|
|
3312
3513
|
} = useTranslations();
|
|
3313
3514
|
return loadingDocuments ? /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, { align: "center", justify: "center", padding: 4, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Spinner, {}) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { style: { maxHeight: "60vh", overflowY: "auto" }, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { space: 2, children: documents.map((document2) => /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { shadow: 1, padding: 3, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
|
|
3314
3515
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Flex, { justify: "space-between", align: "flex-start", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Box, { flex: 1, children: [
|
|
3315
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "semibold", size: 1, children: document2
|
|
3516
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "semibold", size: 1, children: getDocumentPublishedId(document2) }),
|
|
3316
3517
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 0, muted: !0, style: { marginTop: "2px" }, children: document2._type })
|
|
3317
3518
|
] }) }),
|
|
3318
3519
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { space: 2, children: locales.length > 0 ? locales.filter((locale) => locale.enabled !== !1).map((locale) => {
|
|
3319
|
-
const documentId =
|
|
3520
|
+
const documentId = getDocumentPublishedId(document2), key = createTranslationStatusKey(
|
|
3521
|
+
branchId,
|
|
3522
|
+
documentId,
|
|
3523
|
+
document2._rev,
|
|
3524
|
+
locale.localeId
|
|
3525
|
+
), status = translationStatuses.get(key), isDownloaded = downloadStatus.downloaded.has(key), isImported = importedTranslations.has(key);
|
|
3320
3526
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3321
3527
|
LanguageStatus,
|
|
3322
3528
|
{
|
|
@@ -3697,6 +3903,7 @@ const WrapText = dt(ui.Box)`
|
|
|
3697
3903
|
singletons,
|
|
3698
3904
|
singletonMapping,
|
|
3699
3905
|
ignoreFields,
|
|
3906
|
+
dedupeFields,
|
|
3700
3907
|
skipFields,
|
|
3701
3908
|
translateDocuments,
|
|
3702
3909
|
secretsNamespace = SECRETS_NAMESPACE,
|
|
@@ -3717,6 +3924,7 @@ const WrapText = dt(ui.Box)`
|
|
|
3717
3924
|
// singletons is a string array of singleton document ids
|
|
3718
3925
|
singletonMapping || ((sourceDocumentId, locale) => `${sourceDocumentId}-${locale}`),
|
|
3719
3926
|
ignoreFields || [],
|
|
3927
|
+
dedupeFields || [],
|
|
3720
3928
|
skipFields || [],
|
|
3721
3929
|
normalizedTranslateDocuments || [],
|
|
3722
3930
|
additionalStopTypes,
|