sanity-plugin-internationalized-array 3.2.2 → 4.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 +3 -34
- package/{lib → dist}/index.d.ts +41 -61
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +896 -0
- package/dist/index.js.map +1 -0
- package/package.json +36 -74
- package/lib/index.d.mts +0 -149
- package/lib/index.esm.js +0 -854
- package/lib/index.esm.js.map +0 -1
- package/lib/index.js +0 -863
- package/lib/index.js.map +0 -1
- package/lib/index.mjs +0 -854
- package/lib/index.mjs.map +0 -1
- package/sanity.json +0 -8
- package/src/cache.ts +0 -148
- package/src/components/AddButtons.tsx +0 -60
- package/src/components/DocumentAddButtons.tsx +0 -183
- package/src/components/Feedback.tsx +0 -28
- package/src/components/InternationalizedArray.tsx +0 -286
- package/src/components/InternationalizedArrayContext.tsx +0 -136
- package/src/components/InternationalizedField.tsx +0 -57
- package/src/components/InternationalizedInput.tsx +0 -257
- package/src/components/Preload.tsx +0 -31
- package/src/components/createFieldName.ts +0 -20
- package/src/components/getSelectedValue.ts +0 -31
- package/src/components/getToneFromValidation.ts +0 -20
- package/src/constants.ts +0 -18
- package/src/fieldActions/index.ts +0 -138
- package/src/index.ts +0 -3
- package/src/plugin.tsx +0 -87
- package/src/schema/array.ts +0 -148
- package/src/schema/object.ts +0 -36
- package/src/types.ts +0 -135
- package/src/utils/checkAllLanguagesArePresent.ts +0 -14
- package/src/utils/createAddAllTitle.ts +0 -16
- package/src/utils/createAddLanguagePatches.ts +0 -84
- package/src/utils/createValueSchemaTypeName.ts +0 -5
- package/src/utils/flattenSchemaType.ts +0 -63
- package/src/utils/getDocumentsToTranslate.ts +0 -66
- package/src/utils/getLanguageDisplay.ts +0 -13
- package/src/utils/getLanguagesFieldOption.ts +0 -16
- package/v2-incompatible.js +0 -11
package/src/schema/array.ts
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-nested-ternary */
|
|
2
|
-
import {defineField, type FieldDefinition, type Rule} from 'sanity'
|
|
3
|
-
|
|
4
|
-
import {getFunctionCache, peek, setFunctionCache} from '../cache'
|
|
5
|
-
import {createFieldName} from '../components/createFieldName'
|
|
6
|
-
import {getSelectedValue} from '../components/getSelectedValue'
|
|
7
|
-
import InternationalizedArray from '../components/InternationalizedArray'
|
|
8
|
-
import type {Language, LanguageCallback, Value} from '../types'
|
|
9
|
-
import {getLanguagesFieldOption} from '../utils/getLanguagesFieldOption'
|
|
10
|
-
|
|
11
|
-
type ArrayFactoryConfig = {
|
|
12
|
-
apiVersion: string
|
|
13
|
-
select?: Record<string, string>
|
|
14
|
-
languages: Language[] | LanguageCallback
|
|
15
|
-
defaultLanguages?: string[]
|
|
16
|
-
type: string | FieldDefinition
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export type ArrayFieldOptions = Pick<
|
|
20
|
-
ArrayFactoryConfig,
|
|
21
|
-
'apiVersion' | 'select' | 'languages'
|
|
22
|
-
>
|
|
23
|
-
|
|
24
|
-
export default (config: ArrayFactoryConfig): FieldDefinition<'array'> => {
|
|
25
|
-
const {apiVersion, select, languages, type} = config
|
|
26
|
-
const typeName = typeof type === `string` ? type : type.name
|
|
27
|
-
const arrayName = createFieldName(typeName)
|
|
28
|
-
const objectName = createFieldName(typeName, true)
|
|
29
|
-
|
|
30
|
-
return defineField({
|
|
31
|
-
name: arrayName,
|
|
32
|
-
title: 'Internationalized array',
|
|
33
|
-
type: 'array',
|
|
34
|
-
components: {
|
|
35
|
-
input: InternationalizedArray,
|
|
36
|
-
},
|
|
37
|
-
options: {
|
|
38
|
-
// @ts-expect-error - these options are required for validation rules – not the custom input component
|
|
39
|
-
apiVersion,
|
|
40
|
-
select,
|
|
41
|
-
languages,
|
|
42
|
-
},
|
|
43
|
-
of: [
|
|
44
|
-
defineField({
|
|
45
|
-
...(typeof type === 'string' ? {} : type),
|
|
46
|
-
name: objectName,
|
|
47
|
-
type: objectName,
|
|
48
|
-
}),
|
|
49
|
-
],
|
|
50
|
-
// @ts-expect-error - fix typings
|
|
51
|
-
validation: (rule: Rule) =>
|
|
52
|
-
rule.custom<Value[]>(async (value, context) => {
|
|
53
|
-
if (!value || value.length === 0) {
|
|
54
|
-
return true
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Early return for simple cases to avoid expensive operations
|
|
58
|
-
if (value.length === 1 && !value[0]?._key) {
|
|
59
|
-
return true
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const selectedValue = getSelectedValue(select, context.document)
|
|
63
|
-
const client = context.getClient({apiVersion})
|
|
64
|
-
|
|
65
|
-
let contextLanguages: Language[] = []
|
|
66
|
-
const languagesFieldOption = getLanguagesFieldOption(context?.type)
|
|
67
|
-
|
|
68
|
-
if (Array.isArray(languagesFieldOption)) {
|
|
69
|
-
contextLanguages = languagesFieldOption
|
|
70
|
-
} else if (Array.isArray(peek(selectedValue))) {
|
|
71
|
-
contextLanguages = peek(selectedValue) || []
|
|
72
|
-
} else if (typeof languagesFieldOption === 'function') {
|
|
73
|
-
// Try to get from function cache first (if it's the same function as the component)
|
|
74
|
-
const cachedLanguages = getFunctionCache(
|
|
75
|
-
languagesFieldOption,
|
|
76
|
-
selectedValue
|
|
77
|
-
)
|
|
78
|
-
|
|
79
|
-
if (Array.isArray(cachedLanguages)) {
|
|
80
|
-
contextLanguages = cachedLanguages
|
|
81
|
-
} else {
|
|
82
|
-
// Try suspend cache as fallback
|
|
83
|
-
const suspendCachedLanguages = peek(selectedValue)
|
|
84
|
-
if (Array.isArray(suspendCachedLanguages)) {
|
|
85
|
-
contextLanguages = suspendCachedLanguages
|
|
86
|
-
} else {
|
|
87
|
-
// Only make the async call if we don't have cached data
|
|
88
|
-
contextLanguages = await languagesFieldOption(
|
|
89
|
-
client,
|
|
90
|
-
selectedValue
|
|
91
|
-
)
|
|
92
|
-
// Cache the result for future validation calls
|
|
93
|
-
setFunctionCache(
|
|
94
|
-
languagesFieldOption,
|
|
95
|
-
selectedValue,
|
|
96
|
-
contextLanguages
|
|
97
|
-
)
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (value && value.length > contextLanguages.length) {
|
|
103
|
-
return `Cannot be more than ${
|
|
104
|
-
contextLanguages.length === 1
|
|
105
|
-
? `1 item`
|
|
106
|
-
: `${contextLanguages.length} items`
|
|
107
|
-
}`
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// Create a Set for faster language ID lookups
|
|
111
|
-
const languageIds = new Set(contextLanguages.map((lang) => lang.id))
|
|
112
|
-
|
|
113
|
-
// Check for invalid language keys
|
|
114
|
-
const nonLanguageKeys = value.filter(
|
|
115
|
-
(item) => item?._key && !languageIds.has(item._key)
|
|
116
|
-
)
|
|
117
|
-
if (nonLanguageKeys.length) {
|
|
118
|
-
return {
|
|
119
|
-
message: `Array item keys must be valid languages registered to the field type`,
|
|
120
|
-
paths: nonLanguageKeys.map((item) => [{_key: item._key}]),
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// Check for duplicate language keys (more efficient)
|
|
125
|
-
const seenKeys = new Set<string>()
|
|
126
|
-
const duplicateValues: Value[] = []
|
|
127
|
-
|
|
128
|
-
for (const item of value) {
|
|
129
|
-
if (item?._key) {
|
|
130
|
-
if (seenKeys.has(item._key)) {
|
|
131
|
-
duplicateValues.push(item)
|
|
132
|
-
} else {
|
|
133
|
-
seenKeys.add(item._key)
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
if (duplicateValues.length) {
|
|
139
|
-
return {
|
|
140
|
-
message: 'There can only be one field per language',
|
|
141
|
-
paths: duplicateValues.map((item) => [{_key: item._key}]),
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return true
|
|
146
|
-
}),
|
|
147
|
-
})
|
|
148
|
-
}
|
package/src/schema/object.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import {defineField, FieldDefinition} from 'sanity'
|
|
2
|
-
|
|
3
|
-
import {createFieldName} from '../components/createFieldName'
|
|
4
|
-
import InternationalizedInput from '../components/InternationalizedInput'
|
|
5
|
-
|
|
6
|
-
type ObjectFactoryConfig = {
|
|
7
|
-
type: string | FieldDefinition
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export default (config: ObjectFactoryConfig): FieldDefinition<'object'> => {
|
|
11
|
-
const {type} = config
|
|
12
|
-
const typeName = typeof type === `string` ? type : type.name
|
|
13
|
-
const objectName = createFieldName(typeName, true)
|
|
14
|
-
|
|
15
|
-
return defineField({
|
|
16
|
-
name: objectName,
|
|
17
|
-
title: `Internationalized array ${type}`,
|
|
18
|
-
type: 'object',
|
|
19
|
-
components: {
|
|
20
|
-
// @ts-expect-error - fix typings
|
|
21
|
-
item: InternationalizedInput,
|
|
22
|
-
},
|
|
23
|
-
fields: [
|
|
24
|
-
defineField({
|
|
25
|
-
...(typeof type === 'string' ? {type} : type),
|
|
26
|
-
name: 'value',
|
|
27
|
-
}),
|
|
28
|
-
],
|
|
29
|
-
preview: {
|
|
30
|
-
select: {
|
|
31
|
-
title: 'value',
|
|
32
|
-
subtitle: '_key',
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
})
|
|
36
|
-
}
|
package/src/types.ts
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
FieldDefinition,
|
|
3
|
-
Rule,
|
|
4
|
-
RuleTypeConstraint,
|
|
5
|
-
SanityClient,
|
|
6
|
-
} from 'sanity'
|
|
7
|
-
|
|
8
|
-
export type Language = {
|
|
9
|
-
id: Intl.UnicodeBCP47LocaleIdentifier
|
|
10
|
-
title: string
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export type AllowedType = 'string' | 'number' | 'boolean' | 'text' | 'reference'
|
|
14
|
-
|
|
15
|
-
export type ArrayConfig = {
|
|
16
|
-
name: string
|
|
17
|
-
type: AllowedType
|
|
18
|
-
languages: Language[]
|
|
19
|
-
title?: string
|
|
20
|
-
group?: string
|
|
21
|
-
hidden?: boolean | (() => boolean)
|
|
22
|
-
readOnly?: boolean | (() => boolean)
|
|
23
|
-
validation?: Rule | Rule[]
|
|
24
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
25
|
-
field?: {[key: string]: any; options: {[key: string]: any}}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export type Value = {
|
|
29
|
-
_key: string
|
|
30
|
-
value?: unknown
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export type LanguageCallback = (
|
|
34
|
-
client: SanityClient,
|
|
35
|
-
selectedValue: Record<string, unknown>
|
|
36
|
-
) => Promise<Language[]>
|
|
37
|
-
|
|
38
|
-
export type LanguageDisplay = 'titleOnly' | 'codeOnly' | 'titleAndCode'
|
|
39
|
-
|
|
40
|
-
export type PluginConfig = {
|
|
41
|
-
/**
|
|
42
|
-
* https://www.sanity.io/docs/api-versioning
|
|
43
|
-
* @defaultValue '2025-10-15'
|
|
44
|
-
*/
|
|
45
|
-
apiVersion?: string
|
|
46
|
-
/**
|
|
47
|
-
* Specify fields that should be available in the language callback:
|
|
48
|
-
* ```tsx
|
|
49
|
-
* {
|
|
50
|
-
* select: {
|
|
51
|
-
* markets: 'markets'
|
|
52
|
-
* },
|
|
53
|
-
* languages: (client, {markets}) =>
|
|
54
|
-
* query.fetch(groq`*[_type == "language" && market in $markets]{id,title}`, {markets})
|
|
55
|
-
* }
|
|
56
|
-
* ```
|
|
57
|
-
*/
|
|
58
|
-
select?: Record<string, string>
|
|
59
|
-
/**
|
|
60
|
-
* You can give it an array of language definitions:
|
|
61
|
-
* ```tsx
|
|
62
|
-
* {
|
|
63
|
-
* languages: [
|
|
64
|
-
* {id: 'en', title: 'English'},
|
|
65
|
-
* {id: 'fr', title: 'French'}
|
|
66
|
-
* ]
|
|
67
|
-
* }
|
|
68
|
-
* ```
|
|
69
|
-
* You can load them async by passing a function that returns a promise:
|
|
70
|
-
* ```tsx
|
|
71
|
-
* {
|
|
72
|
-
* languages: async () => {
|
|
73
|
-
* const response = await fetch('https://example.com/languages')
|
|
74
|
-
* return response.json()
|
|
75
|
-
* }
|
|
76
|
-
* }
|
|
77
|
-
* ```
|
|
78
|
-
* You can query your dataset for languages::
|
|
79
|
-
* ```tsx
|
|
80
|
-
* {
|
|
81
|
-
* languages: (client) =>
|
|
82
|
-
* query.fetch(groq`*[_type == "language"]{id,title}`)
|
|
83
|
-
* }
|
|
84
|
-
* ```
|
|
85
|
-
*/
|
|
86
|
-
languages: Language[] | LanguageCallback
|
|
87
|
-
/**
|
|
88
|
-
* You can specify a list of language IDs that should be pre-filled when creating a new document
|
|
89
|
-
* ```tsx
|
|
90
|
-
* {
|
|
91
|
-
* defaultLanguages: ['en']
|
|
92
|
-
* }
|
|
93
|
-
* ```
|
|
94
|
-
*/
|
|
95
|
-
defaultLanguages?: string[]
|
|
96
|
-
/**
|
|
97
|
-
* Can be a string matching core field types, as well as custom ones:
|
|
98
|
-
* ```tsx
|
|
99
|
-
* {
|
|
100
|
-
* fieldTypes: [
|
|
101
|
-
* "date", "datetime", "file", "image", "number", "string", "text", "url"
|
|
102
|
-
* ]
|
|
103
|
-
* }
|
|
104
|
-
* ```
|
|
105
|
-
* You can also define a type directly:
|
|
106
|
-
* ```tsx
|
|
107
|
-
* {
|
|
108
|
-
* fieldTypes: [
|
|
109
|
-
* defineField({
|
|
110
|
-
* name: 'featuredProduct',
|
|
111
|
-
* type: 'reference',
|
|
112
|
-
* to: [{type: 'product'}]
|
|
113
|
-
* hidden: (({document}) => !document?.title)
|
|
114
|
-
* })
|
|
115
|
-
* ]
|
|
116
|
-
* }
|
|
117
|
-
* ```
|
|
118
|
-
*/
|
|
119
|
-
fieldTypes: (string | RuleTypeConstraint | FieldDefinition)[]
|
|
120
|
-
/**
|
|
121
|
-
* Locations where the "+ EN" add language buttons are visible
|
|
122
|
-
* @defaultValue ['field']
|
|
123
|
-
* */
|
|
124
|
-
buttonLocations?: ('field' | 'unstable__fieldAction' | 'document')[]
|
|
125
|
-
/**
|
|
126
|
-
* Show or hide the "Add missing languages" button
|
|
127
|
-
* @defaultValue true
|
|
128
|
-
* */
|
|
129
|
-
buttonAddAll?: boolean
|
|
130
|
-
/**
|
|
131
|
-
* How to display the languages on buttons and fields
|
|
132
|
-
* @defaultValue 'code'
|
|
133
|
-
* */
|
|
134
|
-
languageDisplay?: LanguageDisplay
|
|
135
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import {Language, Value} from '../types'
|
|
2
|
-
|
|
3
|
-
export function checkAllLanguagesArePresent(
|
|
4
|
-
languages: Language[],
|
|
5
|
-
value: Value[] | undefined
|
|
6
|
-
): boolean {
|
|
7
|
-
const filteredLanguageIds = languages.map((l) => l.id)
|
|
8
|
-
const languagesInUseIds = value ? value.map((v) => v._key) : []
|
|
9
|
-
|
|
10
|
-
return (
|
|
11
|
-
languagesInUseIds.length === filteredLanguageIds.length &&
|
|
12
|
-
languagesInUseIds.every((l) => filteredLanguageIds.includes(l))
|
|
13
|
-
)
|
|
14
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import {Language, Value} from '../types'
|
|
2
|
-
|
|
3
|
-
export function createAddAllTitle(
|
|
4
|
-
value: Value[] | undefined,
|
|
5
|
-
languages: Language[]
|
|
6
|
-
): string {
|
|
7
|
-
if (value?.length) {
|
|
8
|
-
return `Add missing ${
|
|
9
|
-
languages.length - value.length === 1 ? `language` : `languages`
|
|
10
|
-
}`
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
return languages.length === 1
|
|
14
|
-
? `Add ${languages[0].title} Field`
|
|
15
|
-
: `Add all languages`
|
|
16
|
-
}
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import {FormInsertPatch, insert, Path, SchemaType} from 'sanity'
|
|
2
|
-
|
|
3
|
-
import {Language, Value} from '../types'
|
|
4
|
-
import {createValueSchemaTypeName} from './createValueSchemaTypeName'
|
|
5
|
-
|
|
6
|
-
type AddConfig = {
|
|
7
|
-
// New keys to add to the field
|
|
8
|
-
addLanguageKeys: string[]
|
|
9
|
-
// Schema of the current field
|
|
10
|
-
schemaType: SchemaType
|
|
11
|
-
// All languages registered in the plugin
|
|
12
|
-
languages: Language[]
|
|
13
|
-
// Languages that are currently visible
|
|
14
|
-
filteredLanguages: Language[]
|
|
15
|
-
// Current value of the internationalizedArray field
|
|
16
|
-
value?: Value[]
|
|
17
|
-
// Path to this item
|
|
18
|
-
path?: Path
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function createAddLanguagePatches(config: AddConfig): FormInsertPatch[] {
|
|
22
|
-
const {
|
|
23
|
-
addLanguageKeys,
|
|
24
|
-
schemaType,
|
|
25
|
-
languages,
|
|
26
|
-
filteredLanguages,
|
|
27
|
-
value,
|
|
28
|
-
path = [],
|
|
29
|
-
} = config
|
|
30
|
-
|
|
31
|
-
const itemBase = {_type: createValueSchemaTypeName(schemaType)}
|
|
32
|
-
|
|
33
|
-
// Create new items
|
|
34
|
-
const getNewItems = () => {
|
|
35
|
-
if (Array.isArray(addLanguageKeys) && addLanguageKeys.length > 0) {
|
|
36
|
-
return addLanguageKeys.map((id) => ({
|
|
37
|
-
...itemBase,
|
|
38
|
-
_key: id,
|
|
39
|
-
}))
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return filteredLanguages
|
|
43
|
-
.filter((language) =>
|
|
44
|
-
value?.length ? !value.find((v) => v._key === language.id) : true
|
|
45
|
-
)
|
|
46
|
-
.map((language) => ({
|
|
47
|
-
...itemBase,
|
|
48
|
-
_key: language.id,
|
|
49
|
-
}))
|
|
50
|
-
}
|
|
51
|
-
const newItems = getNewItems()
|
|
52
|
-
|
|
53
|
-
// Insert new items in the correct order
|
|
54
|
-
const languagesInUse = value?.length ? value.map((v) => v) : []
|
|
55
|
-
|
|
56
|
-
const insertions = newItems.map((item) => {
|
|
57
|
-
// What's the original index of this language?
|
|
58
|
-
const languageIndex = languages.findIndex((l) => item._key === l.id)
|
|
59
|
-
|
|
60
|
-
// What languages are there beyond that index?
|
|
61
|
-
const remainingLanguages = languages.slice(languageIndex + 1)
|
|
62
|
-
|
|
63
|
-
// So what is the index in the current value array of the next language in the language array?
|
|
64
|
-
const nextLanguageIndex = languagesInUse.findIndex((l) =>
|
|
65
|
-
// eslint-disable-next-line max-nested-callbacks
|
|
66
|
-
remainingLanguages.find((r) => r.id === l._key)
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
// Keep local state up to date incase multiple insertions are being made
|
|
70
|
-
if (nextLanguageIndex < 0) {
|
|
71
|
-
languagesInUse.push(item)
|
|
72
|
-
} else {
|
|
73
|
-
languagesInUse.splice(nextLanguageIndex, 0, item)
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return nextLanguageIndex < 0
|
|
77
|
-
? // No next language (-1), add to end of array
|
|
78
|
-
insert([item], 'after', [...path, nextLanguageIndex])
|
|
79
|
-
: // Next language found, insert before that
|
|
80
|
-
insert([item], 'before', [...path, nextLanguageIndex])
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
return insertions
|
|
84
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
isDocumentSchemaType,
|
|
3
|
-
type ObjectField,
|
|
4
|
-
type Path,
|
|
5
|
-
type SchemaType,
|
|
6
|
-
} from 'sanity'
|
|
7
|
-
|
|
8
|
-
type ObjectFieldWithPath = ObjectField<SchemaType> & {path: Path}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Flattens a document's schema type into a flat array of fields and includes their path
|
|
12
|
-
*/
|
|
13
|
-
export function flattenSchemaType(
|
|
14
|
-
schemaType: SchemaType
|
|
15
|
-
): ObjectFieldWithPath[] {
|
|
16
|
-
if (!isDocumentSchemaType(schemaType)) {
|
|
17
|
-
console.error(`Schema type is not a document`)
|
|
18
|
-
return []
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return extractInnerFields(schemaType.fields, [], 3)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function extractInnerFields(
|
|
25
|
-
fields: ObjectField<SchemaType>[],
|
|
26
|
-
path: Path,
|
|
27
|
-
maxDepth: number
|
|
28
|
-
): ObjectFieldWithPath[] {
|
|
29
|
-
if (path.length >= maxDepth) {
|
|
30
|
-
return []
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return fields.reduce<ObjectFieldWithPath[]>((acc, field) => {
|
|
34
|
-
const thisFieldWithPath = {path: [...path, field.name], ...field}
|
|
35
|
-
|
|
36
|
-
if (field.type.jsonType === 'object') {
|
|
37
|
-
const innerFields = extractInnerFields(
|
|
38
|
-
field.type.fields,
|
|
39
|
-
[...path, field.name],
|
|
40
|
-
maxDepth
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
return [...acc, thisFieldWithPath, ...innerFields]
|
|
44
|
-
} else if (
|
|
45
|
-
field.type.jsonType === 'array' &&
|
|
46
|
-
field.type.of.length &&
|
|
47
|
-
field.type.of.some((item) => 'fields' in item)
|
|
48
|
-
) {
|
|
49
|
-
const innerFields = field.type.of.flatMap((innerField) =>
|
|
50
|
-
extractInnerFields(
|
|
51
|
-
// @ts-expect-error - Fix TS assertion for array fields
|
|
52
|
-
innerField.fields,
|
|
53
|
-
[...path, field.name],
|
|
54
|
-
maxDepth
|
|
55
|
-
)
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
-
return [...acc, thisFieldWithPath, ...innerFields]
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return [...acc, thisFieldWithPath]
|
|
62
|
-
}, [])
|
|
63
|
-
}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import {SanityDocument} from 'sanity'
|
|
2
|
-
|
|
3
|
-
export interface DocumentsToTranslate {
|
|
4
|
-
path: (string | number)[]
|
|
5
|
-
pathString: string
|
|
6
|
-
_key: string
|
|
7
|
-
_type: string
|
|
8
|
-
[key: string]: unknown
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export const getDocumentsToTranslate = (
|
|
12
|
-
value: SanityDocument | unknown,
|
|
13
|
-
rootPath: (string | number)[] = []
|
|
14
|
-
): DocumentsToTranslate[] => {
|
|
15
|
-
if (Array.isArray(value)) {
|
|
16
|
-
const arrayRootPath = [...rootPath]
|
|
17
|
-
|
|
18
|
-
// if item contains internationalized return array
|
|
19
|
-
const internationalizedValues = value.filter((item) => {
|
|
20
|
-
if (Array.isArray(item)) return false
|
|
21
|
-
|
|
22
|
-
if (typeof item === 'object') {
|
|
23
|
-
const type = item?._type as string | undefined
|
|
24
|
-
return (
|
|
25
|
-
type?.startsWith('internationalizedArray') && type?.endsWith('Value')
|
|
26
|
-
)
|
|
27
|
-
}
|
|
28
|
-
return false
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
if (internationalizedValues.length > 0) {
|
|
32
|
-
return internationalizedValues.map((internationalizedValue) => {
|
|
33
|
-
return {
|
|
34
|
-
...internationalizedValue,
|
|
35
|
-
path: arrayRootPath,
|
|
36
|
-
pathString: arrayRootPath.join('.'),
|
|
37
|
-
}
|
|
38
|
-
})
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (value.length > 0) {
|
|
42
|
-
return value
|
|
43
|
-
.map((item, index) =>
|
|
44
|
-
getDocumentsToTranslate(item, [...arrayRootPath, index])
|
|
45
|
-
)
|
|
46
|
-
.flat()
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return []
|
|
50
|
-
}
|
|
51
|
-
if (typeof value === 'object' && value) {
|
|
52
|
-
const startsWithUnderscoreRegex = /^_/
|
|
53
|
-
const itemKeys = Object.keys(value).filter(
|
|
54
|
-
(key) => !key.match(startsWithUnderscoreRegex)
|
|
55
|
-
) as (keyof typeof value)[]
|
|
56
|
-
|
|
57
|
-
return itemKeys
|
|
58
|
-
.map((item) => {
|
|
59
|
-
const selectedValue = value[item] as unknown
|
|
60
|
-
const path = [...rootPath, item]
|
|
61
|
-
return getDocumentsToTranslate(selectedValue, path)
|
|
62
|
-
})
|
|
63
|
-
.flat()
|
|
64
|
-
}
|
|
65
|
-
return []
|
|
66
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import {LanguageDisplay} from '../types'
|
|
2
|
-
|
|
3
|
-
export function getLanguageDisplay(
|
|
4
|
-
languageDisplay: LanguageDisplay,
|
|
5
|
-
title: string,
|
|
6
|
-
code: string
|
|
7
|
-
): string {
|
|
8
|
-
if (languageDisplay === 'codeOnly') return code.toUpperCase()
|
|
9
|
-
if (languageDisplay === 'titleOnly') return title
|
|
10
|
-
if (languageDisplay === 'titleAndCode')
|
|
11
|
-
return `${title} (${code.toUpperCase()})`
|
|
12
|
-
return title
|
|
13
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import {SchemaType} from 'sanity'
|
|
2
|
-
|
|
3
|
-
import {ArrayFieldOptions} from '../schema/array'
|
|
4
|
-
|
|
5
|
-
export function getLanguagesFieldOption(
|
|
6
|
-
schemaType: SchemaType | undefined
|
|
7
|
-
): ArrayFieldOptions['languages'] | undefined {
|
|
8
|
-
if (!schemaType) {
|
|
9
|
-
return undefined
|
|
10
|
-
}
|
|
11
|
-
const languagesOption = (schemaType.options as ArrayFieldOptions)?.languages
|
|
12
|
-
if (languagesOption) {
|
|
13
|
-
return languagesOption
|
|
14
|
-
}
|
|
15
|
-
return getLanguagesFieldOption(schemaType.type)
|
|
16
|
-
}
|
package/v2-incompatible.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
const {showIncompatiblePluginDialog} = require('@sanity/incompatible-plugin')
|
|
2
|
-
const {name, version, sanityExchangeUrl} = require('./package.json')
|
|
3
|
-
|
|
4
|
-
export default showIncompatiblePluginDialog({
|
|
5
|
-
name: name,
|
|
6
|
-
versions: {
|
|
7
|
-
v3: version,
|
|
8
|
-
v2: undefined,
|
|
9
|
-
},
|
|
10
|
-
sanityExchangeUrl,
|
|
11
|
-
})
|