@strapi/i18n 0.0.0-experimental.145e7d7ddefd1aef71aaf3d9bb86440d013035bf → 0.0.0-experimental.1610404a03d98b65f497f9adda35815021b8fd76

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 (44) hide show
  1. package/dist/_chunks/{SettingsPage-CPNFX0bZ.mjs → SettingsPage-BWEhlJzY.mjs} +4 -4
  2. package/dist/_chunks/SettingsPage-BWEhlJzY.mjs.map +1 -0
  3. package/dist/_chunks/{SettingsPage-C-1h_H38.js → SettingsPage-DqW7hbxl.js} +5 -6
  4. package/dist/_chunks/SettingsPage-DqW7hbxl.js.map +1 -0
  5. package/dist/_chunks/{en-CwI88-PP.js → en-BKBz3tro.js} +10 -4
  6. package/dist/_chunks/en-BKBz3tro.js.map +1 -0
  7. package/dist/_chunks/{en-CtekP_47.mjs → en-DlXfy6Gy.mjs} +10 -4
  8. package/dist/_chunks/en-DlXfy6Gy.mjs.map +1 -0
  9. package/dist/_chunks/{index-jpk39Rxo.js → index-93hDLj9o.js} +267 -41
  10. package/dist/_chunks/index-93hDLj9o.js.map +1 -0
  11. package/dist/_chunks/{index-CgjpU2bY.mjs → index-C6Fyjx-i.mjs} +269 -42
  12. package/dist/_chunks/index-C6Fyjx-i.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 +28 -3
  16. package/dist/admin/src/components/CreateLocale.d.ts +6 -6
  17. package/dist/admin/src/utils/clean.d.ts +4 -0
  18. package/dist/server/index.js +368 -488
  19. package/dist/server/index.js.map +1 -1
  20. package/dist/server/index.mjs +368 -487
  21. package/dist/server/index.mjs.map +1 -1
  22. package/dist/server/src/bootstrap.d.ts +1 -4
  23. package/dist/server/src/bootstrap.d.ts.map +1 -1
  24. package/dist/server/src/index.d.ts +1 -11
  25. package/dist/server/src/index.d.ts.map +1 -1
  26. package/dist/server/src/register.d.ts.map +1 -1
  27. package/dist/server/src/services/index.d.ts +0 -8
  28. package/dist/server/src/services/index.d.ts.map +1 -1
  29. package/dist/server/src/utils/index.d.ts +0 -2
  30. package/dist/server/src/utils/index.d.ts.map +1 -1
  31. package/package.json +10 -10
  32. package/dist/_chunks/SettingsPage-C-1h_H38.js.map +0 -1
  33. package/dist/_chunks/SettingsPage-CPNFX0bZ.mjs.map +0 -1
  34. package/dist/_chunks/en-CtekP_47.mjs.map +0 -1
  35. package/dist/_chunks/en-CwI88-PP.js.map +0 -1
  36. package/dist/_chunks/index-CgjpU2bY.mjs.map +0 -1
  37. package/dist/_chunks/index-jpk39Rxo.js.map +0 -1
  38. package/dist/server/src/migrations/content-type/disable/index.d.ts +0 -3
  39. package/dist/server/src/migrations/content-type/disable/index.d.ts.map +0 -1
  40. package/dist/server/src/migrations/content-type/enable/index.d.ts +0 -3
  41. package/dist/server/src/migrations/content-type/enable/index.d.ts.map +0 -1
  42. package/dist/server/src/services/entity-service-decorator.d.ts +0 -29
  43. package/dist/server/src/services/entity-service-decorator.d.ts.map +0 -1
  44. package/strapi-server.js +0 -3
@@ -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) {
@@ -51,7 +50,7 @@ const registerModelsHooks = () => {
51
50
  const attributesToPopulate = getNestedPopulateOfNonLocalizedAttributes2(schema2.uid);
52
51
  const result = await next();
53
52
  let resultID;
54
- if (Array.isArray(result?.entries)) {
53
+ if (Array.isArray(result?.entries) && result.entries[0]?.id) {
55
54
  resultID = result.entries[0].id;
56
55
  } else if (result?.id) {
57
56
  resultID = result.id;
@@ -65,12 +64,10 @@ const registerModelsHooks = () => {
65
64
  return result;
66
65
  });
67
66
  };
68
- const bootstrap = async ({ strapi: strapi2 }) => {
67
+ const bootstrap = async () => {
69
68
  const { sendDidInitializeEvent: sendDidInitializeEvent2 } = getService("metrics");
70
- const { decorator: decorator2 } = getService("entity-service-decorator");
71
69
  const { initDefaultLocale: initDefaultLocale2 } = getService("locales");
72
70
  const { sectionsBuilder, actions: actions2, engine } = getService("permissions");
73
- strapi2.entityService.decorate(decorator2);
74
71
  await initDefaultLocale2();
75
72
  sectionsBuilder.registerLocalesPropertyHandler();
76
73
  await actions2.registerI18nActions();
@@ -197,6 +194,350 @@ const getI18nLocaleArgPlugin = ({ nexus, typeRegistry }) => {
197
194
  }
198
195
  });
199
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
+ Object.values(strapi2.contentTypes).forEach((contentType) => {
217
+ const { attributes: attributes2 } = contentType;
218
+ ___default.default.set(attributes2, "locale", {
219
+ writable: true,
220
+ private: false,
221
+ configurable: false,
222
+ visible: false,
223
+ type: "string"
224
+ });
225
+ ___default.default.set(attributes2, "localizations", {
226
+ type: "relation",
227
+ relation: "oneToMany",
228
+ target: contentType.uid,
229
+ writable: false,
230
+ private: false,
231
+ configurable: false,
232
+ visible: false,
233
+ unstable_virtual: true,
234
+ joinColumn: {
235
+ name: "document_id",
236
+ referencedColumn: "document_id",
237
+ referencedTable: strapi2.db.metadata.identifiers.getTableName(contentType.collectionName),
238
+ // ensure the population will not include the results we already loaded
239
+ on({ results }) {
240
+ return {
241
+ id: {
242
+ $notIn: results.map((r) => r.id)
243
+ }
244
+ };
245
+ }
246
+ }
247
+ });
248
+ });
249
+ if (strapi2.plugin("graphql")) {
250
+ graphqlProvider({ strapi: strapi2 }).register();
251
+ }
252
+ };
253
+ const info = {
254
+ singularName: "locale",
255
+ pluralName: "locales",
256
+ collectionName: "locales",
257
+ displayName: "Locale",
258
+ description: ""
259
+ };
260
+ const options = {};
261
+ const pluginOptions = {
262
+ "content-manager": {
263
+ visible: false
264
+ },
265
+ "content-type-builder": {
266
+ visible: false
267
+ }
268
+ };
269
+ const attributes = {
270
+ name: {
271
+ type: "string",
272
+ min: 1,
273
+ max: 50,
274
+ configurable: false
275
+ },
276
+ code: {
277
+ type: "string",
278
+ unique: true,
279
+ configurable: false
280
+ }
281
+ };
282
+ const schema = {
283
+ info,
284
+ options,
285
+ pluginOptions,
286
+ attributes
287
+ };
288
+ const locale = {
289
+ schema
290
+ };
291
+ const contentTypes$1 = {
292
+ locale
293
+ };
294
+ const actions = [
295
+ {
296
+ section: "settings",
297
+ category: "Internationalization",
298
+ subCategory: "Locales",
299
+ pluginName: "i18n",
300
+ displayName: "Create",
301
+ uid: "locale.create"
302
+ },
303
+ {
304
+ section: "settings",
305
+ category: "Internationalization",
306
+ subCategory: "Locales",
307
+ pluginName: "i18n",
308
+ displayName: "Read",
309
+ uid: "locale.read",
310
+ aliases: [
311
+ { actionId: "plugin::content-manager.explorer.read", subjects: ["plugin::i18n.locale"] }
312
+ ]
313
+ },
314
+ {
315
+ section: "settings",
316
+ category: "Internationalization",
317
+ subCategory: "Locales",
318
+ pluginName: "i18n",
319
+ displayName: "Update",
320
+ uid: "locale.update"
321
+ },
322
+ {
323
+ section: "settings",
324
+ category: "Internationalization",
325
+ subCategory: "Locales",
326
+ pluginName: "i18n",
327
+ displayName: "Delete",
328
+ uid: "locale.delete"
329
+ }
330
+ ];
331
+ const addLocalesPropertyIfNeeded = ({ value: action }) => {
332
+ const {
333
+ section,
334
+ options: { applyToProperties }
335
+ } = action;
336
+ if (section !== "contentTypes") {
337
+ return;
338
+ }
339
+ if (fp.isArray(applyToProperties) && applyToProperties.includes("locales")) {
340
+ return;
341
+ }
342
+ action.options.applyToProperties = fp.isArray(applyToProperties) ? applyToProperties.concat("locales") : ["locales"];
343
+ };
344
+ const shouldApplyLocalesPropertyToSubject = ({ property, subject }) => {
345
+ if (property === "locales") {
346
+ const model = strapi.getModel(subject);
347
+ return getService("content-types").isLocalizedContentType(model);
348
+ }
349
+ return true;
350
+ };
351
+ const addAllLocalesToPermissions = async (permissions2) => {
352
+ const { actionProvider } = strapi.service("admin::permission");
353
+ const { find: findAllLocales } = getService("locales");
354
+ const allLocales = await findAllLocales();
355
+ const allLocalesCode = allLocales.map(fp.prop("code"));
356
+ return Promise.all(
357
+ permissions2.map(async (permission) => {
358
+ const { action, subject } = permission;
359
+ const appliesToLocalesProperty = await actionProvider.appliesToProperty(
360
+ "locales",
361
+ action,
362
+ subject
363
+ );
364
+ if (!appliesToLocalesProperty) {
365
+ return permission;
366
+ }
367
+ const oldPermissionProperties = fp.getOr({}, "properties", permission);
368
+ return { ...permission, properties: { ...oldPermissionProperties, locales: allLocalesCode } };
369
+ })
370
+ );
371
+ };
372
+ const syncSuperAdminPermissionsWithLocales = async () => {
373
+ const roleService = strapi.service("admin::role");
374
+ const permissionService = strapi.service("admin::permission");
375
+ const superAdminRole = await roleService.getSuperAdmin();
376
+ if (!superAdminRole) {
377
+ return;
378
+ }
379
+ const superAdminPermissions = await permissionService.findMany({
380
+ where: {
381
+ role: {
382
+ id: superAdminRole.id
383
+ }
384
+ }
385
+ });
386
+ const newSuperAdminPermissions = await addAllLocalesToPermissions(superAdminPermissions);
387
+ await roleService.assignPermissions(superAdminRole.id, newSuperAdminPermissions);
388
+ };
389
+ const registerI18nActions = async () => {
390
+ const { actionProvider } = strapi.service("admin::permission");
391
+ await actionProvider.registerMany(actions);
392
+ };
393
+ const registerI18nActionsHooks = () => {
394
+ const { actionProvider } = strapi.service("admin::permission");
395
+ const { hooks } = strapi.service("admin::role");
396
+ actionProvider.hooks.appliesPropertyToSubject.register(shouldApplyLocalesPropertyToSubject);
397
+ hooks.willResetSuperAdminPermissions.register(addAllLocalesToPermissions);
398
+ };
399
+ const updateActionsProperties = () => {
400
+ const { actionProvider } = strapi.service("admin::permission");
401
+ actionProvider.hooks.willRegister.register(addLocalesPropertyIfNeeded);
402
+ actionProvider.values().forEach((action) => addLocalesPropertyIfNeeded({ value: action }));
403
+ };
404
+ const i18nActionsService = {
405
+ actions,
406
+ registerI18nActions,
407
+ registerI18nActionsHooks,
408
+ updateActionsProperties,
409
+ syncSuperAdminPermissionsWithLocales
410
+ };
411
+ const localesPropertyHandler = async ({ action, section }) => {
412
+ const { actionProvider } = strapi.service("admin::permission");
413
+ const locales2 = await getService("locales").find();
414
+ if (fp.isEmpty(locales2)) {
415
+ return;
416
+ }
417
+ for (const subject of section.subjects) {
418
+ const applies = await actionProvider.appliesToProperty("locales", action.actionId, subject.uid);
419
+ const hasLocalesProperty = subject.properties.find(
420
+ (property) => property.value === "locales"
421
+ );
422
+ if (applies && !hasLocalesProperty) {
423
+ subject.properties.push({
424
+ label: "Locales",
425
+ value: "locales",
426
+ children: locales2.map(({ name, code }) => ({ label: name || code, value: code }))
427
+ });
428
+ }
429
+ }
430
+ };
431
+ const registerLocalesPropertyHandler = () => {
432
+ const { sectionsBuilder } = strapi.service("admin::permission");
433
+ sectionsBuilder.addHandler("singleTypes", localesPropertyHandler);
434
+ sectionsBuilder.addHandler("collectionTypes", localesPropertyHandler);
435
+ };
436
+ const sectionsBuilderService = {
437
+ localesPropertyHandler,
438
+ registerLocalesPropertyHandler
439
+ };
440
+ const willRegisterPermission = (context) => {
441
+ const { permission, condition, user } = context;
442
+ const { subject, properties } = permission;
443
+ const isSuperAdmin = strapi.service("admin::role").hasSuperAdminRole(user);
444
+ if (isSuperAdmin) {
445
+ return;
446
+ }
447
+ const { locales: locales2 } = properties || {};
448
+ const { isLocalizedContentType: isLocalizedContentType2 } = getService("content-types");
449
+ if (!subject) {
450
+ return;
451
+ }
452
+ const ct = strapi.contentTypes[subject];
453
+ if (!isLocalizedContentType2(ct)) {
454
+ return;
455
+ }
456
+ if (locales2 === null) {
457
+ return;
458
+ }
459
+ condition.and({
460
+ locale: {
461
+ $in: locales2 || []
462
+ }
463
+ });
464
+ };
465
+ const registerI18nPermissionsHandlers = () => {
466
+ const { engine } = strapi.service("admin::permission");
467
+ engine.hooks["before-register.permission"].register(willRegisterPermission);
468
+ };
469
+ const engineService = {
470
+ willRegisterPermission,
471
+ registerI18nPermissionsHandlers
472
+ };
473
+ const permissions = () => ({
474
+ actions: i18nActionsService,
475
+ sectionsBuilder: sectionsBuilderService,
476
+ engine: engineService
477
+ });
478
+ const sendDidInitializeEvent = async () => {
479
+ const { isLocalizedContentType: isLocalizedContentType2 } = getService("content-types");
480
+ const numberOfContentTypes = fp.reduce(
481
+ (sum, contentType) => isLocalizedContentType2(contentType) ? sum + 1 : sum,
482
+ 0
483
+ )(strapi.contentTypes);
484
+ await strapi.telemetry.send("didInitializeI18n", { groupProperties: { numberOfContentTypes } });
485
+ };
486
+ const sendDidUpdateI18nLocalesEvent = async () => {
487
+ const numberOfLocales = await getService("locales").count();
488
+ await strapi.telemetry.send("didUpdateI18nLocales", {
489
+ groupProperties: { numberOfLocales }
490
+ });
491
+ };
492
+ const metrics = () => ({
493
+ sendDidInitializeEvent,
494
+ sendDidUpdateI18nLocalesEvent
495
+ });
496
+ const syncNonLocalizedAttributes = async (sourceEntry, model) => {
497
+ const { copyNonLocalizedAttributes: copyNonLocalizedAttributes2 } = getService("content-types");
498
+ const nonLocalizedAttributes = copyNonLocalizedAttributes2(model, sourceEntry);
499
+ if (fp.isEmpty(nonLocalizedAttributes)) {
500
+ return;
501
+ }
502
+ const uid = model.uid;
503
+ const documentId = sourceEntry.documentId;
504
+ const locale2 = sourceEntry.locale;
505
+ const status = sourceEntry?.publishedAt ? "published" : "draft";
506
+ const localeEntriesToUpdate = await strapi.db.query(uid).findMany({
507
+ where: {
508
+ documentId,
509
+ publishedAt: status === "published" ? { $ne: null } : null,
510
+ locale: { $ne: locale2 }
511
+ },
512
+ select: ["locale", "id"]
513
+ });
514
+ const entryData = await strapi.documents(uid).omitComponentData(nonLocalizedAttributes);
515
+ await utils.async.map(localeEntriesToUpdate, async (entry) => {
516
+ const transformedData = await strapi.documents.utils.transformData(
517
+ fp.cloneDeep(nonLocalizedAttributes),
518
+ {
519
+ uid,
520
+ status,
521
+ locale: entry.locale,
522
+ allowMissingId: true
523
+ }
524
+ );
525
+ const componentData = await strapi.documents(uid).updateComponents(entry, transformedData);
526
+ await strapi.db.query(uid).update({
527
+ where: {
528
+ documentId,
529
+ publishedAt: status === "published" ? { $ne: null } : null,
530
+ locale: { $eq: entry.locale }
531
+ },
532
+ // The data we send to the update function is the entry data merged with
533
+ // the updated component data
534
+ data: Object.assign(fp.cloneDeep(entryData), componentData)
535
+ });
536
+ });
537
+ };
538
+ const localizations = () => ({
539
+ syncNonLocalizedAttributes
540
+ });
200
541
  const isoLocales = [
201
542
  {
202
543
  code: "af",
@@ -2595,410 +2936,35 @@ const isoLocales = [
2595
2936
  name: "Zarma (dje)"
2596
2937
  },
2597
2938
  {
2598
- code: "dje-NE",
2599
- name: "Zarma (Niger) (dje-NE)"
2600
- },
2601
- {
2602
- code: "zu",
2603
- name: "Zulu (zu)"
2604
- },
2605
- {
2606
- code: "zu-ZA",
2607
- name: "Zulu (South Africa) (zu-ZA)"
2608
- }
2609
- ];
2610
- const getInitLocale = () => {
2611
- const envLocaleCode = process.env.STRAPI_PLUGIN_I18N_INIT_LOCALE_CODE;
2612
- if (envLocaleCode) {
2613
- const matchingLocale = isoLocales.find(({ code }) => code === envLocaleCode);
2614
- if (!matchingLocale) {
2615
- throw new Error(
2616
- "Unknown locale code provided in the environment variable STRAPI_PLUGIN_I18N_INIT_LOCALE_CODE"
2617
- );
2618
- }
2619
- return { ...matchingLocale };
2620
- }
2621
- return {
2622
- code: "en",
2623
- name: "English (en)"
2624
- };
2625
- };
2626
- const DEFAULT_LOCALE = getInitLocale();
2627
- const enableContentType = async ({ oldContentTypes, contentTypes: contentTypes2 }) => {
2628
- const { isLocalizedContentType: isLocalizedContentType2 } = getService("content-types");
2629
- const { getDefaultLocale: getDefaultLocale2 } = getService("locales");
2630
- if (!oldContentTypes) {
2631
- return;
2632
- }
2633
- for (const uid in contentTypes2) {
2634
- if (!oldContentTypes[uid]) {
2635
- continue;
2636
- }
2637
- const oldContentType = oldContentTypes[uid];
2638
- const contentType = contentTypes2[uid];
2639
- if (!isLocalizedContentType2(oldContentType) && isLocalizedContentType2(contentType)) {
2640
- const defaultLocale = await getDefaultLocale2() || DEFAULT_LOCALE.code;
2641
- await strapi.db.query(uid).updateMany({
2642
- where: { locale: null },
2643
- data: { locale: defaultLocale }
2644
- });
2645
- }
2646
- }
2647
- };
2648
- const disableContentType = async ({ oldContentTypes, contentTypes: contentTypes2 }) => {
2649
- const { isLocalizedContentType: isLocalizedContentType2 } = getService("content-types");
2650
- const { getDefaultLocale: getDefaultLocale2 } = getService("locales");
2651
- if (!oldContentTypes) {
2652
- return;
2653
- }
2654
- for (const uid in contentTypes2) {
2655
- if (!oldContentTypes[uid]) {
2656
- continue;
2657
- }
2658
- const oldContentType = oldContentTypes[uid];
2659
- const contentType = contentTypes2[uid];
2660
- if (isLocalizedContentType2(oldContentType) && !isLocalizedContentType2(contentType)) {
2661
- const defaultLocale = await getDefaultLocale2() || DEFAULT_LOCALE.code;
2662
- await Promise.all([
2663
- // Delete all entities that are not in the default locale
2664
- strapi.db.query(uid).deleteMany({
2665
- where: { locale: { $ne: defaultLocale } }
2666
- }),
2667
- // Set locale to null for the rest
2668
- strapi.db.query(uid).updateMany({
2669
- where: { locale: { $eq: defaultLocale } },
2670
- data: { locale: null }
2671
- })
2672
- ]);
2673
- }
2674
- }
2675
- };
2676
- const register = ({ strapi: strapi2 }) => {
2677
- extendContentTypes(strapi2);
2678
- addContentManagerLocaleMiddleware(strapi2);
2679
- addContentTypeSyncHooks(strapi2);
2680
- };
2681
- const addContentManagerLocaleMiddleware = (strapi2) => {
2682
- strapi2.server.router.use("/content-manager/collection-types/:model", (ctx, next) => {
2683
- if (ctx.method === "POST" || ctx.method === "PUT") {
2684
- return validateLocaleCreation(ctx, next);
2685
- }
2686
- return next();
2687
- });
2688
- strapi2.server.router.use("/content-manager/single-types/:model", (ctx, next) => {
2689
- if (ctx.method === "POST" || ctx.method === "PUT") {
2690
- return validateLocaleCreation(ctx, next);
2691
- }
2692
- return next();
2693
- });
2694
- };
2695
- const addContentTypeSyncHooks = (strapi2) => {
2696
- strapi2.hook("strapi::content-types.beforeSync").register(disableContentType);
2697
- strapi2.hook("strapi::content-types.afterSync").register(enableContentType);
2698
- };
2699
- const extendContentTypes = (strapi2) => {
2700
- Object.values(strapi2.contentTypes).forEach((contentType) => {
2701
- const { attributes: attributes2 } = contentType;
2702
- ___default.default.set(attributes2, "locale", {
2703
- writable: true,
2704
- private: false,
2705
- configurable: false,
2706
- visible: false,
2707
- type: "string"
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"
2763
- },
2764
- {
2765
- section: "settings",
2766
- category: "Internationalization",
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
- ]
2774
- },
2775
- {
2776
- section: "settings",
2777
- category: "Internationalization",
2778
- subCategory: "Locales",
2779
- pluginName: "i18n",
2780
- displayName: "Update",
2781
- uid: "locale.update"
2939
+ code: "dje-NE",
2940
+ name: "Zarma (Niger) (dje-NE)"
2782
2941
  },
2783
2942
  {
2784
- section: "settings",
2785
- category: "Internationalization",
2786
- subCategory: "Locales",
2787
- pluginName: "i18n",
2788
- displayName: "Delete",
2789
- uid: "locale.delete"
2943
+ code: "zu",
2944
+ name: "Zulu (zu)"
2945
+ },
2946
+ {
2947
+ code: "zu-ZA",
2948
+ name: "Zulu (South Africa) (zu-ZA)"
2790
2949
  }
2791
2950
  ];
2792
- const addLocalesPropertyIfNeeded = ({ value: action }) => {
2793
- const {
2794
- section,
2795
- options: { applyToProperties }
2796
- } = action;
2797
- if (section !== "contentTypes") {
2798
- return;
2799
- }
2800
- if (fp.isArray(applyToProperties) && applyToProperties.includes("locales")) {
2801
- return;
2802
- }
2803
- action.options.applyToProperties = fp.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(fp.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
2951
+ const getInitLocale = () => {
2952
+ const envLocaleCode = process.env.STRAPI_PLUGIN_I18N_INIT_LOCALE_CODE;
2953
+ if (envLocaleCode) {
2954
+ const matchingLocale = isoLocales.find(({ code }) => code === envLocaleCode);
2955
+ if (!matchingLocale) {
2956
+ throw new Error(
2957
+ "Unknown locale code provided in the environment variable STRAPI_PLUGIN_I18N_INIT_LOCALE_CODE"
2824
2958
  );
2825
- if (!appliesToLocalesProperty) {
2826
- return permission;
2827
- }
2828
- const oldPermissionProperties = fp.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 (fp.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
2959
  }
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 = fp.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 (fp.isEmpty(nonLocalizedAttributes)) {
2961
- return;
2960
+ return { ...matchingLocale };
2962
2961
  }
2963
- const uid = model.uid;
2964
- const documentId = sourceEntry.documentId;
2965
- const locale2 = sourceEntry.locale;
2966
- const status = sourceEntry?.publishedAt ? "published" : "draft";
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 utils.async.map(localeEntriesToUpdate, async (entry) => {
2977
- const transformedData = await strapi.documents.utils.transformData(
2978
- fp.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(fp.cloneDeep(entryData), componentData)
2996
- });
2997
- });
2962
+ return {
2963
+ code: "en",
2964
+ name: "English (en)"
2965
+ };
2998
2966
  };
2999
- const localizations = () => ({
3000
- syncNonLocalizedAttributes
3001
- });
2967
+ const DEFAULT_LOCALE = getInitLocale();
3002
2968
  const find = (params = {}) => strapi.db.query("plugin::i18n.locale").findMany({ where: params });
3003
2969
  const findById = (id) => strapi.db.query("plugin::i18n.locale").findOne({ where: { id } });
3004
2970
  const findByCode = (code) => strapi.db.query("plugin::i18n.locale").findOne({ where: { code } });
@@ -3066,91 +3032,6 @@ const getIsoLocales = () => isoLocales;
3066
3032
  const isoLocalesService = () => ({
3067
3033
  getIsoLocales
3068
3034
  });
3069
- const LOCALE_QUERY_FILTER = "locale";
3070
- const SINGLE_ENTRY_ACTIONS = ["findOne", "update", "delete"];
3071
- const BULK_ACTIONS = ["delete"];
3072
- const paramsContain = (key, params) => {
3073
- return fp.has(key, params.filters) || fp.isArray(params.filters) && params.filters.some((clause) => fp.has(key, clause)) || fp.isArray(fp.get("$and", params.filters)) && params.filters.$and.some((clause) => fp.has(key, clause));
3074
- };
3075
- const wrapParams = async (params = {}, ctx = {}) => {
3076
- const { action } = ctx;
3077
- if (fp.has(LOCALE_QUERY_FILTER, params)) {
3078
- if (params[LOCALE_QUERY_FILTER] === "all") {
3079
- return fp.omit(LOCALE_QUERY_FILTER, params);
3080
- }
3081
- return {
3082
- ...fp.omit(LOCALE_QUERY_FILTER, params),
3083
- filters: {
3084
- $and: [{ locale: params[LOCALE_QUERY_FILTER] }].concat(params.filters || [])
3085
- }
3086
- };
3087
- }
3088
- const entityDefinedById = paramsContain("id", params) && SINGLE_ENTRY_ACTIONS.includes(action);
3089
- const entitiesDefinedByIds = paramsContain("id.$in", params) && BULK_ACTIONS.includes(action);
3090
- if (entityDefinedById || entitiesDefinedByIds) {
3091
- return params;
3092
- }
3093
- const { getDefaultLocale: getDefaultLocale2 } = getService("locales");
3094
- return {
3095
- ...params,
3096
- filters: {
3097
- $and: [{ locale: await getDefaultLocale2() }].concat(params.filters || [])
3098
- }
3099
- };
3100
- };
3101
- const decorator = (service) => ({
3102
- /**
3103
- * Wraps result
3104
- * @param {object} result - result object of query
3105
- * @param {object} ctx - Query context
3106
- * @param {object} ctx.model - Model that is being used
3107
- */
3108
- async wrapResult(result = {}, ctx = {}) {
3109
- return service.wrapResult.call(this, result, ctx);
3110
- },
3111
- /**
3112
- * Wraps query options. In particular will add default locale to query params
3113
- * @param {object} params - Query options object (params, data, files, populate)
3114
- * @param {object} ctx - Query context
3115
- * @param {object} ctx.model - Model that is being used
3116
- */
3117
- async wrapParams(params = {}, ctx = {}) {
3118
- const wrappedParams = await service.wrapParams.call(this, params, ctx);
3119
- const model = strapi.getModel(ctx.uid);
3120
- const { isLocalizedContentType: isLocalizedContentType2 } = getService("content-types");
3121
- if (!isLocalizedContentType2(model)) {
3122
- return wrappedParams;
3123
- }
3124
- return wrapParams(wrappedParams, ctx);
3125
- },
3126
- /**
3127
- * Find an entry or several if fetching all locales
3128
- * @param {string} uid - Model uid
3129
- * @param {object} opts - Query options object (params, data, files, populate)
3130
- */
3131
- async findMany(uid, opts) {
3132
- const model = strapi.getModel(uid);
3133
- const { isLocalizedContentType: isLocalizedContentType2 } = getService("content-types");
3134
- if (!isLocalizedContentType2(model)) {
3135
- return service.findMany.call(this, uid, opts);
3136
- }
3137
- const { kind } = model;
3138
- if (kind === "singleType") {
3139
- if (opts[LOCALE_QUERY_FILTER] === "all") {
3140
- const wrappedParams = await this.wrapParams(opts, { uid, action: "findMany" });
3141
- const query = strapi.get("query-params").transform(uid, wrappedParams);
3142
- const entities = await strapi.db.query(uid).findMany(query);
3143
- return this.wrapResult(entities, { uid, action: "findMany" });
3144
- }
3145
- return service.findMany.call(this, uid, opts);
3146
- }
3147
- return service.findMany.call(this, uid, opts);
3148
- }
3149
- });
3150
- const entityServiceDecorator = () => ({
3151
- decorator,
3152
- wrapParams
3153
- });
3154
3035
  const {
3155
3036
  isRelationalAttribute,
3156
3037
  getVisibleAttributes,
@@ -3281,7 +3162,6 @@ const services = {
3281
3162
  localizations,
3282
3163
  locales,
3283
3164
  "iso-locales": isoLocalesService,
3284
- "entity-service-decorator": entityServiceDecorator,
3285
3165
  "content-types": contentTypes
3286
3166
  };
3287
3167
  const admin = {