@easyling/sanity-connector 0.0.1 → 0.0.2-rc.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/dist/.tsbuildinfo +1 -1
- package/package.json +18 -12
- package/dist/actions/bulkTranslate.d.ts +0 -7
- package/dist/actions/bulkTranslate.d.ts.map +0 -1
- package/dist/actions/bulkTranslate.js +0 -543
- package/dist/actions/bulkTranslate.js.map +0 -1
- package/dist/actions/manageDNTFields.d.ts +0 -12
- package/dist/actions/manageDNTFields.d.ts.map +0 -1
- package/dist/actions/manageDNTFields.js +0 -100
- package/dist/actions/manageDNTFields.js.map +0 -1
- package/dist/actions/translateDocument.d.ts +0 -7
- package/dist/actions/translateDocument.d.ts.map +0 -1
- package/dist/actions/translateDocument.js +0 -256
- package/dist/actions/translateDocument.js.map +0 -1
- package/dist/components/RadioWithDefault.d.ts +0 -17
- package/dist/components/RadioWithDefault.d.ts.map +0 -1
- package/dist/components/RadioWithDefault.js +0 -29
- package/dist/components/RadioWithDefault.js.map +0 -1
- package/dist/components/auth/AuthNavbar.d.ts +0 -18
- package/dist/components/auth/AuthNavbar.d.ts.map +0 -1
- package/dist/components/auth/AuthNavbar.js +0 -15
- package/dist/components/auth/AuthNavbar.js.map +0 -1
- package/dist/components/auth/AuthStatus.d.ts +0 -27
- package/dist/components/auth/AuthStatus.d.ts.map +0 -1
- package/dist/components/auth/AuthStatus.js +0 -82
- package/dist/components/auth/AuthStatus.js.map +0 -1
- package/dist/components/auth/AuthStatusWrapper.d.ts +0 -15
- package/dist/components/auth/AuthStatusWrapper.d.ts.map +0 -1
- package/dist/components/auth/AuthStatusWrapper.js +0 -39
- package/dist/components/auth/AuthStatusWrapper.js.map +0 -1
- package/dist/components/auth/MigrationPrompt.d.ts +0 -20
- package/dist/components/auth/MigrationPrompt.d.ts.map +0 -1
- package/dist/components/auth/MigrationPrompt.js +0 -16
- package/dist/components/auth/MigrationPrompt.js.map +0 -1
- package/dist/components/auth/MigrationPromptWrapper.d.ts +0 -14
- package/dist/components/auth/MigrationPromptWrapper.d.ts.map +0 -1
- package/dist/components/auth/MigrationPromptWrapper.js +0 -16
- package/dist/components/auth/MigrationPromptWrapper.js.map +0 -1
- package/dist/components/auth/OAuthCallback.d.ts +0 -20
- package/dist/components/auth/OAuthCallback.d.ts.map +0 -1
- package/dist/components/auth/OAuthCallback.js +0 -12
- package/dist/components/auth/OAuthCallback.js.map +0 -1
- package/dist/components/auth/index.d.ts +0 -15
- package/dist/components/auth/index.d.ts.map +0 -1
- package/dist/components/auth/index.js +0 -12
- package/dist/components/auth/index.js.map +0 -1
- package/dist/components/config/LocaleConfigTool.d.ts +0 -17
- package/dist/components/config/LocaleConfigTool.d.ts.map +0 -1
- package/dist/components/config/LocaleConfigTool.js +0 -186
- package/dist/components/config/LocaleConfigTool.js.map +0 -1
- package/dist/components/config/LocaleConfigToolWrapper.d.ts +0 -13
- package/dist/components/config/LocaleConfigToolWrapper.d.ts.map +0 -1
- package/dist/components/config/LocaleConfigToolWrapper.js +0 -26
- package/dist/components/config/LocaleConfigToolWrapper.js.map +0 -1
- package/dist/components/config/OAuthConfig.d.ts +0 -26
- package/dist/components/config/OAuthConfig.d.ts.map +0 -1
- package/dist/components/config/OAuthConfig.js +0 -152
- package/dist/components/config/OAuthConfig.js.map +0 -1
- package/dist/components/config/OAuthConfigWrapper.d.ts +0 -13
- package/dist/components/config/OAuthConfigWrapper.d.ts.map +0 -1
- package/dist/components/config/OAuthConfigWrapper.js +0 -41
- package/dist/components/config/OAuthConfigWrapper.js.map +0 -1
- package/dist/components/config/PasswordInput.d.ts +0 -14
- package/dist/components/config/PasswordInput.d.ts.map +0 -1
- package/dist/components/config/PasswordInput.js +0 -23
- package/dist/components/config/PasswordInput.js.map +0 -1
- package/dist/components/config/index.d.ts +0 -9
- package/dist/components/config/index.d.ts.map +0 -1
- package/dist/components/config/index.js +0 -8
- package/dist/components/config/index.js.map +0 -1
- package/dist/components/config/localeConfigToolDefinition.d.ts +0 -13
- package/dist/components/config/localeConfigToolDefinition.d.ts.map +0 -1
- package/dist/components/config/localeConfigToolDefinition.js +0 -19
- package/dist/components/config/localeConfigToolDefinition.js.map +0 -1
- package/dist/components/config/oauthConfigToolDefinition.d.ts +0 -13
- package/dist/components/config/oauthConfigToolDefinition.d.ts.map +0 -1
- package/dist/components/config/oauthConfigToolDefinition.js +0 -19
- package/dist/components/config/oauthConfigToolDefinition.js.map +0 -1
- package/dist/components/dialogs/ConfirmationDialog.d.ts +0 -21
- package/dist/components/dialogs/ConfirmationDialog.d.ts.map +0 -1
- package/dist/components/dialogs/ConfirmationDialog.js +0 -28
- package/dist/components/dialogs/ConfirmationDialog.js.map +0 -1
- package/dist/components/dialogs/ErrorDialog.d.ts +0 -21
- package/dist/components/dialogs/ErrorDialog.d.ts.map +0 -1
- package/dist/components/dialogs/ErrorDialog.js +0 -28
- package/dist/components/dialogs/ErrorDialog.js.map +0 -1
- package/dist/components/dialogs/LocaleSelectionDialog.d.ts +0 -41
- package/dist/components/dialogs/LocaleSelectionDialog.d.ts.map +0 -1
- package/dist/components/dialogs/LocaleSelectionDialog.js +0 -117
- package/dist/components/dialogs/LocaleSelectionDialog.js.map +0 -1
- package/dist/components/dialogs/SuccessDialog.d.ts +0 -19
- package/dist/components/dialogs/SuccessDialog.d.ts.map +0 -1
- package/dist/components/dialogs/SuccessDialog.js +0 -37
- package/dist/components/dialogs/SuccessDialog.js.map +0 -1
- package/dist/components/dialogs/index.d.ts +0 -12
- package/dist/components/dialogs/index.d.ts.map +0 -1
- package/dist/components/dialogs/index.js +0 -8
- package/dist/components/dialogs/index.js.map +0 -1
- package/dist/components/dnt/DNTFieldBadge.d.ts +0 -16
- package/dist/components/dnt/DNTFieldBadge.d.ts.map +0 -1
- package/dist/components/dnt/DNTFieldBadge.js +0 -56
- package/dist/components/dnt/DNTFieldBadge.js.map +0 -1
- package/dist/components/dnt/DNTFieldComponent.d.ts +0 -17
- package/dist/components/dnt/DNTFieldComponent.d.ts.map +0 -1
- package/dist/components/dnt/DNTFieldComponent.js +0 -21
- package/dist/components/dnt/DNTFieldComponent.js.map +0 -1
- package/dist/components/dnt/DNTFieldInput.d.ts +0 -14
- package/dist/components/dnt/DNTFieldInput.d.ts.map +0 -1
- package/dist/components/dnt/DNTFieldInput.js +0 -76
- package/dist/components/dnt/DNTFieldInput.js.map +0 -1
- package/dist/components/dnt/index.d.ts +0 -7
- package/dist/components/dnt/index.d.ts.map +0 -1
- package/dist/components/dnt/index.js +0 -7
- package/dist/components/dnt/index.js.map +0 -1
- package/dist/config/index.d.ts +0 -6
- package/dist/config/index.d.ts.map +0 -1
- package/dist/config/index.js +0 -6
- package/dist/config/index.js.map +0 -1
- package/dist/config/pluginConfig.d.ts +0 -163
- package/dist/config/pluginConfig.d.ts.map +0 -1
- package/dist/config/pluginConfig.js +0 -548
- package/dist/config/pluginConfig.js.map +0 -1
- package/dist/index.d.ts +0 -12
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -12
- package/dist/index.js.map +0 -1
- package/dist/plugin.d.ts +0 -3
- package/dist/plugin.d.ts.map +0 -1
- package/dist/plugin.js +0 -137
- package/dist/plugin.js.map +0 -1
- package/dist/services/authStateManager.d.ts +0 -94
- package/dist/services/authStateManager.d.ts.map +0 -1
- package/dist/services/authStateManager.js +0 -208
- package/dist/services/authStateManager.js.map +0 -1
- package/dist/services/contentExtractor.d.ts +0 -95
- package/dist/services/contentExtractor.d.ts.map +0 -1
- package/dist/services/contentExtractor.js +0 -516
- package/dist/services/contentExtractor.js.map +0 -1
- package/dist/services/dialogService.d.ts +0 -96
- package/dist/services/dialogService.d.ts.map +0 -1
- package/dist/services/dialogService.js +0 -244
- package/dist/services/dialogService.js.map +0 -1
- package/dist/services/dntServiceManager.d.ts +0 -44
- package/dist/services/dntServiceManager.d.ts.map +0 -1
- package/dist/services/dntServiceManager.js +0 -74
- package/dist/services/dntServiceManager.js.map +0 -1
- package/dist/services/dntStorageAdapter.d.ts +0 -73
- package/dist/services/dntStorageAdapter.d.ts.map +0 -1
- package/dist/services/dntStorageAdapter.js +0 -192
- package/dist/services/dntStorageAdapter.js.map +0 -1
- package/dist/services/documentCreationService.d.ts +0 -139
- package/dist/services/documentCreationService.d.ts.map +0 -1
- package/dist/services/documentCreationService.js +0 -938
- package/dist/services/documentCreationService.js.map +0 -1
- package/dist/services/localeService.d.ts +0 -160
- package/dist/services/localeService.d.ts.map +0 -1
- package/dist/services/localeService.js +0 -300
- package/dist/services/localeService.js.map +0 -1
- package/dist/services/localeStorageAdapter.d.ts +0 -42
- package/dist/services/localeStorageAdapter.d.ts.map +0 -1
- package/dist/services/localeStorageAdapter.js +0 -107
- package/dist/services/localeStorageAdapter.js.map +0 -1
- package/dist/services/oauthConfigStorage.d.ts +0 -46
- package/dist/services/oauthConfigStorage.d.ts.map +0 -1
- package/dist/services/oauthConfigStorage.js +0 -122
- package/dist/services/oauthConfigStorage.js.map +0 -1
- package/dist/services/oauthService.d.ts +0 -48
- package/dist/services/oauthService.d.ts.map +0 -1
- package/dist/services/oauthService.js +0 -71
- package/dist/services/oauthService.js.map +0 -1
- package/dist/services/oauthServiceManager.d.ts +0 -189
- package/dist/services/oauthServiceManager.d.ts.map +0 -1
- package/dist/services/oauthServiceManager.js +0 -380
- package/dist/services/oauthServiceManager.js.map +0 -1
- package/dist/services/tokenStorage.d.ts +0 -54
- package/dist/services/tokenStorage.d.ts.map +0 -1
- package/dist/services/tokenStorage.js +0 -140
- package/dist/services/tokenStorage.js.map +0 -1
- package/dist/services/translationService.d.ts +0 -374
- package/dist/services/translationService.d.ts.map +0 -1
- package/dist/services/translationService.js +0 -687
- package/dist/services/translationService.js.map +0 -1
- package/dist/services/unifiedConfigStorage.d.ts +0 -124
- package/dist/services/unifiedConfigStorage.d.ts.map +0 -1
- package/dist/services/unifiedConfigStorage.js +0 -304
- package/dist/services/unifiedConfigStorage.js.map +0 -1
- package/dist/test-utils.d.ts +0 -9
- package/dist/test-utils.d.ts.map +0 -1
- package/dist/test-utils.js +0 -13
- package/dist/test-utils.js.map +0 -1
- package/dist/types/dialog.d.ts +0 -107
- package/dist/types/dialog.d.ts.map +0 -1
- package/dist/types/dialog.js +0 -6
- package/dist/types/dialog.js.map +0 -1
- package/dist/types/dnt.d.ts +0 -84
- package/dist/types/dnt.d.ts.map +0 -1
- package/dist/types/dnt.js +0 -5
- package/dist/types/dnt.js.map +0 -1
- package/dist/types/index.d.ts +0 -12
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -6
- package/dist/types/index.js.map +0 -1
- package/dist/types/locale.d.ts +0 -116
- package/dist/types/locale.d.ts.map +0 -1
- package/dist/types/locale.js +0 -189
- package/dist/types/locale.js.map +0 -1
- package/dist/types/oauth.d.ts +0 -90
- package/dist/types/oauth.d.ts.map +0 -1
- package/dist/types/oauth.js +0 -62
- package/dist/types/oauth.js.map +0 -1
- package/dist/types/pluginConfig.d.ts +0 -45
- package/dist/types/pluginConfig.d.ts.map +0 -1
- package/dist/types/pluginConfig.js +0 -6
- package/dist/types/pluginConfig.js.map +0 -1
- package/dist/types/translation.d.ts +0 -122
- package/dist/types/translation.d.ts.map +0 -1
- package/dist/types/translation.js +0 -6
- package/dist/types/translation.js.map +0 -1
- package/dist/utils/htmlFormatter.d.ts +0 -66
- package/dist/utils/htmlFormatter.d.ts.map +0 -1
- package/dist/utils/htmlFormatter.js +0 -191
- package/dist/utils/htmlFormatter.js.map +0 -1
- package/dist/utils/index.d.ts +0 -15
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -16
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/logger.d.ts +0 -105
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.js +0 -229
- package/dist/utils/logger.js.map +0 -1
- package/dist/utils/oauthErrorFeedback.d.ts +0 -76
- package/dist/utils/oauthErrorFeedback.d.ts.map +0 -1
- package/dist/utils/oauthErrorFeedback.js +0 -134
- package/dist/utils/oauthErrorFeedback.js.map +0 -1
- package/dist/utils/oauthLogger.d.ts +0 -176
- package/dist/utils/oauthLogger.d.ts.map +0 -1
- package/dist/utils/oauthLogger.js +0 -282
- package/dist/utils/oauthLogger.js.map +0 -1
- package/dist/utils/validator.d.ts +0 -67
- package/dist/utils/validator.d.ts.map +0 -1
- package/dist/utils/validator.js +0 -390
- package/dist/utils/validator.js.map +0 -1
|
@@ -1,687 +0,0 @@
|
|
|
1
|
-
import * as TranslationRequestProto from '@easyling/sanity/dist/generated/translation_request';
|
|
2
|
-
import * as TranslationResponseProto from '@easyling/sanity/dist/generated/translation_response';
|
|
3
|
-
export class TranslationService {
|
|
4
|
-
constructor(placeholderEndpoint = 'http://localhost:8275/translate', requestContentType = 'application/json', responseAcceptHeader = 'application/json') {
|
|
5
|
-
this.placeholderEndpoint = placeholderEndpoint;
|
|
6
|
-
this.requestContentType = requestContentType;
|
|
7
|
-
this.responseAcceptHeader = responseAcceptHeader;
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Infer the Sanity field type from a value
|
|
11
|
-
*
|
|
12
|
-
* @param value - The field value to inspect
|
|
13
|
-
* @returns The inferred Sanity type string
|
|
14
|
-
*/
|
|
15
|
-
inferSanityType(value) {
|
|
16
|
-
if (value === null || value === undefined) {
|
|
17
|
-
return 'undefined';
|
|
18
|
-
}
|
|
19
|
-
// Check for Sanity-specific object types
|
|
20
|
-
if (typeof value === 'object' && !Array.isArray(value)) {
|
|
21
|
-
const obj = value;
|
|
22
|
-
// Sanity objects have a _type field
|
|
23
|
-
if (obj._type) {
|
|
24
|
-
return obj._type;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
// Check primitive types
|
|
28
|
-
if (typeof value === 'string') {
|
|
29
|
-
return 'string';
|
|
30
|
-
}
|
|
31
|
-
if (typeof value === 'number') {
|
|
32
|
-
return 'number';
|
|
33
|
-
}
|
|
34
|
-
if (typeof value === 'boolean') {
|
|
35
|
-
return 'boolean';
|
|
36
|
-
}
|
|
37
|
-
if (Array.isArray(value)) {
|
|
38
|
-
return 'array';
|
|
39
|
-
}
|
|
40
|
-
if (typeof value === 'object') {
|
|
41
|
-
return 'object';
|
|
42
|
-
}
|
|
43
|
-
return 'unknown';
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Set authentication token and project ID
|
|
47
|
-
* Requirements: 4.1, 4.2, 4.3
|
|
48
|
-
*
|
|
49
|
-
* @param token - Access token for API authentication
|
|
50
|
-
* @param projectId - Project ID to include in requests
|
|
51
|
-
*/
|
|
52
|
-
setAuthToken(token, projectId) {
|
|
53
|
-
this.accessToken = token;
|
|
54
|
-
this.projectId = projectId;
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Clear authentication data
|
|
58
|
-
*/
|
|
59
|
-
clearAuth() {
|
|
60
|
-
this.accessToken = undefined;
|
|
61
|
-
this.projectId = undefined;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Update configuration for content types and endpoint
|
|
65
|
-
* Allows partial updates - only provided parameters will be updated
|
|
66
|
-
* Requirements: 1.1, 2.3, 3.3
|
|
67
|
-
*
|
|
68
|
-
* @param endpoint - Optional translation API endpoint URL
|
|
69
|
-
* @param requestContentType - Optional request Content-Type header value
|
|
70
|
-
* @param responseAcceptHeader - Optional response Accept header value
|
|
71
|
-
*/
|
|
72
|
-
setConfiguration(endpoint, requestContentType, responseAcceptHeader) {
|
|
73
|
-
if (endpoint !== undefined) {
|
|
74
|
-
this.placeholderEndpoint = endpoint;
|
|
75
|
-
}
|
|
76
|
-
if (requestContentType !== undefined) {
|
|
77
|
-
this.requestContentType = requestContentType;
|
|
78
|
-
}
|
|
79
|
-
if (responseAcceptHeader !== undefined) {
|
|
80
|
-
this.responseAcceptHeader = responseAcceptHeader;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Convert internal payload to Protocol Buffer binary format
|
|
85
|
-
* Requirements: Uses @easyling/sanity protobuf library
|
|
86
|
-
*
|
|
87
|
-
* @param payload - Internal translation request payload
|
|
88
|
-
* @returns Binary protobuf message
|
|
89
|
-
*/
|
|
90
|
-
convertPayloadToProtobuf(payload) {
|
|
91
|
-
// Convert internal TranslatableField objects to protobuf format
|
|
92
|
-
// Type information should be set by this point (from contentExtractor)
|
|
93
|
-
const protoFields = {};
|
|
94
|
-
for (const [key, field] of Object.entries(payload.content.fields)) {
|
|
95
|
-
// Handle both TranslatableField objects and plain values (for backward compatibility)
|
|
96
|
-
if (field && typeof field === 'object' && 'value' in field) {
|
|
97
|
-
// Already a TranslatableField object - type should be set from contentExtractor
|
|
98
|
-
const typedField = field;
|
|
99
|
-
// Warn if type is missing - should be set by contentExtractor in normal flow
|
|
100
|
-
let fieldType = typedField.type;
|
|
101
|
-
if (!fieldType) {
|
|
102
|
-
console.warn(`Field '${key}' missing type in protobuf conversion, inferring from value`);
|
|
103
|
-
fieldType = this.inferSanityType(typedField.value);
|
|
104
|
-
}
|
|
105
|
-
protoFields[key] = {
|
|
106
|
-
value: typeof typedField.value === 'string' ? typedField.value : JSON.stringify(typedField.value),
|
|
107
|
-
dnt: typedField.dnt || false,
|
|
108
|
-
type: fieldType
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
// Plain value - may happen for direct API calls that bypass contentExtractor
|
|
113
|
-
console.warn(`Field '${key}' not in TranslatableField format, wrapping with inferred type`);
|
|
114
|
-
protoFields[key] = {
|
|
115
|
-
value: typeof field === 'string' ? field : JSON.stringify(field),
|
|
116
|
-
dnt: false,
|
|
117
|
-
type: this.inferSanityType(field)
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
// Create protobuf message from our payload
|
|
122
|
-
const protoPayload = TranslationRequestProto.TranslationRequestPayload.create({
|
|
123
|
-
content: {
|
|
124
|
-
body: payload.content.body,
|
|
125
|
-
title: payload.content.title,
|
|
126
|
-
slug: payload.content.slug,
|
|
127
|
-
fields: protoFields
|
|
128
|
-
},
|
|
129
|
-
project: this.projectId || '', // Project code for identification
|
|
130
|
-
format: payload.format,
|
|
131
|
-
metadata: {
|
|
132
|
-
documentId: payload.metadata.documentId,
|
|
133
|
-
documentType: payload.metadata.documentType,
|
|
134
|
-
title: payload.metadata.title,
|
|
135
|
-
sourceLanguage: payload.metadata.sourceLanguage || '',
|
|
136
|
-
targetLanguage: payload.metadata.targetLanguage || '',
|
|
137
|
-
targetLocales: payload.metadata.targetLocales || []
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
// Encode protobuf message to binary format
|
|
141
|
-
return TranslationRequestProto.TranslationRequestPayload.encode(protoPayload).finish();
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Convert protobuf payload to JSON for logging purposes only
|
|
145
|
-
*
|
|
146
|
-
* @param payload - Internal translation request payload
|
|
147
|
-
* @returns JSON representation for logging
|
|
148
|
-
*/
|
|
149
|
-
convertPayloadToProtobufJSON(payload) {
|
|
150
|
-
// Convert internal TranslatableField objects to protobuf format
|
|
151
|
-
const protoFields = {};
|
|
152
|
-
for (const [key, field] of Object.entries(payload.content.fields)) {
|
|
153
|
-
if (field && typeof field === 'object' && 'value' in field) {
|
|
154
|
-
const typedField = field;
|
|
155
|
-
protoFields[key] = {
|
|
156
|
-
value: typeof typedField.value === 'string' ? typedField.value : JSON.stringify(typedField.value),
|
|
157
|
-
dnt: typedField.dnt || false,
|
|
158
|
-
type: typedField.type || 'unknown'
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
else {
|
|
162
|
-
protoFields[key] = {
|
|
163
|
-
value: typeof field === 'string' ? field : JSON.stringify(field),
|
|
164
|
-
dnt: false,
|
|
165
|
-
type: 'unknown'
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
const protoPayload = TranslationRequestProto.TranslationRequestPayload.create({
|
|
170
|
-
content: {
|
|
171
|
-
body: payload.content.body,
|
|
172
|
-
title: payload.content.title,
|
|
173
|
-
slug: payload.content.slug,
|
|
174
|
-
fields: protoFields
|
|
175
|
-
},
|
|
176
|
-
project: this.projectId || '',
|
|
177
|
-
format: payload.format,
|
|
178
|
-
metadata: {
|
|
179
|
-
documentId: payload.metadata.documentId,
|
|
180
|
-
documentType: payload.metadata.documentType,
|
|
181
|
-
title: payload.metadata.title,
|
|
182
|
-
sourceLanguage: payload.metadata.sourceLanguage || '',
|
|
183
|
-
targetLanguage: payload.metadata.targetLanguage || '',
|
|
184
|
-
targetLocales: payload.metadata.targetLocales || []
|
|
185
|
-
}
|
|
186
|
-
});
|
|
187
|
-
return TranslationRequestProto.TranslationRequestPayload.toJSON(protoPayload);
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* Normalize field values to ensure consistency
|
|
191
|
-
* Extracts values from TranslatableField objects and handles various formats
|
|
192
|
-
*/
|
|
193
|
-
normalizeTranslatedFields(fields) {
|
|
194
|
-
const normalizedFields = {};
|
|
195
|
-
if (!fields || typeof fields !== 'object') {
|
|
196
|
-
return normalizedFields;
|
|
197
|
-
}
|
|
198
|
-
for (const [key, fieldValue] of Object.entries(fields)) {
|
|
199
|
-
// Handle both TranslatableField objects and plain values
|
|
200
|
-
if (fieldValue && typeof fieldValue === 'object' && 'value' in fieldValue) {
|
|
201
|
-
// It's already a TranslatableField object
|
|
202
|
-
normalizedFields[key] = {
|
|
203
|
-
value: fieldValue.value,
|
|
204
|
-
dnt: fieldValue.dnt || false,
|
|
205
|
-
type: fieldValue.type || this.inferSanityType(fieldValue.value)
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
else {
|
|
209
|
-
// It's a plain value - wrap it in TranslatableField format
|
|
210
|
-
normalizedFields[key] = {
|
|
211
|
-
value: fieldValue,
|
|
212
|
-
dnt: false,
|
|
213
|
-
type: this.inferSanityType(fieldValue)
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
return normalizedFields;
|
|
218
|
-
}
|
|
219
|
-
/**
|
|
220
|
-
* Convert binary protobuf response to internal format
|
|
221
|
-
* Requirements: Uses @easyling/sanity protobuf library
|
|
222
|
-
*
|
|
223
|
-
* @param binaryData - Binary protobuf response data
|
|
224
|
-
* @returns Internal translation response format
|
|
225
|
-
*/
|
|
226
|
-
convertProtobufBinaryToResponse(binaryData) {
|
|
227
|
-
// Decode binary protobuf response
|
|
228
|
-
const protoResponse = TranslationResponseProto.TranslationResponse.decode(binaryData);
|
|
229
|
-
// Convert to internal format
|
|
230
|
-
const translatedDocuments = protoResponse.translatedDocuments.map(doc => {
|
|
231
|
-
// Convert protobuf TranslatableField back to internal format
|
|
232
|
-
const fields = {};
|
|
233
|
-
if (doc.fields && typeof doc.fields === 'object') {
|
|
234
|
-
for (const [key, protoField] of Object.entries(doc.fields)) {
|
|
235
|
-
if (protoField && typeof protoField === 'object' && 'value' in protoField) {
|
|
236
|
-
const fieldValue = protoField.value;
|
|
237
|
-
const fieldType = protoField.type;
|
|
238
|
-
try {
|
|
239
|
-
// Try to parse as JSON if it's a stringified value
|
|
240
|
-
const parsedValue = JSON.parse(fieldValue);
|
|
241
|
-
fields[key] = {
|
|
242
|
-
value: parsedValue,
|
|
243
|
-
dnt: protoField.dnt || false,
|
|
244
|
-
type: fieldType || this.inferSanityType(parsedValue)
|
|
245
|
-
};
|
|
246
|
-
}
|
|
247
|
-
catch {
|
|
248
|
-
// If parsing fails, use the string value as-is
|
|
249
|
-
fields[key] = {
|
|
250
|
-
value: fieldValue,
|
|
251
|
-
dnt: protoField.dnt || false,
|
|
252
|
-
type: fieldType || this.inferSanityType(fieldValue)
|
|
253
|
-
};
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
return {
|
|
259
|
-
body: doc.body,
|
|
260
|
-
title: doc.title,
|
|
261
|
-
slug: doc.slug,
|
|
262
|
-
fields,
|
|
263
|
-
locale: doc.locale
|
|
264
|
-
};
|
|
265
|
-
});
|
|
266
|
-
return {
|
|
267
|
-
success: protoResponse.success,
|
|
268
|
-
translatedDocuments,
|
|
269
|
-
sourceLocale: protoResponse.sourceLocale,
|
|
270
|
-
error: protoResponse.error,
|
|
271
|
-
requestId: protoResponse.requestId
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
|
-
/**
|
|
275
|
-
* Convert protobuf JSON response back to internal format (for legacy support)
|
|
276
|
-
* Requirements: Uses @easyling/sanity protobuf library
|
|
277
|
-
*
|
|
278
|
-
* @param jsonData - JSON response data
|
|
279
|
-
* @returns Internal translation response format
|
|
280
|
-
*/
|
|
281
|
-
convertProtobufJSONToResponse(jsonData) {
|
|
282
|
-
// Parse the JSON into a protobuf message
|
|
283
|
-
const protoResponse = TranslationResponseProto.TranslationResponse.fromJSON(jsonData);
|
|
284
|
-
// Convert to internal format
|
|
285
|
-
const translatedDocuments = protoResponse.translatedDocuments.map((doc, index) => {
|
|
286
|
-
// Get original document data from jsonData to handle mixed field formats
|
|
287
|
-
const originalDoc = jsonData.translatedDocuments?.[index];
|
|
288
|
-
// Convert protobuf TranslatableField back to internal format
|
|
289
|
-
const protoFields = {};
|
|
290
|
-
if (doc.fields && typeof doc.fields === 'object') {
|
|
291
|
-
for (const [key, protoField] of Object.entries(doc.fields)) {
|
|
292
|
-
// Get the original value from jsonData to check if protobuf lost it
|
|
293
|
-
const originalValue = originalDoc?.fields?.[key];
|
|
294
|
-
// Handle protobuf field format
|
|
295
|
-
if (protoField && typeof protoField === 'object' && 'value' in protoField) {
|
|
296
|
-
const fieldValue = protoField.value;
|
|
297
|
-
const fieldType = protoField.type;
|
|
298
|
-
// Check if protobuf parsing lost the value (empty string when original had value)
|
|
299
|
-
if ((fieldValue === '' || fieldValue === undefined) && originalValue !== undefined && originalValue !== '') {
|
|
300
|
-
// Use original value instead
|
|
301
|
-
protoFields[key] = originalValue;
|
|
302
|
-
}
|
|
303
|
-
else {
|
|
304
|
-
try {
|
|
305
|
-
// Try to parse as JSON if it's a stringified value
|
|
306
|
-
const parsedValue = JSON.parse(fieldValue);
|
|
307
|
-
protoFields[key] = {
|
|
308
|
-
value: parsedValue,
|
|
309
|
-
dnt: protoField.dnt || false,
|
|
310
|
-
type: fieldType || this.inferSanityType(parsedValue)
|
|
311
|
-
};
|
|
312
|
-
}
|
|
313
|
-
catch {
|
|
314
|
-
// If parsing fails, use the string value as-is
|
|
315
|
-
protoFields[key] = {
|
|
316
|
-
value: fieldValue,
|
|
317
|
-
dnt: protoField.dnt || false,
|
|
318
|
-
type: fieldType || this.inferSanityType(fieldValue)
|
|
319
|
-
};
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
else {
|
|
324
|
-
// Plain value - but protobuf parsing might have lost it
|
|
325
|
-
// Fall back to original JSON data if the value is empty/undefined
|
|
326
|
-
if (originalValue !== undefined && (!protoField || protoField === '')) {
|
|
327
|
-
protoFields[key] = originalValue;
|
|
328
|
-
}
|
|
329
|
-
else {
|
|
330
|
-
protoFields[key] = protoField;
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
// Also check for fields in original data that might have been lost in protobuf conversion
|
|
336
|
-
if (originalDoc?.fields && typeof originalDoc.fields === 'object') {
|
|
337
|
-
for (const [key, originalValue] of Object.entries(originalDoc.fields)) {
|
|
338
|
-
if (!(key in protoFields)) {
|
|
339
|
-
protoFields[key] = originalValue;
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
// Normalize the fields to ensure consistent format
|
|
344
|
-
const fields = this.normalizeTranslatedFields(protoFields);
|
|
345
|
-
return {
|
|
346
|
-
body: doc.body,
|
|
347
|
-
title: doc.title,
|
|
348
|
-
slug: doc.slug,
|
|
349
|
-
fields,
|
|
350
|
-
locale: doc.locale
|
|
351
|
-
};
|
|
352
|
-
});
|
|
353
|
-
return {
|
|
354
|
-
success: protoResponse.success,
|
|
355
|
-
translatedDocuments,
|
|
356
|
-
sourceLocale: protoResponse.sourceLocale,
|
|
357
|
-
error: protoResponse.error,
|
|
358
|
-
requestId: protoResponse.requestId
|
|
359
|
-
};
|
|
360
|
-
}
|
|
361
|
-
/**
|
|
362
|
-
* Prepare a translation request for a single document
|
|
363
|
-
* Requirements: 1.2, 1.3, 3.3, 2.5, 2.7
|
|
364
|
-
*
|
|
365
|
-
* @param content - Document content to translate
|
|
366
|
-
* @param documentType - Type of the document
|
|
367
|
-
* @param sourceLanguage - Source language code (optional)
|
|
368
|
-
* @param targetLanguage - Single target language code (optional, for backward compatibility)
|
|
369
|
-
* @param targetLocales - Array of target locale codes (optional, for multi-locale support)
|
|
370
|
-
*/
|
|
371
|
-
prepareTranslationRequest(content, documentType = 'document', sourceLanguage, targetLanguage, targetLocales) {
|
|
372
|
-
if (!content || !content.documentId || !content.htmlContent) {
|
|
373
|
-
throw new Error('Invalid document content provided');
|
|
374
|
-
}
|
|
375
|
-
// Convert flat fields to TranslatableField objects and ensure type is ALWAYS set
|
|
376
|
-
const translatableFields = {};
|
|
377
|
-
if (content.fields) {
|
|
378
|
-
for (const [key, value] of Object.entries(content.fields)) {
|
|
379
|
-
// If the field is already in the new format, ensure type is set
|
|
380
|
-
if (value && typeof value === 'object' && 'value' in value) {
|
|
381
|
-
const typedField = value;
|
|
382
|
-
// Type should already be set from contentExtractor, but ensure it's never undefined
|
|
383
|
-
if (!typedField.type) {
|
|
384
|
-
console.warn(`Field '${key}' missing type, inferring from value`);
|
|
385
|
-
}
|
|
386
|
-
translatableFields[key] = {
|
|
387
|
-
...typedField,
|
|
388
|
-
type: typedField.type || this.inferSanityType(typedField.value)
|
|
389
|
-
};
|
|
390
|
-
}
|
|
391
|
-
else {
|
|
392
|
-
// Convert flat field to TranslatableField object (should rarely happen)
|
|
393
|
-
console.warn(`Field '${key}' not in TranslatableField format, converting`);
|
|
394
|
-
translatableFields[key] = {
|
|
395
|
-
value,
|
|
396
|
-
dnt: false,
|
|
397
|
-
type: this.inferSanityType(value)
|
|
398
|
-
};
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
const payload = {
|
|
403
|
-
content: {
|
|
404
|
-
body: content.htmlContent,
|
|
405
|
-
title: content.title || `Document ${content.documentId}`,
|
|
406
|
-
slug: content.slug || '',
|
|
407
|
-
fields: translatableFields
|
|
408
|
-
},
|
|
409
|
-
format: 'html',
|
|
410
|
-
metadata: {
|
|
411
|
-
documentId: content.documentId,
|
|
412
|
-
documentType,
|
|
413
|
-
title: content.title || `Document ${content.documentId}`,
|
|
414
|
-
...(sourceLanguage && { sourceLanguage }),
|
|
415
|
-
// Support both single targetLanguage (backward compatibility) and targetLocales array
|
|
416
|
-
...(targetLanguage && { targetLanguage }),
|
|
417
|
-
...(targetLocales && targetLocales.length > 0 && { targetLocales })
|
|
418
|
-
}
|
|
419
|
-
};
|
|
420
|
-
return {
|
|
421
|
-
documentId: content.documentId,
|
|
422
|
-
endpoint: this.placeholderEndpoint,
|
|
423
|
-
payload
|
|
424
|
-
};
|
|
425
|
-
}
|
|
426
|
-
/**
|
|
427
|
-
* Translate a single document
|
|
428
|
-
* Requirements: 1.2, 1.3, 3.3, 2.5, 2.7
|
|
429
|
-
*
|
|
430
|
-
* @param content - Document content to translate
|
|
431
|
-
* @param documentType - Type of the document
|
|
432
|
-
* @param sourceLanguage - Source language code (optional)
|
|
433
|
-
* @param targetLanguage - Single target language code (optional, for backward compatibility)
|
|
434
|
-
* @param targetLocales - Array of target locale codes (optional, for multi-locale support)
|
|
435
|
-
*/
|
|
436
|
-
async translateDocument(content, documentType = 'document', sourceLanguage, targetLanguage, targetLocales) {
|
|
437
|
-
const request = this.prepareTranslationRequest(content, documentType, sourceLanguage, targetLanguage, targetLocales);
|
|
438
|
-
return this.sendTranslationRequest(request);
|
|
439
|
-
}
|
|
440
|
-
/**
|
|
441
|
-
* Send translation request to the configured endpoint
|
|
442
|
-
*
|
|
443
|
-
* Uses the @easyling/sanity Protocol Buffer library to format messages as JSON
|
|
444
|
-
* (not binary protobuf) for better compatibility with various backends.
|
|
445
|
-
* Handles the new array-based response format with backward compatibility.
|
|
446
|
-
* The service now expects translatedDocuments as an array, but will convert
|
|
447
|
-
* legacy formats (translatedContent or translations object) to the new format.
|
|
448
|
-
*
|
|
449
|
-
* Supports dual mode operation:
|
|
450
|
-
* - Authenticated mode: Uses Bearer token authentication when configured
|
|
451
|
-
* - Legacy mode: Works without authentication for backward compatibility
|
|
452
|
-
*/
|
|
453
|
-
async sendTranslationRequest(request) {
|
|
454
|
-
try {
|
|
455
|
-
this.logTranslationRequest(request);
|
|
456
|
-
// Build headers with configured content types
|
|
457
|
-
// Requirements: 2.2, 2.3, 3.2, 3.3
|
|
458
|
-
const headers = {
|
|
459
|
-
'Content-Type': this.requestContentType,
|
|
460
|
-
'Accept': this.responseAcceptHeader
|
|
461
|
-
};
|
|
462
|
-
// Add Authorization header if access token is available
|
|
463
|
-
if (this.accessToken) {
|
|
464
|
-
headers['Authorization'] = `Bearer ${this.accessToken}`;
|
|
465
|
-
}
|
|
466
|
-
// Serialize payload based on configured content type
|
|
467
|
-
// Requirements: 2.2, 2.3
|
|
468
|
-
let body;
|
|
469
|
-
if (this.requestContentType === 'application/x-protobuf') {
|
|
470
|
-
// Use binary protobuf serialization
|
|
471
|
-
body = this.convertPayloadToProtobuf(request.payload);
|
|
472
|
-
}
|
|
473
|
-
else {
|
|
474
|
-
// Use JSON serialization (protobuf JSON format)
|
|
475
|
-
const protobufJSON = this.convertPayloadToProtobufJSON(request.payload);
|
|
476
|
-
body = JSON.stringify(protobufJSON);
|
|
477
|
-
}
|
|
478
|
-
const response = await fetch(request.endpoint, {
|
|
479
|
-
method: 'POST',
|
|
480
|
-
headers,
|
|
481
|
-
body: body // TypeScript fetch types are strict, but Uint8Array is valid
|
|
482
|
-
});
|
|
483
|
-
if (!response.ok) {
|
|
484
|
-
// Handle 401 Unauthorized
|
|
485
|
-
if (response.status === 401) {
|
|
486
|
-
return {
|
|
487
|
-
success: false,
|
|
488
|
-
error: 'Authentication failed. Please check your access token in the Easyling Configuration.'
|
|
489
|
-
};
|
|
490
|
-
}
|
|
491
|
-
throw new Error(`HTTP error! status: ${response.status}`);
|
|
492
|
-
}
|
|
493
|
-
// Parse response based on configured Accept header
|
|
494
|
-
// Requirements: 3.2, 3.3, 3.5
|
|
495
|
-
if (this.responseAcceptHeader === 'application/x-protobuf') {
|
|
496
|
-
// Parse binary protobuf response
|
|
497
|
-
const arrayBuffer = await response.arrayBuffer();
|
|
498
|
-
const binaryData = new Uint8Array(arrayBuffer);
|
|
499
|
-
return this.convertProtobufBinaryToResponse(binaryData);
|
|
500
|
-
}
|
|
501
|
-
// Parse JSON response
|
|
502
|
-
const data = await response.json();
|
|
503
|
-
// Try to parse as protobuf JSON format first
|
|
504
|
-
try {
|
|
505
|
-
// If the response has the expected protobuf structure, parse it
|
|
506
|
-
if (data.success !== undefined && (data.translatedDocuments || data.error)) {
|
|
507
|
-
return this.convertProtobufJSONToResponse(data);
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
catch (protoError) {
|
|
511
|
-
console.warn('Failed to parse response as protobuf format, falling back to legacy handling:', protoError);
|
|
512
|
-
}
|
|
513
|
-
// New format: translatedDocuments array (without success field - for backward compatibility)
|
|
514
|
-
if (data.translatedDocuments && Array.isArray(data.translatedDocuments)) {
|
|
515
|
-
// Normalize fields in each translated document to ensure consistency
|
|
516
|
-
const normalizedDocuments = data.translatedDocuments.map((doc) => ({
|
|
517
|
-
...doc,
|
|
518
|
-
fields: this.normalizeTranslatedFields(doc.fields || {})
|
|
519
|
-
}));
|
|
520
|
-
return {
|
|
521
|
-
success: true,
|
|
522
|
-
translatedDocuments: normalizedDocuments,
|
|
523
|
-
sourceLocale: data.sourceLocale,
|
|
524
|
-
requestId: data.requestId
|
|
525
|
-
};
|
|
526
|
-
}
|
|
527
|
-
// Backward compatibility: translations object (convert to array)
|
|
528
|
-
if (data.translations) {
|
|
529
|
-
const translatedDocuments = [];
|
|
530
|
-
for (const [locale, translation] of Object.entries(data.translations)) {
|
|
531
|
-
if (translation && typeof translation === 'object' && 'content' in translation) {
|
|
532
|
-
const content = translation.content;
|
|
533
|
-
// Normalize fields to ensure consistency
|
|
534
|
-
translatedDocuments.push({
|
|
535
|
-
...content,
|
|
536
|
-
fields: this.normalizeTranslatedFields(content.fields || {}),
|
|
537
|
-
locale
|
|
538
|
-
});
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
return {
|
|
542
|
-
success: true,
|
|
543
|
-
translatedDocuments,
|
|
544
|
-
sourceLocale: data.sourceLocale,
|
|
545
|
-
requestId: data.requestId,
|
|
546
|
-
// Keep deprecated field for backward compatibility
|
|
547
|
-
translations: data.translations
|
|
548
|
-
};
|
|
549
|
-
}
|
|
550
|
-
// Backward compatibility: single translatedContent object (convert to array)
|
|
551
|
-
if (data.translatedContent) {
|
|
552
|
-
const targetLocale = request.payload.metadata.targetLanguage ||
|
|
553
|
-
request.payload.metadata.targetLocales?.[0];
|
|
554
|
-
// Normalize fields to ensure consistency
|
|
555
|
-
const normalizedContent = {
|
|
556
|
-
...data.translatedContent,
|
|
557
|
-
fields: this.normalizeTranslatedFields(data.translatedContent.fields || {}),
|
|
558
|
-
locale: targetLocale
|
|
559
|
-
};
|
|
560
|
-
return {
|
|
561
|
-
success: true,
|
|
562
|
-
translatedDocuments: [normalizedContent],
|
|
563
|
-
sourceLocale: request.payload.metadata.sourceLanguage,
|
|
564
|
-
requestId: data.requestId,
|
|
565
|
-
// Keep deprecated field for backward compatibility
|
|
566
|
-
translatedContent: data.translatedContent
|
|
567
|
-
};
|
|
568
|
-
}
|
|
569
|
-
// Fallback: treat data.content as translatedContent
|
|
570
|
-
if (data.content) {
|
|
571
|
-
const targetLocale = request.payload.metadata.targetLanguage ||
|
|
572
|
-
request.payload.metadata.targetLocales?.[0];
|
|
573
|
-
// Normalize fields to ensure consistency
|
|
574
|
-
const normalizedContent = {
|
|
575
|
-
...data.content,
|
|
576
|
-
fields: this.normalizeTranslatedFields(data.content.fields || {}),
|
|
577
|
-
locale: targetLocale
|
|
578
|
-
};
|
|
579
|
-
return {
|
|
580
|
-
success: true,
|
|
581
|
-
translatedDocuments: [normalizedContent],
|
|
582
|
-
sourceLocale: request.payload.metadata.sourceLanguage,
|
|
583
|
-
requestId: data.requestId,
|
|
584
|
-
// Keep deprecated field for backward compatibility
|
|
585
|
-
translatedContent: data.content
|
|
586
|
-
};
|
|
587
|
-
}
|
|
588
|
-
throw new Error('Invalid response format: missing translatedDocuments, translations, or translatedContent');
|
|
589
|
-
}
|
|
590
|
-
catch (error) {
|
|
591
|
-
console.error(`Translation request failed for document ${request.documentId}:`, error);
|
|
592
|
-
return {
|
|
593
|
-
success: false,
|
|
594
|
-
error: error instanceof Error ? error.message : 'Unknown error occurred'
|
|
595
|
-
};
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
/**
|
|
599
|
-
* Log translation request to console for verification
|
|
600
|
-
* Requirements: 1.3, 2.4
|
|
601
|
-
*/
|
|
602
|
-
logTranslationRequest(request) {
|
|
603
|
-
console.log('Translation Request:', {
|
|
604
|
-
timestamp: new Date().toISOString(),
|
|
605
|
-
documentId: request.documentId,
|
|
606
|
-
endpoint: request.endpoint,
|
|
607
|
-
payload: request.payload
|
|
608
|
-
});
|
|
609
|
-
}
|
|
610
|
-
/**
|
|
611
|
-
* Process bulk translation for multiple documents
|
|
612
|
-
* Requirements: 2.1, 2.2, 2.3, 2.4, 2.5, 2.7
|
|
613
|
-
*
|
|
614
|
-
* @param contents - Array of document contents to translate
|
|
615
|
-
* @param documentType - Type of the documents
|
|
616
|
-
* @param sourceLanguage - Source language code (optional)
|
|
617
|
-
* @param targetLanguage - Single target language code (optional, for backward compatibility)
|
|
618
|
-
* @param targetLocales - Array of target locale codes (optional, for multi-locale support)
|
|
619
|
-
*/
|
|
620
|
-
async processBulkTranslation(contents, documentType = 'document', sourceLanguage, targetLanguage, targetLocales) {
|
|
621
|
-
const summary = {
|
|
622
|
-
totalDocuments: contents.length,
|
|
623
|
-
processedDocuments: 0,
|
|
624
|
-
failedDocuments: 0,
|
|
625
|
-
requests: [],
|
|
626
|
-
responses: []
|
|
627
|
-
};
|
|
628
|
-
const localeCount = targetLocales?.length || 1;
|
|
629
|
-
console.log(`Starting bulk translation for ${contents.length} documents to ${localeCount} locale(s)`);
|
|
630
|
-
for (const content of contents) {
|
|
631
|
-
try {
|
|
632
|
-
// Prepare translation request for each document
|
|
633
|
-
const request = this.prepareTranslationRequest(content, documentType, sourceLanguage, targetLanguage, targetLocales);
|
|
634
|
-
// Send the translation request
|
|
635
|
-
const response = await this.sendTranslationRequest(request);
|
|
636
|
-
// Add to summary
|
|
637
|
-
summary.requests.push(request);
|
|
638
|
-
summary.responses.push(response);
|
|
639
|
-
if (response.success) {
|
|
640
|
-
summary.processedDocuments++;
|
|
641
|
-
}
|
|
642
|
-
else {
|
|
643
|
-
summary.failedDocuments++;
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
catch (error) {
|
|
647
|
-
console.error(`Failed to process document ${content.documentId}:`, error);
|
|
648
|
-
summary.failedDocuments++;
|
|
649
|
-
summary.responses.push({
|
|
650
|
-
success: false,
|
|
651
|
-
error: error instanceof Error ? error.message : 'Unknown error occurred'
|
|
652
|
-
});
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
// Log bulk operation summary
|
|
656
|
-
this.logBulkTranslationSummary(summary);
|
|
657
|
-
return summary;
|
|
658
|
-
}
|
|
659
|
-
/**
|
|
660
|
-
* Log bulk translation summary
|
|
661
|
-
* Requirements: 2.5
|
|
662
|
-
*/
|
|
663
|
-
logBulkTranslationSummary(summary) {
|
|
664
|
-
console.log('Bulk Translation Summary:', {
|
|
665
|
-
timestamp: new Date().toISOString(),
|
|
666
|
-
totalDocuments: summary.totalDocuments,
|
|
667
|
-
processedDocuments: summary.processedDocuments,
|
|
668
|
-
failedDocuments: summary.failedDocuments,
|
|
669
|
-
successRate: summary.totalDocuments > 0
|
|
670
|
-
? ((summary.processedDocuments / summary.totalDocuments) * 100).toFixed(2) + '%'
|
|
671
|
-
: '0%'
|
|
672
|
-
});
|
|
673
|
-
}
|
|
674
|
-
/**
|
|
675
|
-
* Update the placeholder endpoint
|
|
676
|
-
*/
|
|
677
|
-
setEndpoint(endpoint) {
|
|
678
|
-
this.placeholderEndpoint = endpoint;
|
|
679
|
-
}
|
|
680
|
-
/**
|
|
681
|
-
* Get the current endpoint
|
|
682
|
-
*/
|
|
683
|
-
getEndpoint() {
|
|
684
|
-
return this.placeholderEndpoint;
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
//# sourceMappingURL=translationService.js.map
|