@strapi/i18n 5.0.0-rc.9 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/_chunks/{SettingsPage-CbEn7zF5.mjs → SettingsPage-DbRFoF_H.mjs} +4 -4
  2. package/dist/_chunks/SettingsPage-DbRFoF_H.mjs.map +1 -0
  3. package/dist/_chunks/{SettingsPage-C0l7c5fn.js → SettingsPage-uGJv15wR.js} +4 -4
  4. package/dist/_chunks/SettingsPage-uGJv15wR.js.map +1 -0
  5. package/dist/_chunks/{en-CM6Pjfyv.mjs → en-BYRZFDBV.mjs} +9 -2
  6. package/dist/_chunks/en-BYRZFDBV.mjs.map +1 -0
  7. package/dist/_chunks/{en-BsOU9o5z.js → en-Dk9At9_Z.js} +9 -2
  8. package/dist/_chunks/en-Dk9At9_Z.js.map +1 -0
  9. package/dist/_chunks/{index-CkrCiZyq.mjs → index-7_EUScSl.mjs} +390 -143
  10. package/dist/_chunks/index-7_EUScSl.mjs.map +1 -0
  11. package/dist/_chunks/{index-C0i3v7QQ.js → index-BGtXLYX-.js} +383 -136
  12. package/dist/_chunks/index-BGtXLYX-.js.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/BulkLocaleActionModal.d.ts +2 -1
  16. package/dist/admin/src/components/CMHeaderActions.d.ts +29 -3
  17. package/dist/admin/src/components/CreateLocale.d.ts +6 -6
  18. package/dist/admin/src/utils/clean.d.ts +4 -0
  19. package/dist/server/index.js +367 -486
  20. package/dist/server/index.js.map +1 -1
  21. package/dist/server/index.mjs +368 -487
  22. package/dist/server/index.mjs.map +1 -1
  23. package/dist/server/src/bootstrap.d.ts +1 -4
  24. package/dist/server/src/bootstrap.d.ts.map +1 -1
  25. package/dist/server/src/index.d.ts +1 -11
  26. package/dist/server/src/index.d.ts.map +1 -1
  27. package/dist/server/src/register.d.ts.map +1 -1
  28. package/dist/server/src/services/index.d.ts +0 -8
  29. package/dist/server/src/services/index.d.ts.map +1 -1
  30. package/dist/server/src/utils/index.d.ts +0 -2
  31. package/dist/server/src/utils/index.d.ts.map +1 -1
  32. package/package.json +9 -9
  33. package/dist/_chunks/SettingsPage-C0l7c5fn.js.map +0 -1
  34. package/dist/_chunks/SettingsPage-CbEn7zF5.mjs.map +0 -1
  35. package/dist/_chunks/en-BsOU9o5z.js.map +0 -1
  36. package/dist/_chunks/en-CM6Pjfyv.mjs.map +0 -1
  37. package/dist/_chunks/index-C0i3v7QQ.js.map +0 -1
  38. package/dist/_chunks/index-CkrCiZyq.mjs.map +0 -1
  39. package/dist/server/src/migrations/content-type/disable/index.d.ts +0 -3
  40. package/dist/server/src/migrations/content-type/disable/index.d.ts.map +0 -1
  41. package/dist/server/src/migrations/content-type/enable/index.d.ts +0 -3
  42. package/dist/server/src/migrations/content-type/enable/index.d.ts.map +0 -1
  43. package/dist/server/src/services/entity-service-decorator.d.ts +0 -29
  44. package/dist/server/src/services/entity-service-decorator.d.ts.map +0 -1
  45. package/strapi-server.js +0 -3
@@ -1,5 +1,5 @@
1
1
  import _ from "lodash";
2
- import { get, identity, propEq, isArray, prop, getOr, isEmpty, reduce, cloneDeep, isNil, has, omit, pipe, pick, map, flatten, uniq } from "lodash/fp";
2
+ import { get, identity, propEq, isArray, prop, getOr, isEmpty, reduce, cloneDeep, isNil, pipe, pick, has, map, flatten, uniq } from "lodash/fp";
3
3
  import * as utils from "@strapi/utils";
4
4
  import { errors, async, contentTypes as contentTypes$2, yup, validateYupSchema } from "@strapi/utils";
5
5
  const getCoreStore = () => {
@@ -30,7 +30,7 @@ const registerModelsHooks = () => {
30
30
  const attributesToPopulate = getNestedPopulateOfNonLocalizedAttributes2(schema2.uid);
31
31
  const result = await next();
32
32
  let resultID;
33
- if (Array.isArray(result?.entries)) {
33
+ if (Array.isArray(result?.entries) && result.entries[0]?.id) {
34
34
  resultID = result.entries[0].id;
35
35
  } else if (result?.id) {
36
36
  resultID = result.id;
@@ -44,12 +44,10 @@ const registerModelsHooks = () => {
44
44
  return result;
45
45
  });
46
46
  };
47
- const bootstrap = async ({ strapi: strapi2 }) => {
47
+ const bootstrap = async () => {
48
48
  const { sendDidInitializeEvent: sendDidInitializeEvent2 } = getService("metrics");
49
- const { decorator: decorator2 } = getService("entity-service-decorator");
50
49
  const { initDefaultLocale: initDefaultLocale2 } = getService("locales");
51
50
  const { sectionsBuilder, actions: actions2, engine } = getService("permissions");
52
- strapi2.entityService.decorate(decorator2);
53
51
  await initDefaultLocale2();
54
52
  sectionsBuilder.registerLocalesPropertyHandler();
55
53
  await actions2.registerI18nActions();
@@ -176,6 +174,350 @@ const getI18nLocaleArgPlugin = ({ nexus, typeRegistry }) => {
176
174
  }
177
175
  });
178
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
+ Object.values(strapi2.contentTypes).forEach((contentType) => {
197
+ const { attributes: attributes2 } = contentType;
198
+ _.set(attributes2, "locale", {
199
+ writable: true,
200
+ private: false,
201
+ configurable: false,
202
+ visible: false,
203
+ type: "string"
204
+ });
205
+ _.set(attributes2, "localizations", {
206
+ type: "relation",
207
+ relation: "oneToMany",
208
+ target: contentType.uid,
209
+ writable: false,
210
+ private: false,
211
+ configurable: false,
212
+ visible: false,
213
+ unstable_virtual: true,
214
+ joinColumn: {
215
+ name: "document_id",
216
+ referencedColumn: "document_id",
217
+ referencedTable: strapi2.db.metadata.identifiers.getTableName(contentType.collectionName),
218
+ // ensure the population will not include the results we already loaded
219
+ on({ results }) {
220
+ return {
221
+ id: {
222
+ $notIn: results.map((r) => r.id)
223
+ }
224
+ };
225
+ }
226
+ }
227
+ });
228
+ });
229
+ if (strapi2.plugin("graphql")) {
230
+ graphqlProvider({ strapi: strapi2 }).register();
231
+ }
232
+ };
233
+ const info = {
234
+ singularName: "locale",
235
+ pluralName: "locales",
236
+ collectionName: "locales",
237
+ displayName: "Locale",
238
+ description: ""
239
+ };
240
+ const options = {};
241
+ const pluginOptions = {
242
+ "content-manager": {
243
+ visible: false
244
+ },
245
+ "content-type-builder": {
246
+ visible: false
247
+ }
248
+ };
249
+ const attributes = {
250
+ name: {
251
+ type: "string",
252
+ min: 1,
253
+ max: 50,
254
+ configurable: false
255
+ },
256
+ code: {
257
+ type: "string",
258
+ unique: true,
259
+ configurable: false
260
+ }
261
+ };
262
+ const schema = {
263
+ info,
264
+ options,
265
+ pluginOptions,
266
+ attributes
267
+ };
268
+ const locale = {
269
+ schema
270
+ };
271
+ const contentTypes$1 = {
272
+ locale
273
+ };
274
+ const actions = [
275
+ {
276
+ section: "settings",
277
+ category: "Internationalization",
278
+ subCategory: "Locales",
279
+ pluginName: "i18n",
280
+ displayName: "Create",
281
+ uid: "locale.create"
282
+ },
283
+ {
284
+ section: "settings",
285
+ category: "Internationalization",
286
+ subCategory: "Locales",
287
+ pluginName: "i18n",
288
+ displayName: "Read",
289
+ uid: "locale.read",
290
+ aliases: [
291
+ { actionId: "plugin::content-manager.explorer.read", subjects: ["plugin::i18n.locale"] }
292
+ ]
293
+ },
294
+ {
295
+ section: "settings",
296
+ category: "Internationalization",
297
+ subCategory: "Locales",
298
+ pluginName: "i18n",
299
+ displayName: "Update",
300
+ uid: "locale.update"
301
+ },
302
+ {
303
+ section: "settings",
304
+ category: "Internationalization",
305
+ subCategory: "Locales",
306
+ pluginName: "i18n",
307
+ displayName: "Delete",
308
+ uid: "locale.delete"
309
+ }
310
+ ];
311
+ const addLocalesPropertyIfNeeded = ({ value: action }) => {
312
+ const {
313
+ section,
314
+ options: { applyToProperties }
315
+ } = action;
316
+ if (section !== "contentTypes") {
317
+ return;
318
+ }
319
+ if (isArray(applyToProperties) && applyToProperties.includes("locales")) {
320
+ return;
321
+ }
322
+ action.options.applyToProperties = isArray(applyToProperties) ? applyToProperties.concat("locales") : ["locales"];
323
+ };
324
+ const shouldApplyLocalesPropertyToSubject = ({ property, subject }) => {
325
+ if (property === "locales") {
326
+ const model = strapi.getModel(subject);
327
+ return getService("content-types").isLocalizedContentType(model);
328
+ }
329
+ return true;
330
+ };
331
+ const addAllLocalesToPermissions = async (permissions2) => {
332
+ const { actionProvider } = strapi.service("admin::permission");
333
+ const { find: findAllLocales } = getService("locales");
334
+ const allLocales = await findAllLocales();
335
+ const allLocalesCode = allLocales.map(prop("code"));
336
+ return Promise.all(
337
+ permissions2.map(async (permission) => {
338
+ const { action, subject } = permission;
339
+ const appliesToLocalesProperty = await actionProvider.appliesToProperty(
340
+ "locales",
341
+ action,
342
+ subject
343
+ );
344
+ if (!appliesToLocalesProperty) {
345
+ return permission;
346
+ }
347
+ const oldPermissionProperties = getOr({}, "properties", permission);
348
+ return { ...permission, properties: { ...oldPermissionProperties, locales: allLocalesCode } };
349
+ })
350
+ );
351
+ };
352
+ const syncSuperAdminPermissionsWithLocales = async () => {
353
+ const roleService = strapi.service("admin::role");
354
+ const permissionService = strapi.service("admin::permission");
355
+ const superAdminRole = await roleService.getSuperAdmin();
356
+ if (!superAdminRole) {
357
+ return;
358
+ }
359
+ const superAdminPermissions = await permissionService.findMany({
360
+ where: {
361
+ role: {
362
+ id: superAdminRole.id
363
+ }
364
+ }
365
+ });
366
+ const newSuperAdminPermissions = await addAllLocalesToPermissions(superAdminPermissions);
367
+ await roleService.assignPermissions(superAdminRole.id, newSuperAdminPermissions);
368
+ };
369
+ const registerI18nActions = async () => {
370
+ const { actionProvider } = strapi.service("admin::permission");
371
+ await actionProvider.registerMany(actions);
372
+ };
373
+ const registerI18nActionsHooks = () => {
374
+ const { actionProvider } = strapi.service("admin::permission");
375
+ const { hooks } = strapi.service("admin::role");
376
+ actionProvider.hooks.appliesPropertyToSubject.register(shouldApplyLocalesPropertyToSubject);
377
+ hooks.willResetSuperAdminPermissions.register(addAllLocalesToPermissions);
378
+ };
379
+ const updateActionsProperties = () => {
380
+ const { actionProvider } = strapi.service("admin::permission");
381
+ actionProvider.hooks.willRegister.register(addLocalesPropertyIfNeeded);
382
+ actionProvider.values().forEach((action) => addLocalesPropertyIfNeeded({ value: action }));
383
+ };
384
+ const i18nActionsService = {
385
+ actions,
386
+ registerI18nActions,
387
+ registerI18nActionsHooks,
388
+ updateActionsProperties,
389
+ syncSuperAdminPermissionsWithLocales
390
+ };
391
+ const localesPropertyHandler = async ({ action, section }) => {
392
+ const { actionProvider } = strapi.service("admin::permission");
393
+ const locales2 = await getService("locales").find();
394
+ if (isEmpty(locales2)) {
395
+ return;
396
+ }
397
+ for (const subject of section.subjects) {
398
+ const applies = await actionProvider.appliesToProperty("locales", action.actionId, subject.uid);
399
+ const hasLocalesProperty = subject.properties.find(
400
+ (property) => property.value === "locales"
401
+ );
402
+ if (applies && !hasLocalesProperty) {
403
+ subject.properties.push({
404
+ label: "Locales",
405
+ value: "locales",
406
+ children: locales2.map(({ name, code }) => ({ label: name || code, value: code }))
407
+ });
408
+ }
409
+ }
410
+ };
411
+ const registerLocalesPropertyHandler = () => {
412
+ const { sectionsBuilder } = strapi.service("admin::permission");
413
+ sectionsBuilder.addHandler("singleTypes", localesPropertyHandler);
414
+ sectionsBuilder.addHandler("collectionTypes", localesPropertyHandler);
415
+ };
416
+ const sectionsBuilderService = {
417
+ localesPropertyHandler,
418
+ registerLocalesPropertyHandler
419
+ };
420
+ const willRegisterPermission = (context) => {
421
+ const { permission, condition, user } = context;
422
+ const { subject, properties } = permission;
423
+ const isSuperAdmin = strapi.service("admin::role").hasSuperAdminRole(user);
424
+ if (isSuperAdmin) {
425
+ return;
426
+ }
427
+ const { locales: locales2 } = properties || {};
428
+ const { isLocalizedContentType: isLocalizedContentType2 } = getService("content-types");
429
+ if (!subject) {
430
+ return;
431
+ }
432
+ const ct = strapi.contentTypes[subject];
433
+ if (!isLocalizedContentType2(ct)) {
434
+ return;
435
+ }
436
+ if (locales2 === null) {
437
+ return;
438
+ }
439
+ condition.and({
440
+ locale: {
441
+ $in: locales2 || []
442
+ }
443
+ });
444
+ };
445
+ const registerI18nPermissionsHandlers = () => {
446
+ const { engine } = strapi.service("admin::permission");
447
+ engine.hooks["before-register.permission"].register(willRegisterPermission);
448
+ };
449
+ const engineService = {
450
+ willRegisterPermission,
451
+ registerI18nPermissionsHandlers
452
+ };
453
+ const permissions = () => ({
454
+ actions: i18nActionsService,
455
+ sectionsBuilder: sectionsBuilderService,
456
+ engine: engineService
457
+ });
458
+ const sendDidInitializeEvent = async () => {
459
+ const { isLocalizedContentType: isLocalizedContentType2 } = getService("content-types");
460
+ const numberOfContentTypes = reduce(
461
+ (sum, contentType) => isLocalizedContentType2(contentType) ? sum + 1 : sum,
462
+ 0
463
+ )(strapi.contentTypes);
464
+ await strapi.telemetry.send("didInitializeI18n", { groupProperties: { numberOfContentTypes } });
465
+ };
466
+ const sendDidUpdateI18nLocalesEvent = async () => {
467
+ const numberOfLocales = await getService("locales").count();
468
+ await strapi.telemetry.send("didUpdateI18nLocales", {
469
+ groupProperties: { numberOfLocales }
470
+ });
471
+ };
472
+ const metrics = () => ({
473
+ sendDidInitializeEvent,
474
+ sendDidUpdateI18nLocalesEvent
475
+ });
476
+ const syncNonLocalizedAttributes = async (sourceEntry, model) => {
477
+ const { copyNonLocalizedAttributes: copyNonLocalizedAttributes2 } = getService("content-types");
478
+ const nonLocalizedAttributes = copyNonLocalizedAttributes2(model, sourceEntry);
479
+ if (isEmpty(nonLocalizedAttributes)) {
480
+ return;
481
+ }
482
+ const uid = model.uid;
483
+ const documentId = sourceEntry.documentId;
484
+ const locale2 = sourceEntry.locale;
485
+ const status = sourceEntry?.publishedAt ? "published" : "draft";
486
+ const localeEntriesToUpdate = await strapi.db.query(uid).findMany({
487
+ where: {
488
+ documentId,
489
+ publishedAt: status === "published" ? { $ne: null } : null,
490
+ locale: { $ne: locale2 }
491
+ },
492
+ select: ["locale", "id"]
493
+ });
494
+ const entryData = await strapi.documents(uid).omitComponentData(nonLocalizedAttributes);
495
+ await async.map(localeEntriesToUpdate, async (entry) => {
496
+ const transformedData = await strapi.documents.utils.transformData(
497
+ cloneDeep(nonLocalizedAttributes),
498
+ {
499
+ uid,
500
+ status,
501
+ locale: entry.locale,
502
+ allowMissingId: true
503
+ }
504
+ );
505
+ const componentData = await strapi.documents(uid).updateComponents(entry, transformedData);
506
+ await strapi.db.query(uid).update({
507
+ where: {
508
+ documentId,
509
+ publishedAt: status === "published" ? { $ne: null } : null,
510
+ locale: { $eq: entry.locale }
511
+ },
512
+ // The data we send to the update function is the entry data merged with
513
+ // the updated component data
514
+ data: Object.assign(cloneDeep(entryData), componentData)
515
+ });
516
+ });
517
+ };
518
+ const localizations = () => ({
519
+ syncNonLocalizedAttributes
520
+ });
179
521
  const isoLocales = [
180
522
  {
181
523
  code: "af",
@@ -2574,410 +2916,35 @@ const isoLocales = [
2574
2916
  name: "Zarma (dje)"
2575
2917
  },
2576
2918
  {
2577
- code: "dje-NE",
2578
- name: "Zarma (Niger) (dje-NE)"
2579
- },
2580
- {
2581
- code: "zu",
2582
- name: "Zulu (zu)"
2583
- },
2584
- {
2585
- code: "zu-ZA",
2586
- name: "Zulu (South Africa) (zu-ZA)"
2587
- }
2588
- ];
2589
- const getInitLocale = () => {
2590
- const envLocaleCode = process.env.STRAPI_PLUGIN_I18N_INIT_LOCALE_CODE;
2591
- if (envLocaleCode) {
2592
- const matchingLocale = isoLocales.find(({ code }) => code === envLocaleCode);
2593
- if (!matchingLocale) {
2594
- throw new Error(
2595
- "Unknown locale code provided in the environment variable STRAPI_PLUGIN_I18N_INIT_LOCALE_CODE"
2596
- );
2597
- }
2598
- return { ...matchingLocale };
2599
- }
2600
- return {
2601
- code: "en",
2602
- name: "English (en)"
2603
- };
2604
- };
2605
- const DEFAULT_LOCALE = getInitLocale();
2606
- const enableContentType = async ({ oldContentTypes, contentTypes: contentTypes2 }) => {
2607
- const { isLocalizedContentType: isLocalizedContentType2 } = getService("content-types");
2608
- const { getDefaultLocale: getDefaultLocale2 } = getService("locales");
2609
- if (!oldContentTypes) {
2610
- return;
2611
- }
2612
- for (const uid in contentTypes2) {
2613
- if (!oldContentTypes[uid]) {
2614
- continue;
2615
- }
2616
- const oldContentType = oldContentTypes[uid];
2617
- const contentType = contentTypes2[uid];
2618
- if (!isLocalizedContentType2(oldContentType) && isLocalizedContentType2(contentType)) {
2619
- const defaultLocale = await getDefaultLocale2() || DEFAULT_LOCALE.code;
2620
- await strapi.db.query(uid).updateMany({
2621
- where: { locale: null },
2622
- data: { locale: defaultLocale }
2623
- });
2624
- }
2625
- }
2626
- };
2627
- const disableContentType = 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 Promise.all([
2642
- // Delete all entities that are not in the default locale
2643
- strapi.db.query(uid).deleteMany({
2644
- where: { locale: { $ne: defaultLocale } }
2645
- }),
2646
- // Set locale to null for the rest
2647
- strapi.db.query(uid).updateMany({
2648
- where: { locale: { $eq: defaultLocale } },
2649
- data: { locale: null }
2650
- })
2651
- ]);
2652
- }
2653
- }
2654
- };
2655
- const register = ({ strapi: strapi2 }) => {
2656
- extendContentTypes(strapi2);
2657
- addContentManagerLocaleMiddleware(strapi2);
2658
- addContentTypeSyncHooks(strapi2);
2659
- };
2660
- const addContentManagerLocaleMiddleware = (strapi2) => {
2661
- strapi2.server.router.use("/content-manager/collection-types/:model", (ctx, next) => {
2662
- if (ctx.method === "POST" || ctx.method === "PUT") {
2663
- return validateLocaleCreation(ctx, next);
2664
- }
2665
- return next();
2666
- });
2667
- strapi2.server.router.use("/content-manager/single-types/:model", (ctx, next) => {
2668
- if (ctx.method === "POST" || ctx.method === "PUT") {
2669
- return validateLocaleCreation(ctx, next);
2670
- }
2671
- return next();
2672
- });
2673
- };
2674
- const addContentTypeSyncHooks = (strapi2) => {
2675
- strapi2.hook("strapi::content-types.beforeSync").register(disableContentType);
2676
- strapi2.hook("strapi::content-types.afterSync").register(enableContentType);
2677
- };
2678
- const extendContentTypes = (strapi2) => {
2679
- Object.values(strapi2.contentTypes).forEach((contentType) => {
2680
- const { attributes: attributes2 } = contentType;
2681
- _.set(attributes2, "locale", {
2682
- writable: true,
2683
- private: false,
2684
- configurable: false,
2685
- visible: false,
2686
- type: "string"
2687
- });
2688
- });
2689
- if (strapi2.plugin("graphql")) {
2690
- graphqlProvider({ strapi: strapi2 }).register();
2691
- }
2692
- };
2693
- const info = {
2694
- singularName: "locale",
2695
- pluralName: "locales",
2696
- collectionName: "locales",
2697
- displayName: "Locale",
2698
- description: ""
2699
- };
2700
- const options = {};
2701
- const pluginOptions = {
2702
- "content-manager": {
2703
- visible: false
2704
- },
2705
- "content-type-builder": {
2706
- visible: false
2707
- }
2708
- };
2709
- const attributes = {
2710
- name: {
2711
- type: "string",
2712
- min: 1,
2713
- max: 50,
2714
- configurable: false
2715
- },
2716
- code: {
2717
- type: "string",
2718
- unique: true,
2719
- configurable: false
2720
- }
2721
- };
2722
- const schema = {
2723
- info,
2724
- options,
2725
- pluginOptions,
2726
- attributes
2727
- };
2728
- const locale = {
2729
- schema
2730
- };
2731
- const contentTypes$1 = {
2732
- locale
2733
- };
2734
- const actions = [
2735
- {
2736
- section: "settings",
2737
- category: "Internationalization",
2738
- subCategory: "Locales",
2739
- pluginName: "i18n",
2740
- displayName: "Create",
2741
- uid: "locale.create"
2742
- },
2743
- {
2744
- section: "settings",
2745
- category: "Internationalization",
2746
- subCategory: "Locales",
2747
- pluginName: "i18n",
2748
- displayName: "Read",
2749
- uid: "locale.read",
2750
- aliases: [
2751
- { actionId: "plugin::content-manager.explorer.read", subjects: ["plugin::i18n.locale"] }
2752
- ]
2753
- },
2754
- {
2755
- section: "settings",
2756
- category: "Internationalization",
2757
- subCategory: "Locales",
2758
- pluginName: "i18n",
2759
- displayName: "Update",
2760
- uid: "locale.update"
2919
+ code: "dje-NE",
2920
+ name: "Zarma (Niger) (dje-NE)"
2761
2921
  },
2762
2922
  {
2763
- section: "settings",
2764
- category: "Internationalization",
2765
- subCategory: "Locales",
2766
- pluginName: "i18n",
2767
- displayName: "Delete",
2768
- uid: "locale.delete"
2923
+ code: "zu",
2924
+ name: "Zulu (zu)"
2925
+ },
2926
+ {
2927
+ code: "zu-ZA",
2928
+ name: "Zulu (South Africa) (zu-ZA)"
2769
2929
  }
2770
2930
  ];
2771
- const addLocalesPropertyIfNeeded = ({ value: action }) => {
2772
- const {
2773
- section,
2774
- options: { applyToProperties }
2775
- } = action;
2776
- if (section !== "contentTypes") {
2777
- return;
2778
- }
2779
- if (isArray(applyToProperties) && applyToProperties.includes("locales")) {
2780
- return;
2781
- }
2782
- action.options.applyToProperties = isArray(applyToProperties) ? applyToProperties.concat("locales") : ["locales"];
2783
- };
2784
- const shouldApplyLocalesPropertyToSubject = ({ property, subject }) => {
2785
- if (property === "locales") {
2786
- const model = strapi.getModel(subject);
2787
- return getService("content-types").isLocalizedContentType(model);
2788
- }
2789
- return true;
2790
- };
2791
- const addAllLocalesToPermissions = async (permissions2) => {
2792
- const { actionProvider } = strapi.service("admin::permission");
2793
- const { find: findAllLocales } = getService("locales");
2794
- const allLocales = await findAllLocales();
2795
- const allLocalesCode = allLocales.map(prop("code"));
2796
- return Promise.all(
2797
- permissions2.map(async (permission) => {
2798
- const { action, subject } = permission;
2799
- const appliesToLocalesProperty = await actionProvider.appliesToProperty(
2800
- "locales",
2801
- action,
2802
- subject
2931
+ const getInitLocale = () => {
2932
+ const envLocaleCode = process.env.STRAPI_PLUGIN_I18N_INIT_LOCALE_CODE;
2933
+ if (envLocaleCode) {
2934
+ const matchingLocale = isoLocales.find(({ code }) => code === envLocaleCode);
2935
+ if (!matchingLocale) {
2936
+ throw new Error(
2937
+ "Unknown locale code provided in the environment variable STRAPI_PLUGIN_I18N_INIT_LOCALE_CODE"
2803
2938
  );
2804
- if (!appliesToLocalesProperty) {
2805
- return permission;
2806
- }
2807
- const oldPermissionProperties = getOr({}, "properties", permission);
2808
- return { ...permission, properties: { ...oldPermissionProperties, locales: allLocalesCode } };
2809
- })
2810
- );
2811
- };
2812
- const syncSuperAdminPermissionsWithLocales = async () => {
2813
- const roleService = strapi.service("admin::role");
2814
- const permissionService = strapi.service("admin::permission");
2815
- const superAdminRole = await roleService.getSuperAdmin();
2816
- if (!superAdminRole) {
2817
- return;
2818
- }
2819
- const superAdminPermissions = await permissionService.findMany({
2820
- where: {
2821
- role: {
2822
- id: superAdminRole.id
2823
- }
2824
- }
2825
- });
2826
- const newSuperAdminPermissions = await addAllLocalesToPermissions(superAdminPermissions);
2827
- await roleService.assignPermissions(superAdminRole.id, newSuperAdminPermissions);
2828
- };
2829
- const registerI18nActions = async () => {
2830
- const { actionProvider } = strapi.service("admin::permission");
2831
- await actionProvider.registerMany(actions);
2832
- };
2833
- const registerI18nActionsHooks = () => {
2834
- const { actionProvider } = strapi.service("admin::permission");
2835
- const { hooks } = strapi.service("admin::role");
2836
- actionProvider.hooks.appliesPropertyToSubject.register(shouldApplyLocalesPropertyToSubject);
2837
- hooks.willResetSuperAdminPermissions.register(addAllLocalesToPermissions);
2838
- };
2839
- const updateActionsProperties = () => {
2840
- const { actionProvider } = strapi.service("admin::permission");
2841
- actionProvider.hooks.willRegister.register(addLocalesPropertyIfNeeded);
2842
- actionProvider.values().forEach((action) => addLocalesPropertyIfNeeded({ value: action }));
2843
- };
2844
- const i18nActionsService = {
2845
- actions,
2846
- registerI18nActions,
2847
- registerI18nActionsHooks,
2848
- updateActionsProperties,
2849
- syncSuperAdminPermissionsWithLocales
2850
- };
2851
- const localesPropertyHandler = async ({ action, section }) => {
2852
- const { actionProvider } = strapi.service("admin::permission");
2853
- const locales2 = await getService("locales").find();
2854
- if (isEmpty(locales2)) {
2855
- return;
2856
- }
2857
- for (const subject of section.subjects) {
2858
- const applies = await actionProvider.appliesToProperty("locales", action.actionId, subject.uid);
2859
- const hasLocalesProperty = subject.properties.find(
2860
- (property) => property.value === "locales"
2861
- );
2862
- if (applies && !hasLocalesProperty) {
2863
- subject.properties.push({
2864
- label: "Locales",
2865
- value: "locales",
2866
- children: locales2.map(({ name, code }) => ({ label: name || code, value: code }))
2867
- });
2868
- }
2869
- }
2870
- };
2871
- const registerLocalesPropertyHandler = () => {
2872
- const { sectionsBuilder } = strapi.service("admin::permission");
2873
- sectionsBuilder.addHandler("singleTypes", localesPropertyHandler);
2874
- sectionsBuilder.addHandler("collectionTypes", localesPropertyHandler);
2875
- };
2876
- const sectionsBuilderService = {
2877
- localesPropertyHandler,
2878
- registerLocalesPropertyHandler
2879
- };
2880
- const willRegisterPermission = (context) => {
2881
- const { permission, condition, user } = context;
2882
- const { subject, properties } = permission;
2883
- const isSuperAdmin = strapi.service("admin::role").hasSuperAdminRole(user);
2884
- if (isSuperAdmin) {
2885
- return;
2886
- }
2887
- const { locales: locales2 } = properties || {};
2888
- const { isLocalizedContentType: isLocalizedContentType2 } = getService("content-types");
2889
- if (!subject) {
2890
- return;
2891
- }
2892
- const ct = strapi.contentTypes[subject];
2893
- if (!isLocalizedContentType2(ct)) {
2894
- return;
2895
- }
2896
- if (locales2 === null) {
2897
- return;
2898
- }
2899
- condition.and({
2900
- locale: {
2901
- $in: locales2 || []
2902
2939
  }
2903
- });
2904
- };
2905
- const registerI18nPermissionsHandlers = () => {
2906
- const { engine } = strapi.service("admin::permission");
2907
- engine.hooks["before-register.permission"].register(willRegisterPermission);
2908
- };
2909
- const engineService = {
2910
- willRegisterPermission,
2911
- registerI18nPermissionsHandlers
2912
- };
2913
- const permissions = () => ({
2914
- actions: i18nActionsService,
2915
- sectionsBuilder: sectionsBuilderService,
2916
- engine: engineService
2917
- });
2918
- const sendDidInitializeEvent = async () => {
2919
- const { isLocalizedContentType: isLocalizedContentType2 } = getService("content-types");
2920
- const numberOfContentTypes = reduce(
2921
- (sum, contentType) => isLocalizedContentType2(contentType) ? sum + 1 : sum,
2922
- 0
2923
- )(strapi.contentTypes);
2924
- await strapi.telemetry.send("didInitializeI18n", { groupProperties: { numberOfContentTypes } });
2925
- };
2926
- const sendDidUpdateI18nLocalesEvent = async () => {
2927
- const numberOfLocales = await getService("locales").count();
2928
- await strapi.telemetry.send("didUpdateI18nLocales", {
2929
- groupProperties: { numberOfLocales }
2930
- });
2931
- };
2932
- const metrics = () => ({
2933
- sendDidInitializeEvent,
2934
- sendDidUpdateI18nLocalesEvent
2935
- });
2936
- const syncNonLocalizedAttributes = async (sourceEntry, model) => {
2937
- const { copyNonLocalizedAttributes: copyNonLocalizedAttributes2 } = getService("content-types");
2938
- const nonLocalizedAttributes = copyNonLocalizedAttributes2(model, sourceEntry);
2939
- if (isEmpty(nonLocalizedAttributes)) {
2940
- return;
2940
+ return { ...matchingLocale };
2941
2941
  }
2942
- const uid = model.uid;
2943
- const documentId = sourceEntry.documentId;
2944
- const locale2 = sourceEntry.locale;
2945
- const status = sourceEntry?.publishedAt ? "published" : "draft";
2946
- const localeEntriesToUpdate = await strapi.db.query(uid).findMany({
2947
- where: {
2948
- documentId,
2949
- publishedAt: status === "published" ? { $ne: null } : null,
2950
- locale: { $ne: locale2 }
2951
- },
2952
- select: ["locale", "id"]
2953
- });
2954
- const entryData = await strapi.documents(uid).omitComponentData(nonLocalizedAttributes);
2955
- await async.map(localeEntriesToUpdate, async (entry) => {
2956
- const transformedData = await strapi.documents.utils.transformData(
2957
- cloneDeep(nonLocalizedAttributes),
2958
- {
2959
- uid,
2960
- status,
2961
- locale: entry.locale,
2962
- allowMissingId: true
2963
- }
2964
- );
2965
- const componentData = await strapi.documents(uid).updateComponents(entry, transformedData);
2966
- await strapi.db.query(uid).update({
2967
- where: {
2968
- documentId,
2969
- publishedAt: status === "published" ? { $ne: null } : null,
2970
- locale: { $eq: entry.locale }
2971
- },
2972
- // The data we send to the update function is the entry data merged with
2973
- // the updated component data
2974
- data: Object.assign(cloneDeep(entryData), componentData)
2975
- });
2976
- });
2942
+ return {
2943
+ code: "en",
2944
+ name: "English (en)"
2945
+ };
2977
2946
  };
2978
- const localizations = () => ({
2979
- syncNonLocalizedAttributes
2980
- });
2947
+ const DEFAULT_LOCALE = getInitLocale();
2981
2948
  const find = (params = {}) => strapi.db.query("plugin::i18n.locale").findMany({ where: params });
2982
2949
  const findById = (id) => strapi.db.query("plugin::i18n.locale").findOne({ where: { id } });
2983
2950
  const findByCode = (code) => strapi.db.query("plugin::i18n.locale").findOne({ where: { code } });
@@ -3045,91 +3012,6 @@ const getIsoLocales = () => isoLocales;
3045
3012
  const isoLocalesService = () => ({
3046
3013
  getIsoLocales
3047
3014
  });
3048
- const LOCALE_QUERY_FILTER = "locale";
3049
- const SINGLE_ENTRY_ACTIONS = ["findOne", "update", "delete"];
3050
- const BULK_ACTIONS = ["delete"];
3051
- const paramsContain = (key, params) => {
3052
- return has(key, params.filters) || isArray(params.filters) && params.filters.some((clause) => has(key, clause)) || isArray(get("$and", params.filters)) && params.filters.$and.some((clause) => has(key, clause));
3053
- };
3054
- const wrapParams = async (params = {}, ctx = {}) => {
3055
- const { action } = ctx;
3056
- if (has(LOCALE_QUERY_FILTER, params)) {
3057
- if (params[LOCALE_QUERY_FILTER] === "all") {
3058
- return omit(LOCALE_QUERY_FILTER, params);
3059
- }
3060
- return {
3061
- ...omit(LOCALE_QUERY_FILTER, params),
3062
- filters: {
3063
- $and: [{ locale: params[LOCALE_QUERY_FILTER] }].concat(params.filters || [])
3064
- }
3065
- };
3066
- }
3067
- const entityDefinedById = paramsContain("id", params) && SINGLE_ENTRY_ACTIONS.includes(action);
3068
- const entitiesDefinedByIds = paramsContain("id.$in", params) && BULK_ACTIONS.includes(action);
3069
- if (entityDefinedById || entitiesDefinedByIds) {
3070
- return params;
3071
- }
3072
- const { getDefaultLocale: getDefaultLocale2 } = getService("locales");
3073
- return {
3074
- ...params,
3075
- filters: {
3076
- $and: [{ locale: await getDefaultLocale2() }].concat(params.filters || [])
3077
- }
3078
- };
3079
- };
3080
- const decorator = (service) => ({
3081
- /**
3082
- * Wraps result
3083
- * @param {object} result - result object of query
3084
- * @param {object} ctx - Query context
3085
- * @param {object} ctx.model - Model that is being used
3086
- */
3087
- async wrapResult(result = {}, ctx = {}) {
3088
- return service.wrapResult.call(this, result, ctx);
3089
- },
3090
- /**
3091
- * Wraps query options. In particular will add default locale to query params
3092
- * @param {object} params - Query options object (params, data, files, populate)
3093
- * @param {object} ctx - Query context
3094
- * @param {object} ctx.model - Model that is being used
3095
- */
3096
- async wrapParams(params = {}, ctx = {}) {
3097
- const wrappedParams = await service.wrapParams.call(this, params, ctx);
3098
- const model = strapi.getModel(ctx.uid);
3099
- const { isLocalizedContentType: isLocalizedContentType2 } = getService("content-types");
3100
- if (!isLocalizedContentType2(model)) {
3101
- return wrappedParams;
3102
- }
3103
- return wrapParams(wrappedParams, ctx);
3104
- },
3105
- /**
3106
- * Find an entry or several if fetching all locales
3107
- * @param {string} uid - Model uid
3108
- * @param {object} opts - Query options object (params, data, files, populate)
3109
- */
3110
- async findMany(uid, opts) {
3111
- const model = strapi.getModel(uid);
3112
- const { isLocalizedContentType: isLocalizedContentType2 } = getService("content-types");
3113
- if (!isLocalizedContentType2(model)) {
3114
- return service.findMany.call(this, uid, opts);
3115
- }
3116
- const { kind } = model;
3117
- if (kind === "singleType") {
3118
- if (opts[LOCALE_QUERY_FILTER] === "all") {
3119
- const wrappedParams = await this.wrapParams(opts, { uid, action: "findMany" });
3120
- const query = strapi.get("query-params").transform(uid, wrappedParams);
3121
- const entities = await strapi.db.query(uid).findMany(query);
3122
- return this.wrapResult(entities, { uid, action: "findMany" });
3123
- }
3124
- return service.findMany.call(this, uid, opts);
3125
- }
3126
- return service.findMany.call(this, uid, opts);
3127
- }
3128
- });
3129
- const entityServiceDecorator = () => ({
3130
- decorator,
3131
- wrapParams
3132
- });
3133
3015
  const {
3134
3016
  isRelationalAttribute,
3135
3017
  getVisibleAttributes,
@@ -3260,7 +3142,6 @@ const services = {
3260
3142
  localizations,
3261
3143
  locales,
3262
3144
  "iso-locales": isoLocalesService,
3263
- "entity-service-decorator": entityServiceDecorator,
3264
3145
  "content-types": contentTypes
3265
3146
  };
3266
3147
  const admin = {