@translationstudio/translationstudio-strapi-extension 1.1.3 → 2.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/dist/Types.d.ts +8 -9
- package/dist/_chunks/{App-DkdbSZwI.js → App-C5dxwMbx.js} +0 -1
- package/dist/_chunks/{App-Cq1SRR-L.mjs → App-DxAbaDu8.mjs} +0 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/server/index.js +470 -351
- package/dist/server/index.mjs +451 -350
- package/dist/server/src/index.d.ts +6 -5
- 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 +6 -5
- package/dist/server/src/services/service.d.ts +6 -5
- package/package.json +14 -2
- 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.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as crypto from "crypto";
|
|
1
2
|
const bootstrap = ({ strapi: strapi2 }) => {
|
|
2
3
|
};
|
|
3
4
|
const destroy = ({ strapi: strapi2 }) => {
|
|
@@ -75,10 +76,15 @@ const controller = ({ strapi: strapi2 }) => ({
|
|
|
75
76
|
ctx.status = 400;
|
|
76
77
|
return;
|
|
77
78
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
79
|
+
try {
|
|
80
|
+
const payload = typeof ctx.request.body === "string" ? JSON.parse(ctx.request.body) : ctx.request.body;
|
|
81
|
+
const result = await strapi2.plugin(APP_NAME$1).service("service").exportData(payload);
|
|
82
|
+
ctx.status = 200;
|
|
83
|
+
ctx.body = [{ fields: result }];
|
|
84
|
+
} catch (ex) {
|
|
85
|
+
ctx.status = 500;
|
|
86
|
+
ctx.body = { error: ex.message ?? "Generic error" };
|
|
87
|
+
}
|
|
82
88
|
},
|
|
83
89
|
async setDevelopmentUrl(ctx) {
|
|
84
90
|
const url = ctx.request.body.url;
|
|
@@ -106,23 +112,36 @@ const controller = ({ strapi: strapi2 }) => ({
|
|
|
106
112
|
ctx.status = 400;
|
|
107
113
|
return;
|
|
108
114
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
115
|
+
try {
|
|
116
|
+
const payload = typeof ctx.request.body === "object" ? ctx.request.body : JSON.parse(ctx.request.body);
|
|
117
|
+
strapi2.log.info("Importing");
|
|
118
|
+
const result = await strapi2.plugin(APP_NAME$1).service("service").importData(payload);
|
|
119
|
+
ctx.body = { success: result };
|
|
120
|
+
ctx.status = 200;
|
|
121
|
+
return;
|
|
122
|
+
} catch (err) {
|
|
123
|
+
strapi2.log.error(err.message ?? err);
|
|
124
|
+
}
|
|
125
|
+
ctx.body = { message: "Could not perform import" };
|
|
126
|
+
ctx.status = 500;
|
|
112
127
|
},
|
|
113
128
|
async ping(ctx) {
|
|
114
|
-
|
|
129
|
+
await strapi2.plugin(APP_NAME$1).service("service").ping();
|
|
115
130
|
ctx.status = 204;
|
|
116
|
-
ctx.body = result;
|
|
117
131
|
},
|
|
118
132
|
async getLanguages(ctx) {
|
|
119
133
|
if (!await this.validateToken(ctx)) {
|
|
120
134
|
ctx.status = 400;
|
|
121
135
|
return;
|
|
122
136
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
137
|
+
try {
|
|
138
|
+
const result = await strapi2.plugin(APP_NAME$1).service("service").getLanguages();
|
|
139
|
+
ctx.status = 200;
|
|
140
|
+
ctx.body = result;
|
|
141
|
+
} catch (err) {
|
|
142
|
+
ctx.status = 400;
|
|
143
|
+
ctx.body = {};
|
|
144
|
+
}
|
|
126
145
|
},
|
|
127
146
|
async getEmail(ctx) {
|
|
128
147
|
const result = await strapi2.plugin(APP_NAME$1).service("service").getEmail(ctx);
|
|
@@ -256,6 +275,7 @@ const routes = [
|
|
|
256
275
|
policies: []
|
|
257
276
|
}
|
|
258
277
|
},
|
|
278
|
+
/* get entry title */
|
|
259
279
|
{
|
|
260
280
|
method: "POST",
|
|
261
281
|
path: "/entrydata",
|
|
@@ -265,13 +285,33 @@ const routes = [
|
|
|
265
285
|
}
|
|
266
286
|
}
|
|
267
287
|
];
|
|
268
|
-
|
|
269
|
-
const
|
|
288
|
+
function getComponentSchemata(schema) {
|
|
289
|
+
const res = {};
|
|
290
|
+
for (let fieldName in schema.attributes) {
|
|
291
|
+
const field = schema.attributes[fieldName];
|
|
292
|
+
if (!field.components || !Array.isArray(field.components) || field.components.length === 0)
|
|
293
|
+
continue;
|
|
294
|
+
for (let type of field.components) {
|
|
295
|
+
const schema2 = strapi.components[type];
|
|
296
|
+
if (schema2 && schema2.attributes)
|
|
297
|
+
res[type] = schema2;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return res;
|
|
301
|
+
}
|
|
302
|
+
function getContentType(contentTypeID) {
|
|
303
|
+
const contentType = strapi.contentType(contentTypeID);
|
|
270
304
|
if (!contentType?.attributes) {
|
|
271
|
-
|
|
305
|
+
strapi.log.error(`Content type or schema not found: ${contentTypeID}`);
|
|
306
|
+
return null;
|
|
272
307
|
}
|
|
273
|
-
|
|
274
|
-
|
|
308
|
+
const res = {
|
|
309
|
+
entry: contentType,
|
|
310
|
+
components: getComponentSchemata(contentType)
|
|
311
|
+
};
|
|
312
|
+
strapi.log.info("SChema loaded for " + contentTypeID + ". Component schemata loaded: " + Object.keys(res.components).length);
|
|
313
|
+
return res;
|
|
314
|
+
}
|
|
275
315
|
const parsePayload = (payload) => {
|
|
276
316
|
const [contentTypeID, entryID] = payload.element.includes("#") ? payload.element.split("#") : [payload.element, void 0];
|
|
277
317
|
const locale = payload.source.includes("-") ? payload.source.split("-")[0] : payload.source;
|
|
@@ -281,7 +321,7 @@ const getComponentSchema = async (componentName) => {
|
|
|
281
321
|
try {
|
|
282
322
|
return await strapi.components[componentName];
|
|
283
323
|
} catch (error) {
|
|
284
|
-
|
|
324
|
+
strapi.log.error(`Failed to get component schema for ${componentName}:`, error);
|
|
285
325
|
return null;
|
|
286
326
|
}
|
|
287
327
|
};
|
|
@@ -304,27 +344,32 @@ const buildPopulateConfig = async (schema) => {
|
|
|
304
344
|
}
|
|
305
345
|
return populate;
|
|
306
346
|
};
|
|
307
|
-
const getEntry = async (contentTypeID, entryID, locale) => {
|
|
347
|
+
const getEntry = async (contentTypeID, entryID, locale, logError = true) => {
|
|
308
348
|
try {
|
|
309
349
|
const contentType = await strapi.contentTypes[contentTypeID];
|
|
310
350
|
const populateConfig = await buildPopulateConfig(contentType);
|
|
311
351
|
const query = {
|
|
312
352
|
locale,
|
|
353
|
+
documentId: entryID,
|
|
313
354
|
populate: populateConfig
|
|
314
355
|
};
|
|
315
|
-
if (entryID) {
|
|
316
|
-
Object.assign(query, { documentId: entryID });
|
|
317
|
-
}
|
|
318
356
|
const entry = await strapi.documents(contentTypeID).findFirst(query);
|
|
319
|
-
|
|
357
|
+
if (entry) {
|
|
358
|
+
strapi.log.info("Obtained " + contentTypeID + "::" + entryID + " in " + locale);
|
|
359
|
+
return entry;
|
|
360
|
+
}
|
|
320
361
|
} catch (error) {
|
|
321
|
-
|
|
322
|
-
return null;
|
|
362
|
+
strapi.log.error(error.message ?? error);
|
|
323
363
|
}
|
|
364
|
+
strapi.log.warn("Could not find entry " + entryID + " in locale " + locale);
|
|
365
|
+
return null;
|
|
366
|
+
};
|
|
367
|
+
const transformResponse = function(data) {
|
|
368
|
+
data.fields = data.fields.map(
|
|
369
|
+
(item) => item.realType === "blocks" && Array.isArray(item.translatableValue[0]) ? { ...item, translatableValue: item.translatableValue[0] } : item
|
|
370
|
+
);
|
|
371
|
+
return data;
|
|
324
372
|
};
|
|
325
|
-
const transformResponse = (data) => data.map(
|
|
326
|
-
(item) => item.realType === "blocks" && Array.isArray(item.translatableValue[0]) ? { ...item, translatableValue: item.translatableValue[0] } : item
|
|
327
|
-
);
|
|
328
373
|
function jsonToHtml(json) {
|
|
329
374
|
if (!json || !Array.isArray(json)) {
|
|
330
375
|
return "";
|
|
@@ -373,43 +418,37 @@ function formatText(child) {
|
|
|
373
418
|
}
|
|
374
419
|
return text;
|
|
375
420
|
}
|
|
376
|
-
const
|
|
421
|
+
const Logger$4 = {
|
|
422
|
+
log: typeof strapi !== "undefined" ? strapi.log : console,
|
|
423
|
+
info: (val) => Logger$4.log.info(val),
|
|
424
|
+
warn: (val) => Logger$4.log.warn(val),
|
|
425
|
+
error: (val) => Logger$4.log.error(val),
|
|
426
|
+
debug: (val) => Logger$4.log.debug(val)
|
|
427
|
+
};
|
|
428
|
+
async function processComponent(fieldName, value, componentSchema, schemata) {
|
|
377
429
|
const contentFields = [];
|
|
378
|
-
|
|
379
|
-
if (!componentSchema)
|
|
380
|
-
|
|
381
|
-
}
|
|
430
|
+
Logger$4.info("Processing dynamic field " + fieldName);
|
|
431
|
+
if (!componentSchema || !componentSchema.attributes)
|
|
432
|
+
return [];
|
|
382
433
|
const schemaAttributes = componentSchema.attributes || {};
|
|
383
434
|
const dataToProcess = value || {};
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
schemaAttributes,
|
|
389
|
-
fieldName,
|
|
390
|
-
componentName,
|
|
391
|
-
schemaName,
|
|
392
|
-
item.id
|
|
393
|
-
);
|
|
394
|
-
contentFields.push(...processedFields);
|
|
395
|
-
}
|
|
396
|
-
} else {
|
|
397
|
-
const processedFields = await processComponentFields$1(
|
|
398
|
-
dataToProcess,
|
|
435
|
+
const candidates = Array.isArray(dataToProcess) ? dataToProcess : [dataToProcess];
|
|
436
|
+
for (const item of candidates) {
|
|
437
|
+
const processedFields = await processComponentFields(
|
|
438
|
+
item,
|
|
399
439
|
schemaAttributes,
|
|
400
440
|
fieldName,
|
|
401
|
-
|
|
402
|
-
schemaName,
|
|
403
|
-
componentId
|
|
441
|
+
schemata
|
|
404
442
|
);
|
|
405
|
-
|
|
443
|
+
if (processedFields.length > 0)
|
|
444
|
+
contentFields.push(...processedFields);
|
|
406
445
|
}
|
|
407
446
|
return contentFields;
|
|
408
|
-
}
|
|
447
|
+
}
|
|
409
448
|
const shouldSkipField$1 = (key, fieldSchema) => {
|
|
410
449
|
return key === "id" || fieldSchema.private;
|
|
411
450
|
};
|
|
412
|
-
const isTranslatableField
|
|
451
|
+
const isTranslatableField = (type) => {
|
|
413
452
|
return ["string", "text", "blocks", "richtext"].includes(type);
|
|
414
453
|
};
|
|
415
454
|
const getTranslatedValue = (type, value) => {
|
|
@@ -418,64 +457,61 @@ const getTranslatedValue = (type, value) => {
|
|
|
418
457
|
}
|
|
419
458
|
return value.toString();
|
|
420
459
|
};
|
|
421
|
-
const buildTranslatable = (key, fieldSchema, value,
|
|
460
|
+
const buildTranslatable = (key, fieldSchema, value, uuid = "") => {
|
|
422
461
|
return {
|
|
423
462
|
field: key,
|
|
424
463
|
type: ["richtext", "blocks"].includes(fieldSchema.type) ? "html" : "text",
|
|
425
464
|
translatableValue: [value],
|
|
426
465
|
realType: fieldSchema.type,
|
|
427
|
-
|
|
428
|
-
namePath: parentPath,
|
|
429
|
-
id: componentId,
|
|
430
|
-
schemaName
|
|
431
|
-
}
|
|
466
|
+
uuid
|
|
432
467
|
};
|
|
433
468
|
};
|
|
434
|
-
const processComponentFields
|
|
469
|
+
const processComponentFields = async (componentData, schema, parentField, schemata) => {
|
|
435
470
|
const contentFields = [];
|
|
436
|
-
const
|
|
471
|
+
const uuid = crypto.randomUUID();
|
|
437
472
|
for (const [key, fieldSchema] of Object.entries(schema)) {
|
|
438
473
|
if (shouldSkipField$1(key, fieldSchema)) continue;
|
|
439
474
|
const value = componentData?.[key];
|
|
440
|
-
|
|
475
|
+
if (!value)
|
|
476
|
+
continue;
|
|
441
477
|
if (fieldSchema.type === "component") {
|
|
442
|
-
if (!
|
|
478
|
+
if (!value.__component)
|
|
479
|
+
continue;
|
|
480
|
+
const targetSchema = schemata[value.__component];
|
|
481
|
+
if (!targetSchema)
|
|
482
|
+
continue;
|
|
443
483
|
const nestedFields = await processComponent(
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
value?.id
|
|
484
|
+
`${parentField}.${key}`,
|
|
485
|
+
value,
|
|
486
|
+
targetSchema,
|
|
487
|
+
schemata
|
|
449
488
|
);
|
|
450
|
-
|
|
489
|
+
if (nestedFields.length > 0)
|
|
490
|
+
contentFields.push(...nestedFields);
|
|
451
491
|
continue;
|
|
452
492
|
}
|
|
453
|
-
if (!isTranslatableField
|
|
493
|
+
if (!isTranslatableField(fieldSchema.type)) continue;
|
|
454
494
|
if (value === null || value === void 0 || value === "") continue;
|
|
455
495
|
const translatedValue = getTranslatedValue(fieldSchema.type, value);
|
|
456
496
|
const translatable = buildTranslatable(
|
|
457
497
|
key,
|
|
458
498
|
fieldSchema,
|
|
459
499
|
translatedValue,
|
|
460
|
-
|
|
461
|
-
componentId,
|
|
462
|
-
schemaName
|
|
500
|
+
uuid
|
|
463
501
|
);
|
|
502
|
+
componentData.__tsuid = uuid;
|
|
464
503
|
contentFields.push(translatable);
|
|
465
504
|
}
|
|
466
505
|
return contentFields;
|
|
467
506
|
};
|
|
468
|
-
const
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
return localizableTypes.includes(fieldSchema.type);
|
|
475
|
-
}
|
|
476
|
-
return false;
|
|
507
|
+
const Logger$3 = {
|
|
508
|
+
log: typeof strapi !== "undefined" ? strapi.log : console,
|
|
509
|
+
info: (val) => Logger$3.log.info(val),
|
|
510
|
+
warn: (val) => Logger$3.log.warn(val),
|
|
511
|
+
error: (val) => Logger$3.log.error(val),
|
|
512
|
+
debug: (val) => Logger$3.log.debug(val)
|
|
477
513
|
};
|
|
478
|
-
const DEFAULT_FIELDS = /* @__PURE__ */ new Set([
|
|
514
|
+
const DEFAULT_FIELDS$1 = /* @__PURE__ */ new Set([
|
|
479
515
|
"id",
|
|
480
516
|
"documentId",
|
|
481
517
|
"createdAt",
|
|
@@ -487,45 +523,41 @@ const DEFAULT_FIELDS = /* @__PURE__ */ new Set([
|
|
|
487
523
|
"createdBy"
|
|
488
524
|
]);
|
|
489
525
|
const isEmpty = (value) => value === null || value === void 0 || value === "";
|
|
490
|
-
const
|
|
491
|
-
const processDynamicZone = async (key, value,
|
|
526
|
+
const isSimpleTranslatableField = (fieldSchema) => ["string", "text", "blocks", "richtext"].includes(fieldSchema.type) && fieldSchema.pluginOptions?.i18n?.localized === true;
|
|
527
|
+
const processDynamicZone = async (key, value, schemata) => {
|
|
492
528
|
const results = [];
|
|
493
529
|
for (const component of value) {
|
|
494
530
|
const componentName = component?.__component;
|
|
495
531
|
if (!componentName) continue;
|
|
532
|
+
const schema = schemata[componentName];
|
|
533
|
+
if (!schema) continue;
|
|
496
534
|
const fields = await processComponent(
|
|
497
535
|
key,
|
|
498
|
-
componentName,
|
|
499
536
|
component,
|
|
500
|
-
|
|
501
|
-
|
|
537
|
+
schema,
|
|
538
|
+
schemata
|
|
502
539
|
);
|
|
503
|
-
|
|
540
|
+
if (fields.length > 0)
|
|
541
|
+
results.push(...fields);
|
|
504
542
|
}
|
|
505
543
|
return results;
|
|
506
544
|
};
|
|
507
|
-
const processComponentField = async (key, value, fieldSchema) => {
|
|
545
|
+
const processComponentField = async (key, value, fieldSchema, schemata) => {
|
|
508
546
|
const results = [];
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
fieldSchema.component,
|
|
516
|
-
component.id
|
|
517
|
-
);
|
|
518
|
-
results.push(...fields);
|
|
519
|
-
}
|
|
520
|
-
} else {
|
|
547
|
+
const candidates = Array.isArray(value) ? value : [value];
|
|
548
|
+
for (const component of candidates) {
|
|
549
|
+
const componentName = component?.__component;
|
|
550
|
+
if (!componentName) continue;
|
|
551
|
+
const schema = schemata[componentName];
|
|
552
|
+
if (!schema) continue;
|
|
521
553
|
const fields = await processComponent(
|
|
522
554
|
key,
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
value.id
|
|
555
|
+
component,
|
|
556
|
+
schema,
|
|
557
|
+
schemata
|
|
527
558
|
);
|
|
528
|
-
|
|
559
|
+
if (fields.length > 0)
|
|
560
|
+
results.push(...fields);
|
|
529
561
|
}
|
|
530
562
|
return results;
|
|
531
563
|
};
|
|
@@ -538,38 +570,148 @@ const processRegularField = (key, value, fieldSchema) => {
|
|
|
538
570
|
realType: fieldSchema.type
|
|
539
571
|
};
|
|
540
572
|
};
|
|
541
|
-
|
|
573
|
+
function IsLocalisableSchema(schema) {
|
|
574
|
+
return schema.pluginOptions?.i18n?.localized === true;
|
|
575
|
+
}
|
|
576
|
+
function IsLocalisedField(field) {
|
|
577
|
+
return field.pluginOptions?.i18n?.localized === true;
|
|
578
|
+
}
|
|
579
|
+
const processEntryFields = async (entry, schemaData, _locale) => {
|
|
542
580
|
const contentFields = [];
|
|
581
|
+
const staticContent = {};
|
|
582
|
+
const schema = schemaData.entry.attributes;
|
|
543
583
|
for (const [key, value] of Object.entries(entry)) {
|
|
544
|
-
if (shouldSkipField(key, value))
|
|
545
|
-
const fieldSchema = schema[key];
|
|
546
|
-
if (!fieldSchema) continue;
|
|
547
|
-
if (isDynamicZone(fieldSchema, value, schema)) {
|
|
548
|
-
const zoneFields = await processDynamicZone(key, value);
|
|
549
|
-
contentFields.push(...zoneFields);
|
|
584
|
+
if (shouldSkipField(key, value))
|
|
550
585
|
continue;
|
|
551
|
-
|
|
552
|
-
if (
|
|
553
|
-
|
|
554
|
-
contentFields.push(...componentFields);
|
|
586
|
+
const fieldSchema = schema[key];
|
|
587
|
+
if (!fieldSchema || !IsLocalisedField(fieldSchema)) {
|
|
588
|
+
Logger$3.debug("SKipping non-local field " + key);
|
|
555
589
|
continue;
|
|
556
590
|
}
|
|
557
|
-
if (
|
|
591
|
+
if (isSimpleTranslatableField(fieldSchema)) {
|
|
592
|
+
Logger$3.debug("Processing simple field " + key);
|
|
558
593
|
const translatedField = processRegularField(key, value, fieldSchema);
|
|
559
594
|
contentFields.push(translatedField);
|
|
595
|
+
continue;
|
|
596
|
+
}
|
|
597
|
+
const zoneInfo = isDynamicZone(fieldSchema, value);
|
|
598
|
+
if (zoneInfo.isZone) {
|
|
599
|
+
if (zoneInfo.hasContent) {
|
|
600
|
+
Logger$3.debug("Processing dynamic zone field " + key);
|
|
601
|
+
const zoneFields = await processDynamicZone(key, value, schemaData.components);
|
|
602
|
+
contentFields.push(...zoneFields);
|
|
603
|
+
staticContent[key] = value;
|
|
604
|
+
}
|
|
605
|
+
continue;
|
|
606
|
+
}
|
|
607
|
+
const componentInfo = isComponent(fieldSchema);
|
|
608
|
+
if (componentInfo.isZone) {
|
|
609
|
+
const componentFields = await processComponentField(key, value, fieldSchema, schemaData.components);
|
|
610
|
+
contentFields.push(...componentFields);
|
|
611
|
+
staticContent[key] = value;
|
|
560
612
|
}
|
|
561
613
|
}
|
|
562
|
-
|
|
614
|
+
Logger$3.info("Process completed");
|
|
615
|
+
return {
|
|
616
|
+
fields: contentFields,
|
|
617
|
+
keep: staticContent
|
|
618
|
+
};
|
|
563
619
|
};
|
|
564
620
|
const shouldSkipField = (key, value) => {
|
|
565
|
-
return DEFAULT_FIELDS.has(key) || isEmpty(value);
|
|
621
|
+
return DEFAULT_FIELDS$1.has(key) || isEmpty(value);
|
|
622
|
+
};
|
|
623
|
+
const isDynamicZone = (fieldSchema, value) => {
|
|
624
|
+
return {
|
|
625
|
+
isZone: fieldSchema.type === "dynamiczone",
|
|
626
|
+
hasContent: Array.isArray(value) && value.length > 0
|
|
627
|
+
};
|
|
628
|
+
};
|
|
629
|
+
const isComponent = (fieldSchema) => {
|
|
630
|
+
return {
|
|
631
|
+
isZone: fieldSchema.type === "dynamiczone",
|
|
632
|
+
hasContent: true
|
|
633
|
+
};
|
|
634
|
+
};
|
|
635
|
+
const Logger$2 = {
|
|
636
|
+
log: typeof strapi !== "undefined" ? strapi.log : console,
|
|
637
|
+
info: (val) => Logger$2.log.info(val),
|
|
638
|
+
warn: (val) => Logger$2.log.warn(val),
|
|
639
|
+
error: (val) => Logger$2.log.error(val),
|
|
640
|
+
debug: (val) => Logger$2.log.debug(val)
|
|
566
641
|
};
|
|
567
|
-
const
|
|
568
|
-
|
|
642
|
+
const DEFAULT_FIELDS = [
|
|
643
|
+
"id",
|
|
644
|
+
"documentId",
|
|
645
|
+
"createdAt",
|
|
646
|
+
"updatedAt",
|
|
647
|
+
,
|
|
648
|
+
"createdBy",
|
|
649
|
+
"updatedBy",
|
|
650
|
+
"publishedAt",
|
|
651
|
+
"locale",
|
|
652
|
+
"localizations"
|
|
653
|
+
];
|
|
654
|
+
const getContentFields = function(schema) {
|
|
655
|
+
const nullFields = [];
|
|
656
|
+
for (let field in schema) {
|
|
657
|
+
if (!DEFAULT_FIELDS.includes(field))
|
|
658
|
+
nullFields.push(field);
|
|
659
|
+
}
|
|
660
|
+
return nullFields;
|
|
569
661
|
};
|
|
570
|
-
const
|
|
571
|
-
|
|
662
|
+
const getInvalidOrNullFields = function(document, schema) {
|
|
663
|
+
if (!document)
|
|
664
|
+
return getContentFields(schema);
|
|
665
|
+
const nullFields = [];
|
|
666
|
+
let fieldsValid = 0;
|
|
667
|
+
for (let field in document) {
|
|
668
|
+
if (DEFAULT_FIELDS.includes(field))
|
|
669
|
+
continue;
|
|
670
|
+
if (document[field] === null)
|
|
671
|
+
nullFields.push(field);
|
|
672
|
+
else
|
|
673
|
+
fieldsValid++;
|
|
674
|
+
}
|
|
675
|
+
if (nullFields.length > 0 || fieldsValid > 0)
|
|
676
|
+
return nullFields;
|
|
677
|
+
return getContentFields(schema);
|
|
572
678
|
};
|
|
679
|
+
function appendMissingFields(data, sourceEntry, targetSchema, targetEntry) {
|
|
680
|
+
const nullFields = getInvalidOrNullFields(targetEntry, targetSchema.entry.attributes);
|
|
681
|
+
if (nullFields.length === 0)
|
|
682
|
+
return;
|
|
683
|
+
let count = 0;
|
|
684
|
+
Logger$2.info("Adding missing fields to new locale: " + nullFields.join(", "));
|
|
685
|
+
for (let field of nullFields) {
|
|
686
|
+
if (data[field]) {
|
|
687
|
+
Logger$2.info("Field already present: " + field);
|
|
688
|
+
continue;
|
|
689
|
+
}
|
|
690
|
+
if (!sourceEntry[field]) {
|
|
691
|
+
Logger$2.info("No valid source langauge field value for " + field + " - skipping it.");
|
|
692
|
+
continue;
|
|
693
|
+
}
|
|
694
|
+
if (!targetSchema.entry.attributes[field]) {
|
|
695
|
+
Logger$2.warn("Schema does not contain field " + field);
|
|
696
|
+
continue;
|
|
697
|
+
}
|
|
698
|
+
Logger$2.info("Adding missing field and value for " + field);
|
|
699
|
+
data[field] = sourceEntry[field];
|
|
700
|
+
count++;
|
|
701
|
+
}
|
|
702
|
+
if (count > 0)
|
|
703
|
+
Logger$2.info(count + " missing fields added.");
|
|
704
|
+
}
|
|
705
|
+
async function updateEntry(contentTypeID, entryID, targetLocale, data) {
|
|
706
|
+
strapi.log.info("Updating target entry " + contentTypeID + "::" + entryID + " in locale " + targetLocale);
|
|
707
|
+
const newEntry = await strapi.documents(contentTypeID).update({
|
|
708
|
+
documentId: entryID,
|
|
709
|
+
locale: targetLocale,
|
|
710
|
+
data
|
|
711
|
+
});
|
|
712
|
+
if (!newEntry)
|
|
713
|
+
throw new Error("Cannot update target entry " + contentTypeID + "::" + entryID + " in locale " + targetLocale);
|
|
714
|
+
}
|
|
573
715
|
function htmlToJson(html) {
|
|
574
716
|
function parseHTML(html2) {
|
|
575
717
|
const elements2 = [];
|
|
@@ -762,227 +904,171 @@ function htmlToJson(html) {
|
|
|
762
904
|
}
|
|
763
905
|
return blocks;
|
|
764
906
|
}
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
)
|
|
780
|
-
|
|
907
|
+
const Logger$1 = {
|
|
908
|
+
log: typeof strapi !== "undefined" ? strapi.log : console,
|
|
909
|
+
info: (val) => Logger$1.log.info(val),
|
|
910
|
+
warn: (val) => Logger$1.log.warn(val),
|
|
911
|
+
error: (val) => Logger$1.log.error(val),
|
|
912
|
+
debug: (val) => Logger$1.log.debug(val)
|
|
913
|
+
};
|
|
914
|
+
const removeComponentIds = function(elem) {
|
|
915
|
+
const list = Array.isArray(elem) ? elem : [elem];
|
|
916
|
+
for (let obj of list) {
|
|
917
|
+
if (obj.__component && obj.id)
|
|
918
|
+
delete obj.id;
|
|
919
|
+
for (let key in obj) {
|
|
920
|
+
const child = obj[key];
|
|
921
|
+
if (Array.isArray(child) && Array.length > 0)
|
|
922
|
+
removeComponentIds(child);
|
|
923
|
+
else if (typeof child === "object")
|
|
924
|
+
removeComponentIds(child);
|
|
781
925
|
}
|
|
782
926
|
}
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
927
|
+
};
|
|
928
|
+
function replaceDynamicZones(strapiEntry, replacableFields) {
|
|
929
|
+
const fields = [];
|
|
930
|
+
for (let key in strapiEntry) {
|
|
931
|
+
if (replacableFields[key]) {
|
|
932
|
+
removeComponentIds(replacableFields[key]);
|
|
933
|
+
strapiEntry[key] = replacableFields[key];
|
|
934
|
+
fields.push(key);
|
|
787
935
|
}
|
|
788
936
|
}
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
data: localizedData
|
|
793
|
-
});
|
|
794
|
-
if (originalEntry.publishedAt !== null) {
|
|
795
|
-
await strapi.documents(contentTypeID).publish({
|
|
796
|
-
documentId: entryID,
|
|
797
|
-
locale: sourceLocale
|
|
798
|
-
});
|
|
799
|
-
}
|
|
937
|
+
if (fields.length > 0)
|
|
938
|
+
Logger$1.info(fields.length + " dynamic fields/components replaced for later merge: " + fields.join(", "));
|
|
939
|
+
return fields;
|
|
800
940
|
}
|
|
801
|
-
function
|
|
802
|
-
if (
|
|
803
|
-
return
|
|
941
|
+
const mergeValue = function(field, translatable, targetSchema, map) {
|
|
942
|
+
if (translatable.translatableValue.length === 0)
|
|
943
|
+
return false;
|
|
944
|
+
if (targetSchema.attributes[field] === void 0) {
|
|
945
|
+
Logger$1.info("Field " + field + " does not exist in schema. Skipping it");
|
|
946
|
+
Logger$1.info(targetSchema);
|
|
947
|
+
return false;
|
|
804
948
|
}
|
|
805
|
-
if (
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
for (const fieldData of data[0].fields) {
|
|
809
|
-
if (fieldData.realType === "blocks") {
|
|
810
|
-
if (fieldData.translatableValue?.[0]) {
|
|
811
|
-
processedFields[fieldData.field] = htmlToJson(fieldData.translatableValue[0]);
|
|
812
|
-
}
|
|
813
|
-
} else {
|
|
814
|
-
processedFields[fieldData.field] = fieldData.translatableValue?.[0] || null;
|
|
815
|
-
}
|
|
816
|
-
}
|
|
817
|
-
return processedFields;
|
|
818
|
-
}
|
|
819
|
-
return data.map((item) => processDataRecursively(item));
|
|
949
|
+
if (translatable.translatableValue[0] === "") {
|
|
950
|
+
Logger$1.info("Skipping empty translated content for field " + field);
|
|
951
|
+
return false;
|
|
820
952
|
}
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
953
|
+
if (translatable.realType === "blocks") {
|
|
954
|
+
Logger$1.info("Merge block field " + field);
|
|
955
|
+
map[field] = htmlToJson(translatable.translatableValue[0] || "");
|
|
956
|
+
return true;
|
|
824
957
|
}
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
const
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
if (!field.componentInfo) {
|
|
863
|
-
console.warn(`Component info missing for field: ${field.field}`);
|
|
864
|
-
return;
|
|
865
|
-
}
|
|
866
|
-
const componentId = field.componentInfo.id;
|
|
867
|
-
if (!componentsById.has(componentId)) {
|
|
868
|
-
const existingComponent = existingComponents.find((c) => c.id === componentId);
|
|
869
|
-
componentsById.set(componentId, existingComponent ? { ...existingComponent } : {});
|
|
870
|
-
}
|
|
871
|
-
const component = componentsById.get(componentId);
|
|
872
|
-
if (field.realType === "blocks") {
|
|
873
|
-
component[field.field] = htmlToJson(field.translatableValue[0] || "");
|
|
874
|
-
} else {
|
|
875
|
-
component[field.field] = field.translatableValue[0];
|
|
876
|
-
}
|
|
877
|
-
});
|
|
878
|
-
return Array.from(componentsById.values()).map((comp) => {
|
|
879
|
-
if (!existingComponents.find((ec) => ec.id === comp.id)) {
|
|
880
|
-
const { id, ...rest } = comp;
|
|
881
|
-
return rest;
|
|
882
|
-
}
|
|
883
|
-
return comp;
|
|
884
|
-
}).filter((comp) => Object.keys(comp).length > 0);
|
|
885
|
-
}
|
|
886
|
-
function processNestedComponents(fields, pathParts, existingEntry, acc) {
|
|
887
|
-
let current = acc;
|
|
888
|
-
let currentExisting = existingEntry;
|
|
889
|
-
pathParts.forEach((part, index2) => {
|
|
890
|
-
if (!current[part]) {
|
|
891
|
-
current[part] = {};
|
|
892
|
-
if (currentExisting?.[part]?.id) {
|
|
893
|
-
current[part].id = currentExisting[part].id;
|
|
894
|
-
}
|
|
895
|
-
}
|
|
896
|
-
if (index2 === pathParts.length - 1) {
|
|
897
|
-
fields.forEach((field) => {
|
|
898
|
-
if (field.realType === "blocks") {
|
|
899
|
-
current[part][field.field] = htmlToJson(field.translatableValue[0] || "");
|
|
900
|
-
} else {
|
|
901
|
-
current[part][field.field] = field.translatableValue[0];
|
|
902
|
-
}
|
|
903
|
-
});
|
|
904
|
-
} else {
|
|
905
|
-
current = current[part];
|
|
906
|
-
currentExisting = currentExisting?.[part];
|
|
907
|
-
}
|
|
908
|
-
});
|
|
909
|
-
}
|
|
910
|
-
function processComponentFields(componentFieldsMap, acc, existingEntry, targetSchema) {
|
|
911
|
-
componentFieldsMap.forEach((fields, namePath) => {
|
|
912
|
-
if (!fields.length) return;
|
|
913
|
-
const pathParts = namePath.split(".");
|
|
914
|
-
const rootPath = pathParts[0];
|
|
915
|
-
const schema = targetSchema.attributes?.[rootPath];
|
|
916
|
-
if (schema?.repeatable) {
|
|
917
|
-
acc[rootPath] = processRepeatableComponents(fields, existingEntry, rootPath);
|
|
918
|
-
} else {
|
|
919
|
-
processNestedComponents(fields, pathParts, existingEntry, acc);
|
|
958
|
+
if (translatable.type === "text") {
|
|
959
|
+
Logger$1.info("Merge text field " + field);
|
|
960
|
+
map[field] = translatable.translatableValue[0];
|
|
961
|
+
return true;
|
|
962
|
+
}
|
|
963
|
+
Logger$1.warn("Did not process " + field);
|
|
964
|
+
return false;
|
|
965
|
+
};
|
|
966
|
+
const mergeSimpleFields = function(translatables, existingEntry, targetSchema, map) {
|
|
967
|
+
let count = 0;
|
|
968
|
+
for (const candidate of translatables) {
|
|
969
|
+
const field = candidate.field;
|
|
970
|
+
if (!candidate.uuid && mergeValue(field, candidate, targetSchema.entry, map))
|
|
971
|
+
count++;
|
|
972
|
+
}
|
|
973
|
+
if (count > 0) {
|
|
974
|
+
Logger$1.info("Updated " + count + " simple text fields");
|
|
975
|
+
return true;
|
|
976
|
+
}
|
|
977
|
+
return false;
|
|
978
|
+
};
|
|
979
|
+
const buildMapOfUuids = function(existingEntry, schemaMap, map) {
|
|
980
|
+
if (typeof existingEntry !== "object")
|
|
981
|
+
return map;
|
|
982
|
+
const componentName = existingEntry["__component"] ?? "";
|
|
983
|
+
const schema = componentName && schemaMap.components[componentName] ? schemaMap.components[componentName] : null;
|
|
984
|
+
if (componentName && !schema)
|
|
985
|
+
Logger$1.warn("Cannot find component schema " + componentName);
|
|
986
|
+
for (const key of Object.keys(existingEntry)) {
|
|
987
|
+
if (key === "__component")
|
|
988
|
+
continue;
|
|
989
|
+
if (schema !== null && key === "__tsuid") {
|
|
990
|
+
map[existingEntry[key]] = {
|
|
991
|
+
entry: existingEntry,
|
|
992
|
+
schema
|
|
993
|
+
};
|
|
994
|
+
continue;
|
|
920
995
|
}
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
return acc;
|
|
996
|
+
const child = existingEntry[key];
|
|
997
|
+
if (child) {
|
|
998
|
+
if (Array.isArray(child)) {
|
|
999
|
+
for (let e of child)
|
|
1000
|
+
buildMapOfUuids(e, schemaMap, map);
|
|
1001
|
+
} else
|
|
1002
|
+
buildMapOfUuids(child, schemaMap, map);
|
|
929
1003
|
}
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
1004
|
+
}
|
|
1005
|
+
if (existingEntry["__tsuid"]) {
|
|
1006
|
+
delete existingEntry["__tsuid"];
|
|
1007
|
+
Logger$1.info("Removed cusom property __tsuid");
|
|
1008
|
+
}
|
|
1009
|
+
return map;
|
|
1010
|
+
};
|
|
1011
|
+
const mergeDynamicZones = function(translatables, schemaMap, existingEntry) {
|
|
1012
|
+
if (translatables.length === 0) {
|
|
1013
|
+
Logger$1.info("Skipping merging of dynamic zones, because none are present.");
|
|
1014
|
+
return;
|
|
1015
|
+
}
|
|
1016
|
+
const map = {};
|
|
1017
|
+
buildMapOfUuids(existingEntry, schemaMap, map);
|
|
1018
|
+
const mapSize = Object.keys(map).length;
|
|
1019
|
+
if (mapSize === 0) {
|
|
1020
|
+
Logger$1.warn("Could not create a uuid map");
|
|
1021
|
+
return false;
|
|
1022
|
+
}
|
|
1023
|
+
Logger$1.info("Built uuid map with " + mapSize + " entry(s)");
|
|
1024
|
+
let count = 0;
|
|
1025
|
+
for (const translatable of translatables) {
|
|
1026
|
+
if (!translatable.uuid)
|
|
1027
|
+
continue;
|
|
1028
|
+
const uuid = translatable.uuid;
|
|
1029
|
+
if (!map[uuid])
|
|
1030
|
+
continue;
|
|
1031
|
+
const entry = map[uuid];
|
|
1032
|
+
const schema = entry.schema;
|
|
1033
|
+
if (!schema) {
|
|
1034
|
+
Logger$1.warn("Cannot find schema by uuid #" + uuid);
|
|
1035
|
+
continue;
|
|
936
1036
|
}
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
}
|
|
940
|
-
function processDynamicZones(dynamicZoneFields, acc, existingEntry) {
|
|
941
|
-
if (dynamicZoneFields.size > 0) {
|
|
942
|
-
const existingDynamicZone = existingEntry?.dynamiczone || [];
|
|
943
|
-
acc.dynamiczone = Array.from(dynamicZoneFields.entries()).sort(([a], [b]) => a - b).map(([_, fields]) => {
|
|
944
|
-
if (!fields[0].componentInfo) {
|
|
945
|
-
console.warn(
|
|
946
|
-
`Component info missing for dynamic zone field: ${fields[0].field}`
|
|
947
|
-
);
|
|
948
|
-
return null;
|
|
949
|
-
}
|
|
950
|
-
const { schemaName } = fields[0].componentInfo;
|
|
951
|
-
const componentData = transformFieldsToData(fields);
|
|
952
|
-
const matchingComponent = existingDynamicZone.find(
|
|
953
|
-
(comp) => comp.__component === schemaName
|
|
954
|
-
);
|
|
955
|
-
return {
|
|
956
|
-
__component: schemaName,
|
|
957
|
-
...componentData,
|
|
958
|
-
...matchingComponent?.id ? { id: matchingComponent.id } : {}
|
|
959
|
-
};
|
|
960
|
-
}).filter(Boolean);
|
|
1037
|
+
if (mergeValue(translatable.field, translatable, schema, entry.entry))
|
|
1038
|
+
count++;
|
|
961
1039
|
}
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
1040
|
+
if (count > 0) {
|
|
1041
|
+
Logger$1.info("Updated " + count + " entries in dynamic zones/content blocks");
|
|
1042
|
+
return true;
|
|
1043
|
+
}
|
|
1044
|
+
return false;
|
|
1045
|
+
};
|
|
1046
|
+
function prepareImportData(translatables, keepData, existingEntry, targetSchema) {
|
|
1047
|
+
const result = {};
|
|
1048
|
+
const simpleUpdated = mergeSimpleFields(translatables, existingEntry, targetSchema, result);
|
|
1049
|
+
let otherUpdated = false;
|
|
1050
|
+
const vsFields = replaceDynamicZones(existingEntry, keepData);
|
|
1051
|
+
if (vsFields.length > 0) {
|
|
1052
|
+
if (mergeDynamicZones(translatables, targetSchema, existingEntry)) {
|
|
1053
|
+
vsFields.forEach((field) => result[field] = existingEntry[field]);
|
|
1054
|
+
otherUpdated = true;
|
|
1055
|
+
} else
|
|
1056
|
+
Logger$1.warn("Could not merge dynamic fields");
|
|
1057
|
+
}
|
|
1058
|
+
if (simpleUpdated || otherUpdated)
|
|
1059
|
+
return result;
|
|
1060
|
+
else
|
|
1061
|
+
return null;
|
|
981
1062
|
}
|
|
982
|
-
require("jsonwebtoken");
|
|
983
|
-
const crypto = require("crypto");
|
|
984
1063
|
const TRANSLATIONTUDIO_URL = "https://strapi.translationstudio.tech";
|
|
985
1064
|
const APP_NAME = "translationstudio";
|
|
1065
|
+
const Logger = {
|
|
1066
|
+
log: typeof strapi !== "undefined" ? strapi.log : console,
|
|
1067
|
+
info: (val) => Logger.log.info(val),
|
|
1068
|
+
warn: (val) => Logger.log.warn(val),
|
|
1069
|
+
error: (val) => Logger.log.error(val),
|
|
1070
|
+
debug: (val) => Logger.log.debug(val)
|
|
1071
|
+
};
|
|
986
1072
|
const service = ({ strapi: strapi2 }) => {
|
|
987
1073
|
const pluginStore = strapi2.store({
|
|
988
1074
|
type: "plugin",
|
|
@@ -1000,7 +1086,7 @@ const service = ({ strapi: strapi2 }) => {
|
|
|
1000
1086
|
if (typeof result === "string" && result !== "")
|
|
1001
1087
|
return result;
|
|
1002
1088
|
} catch (err) {
|
|
1003
|
-
|
|
1089
|
+
strapi2.log.warn(err);
|
|
1004
1090
|
}
|
|
1005
1091
|
return TRANSLATIONTUDIO_URL;
|
|
1006
1092
|
},
|
|
@@ -1063,9 +1149,15 @@ const service = ({ strapi: strapi2 }) => {
|
|
|
1063
1149
|
},
|
|
1064
1150
|
async exportData(payload) {
|
|
1065
1151
|
const { contentTypeID, entryID, locale } = parsePayload(payload);
|
|
1066
|
-
const contentType =
|
|
1152
|
+
const contentType = getContentType(contentTypeID);
|
|
1153
|
+
if (contentType === null || !IsLocalisableSchema(contentType.entry)) {
|
|
1154
|
+
return {
|
|
1155
|
+
fields: [],
|
|
1156
|
+
keep: {}
|
|
1157
|
+
};
|
|
1158
|
+
}
|
|
1067
1159
|
const entry = await getEntry(contentTypeID, entryID, locale);
|
|
1068
|
-
const contentFields = await processEntryFields(entry, contentType
|
|
1160
|
+
const contentFields = await processEntryFields(entry, contentType);
|
|
1069
1161
|
return transformResponse(contentFields);
|
|
1070
1162
|
},
|
|
1071
1163
|
async importData(payload) {
|
|
@@ -1073,23 +1165,32 @@ const service = ({ strapi: strapi2 }) => {
|
|
|
1073
1165
|
const sourceLocale = payload.source;
|
|
1074
1166
|
const targetLocale = payload.target;
|
|
1075
1167
|
try {
|
|
1076
|
-
const
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1168
|
+
const sourceEntry = await getEntry(contentTypeID, entryID, sourceLocale);
|
|
1169
|
+
if (sourceEntry == null)
|
|
1170
|
+
throw new Error("Cannot find source entry " + contentTypeID + "::" + entryID + " in " + sourceLocale);
|
|
1171
|
+
const targetSchema = getContentType(contentTypeID);
|
|
1172
|
+
if (targetSchema === null || !IsLocalisableSchema(targetSchema.entry))
|
|
1173
|
+
throw new Error("Cannot find schema");
|
|
1174
|
+
const data = prepareImportData(
|
|
1175
|
+
payload.document[0].fields,
|
|
1176
|
+
payload.document[0].keep ?? {},
|
|
1177
|
+
sourceEntry,
|
|
1178
|
+
targetSchema
|
|
1179
|
+
);
|
|
1180
|
+
strapi2.log.info("Loading target language entry");
|
|
1181
|
+
const targetLocaleEntry = await getEntry(contentTypeID, entryID, targetLocale);
|
|
1182
|
+
appendMissingFields(data, sourceEntry, targetSchema, targetLocaleEntry);
|
|
1183
|
+
await updateEntry(
|
|
1184
|
+
contentTypeID,
|
|
1185
|
+
entryID,
|
|
1186
|
+
targetLocale,
|
|
1187
|
+
data
|
|
1188
|
+
);
|
|
1189
|
+
return true;
|
|
1090
1190
|
} catch (error) {
|
|
1091
|
-
|
|
1191
|
+
strapi2.log.error(error);
|
|
1092
1192
|
}
|
|
1193
|
+
return false;
|
|
1093
1194
|
},
|
|
1094
1195
|
async requestTranslation(payload) {
|
|
1095
1196
|
const { license } = await this.getLicense();
|