@strapi/i18n 0.0.0-experimental.7b750d18de359d0a42233cb8707e3c31c5983345 → 0.0.0-experimental.7bd770909ce799cf6fc76b7ebccd6d3ce2e377b5

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.
Files changed (40) hide show
  1. package/dist/_chunks/{SettingsPage-BIZrSFGY.mjs → SettingsPage-BAx9nmep.mjs} +4 -4
  2. package/dist/_chunks/SettingsPage-BAx9nmep.mjs.map +1 -0
  3. package/dist/_chunks/{SettingsPage-kMDCxWLw.js → SettingsPage-BTgjb2KS.js} +5 -6
  4. package/dist/_chunks/SettingsPage-BTgjb2KS.js.map +1 -0
  5. package/dist/_chunks/{en-B6327hMz.js → en-BKBz3tro.js} +4 -3
  6. package/dist/_chunks/en-BKBz3tro.js.map +1 -0
  7. package/dist/_chunks/{en-DZXpOMHo.mjs → en-DlXfy6Gy.mjs} +4 -3
  8. package/dist/_chunks/en-DlXfy6Gy.mjs.map +1 -0
  9. package/dist/_chunks/{index-Dncj9Inq.js → index-3yyF237r.js} +83 -32
  10. package/dist/_chunks/index-3yyF237r.js.map +1 -0
  11. package/dist/_chunks/{index-DXrgAtCA.mjs → index-B0NijiBB.mjs} +83 -31
  12. package/dist/_chunks/index-B0NijiBB.mjs.map +1 -0
  13. package/dist/admin/index.js +1 -1
  14. package/dist/admin/index.mjs +1 -1
  15. package/dist/admin/src/components/CMHeaderActions.d.ts +5 -3
  16. package/dist/admin/src/components/CreateLocale.d.ts +6 -6
  17. package/dist/server/index.js +390 -423
  18. package/dist/server/index.js.map +1 -1
  19. package/dist/server/index.mjs +391 -423
  20. package/dist/server/index.mjs.map +1 -1
  21. package/dist/server/src/index.d.ts +6 -0
  22. package/dist/server/src/index.d.ts.map +1 -1
  23. package/dist/server/src/register.d.ts.map +1 -1
  24. package/dist/server/src/services/index.d.ts +6 -0
  25. package/dist/server/src/services/index.d.ts.map +1 -1
  26. package/dist/server/src/services/sanitize/index.d.ts +11 -0
  27. package/dist/server/src/services/sanitize/index.d.ts.map +1 -0
  28. package/dist/server/src/utils/index.d.ts +2 -0
  29. package/dist/server/src/utils/index.d.ts.map +1 -1
  30. package/package.json +13 -13
  31. package/dist/_chunks/SettingsPage-BIZrSFGY.mjs.map +0 -1
  32. package/dist/_chunks/SettingsPage-kMDCxWLw.js.map +0 -1
  33. package/dist/_chunks/en-B6327hMz.js.map +0 -1
  34. package/dist/_chunks/en-DZXpOMHo.mjs.map +0 -1
  35. package/dist/_chunks/index-DXrgAtCA.mjs.map +0 -1
  36. package/dist/_chunks/index-Dncj9Inq.js.map +0 -1
  37. package/dist/server/src/migrations/content-type/disable/index.d.ts +0 -3
  38. package/dist/server/src/migrations/content-type/disable/index.d.ts.map +0 -1
  39. package/dist/server/src/migrations/content-type/enable/index.d.ts +0 -3
  40. package/dist/server/src/migrations/content-type/enable/index.d.ts.map +0 -1
@@ -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,439 +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
- useJoinColumn: false,
2696
- joinColumn: {
2697
- name: "document_id",
2698
- referencedColumn: "document_id",
2699
- referencedTable: strapi2.db.metadata.identifiers.getTableName(contentType.collectionName),
2700
- // ensure the population will not include the results we already loaded
2701
- on({ results }) {
2702
- return {
2703
- id: {
2704
- $notIn: results.map((r) => r.id)
2705
- }
2706
- };
2707
- }
2708
- }
2709
- });
2710
- });
2711
- if (strapi2.plugin("graphql")) {
2712
- graphqlProvider({ strapi: strapi2 }).register();
2713
- }
2714
- };
2715
- const info = {
2716
- singularName: "locale",
2717
- pluralName: "locales",
2718
- collectionName: "locales",
2719
- displayName: "Locale",
2720
- description: ""
2721
- };
2722
- const options = {};
2723
- const pluginOptions = {
2724
- "content-manager": {
2725
- visible: false
2726
- },
2727
- "content-type-builder": {
2728
- visible: false
2729
- }
2730
- };
2731
- const attributes = {
2732
- name: {
2733
- type: "string",
2734
- min: 1,
2735
- max: 50,
2736
- configurable: false
2737
- },
2738
- code: {
2739
- type: "string",
2740
- unique: true,
2741
- configurable: false
2742
- }
2743
- };
2744
- const schema = {
2745
- info,
2746
- options,
2747
- pluginOptions,
2748
- attributes
2749
- };
2750
- const locale = {
2751
- schema
2752
- };
2753
- const contentTypes$1 = {
2754
- locale
2755
- };
2756
- const actions = [
2757
- {
2758
- section: "settings",
2759
- category: "Internationalization",
2760
- subCategory: "Locales",
2761
- pluginName: "i18n",
2762
- displayName: "Create",
2763
- uid: "locale.create"
2916
+ {
2917
+ code: "dje",
2918
+ name: "Zarma (dje)"
2764
2919
  },
2765
2920
  {
2766
- section: "settings",
2767
- category: "Internationalization",
2768
- subCategory: "Locales",
2769
- pluginName: "i18n",
2770
- displayName: "Read",
2771
- uid: "locale.read",
2772
- aliases: [
2773
- { actionId: "plugin::content-manager.explorer.read", subjects: ["plugin::i18n.locale"] }
2774
- ]
2921
+ code: "dje-NE",
2922
+ name: "Zarma (Niger) (dje-NE)"
2775
2923
  },
2776
2924
  {
2777
- section: "settings",
2778
- category: "Internationalization",
2779
- subCategory: "Locales",
2780
- pluginName: "i18n",
2781
- displayName: "Update",
2782
- uid: "locale.update"
2925
+ code: "zu",
2926
+ name: "Zulu (zu)"
2783
2927
  },
2784
2928
  {
2785
- section: "settings",
2786
- category: "Internationalization",
2787
- subCategory: "Locales",
2788
- pluginName: "i18n",
2789
- displayName: "Delete",
2790
- uid: "locale.delete"
2929
+ code: "zu-ZA",
2930
+ name: "Zulu (South Africa) (zu-ZA)"
2791
2931
  }
2792
2932
  ];
2793
- const addLocalesPropertyIfNeeded = ({ value: action }) => {
2794
- const {
2795
- section,
2796
- options: { applyToProperties }
2797
- } = action;
2798
- if (section !== "contentTypes") {
2799
- return;
2800
- }
2801
- if (isArray(applyToProperties) && applyToProperties.includes("locales")) {
2802
- return;
2803
- }
2804
- action.options.applyToProperties = isArray(applyToProperties) ? applyToProperties.concat("locales") : ["locales"];
2805
- };
2806
- const shouldApplyLocalesPropertyToSubject = ({ property, subject }) => {
2807
- if (property === "locales") {
2808
- const model = strapi.getModel(subject);
2809
- return getService("content-types").isLocalizedContentType(model);
2810
- }
2811
- return true;
2812
- };
2813
- const addAllLocalesToPermissions = async (permissions2) => {
2814
- const { actionProvider } = strapi.service("admin::permission");
2815
- const { find: findAllLocales } = getService("locales");
2816
- const allLocales = await findAllLocales();
2817
- const allLocalesCode = allLocales.map(prop("code"));
2818
- return Promise.all(
2819
- permissions2.map(async (permission) => {
2820
- const { action, subject } = permission;
2821
- const appliesToLocalesProperty = await actionProvider.appliesToProperty(
2822
- "locales",
2823
- action,
2824
- 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"
2825
2940
  );
2826
- if (!appliesToLocalesProperty) {
2827
- return permission;
2828
- }
2829
- const oldPermissionProperties = getOr({}, "properties", permission);
2830
- return { ...permission, properties: { ...oldPermissionProperties, locales: allLocalesCode } };
2831
- })
2832
- );
2833
- };
2834
- const syncSuperAdminPermissionsWithLocales = async () => {
2835
- const roleService = strapi.service("admin::role");
2836
- const permissionService = strapi.service("admin::permission");
2837
- const superAdminRole = await roleService.getSuperAdmin();
2838
- if (!superAdminRole) {
2839
- return;
2840
- }
2841
- const superAdminPermissions = await permissionService.findMany({
2842
- where: {
2843
- role: {
2844
- id: superAdminRole.id
2845
- }
2846
- }
2847
- });
2848
- const newSuperAdminPermissions = await addAllLocalesToPermissions(superAdminPermissions);
2849
- await roleService.assignPermissions(superAdminRole.id, newSuperAdminPermissions);
2850
- };
2851
- const registerI18nActions = async () => {
2852
- const { actionProvider } = strapi.service("admin::permission");
2853
- await actionProvider.registerMany(actions);
2854
- };
2855
- const registerI18nActionsHooks = () => {
2856
- const { actionProvider } = strapi.service("admin::permission");
2857
- const { hooks } = strapi.service("admin::role");
2858
- actionProvider.hooks.appliesPropertyToSubject.register(shouldApplyLocalesPropertyToSubject);
2859
- hooks.willResetSuperAdminPermissions.register(addAllLocalesToPermissions);
2860
- };
2861
- const updateActionsProperties = () => {
2862
- const { actionProvider } = strapi.service("admin::permission");
2863
- actionProvider.hooks.willRegister.register(addLocalesPropertyIfNeeded);
2864
- actionProvider.values().forEach((action) => addLocalesPropertyIfNeeded({ value: action }));
2865
- };
2866
- const i18nActionsService = {
2867
- actions,
2868
- registerI18nActions,
2869
- registerI18nActionsHooks,
2870
- updateActionsProperties,
2871
- syncSuperAdminPermissionsWithLocales
2872
- };
2873
- const localesPropertyHandler = async ({ action, section }) => {
2874
- const { actionProvider } = strapi.service("admin::permission");
2875
- const locales2 = await getService("locales").find();
2876
- if (isEmpty(locales2)) {
2877
- return;
2878
- }
2879
- for (const subject of section.subjects) {
2880
- const applies = await actionProvider.appliesToProperty("locales", action.actionId, subject.uid);
2881
- const hasLocalesProperty = subject.properties.find(
2882
- (property) => property.value === "locales"
2883
- );
2884
- if (applies && !hasLocalesProperty) {
2885
- subject.properties.push({
2886
- label: "Locales",
2887
- value: "locales",
2888
- children: locales2.map(({ name, code }) => ({ label: name || code, value: code }))
2889
- });
2890
- }
2891
- }
2892
- };
2893
- const registerLocalesPropertyHandler = () => {
2894
- const { sectionsBuilder } = strapi.service("admin::permission");
2895
- sectionsBuilder.addHandler("singleTypes", localesPropertyHandler);
2896
- sectionsBuilder.addHandler("collectionTypes", localesPropertyHandler);
2897
- };
2898
- const sectionsBuilderService = {
2899
- localesPropertyHandler,
2900
- registerLocalesPropertyHandler
2901
- };
2902
- const willRegisterPermission = (context) => {
2903
- const { permission, condition, user } = context;
2904
- const { subject, properties } = permission;
2905
- const isSuperAdmin = strapi.service("admin::role").hasSuperAdminRole(user);
2906
- if (isSuperAdmin) {
2907
- return;
2908
- }
2909
- const { locales: locales2 } = properties || {};
2910
- const { isLocalizedContentType: isLocalizedContentType2 } = getService("content-types");
2911
- if (!subject) {
2912
- return;
2913
- }
2914
- const ct = strapi.contentTypes[subject];
2915
- if (!isLocalizedContentType2(ct)) {
2916
- return;
2917
- }
2918
- if (locales2 === null) {
2919
- return;
2920
- }
2921
- condition.and({
2922
- locale: {
2923
- $in: locales2 || []
2924
2941
  }
2925
- });
2926
- };
2927
- const registerI18nPermissionsHandlers = () => {
2928
- const { engine } = strapi.service("admin::permission");
2929
- engine.hooks["before-register.permission"].register(willRegisterPermission);
2930
- };
2931
- const engineService = {
2932
- willRegisterPermission,
2933
- registerI18nPermissionsHandlers
2934
- };
2935
- const permissions = () => ({
2936
- actions: i18nActionsService,
2937
- sectionsBuilder: sectionsBuilderService,
2938
- engine: engineService
2939
- });
2940
- const sendDidInitializeEvent = async () => {
2941
- const { isLocalizedContentType: isLocalizedContentType2 } = getService("content-types");
2942
- const numberOfContentTypes = reduce(
2943
- (sum, contentType) => isLocalizedContentType2(contentType) ? sum + 1 : sum,
2944
- 0
2945
- )(strapi.contentTypes);
2946
- await strapi.telemetry.send("didInitializeI18n", { groupProperties: { numberOfContentTypes } });
2947
- };
2948
- const sendDidUpdateI18nLocalesEvent = async () => {
2949
- const numberOfLocales = await getService("locales").count();
2950
- await strapi.telemetry.send("didUpdateI18nLocales", {
2951
- groupProperties: { numberOfLocales }
2952
- });
2953
- };
2954
- const metrics = () => ({
2955
- sendDidInitializeEvent,
2956
- sendDidUpdateI18nLocalesEvent
2957
- });
2958
- const syncNonLocalizedAttributes = async (sourceEntry, model) => {
2959
- const { copyNonLocalizedAttributes: copyNonLocalizedAttributes2 } = getService("content-types");
2960
- const nonLocalizedAttributes = copyNonLocalizedAttributes2(model, sourceEntry);
2961
- if (isEmpty(nonLocalizedAttributes)) {
2962
- return;
2942
+ return { ...matchingLocale };
2963
2943
  }
2964
- const uid = model.uid;
2965
- const documentId = sourceEntry.documentId;
2966
- const locale2 = sourceEntry.locale;
2967
- const status = sourceEntry?.publishedAt ? "published" : "draft";
2968
- const localeEntriesToUpdate = await strapi.db.query(uid).findMany({
2969
- where: {
2970
- documentId,
2971
- publishedAt: status === "published" ? { $ne: null } : null,
2972
- locale: { $ne: locale2 }
2973
- },
2974
- select: ["locale", "id"]
2975
- });
2976
- const entryData = await strapi.documents(uid).omitComponentData(nonLocalizedAttributes);
2977
- await async.map(localeEntriesToUpdate, async (entry) => {
2978
- const transformedData = await strapi.documents.utils.transformData(
2979
- cloneDeep(nonLocalizedAttributes),
2980
- {
2981
- uid,
2982
- status,
2983
- locale: entry.locale,
2984
- allowMissingId: true
2985
- }
2986
- );
2987
- const componentData = await strapi.documents(uid).updateComponents(entry, transformedData);
2988
- await strapi.db.query(uid).update({
2989
- where: {
2990
- documentId,
2991
- publishedAt: status === "published" ? { $ne: null } : null,
2992
- locale: { $eq: entry.locale }
2993
- },
2994
- // The data we send to the update function is the entry data merged with
2995
- // the updated component data
2996
- data: Object.assign(cloneDeep(entryData), componentData)
2997
- });
2998
- });
2944
+ return {
2945
+ code: "en",
2946
+ name: "English (en)"
2947
+ };
2999
2948
  };
3000
- const localizations = () => ({
3001
- syncNonLocalizedAttributes
3002
- });
2949
+ const DEFAULT_LOCALE = getInitLocale();
3003
2950
  const find = (params = {}) => strapi.db.query("plugin::i18n.locale").findMany({ where: params });
3004
2951
  const findById = (id) => strapi.db.query("plugin::i18n.locale").findOne({ where: { id } });
3005
2952
  const findByCode = (code) => strapi.db.query("plugin::i18n.locale").findOne({ where: { code } });
@@ -3191,11 +3138,32 @@ const contentTypes = () => ({
3191
3138
  fillNonLocalizedAttributes,
3192
3139
  getNestedPopulateOfNonLocalizedAttributes
3193
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
+ };
3194
3161
  const services = {
3195
3162
  permissions,
3196
3163
  metrics,
3197
3164
  localizations,
3198
3165
  locales,
3166
+ sanitize,
3199
3167
  "iso-locales": isoLocalesService,
3200
3168
  "content-types": contentTypes
3201
3169
  };