sanity-plugin-studio-smartling 4.3.3 → 5.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/README.md +1 -5
- package/dist/index.d.ts +7 -47
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +100 -219
- package/dist/index.js.map +1 -1
- package/package.json +34 -66
- package/dist/index.esm.js +0 -268
- package/dist/index.esm.js.map +0 -1
- package/sanity.json +0 -8
- package/src/adapter/createTask.ts +0 -166
- package/src/adapter/getLocales.ts +0 -18
- package/src/adapter/getTranslation.ts +0 -36
- package/src/adapter/getTranslationTask.ts +0 -89
- package/src/adapter/helpers.ts +0 -84
- package/src/adapter/index.ts +0 -12
- package/src/index.ts +0 -52
- package/src/types.d.ts +0 -0
- package/v2-incompatible.js +0 -11
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import {authenticate, getHeaders} from './helpers'
|
|
2
|
-
import {Adapter, Secrets} from 'sanity-translations-tab'
|
|
3
|
-
|
|
4
|
-
export const getTranslation: Adapter['getTranslation'] = async (
|
|
5
|
-
taskId: string,
|
|
6
|
-
localeId: string,
|
|
7
|
-
secrets: Secrets | null,
|
|
8
|
-
) => {
|
|
9
|
-
if (!secrets?.project || !secrets?.secret || !secrets?.proxy) {
|
|
10
|
-
throw new Error(
|
|
11
|
-
'The Smartling adapter requires a project ID, a secret key, and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',
|
|
12
|
-
)
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const {project, proxy} = secrets
|
|
16
|
-
|
|
17
|
-
const url = `https://api.smartling.com/files-api/v2/projects/${project}/locales/${localeId}/file?fileUri=${taskId}&retrievalType=pending`
|
|
18
|
-
const accessToken = await authenticate(secrets)
|
|
19
|
-
const translatedHTML = await fetch(proxy, {
|
|
20
|
-
method: 'GET',
|
|
21
|
-
headers: getHeaders(url, accessToken),
|
|
22
|
-
})
|
|
23
|
-
.then((res) => res.json())
|
|
24
|
-
.then((res) => {
|
|
25
|
-
if (res.body) {
|
|
26
|
-
return res.body
|
|
27
|
-
} else if (res.response.errors) {
|
|
28
|
-
const errMsg =
|
|
29
|
-
res.response.errors[0]?.message || 'Error retrieving translation from Smartling'
|
|
30
|
-
throw new Error(errMsg)
|
|
31
|
-
}
|
|
32
|
-
return ''
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
return translatedHTML
|
|
36
|
-
}
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import {authenticate, getHeaders, findExistingJob} from './helpers'
|
|
2
|
-
import {Adapter, Secrets} from 'sanity-translations-tab'
|
|
3
|
-
|
|
4
|
-
interface WorkflowProgressItem {
|
|
5
|
-
workflowStepSummaryReportItemList: {
|
|
6
|
-
wordCount: number
|
|
7
|
-
}[]
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
interface SmartlingProgressItem {
|
|
11
|
-
targetLocaleId: string
|
|
12
|
-
progress: {
|
|
13
|
-
percentComplete: number
|
|
14
|
-
totalWordCount: number
|
|
15
|
-
}
|
|
16
|
-
workflowProgressReportList: WorkflowProgressItem[]
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export const getTranslationTask: Adapter['getTranslationTask'] = async (
|
|
20
|
-
documentId: string,
|
|
21
|
-
secrets: Secrets | null,
|
|
22
|
-
) => {
|
|
23
|
-
if (!secrets?.project || !secrets?.secret || !secrets?.proxy) {
|
|
24
|
-
return {
|
|
25
|
-
documentId,
|
|
26
|
-
taskId: documentId,
|
|
27
|
-
locales: [],
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const {project, proxy} = secrets
|
|
32
|
-
|
|
33
|
-
const accessToken = await authenticate(secrets)
|
|
34
|
-
const taskId = await findExistingJob(documentId, secrets, accessToken)
|
|
35
|
-
if (!taskId) {
|
|
36
|
-
return {
|
|
37
|
-
documentId,
|
|
38
|
-
taskId: documentId,
|
|
39
|
-
locales: [],
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const progressUrl = `https://api.smartling.com/jobs-api/v3/projects/${project}/jobs/${taskId}/progress`
|
|
44
|
-
const smartlingTask = await fetch(proxy, {
|
|
45
|
-
method: 'GET',
|
|
46
|
-
headers: getHeaders(progressUrl, accessToken),
|
|
47
|
-
})
|
|
48
|
-
.then((res) => res.json())
|
|
49
|
-
.then((res) => res.response.data)
|
|
50
|
-
|
|
51
|
-
let locales = []
|
|
52
|
-
if (smartlingTask && smartlingTask.contentProgressReport) {
|
|
53
|
-
locales = smartlingTask.contentProgressReport.map((item: SmartlingProgressItem) => {
|
|
54
|
-
let progress = item.progress ? item.progress.percentComplete : 0
|
|
55
|
-
if (
|
|
56
|
-
item.workflowProgressReportList &&
|
|
57
|
-
item.workflowProgressReportList.length > 0 &&
|
|
58
|
-
item.progress
|
|
59
|
-
) {
|
|
60
|
-
//default to the first workflow -- it's likely what is being used
|
|
61
|
-
const progressItem = item.workflowProgressReportList[0]
|
|
62
|
-
//this is a list of the various steps in the workflow
|
|
63
|
-
if (
|
|
64
|
-
progressItem.workflowStepSummaryReportItemList &&
|
|
65
|
-
progressItem.workflowStepSummaryReportItemList.length > 1
|
|
66
|
-
) {
|
|
67
|
-
//get the last step in the workflow -- usually "published"
|
|
68
|
-
const lastStep = progressItem.workflowStepSummaryReportItemList.at(-1)
|
|
69
|
-
//get the percentage of how many words have reached the last step
|
|
70
|
-
if (lastStep && lastStep.wordCount >= 0) {
|
|
71
|
-
progress = Math.floor((lastStep.wordCount / item.progress.totalWordCount) * 100) ?? 0
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return {
|
|
76
|
-
localeId: item.targetLocaleId,
|
|
77
|
-
progress,
|
|
78
|
-
}
|
|
79
|
-
})
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return {
|
|
83
|
-
documentId,
|
|
84
|
-
locales,
|
|
85
|
-
//since our download is tied to document id for smartling, keep track of it as a task
|
|
86
|
-
taskId: documentId,
|
|
87
|
-
linkToVendorTask: `https://dashboard.smartling.com/app/projects/${project}/account-jobs/${project}:${taskId}`,
|
|
88
|
-
}
|
|
89
|
-
}
|
package/src/adapter/helpers.ts
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import {Secrets} from 'sanity-translations-tab'
|
|
2
|
-
|
|
3
|
-
interface Headers {
|
|
4
|
-
[key: string]: string
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export const authenticate = (secrets: Secrets): Promise<string> => {
|
|
8
|
-
const url = 'https://api.smartling.com/auth-api/v2/authenticate'
|
|
9
|
-
const headers = {
|
|
10
|
-
'content-type': 'application/json',
|
|
11
|
-
'X-URL': url,
|
|
12
|
-
}
|
|
13
|
-
const {secret, proxy} = secrets
|
|
14
|
-
if (!secret || !proxy) {
|
|
15
|
-
throw new Error(
|
|
16
|
-
'The Smartling adapter requires a secret key and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',
|
|
17
|
-
)
|
|
18
|
-
}
|
|
19
|
-
return fetch(proxy, {
|
|
20
|
-
headers,
|
|
21
|
-
method: 'POST',
|
|
22
|
-
body: JSON.stringify(secret),
|
|
23
|
-
})
|
|
24
|
-
.then((res) => res.json())
|
|
25
|
-
.then((res) => res.response.data.accessToken)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export const getHeaders = (url: string, accessToken: string): Headers => ({
|
|
29
|
-
Authorization: `Bearer ${accessToken}`,
|
|
30
|
-
'X-URL': url,
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
export const findExistingJob = async (
|
|
34
|
-
documentId: string,
|
|
35
|
-
secrets: Secrets,
|
|
36
|
-
accessToken: string,
|
|
37
|
-
): Promise<string> => {
|
|
38
|
-
const {project, proxy} = secrets
|
|
39
|
-
if (!project || !proxy) {
|
|
40
|
-
throw new Error(
|
|
41
|
-
'The Smartling adapter requires a Smartling project identifier and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',
|
|
42
|
-
)
|
|
43
|
-
}
|
|
44
|
-
const url = `https://api.smartling.com/jobs-api/v3/projects/${project}/jobs?jobName=${documentId}`
|
|
45
|
-
//first, try fetching from name resolution
|
|
46
|
-
let items = await fetch(proxy, {
|
|
47
|
-
headers: getHeaders(url, accessToken),
|
|
48
|
-
})
|
|
49
|
-
.then((res) => res.json())
|
|
50
|
-
.then((res) => res?.response?.data?.items)
|
|
51
|
-
|
|
52
|
-
if (!items || !items.length) {
|
|
53
|
-
//if that fails, try fetching by fileUri and check the referenceNumber
|
|
54
|
-
const refUrl = `https://api.smartling.com/jobs-api/v3/projects/${project}/jobs/search`
|
|
55
|
-
items = await fetch(proxy, {
|
|
56
|
-
headers: {
|
|
57
|
-
...getHeaders(refUrl, accessToken),
|
|
58
|
-
'content-type': 'application/json',
|
|
59
|
-
},
|
|
60
|
-
method: 'POST',
|
|
61
|
-
body: JSON.stringify({
|
|
62
|
-
fileUris: [documentId],
|
|
63
|
-
}),
|
|
64
|
-
})
|
|
65
|
-
.then((res) => res.json())
|
|
66
|
-
.then((res) => res?.response?.data?.items)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (items.length) {
|
|
70
|
-
//smartling will fuzzy match job names. We need to be precise.
|
|
71
|
-
const correctJob = items
|
|
72
|
-
.filter((item: {jobStatus: string}) => item.jobStatus !== 'DELETED')
|
|
73
|
-
.find(
|
|
74
|
-
(item: {jobName: string; referenceNumber: string}) =>
|
|
75
|
-
(item.jobName && item.jobName === documentId) ||
|
|
76
|
-
(item.referenceNumber && item.referenceNumber === documentId),
|
|
77
|
-
)
|
|
78
|
-
|
|
79
|
-
if (correctJob) {
|
|
80
|
-
return correctJob.translationJobUid
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
return ''
|
|
84
|
-
}
|
package/src/adapter/index.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import {Adapter} from 'sanity-translations-tab'
|
|
2
|
-
import {getLocales} from './getLocales'
|
|
3
|
-
import {getTranslationTask} from './getTranslationTask'
|
|
4
|
-
import {createTask} from './createTask'
|
|
5
|
-
import {getTranslation} from './getTranslation'
|
|
6
|
-
|
|
7
|
-
export const SmartlingAdapter: Adapter = {
|
|
8
|
-
getLocales,
|
|
9
|
-
getTranslationTask,
|
|
10
|
-
createTask,
|
|
11
|
-
getTranslation,
|
|
12
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
TranslationsTab,
|
|
3
|
-
baseDocumentLevelConfig,
|
|
4
|
-
legacyDocumentLevelConfig as baseLegacyDocumentLevelConfig,
|
|
5
|
-
baseFieldLevelConfig,
|
|
6
|
-
findLatestDraft,
|
|
7
|
-
BaseDocumentDeserializer,
|
|
8
|
-
BaseDocumentSerializer,
|
|
9
|
-
BaseDocumentMerger,
|
|
10
|
-
defaultStopTypes,
|
|
11
|
-
customSerializers,
|
|
12
|
-
legacyDocumentLevelPatch,
|
|
13
|
-
documentLevelPatch,
|
|
14
|
-
fieldLevelPatch,
|
|
15
|
-
TranslationFunctionContext,
|
|
16
|
-
TranslationsTabConfigOptions,
|
|
17
|
-
} from 'sanity-translations-tab'
|
|
18
|
-
import {SmartlingAdapter} from './adapter'
|
|
19
|
-
|
|
20
|
-
const defaultDocumentLevelConfig: TranslationsTabConfigOptions = {
|
|
21
|
-
...baseDocumentLevelConfig,
|
|
22
|
-
adapter: SmartlingAdapter,
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const legacyDocumentLevelConfig: TranslationsTabConfigOptions = {
|
|
26
|
-
...baseLegacyDocumentLevelConfig,
|
|
27
|
-
adapter: SmartlingAdapter,
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const defaultFieldLevelConfig: TranslationsTabConfigOptions = {
|
|
31
|
-
...baseFieldLevelConfig,
|
|
32
|
-
adapter: SmartlingAdapter,
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export {
|
|
36
|
-
TranslationsTab,
|
|
37
|
-
findLatestDraft,
|
|
38
|
-
legacyDocumentLevelPatch,
|
|
39
|
-
documentLevelPatch,
|
|
40
|
-
fieldLevelPatch,
|
|
41
|
-
BaseDocumentDeserializer,
|
|
42
|
-
BaseDocumentSerializer,
|
|
43
|
-
BaseDocumentMerger,
|
|
44
|
-
defaultStopTypes,
|
|
45
|
-
customSerializers,
|
|
46
|
-
SmartlingAdapter,
|
|
47
|
-
legacyDocumentLevelConfig,
|
|
48
|
-
defaultDocumentLevelConfig,
|
|
49
|
-
defaultFieldLevelConfig,
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export type {TranslationFunctionContext, TranslationsTabConfigOptions}
|
package/src/types.d.ts
DELETED
|
File without changes
|
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
|
-
})
|