@sanity/document-internationalization 1.0.0 → 1.0.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/LICENSE +1 -1
- package/README.md +89 -47
- package/lib/index.esm.js +2 -0
- package/lib/index.esm.js.map +1 -0
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -0
- package/lib/src/index.d.ts +200 -0
- package/package.json +100 -43
- package/src/actions/DeleteWithi18nAction.tsx +118 -0
- package/src/actions/DuplicateWithi18nAction.tsx +77 -0
- package/src/actions/PublishWithi18nAction.ts +118 -0
- package/src/actions/index.ts +42 -0
- package/src/badges/LanguageBadge.tsx +22 -0
- package/src/constants/I18nDelimiter.ts +1 -0
- package/src/constants/I18nPrefix.ts +1 -0
- package/src/constants/IdStructure.ts +4 -0
- package/src/constants/LanguageCultures.ts +902 -0
- package/src/constants/ReferenceBehavior.ts +5 -0
- package/src/constants/SupportedEmojiFlagCodes.ts +251 -0
- package/src/constants/UiMessages.ts +56 -0
- package/src/constants/index.ts +7 -0
- package/src/documentI18n.tsx +33 -0
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useConfig.ts +22 -0
- package/src/hooks/useDelayedFlag.ts +31 -0
- package/src/index.ts +6 -1
- package/src/language-select/components/LanguageSelect/LanguageConfigContext.tsx +4 -0
- package/src/language-select/components/LanguageSelect/LanguageSelect.tsx +188 -0
- package/src/language-select/components/LanguageSelect/LanguageSelectContext.ts +16 -0
- package/src/language-select/components/LanguageSelect/LanguageSelectLabel.tsx +12 -0
- package/src/language-select/components/LanguageSelect/LanguageSelectList.tsx +84 -0
- package/src/language-select/components/LanguageSelect/LanguageSelectListItem.tsx +251 -0
- package/src/language-select/components/LanguageSelect/index.tsx +25 -0
- package/src/language-select/components/SingleFlag/SingleFlag.tsx +44 -0
- package/src/language-select/components/SingleFlag/allEmojiFlagCodes.ts +251 -0
- package/src/language-select/components/SingleFlag/index.ts +1 -0
- package/src/language-select/components/SplitPaneIcon/SplitPaneIcon.tsx +25 -0
- package/src/language-select/components/SplitPaneIcon/index.ts +1 -0
- package/src/language-select/components/index.ts +2 -0
- package/src/language-select/hooks/index.ts +1 -0
- package/src/language-select/hooks/useLanguages.ts +37 -0
- package/src/language-select/hooks/useListeningQuery.ts +66 -0
- package/src/structure/IDefaultDocumentNodeStructureProps.ts +4 -0
- package/src/structure/components/MaintenanceTab/MaintenanceTab.tsx +13 -0
- package/src/structure/components/MaintenanceTab/MaintenanceTabContent.tsx +259 -0
- package/src/structure/components/MaintenanceTab/index.ts +1 -0
- package/src/structure/components/MaintenanceTabResult/MaintenanceTabResult.tsx +44 -0
- package/src/structure/components/MaintenanceTabResult/index.ts +1 -0
- package/src/structure/components/MaintenanceTabTypeSelector/MaintenanceTabTypeSelector.tsx +56 -0
- package/src/structure/components/MaintenanceTabTypeSelector/index.ts +1 -0
- package/src/structure/hooks/index.ts +1 -0
- package/src/structure/hooks/useDocumentsInformation.ts +110 -0
- package/src/structure/index.tsx +120 -0
- package/src/structure/utils/fixBaseDocumentRefs.ts +30 -0
- package/src/structure/utils/fixBaseLanguageMismatch.ts +21 -0
- package/src/structure/utils/fixIdStructureMismatchDocuments.ts +72 -0
- package/src/structure/utils/fixLanguageFields.ts +32 -0
- package/src/structure/utils/fixOrphanedDocuments.ts +22 -0
- package/src/structure/utils/fixTranslationRefs.ts +50 -0
- package/src/structure/utils/index.ts +6 -0
- package/src/types/IEditState.ts +6 -0
- package/src/types/IExtendedLanguageObject.ts +6 -0
- package/src/types/ILanguageObject.ts +4 -0
- package/src/types/ILanguageQuery.ts +13 -0
- package/src/types/IResolverProps.ts +10 -0
- package/src/types/ITranslationRef.ts +6 -0
- package/src/types/IType.ts +40 -0
- package/src/types/IUseDocumentOperationResult.ts +11 -0
- package/src/types/TFieldNamesConfig.ts +5 -0
- package/src/types/TLanguage.ts +3 -0
- package/src/types/TLanguagesOption.ts +4 -0
- package/src/types/TSchema.ts +6 -0
- package/src/types/Ti18nConfig.ts +33 -0
- package/src/types/Ti18nDocument.ts +14 -0
- package/src/types/Ti18nSchema.ts +13 -0
- package/src/types/index.ts +15 -0
- package/src/utils/applyConfig.ts +43 -0
- package/src/utils/baseToTop.ts +5 -0
- package/src/utils/buildDocId.ts +8 -0
- package/src/utils/createSanityReference.ts +11 -0
- package/src/utils/getBaseIdFromId.ts +20 -0
- package/src/utils/getBaseLanguage.ts +6 -0
- package/src/utils/getFlag.ts +38 -0
- package/src/utils/getLanguageFromDocument.ts +9 -0
- package/src/utils/getLanguageFromId.ts +13 -0
- package/src/utils/getLanguagesFromOption.ts +40 -0
- package/src/utils/getTranslationsForId.ts +39 -0
- package/src/utils/index.ts +14 -0
- package/src/utils/makeObjectKey.ts +3 -0
- package/src/utils/normalizeLanguageList.ts +26 -0
- package/src/utils/serializePath.ts +11 -0
- package/src/utils/updateIntlFieldsForDocument.ts +79 -0
- package/src/utils/useSanityClient.ts +6 -0
- package/src/validators/index.ts +1 -0
- package/src/validators/isSlugUnique.ts +56 -0
- package/src/withDocumentI18nPlugin.ts +24 -0
- package/v2-incompatible.js +1 -1
- package/lib/cjs/index.js +0 -539
- package/lib/cjs/index.js.map +0 -1
- package/lib/esm/index.js +0 -532
- package/lib/esm/index.js.map +0 -1
- package/lib/types/index.d.ts +0 -12
- package/lib/types/index.d.ts.map +0 -1
- package/src/LanguageManage.tsx +0 -25
- package/src/LanguageOption.tsx +0 -158
- package/src/LanguagePatch.tsx +0 -61
- package/src/MenuButton.tsx +0 -101
- package/src/badges/index.tsx +0 -23
- package/src/constants.ts +0 -1
- package/src/hooks/useLanguageMetadata.tsx +0 -21
- package/src/hooks/useOpenInNewPane.tsx +0 -27
- package/src/plugin.tsx +0 -104
- package/src/schema/translation/metadata.ts +0 -42
- package/src/types.ts +0 -24
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import {getEmojiFlag} from '@cprecioso/country-flag-emoji'
|
|
2
|
+
import {SupportedEmojiFlagCodes} from '../constants'
|
|
3
|
+
|
|
4
|
+
// Get flag from a valid country code
|
|
5
|
+
export const getFlag = (code = ``): string => {
|
|
6
|
+
if (!code) {
|
|
7
|
+
return ``
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const flagCode = getFlagCode(code)
|
|
11
|
+
|
|
12
|
+
if (!SupportedEmojiFlagCodes.includes(flagCode.toUpperCase())) {
|
|
13
|
+
return ``
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const emoji = getEmojiFlag(flagCode)
|
|
17
|
+
|
|
18
|
+
return emoji
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Convert some language codes to country codes
|
|
22
|
+
export const getFlagCode = (code = ``): string => {
|
|
23
|
+
if (!code) {
|
|
24
|
+
return ``
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
switch (code.toLocaleLowerCase()) {
|
|
28
|
+
// Return :flag-gb: for English
|
|
29
|
+
case `en`:
|
|
30
|
+
return `gb`
|
|
31
|
+
// Return :flag-al: (Albania) for `sq` language code
|
|
32
|
+
case `sq`:
|
|
33
|
+
return `al`
|
|
34
|
+
|
|
35
|
+
default:
|
|
36
|
+
return code
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type {SanityDocument} from '@sanity/client'
|
|
2
|
+
import type {ApplyConfigResult} from './applyConfig'
|
|
3
|
+
|
|
4
|
+
export function getLanguageFromDocument(
|
|
5
|
+
doc: SanityDocument,
|
|
6
|
+
config: ApplyConfigResult
|
|
7
|
+
): string | null {
|
|
8
|
+
return doc?.[config.fieldNames.lang] || config.base || null
|
|
9
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import {I18nPrefix, I18nDelimiter} from '../constants'
|
|
2
|
+
|
|
3
|
+
export const getLanguageFromId = (id: string): string | undefined => {
|
|
4
|
+
// subpath
|
|
5
|
+
const rx = new RegExp(`${I18nPrefix}\\.[^.]+\\.([^.]+)`)
|
|
6
|
+
const match = id.match(rx)
|
|
7
|
+
if (match && match.length === 2) return match[1]
|
|
8
|
+
|
|
9
|
+
// delimiter
|
|
10
|
+
const split = id.split(I18nDelimiter)
|
|
11
|
+
if (split.length > 1) return split[1]
|
|
12
|
+
return undefined
|
|
13
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import get from 'just-safe-get'
|
|
2
|
+
import type {SanityClient, SanityDocument} from '@sanity/client'
|
|
3
|
+
import {ILanguageObject, ILanguageQuery, TLanguagesOption} from '../types'
|
|
4
|
+
import type {ApplyConfigResult} from '../utils'
|
|
5
|
+
import {normalizeLanguageList} from './normalizeLanguageList'
|
|
6
|
+
|
|
7
|
+
export const getLanguagesFromOption = async <D extends SanityDocument>(
|
|
8
|
+
client: SanityClient,
|
|
9
|
+
config: ApplyConfigResult,
|
|
10
|
+
langs: TLanguagesOption,
|
|
11
|
+
document?: D | null
|
|
12
|
+
): Promise<ILanguageObject[]> => {
|
|
13
|
+
const languages = normalizeLanguageList(
|
|
14
|
+
await (async () => {
|
|
15
|
+
if (Array.isArray(langs)) return langs
|
|
16
|
+
const r = await client.fetch<ILanguageQuery['value'][]>(langs.query)
|
|
17
|
+
const value = langs.value
|
|
18
|
+
|
|
19
|
+
if (typeof value === 'string') return r.map((l) => get(l, value))
|
|
20
|
+
return r.map((l) => {
|
|
21
|
+
// @deprecated
|
|
22
|
+
if ('name' in value) {
|
|
23
|
+
return {
|
|
24
|
+
name: get(l, value.name),
|
|
25
|
+
title: get(l, value.title),
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
id: get(l, value.id),
|
|
31
|
+
title: get(l, value.title),
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
})()
|
|
35
|
+
)
|
|
36
|
+
if (config.languagesLoader) {
|
|
37
|
+
return config.languagesLoader(languages, document ?? undefined)
|
|
38
|
+
}
|
|
39
|
+
return languages
|
|
40
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {SanityClient} from '@sanity/client'
|
|
2
|
+
import type {ApplyConfigResult} from '../utils'
|
|
3
|
+
import {I18nDelimiter, IdStructure} from '../constants'
|
|
4
|
+
import {Ti18nDocument} from '../types'
|
|
5
|
+
import {buildDocId} from './buildDocId'
|
|
6
|
+
|
|
7
|
+
export const getTranslationsFor = async (
|
|
8
|
+
client: SanityClient,
|
|
9
|
+
config: ApplyConfigResult,
|
|
10
|
+
baseDocumentId: string,
|
|
11
|
+
includeDrafts = false
|
|
12
|
+
): Promise<Ti18nDocument[]> => {
|
|
13
|
+
if (config.idStructure === IdStructure.DELIMITER) {
|
|
14
|
+
const segments = baseDocumentId.split('-')
|
|
15
|
+
segments[segments.length - 1] = `${segments[segments.length - 1]}${I18nDelimiter}*`
|
|
16
|
+
const documents = await client.fetch<Ti18nDocument[]>(
|
|
17
|
+
includeDrafts
|
|
18
|
+
? '*[_id match $segments]'
|
|
19
|
+
: `*[_id match $segments && !(_id in path('drafts.**'))]`,
|
|
20
|
+
{segments}
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
return documents
|
|
24
|
+
? documents.filter(
|
|
25
|
+
(d) =>
|
|
26
|
+
d._id.startsWith(baseDocumentId) ||
|
|
27
|
+
(includeDrafts && d._id.startsWith(`drafts.${baseDocumentId}`))
|
|
28
|
+
)
|
|
29
|
+
: []
|
|
30
|
+
}
|
|
31
|
+
const documents = await client.fetch<Ti18nDocument[]>(
|
|
32
|
+
includeDrafts ? '*[_id in path($path) || _id in path($draftPath)]' : '*[_id in path($path)]',
|
|
33
|
+
{
|
|
34
|
+
path: buildDocId(config, baseDocumentId, '*'),
|
|
35
|
+
draftPath: `drafts.${buildDocId(config, baseDocumentId, '*')}`,
|
|
36
|
+
}
|
|
37
|
+
)
|
|
38
|
+
return documents ?? []
|
|
39
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * from './buildDocId'
|
|
2
|
+
export * from './normalizeLanguageList'
|
|
3
|
+
export * from './getBaseLanguage'
|
|
4
|
+
export * from './useSanityClient'
|
|
5
|
+
export * from './getLanguagesFromOption'
|
|
6
|
+
export * from './getLanguageFromId'
|
|
7
|
+
export * from './getBaseIdFromId'
|
|
8
|
+
export * from './getTranslationsForId'
|
|
9
|
+
export * from './makeObjectKey'
|
|
10
|
+
export * from './createSanityReference'
|
|
11
|
+
export * from './updateIntlFieldsForDocument'
|
|
12
|
+
export * from './serializePath'
|
|
13
|
+
export * from './applyConfig'
|
|
14
|
+
export * from './getLanguageFromDocument'
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import {ILanguageObject} from '../types'
|
|
2
|
+
import {LanguageCultures} from '../constants'
|
|
3
|
+
|
|
4
|
+
type LanguageConfigObject =
|
|
5
|
+
| ILanguageObject
|
|
6
|
+
| (Omit<ILanguageObject, 'id'> & {
|
|
7
|
+
name: string
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
export const normalizeLanguageList = (languages: (string | LanguageConfigObject)[]) =>
|
|
11
|
+
languages.map<ILanguageObject>((l) => {
|
|
12
|
+
if (typeof l === 'string') {
|
|
13
|
+
const langCult = LanguageCultures.find((x) => x.value === l)
|
|
14
|
+
if (langCult) return {title: langCult.title, id: l}
|
|
15
|
+
return {title: l, id: l}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if ('name' in l) {
|
|
19
|
+
console.warn(
|
|
20
|
+
`The "name" field in your language configuration is deprecated, please replace it with "id".`
|
|
21
|
+
)
|
|
22
|
+
return {title: l.title, id: l.name}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return {title: l.title, id: l.id}
|
|
26
|
+
})
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import {Path, isKeyedObject} from 'sanity'
|
|
2
|
+
|
|
3
|
+
export function serializePath(path: Path): string {
|
|
4
|
+
return path.reduce<string>((target, part, i) => {
|
|
5
|
+
const isIndex = typeof part === 'number'
|
|
6
|
+
const isKey = isKeyedObject(part)
|
|
7
|
+
const separator = i === 0 ? '' : '.'
|
|
8
|
+
const add = isIndex || isKey ? '[]' : `${separator}${part}`
|
|
9
|
+
return `${target}${add}`
|
|
10
|
+
}, '')
|
|
11
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import compact from 'lodash/compact'
|
|
2
|
+
import {SanityClient, SanityDocument} from '@sanity/client'
|
|
3
|
+
import {ITranslationRef} from '../types'
|
|
4
|
+
import {ReferenceBehavior} from '../constants'
|
|
5
|
+
import {ApplyConfigResult} from '../utils'
|
|
6
|
+
import {getLanguagesFromOption} from './getLanguagesFromOption'
|
|
7
|
+
import {getBaseLanguage} from './getBaseLanguage'
|
|
8
|
+
import {getTranslationsFor} from './getTranslationsForId'
|
|
9
|
+
import {getBaseIdFromId} from './getBaseIdFromId'
|
|
10
|
+
import {createSanityReference} from './createSanityReference'
|
|
11
|
+
import {getLanguageFromDocument} from './getLanguageFromDocument'
|
|
12
|
+
|
|
13
|
+
// @TODO make this into a hook so the hook
|
|
14
|
+
// can look up the existance of a base document on its own
|
|
15
|
+
export async function updateIntlFieldsForDocument(
|
|
16
|
+
client: SanityClient,
|
|
17
|
+
config: ApplyConfigResult,
|
|
18
|
+
document: SanityDocument,
|
|
19
|
+
baseDocument?: SanityDocument
|
|
20
|
+
): Promise<void> {
|
|
21
|
+
const {_type: type, _id: id} = document
|
|
22
|
+
const baseDocumentId = getBaseIdFromId(id)
|
|
23
|
+
const isTranslation = id !== baseDocumentId
|
|
24
|
+
const fieldName = config.fieldNames.lang
|
|
25
|
+
const refsFieldName = config.fieldNames.references
|
|
26
|
+
const baseRefFieldName = config.fieldNames.baseReference
|
|
27
|
+
const langs = await getLanguagesFromOption(client, config, config.languages, document)
|
|
28
|
+
const languageId =
|
|
29
|
+
getLanguageFromDocument(document, config) || getBaseLanguage(langs, config.base)?.id
|
|
30
|
+
|
|
31
|
+
// Update I18n field for current document
|
|
32
|
+
const currentDocumentTransaction = client.transaction()
|
|
33
|
+
currentDocumentTransaction.createIfNotExists({_id: id, _type: type})
|
|
34
|
+
currentDocumentTransaction.patch(id, {
|
|
35
|
+
set: {
|
|
36
|
+
[fieldName]: languageId,
|
|
37
|
+
...(isTranslation && config.referenceBehavior !== ReferenceBehavior.DISABLED
|
|
38
|
+
? {
|
|
39
|
+
[baseRefFieldName]: createSanityReference(
|
|
40
|
+
baseDocumentId,
|
|
41
|
+
config.referenceBehavior === ReferenceBehavior.WEAK
|
|
42
|
+
),
|
|
43
|
+
}
|
|
44
|
+
: {}),
|
|
45
|
+
},
|
|
46
|
+
})
|
|
47
|
+
await currentDocumentTransaction.commit()
|
|
48
|
+
|
|
49
|
+
// update base document reference if required
|
|
50
|
+
if (baseDocument) {
|
|
51
|
+
const translatedDocuments = await getTranslationsFor(client, config, baseDocumentId)
|
|
52
|
+
if (translatedDocuments.length > 0) {
|
|
53
|
+
const baseDocumentTransaction = client.transaction()
|
|
54
|
+
let translatedRefs: ITranslationRef[] = []
|
|
55
|
+
if (config.referenceBehavior !== ReferenceBehavior.DISABLED) {
|
|
56
|
+
translatedRefs = compact(
|
|
57
|
+
translatedDocuments.map((doc) => {
|
|
58
|
+
const lang = getLanguageFromDocument(doc, config)
|
|
59
|
+
if (!lang) return null
|
|
60
|
+
return {
|
|
61
|
+
_key: lang,
|
|
62
|
+
...createSanityReference(
|
|
63
|
+
doc._id,
|
|
64
|
+
config.referenceBehavior === ReferenceBehavior.WEAK
|
|
65
|
+
),
|
|
66
|
+
}
|
|
67
|
+
}, {})
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
// baseDocumentTransaction.createIfNotExists({_id: baseDocumentId, _type: type})
|
|
71
|
+
baseDocumentTransaction.patch(baseDocumentId, {
|
|
72
|
+
set: {
|
|
73
|
+
[refsFieldName]: translatedRefs,
|
|
74
|
+
},
|
|
75
|
+
})
|
|
76
|
+
await baseDocumentTransaction.commit()
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './isSlugUnique'
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type {SlugIsUniqueValidator} from 'sanity'
|
|
2
|
+
import type {SanityClient} from '@sanity/client'
|
|
3
|
+
import {I18nDelimiter} from '../constants'
|
|
4
|
+
import {getBaseIdFromId, serializePath} from '../utils'
|
|
5
|
+
|
|
6
|
+
/*
|
|
7
|
+
* most of this is taken from the deafultUnique function in @sanity/validation
|
|
8
|
+
*/
|
|
9
|
+
export function createIsSlugUnique(client: SanityClient): SlugIsUniqueValidator {
|
|
10
|
+
return (slug, context) => {
|
|
11
|
+
const {document, path, type} = context
|
|
12
|
+
const schemaOptions = type?.options as {disableArrayWarning?: boolean} | undefined
|
|
13
|
+
|
|
14
|
+
if (!document) {
|
|
15
|
+
throw new Error(`\`document\` was not provided in validation context.`)
|
|
16
|
+
}
|
|
17
|
+
if (!path) {
|
|
18
|
+
throw new Error(`\`path\` was not provided in validation context.`)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const disableArrayWarning = schemaOptions?.disableArrayWarning || false
|
|
22
|
+
const baseId = getBaseIdFromId(document._id)
|
|
23
|
+
const docType = document._type
|
|
24
|
+
const atPath = serializePath(path.concat('current'))
|
|
25
|
+
|
|
26
|
+
if (!disableArrayWarning && atPath.includes('[]')) {
|
|
27
|
+
const serializedPath = serializePath(path)
|
|
28
|
+
console.warn(
|
|
29
|
+
[
|
|
30
|
+
`Slug field at path ${serializedPath} is within an array and cannot be automatically checked for uniqueness`,
|
|
31
|
+
`If you need to check for uniqueness, provide your own "isUnique" method`,
|
|
32
|
+
`To disable this message, set \`disableArrayWarning: true\` on the slug \`options\` field`,
|
|
33
|
+
].join('\n')
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const constraints = [
|
|
38
|
+
'_type == $docType',
|
|
39
|
+
'!(_id in path("drafts.**"))', // exclude drafts
|
|
40
|
+
'_id != $baseId', // exclude own base document
|
|
41
|
+
'!(_id in path("i18n." + $baseId + ".*"))', // exclude any subpath translations
|
|
42
|
+
`!(_id match $baseId + "${I18nDelimiter}*")`, // exclude any delimiter based translations
|
|
43
|
+
`${atPath} == $slug`,
|
|
44
|
+
].join(' && ')
|
|
45
|
+
|
|
46
|
+
return client.fetch<boolean>(
|
|
47
|
+
`!defined(*[${constraints}][0]._id)`,
|
|
48
|
+
{
|
|
49
|
+
docType,
|
|
50
|
+
baseId,
|
|
51
|
+
slug,
|
|
52
|
+
},
|
|
53
|
+
{tag: 'validation.slug-is-unique'}
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import compact from 'lodash/compact'
|
|
2
|
+
import type {PluginOptions} from 'sanity'
|
|
3
|
+
import {deskTool} from 'sanity/desk'
|
|
4
|
+
import type {Ti18nConfig} from './types'
|
|
5
|
+
import {documentI18n} from './documentI18n'
|
|
6
|
+
import {getDocumentList} from './structure'
|
|
7
|
+
|
|
8
|
+
export function withDocumentI18nPlugin(
|
|
9
|
+
plugins: PluginOptions[] | ((config: Ti18nConfig) => PluginOptions[]),
|
|
10
|
+
config: Ti18nConfig & {
|
|
11
|
+
includeDeskTool?: boolean
|
|
12
|
+
}
|
|
13
|
+
): PluginOptions[] {
|
|
14
|
+
const i18nplugin = documentI18n(config)
|
|
15
|
+
return compact([
|
|
16
|
+
...(Array.isArray(plugins) ? plugins : plugins(config)),
|
|
17
|
+
config.includeDeskTool ?? true
|
|
18
|
+
? deskTool({
|
|
19
|
+
structure: (S, {schema}) => getDocumentList({S, schema, config}),
|
|
20
|
+
})
|
|
21
|
+
: null,
|
|
22
|
+
i18nplugin,
|
|
23
|
+
])
|
|
24
|
+
}
|