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