@strapi/i18n 0.0.0-experimental.c592deb623aed3f74ef7fdacfad9757ed59d34f7 → 0.0.0-experimental.cb74730ce5154c26404d4dccca14976a22319002
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/_chunks/{SettingsPage-CnBFTsrq.mjs → SettingsPage-BAx9nmep.mjs} +4 -4
- package/dist/_chunks/SettingsPage-BAx9nmep.mjs.map +1 -0
- package/dist/_chunks/{SettingsPage-CJOMVQv5.js → SettingsPage-BTgjb2KS.js} +5 -6
- package/dist/_chunks/SettingsPage-BTgjb2KS.js.map +1 -0
- package/dist/_chunks/{en-Dk9At9_Z.js → en-BKBz3tro.js} +3 -3
- package/dist/_chunks/en-BKBz3tro.js.map +1 -0
- package/dist/_chunks/{en-BYRZFDBV.mjs → en-DlXfy6Gy.mjs} +3 -3
- package/dist/_chunks/en-DlXfy6Gy.mjs.map +1 -0
- package/dist/_chunks/{index-C5SImSYG.js → index-3yyF237r.js} +28 -15
- package/dist/_chunks/index-3yyF237r.js.map +1 -0
- package/dist/_chunks/{index-BFk3nfTb.mjs → index-B0NijiBB.mjs} +27 -13
- package/dist/_chunks/index-B0NijiBB.mjs.map +1 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/components/CMHeaderActions.d.ts +1 -1
- package/dist/admin/src/components/CreateLocale.d.ts +6 -6
- package/dist/server/index.js +390 -422
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +391 -422
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/index.d.ts +6 -0
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/register.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +6 -0
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/sanitize/index.d.ts +11 -0
- package/dist/server/src/services/sanitize/index.d.ts.map +1 -0
- package/dist/server/src/utils/index.d.ts +2 -0
- package/dist/server/src/utils/index.d.ts.map +1 -1
- package/package.json +13 -13
- package/dist/_chunks/SettingsPage-CJOMVQv5.js.map +0 -1
- package/dist/_chunks/SettingsPage-CnBFTsrq.mjs.map +0 -1
- package/dist/_chunks/en-BYRZFDBV.mjs.map +0 -1
- package/dist/_chunks/en-Dk9At9_Z.js.map +0 -1
- package/dist/_chunks/index-BFk3nfTb.mjs.map +0 -1
- package/dist/_chunks/index-C5SImSYG.js.map +0 -1
- package/dist/server/src/migrations/content-type/disable/index.d.ts +0 -3
- package/dist/server/src/migrations/content-type/disable/index.d.ts.map +0 -1
- package/dist/server/src/migrations/content-type/enable/index.d.ts +0 -3
- package/dist/server/src/migrations/content-type/enable/index.d.ts.map +0 -1
package/dist/server/index.mjs
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
import _ from "lodash";
|
2
|
-
import { get, identity, propEq, isArray, prop, getOr, isEmpty, reduce, cloneDeep, isNil, pipe, pick, has, map, flatten, uniq } from "lodash/fp";
|
2
|
+
import { get, identity, propEq, isArray, prop, getOr, isEmpty, reduce, cloneDeep, isNil, pipe, pick, has, curry, map, flatten, uniq } from "lodash/fp";
|
3
3
|
import * as utils from "@strapi/utils";
|
4
|
-
import { errors, async, contentTypes as contentTypes$2, yup, validateYupSchema } from "@strapi/utils";
|
4
|
+
import { errors, async, contentTypes as contentTypes$2, traverseEntity, yup, validateYupSchema } from "@strapi/utils";
|
5
5
|
const getCoreStore = () => {
|
6
6
|
return strapi.store({ type: "plugin", name: "i18n" });
|
7
7
|
};
|
@@ -174,6 +174,352 @@ const getI18nLocaleArgPlugin = ({ nexus, typeRegistry }) => {
|
|
174
174
|
}
|
175
175
|
});
|
176
176
|
};
|
177
|
+
const register = ({ strapi: strapi2 }) => {
|
178
|
+
extendContentTypes(strapi2);
|
179
|
+
addContentManagerLocaleMiddleware(strapi2);
|
180
|
+
};
|
181
|
+
const addContentManagerLocaleMiddleware = (strapi2) => {
|
182
|
+
strapi2.server.router.use("/content-manager/collection-types/:model", (ctx, next) => {
|
183
|
+
if (ctx.method === "POST" || ctx.method === "PUT") {
|
184
|
+
return validateLocaleCreation(ctx, next);
|
185
|
+
}
|
186
|
+
return next();
|
187
|
+
});
|
188
|
+
strapi2.server.router.use("/content-manager/single-types/:model", (ctx, next) => {
|
189
|
+
if (ctx.method === "POST" || ctx.method === "PUT") {
|
190
|
+
return validateLocaleCreation(ctx, next);
|
191
|
+
}
|
192
|
+
return next();
|
193
|
+
});
|
194
|
+
};
|
195
|
+
const extendContentTypes = (strapi2) => {
|
196
|
+
const { isLocalizedContentType: isLocalizedContentType2 } = getService("content-types");
|
197
|
+
Object.values(strapi2.contentTypes).forEach((contentType) => {
|
198
|
+
const { attributes: attributes2 } = contentType;
|
199
|
+
const isLocalized = isLocalizedContentType2(contentType);
|
200
|
+
_.set(attributes2, "locale", {
|
201
|
+
writable: true,
|
202
|
+
private: !isLocalized,
|
203
|
+
configurable: false,
|
204
|
+
visible: false,
|
205
|
+
type: "string"
|
206
|
+
});
|
207
|
+
_.set(attributes2, "localizations", {
|
208
|
+
type: "relation",
|
209
|
+
relation: "oneToMany",
|
210
|
+
target: contentType.uid,
|
211
|
+
writable: false,
|
212
|
+
private: !isLocalized,
|
213
|
+
configurable: false,
|
214
|
+
visible: false,
|
215
|
+
unstable_virtual: true,
|
216
|
+
joinColumn: {
|
217
|
+
name: "document_id",
|
218
|
+
referencedColumn: "document_id",
|
219
|
+
referencedTable: strapi2.db.metadata.identifiers.getTableName(contentType.collectionName),
|
220
|
+
// ensure the population will not include the results we already loaded
|
221
|
+
on({ results }) {
|
222
|
+
return {
|
223
|
+
id: {
|
224
|
+
$notIn: results.map((r) => r.id)
|
225
|
+
}
|
226
|
+
};
|
227
|
+
}
|
228
|
+
}
|
229
|
+
});
|
230
|
+
});
|
231
|
+
if (strapi2.plugin("graphql")) {
|
232
|
+
graphqlProvider({ strapi: strapi2 }).register();
|
233
|
+
}
|
234
|
+
};
|
235
|
+
const info = {
|
236
|
+
singularName: "locale",
|
237
|
+
pluralName: "locales",
|
238
|
+
collectionName: "locales",
|
239
|
+
displayName: "Locale",
|
240
|
+
description: ""
|
241
|
+
};
|
242
|
+
const options = {};
|
243
|
+
const pluginOptions = {
|
244
|
+
"content-manager": {
|
245
|
+
visible: false
|
246
|
+
},
|
247
|
+
"content-type-builder": {
|
248
|
+
visible: false
|
249
|
+
}
|
250
|
+
};
|
251
|
+
const attributes = {
|
252
|
+
name: {
|
253
|
+
type: "string",
|
254
|
+
min: 1,
|
255
|
+
max: 50,
|
256
|
+
configurable: false
|
257
|
+
},
|
258
|
+
code: {
|
259
|
+
type: "string",
|
260
|
+
unique: true,
|
261
|
+
configurable: false
|
262
|
+
}
|
263
|
+
};
|
264
|
+
const schema = {
|
265
|
+
info,
|
266
|
+
options,
|
267
|
+
pluginOptions,
|
268
|
+
attributes
|
269
|
+
};
|
270
|
+
const locale = {
|
271
|
+
schema
|
272
|
+
};
|
273
|
+
const contentTypes$1 = {
|
274
|
+
locale
|
275
|
+
};
|
276
|
+
const actions = [
|
277
|
+
{
|
278
|
+
section: "settings",
|
279
|
+
category: "Internationalization",
|
280
|
+
subCategory: "Locales",
|
281
|
+
pluginName: "i18n",
|
282
|
+
displayName: "Create",
|
283
|
+
uid: "locale.create"
|
284
|
+
},
|
285
|
+
{
|
286
|
+
section: "settings",
|
287
|
+
category: "Internationalization",
|
288
|
+
subCategory: "Locales",
|
289
|
+
pluginName: "i18n",
|
290
|
+
displayName: "Read",
|
291
|
+
uid: "locale.read",
|
292
|
+
aliases: [
|
293
|
+
{ actionId: "plugin::content-manager.explorer.read", subjects: ["plugin::i18n.locale"] }
|
294
|
+
]
|
295
|
+
},
|
296
|
+
{
|
297
|
+
section: "settings",
|
298
|
+
category: "Internationalization",
|
299
|
+
subCategory: "Locales",
|
300
|
+
pluginName: "i18n",
|
301
|
+
displayName: "Update",
|
302
|
+
uid: "locale.update"
|
303
|
+
},
|
304
|
+
{
|
305
|
+
section: "settings",
|
306
|
+
category: "Internationalization",
|
307
|
+
subCategory: "Locales",
|
308
|
+
pluginName: "i18n",
|
309
|
+
displayName: "Delete",
|
310
|
+
uid: "locale.delete"
|
311
|
+
}
|
312
|
+
];
|
313
|
+
const addLocalesPropertyIfNeeded = ({ value: action }) => {
|
314
|
+
const {
|
315
|
+
section,
|
316
|
+
options: { applyToProperties }
|
317
|
+
} = action;
|
318
|
+
if (section !== "contentTypes") {
|
319
|
+
return;
|
320
|
+
}
|
321
|
+
if (isArray(applyToProperties) && applyToProperties.includes("locales")) {
|
322
|
+
return;
|
323
|
+
}
|
324
|
+
action.options.applyToProperties = isArray(applyToProperties) ? applyToProperties.concat("locales") : ["locales"];
|
325
|
+
};
|
326
|
+
const shouldApplyLocalesPropertyToSubject = ({ property, subject }) => {
|
327
|
+
if (property === "locales") {
|
328
|
+
const model = strapi.getModel(subject);
|
329
|
+
return getService("content-types").isLocalizedContentType(model);
|
330
|
+
}
|
331
|
+
return true;
|
332
|
+
};
|
333
|
+
const addAllLocalesToPermissions = async (permissions2) => {
|
334
|
+
const { actionProvider } = strapi.service("admin::permission");
|
335
|
+
const { find: findAllLocales } = getService("locales");
|
336
|
+
const allLocales = await findAllLocales();
|
337
|
+
const allLocalesCode = allLocales.map(prop("code"));
|
338
|
+
return Promise.all(
|
339
|
+
permissions2.map(async (permission) => {
|
340
|
+
const { action, subject } = permission;
|
341
|
+
const appliesToLocalesProperty = await actionProvider.appliesToProperty(
|
342
|
+
"locales",
|
343
|
+
action,
|
344
|
+
subject
|
345
|
+
);
|
346
|
+
if (!appliesToLocalesProperty) {
|
347
|
+
return permission;
|
348
|
+
}
|
349
|
+
const oldPermissionProperties = getOr({}, "properties", permission);
|
350
|
+
return { ...permission, properties: { ...oldPermissionProperties, locales: allLocalesCode } };
|
351
|
+
})
|
352
|
+
);
|
353
|
+
};
|
354
|
+
const syncSuperAdminPermissionsWithLocales = async () => {
|
355
|
+
const roleService = strapi.service("admin::role");
|
356
|
+
const permissionService = strapi.service("admin::permission");
|
357
|
+
const superAdminRole = await roleService.getSuperAdmin();
|
358
|
+
if (!superAdminRole) {
|
359
|
+
return;
|
360
|
+
}
|
361
|
+
const superAdminPermissions = await permissionService.findMany({
|
362
|
+
where: {
|
363
|
+
role: {
|
364
|
+
id: superAdminRole.id
|
365
|
+
}
|
366
|
+
}
|
367
|
+
});
|
368
|
+
const newSuperAdminPermissions = await addAllLocalesToPermissions(superAdminPermissions);
|
369
|
+
await roleService.assignPermissions(superAdminRole.id, newSuperAdminPermissions);
|
370
|
+
};
|
371
|
+
const registerI18nActions = async () => {
|
372
|
+
const { actionProvider } = strapi.service("admin::permission");
|
373
|
+
await actionProvider.registerMany(actions);
|
374
|
+
};
|
375
|
+
const registerI18nActionsHooks = () => {
|
376
|
+
const { actionProvider } = strapi.service("admin::permission");
|
377
|
+
const { hooks } = strapi.service("admin::role");
|
378
|
+
actionProvider.hooks.appliesPropertyToSubject.register(shouldApplyLocalesPropertyToSubject);
|
379
|
+
hooks.willResetSuperAdminPermissions.register(addAllLocalesToPermissions);
|
380
|
+
};
|
381
|
+
const updateActionsProperties = () => {
|
382
|
+
const { actionProvider } = strapi.service("admin::permission");
|
383
|
+
actionProvider.hooks.willRegister.register(addLocalesPropertyIfNeeded);
|
384
|
+
actionProvider.values().forEach((action) => addLocalesPropertyIfNeeded({ value: action }));
|
385
|
+
};
|
386
|
+
const i18nActionsService = {
|
387
|
+
actions,
|
388
|
+
registerI18nActions,
|
389
|
+
registerI18nActionsHooks,
|
390
|
+
updateActionsProperties,
|
391
|
+
syncSuperAdminPermissionsWithLocales
|
392
|
+
};
|
393
|
+
const localesPropertyHandler = async ({ action, section }) => {
|
394
|
+
const { actionProvider } = strapi.service("admin::permission");
|
395
|
+
const locales2 = await getService("locales").find();
|
396
|
+
if (isEmpty(locales2)) {
|
397
|
+
return;
|
398
|
+
}
|
399
|
+
for (const subject of section.subjects) {
|
400
|
+
const applies = await actionProvider.appliesToProperty("locales", action.actionId, subject.uid);
|
401
|
+
const hasLocalesProperty = subject.properties.find(
|
402
|
+
(property) => property.value === "locales"
|
403
|
+
);
|
404
|
+
if (applies && !hasLocalesProperty) {
|
405
|
+
subject.properties.push({
|
406
|
+
label: "Locales",
|
407
|
+
value: "locales",
|
408
|
+
children: locales2.map(({ name, code }) => ({ label: name || code, value: code }))
|
409
|
+
});
|
410
|
+
}
|
411
|
+
}
|
412
|
+
};
|
413
|
+
const registerLocalesPropertyHandler = () => {
|
414
|
+
const { sectionsBuilder } = strapi.service("admin::permission");
|
415
|
+
sectionsBuilder.addHandler("singleTypes", localesPropertyHandler);
|
416
|
+
sectionsBuilder.addHandler("collectionTypes", localesPropertyHandler);
|
417
|
+
};
|
418
|
+
const sectionsBuilderService = {
|
419
|
+
localesPropertyHandler,
|
420
|
+
registerLocalesPropertyHandler
|
421
|
+
};
|
422
|
+
const willRegisterPermission = (context) => {
|
423
|
+
const { permission, condition, user } = context;
|
424
|
+
const { subject, properties } = permission;
|
425
|
+
const isSuperAdmin = strapi.service("admin::role").hasSuperAdminRole(user);
|
426
|
+
if (isSuperAdmin) {
|
427
|
+
return;
|
428
|
+
}
|
429
|
+
const { locales: locales2 } = properties || {};
|
430
|
+
const { isLocalizedContentType: isLocalizedContentType2 } = getService("content-types");
|
431
|
+
if (!subject) {
|
432
|
+
return;
|
433
|
+
}
|
434
|
+
const ct = strapi.contentTypes[subject];
|
435
|
+
if (!isLocalizedContentType2(ct)) {
|
436
|
+
return;
|
437
|
+
}
|
438
|
+
if (locales2 === null) {
|
439
|
+
return;
|
440
|
+
}
|
441
|
+
condition.and({
|
442
|
+
locale: {
|
443
|
+
$in: locales2 || []
|
444
|
+
}
|
445
|
+
});
|
446
|
+
};
|
447
|
+
const registerI18nPermissionsHandlers = () => {
|
448
|
+
const { engine } = strapi.service("admin::permission");
|
449
|
+
engine.hooks["before-register.permission"].register(willRegisterPermission);
|
450
|
+
};
|
451
|
+
const engineService = {
|
452
|
+
willRegisterPermission,
|
453
|
+
registerI18nPermissionsHandlers
|
454
|
+
};
|
455
|
+
const permissions = () => ({
|
456
|
+
actions: i18nActionsService,
|
457
|
+
sectionsBuilder: sectionsBuilderService,
|
458
|
+
engine: engineService
|
459
|
+
});
|
460
|
+
const sendDidInitializeEvent = async () => {
|
461
|
+
const { isLocalizedContentType: isLocalizedContentType2 } = getService("content-types");
|
462
|
+
const numberOfContentTypes = reduce(
|
463
|
+
(sum, contentType) => isLocalizedContentType2(contentType) ? sum + 1 : sum,
|
464
|
+
0
|
465
|
+
)(strapi.contentTypes);
|
466
|
+
await strapi.telemetry.send("didInitializeI18n", { groupProperties: { numberOfContentTypes } });
|
467
|
+
};
|
468
|
+
const sendDidUpdateI18nLocalesEvent = async () => {
|
469
|
+
const numberOfLocales = await getService("locales").count();
|
470
|
+
await strapi.telemetry.send("didUpdateI18nLocales", {
|
471
|
+
groupProperties: { numberOfLocales }
|
472
|
+
});
|
473
|
+
};
|
474
|
+
const metrics = () => ({
|
475
|
+
sendDidInitializeEvent,
|
476
|
+
sendDidUpdateI18nLocalesEvent
|
477
|
+
});
|
478
|
+
const syncNonLocalizedAttributes = async (sourceEntry, model) => {
|
479
|
+
const { copyNonLocalizedAttributes: copyNonLocalizedAttributes2 } = getService("content-types");
|
480
|
+
const nonLocalizedAttributes = copyNonLocalizedAttributes2(model, sourceEntry);
|
481
|
+
if (isEmpty(nonLocalizedAttributes)) {
|
482
|
+
return;
|
483
|
+
}
|
484
|
+
const uid = model.uid;
|
485
|
+
const documentId = sourceEntry.documentId;
|
486
|
+
const locale2 = sourceEntry.locale;
|
487
|
+
const status = sourceEntry?.publishedAt ? "published" : "draft";
|
488
|
+
const localeEntriesToUpdate = await strapi.db.query(uid).findMany({
|
489
|
+
where: {
|
490
|
+
documentId,
|
491
|
+
publishedAt: status === "published" ? { $ne: null } : null,
|
492
|
+
locale: { $ne: locale2 }
|
493
|
+
},
|
494
|
+
select: ["locale", "id"]
|
495
|
+
});
|
496
|
+
const entryData = await strapi.documents(uid).omitComponentData(nonLocalizedAttributes);
|
497
|
+
await async.map(localeEntriesToUpdate, async (entry) => {
|
498
|
+
const transformedData = await strapi.documents.utils.transformData(
|
499
|
+
cloneDeep(nonLocalizedAttributes),
|
500
|
+
{
|
501
|
+
uid,
|
502
|
+
status,
|
503
|
+
locale: entry.locale,
|
504
|
+
allowMissingId: true
|
505
|
+
}
|
506
|
+
);
|
507
|
+
const componentData = await strapi.documents(uid).updateComponents(entry, transformedData);
|
508
|
+
await strapi.db.query(uid).update({
|
509
|
+
where: {
|
510
|
+
documentId,
|
511
|
+
publishedAt: status === "published" ? { $ne: null } : null,
|
512
|
+
locale: { $eq: entry.locale }
|
513
|
+
},
|
514
|
+
// The data we send to the update function is the entry data merged with
|
515
|
+
// the updated component data
|
516
|
+
data: Object.assign(cloneDeep(entryData), componentData)
|
517
|
+
});
|
518
|
+
});
|
519
|
+
};
|
520
|
+
const localizations = () => ({
|
521
|
+
syncNonLocalizedAttributes
|
522
|
+
});
|
177
523
|
const isoLocales = [
|
178
524
|
{
|
179
525
|
code: "af",
|
@@ -2567,438 +2913,40 @@ const isoLocales = [
|
|
2567
2913
|
code: "yo-NG",
|
2568
2914
|
name: "Yoruba (Nigeria) (yo-NG)"
|
2569
2915
|
},
|
2570
|
-
{
|
2571
|
-
code: "dje",
|
2572
|
-
name: "Zarma (dje)"
|
2573
|
-
},
|
2574
|
-
{
|
2575
|
-
code: "dje-NE",
|
2576
|
-
name: "Zarma (Niger) (dje-NE)"
|
2577
|
-
},
|
2578
|
-
{
|
2579
|
-
code: "zu",
|
2580
|
-
name: "Zulu (zu)"
|
2581
|
-
},
|
2582
|
-
{
|
2583
|
-
code: "zu-ZA",
|
2584
|
-
name: "Zulu (South Africa) (zu-ZA)"
|
2585
|
-
}
|
2586
|
-
];
|
2587
|
-
const getInitLocale = () => {
|
2588
|
-
const envLocaleCode = process.env.STRAPI_PLUGIN_I18N_INIT_LOCALE_CODE;
|
2589
|
-
if (envLocaleCode) {
|
2590
|
-
const matchingLocale = isoLocales.find(({ code }) => code === envLocaleCode);
|
2591
|
-
if (!matchingLocale) {
|
2592
|
-
throw new Error(
|
2593
|
-
"Unknown locale code provided in the environment variable STRAPI_PLUGIN_I18N_INIT_LOCALE_CODE"
|
2594
|
-
);
|
2595
|
-
}
|
2596
|
-
return { ...matchingLocale };
|
2597
|
-
}
|
2598
|
-
return {
|
2599
|
-
code: "en",
|
2600
|
-
name: "English (en)"
|
2601
|
-
};
|
2602
|
-
};
|
2603
|
-
const DEFAULT_LOCALE = getInitLocale();
|
2604
|
-
const enableContentType = async ({ oldContentTypes, contentTypes: contentTypes2 }) => {
|
2605
|
-
const { isLocalizedContentType: isLocalizedContentType2 } = getService("content-types");
|
2606
|
-
const { getDefaultLocale: getDefaultLocale2 } = getService("locales");
|
2607
|
-
if (!oldContentTypes) {
|
2608
|
-
return;
|
2609
|
-
}
|
2610
|
-
for (const uid in contentTypes2) {
|
2611
|
-
if (!oldContentTypes[uid]) {
|
2612
|
-
continue;
|
2613
|
-
}
|
2614
|
-
const oldContentType = oldContentTypes[uid];
|
2615
|
-
const contentType = contentTypes2[uid];
|
2616
|
-
if (!isLocalizedContentType2(oldContentType) && isLocalizedContentType2(contentType)) {
|
2617
|
-
const defaultLocale = await getDefaultLocale2() || DEFAULT_LOCALE.code;
|
2618
|
-
await strapi.db.query(uid).updateMany({
|
2619
|
-
where: { locale: null },
|
2620
|
-
data: { locale: defaultLocale }
|
2621
|
-
});
|
2622
|
-
}
|
2623
|
-
}
|
2624
|
-
};
|
2625
|
-
const disableContentType = async ({ oldContentTypes, contentTypes: contentTypes2 }) => {
|
2626
|
-
const { isLocalizedContentType: isLocalizedContentType2 } = getService("content-types");
|
2627
|
-
const { getDefaultLocale: getDefaultLocale2 } = getService("locales");
|
2628
|
-
if (!oldContentTypes) {
|
2629
|
-
return;
|
2630
|
-
}
|
2631
|
-
for (const uid in contentTypes2) {
|
2632
|
-
if (!oldContentTypes[uid]) {
|
2633
|
-
continue;
|
2634
|
-
}
|
2635
|
-
const oldContentType = oldContentTypes[uid];
|
2636
|
-
const contentType = contentTypes2[uid];
|
2637
|
-
if (isLocalizedContentType2(oldContentType) && !isLocalizedContentType2(contentType)) {
|
2638
|
-
const defaultLocale = await getDefaultLocale2() || DEFAULT_LOCALE.code;
|
2639
|
-
await Promise.all([
|
2640
|
-
// Delete all entities that are not in the default locale
|
2641
|
-
strapi.db.query(uid).deleteMany({
|
2642
|
-
where: { locale: { $ne: defaultLocale } }
|
2643
|
-
}),
|
2644
|
-
// Set locale to null for the rest
|
2645
|
-
strapi.db.query(uid).updateMany({
|
2646
|
-
where: { locale: { $eq: defaultLocale } },
|
2647
|
-
data: { locale: null }
|
2648
|
-
})
|
2649
|
-
]);
|
2650
|
-
}
|
2651
|
-
}
|
2652
|
-
};
|
2653
|
-
const register = ({ strapi: strapi2 }) => {
|
2654
|
-
extendContentTypes(strapi2);
|
2655
|
-
addContentManagerLocaleMiddleware(strapi2);
|
2656
|
-
addContentTypeSyncHooks(strapi2);
|
2657
|
-
};
|
2658
|
-
const addContentManagerLocaleMiddleware = (strapi2) => {
|
2659
|
-
strapi2.server.router.use("/content-manager/collection-types/:model", (ctx, next) => {
|
2660
|
-
if (ctx.method === "POST" || ctx.method === "PUT") {
|
2661
|
-
return validateLocaleCreation(ctx, next);
|
2662
|
-
}
|
2663
|
-
return next();
|
2664
|
-
});
|
2665
|
-
strapi2.server.router.use("/content-manager/single-types/:model", (ctx, next) => {
|
2666
|
-
if (ctx.method === "POST" || ctx.method === "PUT") {
|
2667
|
-
return validateLocaleCreation(ctx, next);
|
2668
|
-
}
|
2669
|
-
return next();
|
2670
|
-
});
|
2671
|
-
};
|
2672
|
-
const addContentTypeSyncHooks = (strapi2) => {
|
2673
|
-
strapi2.hook("strapi::content-types.beforeSync").register(disableContentType);
|
2674
|
-
strapi2.hook("strapi::content-types.afterSync").register(enableContentType);
|
2675
|
-
};
|
2676
|
-
const extendContentTypes = (strapi2) => {
|
2677
|
-
Object.values(strapi2.contentTypes).forEach((contentType) => {
|
2678
|
-
const { attributes: attributes2 } = contentType;
|
2679
|
-
_.set(attributes2, "locale", {
|
2680
|
-
writable: true,
|
2681
|
-
private: false,
|
2682
|
-
configurable: false,
|
2683
|
-
visible: false,
|
2684
|
-
type: "string"
|
2685
|
-
});
|
2686
|
-
_.set(attributes2, "localizations", {
|
2687
|
-
type: "relation",
|
2688
|
-
relation: "oneToMany",
|
2689
|
-
target: contentType.uid,
|
2690
|
-
writable: false,
|
2691
|
-
private: false,
|
2692
|
-
configurable: false,
|
2693
|
-
visible: false,
|
2694
|
-
unstable_virtual: true,
|
2695
|
-
joinColumn: {
|
2696
|
-
name: "document_id",
|
2697
|
-
referencedColumn: "document_id",
|
2698
|
-
referencedTable: strapi2.db.metadata.identifiers.getTableName(contentType.collectionName),
|
2699
|
-
// ensure the population will not include the results we already loaded
|
2700
|
-
on({ results }) {
|
2701
|
-
return {
|
2702
|
-
id: {
|
2703
|
-
$notIn: results.map((r) => r.id)
|
2704
|
-
}
|
2705
|
-
};
|
2706
|
-
}
|
2707
|
-
}
|
2708
|
-
});
|
2709
|
-
});
|
2710
|
-
if (strapi2.plugin("graphql")) {
|
2711
|
-
graphqlProvider({ strapi: strapi2 }).register();
|
2712
|
-
}
|
2713
|
-
};
|
2714
|
-
const info = {
|
2715
|
-
singularName: "locale",
|
2716
|
-
pluralName: "locales",
|
2717
|
-
collectionName: "locales",
|
2718
|
-
displayName: "Locale",
|
2719
|
-
description: ""
|
2720
|
-
};
|
2721
|
-
const options = {};
|
2722
|
-
const pluginOptions = {
|
2723
|
-
"content-manager": {
|
2724
|
-
visible: false
|
2725
|
-
},
|
2726
|
-
"content-type-builder": {
|
2727
|
-
visible: false
|
2728
|
-
}
|
2729
|
-
};
|
2730
|
-
const attributes = {
|
2731
|
-
name: {
|
2732
|
-
type: "string",
|
2733
|
-
min: 1,
|
2734
|
-
max: 50,
|
2735
|
-
configurable: false
|
2736
|
-
},
|
2737
|
-
code: {
|
2738
|
-
type: "string",
|
2739
|
-
unique: true,
|
2740
|
-
configurable: false
|
2741
|
-
}
|
2742
|
-
};
|
2743
|
-
const schema = {
|
2744
|
-
info,
|
2745
|
-
options,
|
2746
|
-
pluginOptions,
|
2747
|
-
attributes
|
2748
|
-
};
|
2749
|
-
const locale = {
|
2750
|
-
schema
|
2751
|
-
};
|
2752
|
-
const contentTypes$1 = {
|
2753
|
-
locale
|
2754
|
-
};
|
2755
|
-
const actions = [
|
2756
|
-
{
|
2757
|
-
section: "settings",
|
2758
|
-
category: "Internationalization",
|
2759
|
-
subCategory: "Locales",
|
2760
|
-
pluginName: "i18n",
|
2761
|
-
displayName: "Create",
|
2762
|
-
uid: "locale.create"
|
2916
|
+
{
|
2917
|
+
code: "dje",
|
2918
|
+
name: "Zarma (dje)"
|
2763
2919
|
},
|
2764
2920
|
{
|
2765
|
-
|
2766
|
-
|
2767
|
-
subCategory: "Locales",
|
2768
|
-
pluginName: "i18n",
|
2769
|
-
displayName: "Read",
|
2770
|
-
uid: "locale.read",
|
2771
|
-
aliases: [
|
2772
|
-
{ actionId: "plugin::content-manager.explorer.read", subjects: ["plugin::i18n.locale"] }
|
2773
|
-
]
|
2921
|
+
code: "dje-NE",
|
2922
|
+
name: "Zarma (Niger) (dje-NE)"
|
2774
2923
|
},
|
2775
2924
|
{
|
2776
|
-
|
2777
|
-
|
2778
|
-
subCategory: "Locales",
|
2779
|
-
pluginName: "i18n",
|
2780
|
-
displayName: "Update",
|
2781
|
-
uid: "locale.update"
|
2925
|
+
code: "zu",
|
2926
|
+
name: "Zulu (zu)"
|
2782
2927
|
},
|
2783
2928
|
{
|
2784
|
-
|
2785
|
-
|
2786
|
-
subCategory: "Locales",
|
2787
|
-
pluginName: "i18n",
|
2788
|
-
displayName: "Delete",
|
2789
|
-
uid: "locale.delete"
|
2929
|
+
code: "zu-ZA",
|
2930
|
+
name: "Zulu (South Africa) (zu-ZA)"
|
2790
2931
|
}
|
2791
2932
|
];
|
2792
|
-
const
|
2793
|
-
const
|
2794
|
-
|
2795
|
-
|
2796
|
-
|
2797
|
-
|
2798
|
-
|
2799
|
-
}
|
2800
|
-
if (isArray(applyToProperties) && applyToProperties.includes("locales")) {
|
2801
|
-
return;
|
2802
|
-
}
|
2803
|
-
action.options.applyToProperties = isArray(applyToProperties) ? applyToProperties.concat("locales") : ["locales"];
|
2804
|
-
};
|
2805
|
-
const shouldApplyLocalesPropertyToSubject = ({ property, subject }) => {
|
2806
|
-
if (property === "locales") {
|
2807
|
-
const model = strapi.getModel(subject);
|
2808
|
-
return getService("content-types").isLocalizedContentType(model);
|
2809
|
-
}
|
2810
|
-
return true;
|
2811
|
-
};
|
2812
|
-
const addAllLocalesToPermissions = async (permissions2) => {
|
2813
|
-
const { actionProvider } = strapi.service("admin::permission");
|
2814
|
-
const { find: findAllLocales } = getService("locales");
|
2815
|
-
const allLocales = await findAllLocales();
|
2816
|
-
const allLocalesCode = allLocales.map(prop("code"));
|
2817
|
-
return Promise.all(
|
2818
|
-
permissions2.map(async (permission) => {
|
2819
|
-
const { action, subject } = permission;
|
2820
|
-
const appliesToLocalesProperty = await actionProvider.appliesToProperty(
|
2821
|
-
"locales",
|
2822
|
-
action,
|
2823
|
-
subject
|
2933
|
+
const getInitLocale = () => {
|
2934
|
+
const envLocaleCode = process.env.STRAPI_PLUGIN_I18N_INIT_LOCALE_CODE;
|
2935
|
+
if (envLocaleCode) {
|
2936
|
+
const matchingLocale = isoLocales.find(({ code }) => code === envLocaleCode);
|
2937
|
+
if (!matchingLocale) {
|
2938
|
+
throw new Error(
|
2939
|
+
"Unknown locale code provided in the environment variable STRAPI_PLUGIN_I18N_INIT_LOCALE_CODE"
|
2824
2940
|
);
|
2825
|
-
if (!appliesToLocalesProperty) {
|
2826
|
-
return permission;
|
2827
|
-
}
|
2828
|
-
const oldPermissionProperties = getOr({}, "properties", permission);
|
2829
|
-
return { ...permission, properties: { ...oldPermissionProperties, locales: allLocalesCode } };
|
2830
|
-
})
|
2831
|
-
);
|
2832
|
-
};
|
2833
|
-
const syncSuperAdminPermissionsWithLocales = async () => {
|
2834
|
-
const roleService = strapi.service("admin::role");
|
2835
|
-
const permissionService = strapi.service("admin::permission");
|
2836
|
-
const superAdminRole = await roleService.getSuperAdmin();
|
2837
|
-
if (!superAdminRole) {
|
2838
|
-
return;
|
2839
|
-
}
|
2840
|
-
const superAdminPermissions = await permissionService.findMany({
|
2841
|
-
where: {
|
2842
|
-
role: {
|
2843
|
-
id: superAdminRole.id
|
2844
|
-
}
|
2845
|
-
}
|
2846
|
-
});
|
2847
|
-
const newSuperAdminPermissions = await addAllLocalesToPermissions(superAdminPermissions);
|
2848
|
-
await roleService.assignPermissions(superAdminRole.id, newSuperAdminPermissions);
|
2849
|
-
};
|
2850
|
-
const registerI18nActions = async () => {
|
2851
|
-
const { actionProvider } = strapi.service("admin::permission");
|
2852
|
-
await actionProvider.registerMany(actions);
|
2853
|
-
};
|
2854
|
-
const registerI18nActionsHooks = () => {
|
2855
|
-
const { actionProvider } = strapi.service("admin::permission");
|
2856
|
-
const { hooks } = strapi.service("admin::role");
|
2857
|
-
actionProvider.hooks.appliesPropertyToSubject.register(shouldApplyLocalesPropertyToSubject);
|
2858
|
-
hooks.willResetSuperAdminPermissions.register(addAllLocalesToPermissions);
|
2859
|
-
};
|
2860
|
-
const updateActionsProperties = () => {
|
2861
|
-
const { actionProvider } = strapi.service("admin::permission");
|
2862
|
-
actionProvider.hooks.willRegister.register(addLocalesPropertyIfNeeded);
|
2863
|
-
actionProvider.values().forEach((action) => addLocalesPropertyIfNeeded({ value: action }));
|
2864
|
-
};
|
2865
|
-
const i18nActionsService = {
|
2866
|
-
actions,
|
2867
|
-
registerI18nActions,
|
2868
|
-
registerI18nActionsHooks,
|
2869
|
-
updateActionsProperties,
|
2870
|
-
syncSuperAdminPermissionsWithLocales
|
2871
|
-
};
|
2872
|
-
const localesPropertyHandler = async ({ action, section }) => {
|
2873
|
-
const { actionProvider } = strapi.service("admin::permission");
|
2874
|
-
const locales2 = await getService("locales").find();
|
2875
|
-
if (isEmpty(locales2)) {
|
2876
|
-
return;
|
2877
|
-
}
|
2878
|
-
for (const subject of section.subjects) {
|
2879
|
-
const applies = await actionProvider.appliesToProperty("locales", action.actionId, subject.uid);
|
2880
|
-
const hasLocalesProperty = subject.properties.find(
|
2881
|
-
(property) => property.value === "locales"
|
2882
|
-
);
|
2883
|
-
if (applies && !hasLocalesProperty) {
|
2884
|
-
subject.properties.push({
|
2885
|
-
label: "Locales",
|
2886
|
-
value: "locales",
|
2887
|
-
children: locales2.map(({ name, code }) => ({ label: name || code, value: code }))
|
2888
|
-
});
|
2889
|
-
}
|
2890
|
-
}
|
2891
|
-
};
|
2892
|
-
const registerLocalesPropertyHandler = () => {
|
2893
|
-
const { sectionsBuilder } = strapi.service("admin::permission");
|
2894
|
-
sectionsBuilder.addHandler("singleTypes", localesPropertyHandler);
|
2895
|
-
sectionsBuilder.addHandler("collectionTypes", localesPropertyHandler);
|
2896
|
-
};
|
2897
|
-
const sectionsBuilderService = {
|
2898
|
-
localesPropertyHandler,
|
2899
|
-
registerLocalesPropertyHandler
|
2900
|
-
};
|
2901
|
-
const willRegisterPermission = (context) => {
|
2902
|
-
const { permission, condition, user } = context;
|
2903
|
-
const { subject, properties } = permission;
|
2904
|
-
const isSuperAdmin = strapi.service("admin::role").hasSuperAdminRole(user);
|
2905
|
-
if (isSuperAdmin) {
|
2906
|
-
return;
|
2907
|
-
}
|
2908
|
-
const { locales: locales2 } = properties || {};
|
2909
|
-
const { isLocalizedContentType: isLocalizedContentType2 } = getService("content-types");
|
2910
|
-
if (!subject) {
|
2911
|
-
return;
|
2912
|
-
}
|
2913
|
-
const ct = strapi.contentTypes[subject];
|
2914
|
-
if (!isLocalizedContentType2(ct)) {
|
2915
|
-
return;
|
2916
|
-
}
|
2917
|
-
if (locales2 === null) {
|
2918
|
-
return;
|
2919
|
-
}
|
2920
|
-
condition.and({
|
2921
|
-
locale: {
|
2922
|
-
$in: locales2 || []
|
2923
2941
|
}
|
2924
|
-
|
2925
|
-
};
|
2926
|
-
const registerI18nPermissionsHandlers = () => {
|
2927
|
-
const { engine } = strapi.service("admin::permission");
|
2928
|
-
engine.hooks["before-register.permission"].register(willRegisterPermission);
|
2929
|
-
};
|
2930
|
-
const engineService = {
|
2931
|
-
willRegisterPermission,
|
2932
|
-
registerI18nPermissionsHandlers
|
2933
|
-
};
|
2934
|
-
const permissions = () => ({
|
2935
|
-
actions: i18nActionsService,
|
2936
|
-
sectionsBuilder: sectionsBuilderService,
|
2937
|
-
engine: engineService
|
2938
|
-
});
|
2939
|
-
const sendDidInitializeEvent = async () => {
|
2940
|
-
const { isLocalizedContentType: isLocalizedContentType2 } = getService("content-types");
|
2941
|
-
const numberOfContentTypes = reduce(
|
2942
|
-
(sum, contentType) => isLocalizedContentType2(contentType) ? sum + 1 : sum,
|
2943
|
-
0
|
2944
|
-
)(strapi.contentTypes);
|
2945
|
-
await strapi.telemetry.send("didInitializeI18n", { groupProperties: { numberOfContentTypes } });
|
2946
|
-
};
|
2947
|
-
const sendDidUpdateI18nLocalesEvent = async () => {
|
2948
|
-
const numberOfLocales = await getService("locales").count();
|
2949
|
-
await strapi.telemetry.send("didUpdateI18nLocales", {
|
2950
|
-
groupProperties: { numberOfLocales }
|
2951
|
-
});
|
2952
|
-
};
|
2953
|
-
const metrics = () => ({
|
2954
|
-
sendDidInitializeEvent,
|
2955
|
-
sendDidUpdateI18nLocalesEvent
|
2956
|
-
});
|
2957
|
-
const syncNonLocalizedAttributes = async (sourceEntry, model) => {
|
2958
|
-
const { copyNonLocalizedAttributes: copyNonLocalizedAttributes2 } = getService("content-types");
|
2959
|
-
const nonLocalizedAttributes = copyNonLocalizedAttributes2(model, sourceEntry);
|
2960
|
-
if (isEmpty(nonLocalizedAttributes)) {
|
2961
|
-
return;
|
2942
|
+
return { ...matchingLocale };
|
2962
2943
|
}
|
2963
|
-
|
2964
|
-
|
2965
|
-
|
2966
|
-
|
2967
|
-
const localeEntriesToUpdate = await strapi.db.query(uid).findMany({
|
2968
|
-
where: {
|
2969
|
-
documentId,
|
2970
|
-
publishedAt: status === "published" ? { $ne: null } : null,
|
2971
|
-
locale: { $ne: locale2 }
|
2972
|
-
},
|
2973
|
-
select: ["locale", "id"]
|
2974
|
-
});
|
2975
|
-
const entryData = await strapi.documents(uid).omitComponentData(nonLocalizedAttributes);
|
2976
|
-
await async.map(localeEntriesToUpdate, async (entry) => {
|
2977
|
-
const transformedData = await strapi.documents.utils.transformData(
|
2978
|
-
cloneDeep(nonLocalizedAttributes),
|
2979
|
-
{
|
2980
|
-
uid,
|
2981
|
-
status,
|
2982
|
-
locale: entry.locale,
|
2983
|
-
allowMissingId: true
|
2984
|
-
}
|
2985
|
-
);
|
2986
|
-
const componentData = await strapi.documents(uid).updateComponents(entry, transformedData);
|
2987
|
-
await strapi.db.query(uid).update({
|
2988
|
-
where: {
|
2989
|
-
documentId,
|
2990
|
-
publishedAt: status === "published" ? { $ne: null } : null,
|
2991
|
-
locale: { $eq: entry.locale }
|
2992
|
-
},
|
2993
|
-
// The data we send to the update function is the entry data merged with
|
2994
|
-
// the updated component data
|
2995
|
-
data: Object.assign(cloneDeep(entryData), componentData)
|
2996
|
-
});
|
2997
|
-
});
|
2944
|
+
return {
|
2945
|
+
code: "en",
|
2946
|
+
name: "English (en)"
|
2947
|
+
};
|
2998
2948
|
};
|
2999
|
-
const
|
3000
|
-
syncNonLocalizedAttributes
|
3001
|
-
});
|
2949
|
+
const DEFAULT_LOCALE = getInitLocale();
|
3002
2950
|
const find = (params = {}) => strapi.db.query("plugin::i18n.locale").findMany({ where: params });
|
3003
2951
|
const findById = (id) => strapi.db.query("plugin::i18n.locale").findOne({ where: { id } });
|
3004
2952
|
const findByCode = (code) => strapi.db.query("plugin::i18n.locale").findOne({ where: { code } });
|
@@ -3190,11 +3138,32 @@ const contentTypes = () => ({
|
|
3190
3138
|
fillNonLocalizedAttributes,
|
3191
3139
|
getNestedPopulateOfNonLocalizedAttributes
|
3192
3140
|
});
|
3141
|
+
const LOCALIZATION_FIELDS = ["locale", "localizations"];
|
3142
|
+
const sanitize = ({ strapi: strapi2 }) => {
|
3143
|
+
const { isLocalizedContentType: isLocalizedContentType2 } = getService("content-types");
|
3144
|
+
const sanitizeLocalizationFields = curry(
|
3145
|
+
(schema2, entity) => traverseEntity(
|
3146
|
+
({ key, schema: schema22 }, { remove }) => {
|
3147
|
+
const isLocalized = isLocalizedContentType2(schema22);
|
3148
|
+
const isLocalizationField = LOCALIZATION_FIELDS.includes(key);
|
3149
|
+
if (!isLocalized && isLocalizationField) {
|
3150
|
+
remove(key);
|
3151
|
+
}
|
3152
|
+
},
|
3153
|
+
{ schema: schema2, getModel: strapi2.getModel.bind(strapi2) },
|
3154
|
+
entity
|
3155
|
+
)
|
3156
|
+
);
|
3157
|
+
return {
|
3158
|
+
sanitizeLocalizationFields
|
3159
|
+
};
|
3160
|
+
};
|
3193
3161
|
const services = {
|
3194
3162
|
permissions,
|
3195
3163
|
metrics,
|
3196
3164
|
localizations,
|
3197
3165
|
locales,
|
3166
|
+
sanitize,
|
3198
3167
|
"iso-locales": isoLocalesService,
|
3199
3168
|
"content-types": contentTypes
|
3200
3169
|
};
|