gt-sanity 0.0.6 → 1.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/LICENSE.md +1 -1
- package/dist/index.d.mts +95 -73
- package/dist/index.d.ts +95 -73
- package/dist/index.js +9066 -1207
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +9083 -1197
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -3
- package/src/adapter/core.ts +41 -4
- package/src/adapter/getLocales.ts +2 -2
- package/src/components/TranslationsProvider.tsx +942 -0
- package/src/components/page/BatchProgress.tsx +27 -0
- package/src/components/page/ImportAllDialog.tsx +51 -0
- package/src/components/page/ImportMissingDialog.tsx +55 -0
- package/src/components/page/TranslateAllDialog.tsx +55 -0
- package/src/components/page/TranslationsTable.tsx +81 -0
- package/src/components/page/TranslationsTool.tsx +299 -837
- package/src/components/shared/BaseTranslationWrapper.tsx +82 -0
- package/src/components/shared/LocaleCheckbox.tsx +47 -0
- package/src/components/shared/SingleDocumentView.tsx +108 -0
- package/src/components/tab/TranslationView.tsx +379 -0
- package/src/components/tab/TranslationsTab.tsx +25 -0
- package/src/configuration/baseDocumentLevelConfig/documentLevelPatch.ts +6 -9
- package/src/configuration/baseDocumentLevelConfig/helpers/createI18nDocAndPatchMetadata.ts +5 -24
- package/src/configuration/baseDocumentLevelConfig/helpers/patchI18nDoc.ts +3 -23
- package/src/configuration/baseDocumentLevelConfig/index.ts +16 -68
- package/src/configuration/baseFieldLevelConfig.ts +15 -50
- package/src/index.ts +29 -43
- package/src/sanity-api/findDocuments.ts +44 -0
- package/src/sanity-api/publishDocuments.ts +49 -0
- package/src/sanity-api/resolveRefs.ts +146 -0
- package/src/serialization/BaseDocumentMerger.ts +138 -0
- package/src/serialization/BaseSerializationConfig.ts +220 -0
- package/src/serialization/__tests__/BaseDocumentDeserializer/__snapshots__/documentLevelDeserialization.test.ts.snap +189 -0
- package/src/serialization/__tests__/BaseDocumentDeserializer/__snapshots__/fieldLevelDeserialization.test.ts.snap +107 -0
- package/src/serialization/__tests__/BaseDocumentDeserializer/baseDeserialization.test.ts +397 -0
- package/src/serialization/__tests__/BaseDocumentDeserializer/documentLevelDeserialization.test.ts +107 -0
- package/src/serialization/__tests__/BaseDocumentDeserializer/fieldLevelDeserialization.test.ts +107 -0
- package/src/serialization/__tests__/BaseDocumentMerger/__snapshots__/documentLevelMerge.test.ts.snap +193 -0
- package/src/serialization/__tests__/BaseDocumentMerger/__snapshots__/fieldLevelMerge.test.ts.snap +97 -0
- package/src/serialization/__tests__/BaseDocumentMerger/baseMerge.test.ts +36 -0
- package/src/serialization/__tests__/BaseDocumentMerger/documentLevelMerge.test.ts +96 -0
- package/src/serialization/__tests__/BaseDocumentMerger/fieldLevelMerge.test.ts +142 -0
- package/src/serialization/__tests__/BaseDocumentMerger/utils.ts +52 -0
- package/src/serialization/__tests__/BaseDocumentSerializer/__snapshots__/documentInlineMarks.test.ts.snap +39 -0
- package/src/serialization/__tests__/BaseDocumentSerializer/__snapshots__/documentLevelSerialization.test.ts.snap +8 -0
- package/src/serialization/__tests__/BaseDocumentSerializer/__snapshots__/fieldLevelSerialization.test.ts.snap +8 -0
- package/src/serialization/__tests__/BaseDocumentSerializer/baseSerialization.test.ts +345 -0
- package/src/serialization/__tests__/BaseDocumentSerializer/documentInlineMarks.test.ts +53 -0
- package/src/serialization/__tests__/BaseDocumentSerializer/documentLevelSerialization.test.ts +120 -0
- package/src/serialization/__tests__/BaseDocumentSerializer/fieldLevelSerialization.test.ts +153 -0
- package/src/serialization/__tests__/BaseDocumentSerializer/utils.ts +27 -0
- package/src/serialization/__tests__/README +2 -0
- package/src/serialization/__tests__/__fixtures__/annotationAndInlineBlocks.json +140 -0
- package/src/serialization/__tests__/__fixtures__/customStyles.json +62 -0
- package/src/serialization/__tests__/__fixtures__/documentInlineMarks.json +70 -0
- package/src/serialization/__tests__/__fixtures__/documentLevelArticle.json +185 -0
- package/src/serialization/__tests__/__fixtures__/fieldLevelArticle.json +107 -0
- package/src/serialization/__tests__/__fixtures__/inlineDocumentLevelArticle.json +134 -0
- package/src/serialization/__tests__/__fixtures__/inlineSchema.ts +270 -0
- package/src/serialization/__tests__/__fixtures__/messy-html.html +26 -0
- package/src/serialization/__tests__/__fixtures__/nestedLanguageFields.json +54 -0
- package/src/serialization/__tests__/__fixtures__/schema.ts +310 -0
- package/src/serialization/__tests__/global.setup.ts +40 -0
- package/src/serialization/__tests__/helpers.ts +132 -0
- package/src/serialization/data.ts +82 -0
- package/src/serialization/deserialize/BaseDocumentDeserializer.ts +171 -0
- package/src/serialization/deserialize/helpers.ts +42 -0
- package/src/serialization/helpers.ts +18 -0
- package/src/serialization/index.ts +11 -0
- package/src/serialization/serialize/fieldFilters.ts +124 -0
- package/src/serialization/serialize/index.ts +284 -0
- package/src/serialization/types.ts +41 -0
- package/src/translation/importDocument.ts +4 -5
- package/src/translation/uploadFiles.ts +1 -1
- package/src/types.ts +3 -19
- package/src/utils/batchProcessor.ts +111 -0
- package/src/utils/importUtils.ts +95 -0
- package/src/utils/serialize.ts +25 -5
- package/src/utils/shared.ts +1 -1
- package/src/adapter/index.ts +0 -13
- package/src/components/NewTask.tsx +0 -251
- package/src/components/TaskView.tsx +0 -257
- package/src/components/TranslationContext.tsx +0 -24
- package/src/components/TranslationView.tsx +0 -114
- package/src/components/TranslationsTab.tsx +0 -181
- /package/src/components/{LanguageStatus.tsx → shared/LanguageStatus.tsx} +0 -0
- /package/src/components/{ProgressBar.tsx → shared/ProgressBar.tsx} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// adapted from https://github.com/sanity-io/sanity-translations-tab. See LICENSE.md for more details.
|
|
2
2
|
|
|
3
3
|
import { SanityClient, SanityDocumentLike } from 'sanity';
|
|
4
|
-
import {
|
|
4
|
+
import { pluginConfig } from '../../../adapter/core';
|
|
5
5
|
import { applyDocuments } from '../../../utils/applyDocuments';
|
|
6
6
|
|
|
7
7
|
export async function createI18nDocAndPatchMetadata(
|
|
@@ -11,8 +11,7 @@ export async function createI18nDocAndPatchMetadata(
|
|
|
11
11
|
client: SanityClient,
|
|
12
12
|
translationMetadata: SanityDocumentLike,
|
|
13
13
|
sourceDocumentId: string,
|
|
14
|
-
languageField: string = 'language'
|
|
15
|
-
publish: boolean = false
|
|
14
|
+
languageField: string = 'language'
|
|
16
15
|
): Promise<void> {
|
|
17
16
|
translatedDoc[languageField] = localeId;
|
|
18
17
|
const translations = translationMetadata.translations as Record<
|
|
@@ -34,16 +33,16 @@ export async function createI18nDocAndPatchMetadata(
|
|
|
34
33
|
sourceDocumentId,
|
|
35
34
|
sourceDocument,
|
|
36
35
|
rest,
|
|
37
|
-
|
|
36
|
+
pluginConfig.getIgnoreFields()
|
|
38
37
|
);
|
|
39
38
|
|
|
40
39
|
// Check if this is a singleton document and apply singleton mapping
|
|
41
|
-
const singletons =
|
|
40
|
+
const singletons = pluginConfig.getSingletons();
|
|
42
41
|
const isSingleton = singletons.includes(sourceDocumentId);
|
|
43
42
|
|
|
44
43
|
let createDocumentPromise;
|
|
45
44
|
if (isSingleton) {
|
|
46
|
-
const singletonMapping =
|
|
45
|
+
const singletonMapping = pluginConfig.getSingletonMapping();
|
|
47
46
|
const translatedDocId = singletonMapping(sourceDocumentId, localeId);
|
|
48
47
|
createDocumentPromise = client.create({
|
|
49
48
|
...appliedDocument,
|
|
@@ -79,22 +78,4 @@ export async function createI18nDocAndPatchMetadata(
|
|
|
79
78
|
])
|
|
80
79
|
)
|
|
81
80
|
.commit();
|
|
82
|
-
|
|
83
|
-
if (publish) {
|
|
84
|
-
try {
|
|
85
|
-
// only publish if the document is a draft
|
|
86
|
-
if (doc._id.startsWith('drafts.')) {
|
|
87
|
-
await client.action(
|
|
88
|
-
{
|
|
89
|
-
actionType: 'sanity.action.document.publish',
|
|
90
|
-
draftId: doc._id,
|
|
91
|
-
publishedId: doc._id.replace('drafts.', ''),
|
|
92
|
-
},
|
|
93
|
-
{}
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
} catch (error) {
|
|
97
|
-
console.error('Error publishing document', error);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
81
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { SanityClient, SanityDocumentLike } from 'sanity';
|
|
4
4
|
import { applyDocuments } from '../../../utils/applyDocuments';
|
|
5
|
-
import {
|
|
5
|
+
import { pluginConfig } from '../../../adapter/core';
|
|
6
6
|
|
|
7
7
|
const SYSTEM_FIELDS = ['_id', '_rev', '_updatedAt', 'language'];
|
|
8
8
|
|
|
@@ -14,8 +14,7 @@ export async function patchI18nDoc(
|
|
|
14
14
|
sourceDocument: SanityDocumentLike,
|
|
15
15
|
mergedDocument: SanityDocumentLike,
|
|
16
16
|
translatedFields: Record<string, any>,
|
|
17
|
-
client: SanityClient
|
|
18
|
-
publish: boolean = false
|
|
17
|
+
client: SanityClient
|
|
19
18
|
): Promise<void> {
|
|
20
19
|
const cleanedMerge: Record<string, any> = {};
|
|
21
20
|
Object.entries(mergedDocument).forEach(([key, value]) => {
|
|
@@ -37,32 +36,13 @@ export async function patchI18nDoc(
|
|
|
37
36
|
cleanedSourceDocument[key] = value;
|
|
38
37
|
}
|
|
39
38
|
});
|
|
40
|
-
|
|
41
39
|
const appliedDocument = applyDocuments(
|
|
42
40
|
sourceDocumentId,
|
|
43
41
|
cleanedSourceDocument,
|
|
44
42
|
cleanedMerge,
|
|
45
|
-
|
|
43
|
+
pluginConfig.getIgnoreFields()
|
|
46
44
|
);
|
|
47
45
|
const newDocument = await client
|
|
48
46
|
.patch(i18nDocId, { set: appliedDocument })
|
|
49
47
|
.commit();
|
|
50
|
-
|
|
51
|
-
if (publish) {
|
|
52
|
-
try {
|
|
53
|
-
// only publish if the document is a draft
|
|
54
|
-
if (newDocument._id.startsWith('drafts.')) {
|
|
55
|
-
await client.action(
|
|
56
|
-
{
|
|
57
|
-
actionType: 'sanity.action.document.publish',
|
|
58
|
-
draftId: newDocument._id,
|
|
59
|
-
publishedId: newDocument._id.replace('drafts.', ''),
|
|
60
|
-
},
|
|
61
|
-
{}
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
} catch (error) {
|
|
65
|
-
console.error('Error publishing document', error);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
48
|
}
|
|
@@ -5,50 +5,22 @@ import {
|
|
|
5
5
|
GTSerializedDocument,
|
|
6
6
|
ImportTranslation,
|
|
7
7
|
} from '../../types';
|
|
8
|
-
import { SanityDocument } from 'sanity';
|
|
9
8
|
import { findLatestDraft } from '../utils/findLatestDraft';
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
BaseDocumentSerializer,
|
|
14
|
-
defaultStopTypes,
|
|
15
|
-
customSerializers,
|
|
16
|
-
customBlockDeserializers,
|
|
17
|
-
} from 'sanity-naive-html-serializer';
|
|
18
|
-
import { gtConfig } from '../../adapter/core';
|
|
9
|
+
import { pluginConfig } from '../../adapter/core';
|
|
10
|
+
import { importDocument } from '../../translation/importDocument';
|
|
11
|
+
import { serializeDocument } from '../../utils/serialize';
|
|
19
12
|
|
|
20
13
|
export const baseDocumentLevelConfig = {
|
|
21
14
|
exportForTranslation: async (
|
|
22
|
-
|
|
15
|
+
docInfo: Parameters<ExportForTranslation>[0],
|
|
16
|
+
context: Parameters<ExportForTranslation>[1]
|
|
23
17
|
): Promise<GTSerializedDocument> => {
|
|
24
|
-
const [
|
|
25
|
-
docInfo,
|
|
26
|
-
context,
|
|
27
|
-
serializationOptions = {},
|
|
28
|
-
languageField = 'language',
|
|
29
|
-
] = params;
|
|
30
18
|
const { client, schema } = context;
|
|
31
|
-
const
|
|
32
|
-
...(serializationOptions.additionalStopTypes ?? []),
|
|
33
|
-
...defaultStopTypes,
|
|
34
|
-
];
|
|
35
|
-
const serializers = {
|
|
36
|
-
...customSerializers,
|
|
37
|
-
types: {
|
|
38
|
-
...customSerializers.types,
|
|
39
|
-
...(serializationOptions.additionalSerializers ?? {}),
|
|
40
|
-
},
|
|
41
|
-
};
|
|
19
|
+
const languageField = pluginConfig.getLanguageField();
|
|
42
20
|
const doc = await findLatestDraft(docInfo.documentId, client);
|
|
43
21
|
delete doc[languageField];
|
|
44
|
-
const baseLanguage =
|
|
45
|
-
const serialized =
|
|
46
|
-
doc,
|
|
47
|
-
'document',
|
|
48
|
-
baseLanguage,
|
|
49
|
-
stopTypes,
|
|
50
|
-
serializers
|
|
51
|
-
);
|
|
22
|
+
const baseLanguage = pluginConfig.getSourceLocale();
|
|
23
|
+
const serialized = serializeDocument(doc, schema, baseLanguage);
|
|
52
24
|
return {
|
|
53
25
|
content: serialized.content,
|
|
54
26
|
documentId: docInfo.documentId,
|
|
@@ -56,43 +28,19 @@ export const baseDocumentLevelConfig = {
|
|
|
56
28
|
};
|
|
57
29
|
},
|
|
58
30
|
importTranslation: (
|
|
59
|
-
|
|
31
|
+
docInfo: Parameters<ImportTranslation>[0],
|
|
32
|
+
localeId: Parameters<ImportTranslation>[1],
|
|
33
|
+
document: Parameters<ImportTranslation>[2],
|
|
34
|
+
context: Parameters<ImportTranslation>[3],
|
|
35
|
+
mergeWithTargetLocale: boolean = false
|
|
60
36
|
): Promise<void> => {
|
|
61
|
-
|
|
37
|
+
return importDocument(
|
|
62
38
|
docInfo,
|
|
63
39
|
localeId,
|
|
64
40
|
document,
|
|
65
41
|
context,
|
|
66
|
-
|
|
67
|
-
languageField = 'language',
|
|
68
|
-
mergeWithTargetLocale = false,
|
|
69
|
-
publish = false,
|
|
70
|
-
] = params;
|
|
71
|
-
const { client } = context;
|
|
72
|
-
const deserializers = {
|
|
73
|
-
types: {
|
|
74
|
-
...(serializationOptions.additionalDeserializers ?? {}),
|
|
75
|
-
},
|
|
76
|
-
};
|
|
77
|
-
const blockDeserializers = [
|
|
78
|
-
...(serializationOptions.additionalBlockDeserializers ?? []),
|
|
79
|
-
...customBlockDeserializers,
|
|
80
|
-
];
|
|
81
|
-
|
|
82
|
-
const deserialized = BaseDocumentDeserializer.deserializeDocument(
|
|
83
|
-
document,
|
|
84
|
-
deserializers,
|
|
85
|
-
blockDeserializers
|
|
86
|
-
) as SanityDocument;
|
|
87
|
-
return documentLevelPatch(
|
|
88
|
-
docInfo, // versionId is not used here, since we just use the _rev id in the deserialized HTML itself
|
|
89
|
-
deserialized,
|
|
90
|
-
localeId,
|
|
91
|
-
client,
|
|
92
|
-
languageField,
|
|
93
|
-
mergeWithTargetLocale,
|
|
94
|
-
publish
|
|
42
|
+
mergeWithTargetLocale
|
|
95
43
|
);
|
|
96
44
|
},
|
|
97
|
-
secretsNamespace: '
|
|
45
|
+
secretsNamespace: 'generaltranslation',
|
|
98
46
|
};
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
defaultStopTypes,
|
|
9
9
|
customSerializers,
|
|
10
10
|
customBlockDeserializers,
|
|
11
|
-
} from '
|
|
11
|
+
} from '../serialization/';
|
|
12
12
|
|
|
13
13
|
import type {
|
|
14
14
|
ExportForTranslation,
|
|
@@ -18,7 +18,8 @@ import type {
|
|
|
18
18
|
} from '../types';
|
|
19
19
|
import { findLatestDraft } from './utils/findLatestDraft';
|
|
20
20
|
import { findDocumentAtRevision } from './utils/findDocumentAtRevision';
|
|
21
|
-
import {
|
|
21
|
+
import { pluginConfig } from '../adapter/core';
|
|
22
|
+
import { deserializeDocument, serializeDocument } from '../utils/serialize';
|
|
22
23
|
|
|
23
24
|
export const fieldLevelPatch = async (
|
|
24
25
|
docInfo: GTFile,
|
|
@@ -28,7 +29,7 @@ export const fieldLevelPatch = async (
|
|
|
28
29
|
mergeWithTargetLocale: boolean = false
|
|
29
30
|
): Promise<void> => {
|
|
30
31
|
let baseDoc: SanityDocument;
|
|
31
|
-
const baseLanguage =
|
|
32
|
+
const baseLanguage = pluginConfig.getSourceLocale();
|
|
32
33
|
if (docInfo.documentId && docInfo.versionId) {
|
|
33
34
|
baseDoc = await findDocumentAtRevision(
|
|
34
35
|
docInfo.documentId,
|
|
@@ -51,30 +52,13 @@ export const fieldLevelPatch = async (
|
|
|
51
52
|
|
|
52
53
|
export const baseFieldLevelConfig = {
|
|
53
54
|
exportForTranslation: async (
|
|
54
|
-
|
|
55
|
+
docInfo: Parameters<ExportForTranslation>[0],
|
|
56
|
+
context: Parameters<ExportForTranslation>[1]
|
|
55
57
|
): Promise<GTSerializedDocument> => {
|
|
56
|
-
const
|
|
57
|
-
const baseLanguage = gtConfig.getSourceLocale();
|
|
58
|
+
const baseLanguage = pluginConfig.getSourceLocale();
|
|
58
59
|
const { client, schema } = context;
|
|
59
|
-
const stopTypes = [
|
|
60
|
-
...(serializationOptions.additionalStopTypes ?? []),
|
|
61
|
-
...defaultStopTypes,
|
|
62
|
-
];
|
|
63
|
-
const serializers = {
|
|
64
|
-
...customSerializers,
|
|
65
|
-
types: {
|
|
66
|
-
...customSerializers.types,
|
|
67
|
-
...(serializationOptions.additionalSerializers ?? {}),
|
|
68
|
-
},
|
|
69
|
-
};
|
|
70
60
|
const doc = await findLatestDraft(docInfo.documentId, client);
|
|
71
|
-
const serialized =
|
|
72
|
-
doc,
|
|
73
|
-
'field',
|
|
74
|
-
baseLanguage,
|
|
75
|
-
stopTypes,
|
|
76
|
-
serializers
|
|
77
|
-
);
|
|
61
|
+
const serialized = serializeDocument(doc, schema, baseLanguage);
|
|
78
62
|
return {
|
|
79
63
|
content: serialized.content,
|
|
80
64
|
documentId: docInfo.documentId,
|
|
@@ -82,33 +66,14 @@ export const baseFieldLevelConfig = {
|
|
|
82
66
|
};
|
|
83
67
|
},
|
|
84
68
|
importTranslation: (
|
|
85
|
-
|
|
69
|
+
docInfo: Parameters<ImportTranslation>[0],
|
|
70
|
+
localeId: Parameters<ImportTranslation>[1],
|
|
71
|
+
document: Parameters<ImportTranslation>[2],
|
|
72
|
+
context: Parameters<ImportTranslation>[3],
|
|
73
|
+
mergeWithTargetLocale: boolean = false
|
|
86
74
|
): Promise<void> => {
|
|
87
|
-
const [
|
|
88
|
-
docInfo,
|
|
89
|
-
localeId,
|
|
90
|
-
document,
|
|
91
|
-
context,
|
|
92
|
-
serializationOptions = {},
|
|
93
|
-
,
|
|
94
|
-
mergeWithTargetLocale,
|
|
95
|
-
] = params;
|
|
96
75
|
const { client } = context;
|
|
97
|
-
const
|
|
98
|
-
types: {
|
|
99
|
-
...(serializationOptions.additionalDeserializers ?? {}),
|
|
100
|
-
},
|
|
101
|
-
};
|
|
102
|
-
const blockDeserializers = [
|
|
103
|
-
...(serializationOptions.additionalBlockDeserializers ?? []),
|
|
104
|
-
...customBlockDeserializers,
|
|
105
|
-
];
|
|
106
|
-
|
|
107
|
-
const deserialized = BaseDocumentDeserializer.deserializeDocument(
|
|
108
|
-
document,
|
|
109
|
-
deserializers,
|
|
110
|
-
blockDeserializers
|
|
111
|
-
) as SanityDocument;
|
|
76
|
+
const deserialized = deserializeDocument(document);
|
|
112
77
|
return fieldLevelPatch(
|
|
113
78
|
docInfo,
|
|
114
79
|
deserialized,
|
|
@@ -117,5 +82,5 @@ export const baseFieldLevelConfig = {
|
|
|
117
82
|
mergeWithTargetLocale
|
|
118
83
|
);
|
|
119
84
|
},
|
|
120
|
-
secretsNamespace: '
|
|
85
|
+
secretsNamespace: 'generaltranslation',
|
|
121
86
|
};
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import TranslationsTab from './components/TranslationsTab';
|
|
1
|
+
import TranslationsTab from './components/tab/TranslationsTab';
|
|
2
2
|
import {
|
|
3
3
|
Secrets,
|
|
4
4
|
Adapter,
|
|
@@ -6,13 +6,8 @@ import {
|
|
|
6
6
|
ImportTranslation,
|
|
7
7
|
TranslationFunctionContext,
|
|
8
8
|
TranslationsTabConfigOptions,
|
|
9
|
-
GTFile,
|
|
10
9
|
} from './types';
|
|
11
|
-
import { baseDocumentLevelConfig } from './configuration/baseDocumentLevelConfig';
|
|
12
|
-
import { baseFieldLevelConfig } from './configuration/baseFieldLevelConfig';
|
|
13
10
|
import { findLatestDraft } from './configuration/utils/findLatestDraft';
|
|
14
|
-
import { documentLevelPatch } from './configuration/baseDocumentLevelConfig/documentLevelPatch';
|
|
15
|
-
import { fieldLevelPatch } from './configuration/baseFieldLevelConfig';
|
|
16
11
|
import {
|
|
17
12
|
BaseDocumentSerializer,
|
|
18
13
|
BaseDocumentDeserializer,
|
|
@@ -20,7 +15,7 @@ import {
|
|
|
20
15
|
defaultStopTypes,
|
|
21
16
|
customSerializers,
|
|
22
17
|
SerializedDocument,
|
|
23
|
-
} from '
|
|
18
|
+
} from './serialization';
|
|
24
19
|
|
|
25
20
|
export type {
|
|
26
21
|
Secrets,
|
|
@@ -35,53 +30,24 @@ export {
|
|
|
35
30
|
TranslationsTab,
|
|
36
31
|
//helpers for end developers who may need to customize serialization
|
|
37
32
|
findLatestDraft,
|
|
38
|
-
documentLevelPatch,
|
|
39
|
-
fieldLevelPatch,
|
|
40
33
|
BaseDocumentSerializer,
|
|
41
34
|
BaseDocumentDeserializer,
|
|
42
35
|
BaseDocumentMerger,
|
|
43
36
|
defaultStopTypes,
|
|
44
37
|
customSerializers,
|
|
38
|
+
attachGTData,
|
|
39
|
+
detachGTData,
|
|
45
40
|
};
|
|
46
41
|
|
|
47
|
-
import { GTAdapter } from './adapter';
|
|
48
42
|
import { definePlugin } from 'sanity';
|
|
49
43
|
import { route } from 'sanity/router';
|
|
50
|
-
import { gt,
|
|
51
|
-
import { GTSerializedDocument } from './types';
|
|
44
|
+
import { gt, pluginConfig } from './adapter/core';
|
|
52
45
|
import { libraryDefaultLocale } from 'generaltranslation/internal';
|
|
53
46
|
import type { IgnoreFields, TranslateDocumentFilter } from './adapter/types';
|
|
54
47
|
import TranslationsTool from './components/page/TranslationsTool';
|
|
55
48
|
import { SECRETS_NAMESPACE } from './utils/shared';
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
adapter: Adapter;
|
|
59
|
-
secretsNamespace: string | null;
|
|
60
|
-
exportForTranslation: (
|
|
61
|
-
docInfo: GTFile,
|
|
62
|
-
context: TranslationFunctionContext
|
|
63
|
-
) => Promise<GTSerializedDocument>;
|
|
64
|
-
importTranslation: (
|
|
65
|
-
docInfo: GTFile,
|
|
66
|
-
localeId: string,
|
|
67
|
-
doc: string,
|
|
68
|
-
context: TranslationFunctionContext
|
|
69
|
-
) => Promise<void>;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export const defaultDocumentLevelConfig: ConfigOptions = {
|
|
73
|
-
...baseDocumentLevelConfig,
|
|
74
|
-
adapter: GTAdapter,
|
|
75
|
-
secretsNamespace: 'generaltranslation',
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
export const defaultFieldLevelConfig: ConfigOptions = {
|
|
79
|
-
...baseFieldLevelConfig,
|
|
80
|
-
adapter: GTAdapter,
|
|
81
|
-
secretsNamespace: 'generaltranslation',
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
export { GTAdapter };
|
|
49
|
+
import type { PortableTextHtmlComponents } from '@portabletext/to-html';
|
|
50
|
+
import { attachGTData, detachGTData } from './serialization/data';
|
|
85
51
|
|
|
86
52
|
export type GTPluginConfig = Omit<
|
|
87
53
|
Parameters<typeof gt.setConfig>[0],
|
|
@@ -96,6 +62,10 @@ export type GTPluginConfig = Omit<
|
|
|
96
62
|
languageField?: string;
|
|
97
63
|
translateDocuments?: TranslateDocumentFilter[];
|
|
98
64
|
secretsNamespace?: string;
|
|
65
|
+
additionalStopTypes?: string[];
|
|
66
|
+
additionalSerializers?: Partial<PortableTextHtmlComponents>;
|
|
67
|
+
additionalDeserializers?: Record<string, any>;
|
|
68
|
+
additionalBlockDeserializers?: any[];
|
|
99
69
|
};
|
|
100
70
|
|
|
101
71
|
/**
|
|
@@ -124,6 +94,10 @@ export const gtPlugin = definePlugin<GTPluginConfig>(
|
|
|
124
94
|
ignoreFields,
|
|
125
95
|
translateDocuments,
|
|
126
96
|
secretsNamespace = SECRETS_NAMESPACE,
|
|
97
|
+
additionalStopTypes = [],
|
|
98
|
+
additionalSerializers = {},
|
|
99
|
+
additionalDeserializers = {},
|
|
100
|
+
additionalBlockDeserializers = [],
|
|
127
101
|
}) => {
|
|
128
102
|
// Validate the translateDocuments
|
|
129
103
|
translateDocuments = translateDocuments?.filter((filter) => {
|
|
@@ -133,7 +107,7 @@ export const gtPlugin = definePlugin<GTPluginConfig>(
|
|
|
133
107
|
return false;
|
|
134
108
|
});
|
|
135
109
|
|
|
136
|
-
|
|
110
|
+
pluginConfig.init(
|
|
137
111
|
secretsNamespace,
|
|
138
112
|
languageField,
|
|
139
113
|
sourceLocale,
|
|
@@ -143,7 +117,11 @@ export const gtPlugin = definePlugin<GTPluginConfig>(
|
|
|
143
117
|
singletonMapping ||
|
|
144
118
|
((sourceDocumentId, locale) => `${sourceDocumentId}-${locale}`),
|
|
145
119
|
ignoreFields || [],
|
|
146
|
-
translateDocuments || []
|
|
120
|
+
translateDocuments || [],
|
|
121
|
+
additionalStopTypes,
|
|
122
|
+
additionalSerializers,
|
|
123
|
+
additionalDeserializers,
|
|
124
|
+
additionalBlockDeserializers
|
|
147
125
|
);
|
|
148
126
|
gt.setConfig({
|
|
149
127
|
sourceLocale: sourceLocale,
|
|
@@ -153,6 +131,14 @@ export const gtPlugin = definePlugin<GTPluginConfig>(
|
|
|
153
131
|
});
|
|
154
132
|
return {
|
|
155
133
|
name: 'gt-sanity',
|
|
134
|
+
tools: [
|
|
135
|
+
{
|
|
136
|
+
name: 'translations',
|
|
137
|
+
title: 'Translations',
|
|
138
|
+
component: TranslationsTool,
|
|
139
|
+
router: route.create('/*'),
|
|
140
|
+
},
|
|
141
|
+
],
|
|
156
142
|
};
|
|
157
143
|
}
|
|
158
144
|
);
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { SanityClient } from 'sanity';
|
|
2
|
+
import { pluginConfig } from '../adapter/core';
|
|
3
|
+
|
|
4
|
+
export async function findTranslatedDocuments(
|
|
5
|
+
documentId: string,
|
|
6
|
+
client: SanityClient
|
|
7
|
+
) {
|
|
8
|
+
const documents = await client.fetch(
|
|
9
|
+
`*[_type == "translation.metadata" && references($documentId)]`
|
|
10
|
+
);
|
|
11
|
+
return documents;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export async function findTranslatedDocumentForLocale(
|
|
15
|
+
sourceDocumentId: string,
|
|
16
|
+
localeId: string,
|
|
17
|
+
client: SanityClient
|
|
18
|
+
) {
|
|
19
|
+
const cleanDocId = sourceDocumentId.replace('drafts.', '');
|
|
20
|
+
|
|
21
|
+
// Try both clean and original IDs to be safe, and use -> to directly fetch the translated doc
|
|
22
|
+
const query = `*[
|
|
23
|
+
_type == "translation.metadata" &&
|
|
24
|
+
(
|
|
25
|
+
translations[_key == $sourceLocale][0].value._ref == $cleanDocId
|
|
26
|
+
) &&
|
|
27
|
+
defined(translations[_key == $localeId])
|
|
28
|
+
][0].translations[_key == $localeId][0].value->`;
|
|
29
|
+
|
|
30
|
+
const translatedDoc = await client.fetch(query, {
|
|
31
|
+
sourceLocale: pluginConfig.getSourceLocale(),
|
|
32
|
+
cleanDocId,
|
|
33
|
+
localeId,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
return translatedDoc || null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export async function findDocument(documentId: string, client: SanityClient) {
|
|
40
|
+
const query = `*[_id == $id]`;
|
|
41
|
+
const params = { id: documentId };
|
|
42
|
+
const document = await client.fetch(query, params);
|
|
43
|
+
return document[0] || null;
|
|
44
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { SanityClient } from 'sanity';
|
|
2
|
+
import { processBatch } from '../utils/batchProcessor';
|
|
3
|
+
import { findDocument } from './findDocuments';
|
|
4
|
+
|
|
5
|
+
export async function publishDocument(
|
|
6
|
+
documentId: string,
|
|
7
|
+
client: SanityClient
|
|
8
|
+
) {
|
|
9
|
+
try {
|
|
10
|
+
// only publish if the document is a draft
|
|
11
|
+
if (documentId.startsWith('drafts.')) {
|
|
12
|
+
await client.action(
|
|
13
|
+
{
|
|
14
|
+
actionType: 'sanity.action.document.publish',
|
|
15
|
+
draftId: documentId,
|
|
16
|
+
publishedId: documentId.replace('drafts.', ''),
|
|
17
|
+
},
|
|
18
|
+
{}
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
} catch (error) {
|
|
22
|
+
console.error('Error publishing document', error);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function publishTranslations(
|
|
27
|
+
documentIds: string[],
|
|
28
|
+
client: SanityClient
|
|
29
|
+
) {
|
|
30
|
+
const publishedDocumentIds: string[] = [];
|
|
31
|
+
await processBatch(
|
|
32
|
+
documentIds,
|
|
33
|
+
async (documentId) => {
|
|
34
|
+
const document = await findDocument(`drafts.${documentId}`, client);
|
|
35
|
+
if (!document) {
|
|
36
|
+
return { documentId, published: false };
|
|
37
|
+
}
|
|
38
|
+
await publishDocument(document._id, client);
|
|
39
|
+
publishedDocumentIds.push(documentId);
|
|
40
|
+
return { documentId, published: true };
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
onItemFailure: (documentId, error) => {
|
|
44
|
+
console.error(`Failed to publish document ${documentId}:`, error);
|
|
45
|
+
},
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
return publishedDocumentIds;
|
|
49
|
+
}
|