@sanity/document-internationalization 3.0.1 → 3.2.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/README.md +8 -1
- package/dist/_chunks-cjs/resources.js +8 -0
- package/dist/_chunks-cjs/resources.js.map +1 -0
- package/dist/_chunks-es/resources.mjs +9 -0
- package/dist/_chunks-es/resources.mjs.map +1 -0
- package/dist/_legacy/resources.esm.js +9 -0
- package/dist/_legacy/resources.esm.js.map +1 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.esm.js +586 -31
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +584 -27
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +586 -31
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/actions/DuplicateWithTranslationsAction.tsx +252 -0
- package/src/components/DocumentInternationalizationMenu.tsx +7 -1
- package/src/components/LanguageManage.tsx +76 -10
- package/src/constants.ts +1 -0
- package/src/hooks/useOpenInNewPane.tsx +1 -1
- package/src/i18n/index.ts +21 -0
- package/src/i18n/resources.ts +7 -0
- package/src/index.ts +1 -0
- package/src/plugin.tsx +5 -0
- package/src/types.ts +1 -0
package/package.json
CHANGED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import {CopyIcon} from '@sanity/icons'
|
|
2
|
+
import {useToast} from '@sanity/ui'
|
|
3
|
+
import {uuid} from '@sanity/uuid'
|
|
4
|
+
import {useCallback, useMemo, useState} from 'react'
|
|
5
|
+
import {filter, firstValueFrom} from 'rxjs'
|
|
6
|
+
import {
|
|
7
|
+
DEFAULT_STUDIO_CLIENT_OPTIONS,
|
|
8
|
+
type DocumentActionComponent,
|
|
9
|
+
type Id,
|
|
10
|
+
InsufficientPermissionsMessage,
|
|
11
|
+
type PatchOperations,
|
|
12
|
+
useClient,
|
|
13
|
+
useCurrentUser,
|
|
14
|
+
useDocumentOperation,
|
|
15
|
+
useDocumentPairPermissions,
|
|
16
|
+
useDocumentStore,
|
|
17
|
+
useTranslation,
|
|
18
|
+
} from 'sanity'
|
|
19
|
+
import {useRouter} from 'sanity/router'
|
|
20
|
+
import {structureLocaleNamespace} from 'sanity/structure'
|
|
21
|
+
|
|
22
|
+
import {METADATA_SCHEMA_NAME, TRANSLATIONS_ARRAY_NAME} from '../constants'
|
|
23
|
+
import {useTranslationMetadata} from '../hooks/useLanguageMetadata'
|
|
24
|
+
import {documenti18nLocaleNamespace} from '../i18n'
|
|
25
|
+
|
|
26
|
+
const DISABLED_REASON_KEY = {
|
|
27
|
+
METADATA_NOT_FOUND: 'action.duplicate.disabled.missing-metadata',
|
|
28
|
+
MULTIPLE_METADATA: 'action.duplicate.disabled.multiple-metadata',
|
|
29
|
+
NOTHING_TO_DUPLICATE: 'action.duplicate.disabled.nothing-to-duplicate',
|
|
30
|
+
NOT_READY: 'action.duplicate.disabled.not-ready',
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const DuplicateWithTranslationsAction: DocumentActionComponent = ({
|
|
34
|
+
id,
|
|
35
|
+
type,
|
|
36
|
+
onComplete,
|
|
37
|
+
}) => {
|
|
38
|
+
const documentStore = useDocumentStore()
|
|
39
|
+
const {duplicate} = useDocumentOperation(id, type)
|
|
40
|
+
const {navigateIntent} = useRouter()
|
|
41
|
+
const [isDuplicating, setDuplicating] = useState(false)
|
|
42
|
+
const [permissions, isPermissionsLoading] = useDocumentPairPermissions({
|
|
43
|
+
id,
|
|
44
|
+
type,
|
|
45
|
+
permission: 'duplicate',
|
|
46
|
+
})
|
|
47
|
+
const {data, loading: isMetadataDocumentLoading} = useTranslationMetadata(id)
|
|
48
|
+
const hasOneMetadataDocument = useMemo(() => {
|
|
49
|
+
return Array.isArray(data) && data.length <= 1
|
|
50
|
+
}, [data])
|
|
51
|
+
const metadataDocument = Array.isArray(data) && data.length ? data[0] : null
|
|
52
|
+
const client = useClient(DEFAULT_STUDIO_CLIENT_OPTIONS)
|
|
53
|
+
const toast = useToast()
|
|
54
|
+
const {t: s} = useTranslation(structureLocaleNamespace)
|
|
55
|
+
const {t: d} = useTranslation(documenti18nLocaleNamespace)
|
|
56
|
+
const currentUser = useCurrentUser()
|
|
57
|
+
|
|
58
|
+
const handle = useCallback(async () => {
|
|
59
|
+
setDuplicating(true)
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
if (!metadataDocument) {
|
|
63
|
+
throw new Error('Metadata document not found')
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// 1. Duplicate the document and its localized versions
|
|
67
|
+
const translations = new Map<string, Id>()
|
|
68
|
+
await Promise.all(
|
|
69
|
+
metadataDocument[TRANSLATIONS_ARRAY_NAME].map(async (translation) => {
|
|
70
|
+
const dupeId = uuid()
|
|
71
|
+
const locale = translation._key
|
|
72
|
+
const docId = translation.value?._ref
|
|
73
|
+
|
|
74
|
+
if (!docId) {
|
|
75
|
+
throw new Error('Translation document not found')
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const {duplicate: duplicateTranslation} = await firstValueFrom(
|
|
79
|
+
documentStore.pair
|
|
80
|
+
.editOperations(docId, type)
|
|
81
|
+
.pipe(filter((op) => op.duplicate.disabled !== 'NOT_READY'))
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
if (duplicateTranslation.disabled) {
|
|
85
|
+
throw new Error('Cannot duplicate document')
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const duplicateTranslationSuccess = firstValueFrom(
|
|
89
|
+
documentStore.pair
|
|
90
|
+
.operationEvents(docId, type)
|
|
91
|
+
.pipe(filter((e) => e.op === 'duplicate' && e.type === 'success'))
|
|
92
|
+
)
|
|
93
|
+
duplicateTranslation.execute(dupeId)
|
|
94
|
+
await duplicateTranslationSuccess
|
|
95
|
+
|
|
96
|
+
translations.set(locale, dupeId)
|
|
97
|
+
})
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
// 2. Duplicate the metadata document
|
|
101
|
+
const {duplicate: duplicateMetadata} = await firstValueFrom(
|
|
102
|
+
documentStore.pair
|
|
103
|
+
.editOperations(metadataDocument._id, METADATA_SCHEMA_NAME)
|
|
104
|
+
.pipe(filter((op) => op.duplicate.disabled !== 'NOT_READY'))
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
if (duplicateMetadata.disabled) {
|
|
108
|
+
throw new Error('Cannot duplicate document')
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const duplicateMetadataSuccess = firstValueFrom(
|
|
112
|
+
documentStore.pair
|
|
113
|
+
.operationEvents(metadataDocument._id, METADATA_SCHEMA_NAME)
|
|
114
|
+
.pipe(filter((e) => e.op === 'duplicate' && e.type === 'success'))
|
|
115
|
+
)
|
|
116
|
+
const dupeId = uuid()
|
|
117
|
+
duplicateMetadata.execute(dupeId)
|
|
118
|
+
await duplicateMetadataSuccess
|
|
119
|
+
|
|
120
|
+
// 3. Patch the duplicated metadata document to update the references
|
|
121
|
+
// TODO: use document store
|
|
122
|
+
// const {patch: patchMetadata} = await firstValueFrom(
|
|
123
|
+
// documentStore.pair
|
|
124
|
+
// .editOperations(dupeId, METADATA_SCHEMA_NAME)
|
|
125
|
+
// .pipe(filter((op) => op.patch.disabled !== 'NOT_READY'))
|
|
126
|
+
// )
|
|
127
|
+
|
|
128
|
+
// if (patchMetadata.disabled) {
|
|
129
|
+
// throw new Error('Cannot patch document')
|
|
130
|
+
// }
|
|
131
|
+
|
|
132
|
+
// await firstValueFrom(
|
|
133
|
+
// documentStore.pair
|
|
134
|
+
// .consistencyStatus(dupeId, METADATA_SCHEMA_NAME)
|
|
135
|
+
// .pipe(filter((isConsistant) => isConsistant))
|
|
136
|
+
// )
|
|
137
|
+
|
|
138
|
+
// const patchMetadataSuccess = firstValueFrom(
|
|
139
|
+
// documentStore.pair
|
|
140
|
+
// .operationEvents(dupeId, METADATA_SCHEMA_NAME)
|
|
141
|
+
// .pipe(filter((e) => e.op === 'patch' && e.type === 'success'))
|
|
142
|
+
// )
|
|
143
|
+
|
|
144
|
+
const patch: PatchOperations = {
|
|
145
|
+
set: Object.fromEntries(
|
|
146
|
+
Array.from(translations.entries()).map(([locale, documentId]) => [
|
|
147
|
+
`${TRANSLATIONS_ARRAY_NAME}[_key == "${locale}"].value._ref`,
|
|
148
|
+
documentId,
|
|
149
|
+
])
|
|
150
|
+
),
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// patchMetadata.execute([patch])
|
|
154
|
+
// await patchMetadataSuccess
|
|
155
|
+
await client.transaction().patch(dupeId, patch).commit()
|
|
156
|
+
|
|
157
|
+
// 4. Navigate to the duplicated document
|
|
158
|
+
navigateIntent('edit', {
|
|
159
|
+
id: Array.from(translations.values()).at(0),
|
|
160
|
+
type,
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
onComplete()
|
|
164
|
+
} catch (error) {
|
|
165
|
+
console.error(error)
|
|
166
|
+
toast.push({
|
|
167
|
+
status: 'error',
|
|
168
|
+
title: 'Error duplicating document',
|
|
169
|
+
description:
|
|
170
|
+
error instanceof Error
|
|
171
|
+
? error.message
|
|
172
|
+
: 'Failed to duplicate document',
|
|
173
|
+
})
|
|
174
|
+
} finally {
|
|
175
|
+
setDuplicating(false)
|
|
176
|
+
}
|
|
177
|
+
}, [
|
|
178
|
+
client,
|
|
179
|
+
documentStore.pair,
|
|
180
|
+
metadataDocument,
|
|
181
|
+
navigateIntent,
|
|
182
|
+
onComplete,
|
|
183
|
+
toast,
|
|
184
|
+
type,
|
|
185
|
+
])
|
|
186
|
+
|
|
187
|
+
return useMemo(() => {
|
|
188
|
+
if (!isPermissionsLoading && !permissions?.granted) {
|
|
189
|
+
return {
|
|
190
|
+
icon: CopyIcon,
|
|
191
|
+
disabled: true,
|
|
192
|
+
label: d('action.duplicate.label'),
|
|
193
|
+
title: (
|
|
194
|
+
<InsufficientPermissionsMessage
|
|
195
|
+
context="duplicate-document"
|
|
196
|
+
currentUser={currentUser}
|
|
197
|
+
/>
|
|
198
|
+
),
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (!isMetadataDocumentLoading && !metadataDocument) {
|
|
203
|
+
return {
|
|
204
|
+
icon: CopyIcon,
|
|
205
|
+
disabled: true,
|
|
206
|
+
label: d('action.duplicate.label'),
|
|
207
|
+
title: d(DISABLED_REASON_KEY.METADATA_NOT_FOUND),
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (!hasOneMetadataDocument) {
|
|
212
|
+
return {
|
|
213
|
+
icon: CopyIcon,
|
|
214
|
+
disabled: true,
|
|
215
|
+
label: d('action.duplicate.label'),
|
|
216
|
+
title: d(DISABLED_REASON_KEY.MULTIPLE_METADATA),
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return {
|
|
221
|
+
icon: CopyIcon,
|
|
222
|
+
disabled:
|
|
223
|
+
isDuplicating ||
|
|
224
|
+
Boolean(duplicate.disabled) ||
|
|
225
|
+
isPermissionsLoading ||
|
|
226
|
+
isMetadataDocumentLoading,
|
|
227
|
+
label: isDuplicating
|
|
228
|
+
? s('action.duplicate.running.label')
|
|
229
|
+
: d('action.duplicate.label'),
|
|
230
|
+
title: duplicate.disabled
|
|
231
|
+
? s(DISABLED_REASON_KEY[duplicate.disabled])
|
|
232
|
+
: '',
|
|
233
|
+
onHandle: handle,
|
|
234
|
+
}
|
|
235
|
+
}, [
|
|
236
|
+
currentUser,
|
|
237
|
+
duplicate.disabled,
|
|
238
|
+
handle,
|
|
239
|
+
hasOneMetadataDocument,
|
|
240
|
+
isDuplicating,
|
|
241
|
+
isMetadataDocumentLoading,
|
|
242
|
+
isPermissionsLoading,
|
|
243
|
+
metadataDocument,
|
|
244
|
+
permissions?.granted,
|
|
245
|
+
s,
|
|
246
|
+
d,
|
|
247
|
+
])
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
DuplicateWithTranslationsAction.action = 'duplicate'
|
|
251
|
+
// @ts-expect-error `displayName` is used by React DevTools
|
|
252
|
+
DuplicateWithTranslationsAction.displayName = 'DuplicateWithTranslationsAction'
|
|
@@ -95,7 +95,13 @@ export function DocumentInternationalizationMenu(
|
|
|
95
95
|
</Card>
|
|
96
96
|
) : (
|
|
97
97
|
<Stack space={1}>
|
|
98
|
-
<LanguageManage
|
|
98
|
+
<LanguageManage
|
|
99
|
+
id={metadata?._id}
|
|
100
|
+
documentId={documentId}
|
|
101
|
+
metadataId={metadataId}
|
|
102
|
+
schemaType={schemaType}
|
|
103
|
+
sourceLanguageId={sourceLanguageId}
|
|
104
|
+
/>
|
|
99
105
|
{supportedLanguages.length > 4 ? (
|
|
100
106
|
<TextInput
|
|
101
107
|
onChange={handleQuery}
|
|
@@ -1,40 +1,106 @@
|
|
|
1
1
|
import {CogIcon} from '@sanity/icons'
|
|
2
2
|
import {Box, Button, Stack, Text, Tooltip} from '@sanity/ui'
|
|
3
|
+
import {useCallback, useState} from 'react'
|
|
4
|
+
import {type ObjectSchemaType, useClient} from 'sanity'
|
|
3
5
|
|
|
4
6
|
import {METADATA_SCHEMA_NAME} from '../constants'
|
|
5
7
|
import {useOpenInNewPane} from '../hooks/useOpenInNewPane'
|
|
8
|
+
import {createReference} from '../utils/createReference'
|
|
9
|
+
import {useDocumentInternationalizationContext} from './DocumentInternationalizationContext'
|
|
6
10
|
|
|
7
11
|
type LanguageManageProps = {
|
|
8
12
|
id?: string
|
|
13
|
+
metadataId?: string | null
|
|
14
|
+
schemaType: ObjectSchemaType
|
|
15
|
+
documentId: string
|
|
16
|
+
sourceLanguageId?: string
|
|
9
17
|
}
|
|
10
18
|
|
|
11
19
|
export default function LanguageManage(props: LanguageManageProps) {
|
|
12
|
-
const {id} = props
|
|
20
|
+
const {id, metadataId, schemaType, documentId, sourceLanguageId} = props
|
|
13
21
|
const open = useOpenInNewPane(id, METADATA_SCHEMA_NAME)
|
|
22
|
+
const openCreated = useOpenInNewPane(metadataId, METADATA_SCHEMA_NAME)
|
|
23
|
+
const {allowCreateMetaDoc, apiVersion, weakReferences} =
|
|
24
|
+
useDocumentInternationalizationContext()
|
|
25
|
+
const client = useClient({apiVersion})
|
|
26
|
+
const [userHasClicked, setUserHasClicked] = useState(false)
|
|
27
|
+
|
|
28
|
+
const canCreate = !id && Boolean(metadataId) && allowCreateMetaDoc
|
|
29
|
+
|
|
30
|
+
const handleClick = useCallback(() => {
|
|
31
|
+
if (!id && metadataId && sourceLanguageId) {
|
|
32
|
+
/* Disable button while this request is pending */
|
|
33
|
+
setUserHasClicked(true)
|
|
34
|
+
|
|
35
|
+
// handle creation of meta document
|
|
36
|
+
const transaction = client.transaction()
|
|
37
|
+
|
|
38
|
+
const sourceReference = createReference(
|
|
39
|
+
sourceLanguageId,
|
|
40
|
+
documentId,
|
|
41
|
+
schemaType.name,
|
|
42
|
+
!weakReferences
|
|
43
|
+
)
|
|
44
|
+
const newMetadataDocument = {
|
|
45
|
+
_id: metadataId,
|
|
46
|
+
_type: METADATA_SCHEMA_NAME,
|
|
47
|
+
schemaTypes: [schemaType.name],
|
|
48
|
+
translations: [sourceReference],
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
transaction.createIfNotExists(newMetadataDocument)
|
|
52
|
+
|
|
53
|
+
transaction
|
|
54
|
+
.commit()
|
|
55
|
+
.then(() => {
|
|
56
|
+
setUserHasClicked(false)
|
|
57
|
+
openCreated()
|
|
58
|
+
})
|
|
59
|
+
.catch((err) => {
|
|
60
|
+
console.error(err)
|
|
61
|
+
setUserHasClicked(false)
|
|
62
|
+
})
|
|
63
|
+
} else {
|
|
64
|
+
open()
|
|
65
|
+
}
|
|
66
|
+
}, [
|
|
67
|
+
id,
|
|
68
|
+
metadataId,
|
|
69
|
+
sourceLanguageId,
|
|
70
|
+
client,
|
|
71
|
+
documentId,
|
|
72
|
+
schemaType.name,
|
|
73
|
+
weakReferences,
|
|
74
|
+
openCreated,
|
|
75
|
+
open,
|
|
76
|
+
])
|
|
77
|
+
|
|
78
|
+
const disabled =
|
|
79
|
+
(!id && !canCreate) || (canCreate && !sourceLanguageId) || userHasClicked
|
|
14
80
|
|
|
15
81
|
return (
|
|
16
82
|
<Tooltip
|
|
17
83
|
animate
|
|
18
84
|
content={
|
|
19
|
-
|
|
20
|
-
<
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
</Box>
|
|
25
|
-
)
|
|
85
|
+
<Box padding={2}>
|
|
86
|
+
<Text muted size={1}>
|
|
87
|
+
Document has no other translations
|
|
88
|
+
</Text>
|
|
89
|
+
</Box>
|
|
26
90
|
}
|
|
27
91
|
fallbackPlacements={['right', 'left']}
|
|
28
92
|
placement="top"
|
|
29
93
|
portal
|
|
94
|
+
disabled={Boolean(id) || canCreate}
|
|
30
95
|
>
|
|
31
96
|
<Stack>
|
|
32
97
|
<Button
|
|
33
|
-
disabled={
|
|
98
|
+
disabled={disabled}
|
|
34
99
|
mode="ghost"
|
|
35
100
|
text="Manage Translations"
|
|
36
101
|
icon={CogIcon}
|
|
37
|
-
|
|
102
|
+
loading={userHasClicked}
|
|
103
|
+
onClick={handleClick}
|
|
38
104
|
/>
|
|
39
105
|
</Stack>
|
|
40
106
|
</Tooltip>
|
package/src/constants.ts
CHANGED
|
@@ -2,7 +2,7 @@ import {useCallback, useContext} from 'react'
|
|
|
2
2
|
import {RouterContext} from 'sanity/router'
|
|
3
3
|
import {usePaneRouter} from 'sanity/structure'
|
|
4
4
|
|
|
5
|
-
export function useOpenInNewPane(id?: string, type?: string) {
|
|
5
|
+
export function useOpenInNewPane(id?: string | null, type?: string) {
|
|
6
6
|
const routerContext = useContext(RouterContext)
|
|
7
7
|
const {routerPanesState, groupIndex} = usePaneRouter()
|
|
8
8
|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {defineLocaleResourceBundle} from 'sanity'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The locale namespace for the document internationalization plugin.
|
|
5
|
+
*
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
export const documenti18nLocaleNamespace =
|
|
9
|
+
'document-internationalization' as const
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The default locale bundle for the document internationalization plugin, which is US English.
|
|
13
|
+
*
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
16
|
+
export const documentInternationalizationUsEnglishLocaleBundle =
|
|
17
|
+
defineLocaleResourceBundle({
|
|
18
|
+
locale: 'en-US',
|
|
19
|
+
namespace: documenti18nLocaleNamespace,
|
|
20
|
+
resources: () => import('./resources'),
|
|
21
|
+
})
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
'action.duplicate.label': 'Duplicate with translations',
|
|
3
|
+
'action.duplicate.disabled.missing-metadata':
|
|
4
|
+
'The document cannot be duplicated because the metadata document is missing',
|
|
5
|
+
'action.duplicate.disabled.multiple-metadata':
|
|
6
|
+
'The document cannot be duplicated because there are multiple metadata documents',
|
|
7
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export {DeleteTranslationAction} from './actions/DeleteTranslationAction'
|
|
2
|
+
export {DuplicateWithTranslationsAction} from './actions/DuplicateWithTranslationsAction'
|
|
2
3
|
export {useDocumentInternationalizationContext} from './components/DocumentInternationalizationContext'
|
|
3
4
|
export {DocumentInternationalizationMenu} from './components/DocumentInternationalizationMenu'
|
|
4
5
|
export {documentInternationalization} from './plugin'
|
package/src/plugin.tsx
CHANGED
|
@@ -9,6 +9,7 @@ import {DocumentInternationalizationProvider} from './components/DocumentInterna
|
|
|
9
9
|
import {DocumentInternationalizationMenu} from './components/DocumentInternationalizationMenu'
|
|
10
10
|
import OptimisticallyStrengthen from './components/OptimisticallyStrengthen'
|
|
11
11
|
import {API_VERSION, DEFAULT_CONFIG, METADATA_SCHEMA_NAME} from './constants'
|
|
12
|
+
import {documentInternationalizationUsEnglishLocaleBundle} from './i18n'
|
|
12
13
|
import metadata from './schema/translation/metadata'
|
|
13
14
|
import type {PluginConfig, TranslationReference} from './types'
|
|
14
15
|
|
|
@@ -39,6 +40,10 @@ export const documentInternationalization = definePlugin<PluginConfig>(
|
|
|
39
40
|
},
|
|
40
41
|
},
|
|
41
42
|
|
|
43
|
+
i18n: {
|
|
44
|
+
bundles: [documentInternationalizationUsEnglishLocaleBundle],
|
|
45
|
+
},
|
|
46
|
+
|
|
42
47
|
// Adds:
|
|
43
48
|
// - A bulk-publishing UI component to the form
|
|
44
49
|
// - Will only work for projects on a compatible plan
|