@sanity/document-internationalization 2.0.0-studio-v3-plugin-v2.7 → 2.0.0-studio-v3-plugin-v2.8

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/src/plugin.tsx CHANGED
@@ -1,14 +1,14 @@
1
- import React from 'react'
2
- import {definePlugin, defineField} from 'sanity'
3
- import {internationalizedArray} from 'sanity-plugin-internationalized-array'
4
1
  import {Stack} from '@sanity/ui'
2
+ import {defineField, definePlugin, isSanityDocument} from 'sanity'
3
+ import {internationalizedArray} from 'sanity-plugin-internationalized-array'
5
4
 
6
- import metadata from './schema/translation/metadata'
7
- import MenuButton from './components/MenuButton'
8
- import {PluginConfig} from './types'
9
5
  import {LanguageBadge} from './badges'
10
- import {METADATA_SCHEMA_NAME} from './constants'
11
6
  import BulkPublish from './components/BulkPublish'
7
+ import MenuButton from './components/MenuButton'
8
+ import OptimisticallyStrengthen from './components/OptimisticallyStrengthen'
9
+ import {API_VERSION, METADATA_SCHEMA_NAME} from './constants'
10
+ import metadata from './schema/translation/metadata'
11
+ import {PluginConfig, TranslationReference} from './types'
12
12
 
13
13
  const DEFAULT_CONFIG = {
14
14
  supportedLanguages: [],
@@ -17,159 +17,207 @@ const DEFAULT_CONFIG = {
17
17
  bulkPublish: false,
18
18
  }
19
19
 
20
- export const documentInternationalization = definePlugin<PluginConfig>((config) => {
21
- const {supportedLanguages, schemaTypes, languageField, bulkPublish} = {
22
- ...DEFAULT_CONFIG,
23
- ...config,
24
- }
20
+ export const documentInternationalization = definePlugin<PluginConfig>(
21
+ (config) => {
22
+ const {supportedLanguages, schemaTypes, languageField, bulkPublish} = {
23
+ ...DEFAULT_CONFIG,
24
+ ...config,
25
+ }
26
+
27
+ const renderLanguageFilter = (schemaType: string, documentId?: string) => {
28
+ return (
29
+ <MenuButton
30
+ supportedLanguages={supportedLanguages}
31
+ schemaType={schemaType}
32
+ documentId={documentId ?? ``}
33
+ languageField={languageField}
34
+ />
35
+ )
36
+ }
37
+
38
+ return {
39
+ name: '@sanity/document-internationalization',
40
+
41
+ // Adds:
42
+ // - A bulk-publishing UI component to the form
43
+ // - Will only work for projects on a compatible plan
44
+ form: {
45
+ components: {
46
+ input: (props) => {
47
+ if (
48
+ props.id === 'root' &&
49
+ props.schemaType.name === METADATA_SCHEMA_NAME &&
50
+ isSanityDocument(props?.value)
51
+ ) {
52
+ const metadataId = props?.value?._id
53
+ const translations =
54
+ (props?.value?.translations as TranslationReference[]) ?? []
55
+ const weakAndTypedTranslations = translations.filter(
56
+ (t) => t?.value?._weak && t.value?._strengthenOnPublish
57
+ )
58
+
59
+ return (
60
+ <Stack space={5}>
61
+ {bulkPublish ? (
62
+ <BulkPublish translations={translations} />
63
+ ) : null}
64
+ {weakAndTypedTranslations.length > 0 ? (
65
+ <OptimisticallyStrengthen
66
+ metadataId={metadataId}
67
+ translations={weakAndTypedTranslations}
68
+ />
69
+ ) : null}
70
+ {props.renderDefault(props)}
71
+ </Stack>
72
+ )
73
+ }
74
+
75
+ return props.renderDefault(props)
76
+ },
77
+ },
78
+ },
25
79
 
26
- const renderLanguageFilter = (schemaType: string, documentId?: string) => {
27
- return (
28
- <MenuButton
29
- supportedLanguages={supportedLanguages}
30
- schemaType={schemaType}
31
- documentId={documentId ?? ``}
32
- languageField={languageField}
33
- />
34
- )
35
- }
80
+ // Adds:
81
+ // - The `Translations` dropdown to the editing form
82
+ // - `Badges` to documents with a language value
83
+ document: {
84
+ unstable_languageFilter: (prev, ctx) => {
85
+ const {schemaType, documentId} = ctx
36
86
 
37
- return {
38
- name: '@sanity/document-internationalization',
39
-
40
- // Adds:
41
- // - A bulk-publishing UI component to the form
42
- // - Will only work for projects on a compatible plan
43
- form: {
44
- components: {
45
- input: (props) => {
46
- if (
47
- bulkPublish &&
48
- props.id === 'root' &&
49
- props.schemaType.name === METADATA_SCHEMA_NAME
50
- ) {
51
- return (
52
- <Stack space={5}>
53
- {/* <BulkPublish {...props} /> */}
54
- {props.renderDefault(props)}
55
- </Stack>
56
- )
87
+ return schemaTypes.includes(schemaType)
88
+ ? [...prev, () => renderLanguageFilter(schemaType, documentId)]
89
+ : prev
90
+ },
91
+ badges: (prev, {schemaType}) => {
92
+ if (!schemaTypes.includes(schemaType)) {
93
+ return prev
57
94
  }
58
95
 
59
- return props.renderDefault(props)
96
+ return [
97
+ (props) => LanguageBadge(props, supportedLanguages, languageField),
98
+ ...prev,
99
+ ]
60
100
  },
61
101
  },
62
- },
63
-
64
- // Adds:
65
- // - The `Translations` dropdown to the editing form
66
- // - `Badges` to documents with a language value
67
- document: {
68
- unstable_languageFilter: (prev, ctx) => {
69
- const {schemaType, documentId} = ctx
70
-
71
- return schemaTypes.includes(schemaType)
72
- ? [...prev, () => renderLanguageFilter(schemaType, documentId)]
73
- : prev
74
- },
75
- badges: (prev, {schemaType}) => {
76
- if (!schemaTypes.includes(schemaType)) {
77
- return prev
78
- }
79
102
 
80
- return [(props) => LanguageBadge(props, supportedLanguages, languageField), ...prev]
81
- },
82
- },
83
-
84
- // Adds:
85
- // - The `Translations metadata` document type to the schema
86
- schema: {
87
- // Create the metadata document type
88
- types: [metadata(schemaTypes)],
89
-
90
- // For every schema type this plugin is enabled on
91
- // Create an initial value template to set the language
92
- templates: (prev, {schema}) => {
93
- // Templates are not setup for async languages
94
- if (!Array.isArray(supportedLanguages)) {
95
- return prev
96
- }
97
-
98
- const parameterizedTemplates = schemaTypes.map((schemaType) => ({
99
- id: `${schemaType}-parameterized`,
100
- title: `${schema?.get(schemaType)?.title ?? schemaType}: with Language`,
101
- schemaType,
102
- parameters: [{name: `languageId`, title: `Language ID`, type: `string`}],
103
- value: ({languageId}: {languageId: string}) => ({
104
- [languageField]: languageId,
105
- }),
106
- }))
107
-
108
- const staticTemplates = schemaTypes.flatMap((schemaType) => {
109
- return supportedLanguages.map((language) => ({
110
- id: `${schemaType}-${language.id}`,
111
- title: `${language.title} ${schema?.get(schemaType)?.title ?? schemaType}`,
103
+ // Adds:
104
+ // - The `Translations metadata` document type to the schema
105
+ schema: {
106
+ // Create the metadata document type
107
+ types: [metadata(schemaTypes)],
108
+
109
+ // For every schema type this plugin is enabled on
110
+ // Create an initial value template to set the language
111
+ templates: (prev, {schema}) => {
112
+ // Templates are not setup for async languages
113
+ if (!Array.isArray(supportedLanguages)) {
114
+ return prev
115
+ }
116
+
117
+ const parameterizedTemplates = schemaTypes.map((schemaType) => ({
118
+ id: `${schemaType}-parameterized`,
119
+ title: `${
120
+ schema?.get(schemaType)?.title ?? schemaType
121
+ }: with Language`,
112
122
  schemaType,
113
- value: {
114
- [languageField]: language.id,
115
- },
123
+ parameters: [
124
+ {name: `languageId`, title: `Language ID`, type: `string`},
125
+ ],
126
+ value: ({languageId}: {languageId: string}) => ({
127
+ [languageField]: languageId,
128
+ }),
116
129
  }))
117
- })
118
130
 
119
- return [...prev, ...parameterizedTemplates, ...staticTemplates]
131
+ const staticTemplates = schemaTypes.flatMap((schemaType) => {
132
+ return supportedLanguages.map((language) => ({
133
+ id: `${schemaType}-${language.id}`,
134
+ title: `${language.title} ${
135
+ schema?.get(schemaType)?.title ?? schemaType
136
+ }`,
137
+ schemaType,
138
+ value: {
139
+ [languageField]: language.id,
140
+ },
141
+ }))
142
+ })
143
+
144
+ return [...prev, ...parameterizedTemplates, ...staticTemplates]
145
+ },
120
146
  },
121
- },
122
-
123
- // Uses:
124
- // - `sanity-plugin-internationalized-array` to maintain the translations array
125
- plugins: [
126
- // Translation metadata stores its references using this plugin
127
- // It cuts down on attribute usage and gives UI conveniences to add new translations
128
- internationalizedArray({
129
- languages: supportedLanguages,
130
- fieldTypes: [
131
- // TODO: The plugin should allow this kind of input
132
- // @ts-ignore
133
- defineField(
134
- {
135
- name: 'reference',
136
- type: 'reference',
137
- to: schemaTypes.map((type) => ({type: type})),
138
- // TODO: Add a validation rule to *ensure* the document's language matches the array key
139
- // Reference filters don't actually enforce validation!
140
- // validation: (Rule) => Rule.custom(),
141
- options: {
142
- collapsed: false,
143
- // TODO: Update type once it knows the values of this filter
144
- // @ts-ignore
145
- filter: ({parent, document}) => {
146
- if (!parent) return null
147
-
148
- // I'm not sure in what instance there's an array of parents
149
- // But the Type suggests it's possible
150
- const parentArray = Array.isArray(parent) ? parent : [parent]
151
- const language = parentArray.find((p) => p._key)
152
-
153
- if (!language?._key) return null
154
-
155
- if (document.schemaTypes) {
156
- return {
157
- filter: `_type in $schemaTypes && ${languageField} == $language`,
158
- params: {schemaTypes: document.schemaTypes, language: language._key},
147
+
148
+ // Uses:
149
+ // - `sanity-plugin-internationalized-array` to maintain the translations array
150
+ plugins: [
151
+ // Translation metadata stores its references using this plugin
152
+ // It cuts down on attribute usage and gives UI conveniences to add new translations
153
+ internationalizedArray({
154
+ languages: supportedLanguages,
155
+ fieldTypes: [
156
+ defineField(
157
+ {
158
+ name: 'reference',
159
+ type: 'reference',
160
+ to: schemaTypes.map((type) => ({type})),
161
+ // Reference filters don't actually enforce validation!
162
+ validation: (Rule) =>
163
+ Rule.custom(async (item: TranslationReference, context) => {
164
+ if (!item?.value?._ref || !item?._key) {
165
+ return true
159
166
  }
160
- }
161
167
 
162
- return {
163
- filter: `${languageField} == $language`,
164
- params: {language: language._key},
165
- }
168
+ const client = context.getClient({apiVersion: API_VERSION})
169
+ const valueLanguage = await client.fetch(
170
+ `*[_id in [$ref, $draftRef]][0].${languageField}`,
171
+ {
172
+ ref: item.value._ref,
173
+ draftRef: `drafts.${item.value._ref}`,
174
+ }
175
+ )
176
+
177
+ if (valueLanguage && valueLanguage === item._key) {
178
+ return true
179
+ }
180
+
181
+ return `Referenced document does not have the correct language value`
182
+ }),
183
+ options: {
184
+ collapsed: false,
185
+ // TODO: Update type once it knows the values of this filter
186
+ // @ts-expect-error
187
+ filter: ({parent, document}) => {
188
+ if (!parent) return null
189
+
190
+ // I'm not sure in what instance there's an array of parents
191
+ // But the Type suggests it's possible
192
+ const parentArray = Array.isArray(parent)
193
+ ? parent
194
+ : [parent]
195
+ const language = parentArray.find((p) => p._key)
196
+
197
+ if (!language?._key) return null
198
+
199
+ if (document.schemaTypes) {
200
+ return {
201
+ filter: `_type in $schemaTypes && ${languageField} == $language`,
202
+ params: {
203
+ schemaTypes: document.schemaTypes,
204
+ language: language._key,
205
+ },
206
+ }
207
+ }
208
+
209
+ return {
210
+ filter: `${languageField} == $language`,
211
+ params: {language: language._key},
212
+ }
213
+ },
166
214
  },
167
215
  },
168
- },
169
- {strict: false}
170
- ),
171
- ],
172
- }),
173
- ],
216
+ {strict: false}
217
+ ),
218
+ ],
219
+ }),
220
+ ],
221
+ }
174
222
  }
175
- })
223
+ )
@@ -18,7 +18,7 @@ export default (schemaTypes: string[]): DocumentDefinition =>
18
18
  defineField({
19
19
  name: 'schemaTypes',
20
20
  description:
21
- 'Used to filter the reference fields above so all translations share the same types.',
21
+ 'Optional: Used to filter the reference fields above so all translations share the same types.',
22
22
  type: 'array',
23
23
  // For some reason TS dislikes this line because of the DocumentDefinition return type
24
24
  // @ts-expect-error
package/src/types.ts CHANGED
@@ -1,4 +1,9 @@
1
- import type {SanityClient, SanityDocumentLike} from 'sanity'
1
+ import type {
2
+ KeyedObject,
3
+ Reference,
4
+ SanityClient,
5
+ SanityDocumentLike,
6
+ } from 'sanity'
2
7
 
3
8
  export type Language = {
4
9
  id: Intl.UnicodeBCP47LocaleIdentifier
@@ -16,12 +21,9 @@ export type PluginConfig = {
16
21
  bulkPublish?: boolean
17
22
  }
18
23
 
19
- export type TranslationReference = {
20
- _key: string
21
- value?: {
22
- _ref: string
23
- _type: 'reference'
24
- }
24
+ export type TranslationReference = KeyedObject & {
25
+ _type: 'internationalizedArrayReferenceValue'
26
+ value: Reference
25
27
  }
26
28
 
27
29
  export type Metadata = SanityDocumentLike & {