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