@translationstudio/translationstudio-strapi-extension 1.1.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/Types.d.ts +8 -9
- package/dist/_chunks/{App-rdXR_woe.js → App-C5dxwMbx.js} +145 -80
- package/dist/_chunks/{App-jiozoQyG.mjs → App-DxAbaDu8.mjs} +147 -82
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/server/index.js +542 -388
- package/dist/server/index.mjs +523 -387
- package/dist/server/src/controllers/controller.d.ts +2 -1
- package/dist/server/src/controllers/index.d.ts +2 -1
- package/dist/server/src/index.d.ts +10 -6
- package/dist/server/src/services/functions/exportData/getContentType.d.ts +30 -2
- package/dist/server/src/services/functions/exportData/getEntry.d.ts +3 -1
- package/dist/server/src/services/functions/exportData/processComponent.d.ts +2 -2
- package/dist/server/src/services/functions/exportData/processEntryFields.d.ts +7 -1
- package/dist/server/src/services/functions/exportData/transformResponse.d.ts +7 -1
- package/dist/server/src/services/functions/importData/prepareImportData.d.ts +3 -2
- package/dist/server/src/services/functions/importData/updateEntry.d.ts +3 -2
- package/dist/server/src/services/index.d.ts +8 -5
- package/dist/server/src/services/service.d.ts +8 -5
- package/package.json +18 -6
- package/dist/server/src/services/functions/importData/organizeFields.d.ts +0 -2
- package/dist/server/src/services/functions/importData/processDynamicZones.d.ts +0 -2
- package/dist/server/src/services/functions/importData/processRegularFields.d.ts +0 -2
package/dist/server/index.js
CHANGED
|
@@ -1,4 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
const crypto = require("crypto");
|
|
3
|
+
function _interopNamespace(e) {
|
|
4
|
+
if (e && e.__esModule) return e;
|
|
5
|
+
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
6
|
+
if (e) {
|
|
7
|
+
for (const k in e) {
|
|
8
|
+
if (k !== "default") {
|
|
9
|
+
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
10
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
11
|
+
enumerable: true,
|
|
12
|
+
get: () => e[k]
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
n.default = e;
|
|
18
|
+
return Object.freeze(n);
|
|
19
|
+
}
|
|
20
|
+
const crypto__namespace = /* @__PURE__ */ _interopNamespace(crypto);
|
|
2
21
|
const bootstrap = ({ strapi: strapi2 }) => {
|
|
3
22
|
};
|
|
4
23
|
const destroy = ({ strapi: strapi2 }) => {
|
|
@@ -76,50 +95,76 @@ const controller = ({ strapi: strapi2 }) => ({
|
|
|
76
95
|
ctx.status = 400;
|
|
77
96
|
return;
|
|
78
97
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
98
|
+
try {
|
|
99
|
+
const payload = typeof ctx.request.body === "string" ? JSON.parse(ctx.request.body) : ctx.request.body;
|
|
100
|
+
const result = await strapi2.plugin(APP_NAME$1).service("service").exportData(payload);
|
|
101
|
+
ctx.status = 200;
|
|
102
|
+
ctx.body = [{ fields: result }];
|
|
103
|
+
} catch (ex) {
|
|
104
|
+
ctx.status = 500;
|
|
105
|
+
ctx.body = { error: ex.message ?? "Generic error" };
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
async setDevelopmentUrl(ctx) {
|
|
109
|
+
const url = ctx.request.body.url;
|
|
110
|
+
const result = await strapi2.plugin(APP_NAME$1).service("service").setDevelopmentUrl(url);
|
|
111
|
+
if (result) {
|
|
112
|
+
ctx.status = 200;
|
|
113
|
+
ctx.body = { success: true };
|
|
114
|
+
} else {
|
|
115
|
+
ctx.status = 500;
|
|
116
|
+
ctx.body = { success: false };
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
async getDevelopmentUrl(ctx) {
|
|
120
|
+
const url = await strapi2.plugin(APP_NAME$1).service("service").getDevelopmentUrl();
|
|
121
|
+
if (url) {
|
|
122
|
+
ctx.status = 200;
|
|
123
|
+
ctx.body = { url };
|
|
124
|
+
} else {
|
|
125
|
+
ctx.status = 404;
|
|
126
|
+
ctx.body = { url: "" };
|
|
127
|
+
}
|
|
83
128
|
},
|
|
84
129
|
async importData(ctx) {
|
|
85
130
|
if (!await this.validateToken(ctx)) {
|
|
86
131
|
ctx.status = 400;
|
|
87
132
|
return;
|
|
88
133
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
134
|
+
try {
|
|
135
|
+
const payload = typeof ctx.request.body === "object" ? ctx.request.body : JSON.parse(ctx.request.body);
|
|
136
|
+
strapi2.log.info("Importing");
|
|
137
|
+
const result = await strapi2.plugin(APP_NAME$1).service("service").importData(payload);
|
|
138
|
+
ctx.body = { success: result };
|
|
139
|
+
ctx.status = 200;
|
|
140
|
+
return;
|
|
141
|
+
} catch (err) {
|
|
142
|
+
strapi2.log.error(err.message ?? err);
|
|
143
|
+
}
|
|
144
|
+
ctx.body = { message: "Could not perform import" };
|
|
145
|
+
ctx.status = 500;
|
|
92
146
|
},
|
|
93
147
|
async ping(ctx) {
|
|
94
|
-
|
|
148
|
+
await strapi2.plugin(APP_NAME$1).service("service").ping();
|
|
95
149
|
ctx.status = 204;
|
|
96
|
-
ctx.body = result;
|
|
97
150
|
},
|
|
98
151
|
async getLanguages(ctx) {
|
|
99
152
|
if (!await this.validateToken(ctx)) {
|
|
100
153
|
ctx.status = 400;
|
|
101
154
|
return;
|
|
102
155
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
156
|
+
try {
|
|
157
|
+
const result = await strapi2.plugin(APP_NAME$1).service("service").getLanguages();
|
|
158
|
+
ctx.status = 200;
|
|
159
|
+
ctx.body = result;
|
|
160
|
+
} catch (err) {
|
|
161
|
+
ctx.status = 400;
|
|
162
|
+
ctx.body = {};
|
|
163
|
+
}
|
|
106
164
|
},
|
|
107
165
|
async getEmail(ctx) {
|
|
108
166
|
const result = await strapi2.plugin(APP_NAME$1).service("service").getEmail(ctx);
|
|
109
167
|
ctx.body = result;
|
|
110
|
-
},
|
|
111
|
-
async getEntryData(ctx) {
|
|
112
|
-
const { uid, locale } = ctx.request.body;
|
|
113
|
-
if (!uid) {
|
|
114
|
-
return ctx.badRequest("Missing uid parameter");
|
|
115
|
-
}
|
|
116
|
-
try {
|
|
117
|
-
const [contentTypeID, entryID] = uid.split("#");
|
|
118
|
-
const entry = await strapi2.plugin(APP_NAME$1).service("service").getEntryData(contentTypeID, entryID, locale);
|
|
119
|
-
return entry;
|
|
120
|
-
} catch (error) {
|
|
121
|
-
return ctx.badRequest("Failed to get entry data", { error: error.message });
|
|
122
|
-
}
|
|
123
168
|
}
|
|
124
169
|
});
|
|
125
170
|
const controllers = {
|
|
@@ -144,6 +189,22 @@ const routes = [
|
|
|
144
189
|
policies: []
|
|
145
190
|
}
|
|
146
191
|
},
|
|
192
|
+
{
|
|
193
|
+
method: "GET",
|
|
194
|
+
path: "/devurl",
|
|
195
|
+
handler: "controller.getDevelopmentUrl",
|
|
196
|
+
config: {
|
|
197
|
+
policies: []
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
method: "POST",
|
|
202
|
+
path: "/devurl",
|
|
203
|
+
handler: "controller.setDevelopmentUrl",
|
|
204
|
+
config: {
|
|
205
|
+
policies: []
|
|
206
|
+
}
|
|
207
|
+
},
|
|
147
208
|
{
|
|
148
209
|
method: "GET",
|
|
149
210
|
path: "/getToken",
|
|
@@ -219,23 +280,35 @@ const routes = [
|
|
|
219
280
|
config: {
|
|
220
281
|
policies: []
|
|
221
282
|
}
|
|
222
|
-
},
|
|
223
|
-
{
|
|
224
|
-
method: "POST",
|
|
225
|
-
path: "/entrydata",
|
|
226
|
-
handler: "controller.getEntryData",
|
|
227
|
-
config: {
|
|
228
|
-
policies: []
|
|
229
|
-
}
|
|
230
283
|
}
|
|
231
284
|
];
|
|
232
|
-
|
|
233
|
-
const
|
|
285
|
+
function getComponentSchemata(schema) {
|
|
286
|
+
const res = {};
|
|
287
|
+
for (let fieldName in schema.attributes) {
|
|
288
|
+
const field = schema.attributes[fieldName];
|
|
289
|
+
if (!field.components || !Array.isArray(field.components) || field.components.length === 0)
|
|
290
|
+
continue;
|
|
291
|
+
for (let type of field.components) {
|
|
292
|
+
const schema2 = strapi.components[type];
|
|
293
|
+
if (schema2 && schema2.attributes)
|
|
294
|
+
res[type] = schema2;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return res;
|
|
298
|
+
}
|
|
299
|
+
function getContentType(contentTypeID) {
|
|
300
|
+
const contentType = strapi.contentType(contentTypeID);
|
|
234
301
|
if (!contentType?.attributes) {
|
|
235
|
-
|
|
302
|
+
strapi.log.error(`Content type or schema not found: ${contentTypeID}`);
|
|
303
|
+
return null;
|
|
236
304
|
}
|
|
237
|
-
|
|
238
|
-
|
|
305
|
+
const res = {
|
|
306
|
+
entry: contentType,
|
|
307
|
+
components: getComponentSchemata(contentType)
|
|
308
|
+
};
|
|
309
|
+
strapi.log.info("SChema loaded for " + contentTypeID + ". Component schemata loaded: " + Object.keys(res.components).length);
|
|
310
|
+
return res;
|
|
311
|
+
}
|
|
239
312
|
const parsePayload = (payload) => {
|
|
240
313
|
const [contentTypeID, entryID] = payload.element.includes("#") ? payload.element.split("#") : [payload.element, void 0];
|
|
241
314
|
const locale = payload.source.includes("-") ? payload.source.split("-")[0] : payload.source;
|
|
@@ -245,7 +318,7 @@ const getComponentSchema = async (componentName) => {
|
|
|
245
318
|
try {
|
|
246
319
|
return await strapi.components[componentName];
|
|
247
320
|
} catch (error) {
|
|
248
|
-
|
|
321
|
+
strapi.log.error(`Failed to get component schema for ${componentName}:`, error);
|
|
249
322
|
return null;
|
|
250
323
|
}
|
|
251
324
|
};
|
|
@@ -268,27 +341,32 @@ const buildPopulateConfig = async (schema) => {
|
|
|
268
341
|
}
|
|
269
342
|
return populate;
|
|
270
343
|
};
|
|
271
|
-
const getEntry = async (contentTypeID, entryID, locale) => {
|
|
344
|
+
const getEntry = async (contentTypeID, entryID, locale, logError = true) => {
|
|
272
345
|
try {
|
|
273
346
|
const contentType = await strapi.contentTypes[contentTypeID];
|
|
274
347
|
const populateConfig = await buildPopulateConfig(contentType);
|
|
275
348
|
const query = {
|
|
276
349
|
locale,
|
|
350
|
+
documentId: entryID,
|
|
277
351
|
populate: populateConfig
|
|
278
352
|
};
|
|
279
|
-
if (entryID) {
|
|
280
|
-
Object.assign(query, { documentId: entryID });
|
|
281
|
-
}
|
|
282
353
|
const entry = await strapi.documents(contentTypeID).findFirst(query);
|
|
283
|
-
|
|
354
|
+
if (entry) {
|
|
355
|
+
strapi.log.info("Obtained " + contentTypeID + "::" + entryID + " in " + locale);
|
|
356
|
+
return entry;
|
|
357
|
+
}
|
|
284
358
|
} catch (error) {
|
|
285
|
-
|
|
286
|
-
return null;
|
|
359
|
+
strapi.log.error(error.message ?? error);
|
|
287
360
|
}
|
|
361
|
+
strapi.log.warn("Could not find entry " + entryID + " in locale " + locale);
|
|
362
|
+
return null;
|
|
363
|
+
};
|
|
364
|
+
const transformResponse = function(data) {
|
|
365
|
+
data.fields = data.fields.map(
|
|
366
|
+
(item) => item.realType === "blocks" && Array.isArray(item.translatableValue[0]) ? { ...item, translatableValue: item.translatableValue[0] } : item
|
|
367
|
+
);
|
|
368
|
+
return data;
|
|
288
369
|
};
|
|
289
|
-
const transformResponse = (data) => data.map(
|
|
290
|
-
(item) => item.realType === "blocks" && Array.isArray(item.translatableValue[0]) ? { ...item, translatableValue: item.translatableValue[0] } : item
|
|
291
|
-
);
|
|
292
370
|
function jsonToHtml(json) {
|
|
293
371
|
if (!json || !Array.isArray(json)) {
|
|
294
372
|
return "";
|
|
@@ -337,43 +415,37 @@ function formatText(child) {
|
|
|
337
415
|
}
|
|
338
416
|
return text;
|
|
339
417
|
}
|
|
340
|
-
const
|
|
418
|
+
const Logger$4 = {
|
|
419
|
+
log: typeof strapi !== "undefined" ? strapi.log : console,
|
|
420
|
+
info: (val) => Logger$4.log.info(val),
|
|
421
|
+
warn: (val) => Logger$4.log.warn(val),
|
|
422
|
+
error: (val) => Logger$4.log.error(val),
|
|
423
|
+
debug: (val) => Logger$4.log.debug(val)
|
|
424
|
+
};
|
|
425
|
+
async function processComponent(fieldName, value, componentSchema, schemata) {
|
|
341
426
|
const contentFields = [];
|
|
342
|
-
|
|
343
|
-
if (!componentSchema)
|
|
344
|
-
|
|
345
|
-
}
|
|
427
|
+
Logger$4.info("Processing dynamic field " + fieldName);
|
|
428
|
+
if (!componentSchema || !componentSchema.attributes)
|
|
429
|
+
return [];
|
|
346
430
|
const schemaAttributes = componentSchema.attributes || {};
|
|
347
431
|
const dataToProcess = value || {};
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
schemaAttributes,
|
|
353
|
-
fieldName,
|
|
354
|
-
componentName,
|
|
355
|
-
schemaName,
|
|
356
|
-
item.id
|
|
357
|
-
);
|
|
358
|
-
contentFields.push(...processedFields);
|
|
359
|
-
}
|
|
360
|
-
} else {
|
|
361
|
-
const processedFields = await processComponentFields$1(
|
|
362
|
-
dataToProcess,
|
|
432
|
+
const candidates = Array.isArray(dataToProcess) ? dataToProcess : [dataToProcess];
|
|
433
|
+
for (const item of candidates) {
|
|
434
|
+
const processedFields = await processComponentFields(
|
|
435
|
+
item,
|
|
363
436
|
schemaAttributes,
|
|
364
437
|
fieldName,
|
|
365
|
-
|
|
366
|
-
schemaName,
|
|
367
|
-
componentId
|
|
438
|
+
schemata
|
|
368
439
|
);
|
|
369
|
-
|
|
440
|
+
if (processedFields.length > 0)
|
|
441
|
+
contentFields.push(...processedFields);
|
|
370
442
|
}
|
|
371
443
|
return contentFields;
|
|
372
|
-
}
|
|
444
|
+
}
|
|
373
445
|
const shouldSkipField$1 = (key, fieldSchema) => {
|
|
374
446
|
return key === "id" || fieldSchema.private;
|
|
375
447
|
};
|
|
376
|
-
const isTranslatableField
|
|
448
|
+
const isTranslatableField = (type) => {
|
|
377
449
|
return ["string", "text", "blocks", "richtext"].includes(type);
|
|
378
450
|
};
|
|
379
451
|
const getTranslatedValue = (type, value) => {
|
|
@@ -382,64 +454,61 @@ const getTranslatedValue = (type, value) => {
|
|
|
382
454
|
}
|
|
383
455
|
return value.toString();
|
|
384
456
|
};
|
|
385
|
-
const buildTranslatable = (key, fieldSchema, value,
|
|
457
|
+
const buildTranslatable = (key, fieldSchema, value, uuid = "") => {
|
|
386
458
|
return {
|
|
387
459
|
field: key,
|
|
388
460
|
type: ["richtext", "blocks"].includes(fieldSchema.type) ? "html" : "text",
|
|
389
461
|
translatableValue: [value],
|
|
390
462
|
realType: fieldSchema.type,
|
|
391
|
-
|
|
392
|
-
namePath: parentPath,
|
|
393
|
-
id: componentId,
|
|
394
|
-
schemaName
|
|
395
|
-
}
|
|
463
|
+
uuid
|
|
396
464
|
};
|
|
397
465
|
};
|
|
398
|
-
const processComponentFields
|
|
466
|
+
const processComponentFields = async (componentData, schema, parentField, schemata) => {
|
|
399
467
|
const contentFields = [];
|
|
400
|
-
const
|
|
468
|
+
const uuid = crypto__namespace.randomUUID();
|
|
401
469
|
for (const [key, fieldSchema] of Object.entries(schema)) {
|
|
402
470
|
if (shouldSkipField$1(key, fieldSchema)) continue;
|
|
403
471
|
const value = componentData?.[key];
|
|
404
|
-
|
|
472
|
+
if (!value)
|
|
473
|
+
continue;
|
|
405
474
|
if (fieldSchema.type === "component") {
|
|
406
|
-
if (!
|
|
475
|
+
if (!value.__component)
|
|
476
|
+
continue;
|
|
477
|
+
const targetSchema = schemata[value.__component];
|
|
478
|
+
if (!targetSchema)
|
|
479
|
+
continue;
|
|
407
480
|
const nestedFields = await processComponent(
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
value?.id
|
|
481
|
+
`${parentField}.${key}`,
|
|
482
|
+
value,
|
|
483
|
+
targetSchema,
|
|
484
|
+
schemata
|
|
413
485
|
);
|
|
414
|
-
|
|
486
|
+
if (nestedFields.length > 0)
|
|
487
|
+
contentFields.push(...nestedFields);
|
|
415
488
|
continue;
|
|
416
489
|
}
|
|
417
|
-
if (!isTranslatableField
|
|
490
|
+
if (!isTranslatableField(fieldSchema.type)) continue;
|
|
418
491
|
if (value === null || value === void 0 || value === "") continue;
|
|
419
492
|
const translatedValue = getTranslatedValue(fieldSchema.type, value);
|
|
420
493
|
const translatable = buildTranslatable(
|
|
421
494
|
key,
|
|
422
495
|
fieldSchema,
|
|
423
496
|
translatedValue,
|
|
424
|
-
|
|
425
|
-
componentId,
|
|
426
|
-
schemaName
|
|
497
|
+
uuid
|
|
427
498
|
);
|
|
499
|
+
componentData.__tsuid = uuid;
|
|
428
500
|
contentFields.push(translatable);
|
|
429
501
|
}
|
|
430
502
|
return contentFields;
|
|
431
503
|
};
|
|
432
|
-
const
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
return localizableTypes.includes(fieldSchema.type);
|
|
439
|
-
}
|
|
440
|
-
return false;
|
|
504
|
+
const Logger$3 = {
|
|
505
|
+
log: typeof strapi !== "undefined" ? strapi.log : console,
|
|
506
|
+
info: (val) => Logger$3.log.info(val),
|
|
507
|
+
warn: (val) => Logger$3.log.warn(val),
|
|
508
|
+
error: (val) => Logger$3.log.error(val),
|
|
509
|
+
debug: (val) => Logger$3.log.debug(val)
|
|
441
510
|
};
|
|
442
|
-
const DEFAULT_FIELDS = /* @__PURE__ */ new Set([
|
|
511
|
+
const DEFAULT_FIELDS$1 = /* @__PURE__ */ new Set([
|
|
443
512
|
"id",
|
|
444
513
|
"documentId",
|
|
445
514
|
"createdAt",
|
|
@@ -451,45 +520,41 @@ const DEFAULT_FIELDS = /* @__PURE__ */ new Set([
|
|
|
451
520
|
"createdBy"
|
|
452
521
|
]);
|
|
453
522
|
const isEmpty = (value) => value === null || value === void 0 || value === "";
|
|
454
|
-
const
|
|
455
|
-
const processDynamicZone = async (key, value,
|
|
523
|
+
const isSimpleTranslatableField = (fieldSchema) => ["string", "text", "blocks", "richtext"].includes(fieldSchema.type) && fieldSchema.pluginOptions?.i18n?.localized === true;
|
|
524
|
+
const processDynamicZone = async (key, value, schemata) => {
|
|
456
525
|
const results = [];
|
|
457
526
|
for (const component of value) {
|
|
458
527
|
const componentName = component?.__component;
|
|
459
528
|
if (!componentName) continue;
|
|
529
|
+
const schema = schemata[componentName];
|
|
530
|
+
if (!schema) continue;
|
|
460
531
|
const fields = await processComponent(
|
|
461
532
|
key,
|
|
462
|
-
componentName,
|
|
463
533
|
component,
|
|
464
|
-
|
|
465
|
-
|
|
534
|
+
schema,
|
|
535
|
+
schemata
|
|
466
536
|
);
|
|
467
|
-
|
|
537
|
+
if (fields.length > 0)
|
|
538
|
+
results.push(...fields);
|
|
468
539
|
}
|
|
469
540
|
return results;
|
|
470
541
|
};
|
|
471
|
-
const processComponentField = async (key, value, fieldSchema) => {
|
|
542
|
+
const processComponentField = async (key, value, fieldSchema, schemata) => {
|
|
472
543
|
const results = [];
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
fieldSchema.component,
|
|
480
|
-
component.id
|
|
481
|
-
);
|
|
482
|
-
results.push(...fields);
|
|
483
|
-
}
|
|
484
|
-
} else {
|
|
544
|
+
const candidates = Array.isArray(value) ? value : [value];
|
|
545
|
+
for (const component of candidates) {
|
|
546
|
+
const componentName = component?.__component;
|
|
547
|
+
if (!componentName) continue;
|
|
548
|
+
const schema = schemata[componentName];
|
|
549
|
+
if (!schema) continue;
|
|
485
550
|
const fields = await processComponent(
|
|
486
551
|
key,
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
value.id
|
|
552
|
+
component,
|
|
553
|
+
schema,
|
|
554
|
+
schemata
|
|
491
555
|
);
|
|
492
|
-
|
|
556
|
+
if (fields.length > 0)
|
|
557
|
+
results.push(...fields);
|
|
493
558
|
}
|
|
494
559
|
return results;
|
|
495
560
|
};
|
|
@@ -502,38 +567,148 @@ const processRegularField = (key, value, fieldSchema) => {
|
|
|
502
567
|
realType: fieldSchema.type
|
|
503
568
|
};
|
|
504
569
|
};
|
|
505
|
-
|
|
570
|
+
function IsLocalisableSchema(schema) {
|
|
571
|
+
return schema.pluginOptions?.i18n?.localized === true;
|
|
572
|
+
}
|
|
573
|
+
function IsLocalisedField(field) {
|
|
574
|
+
return field.pluginOptions?.i18n?.localized === true;
|
|
575
|
+
}
|
|
576
|
+
const processEntryFields = async (entry, schemaData, _locale) => {
|
|
506
577
|
const contentFields = [];
|
|
578
|
+
const staticContent = {};
|
|
579
|
+
const schema = schemaData.entry.attributes;
|
|
507
580
|
for (const [key, value] of Object.entries(entry)) {
|
|
508
|
-
if (shouldSkipField(key, value))
|
|
509
|
-
const fieldSchema = schema[key];
|
|
510
|
-
if (!fieldSchema) continue;
|
|
511
|
-
if (isDynamicZone(fieldSchema, value, schema)) {
|
|
512
|
-
const zoneFields = await processDynamicZone(key, value);
|
|
513
|
-
contentFields.push(...zoneFields);
|
|
581
|
+
if (shouldSkipField(key, value))
|
|
514
582
|
continue;
|
|
515
|
-
|
|
516
|
-
if (
|
|
517
|
-
|
|
518
|
-
contentFields.push(...componentFields);
|
|
583
|
+
const fieldSchema = schema[key];
|
|
584
|
+
if (!fieldSchema || !IsLocalisedField(fieldSchema)) {
|
|
585
|
+
Logger$3.debug("SKipping non-local field " + key);
|
|
519
586
|
continue;
|
|
520
587
|
}
|
|
521
|
-
if (
|
|
588
|
+
if (isSimpleTranslatableField(fieldSchema)) {
|
|
589
|
+
Logger$3.debug("Processing simple field " + key);
|
|
522
590
|
const translatedField = processRegularField(key, value, fieldSchema);
|
|
523
591
|
contentFields.push(translatedField);
|
|
592
|
+
continue;
|
|
593
|
+
}
|
|
594
|
+
const zoneInfo = isDynamicZone(fieldSchema, value);
|
|
595
|
+
if (zoneInfo.isZone) {
|
|
596
|
+
if (zoneInfo.hasContent) {
|
|
597
|
+
Logger$3.debug("Processing dynamic zone field " + key);
|
|
598
|
+
const zoneFields = await processDynamicZone(key, value, schemaData.components);
|
|
599
|
+
contentFields.push(...zoneFields);
|
|
600
|
+
staticContent[key] = value;
|
|
601
|
+
}
|
|
602
|
+
continue;
|
|
603
|
+
}
|
|
604
|
+
const componentInfo = isComponent(fieldSchema);
|
|
605
|
+
if (componentInfo.isZone) {
|
|
606
|
+
const componentFields = await processComponentField(key, value, fieldSchema, schemaData.components);
|
|
607
|
+
contentFields.push(...componentFields);
|
|
608
|
+
staticContent[key] = value;
|
|
524
609
|
}
|
|
525
610
|
}
|
|
526
|
-
|
|
611
|
+
Logger$3.info("Process completed");
|
|
612
|
+
return {
|
|
613
|
+
fields: contentFields,
|
|
614
|
+
keep: staticContent
|
|
615
|
+
};
|
|
527
616
|
};
|
|
528
617
|
const shouldSkipField = (key, value) => {
|
|
529
|
-
return DEFAULT_FIELDS.has(key) || isEmpty(value);
|
|
618
|
+
return DEFAULT_FIELDS$1.has(key) || isEmpty(value);
|
|
530
619
|
};
|
|
531
|
-
const isDynamicZone = (fieldSchema, value
|
|
532
|
-
return
|
|
620
|
+
const isDynamicZone = (fieldSchema, value) => {
|
|
621
|
+
return {
|
|
622
|
+
isZone: fieldSchema.type === "dynamiczone",
|
|
623
|
+
hasContent: Array.isArray(value) && value.length > 0
|
|
624
|
+
};
|
|
533
625
|
};
|
|
534
|
-
const isComponent = (fieldSchema
|
|
535
|
-
return
|
|
626
|
+
const isComponent = (fieldSchema) => {
|
|
627
|
+
return {
|
|
628
|
+
isZone: fieldSchema.type === "dynamiczone",
|
|
629
|
+
hasContent: true
|
|
630
|
+
};
|
|
631
|
+
};
|
|
632
|
+
const Logger$2 = {
|
|
633
|
+
log: typeof strapi !== "undefined" ? strapi.log : console,
|
|
634
|
+
info: (val) => Logger$2.log.info(val),
|
|
635
|
+
warn: (val) => Logger$2.log.warn(val),
|
|
636
|
+
error: (val) => Logger$2.log.error(val),
|
|
637
|
+
debug: (val) => Logger$2.log.debug(val)
|
|
638
|
+
};
|
|
639
|
+
const DEFAULT_FIELDS = [
|
|
640
|
+
"id",
|
|
641
|
+
"documentId",
|
|
642
|
+
"createdAt",
|
|
643
|
+
"updatedAt",
|
|
644
|
+
,
|
|
645
|
+
"createdBy",
|
|
646
|
+
"updatedBy",
|
|
647
|
+
"publishedAt",
|
|
648
|
+
"locale",
|
|
649
|
+
"localizations"
|
|
650
|
+
];
|
|
651
|
+
const getContentFields = function(schema) {
|
|
652
|
+
const nullFields = [];
|
|
653
|
+
for (let field in schema) {
|
|
654
|
+
if (!DEFAULT_FIELDS.includes(field))
|
|
655
|
+
nullFields.push(field);
|
|
656
|
+
}
|
|
657
|
+
return nullFields;
|
|
658
|
+
};
|
|
659
|
+
const getInvalidOrNullFields = function(document, schema) {
|
|
660
|
+
if (!document)
|
|
661
|
+
return getContentFields(schema);
|
|
662
|
+
const nullFields = [];
|
|
663
|
+
let fieldsValid = 0;
|
|
664
|
+
for (let field in document) {
|
|
665
|
+
if (DEFAULT_FIELDS.includes(field))
|
|
666
|
+
continue;
|
|
667
|
+
if (document[field] === null)
|
|
668
|
+
nullFields.push(field);
|
|
669
|
+
else
|
|
670
|
+
fieldsValid++;
|
|
671
|
+
}
|
|
672
|
+
if (nullFields.length > 0 || fieldsValid > 0)
|
|
673
|
+
return nullFields;
|
|
674
|
+
return getContentFields(schema);
|
|
536
675
|
};
|
|
676
|
+
function appendMissingFields(data, sourceEntry, targetSchema, targetEntry) {
|
|
677
|
+
const nullFields = getInvalidOrNullFields(targetEntry, targetSchema.entry.attributes);
|
|
678
|
+
if (nullFields.length === 0)
|
|
679
|
+
return;
|
|
680
|
+
let count = 0;
|
|
681
|
+
Logger$2.info("Adding missing fields to new locale: " + nullFields.join(", "));
|
|
682
|
+
for (let field of nullFields) {
|
|
683
|
+
if (data[field]) {
|
|
684
|
+
Logger$2.info("Field already present: " + field);
|
|
685
|
+
continue;
|
|
686
|
+
}
|
|
687
|
+
if (!sourceEntry[field]) {
|
|
688
|
+
Logger$2.info("No valid source langauge field value for " + field + " - skipping it.");
|
|
689
|
+
continue;
|
|
690
|
+
}
|
|
691
|
+
if (!targetSchema.entry.attributes[field]) {
|
|
692
|
+
Logger$2.warn("Schema does not contain field " + field);
|
|
693
|
+
continue;
|
|
694
|
+
}
|
|
695
|
+
Logger$2.info("Adding missing field and value for " + field);
|
|
696
|
+
data[field] = sourceEntry[field];
|
|
697
|
+
count++;
|
|
698
|
+
}
|
|
699
|
+
if (count > 0)
|
|
700
|
+
Logger$2.info(count + " missing fields added.");
|
|
701
|
+
}
|
|
702
|
+
async function updateEntry(contentTypeID, entryID, targetLocale, data) {
|
|
703
|
+
strapi.log.info("Updating target entry " + contentTypeID + "::" + entryID + " in locale " + targetLocale);
|
|
704
|
+
const newEntry = await strapi.documents(contentTypeID).update({
|
|
705
|
+
documentId: entryID,
|
|
706
|
+
locale: targetLocale,
|
|
707
|
+
data
|
|
708
|
+
});
|
|
709
|
+
if (!newEntry)
|
|
710
|
+
throw new Error("Cannot update target entry " + contentTypeID + "::" + entryID + " in locale " + targetLocale);
|
|
711
|
+
}
|
|
537
712
|
function htmlToJson(html) {
|
|
538
713
|
function parseHTML(html2) {
|
|
539
714
|
const elements2 = [];
|
|
@@ -726,227 +901,171 @@ function htmlToJson(html) {
|
|
|
726
901
|
}
|
|
727
902
|
return blocks;
|
|
728
903
|
}
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
)
|
|
744
|
-
|
|
904
|
+
const Logger$1 = {
|
|
905
|
+
log: typeof strapi !== "undefined" ? strapi.log : console,
|
|
906
|
+
info: (val) => Logger$1.log.info(val),
|
|
907
|
+
warn: (val) => Logger$1.log.warn(val),
|
|
908
|
+
error: (val) => Logger$1.log.error(val),
|
|
909
|
+
debug: (val) => Logger$1.log.debug(val)
|
|
910
|
+
};
|
|
911
|
+
const removeComponentIds = function(elem) {
|
|
912
|
+
const list = Array.isArray(elem) ? elem : [elem];
|
|
913
|
+
for (let obj of list) {
|
|
914
|
+
if (obj.__component && obj.id)
|
|
915
|
+
delete obj.id;
|
|
916
|
+
for (let key in obj) {
|
|
917
|
+
const child = obj[key];
|
|
918
|
+
if (Array.isArray(child) && Array.length > 0)
|
|
919
|
+
removeComponentIds(child);
|
|
920
|
+
else if (typeof child === "object")
|
|
921
|
+
removeComponentIds(child);
|
|
745
922
|
}
|
|
746
923
|
}
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
924
|
+
};
|
|
925
|
+
function replaceDynamicZones(strapiEntry, replacableFields) {
|
|
926
|
+
const fields = [];
|
|
927
|
+
for (let key in strapiEntry) {
|
|
928
|
+
if (replacableFields[key]) {
|
|
929
|
+
removeComponentIds(replacableFields[key]);
|
|
930
|
+
strapiEntry[key] = replacableFields[key];
|
|
931
|
+
fields.push(key);
|
|
751
932
|
}
|
|
752
933
|
}
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
data: localizedData
|
|
757
|
-
});
|
|
758
|
-
if (originalEntry.publishedAt !== null) {
|
|
759
|
-
await strapi.documents(contentTypeID).publish({
|
|
760
|
-
documentId: entryID,
|
|
761
|
-
locale: sourceLocale
|
|
762
|
-
});
|
|
763
|
-
}
|
|
934
|
+
if (fields.length > 0)
|
|
935
|
+
Logger$1.info(fields.length + " dynamic fields/components replaced for later merge: " + fields.join(", "));
|
|
936
|
+
return fields;
|
|
764
937
|
}
|
|
765
|
-
function
|
|
766
|
-
if (
|
|
767
|
-
return
|
|
938
|
+
const mergeValue = function(field, translatable, targetSchema, map) {
|
|
939
|
+
if (translatable.translatableValue.length === 0)
|
|
940
|
+
return false;
|
|
941
|
+
if (targetSchema.attributes[field] === void 0) {
|
|
942
|
+
Logger$1.info("Field " + field + " does not exist in schema. Skipping it");
|
|
943
|
+
Logger$1.info(targetSchema);
|
|
944
|
+
return false;
|
|
768
945
|
}
|
|
769
|
-
if (
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
for (const fieldData of data[0].fields) {
|
|
773
|
-
if (fieldData.realType === "blocks") {
|
|
774
|
-
if (fieldData.translatableValue?.[0]) {
|
|
775
|
-
processedFields[fieldData.field] = htmlToJson(fieldData.translatableValue[0]);
|
|
776
|
-
}
|
|
777
|
-
} else {
|
|
778
|
-
processedFields[fieldData.field] = fieldData.translatableValue?.[0] || null;
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
return processedFields;
|
|
782
|
-
}
|
|
783
|
-
return data.map((item) => processDataRecursively(item));
|
|
946
|
+
if (translatable.translatableValue[0] === "") {
|
|
947
|
+
Logger$1.info("Skipping empty translated content for field " + field);
|
|
948
|
+
return false;
|
|
784
949
|
}
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
950
|
+
if (translatable.realType === "blocks") {
|
|
951
|
+
Logger$1.info("Merge block field " + field);
|
|
952
|
+
map[field] = htmlToJson(translatable.translatableValue[0] || "");
|
|
953
|
+
return true;
|
|
788
954
|
}
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
const
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
if (!field.componentInfo) {
|
|
827
|
-
console.warn(`Component info missing for field: ${field.field}`);
|
|
828
|
-
return;
|
|
829
|
-
}
|
|
830
|
-
const componentId = field.componentInfo.id;
|
|
831
|
-
if (!componentsById.has(componentId)) {
|
|
832
|
-
const existingComponent = existingComponents.find((c) => c.id === componentId);
|
|
833
|
-
componentsById.set(componentId, existingComponent ? { ...existingComponent } : {});
|
|
834
|
-
}
|
|
835
|
-
const component = componentsById.get(componentId);
|
|
836
|
-
if (field.realType === "blocks") {
|
|
837
|
-
component[field.field] = htmlToJson(field.translatableValue[0] || "");
|
|
838
|
-
} else {
|
|
839
|
-
component[field.field] = field.translatableValue[0];
|
|
840
|
-
}
|
|
841
|
-
});
|
|
842
|
-
return Array.from(componentsById.values()).map((comp) => {
|
|
843
|
-
if (!existingComponents.find((ec) => ec.id === comp.id)) {
|
|
844
|
-
const { id, ...rest } = comp;
|
|
845
|
-
return rest;
|
|
846
|
-
}
|
|
847
|
-
return comp;
|
|
848
|
-
}).filter((comp) => Object.keys(comp).length > 0);
|
|
849
|
-
}
|
|
850
|
-
function processNestedComponents(fields, pathParts, existingEntry, acc) {
|
|
851
|
-
let current = acc;
|
|
852
|
-
let currentExisting = existingEntry;
|
|
853
|
-
pathParts.forEach((part, index2) => {
|
|
854
|
-
if (!current[part]) {
|
|
855
|
-
current[part] = {};
|
|
856
|
-
if (currentExisting?.[part]?.id) {
|
|
857
|
-
current[part].id = currentExisting[part].id;
|
|
858
|
-
}
|
|
859
|
-
}
|
|
860
|
-
if (index2 === pathParts.length - 1) {
|
|
861
|
-
fields.forEach((field) => {
|
|
862
|
-
if (field.realType === "blocks") {
|
|
863
|
-
current[part][field.field] = htmlToJson(field.translatableValue[0] || "");
|
|
864
|
-
} else {
|
|
865
|
-
current[part][field.field] = field.translatableValue[0];
|
|
866
|
-
}
|
|
867
|
-
});
|
|
868
|
-
} else {
|
|
869
|
-
current = current[part];
|
|
870
|
-
currentExisting = currentExisting?.[part];
|
|
871
|
-
}
|
|
872
|
-
});
|
|
873
|
-
}
|
|
874
|
-
function processComponentFields(componentFieldsMap, acc, existingEntry, targetSchema) {
|
|
875
|
-
componentFieldsMap.forEach((fields, namePath) => {
|
|
876
|
-
if (!fields.length) return;
|
|
877
|
-
const pathParts = namePath.split(".");
|
|
878
|
-
const rootPath = pathParts[0];
|
|
879
|
-
const schema = targetSchema.attributes?.[rootPath];
|
|
880
|
-
if (schema?.repeatable) {
|
|
881
|
-
acc[rootPath] = processRepeatableComponents(fields, existingEntry, rootPath);
|
|
882
|
-
} else {
|
|
883
|
-
processNestedComponents(fields, pathParts, existingEntry, acc);
|
|
955
|
+
if (translatable.type === "text") {
|
|
956
|
+
Logger$1.info("Merge text field " + field);
|
|
957
|
+
map[field] = translatable.translatableValue[0];
|
|
958
|
+
return true;
|
|
959
|
+
}
|
|
960
|
+
Logger$1.warn("Did not process " + field);
|
|
961
|
+
return false;
|
|
962
|
+
};
|
|
963
|
+
const mergeSimpleFields = function(translatables, existingEntry, targetSchema, map) {
|
|
964
|
+
let count = 0;
|
|
965
|
+
for (const candidate of translatables) {
|
|
966
|
+
const field = candidate.field;
|
|
967
|
+
if (!candidate.uuid && mergeValue(field, candidate, targetSchema.entry, map))
|
|
968
|
+
count++;
|
|
969
|
+
}
|
|
970
|
+
if (count > 0) {
|
|
971
|
+
Logger$1.info("Updated " + count + " simple text fields");
|
|
972
|
+
return true;
|
|
973
|
+
}
|
|
974
|
+
return false;
|
|
975
|
+
};
|
|
976
|
+
const buildMapOfUuids = function(existingEntry, schemaMap, map) {
|
|
977
|
+
if (typeof existingEntry !== "object")
|
|
978
|
+
return map;
|
|
979
|
+
const componentName = existingEntry["__component"] ?? "";
|
|
980
|
+
const schema = componentName && schemaMap.components[componentName] ? schemaMap.components[componentName] : null;
|
|
981
|
+
if (componentName && !schema)
|
|
982
|
+
Logger$1.warn("Cannot find component schema " + componentName);
|
|
983
|
+
for (const key of Object.keys(existingEntry)) {
|
|
984
|
+
if (key === "__component")
|
|
985
|
+
continue;
|
|
986
|
+
if (schema !== null && key === "__tsuid") {
|
|
987
|
+
map[existingEntry[key]] = {
|
|
988
|
+
entry: existingEntry,
|
|
989
|
+
schema
|
|
990
|
+
};
|
|
991
|
+
continue;
|
|
884
992
|
}
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
return acc;
|
|
993
|
+
const child = existingEntry[key];
|
|
994
|
+
if (child) {
|
|
995
|
+
if (Array.isArray(child)) {
|
|
996
|
+
for (let e of child)
|
|
997
|
+
buildMapOfUuids(e, schemaMap, map);
|
|
998
|
+
} else
|
|
999
|
+
buildMapOfUuids(child, schemaMap, map);
|
|
893
1000
|
}
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
1001
|
+
}
|
|
1002
|
+
if (existingEntry["__tsuid"]) {
|
|
1003
|
+
delete existingEntry["__tsuid"];
|
|
1004
|
+
Logger$1.info("Removed cusom property __tsuid");
|
|
1005
|
+
}
|
|
1006
|
+
return map;
|
|
1007
|
+
};
|
|
1008
|
+
const mergeDynamicZones = function(translatables, schemaMap, existingEntry) {
|
|
1009
|
+
if (translatables.length === 0) {
|
|
1010
|
+
Logger$1.info("Skipping merging of dynamic zones, because none are present.");
|
|
1011
|
+
return;
|
|
1012
|
+
}
|
|
1013
|
+
const map = {};
|
|
1014
|
+
buildMapOfUuids(existingEntry, schemaMap, map);
|
|
1015
|
+
const mapSize = Object.keys(map).length;
|
|
1016
|
+
if (mapSize === 0) {
|
|
1017
|
+
Logger$1.warn("Could not create a uuid map");
|
|
1018
|
+
return false;
|
|
1019
|
+
}
|
|
1020
|
+
Logger$1.info("Built uuid map with " + mapSize + " entry(s)");
|
|
1021
|
+
let count = 0;
|
|
1022
|
+
for (const translatable of translatables) {
|
|
1023
|
+
if (!translatable.uuid)
|
|
1024
|
+
continue;
|
|
1025
|
+
const uuid = translatable.uuid;
|
|
1026
|
+
if (!map[uuid])
|
|
1027
|
+
continue;
|
|
1028
|
+
const entry = map[uuid];
|
|
1029
|
+
const schema = entry.schema;
|
|
1030
|
+
if (!schema) {
|
|
1031
|
+
Logger$1.warn("Cannot find schema by uuid #" + uuid);
|
|
1032
|
+
continue;
|
|
900
1033
|
}
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
}
|
|
904
|
-
function processDynamicZones(dynamicZoneFields, acc, existingEntry) {
|
|
905
|
-
if (dynamicZoneFields.size > 0) {
|
|
906
|
-
const existingDynamicZone = existingEntry?.dynamiczone || [];
|
|
907
|
-
acc.dynamiczone = Array.from(dynamicZoneFields.entries()).sort(([a], [b]) => a - b).map(([_, fields]) => {
|
|
908
|
-
if (!fields[0].componentInfo) {
|
|
909
|
-
console.warn(
|
|
910
|
-
`Component info missing for dynamic zone field: ${fields[0].field}`
|
|
911
|
-
);
|
|
912
|
-
return null;
|
|
913
|
-
}
|
|
914
|
-
const { schemaName } = fields[0].componentInfo;
|
|
915
|
-
const componentData = transformFieldsToData(fields);
|
|
916
|
-
const matchingComponent = existingDynamicZone.find(
|
|
917
|
-
(comp) => comp.__component === schemaName
|
|
918
|
-
);
|
|
919
|
-
return {
|
|
920
|
-
__component: schemaName,
|
|
921
|
-
...componentData,
|
|
922
|
-
...matchingComponent?.id ? { id: matchingComponent.id } : {}
|
|
923
|
-
};
|
|
924
|
-
}).filter(Boolean);
|
|
1034
|
+
if (mergeValue(translatable.field, translatable, schema, entry.entry))
|
|
1035
|
+
count++;
|
|
925
1036
|
}
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
1037
|
+
if (count > 0) {
|
|
1038
|
+
Logger$1.info("Updated " + count + " entries in dynamic zones/content blocks");
|
|
1039
|
+
return true;
|
|
1040
|
+
}
|
|
1041
|
+
return false;
|
|
1042
|
+
};
|
|
1043
|
+
function prepareImportData(translatables, keepData, existingEntry, targetSchema) {
|
|
1044
|
+
const result = {};
|
|
1045
|
+
const simpleUpdated = mergeSimpleFields(translatables, existingEntry, targetSchema, result);
|
|
1046
|
+
let otherUpdated = false;
|
|
1047
|
+
const vsFields = replaceDynamicZones(existingEntry, keepData);
|
|
1048
|
+
if (vsFields.length > 0) {
|
|
1049
|
+
if (mergeDynamicZones(translatables, targetSchema, existingEntry)) {
|
|
1050
|
+
vsFields.forEach((field) => result[field] = existingEntry[field]);
|
|
1051
|
+
otherUpdated = true;
|
|
1052
|
+
} else
|
|
1053
|
+
Logger$1.warn("Could not merge dynamic fields");
|
|
1054
|
+
}
|
|
1055
|
+
if (simpleUpdated || otherUpdated)
|
|
1056
|
+
return result;
|
|
1057
|
+
else
|
|
1058
|
+
return null;
|
|
945
1059
|
}
|
|
946
|
-
const
|
|
947
|
-
const crypto = require("crypto");
|
|
948
|
-
const TRANSLATIONTUDIO_URL = "https://cms-strapi-service-7866fdd79eab.herokuapp.com";
|
|
1060
|
+
const TRANSLATIONTUDIO_URL = "https://strapi.translationstudio.tech";
|
|
949
1061
|
const APP_NAME = "translationstudio";
|
|
1062
|
+
const Logger = {
|
|
1063
|
+
log: typeof strapi !== "undefined" ? strapi.log : console,
|
|
1064
|
+
info: (val) => Logger.log.info(val),
|
|
1065
|
+
warn: (val) => Logger.log.warn(val),
|
|
1066
|
+
error: (val) => Logger.log.error(val),
|
|
1067
|
+
debug: (val) => Logger.log.debug(val)
|
|
1068
|
+
};
|
|
950
1069
|
const service = ({ strapi: strapi2 }) => {
|
|
951
1070
|
const pluginStore = strapi2.store({
|
|
952
1071
|
type: "plugin",
|
|
@@ -958,6 +1077,16 @@ const service = ({ strapi: strapi2 }) => {
|
|
|
958
1077
|
const result = await pluginStore.get({ key: "license" });
|
|
959
1078
|
return { license: result };
|
|
960
1079
|
},
|
|
1080
|
+
async getTranslationstudioUrl() {
|
|
1081
|
+
try {
|
|
1082
|
+
const result = await pluginStore.get({ key: "developurl" });
|
|
1083
|
+
if (typeof result === "string" && result !== "")
|
|
1084
|
+
return result;
|
|
1085
|
+
} catch (err) {
|
|
1086
|
+
strapi2.log.warn(err);
|
|
1087
|
+
}
|
|
1088
|
+
return TRANSLATIONTUDIO_URL;
|
|
1089
|
+
},
|
|
961
1090
|
async setLicense(license) {
|
|
962
1091
|
try {
|
|
963
1092
|
await pluginStore.set({
|
|
@@ -969,6 +1098,26 @@ const service = ({ strapi: strapi2 }) => {
|
|
|
969
1098
|
return { success: false };
|
|
970
1099
|
}
|
|
971
1100
|
},
|
|
1101
|
+
async setDevelopmentUrl(url) {
|
|
1102
|
+
try {
|
|
1103
|
+
await pluginStore.set({
|
|
1104
|
+
key: "developurl",
|
|
1105
|
+
value: url
|
|
1106
|
+
});
|
|
1107
|
+
return true;
|
|
1108
|
+
} catch (error) {
|
|
1109
|
+
return false;
|
|
1110
|
+
}
|
|
1111
|
+
},
|
|
1112
|
+
async getDevelopmentUrl() {
|
|
1113
|
+
try {
|
|
1114
|
+
const result = await pluginStore.get({ key: "developurl" });
|
|
1115
|
+
if (typeof result === "string")
|
|
1116
|
+
return result;
|
|
1117
|
+
} catch (error) {
|
|
1118
|
+
}
|
|
1119
|
+
return "";
|
|
1120
|
+
},
|
|
972
1121
|
// Access Token
|
|
973
1122
|
async getToken() {
|
|
974
1123
|
try {
|
|
@@ -979,24 +1128,17 @@ const service = ({ strapi: strapi2 }) => {
|
|
|
979
1128
|
}
|
|
980
1129
|
},
|
|
981
1130
|
async generateToken() {
|
|
982
|
-
const secretKey =
|
|
983
|
-
const token = jwt.sign(
|
|
984
|
-
{
|
|
985
|
-
app: APP_NAME,
|
|
986
|
-
iat: Math.floor(Date.now() / 1e3)
|
|
987
|
-
},
|
|
988
|
-
secretKey,
|
|
989
|
-
{ expiresIn: "10y" }
|
|
990
|
-
);
|
|
1131
|
+
const secretKey = crypto__namespace.randomBytes(64).toString("hex");
|
|
991
1132
|
await pluginStore.set({
|
|
992
1133
|
key: "token",
|
|
993
|
-
value:
|
|
1134
|
+
value: secretKey
|
|
994
1135
|
});
|
|
995
|
-
return { token };
|
|
1136
|
+
return { token: secretKey };
|
|
996
1137
|
},
|
|
997
1138
|
async getLanguageOptions() {
|
|
998
1139
|
const { license } = await this.getLicense();
|
|
999
|
-
const
|
|
1140
|
+
const url = await this.getTranslationstudioUrl();
|
|
1141
|
+
const response = await fetch(url + "/mappings", {
|
|
1000
1142
|
headers: { Authorization: `${license}` }
|
|
1001
1143
|
});
|
|
1002
1144
|
const responseData = await response.json();
|
|
@@ -1004,9 +1146,15 @@ const service = ({ strapi: strapi2 }) => {
|
|
|
1004
1146
|
},
|
|
1005
1147
|
async exportData(payload) {
|
|
1006
1148
|
const { contentTypeID, entryID, locale } = parsePayload(payload);
|
|
1007
|
-
const contentType =
|
|
1149
|
+
const contentType = getContentType(contentTypeID);
|
|
1150
|
+
if (contentType === null || !IsLocalisableSchema(contentType.entry)) {
|
|
1151
|
+
return {
|
|
1152
|
+
fields: [],
|
|
1153
|
+
keep: {}
|
|
1154
|
+
};
|
|
1155
|
+
}
|
|
1008
1156
|
const entry = await getEntry(contentTypeID, entryID, locale);
|
|
1009
|
-
const contentFields = await processEntryFields(entry, contentType
|
|
1157
|
+
const contentFields = await processEntryFields(entry, contentType);
|
|
1010
1158
|
return transformResponse(contentFields);
|
|
1011
1159
|
},
|
|
1012
1160
|
async importData(payload) {
|
|
@@ -1014,27 +1162,37 @@ const service = ({ strapi: strapi2 }) => {
|
|
|
1014
1162
|
const sourceLocale = payload.source;
|
|
1015
1163
|
const targetLocale = payload.target;
|
|
1016
1164
|
try {
|
|
1017
|
-
const
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1165
|
+
const sourceEntry = await getEntry(contentTypeID, entryID, sourceLocale);
|
|
1166
|
+
if (sourceEntry == null)
|
|
1167
|
+
throw new Error("Cannot find source entry " + contentTypeID + "::" + entryID + " in " + sourceLocale);
|
|
1168
|
+
const targetSchema = getContentType(contentTypeID);
|
|
1169
|
+
if (targetSchema === null || !IsLocalisableSchema(targetSchema.entry))
|
|
1170
|
+
throw new Error("Cannot find schema");
|
|
1171
|
+
const data = prepareImportData(
|
|
1172
|
+
payload.document[0].fields,
|
|
1173
|
+
payload.document[0].keep ?? {},
|
|
1174
|
+
sourceEntry,
|
|
1175
|
+
targetSchema
|
|
1176
|
+
);
|
|
1177
|
+
strapi2.log.info("Loading target language entry");
|
|
1178
|
+
const targetLocaleEntry = await getEntry(contentTypeID, entryID, targetLocale);
|
|
1179
|
+
appendMissingFields(data, sourceEntry, targetSchema, targetLocaleEntry);
|
|
1180
|
+
await updateEntry(
|
|
1181
|
+
contentTypeID,
|
|
1182
|
+
entryID,
|
|
1183
|
+
targetLocale,
|
|
1184
|
+
data
|
|
1185
|
+
);
|
|
1186
|
+
return true;
|
|
1031
1187
|
} catch (error) {
|
|
1032
|
-
|
|
1188
|
+
strapi2.log.error(error);
|
|
1033
1189
|
}
|
|
1190
|
+
return false;
|
|
1034
1191
|
},
|
|
1035
1192
|
async requestTranslation(payload) {
|
|
1036
1193
|
const { license } = await this.getLicense();
|
|
1037
|
-
const
|
|
1194
|
+
const url = await this.getTranslationstudioUrl();
|
|
1195
|
+
const response = await fetch(url + "/translate", {
|
|
1038
1196
|
method: "POST",
|
|
1039
1197
|
headers: {
|
|
1040
1198
|
Authorization: `${license}`,
|
|
@@ -1065,10 +1223,6 @@ const service = ({ strapi: strapi2 }) => {
|
|
|
1065
1223
|
},
|
|
1066
1224
|
async ping() {
|
|
1067
1225
|
return;
|
|
1068
|
-
},
|
|
1069
|
-
async getEntryData(contentTypeID, entryID, locale) {
|
|
1070
|
-
const entry = await getEntry(contentTypeID, entryID, locale);
|
|
1071
|
-
return entry;
|
|
1072
1226
|
}
|
|
1073
1227
|
};
|
|
1074
1228
|
};
|