gt-sanity 1.0.11 → 1.1.1
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 +125 -112
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +125 -112
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/adapter/getTranslation.ts +1 -1
- package/src/adapter/types.ts +12 -0
- package/src/components/TranslationsProvider.tsx +83 -58
- package/src/components/page/TranslationsTable.tsx +4 -2
- package/src/components/shared/SingleDocumentView.tsx +4 -2
- package/src/components/tab/TranslationView.tsx +26 -36
- package/src/translation/checkTranslationStatus.ts +7 -4
- package/src/translation/downloadTranslations.ts +13 -38
- package/src/translation/initProject.ts +8 -5
- package/src/utils/importUtils.ts +17 -37
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gt-sanity",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "General Translation integration with Sanity",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"jsonpath-plus": "^10.3.0",
|
|
52
52
|
"jsonpointer": "^5.0.1",
|
|
53
53
|
"lodash.merge": "^4.6.2",
|
|
54
|
-
"generaltranslation": "
|
|
54
|
+
"generaltranslation": "8.0.1"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@portabletext/types": "^2.0.15",
|
|
@@ -11,7 +11,7 @@ export const getTranslation: Adapter['getTranslation'] = async (
|
|
|
11
11
|
return '';
|
|
12
12
|
}
|
|
13
13
|
overrideConfig(secrets);
|
|
14
|
-
const text = await gt.
|
|
14
|
+
const text = await gt.downloadFile({
|
|
15
15
|
fileId: documentInfo.documentId,
|
|
16
16
|
versionId: documentInfo.versionId || undefined,
|
|
17
17
|
locale: localeId,
|
package/src/adapter/types.ts
CHANGED
|
@@ -7,3 +7,15 @@ export type TranslateDocumentFilter = {
|
|
|
7
7
|
documentId?: string;
|
|
8
8
|
type?: string;
|
|
9
9
|
};
|
|
10
|
+
|
|
11
|
+
export type FileProperties = {
|
|
12
|
+
versionId: string;
|
|
13
|
+
fileId: string;
|
|
14
|
+
locale: string;
|
|
15
|
+
branchId: string;
|
|
16
|
+
};
|
|
17
|
+
export type TranslationStatus = {
|
|
18
|
+
progress: number;
|
|
19
|
+
isReady: boolean;
|
|
20
|
+
fileData: FileProperties;
|
|
21
|
+
};
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
TranslationLocale,
|
|
17
17
|
TranslationFunctionContext,
|
|
18
18
|
} from '../types';
|
|
19
|
-
import { pluginConfig } from '../adapter/core';
|
|
19
|
+
import { gt, overrideConfig, pluginConfig } from '../adapter/core';
|
|
20
20
|
import { serializeDocument } from '../utils/serialize';
|
|
21
21
|
import { uploadFiles } from '../translation/uploadFiles';
|
|
22
22
|
import { initProject } from '../translation/initProject';
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
import { processBatch } from '../utils/batchProcessor';
|
|
35
35
|
import { publishTranslations } from '../sanity-api/publishDocuments';
|
|
36
36
|
import { getLocales } from '../adapter/getLocales';
|
|
37
|
+
import type { FileProperties, TranslationStatus } from '../adapter/types';
|
|
37
38
|
|
|
38
39
|
interface ImportProgress {
|
|
39
40
|
current: number;
|
|
@@ -47,18 +48,15 @@ interface DownloadStatus {
|
|
|
47
48
|
skipped: Set<string>;
|
|
48
49
|
}
|
|
49
50
|
|
|
50
|
-
interface TranslationStatus {
|
|
51
|
-
progress: number;
|
|
52
|
-
isReady: boolean;
|
|
53
|
-
translationId?: string;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
51
|
interface TranslationsContextType {
|
|
57
52
|
// State
|
|
58
53
|
isBusy: boolean;
|
|
59
54
|
documents: SanityDocument[];
|
|
60
55
|
locales: TranslationLocale[];
|
|
61
56
|
autoRefresh: boolean;
|
|
57
|
+
autoImport: boolean;
|
|
58
|
+
autoPatchReferences: boolean;
|
|
59
|
+
autoPublish: boolean;
|
|
62
60
|
loadingDocuments: boolean;
|
|
63
61
|
importProgress: ImportProgress;
|
|
64
62
|
importedTranslations: Set<string>;
|
|
@@ -68,15 +66,23 @@ interface TranslationsContextType {
|
|
|
68
66
|
isRefreshing: boolean;
|
|
69
67
|
loadingSecrets: boolean;
|
|
70
68
|
secrets: Secrets | null;
|
|
69
|
+
branchId: string | undefined;
|
|
71
70
|
|
|
72
71
|
// Actions
|
|
73
72
|
setLocales: (locales: TranslationLocale[]) => void;
|
|
74
73
|
setAutoRefresh: (value: boolean) => void;
|
|
74
|
+
setAutoImport: (value: boolean) => void;
|
|
75
|
+
setAutoPatchReferences: (value: boolean) => void;
|
|
76
|
+
setAutoPublish: (value: boolean) => void;
|
|
75
77
|
handleTranslateAll: () => Promise<void>;
|
|
76
78
|
handleImportAll: () => Promise<void>;
|
|
77
79
|
handleImportMissing: () => Promise<void>;
|
|
78
80
|
handleRefreshAll: () => Promise<void>;
|
|
79
|
-
handleImportDocument: (
|
|
81
|
+
handleImportDocument: (
|
|
82
|
+
documentId: string,
|
|
83
|
+
versionId: string,
|
|
84
|
+
localeId: string
|
|
85
|
+
) => Promise<void>;
|
|
80
86
|
handlePatchDocumentReferences: () => Promise<number>;
|
|
81
87
|
handlePublishAllTranslations: () => Promise<number>;
|
|
82
88
|
}
|
|
@@ -104,6 +110,9 @@ export const TranslationsProvider: React.FC<TranslationsProviderProps> = ({
|
|
|
104
110
|
const [documents, setDocuments] = useState<SanityDocument[]>([]);
|
|
105
111
|
const [locales, setLocales] = useState<TranslationLocale[]>([]);
|
|
106
112
|
const [autoRefresh, setAutoRefresh] = useState(false);
|
|
113
|
+
const [autoImport, setAutoImport] = useState(false);
|
|
114
|
+
const [autoPatchReferences, setAutoPatchReferences] = useState(false);
|
|
115
|
+
const [autoPublish, setAutoPublish] = useState(false);
|
|
107
116
|
const [loadingDocuments, setLoadingDocuments] = useState(false);
|
|
108
117
|
const [importProgress, setImportProgress] = useState<ImportProgress>({
|
|
109
118
|
current: 0,
|
|
@@ -133,6 +142,7 @@ export const TranslationsProvider: React.FC<TranslationsProviderProps> = ({
|
|
|
133
142
|
const { loading: loadingSecrets, secrets } = useSecrets<Secrets>(
|
|
134
143
|
pluginConfig.getSecretsNamespace()
|
|
135
144
|
);
|
|
145
|
+
const [branchId, setBranchId] = useState<string | undefined>(undefined);
|
|
136
146
|
|
|
137
147
|
const fetchDocuments = useCallback(async () => {
|
|
138
148
|
setLoadingDocuments(true);
|
|
@@ -294,15 +304,12 @@ export const TranslationsProvider: React.FC<TranslationsProviderProps> = ({
|
|
|
294
304
|
}, [secrets, documents, locales, schema]);
|
|
295
305
|
|
|
296
306
|
const handleImportAll = useCallback(async () => {
|
|
297
|
-
if (!secrets || documents.length === 0) return;
|
|
307
|
+
if (!secrets || documents.length === 0 || !branchId) return;
|
|
298
308
|
|
|
299
309
|
setIsBusy(true);
|
|
300
310
|
|
|
301
311
|
try {
|
|
302
|
-
const readyFiles = await getReadyFilesForImport(
|
|
303
|
-
documents,
|
|
304
|
-
translationStatuses
|
|
305
|
-
);
|
|
312
|
+
const readyFiles = await getReadyFilesForImport(translationStatuses);
|
|
306
313
|
|
|
307
314
|
if (readyFiles.length === 0) {
|
|
308
315
|
toast.push({
|
|
@@ -371,12 +378,14 @@ export const TranslationsProvider: React.FC<TranslationsProviderProps> = ({
|
|
|
371
378
|
translationStatuses,
|
|
372
379
|
downloadStatus,
|
|
373
380
|
translationContext,
|
|
381
|
+
branchId,
|
|
374
382
|
]);
|
|
375
383
|
|
|
376
|
-
const
|
|
384
|
+
const getExistingTranslations = useCallback(
|
|
377
385
|
async (
|
|
378
386
|
documentIds: string[],
|
|
379
|
-
localeIds: string[]
|
|
387
|
+
localeIds: string[],
|
|
388
|
+
branchId: string
|
|
380
389
|
): Promise<Set<string>> => {
|
|
381
390
|
const sourceLocale = pluginConfig.getSourceLocale();
|
|
382
391
|
|
|
@@ -384,6 +393,7 @@ export const TranslationsProvider: React.FC<TranslationsProviderProps> = ({
|
|
|
384
393
|
_type == 'translation.metadata' &&
|
|
385
394
|
translations[_key == $sourceLocale][0].value._ref in $documentIds
|
|
386
395
|
] {
|
|
396
|
+
_rev,
|
|
387
397
|
'sourceDocId': translations[_key == $sourceLocale][0].value._ref,
|
|
388
398
|
'existingTranslations': translations[_key in $localeIds]._key
|
|
389
399
|
}`;
|
|
@@ -398,30 +408,20 @@ export const TranslationsProvider: React.FC<TranslationsProviderProps> = ({
|
|
|
398
408
|
existingMetadata.forEach((metadata: any) => {
|
|
399
409
|
metadata.existingTranslations?.forEach((localeId: string) => {
|
|
400
410
|
if (localeId !== sourceLocale) {
|
|
401
|
-
existing.add(
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
});
|
|
405
|
-
|
|
406
|
-
const missing = new Set<string>();
|
|
407
|
-
documentIds.forEach((docId) => {
|
|
408
|
-
localeIds.forEach((localeId) => {
|
|
409
|
-
if (localeId !== sourceLocale) {
|
|
410
|
-
const key = `${docId}:${localeId}`;
|
|
411
|
-
if (!existing.has(key)) {
|
|
412
|
-
missing.add(key);
|
|
413
|
-
}
|
|
411
|
+
existing.add(
|
|
412
|
+
`${branchId}:${metadata.sourceDocId}:${metadata._rev}:${localeId}`
|
|
413
|
+
);
|
|
414
414
|
}
|
|
415
415
|
});
|
|
416
416
|
});
|
|
417
417
|
|
|
418
|
-
return
|
|
418
|
+
return existing;
|
|
419
419
|
},
|
|
420
420
|
[client]
|
|
421
421
|
);
|
|
422
422
|
|
|
423
423
|
const handleImportMissing = useCallback(async () => {
|
|
424
|
-
if (!secrets || documents.length === 0) return;
|
|
424
|
+
if (!secrets || documents.length === 0 || !branchId) return;
|
|
425
425
|
|
|
426
426
|
setIsBusy(true);
|
|
427
427
|
|
|
@@ -434,19 +434,15 @@ export const TranslationsProvider: React.FC<TranslationsProviderProps> = ({
|
|
|
434
434
|
(doc) => doc._id?.replace('drafts.', '') || doc._id
|
|
435
435
|
);
|
|
436
436
|
|
|
437
|
-
const
|
|
437
|
+
const existingTranslations = await getExistingTranslations(
|
|
438
438
|
documentIds,
|
|
439
|
-
availableLocaleIds
|
|
439
|
+
availableLocaleIds,
|
|
440
|
+
branchId
|
|
440
441
|
);
|
|
441
442
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
translationStatuses,
|
|
446
|
-
{
|
|
447
|
-
filterReadyFiles: (key) => missingTranslations.has(key),
|
|
448
|
-
}
|
|
449
|
-
);
|
|
443
|
+
const readyFiles = await getReadyFilesForImport(translationStatuses, {
|
|
444
|
+
filterReadyFiles: (key) => !existingTranslations.has(key),
|
|
445
|
+
});
|
|
450
446
|
|
|
451
447
|
if (readyFiles.length === 0) {
|
|
452
448
|
toast.push({
|
|
@@ -517,12 +513,24 @@ export const TranslationsProvider: React.FC<TranslationsProviderProps> = ({
|
|
|
517
513
|
translationStatuses,
|
|
518
514
|
downloadStatus,
|
|
519
515
|
translationContext,
|
|
520
|
-
|
|
516
|
+
getExistingTranslations,
|
|
517
|
+
branchId,
|
|
521
518
|
]);
|
|
522
519
|
|
|
523
|
-
const
|
|
524
|
-
|
|
520
|
+
const handleGetBranchId = useCallback(
|
|
521
|
+
async (secrets: Secrets) => {
|
|
522
|
+
overrideConfig(secrets);
|
|
523
|
+
const defaultBranch = await gt.createBranch({
|
|
524
|
+
branchName: 'main',
|
|
525
|
+
defaultBranch: true,
|
|
526
|
+
});
|
|
527
|
+
setBranchId(defaultBranch.branch.id);
|
|
528
|
+
},
|
|
529
|
+
[secrets]
|
|
530
|
+
);
|
|
525
531
|
|
|
532
|
+
const handleRefreshAll = useCallback(async () => {
|
|
533
|
+
if (!secrets || documents.length === 0 || !branchId) return;
|
|
526
534
|
setIsRefreshing(true);
|
|
527
535
|
|
|
528
536
|
try {
|
|
@@ -530,13 +538,14 @@ export const TranslationsProvider: React.FC<TranslationsProviderProps> = ({
|
|
|
530
538
|
.filter((locale) => locale.enabled !== false)
|
|
531
539
|
.map((locale) => locale.localeId);
|
|
532
540
|
|
|
533
|
-
const fileQueryData = [];
|
|
541
|
+
const fileQueryData: FileProperties[] = [];
|
|
534
542
|
for (const doc of documents) {
|
|
535
543
|
for (const localeId of availableLocaleIds) {
|
|
536
544
|
const documentId = doc._id?.replace('drafts.', '') || doc._id;
|
|
537
545
|
fileQueryData.push({
|
|
538
546
|
versionId: doc._rev,
|
|
539
547
|
fileId: documentId,
|
|
548
|
+
branchId: branchId,
|
|
540
549
|
locale: localeId,
|
|
541
550
|
});
|
|
542
551
|
}
|
|
@@ -554,18 +563,24 @@ export const TranslationsProvider: React.FC<TranslationsProviderProps> = ({
|
|
|
554
563
|
for (const doc of documents) {
|
|
555
564
|
for (const localeId of availableLocaleIds) {
|
|
556
565
|
const documentId = doc._id?.replace('drafts.', '') || doc._id;
|
|
557
|
-
const
|
|
566
|
+
const versionId = doc._rev;
|
|
567
|
+
const key = `${branchId}:${documentId}:${versionId}:${localeId}`;
|
|
558
568
|
newStatuses.set(key, { progress: 0, isReady: false });
|
|
559
569
|
}
|
|
560
570
|
}
|
|
561
571
|
|
|
562
572
|
if (Array.isArray(readyTranslations)) {
|
|
563
573
|
for (const translation of readyTranslations) {
|
|
564
|
-
const key = `${translation.fileId}:${translation.locale}`;
|
|
574
|
+
const key = `${branchId}:${translation.fileId}:${translation.versionId}:${translation.locale}`;
|
|
565
575
|
newStatuses.set(key, {
|
|
566
576
|
progress: 100,
|
|
567
577
|
isReady: true,
|
|
568
|
-
|
|
578
|
+
fileData: {
|
|
579
|
+
versionId: translation.versionId,
|
|
580
|
+
fileId: translation.fileId,
|
|
581
|
+
branchId: translation.branchId,
|
|
582
|
+
locale: translation.locale,
|
|
583
|
+
},
|
|
569
584
|
});
|
|
570
585
|
}
|
|
571
586
|
}
|
|
@@ -588,16 +603,16 @@ export const TranslationsProvider: React.FC<TranslationsProviderProps> = ({
|
|
|
588
603
|
} finally {
|
|
589
604
|
setIsRefreshing(false);
|
|
590
605
|
}
|
|
591
|
-
}, [secrets, documents, locales]);
|
|
606
|
+
}, [secrets, documents, locales, branchId]);
|
|
592
607
|
|
|
593
608
|
const handleImportDocument = useCallback(
|
|
594
|
-
async (documentId: string, localeId: string) => {
|
|
609
|
+
async (documentId: string, versionId: string, localeId: string) => {
|
|
595
610
|
if (!secrets) return;
|
|
596
611
|
|
|
597
|
-
const key = `${documentId}:${localeId}`;
|
|
612
|
+
const key = `${branchId}:${documentId}:${versionId}:${localeId}`;
|
|
598
613
|
const status = translationStatuses.get(key);
|
|
599
614
|
|
|
600
|
-
if (!status?.isReady || !status.
|
|
615
|
+
if (!status?.isReady || !status.fileData) {
|
|
601
616
|
toast.push({
|
|
602
617
|
title: `Translation not ready for ${documentId} (${localeId})`,
|
|
603
618
|
status: 'warning',
|
|
@@ -623,10 +638,10 @@ export const TranslationsProvider: React.FC<TranslationsProviderProps> = ({
|
|
|
623
638
|
const downloadedFiles = await downloadTranslations(
|
|
624
639
|
[
|
|
625
640
|
{
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
locale:
|
|
641
|
+
fileId: status.fileData.fileId,
|
|
642
|
+
branchId: status.fileData.branchId,
|
|
643
|
+
versionId: status.fileData.versionId,
|
|
644
|
+
locale: status.fileData.locale,
|
|
630
645
|
},
|
|
631
646
|
],
|
|
632
647
|
secrets
|
|
@@ -682,7 +697,7 @@ export const TranslationsProvider: React.FC<TranslationsProviderProps> = ({
|
|
|
682
697
|
});
|
|
683
698
|
}
|
|
684
699
|
},
|
|
685
|
-
[secrets, documents, translationContext, translationStatuses]
|
|
700
|
+
[secrets, documents, translationContext, translationStatuses, branchId]
|
|
686
701
|
);
|
|
687
702
|
|
|
688
703
|
const handlePatchDocumentReferences = useCallback(async () => {
|
|
@@ -789,7 +804,7 @@ export const TranslationsProvider: React.FC<TranslationsProviderProps> = ({
|
|
|
789
804
|
setIsBusy(false);
|
|
790
805
|
setImportProgress({ current: 0, total: 0, isImporting: false });
|
|
791
806
|
}
|
|
792
|
-
}, [secrets, documents, locales, client]);
|
|
807
|
+
}, [secrets, documents, locales, client, branchId]);
|
|
793
808
|
|
|
794
809
|
const handlePublishAllTranslations = useCallback(async () => {
|
|
795
810
|
if (!secrets || documents.length === 0) return 0;
|
|
@@ -869,7 +884,7 @@ export const TranslationsProvider: React.FC<TranslationsProviderProps> = ({
|
|
|
869
884
|
} finally {
|
|
870
885
|
setIsBusy(false);
|
|
871
886
|
}
|
|
872
|
-
}, [secrets, documents, client]);
|
|
887
|
+
}, [secrets, documents, client, branchId]);
|
|
873
888
|
|
|
874
889
|
useEffect(() => {
|
|
875
890
|
fetchDocuments();
|
|
@@ -912,12 +927,18 @@ export const TranslationsProvider: React.FC<TranslationsProviderProps> = ({
|
|
|
912
927
|
setImportedTranslations(new Set(downloadStatus.downloaded));
|
|
913
928
|
}, [downloadStatus.downloaded]);
|
|
914
929
|
|
|
930
|
+
if (secrets) {
|
|
931
|
+
handleGetBranchId(secrets);
|
|
932
|
+
}
|
|
915
933
|
const contextValue: TranslationsContextType = {
|
|
916
934
|
// State
|
|
917
935
|
isBusy,
|
|
918
936
|
documents,
|
|
919
937
|
locales,
|
|
920
938
|
autoRefresh,
|
|
939
|
+
autoImport,
|
|
940
|
+
autoPatchReferences,
|
|
941
|
+
autoPublish,
|
|
921
942
|
loadingDocuments,
|
|
922
943
|
importProgress,
|
|
923
944
|
importedTranslations,
|
|
@@ -927,10 +948,14 @@ export const TranslationsProvider: React.FC<TranslationsProviderProps> = ({
|
|
|
927
948
|
isRefreshing,
|
|
928
949
|
loadingSecrets,
|
|
929
950
|
secrets,
|
|
951
|
+
branchId,
|
|
930
952
|
|
|
931
953
|
// Actions
|
|
932
954
|
setLocales,
|
|
933
955
|
setAutoRefresh,
|
|
956
|
+
setAutoImport,
|
|
957
|
+
setAutoPatchReferences,
|
|
958
|
+
setAutoPublish,
|
|
934
959
|
handleTranslateAll,
|
|
935
960
|
handleImportAll,
|
|
936
961
|
handleImportMissing,
|
|
@@ -12,6 +12,7 @@ export const TranslationsTable: React.FC = () => {
|
|
|
12
12
|
downloadStatus,
|
|
13
13
|
importedTranslations,
|
|
14
14
|
handleImportDocument,
|
|
15
|
+
branchId,
|
|
15
16
|
} = useTranslations();
|
|
16
17
|
|
|
17
18
|
if (loadingDocuments) {
|
|
@@ -46,20 +47,21 @@ export const TranslationsTable: React.FC = () => {
|
|
|
46
47
|
.map((locale) => {
|
|
47
48
|
const documentId =
|
|
48
49
|
document._id?.replace('drafts.', '') || document._id;
|
|
49
|
-
const key = `${documentId}:${locale.localeId}`;
|
|
50
|
+
const key = `${branchId}:${documentId}:${document._rev}:${locale.localeId}`;
|
|
50
51
|
const status = translationStatuses.get(key);
|
|
51
52
|
const isDownloaded = downloadStatus.downloaded.has(key);
|
|
52
53
|
const isImported = importedTranslations.has(key);
|
|
53
54
|
|
|
54
55
|
return (
|
|
55
56
|
<LanguageStatus
|
|
56
|
-
key={`${document._id}-${locale.localeId}`}
|
|
57
|
+
key={`${document._id}-${document._rev}-${locale.localeId}`}
|
|
57
58
|
title={locale.description || locale.localeId}
|
|
58
59
|
progress={status?.progress || 0}
|
|
59
60
|
isImported={isImported || isDownloaded}
|
|
60
61
|
importFile={async () => {
|
|
61
62
|
await handleImportDocument(
|
|
62
63
|
documentId,
|
|
64
|
+
document._rev,
|
|
63
65
|
locale.localeId
|
|
64
66
|
);
|
|
65
67
|
}}
|
|
@@ -13,6 +13,7 @@ export const SingleDocumentView: React.FC = () => {
|
|
|
13
13
|
downloadStatus,
|
|
14
14
|
importedTranslations,
|
|
15
15
|
handleImportDocument,
|
|
16
|
+
branchId,
|
|
16
17
|
} = useTranslations();
|
|
17
18
|
|
|
18
19
|
// Get the first (and only) document in single document mode
|
|
@@ -74,20 +75,21 @@ export const SingleDocumentView: React.FC = () => {
|
|
|
74
75
|
.map((locale) => {
|
|
75
76
|
const documentId =
|
|
76
77
|
document._id?.replace('drafts.', '') || document._id;
|
|
77
|
-
const key = `${documentId}:${locale.localeId}`;
|
|
78
|
+
const key = `${branchId}:${documentId}:${document._rev}:${locale.localeId}`;
|
|
78
79
|
const status = translationStatuses.get(key);
|
|
79
80
|
const isDownloaded = downloadStatus.downloaded.has(key);
|
|
80
81
|
const isImported = importedTranslations.has(key);
|
|
81
82
|
|
|
82
83
|
return (
|
|
83
84
|
<LanguageStatus
|
|
84
|
-
key={`${document._id}-${locale.localeId}`}
|
|
85
|
+
key={`${document._id}-${document._rev}-${locale.localeId}`}
|
|
85
86
|
title={locale.description || locale.localeId}
|
|
86
87
|
progress={status?.progress || 0}
|
|
87
88
|
isImported={isImported || isDownloaded}
|
|
88
89
|
importFile={async () => {
|
|
89
90
|
await handleImportDocument(
|
|
90
91
|
documentId,
|
|
92
|
+
document._rev,
|
|
91
93
|
locale.localeId
|
|
92
94
|
);
|
|
93
95
|
}}
|
|
@@ -28,6 +28,7 @@ export const TranslationView = () => {
|
|
|
28
28
|
documents,
|
|
29
29
|
locales,
|
|
30
30
|
translationStatuses,
|
|
31
|
+
branchId,
|
|
31
32
|
isBusy,
|
|
32
33
|
handleTranslateAll,
|
|
33
34
|
handleImportDocument,
|
|
@@ -37,13 +38,17 @@ export const TranslationView = () => {
|
|
|
37
38
|
setLocales,
|
|
38
39
|
handlePatchDocumentReferences,
|
|
39
40
|
handlePublishAllTranslations,
|
|
41
|
+
autoRefresh,
|
|
42
|
+
setAutoRefresh,
|
|
43
|
+
autoImport,
|
|
44
|
+
setAutoImport,
|
|
45
|
+
autoPatchReferences,
|
|
46
|
+
setAutoPatchReferences,
|
|
47
|
+
autoPublish,
|
|
48
|
+
setAutoPublish,
|
|
40
49
|
} = useTranslations();
|
|
41
50
|
|
|
42
|
-
const [autoImport, setAutoImport] = useState(false);
|
|
43
51
|
const [isImporting, setIsImporting] = useState(false);
|
|
44
|
-
const [autoRefresh, setAutoRefresh] = useState(true);
|
|
45
|
-
const [autoPatchReferences, setAutoPatchReferences] = useState(true);
|
|
46
|
-
const [autoPublish, setAutoPublish] = useState(true);
|
|
47
52
|
const [isPublishing, setIsPublishing] = useState(false);
|
|
48
53
|
|
|
49
54
|
const toast = useToast();
|
|
@@ -94,7 +99,7 @@ export const TranslationView = () => {
|
|
|
94
99
|
|
|
95
100
|
// Find translations ready to import
|
|
96
101
|
const readyTranslations = availableLocales.filter((locale) => {
|
|
97
|
-
const key = `${documentId}:${locale.localeId}`;
|
|
102
|
+
const key = `${branchId}:${documentId}:${document._rev}:${locale.localeId}`;
|
|
98
103
|
const status = translationStatuses.get(key);
|
|
99
104
|
return status?.isReady && !importedTranslations.has(key);
|
|
100
105
|
});
|
|
@@ -106,7 +111,7 @@ export const TranslationView = () => {
|
|
|
106
111
|
// Import all ready translations
|
|
107
112
|
await Promise.all(
|
|
108
113
|
readyTranslations.map((locale) =>
|
|
109
|
-
handleImportDocument(documentId, locale.localeId)
|
|
114
|
+
handleImportDocument(documentId, document._rev, locale.localeId)
|
|
110
115
|
)
|
|
111
116
|
);
|
|
112
117
|
|
|
@@ -144,31 +149,12 @@ export const TranslationView = () => {
|
|
|
144
149
|
handleImportTranslations({ autoOnly: true });
|
|
145
150
|
}, [handleImportTranslations]);
|
|
146
151
|
|
|
147
|
-
//
|
|
148
|
-
useEffect(() => {
|
|
149
|
-
if (!autoRefresh || !documentId || availableLocales.length === 0) return;
|
|
150
|
-
|
|
151
|
-
const interval = setInterval(async () => {
|
|
152
|
-
await handleRefreshAll();
|
|
153
|
-
await handleImportTranslations({ autoOnly: true });
|
|
154
|
-
}, 10000);
|
|
155
|
-
|
|
156
|
-
return () => clearInterval(interval);
|
|
157
|
-
}, [
|
|
158
|
-
autoRefresh,
|
|
159
|
-
documentId,
|
|
160
|
-
availableLocales.length,
|
|
161
|
-
handleRefreshAll,
|
|
162
|
-
handleImportTranslations,
|
|
163
|
-
]);
|
|
164
|
-
|
|
152
|
+
// Enable auto features on mount
|
|
165
153
|
useEffect(() => {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
initialRefresh();
|
|
171
|
-
}, []);
|
|
154
|
+
setAutoRefresh(true);
|
|
155
|
+
setAutoPatchReferences(true);
|
|
156
|
+
setAutoPublish(true);
|
|
157
|
+
}, [setAutoRefresh, setAutoPatchReferences, setAutoPublish]);
|
|
172
158
|
|
|
173
159
|
// Locale toggle functionality
|
|
174
160
|
const toggleLocale = useCallback(
|
|
@@ -285,14 +271,14 @@ export const TranslationView = () => {
|
|
|
285
271
|
padding={2}
|
|
286
272
|
text='Refresh Status'
|
|
287
273
|
onClick={handleRefreshAll}
|
|
288
|
-
disabled={isRefreshing}
|
|
274
|
+
disabled={isRefreshing || isBusy}
|
|
289
275
|
/>
|
|
290
276
|
</Flex>
|
|
291
277
|
</Flex>
|
|
292
278
|
|
|
293
279
|
<Box>
|
|
294
280
|
{availableLocales.map((locale) => {
|
|
295
|
-
const key = `${documentId}:${locale.localeId}`;
|
|
281
|
+
const key = `${branchId}:${documentId}:${document._rev}:${locale.localeId}`;
|
|
296
282
|
const status = translationStatuses.get(key);
|
|
297
283
|
const progress = status?.progress || 0;
|
|
298
284
|
const isImported = importedTranslations.has(key);
|
|
@@ -305,7 +291,11 @@ export const TranslationView = () => {
|
|
|
305
291
|
isImported={isImported}
|
|
306
292
|
importFile={async () => {
|
|
307
293
|
if (!isImported && status?.isReady) {
|
|
308
|
-
await handleImportDocument(
|
|
294
|
+
await handleImportDocument(
|
|
295
|
+
documentId,
|
|
296
|
+
document._rev,
|
|
297
|
+
locale.localeId
|
|
298
|
+
);
|
|
309
299
|
}
|
|
310
300
|
}}
|
|
311
301
|
/>
|
|
@@ -326,7 +316,7 @@ export const TranslationView = () => {
|
|
|
326
316
|
disabled={
|
|
327
317
|
isImporting ||
|
|
328
318
|
availableLocales.every((locale) => {
|
|
329
|
-
const key = `${documentId}:${locale.localeId}`;
|
|
319
|
+
const key = `${branchId}:${documentId}:${document._rev}:${locale.localeId}`;
|
|
330
320
|
const status = translationStatuses.get(key);
|
|
331
321
|
return !status?.isReady || importedTranslations.has(key);
|
|
332
322
|
})
|
|
@@ -346,14 +336,14 @@ export const TranslationView = () => {
|
|
|
346
336
|
Imported{' '}
|
|
347
337
|
{
|
|
348
338
|
availableLocales.filter((locale) => {
|
|
349
|
-
const key = `${documentId}:${locale.localeId}`;
|
|
339
|
+
const key = `${branchId}:${documentId}:${document._rev}:${locale.localeId}`;
|
|
350
340
|
return importedTranslations.has(key);
|
|
351
341
|
}).length
|
|
352
342
|
}
|
|
353
343
|
/
|
|
354
344
|
{
|
|
355
345
|
availableLocales.filter((locale) => {
|
|
356
|
-
const key = `${documentId}:${locale.localeId}`;
|
|
346
|
+
const key = `${branchId}:${documentId}:${document._rev}:${locale.localeId}`;
|
|
357
347
|
const status = translationStatuses.get(key);
|
|
358
348
|
return status?.isReady;
|
|
359
349
|
}).length
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { Secrets } from '../types';
|
|
2
2
|
import { gt, overrideConfig } from '../adapter/core';
|
|
3
|
+
import { FileProperties } from '../adapter/types';
|
|
3
4
|
|
|
4
5
|
export async function checkTranslationStatus(
|
|
5
|
-
fileQueryData:
|
|
6
|
+
fileQueryData: FileProperties[],
|
|
6
7
|
downloadStatus: {
|
|
7
8
|
downloaded: Set<string>;
|
|
8
9
|
failed: Set<string>;
|
|
@@ -25,13 +26,15 @@ export async function checkTranslationStatus(
|
|
|
25
26
|
return true;
|
|
26
27
|
}
|
|
27
28
|
// Check for translations
|
|
28
|
-
const responseData = await gt.
|
|
29
|
+
const responseData = await gt.queryFileData({
|
|
30
|
+
translatedFiles: currentQueryData,
|
|
31
|
+
});
|
|
29
32
|
|
|
30
|
-
const translations = responseData.
|
|
33
|
+
const translations = responseData.translatedFiles || [];
|
|
31
34
|
|
|
32
35
|
// Filter for ready translations
|
|
33
36
|
const readyTranslations = translations.filter(
|
|
34
|
-
(translation) => translation.
|
|
37
|
+
(translation) => translation.completedAt
|
|
35
38
|
);
|
|
36
39
|
|
|
37
40
|
return readyTranslations;
|