gt-sanity 0.0.5 → 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.
Files changed (108) hide show
  1. package/LICENSE.md +1 -8
  2. package/README.md +5 -5
  3. package/dist/index.d.mts +122 -95
  4. package/dist/index.d.ts +122 -95
  5. package/dist/index.js +9089 -1119
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.mjs +9099 -1100
  8. package/dist/index.mjs.map +1 -1
  9. package/package.json +11 -4
  10. package/src/adapter/core.ts +111 -9
  11. package/src/adapter/createTask.ts +1 -1
  12. package/src/adapter/getLocales.ts +2 -2
  13. package/src/adapter/types.ts +9 -0
  14. package/src/components/TranslationsProvider.tsx +942 -0
  15. package/src/components/page/BatchProgress.tsx +27 -0
  16. package/src/components/page/ImportAllDialog.tsx +51 -0
  17. package/src/components/page/ImportMissingDialog.tsx +55 -0
  18. package/src/components/page/TranslateAllDialog.tsx +55 -0
  19. package/src/components/page/TranslationsTable.tsx +81 -0
  20. package/src/components/page/TranslationsTool.tsx +338 -0
  21. package/src/components/shared/BaseTranslationWrapper.tsx +82 -0
  22. package/src/components/{LanguageStatus.tsx → shared/LanguageStatus.tsx} +2 -0
  23. package/src/components/shared/LocaleCheckbox.tsx +47 -0
  24. package/src/components/{ProgressBar.tsx → shared/ProgressBar.tsx} +2 -0
  25. package/src/components/shared/SingleDocumentView.tsx +108 -0
  26. package/src/components/tab/TranslationView.tsx +379 -0
  27. package/src/components/tab/TranslationsTab.tsx +25 -0
  28. package/src/configuration/baseDocumentLevelConfig/documentLevelPatch.ts +21 -11
  29. package/src/configuration/baseDocumentLevelConfig/helpers/createI18nDocAndPatchMetadata.ts +57 -23
  30. package/src/configuration/baseDocumentLevelConfig/helpers/createTranslationMetadata.ts +2 -0
  31. package/src/configuration/baseDocumentLevelConfig/helpers/getOrCreateTranslationMetadata.ts +2 -0
  32. package/src/configuration/baseDocumentLevelConfig/helpers/getTranslationMetadata.ts +2 -0
  33. package/src/configuration/baseDocumentLevelConfig/helpers/patchI18nDoc.ts +31 -8
  34. package/src/configuration/baseDocumentLevelConfig/index.ts +18 -101
  35. package/src/configuration/baseFieldLevelConfig.ts +19 -51
  36. package/src/configuration/utils/checkSerializationVersion.ts +2 -0
  37. package/src/configuration/utils/findDocumentAtRevision.ts +2 -0
  38. package/src/configuration/utils/findLatestDraft.ts +2 -0
  39. package/src/hooks/useClient.ts +3 -1
  40. package/src/hooks/useSecrets.ts +2 -0
  41. package/src/index.ts +91 -67
  42. package/src/sanity-api/findDocuments.ts +44 -0
  43. package/src/sanity-api/publishDocuments.ts +49 -0
  44. package/src/sanity-api/resolveRefs.ts +146 -0
  45. package/src/serialization/BaseDocumentMerger.ts +138 -0
  46. package/src/serialization/BaseSerializationConfig.ts +220 -0
  47. package/src/serialization/__tests__/BaseDocumentDeserializer/__snapshots__/documentLevelDeserialization.test.ts.snap +189 -0
  48. package/src/serialization/__tests__/BaseDocumentDeserializer/__snapshots__/fieldLevelDeserialization.test.ts.snap +107 -0
  49. package/src/serialization/__tests__/BaseDocumentDeserializer/baseDeserialization.test.ts +397 -0
  50. package/src/serialization/__tests__/BaseDocumentDeserializer/documentLevelDeserialization.test.ts +107 -0
  51. package/src/serialization/__tests__/BaseDocumentDeserializer/fieldLevelDeserialization.test.ts +107 -0
  52. package/src/serialization/__tests__/BaseDocumentMerger/__snapshots__/documentLevelMerge.test.ts.snap +193 -0
  53. package/src/serialization/__tests__/BaseDocumentMerger/__snapshots__/fieldLevelMerge.test.ts.snap +97 -0
  54. package/src/serialization/__tests__/BaseDocumentMerger/baseMerge.test.ts +36 -0
  55. package/src/serialization/__tests__/BaseDocumentMerger/documentLevelMerge.test.ts +96 -0
  56. package/src/serialization/__tests__/BaseDocumentMerger/fieldLevelMerge.test.ts +142 -0
  57. package/src/serialization/__tests__/BaseDocumentMerger/utils.ts +52 -0
  58. package/src/serialization/__tests__/BaseDocumentSerializer/__snapshots__/documentInlineMarks.test.ts.snap +39 -0
  59. package/src/serialization/__tests__/BaseDocumentSerializer/__snapshots__/documentLevelSerialization.test.ts.snap +8 -0
  60. package/src/serialization/__tests__/BaseDocumentSerializer/__snapshots__/fieldLevelSerialization.test.ts.snap +8 -0
  61. package/src/serialization/__tests__/BaseDocumentSerializer/baseSerialization.test.ts +345 -0
  62. package/src/serialization/__tests__/BaseDocumentSerializer/documentInlineMarks.test.ts +53 -0
  63. package/src/serialization/__tests__/BaseDocumentSerializer/documentLevelSerialization.test.ts +120 -0
  64. package/src/serialization/__tests__/BaseDocumentSerializer/fieldLevelSerialization.test.ts +153 -0
  65. package/src/serialization/__tests__/BaseDocumentSerializer/utils.ts +27 -0
  66. package/src/serialization/__tests__/README +2 -0
  67. package/src/serialization/__tests__/__fixtures__/annotationAndInlineBlocks.json +140 -0
  68. package/src/serialization/__tests__/__fixtures__/customStyles.json +62 -0
  69. package/src/serialization/__tests__/__fixtures__/documentInlineMarks.json +70 -0
  70. package/src/serialization/__tests__/__fixtures__/documentLevelArticle.json +185 -0
  71. package/src/serialization/__tests__/__fixtures__/fieldLevelArticle.json +107 -0
  72. package/src/serialization/__tests__/__fixtures__/inlineDocumentLevelArticle.json +134 -0
  73. package/src/serialization/__tests__/__fixtures__/inlineSchema.ts +270 -0
  74. package/src/serialization/__tests__/__fixtures__/messy-html.html +26 -0
  75. package/src/serialization/__tests__/__fixtures__/nestedLanguageFields.json +54 -0
  76. package/src/serialization/__tests__/__fixtures__/schema.ts +310 -0
  77. package/src/serialization/__tests__/global.setup.ts +40 -0
  78. package/src/serialization/__tests__/helpers.ts +132 -0
  79. package/src/serialization/data.ts +82 -0
  80. package/src/serialization/deserialize/BaseDocumentDeserializer.ts +171 -0
  81. package/src/serialization/deserialize/helpers.ts +42 -0
  82. package/src/serialization/helpers.ts +18 -0
  83. package/src/serialization/index.ts +11 -0
  84. package/src/serialization/serialize/fieldFilters.ts +124 -0
  85. package/src/serialization/serialize/index.ts +284 -0
  86. package/src/serialization/types.ts +41 -0
  87. package/src/translation/checkTranslationStatus.ts +42 -0
  88. package/src/translation/createJobs.ts +16 -0
  89. package/src/translation/downloadTranslations.ts +68 -0
  90. package/src/translation/importDocument.ts +23 -0
  91. package/src/translation/initProject.ts +61 -0
  92. package/src/translation/uploadFiles.ts +32 -0
  93. package/src/types.ts +7 -20
  94. package/src/utils/applyDocuments.ts +72 -0
  95. package/src/utils/batchProcessor.ts +111 -0
  96. package/src/utils/importUtils.ts +95 -0
  97. package/src/utils/serialize.ts +52 -0
  98. package/src/utils/shared.ts +1 -0
  99. package/src/adapter/index.ts +0 -13
  100. package/src/components/NewTask.tsx +0 -249
  101. package/src/components/TaskView.tsx +0 -255
  102. package/src/components/TranslationContext.tsx +0 -19
  103. package/src/components/TranslationView.tsx +0 -82
  104. package/src/components/TranslationsTab.tsx +0 -177
  105. package/src/configuration/baseDocumentLevelConfig/helpers/index.ts +0 -5
  106. package/src/configuration/baseDocumentLevelConfig/legacyDocumentLevelPatch.ts +0 -69
  107. package/src/configuration/index.ts +0 -18
  108. package/src/configuration/utils/index.ts +0 -3
@@ -1,12 +1,18 @@
1
+ // adapted from https://github.com/sanity-io/sanity-translations-tab. See LICENSE.md for more details.
2
+
1
3
  import { SanityClient, SanityDocumentLike } from 'sanity';
4
+ import { pluginConfig } from '../../../adapter/core';
5
+ import { applyDocuments } from '../../../utils/applyDocuments';
2
6
 
3
- export const createI18nDocAndPatchMetadata = (
7
+ export async function createI18nDocAndPatchMetadata(
8
+ sourceDocument: SanityDocumentLike,
4
9
  translatedDoc: SanityDocumentLike,
5
10
  localeId: string,
6
11
  client: SanityClient,
7
12
  translationMetadata: SanityDocumentLike,
13
+ sourceDocumentId: string,
8
14
  languageField: string = 'language'
9
- ): void => {
15
+ ): Promise<void> {
10
16
  translatedDoc[languageField] = localeId;
11
17
  const translations = translationMetadata.translations as Record<
12
18
  string,
@@ -22,26 +28,54 @@ export const createI18nDocAndPatchMetadata = (
22
28
 
23
29
  //remove system fields
24
30
  const { _updatedAt, _createdAt, ...rest } = translatedDoc;
25
- client.create({ ...rest, _id: 'drafts.' }).then((doc) => {
26
- const _ref = doc._id.replace('drafts.', '');
27
- client
28
- .transaction()
29
- .patch(translationMetadata._id, (p) =>
30
- p.insert(operation, location, [
31
- {
32
- _key: localeId,
33
- _type: 'internationalizedArrayReferenceValue',
34
- value: {
35
- _type: 'reference',
36
- _ref,
37
- _weak: true,
38
- _strengthenOnPublish: {
39
- type: doc._type,
40
- },
31
+
32
+ const appliedDocument = applyDocuments(
33
+ sourceDocumentId,
34
+ sourceDocument,
35
+ rest,
36
+ pluginConfig.getIgnoreFields()
37
+ );
38
+
39
+ // Check if this is a singleton document and apply singleton mapping
40
+ const singletons = pluginConfig.getSingletons();
41
+ const isSingleton = singletons.includes(sourceDocumentId);
42
+
43
+ let createDocumentPromise;
44
+ if (isSingleton) {
45
+ const singletonMapping = pluginConfig.getSingletonMapping();
46
+ const translatedDocId = singletonMapping(sourceDocumentId, localeId);
47
+ createDocumentPromise = client.create({
48
+ ...appliedDocument,
49
+ _type: rest._type,
50
+ _id: `drafts.${translatedDocId}`,
51
+ });
52
+ } else {
53
+ createDocumentPromise = client.create({
54
+ ...appliedDocument,
55
+ _type: rest._type,
56
+ _id: 'drafts.',
57
+ });
58
+ }
59
+
60
+ const doc = await createDocumentPromise;
61
+ const _ref = doc._id.replace('drafts.', '');
62
+ const result = await client
63
+ .transaction()
64
+ .patch(translationMetadata._id, (p) =>
65
+ p.insert(operation, location, [
66
+ {
67
+ _key: localeId,
68
+ _type: 'internationalizedArrayReferenceValue',
69
+ value: {
70
+ _type: 'reference',
71
+ _ref,
72
+ _weak: true,
73
+ _strengthenOnPublish: {
74
+ type: doc._type,
41
75
  },
42
76
  },
43
- ])
44
- )
45
- .commit();
46
- });
47
- };
77
+ },
78
+ ])
79
+ )
80
+ .commit();
81
+ }
@@ -1,3 +1,5 @@
1
+ // adapted from https://github.com/sanity-io/sanity-translations-tab. See LICENSE.md for more details.
2
+
1
3
  import {
2
4
  KeyedObject,
3
5
  Reference,
@@ -1,3 +1,5 @@
1
+ // adapted from https://github.com/sanity-io/sanity-translations-tab. See LICENSE.md for more details.
2
+
1
3
  import {
2
4
  KeyedObject,
3
5
  Reference,
@@ -1,3 +1,5 @@
1
+ // adapted from https://github.com/sanity-io/sanity-translations-tab. See LICENSE.md for more details.
2
+
1
3
  import { SanityClient, SanityDocumentLike } from 'sanity';
2
4
 
3
5
  export const getTranslationMetadata = (
@@ -1,25 +1,48 @@
1
+ // adapted from https://github.com/sanity-io/sanity-translations-tab. See LICENSE.md for more details.
2
+
1
3
  import { SanityClient, SanityDocumentLike } from 'sanity';
4
+ import { applyDocuments } from '../../../utils/applyDocuments';
5
+ import { pluginConfig } from '../../../adapter/core';
6
+
7
+ const SYSTEM_FIELDS = ['_id', '_rev', '_updatedAt', 'language'];
2
8
 
3
- export const patchI18nDoc = (
9
+ const isSystemField = (field: string) => SYSTEM_FIELDS.includes(field);
10
+
11
+ export async function patchI18nDoc(
12
+ sourceDocumentId: string,
4
13
  i18nDocId: string,
14
+ sourceDocument: SanityDocumentLike,
5
15
  mergedDocument: SanityDocumentLike,
6
16
  translatedFields: Record<string, any>,
7
17
  client: SanityClient
8
- ): void => {
18
+ ): Promise<void> {
9
19
  const cleanedMerge: Record<string, any> = {};
10
20
  Object.entries(mergedDocument).forEach(([key, value]) => {
11
21
  if (
12
22
  //only patch those fields that had translated strings
13
23
  key in translatedFields &&
14
24
  //don't overwrite any existing system values on the i18n doc
15
- !['_id', '_rev', '_updatedAt', 'language'].includes(key)
25
+ !isSystemField(key)
16
26
  ) {
17
27
  cleanedMerge[key] = value;
18
28
  }
19
29
  });
20
-
21
- client
22
- .transaction()
23
- .patch(i18nDocId, (p) => p.set(cleanedMerge))
30
+ const cleanedSourceDocument: Record<string, any> = {};
31
+ Object.entries(sourceDocument).forEach(([key, value]) => {
32
+ if (
33
+ // extract only the fields that are not system fields
34
+ !isSystemField(key)
35
+ ) {
36
+ cleanedSourceDocument[key] = value;
37
+ }
38
+ });
39
+ const appliedDocument = applyDocuments(
40
+ sourceDocumentId,
41
+ cleanedSourceDocument,
42
+ cleanedMerge,
43
+ pluginConfig.getIgnoreFields()
44
+ );
45
+ const newDocument = await client
46
+ .patch(i18nDocId, { set: appliedDocument })
24
47
  .commit();
25
- };
48
+ }
@@ -1,53 +1,26 @@
1
+ // adapted from https://github.com/sanity-io/sanity-translations-tab. See LICENSE.md for more details.
2
+
1
3
  import {
2
4
  ExportForTranslation,
3
5
  GTSerializedDocument,
4
6
  ImportTranslation,
5
7
  } from '../../types';
6
- import { SanityDocument } from 'sanity';
7
- import { findLatestDraft } from '../utils';
8
- import { documentLevelPatch } from './documentLevelPatch';
9
- import { legacyDocumentLevelPatch } from './legacyDocumentLevelPatch';
10
- import {
11
- BaseDocumentDeserializer,
12
- BaseDocumentSerializer,
13
- defaultStopTypes,
14
- customSerializers,
15
- customBlockDeserializers,
16
- } from 'sanity-naive-html-serializer';
17
- import { gtConfig } from '../../adapter/core';
8
+ import { findLatestDraft } from '../utils/findLatestDraft';
9
+ import { pluginConfig } from '../../adapter/core';
10
+ import { importDocument } from '../../translation/importDocument';
11
+ import { serializeDocument } from '../../utils/serialize';
18
12
 
19
13
  export const baseDocumentLevelConfig = {
20
14
  exportForTranslation: async (
21
- ...params: Parameters<ExportForTranslation>
15
+ docInfo: Parameters<ExportForTranslation>[0],
16
+ context: Parameters<ExportForTranslation>[1]
22
17
  ): Promise<GTSerializedDocument> => {
23
- const [
24
- docInfo,
25
- context,
26
- serializationOptions = {},
27
- languageField = 'language',
28
- ] = params;
29
18
  const { client, schema } = context;
30
- const stopTypes = [
31
- ...(serializationOptions.additionalStopTypes ?? []),
32
- ...defaultStopTypes,
33
- ];
34
- const serializers = {
35
- ...customSerializers,
36
- types: {
37
- ...customSerializers.types,
38
- ...(serializationOptions.additionalSerializers ?? {}),
39
- },
40
- };
19
+ const languageField = pluginConfig.getLanguageField();
41
20
  const doc = await findLatestDraft(docInfo.documentId, client);
42
21
  delete doc[languageField];
43
- const baseLanguage = gtConfig.getSourceLocale();
44
- const serialized = BaseDocumentSerializer(schema).serializeDocument(
45
- doc,
46
- 'document',
47
- baseLanguage,
48
- stopTypes,
49
- serializers
50
- );
22
+ const baseLanguage = pluginConfig.getSourceLocale();
23
+ const serialized = serializeDocument(doc, schema, baseLanguage);
51
24
  return {
52
25
  content: serialized.content,
53
26
  documentId: docInfo.documentId,
@@ -55,75 +28,19 @@ export const baseDocumentLevelConfig = {
55
28
  };
56
29
  },
57
30
  importTranslation: (
58
- ...params: Parameters<ImportTranslation>
31
+ docInfo: Parameters<ImportTranslation>[0],
32
+ localeId: Parameters<ImportTranslation>[1],
33
+ document: Parameters<ImportTranslation>[2],
34
+ context: Parameters<ImportTranslation>[3],
35
+ mergeWithTargetLocale: boolean = false
59
36
  ): Promise<void> => {
60
- const [
37
+ return importDocument(
61
38
  docInfo,
62
39
  localeId,
63
40
  document,
64
41
  context,
65
- serializationOptions = {},
66
- languageField = 'language',
67
- mergeWithTargetLocale = false,
68
- ] = params;
69
- const { client } = context;
70
- const deserializers = {
71
- types: {
72
- ...(serializationOptions.additionalDeserializers ?? {}),
73
- },
74
- };
75
- const blockDeserializers = [
76
- ...(serializationOptions.additionalBlockDeserializers ?? []),
77
- ...customBlockDeserializers,
78
- ];
79
-
80
- const deserialized = BaseDocumentDeserializer.deserializeDocument(
81
- document,
82
- deserializers,
83
- blockDeserializers
84
- ) as SanityDocument;
85
- return documentLevelPatch(
86
- docInfo, // versionId is not used here, since we just use the _rev id in the deserialized HTML itself
87
- deserialized,
88
- localeId,
89
- client,
90
- languageField,
91
42
  mergeWithTargetLocale
92
43
  );
93
44
  },
94
- secretsNamespace: 'translationService',
45
+ secretsNamespace: 'generaltranslation',
95
46
  };
96
-
97
- export const legacyDocumentLevelConfig = {
98
- ...baseDocumentLevelConfig,
99
- importTranslation: (
100
- ...params: Parameters<ImportTranslation>
101
- ): Promise<void> => {
102
- const [docInfo, localeId, document, context, serializationOptions = {}] =
103
- params;
104
- const { client } = context;
105
- const deserializers = {
106
- types: {
107
- ...(serializationOptions.additionalDeserializers ?? {}),
108
- },
109
- };
110
- const blockDeserializers = [
111
- ...(serializationOptions.additionalBlockDeserializers ?? []),
112
- ...customBlockDeserializers,
113
- ];
114
-
115
- const deserialized = BaseDocumentDeserializer.deserializeDocument(
116
- document,
117
- deserializers,
118
- blockDeserializers
119
- ) as SanityDocument;
120
- return legacyDocumentLevelPatch(
121
- docInfo, // versionId is not used here, since we just use the _rev id in the deserialized HTML itself
122
- deserialized,
123
- localeId,
124
- client
125
- );
126
- },
127
- };
128
-
129
- export { documentLevelPatch, legacyDocumentLevelPatch };
@@ -1,3 +1,5 @@
1
+ // adapted from https://github.com/sanity-io/sanity-translations-tab. See LICENSE.md for more details.
2
+
1
3
  import { SanityClient, SanityDocument } from 'sanity';
2
4
  import {
3
5
  BaseDocumentSerializer,
@@ -6,7 +8,7 @@ import {
6
8
  defaultStopTypes,
7
9
  customSerializers,
8
10
  customBlockDeserializers,
9
- } from 'sanity-naive-html-serializer';
11
+ } from '../serialization/';
10
12
 
11
13
  import type {
12
14
  ExportForTranslation,
@@ -14,8 +16,10 @@ import type {
14
16
  GTSerializedDocument,
15
17
  ImportTranslation,
16
18
  } from '../types';
17
- import { findLatestDraft, findDocumentAtRevision } from './utils';
18
- import { gtConfig } from '../adapter/core';
19
+ import { findLatestDraft } from './utils/findLatestDraft';
20
+ import { findDocumentAtRevision } from './utils/findDocumentAtRevision';
21
+ import { pluginConfig } from '../adapter/core';
22
+ import { deserializeDocument, serializeDocument } from '../utils/serialize';
19
23
 
20
24
  export const fieldLevelPatch = async (
21
25
  docInfo: GTFile,
@@ -25,7 +29,7 @@ export const fieldLevelPatch = async (
25
29
  mergeWithTargetLocale: boolean = false
26
30
  ): Promise<void> => {
27
31
  let baseDoc: SanityDocument;
28
- const baseLanguage = gtConfig.getSourceLocale();
32
+ const baseLanguage = pluginConfig.getSourceLocale();
29
33
  if (docInfo.documentId && docInfo.versionId) {
30
34
  baseDoc = await findDocumentAtRevision(
31
35
  docInfo.documentId,
@@ -48,30 +52,13 @@ export const fieldLevelPatch = async (
48
52
 
49
53
  export const baseFieldLevelConfig = {
50
54
  exportForTranslation: async (
51
- ...params: Parameters<ExportForTranslation>
55
+ docInfo: Parameters<ExportForTranslation>[0],
56
+ context: Parameters<ExportForTranslation>[1]
52
57
  ): Promise<GTSerializedDocument> => {
53
- const [docInfo, context, serializationOptions = {}] = params;
54
- const baseLanguage = gtConfig.getSourceLocale();
58
+ const baseLanguage = pluginConfig.getSourceLocale();
55
59
  const { client, schema } = context;
56
- const stopTypes = [
57
- ...(serializationOptions.additionalStopTypes ?? []),
58
- ...defaultStopTypes,
59
- ];
60
- const serializers = {
61
- ...customSerializers,
62
- types: {
63
- ...customSerializers.types,
64
- ...(serializationOptions.additionalSerializers ?? {}),
65
- },
66
- };
67
60
  const doc = await findLatestDraft(docInfo.documentId, client);
68
- const serialized = BaseDocumentSerializer(schema).serializeDocument(
69
- doc,
70
- 'field',
71
- baseLanguage,
72
- stopTypes,
73
- serializers
74
- );
61
+ const serialized = serializeDocument(doc, schema, baseLanguage);
75
62
  return {
76
63
  content: serialized.content,
77
64
  documentId: docInfo.documentId,
@@ -79,33 +66,14 @@ export const baseFieldLevelConfig = {
79
66
  };
80
67
  },
81
68
  importTranslation: (
82
- ...params: Parameters<ImportTranslation>
69
+ docInfo: Parameters<ImportTranslation>[0],
70
+ localeId: Parameters<ImportTranslation>[1],
71
+ document: Parameters<ImportTranslation>[2],
72
+ context: Parameters<ImportTranslation>[3],
73
+ mergeWithTargetLocale: boolean = false
83
74
  ): Promise<void> => {
84
- const [
85
- docInfo,
86
- localeId,
87
- document,
88
- context,
89
- serializationOptions = {},
90
- ,
91
- mergeWithTargetLocale,
92
- ] = params;
93
75
  const { client } = context;
94
- const deserializers = {
95
- types: {
96
- ...(serializationOptions.additionalDeserializers ?? {}),
97
- },
98
- };
99
- const blockDeserializers = [
100
- ...(serializationOptions.additionalBlockDeserializers ?? []),
101
- ...customBlockDeserializers,
102
- ];
103
-
104
- const deserialized = BaseDocumentDeserializer.deserializeDocument(
105
- document,
106
- deserializers,
107
- blockDeserializers
108
- ) as SanityDocument;
76
+ const deserialized = deserializeDocument(document);
109
77
  return fieldLevelPatch(
110
78
  docInfo,
111
79
  deserialized,
@@ -114,5 +82,5 @@ export const baseFieldLevelConfig = {
114
82
  mergeWithTargetLocale
115
83
  );
116
84
  },
117
- secretsNamespace: 'translationService',
85
+ secretsNamespace: 'generaltranslation',
118
86
  };
@@ -1,3 +1,5 @@
1
+ // adapted from https://github.com/sanity-io/sanity-translations-tab. See LICENSE.md for more details.
2
+
1
3
  export const checkSerializationVersion = (HTMLdoc: string): string | null => {
2
4
  const parser = new DOMParser();
3
5
  const node = parser.parseFromString(HTMLdoc, 'text/html');
@@ -1,3 +1,5 @@
1
+ // adapted from https://github.com/sanity-io/sanity-translations-tab. See LICENSE.md for more details.
2
+
1
3
  import { SanityClient, SanityDocument } from 'sanity';
2
4
 
3
5
  //revision fetch
@@ -1,3 +1,5 @@
1
+ // adapted from https://github.com/sanity-io/sanity-translations-tab. See LICENSE.md for more details.
2
+
1
3
  import { SanityClient, SanityDocument } from 'sanity';
2
4
 
3
5
  //use perspectives in the future
@@ -1,5 +1,7 @@
1
+ // adapted from https://github.com/sanity-io/sanity-translations-tab. See LICENSE.md for more details.
2
+
1
3
  import { SanityClient, useClient as useSanityClient } from 'sanity';
2
4
 
3
5
  export const useClient = (): SanityClient => {
4
- return useSanityClient({ apiVersion: '2022-12-07' });
6
+ return useSanityClient({ apiVersion: '2025-09-15' });
5
7
  };
@@ -1,3 +1,5 @@
1
+ // adapted from https://github.com/sanity-io/sanity-translations-tab. See LICENSE.md for more details.
2
+
1
3
  import { useState, useEffect } from 'react';
2
4
  import { SanityDocumentLike } from 'sanity';
3
5
  import { useClient } from './useClient';
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,17 +6,8 @@ import {
6
6
  ImportTranslation,
7
7
  TranslationFunctionContext,
8
8
  TranslationsTabConfigOptions,
9
- GTFile,
10
9
  } from './types';
11
- import {
12
- baseDocumentLevelConfig,
13
- legacyDocumentLevelConfig as baseLegacyDocumentLevelConfig,
14
- legacyDocumentLevelPatch,
15
- baseFieldLevelConfig,
16
- findLatestDraft,
17
- documentLevelPatch,
18
- fieldLevelPatch,
19
- } from './configuration';
10
+ import { findLatestDraft } from './configuration/utils/findLatestDraft';
20
11
  import {
21
12
  BaseDocumentSerializer,
22
13
  BaseDocumentDeserializer,
@@ -24,7 +15,7 @@ import {
24
15
  defaultStopTypes,
25
16
  customSerializers,
26
17
  SerializedDocument,
27
- } from 'sanity-naive-html-serializer';
18
+ } from './serialization';
28
19
 
29
20
  export type {
30
21
  Secrets,
@@ -39,63 +30,50 @@ export {
39
30
  TranslationsTab,
40
31
  //helpers for end developers who may need to customize serialization
41
32
  findLatestDraft,
42
- legacyDocumentLevelPatch,
43
- documentLevelPatch,
44
- fieldLevelPatch,
45
33
  BaseDocumentSerializer,
46
34
  BaseDocumentDeserializer,
47
35
  BaseDocumentMerger,
48
36
  defaultStopTypes,
49
37
  customSerializers,
38
+ attachGTData,
39
+ detachGTData,
50
40
  };
51
41
 
52
- import { GTAdapter } from './adapter';
53
42
  import { definePlugin } from 'sanity';
54
- import { gt, gtConfig } from './adapter/core';
55
- import { GTSerializedDocument } from './types';
43
+ import { route } from 'sanity/router';
44
+ import { gt, pluginConfig } from './adapter/core';
56
45
  import { libraryDefaultLocale } from 'generaltranslation/internal';
46
+ import type { IgnoreFields, TranslateDocumentFilter } from './adapter/types';
47
+ import TranslationsTool from './components/page/TranslationsTool';
48
+ import { SECRETS_NAMESPACE } from './utils/shared';
49
+ import type { PortableTextHtmlComponents } from '@portabletext/to-html';
50
+ import { attachGTData, detachGTData } from './serialization/data';
57
51
 
58
- interface ConfigOptions {
59
- adapter: Adapter;
60
- secretsNamespace: string | null;
61
- exportForTranslation: (
62
- docInfo: GTFile,
63
- context: TranslationFunctionContext
64
- ) => Promise<GTSerializedDocument>;
65
- importTranslation: (
66
- docInfo: GTFile,
67
- localeId: string,
68
- doc: string,
69
- context: TranslationFunctionContext
70
- ) => Promise<void>;
71
- }
72
-
73
- export const defaultDocumentLevelConfig: ConfigOptions = {
74
- ...baseDocumentLevelConfig,
75
- adapter: GTAdapter,
76
- secretsNamespace: 'generaltranslation',
77
- };
78
-
79
- export const legacyDocumentLevelConfig: ConfigOptions = {
80
- ...baseLegacyDocumentLevelConfig,
81
- adapter: GTAdapter,
82
- secretsNamespace: 'generaltranslation',
52
+ export type GTPluginConfig = Omit<
53
+ Parameters<typeof gt.setConfig>[0],
54
+ 'locales'
55
+ > & {
56
+ locales: string[];
57
+ singletons?: string[];
58
+ // Optional mapping function to map source document ids to translated singleton document ids
59
+ // By default, the translated singleton document is is `${sourceDocumentId}-${locale}`
60
+ singletonMapping?: (sourceDocumentId: string, locale: string) => string;
61
+ ignoreFields?: IgnoreFields[];
62
+ languageField?: string;
63
+ translateDocuments?: TranslateDocumentFilter[];
64
+ secretsNamespace?: string;
65
+ additionalStopTypes?: string[];
66
+ additionalSerializers?: Partial<PortableTextHtmlComponents>;
67
+ additionalDeserializers?: Record<string, any>;
68
+ additionalBlockDeserializers?: any[];
83
69
  };
84
70
 
85
- export const defaultFieldLevelConfig: ConfigOptions = {
86
- ...baseFieldLevelConfig,
87
- adapter: GTAdapter,
88
- secretsNamespace: 'generaltranslation',
89
- };
90
-
91
- export { GTAdapter };
92
-
93
71
  /**
94
72
  * Usage in `sanity.config.ts` (or .js)
95
73
  *
96
74
  * ```ts
97
75
  * import {defineConfig} from 'sanity'
98
- * import {gtPlugin} from '@generaltranslation/sanity'
76
+ * import {gtPlugin} from 'gt-sanity'
99
77
  *
100
78
  * export default defineConfig({
101
79
  * // ...
@@ -103,18 +81,64 @@ export { GTAdapter };
103
81
  * })
104
82
  * ```
105
83
  */
106
- export const gtPlugin = definePlugin<
107
- Omit<Parameters<typeof gt.setConfig>[0], 'locales'> & { locales: string[] }
108
- >(({ sourceLocale, locales, customMapping, apiKey, projectId }) => {
109
- gtConfig.setLocales(locales);
110
- gtConfig.setSourceLocale(sourceLocale || libraryDefaultLocale);
111
- gt.setConfig({
112
- sourceLocale: sourceLocale,
113
- customMapping: customMapping,
114
- apiKey: apiKey,
115
- projectId: projectId,
116
- });
117
- return {
118
- name: '@generaltranslation/sanity',
119
- };
120
- });
84
+ export const gtPlugin = definePlugin<GTPluginConfig>(
85
+ ({
86
+ languageField = 'language',
87
+ sourceLocale = libraryDefaultLocale,
88
+ locales,
89
+ customMapping,
90
+ apiKey,
91
+ projectId,
92
+ singletons,
93
+ singletonMapping,
94
+ ignoreFields,
95
+ translateDocuments,
96
+ secretsNamespace = SECRETS_NAMESPACE,
97
+ additionalStopTypes = [],
98
+ additionalSerializers = {},
99
+ additionalDeserializers = {},
100
+ additionalBlockDeserializers = [],
101
+ }) => {
102
+ // Validate the translateDocuments
103
+ translateDocuments = translateDocuments?.filter((filter) => {
104
+ if (filter.documentId || filter.type) {
105
+ return true;
106
+ }
107
+ return false;
108
+ });
109
+
110
+ pluginConfig.init(
111
+ secretsNamespace,
112
+ languageField,
113
+ sourceLocale,
114
+ locales,
115
+ singletons || [],
116
+ // singletons is a string array of singleton document ids
117
+ singletonMapping ||
118
+ ((sourceDocumentId, locale) => `${sourceDocumentId}-${locale}`),
119
+ ignoreFields || [],
120
+ translateDocuments || [],
121
+ additionalStopTypes,
122
+ additionalSerializers,
123
+ additionalDeserializers,
124
+ additionalBlockDeserializers
125
+ );
126
+ gt.setConfig({
127
+ sourceLocale: sourceLocale,
128
+ customMapping: customMapping,
129
+ apiKey: apiKey,
130
+ projectId: projectId,
131
+ });
132
+ return {
133
+ name: 'gt-sanity',
134
+ tools: [
135
+ {
136
+ name: 'translations',
137
+ title: 'Translations',
138
+ component: TranslationsTool,
139
+ router: route.create('/*'),
140
+ },
141
+ ],
142
+ };
143
+ }
144
+ );