@strapi/i18n 0.0.0-experimental.da85533897155e719d784f0271223c866d2f69ab → 0.0.0-experimental.dd1d47ef78ef6cfec4ed62576108500bd9f13740

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 (47) hide show
  1. package/dist/_chunks/{SettingsPage-DW0GwDcD.mjs → SettingsPage-BHvunuIF.mjs} +4 -4
  2. package/dist/_chunks/SettingsPage-BHvunuIF.mjs.map +1 -0
  3. package/dist/_chunks/{SettingsPage-a96ZyFLy.js → SettingsPage-Bcj7380u.js} +4 -4
  4. package/dist/_chunks/SettingsPage-Bcj7380u.js.map +1 -0
  5. package/dist/_chunks/{en-BsOU9o5z.js → en-BKBz3tro.js} +10 -3
  6. package/dist/_chunks/en-BKBz3tro.js.map +1 -0
  7. package/dist/_chunks/{en-CM6Pjfyv.mjs → en-DlXfy6Gy.mjs} +10 -3
  8. package/dist/_chunks/en-DlXfy6Gy.mjs.map +1 -0
  9. package/dist/_chunks/{index-sfNkjx75.js → index-BKZbxhpm.js} +383 -94
  10. package/dist/_chunks/index-BKZbxhpm.js.map +1 -0
  11. package/dist/_chunks/{index-4KJn181Q.mjs → index-DUdrr5PR.mjs} +386 -97
  12. package/dist/_chunks/index-DUdrr5PR.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/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 +389 -485
  20. package/dist/server/index.js.map +1 -1
  21. package/dist/server/index.mjs +391 -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 +7 -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 +6 -8
  29. package/dist/server/src/services/index.d.ts.map +1 -1
  30. package/dist/server/src/services/sanitize/index.d.ts +11 -0
  31. package/dist/server/src/services/sanitize/index.d.ts.map +1 -0
  32. package/dist/server/src/utils/index.d.ts +2 -2
  33. package/dist/server/src/utils/index.d.ts.map +1 -1
  34. package/package.json +10 -10
  35. package/dist/_chunks/SettingsPage-DW0GwDcD.mjs.map +0 -1
  36. package/dist/_chunks/SettingsPage-a96ZyFLy.js.map +0 -1
  37. package/dist/_chunks/en-BsOU9o5z.js.map +0 -1
  38. package/dist/_chunks/en-CM6Pjfyv.mjs.map +0 -1
  39. package/dist/_chunks/index-4KJn181Q.mjs.map +0 -1
  40. package/dist/_chunks/index-sfNkjx75.js.map +0 -1
  41. package/dist/server/src/migrations/content-type/disable/index.d.ts +0 -3
  42. package/dist/server/src/migrations/content-type/disable/index.d.ts.map +0 -1
  43. package/dist/server/src/migrations/content-type/enable/index.d.ts +0 -3
  44. package/dist/server/src/migrations/content-type/enable/index.d.ts.map +0 -1
  45. package/dist/server/src/services/entity-service-decorator.d.ts +0 -29
  46. package/dist/server/src/services/entity-service-decorator.d.ts.map +0 -1
  47. package/strapi-server.js +0 -3
@@ -241,10 +241,94 @@ const relationsApi = i18nApi.injectEndpoints({
241
241
  })
242
242
  });
243
243
  const { useGetManyDraftRelationCountQuery } = relationsApi;
244
+ const cleanData = (data, schema, components) => {
245
+ const cleanedData = removeFields(data, [
246
+ "createdAt",
247
+ "createdBy",
248
+ "updatedAt",
249
+ "updatedBy",
250
+ "id",
251
+ "documentId",
252
+ "publishedAt",
253
+ "strapi_stage",
254
+ "strapi_assignee",
255
+ "locale",
256
+ "status"
257
+ ]);
258
+ const cleanedDataWithoutPasswordAndRelation = recursiveRemoveFieldTypes(
259
+ cleanedData,
260
+ schema,
261
+ components,
262
+ ["relation", "password"]
263
+ );
264
+ return cleanedDataWithoutPasswordAndRelation;
265
+ };
266
+ const removeFields = (data, fields) => {
267
+ return Object.keys(data).reduce((acc, current) => {
268
+ if (fields.includes(current)) {
269
+ return acc;
270
+ }
271
+ acc[current] = data[current];
272
+ return acc;
273
+ }, {});
274
+ };
275
+ const recursiveRemoveFieldTypes = (data, schema, components, fields) => {
276
+ return Object.keys(data).reduce((acc, current) => {
277
+ const attribute = schema.attributes[current] ?? { type: void 0 };
278
+ if (fields.includes(attribute.type)) {
279
+ return acc;
280
+ }
281
+ if (attribute.type === "dynamiczone") {
282
+ acc[current] = data[current].map((componentValue, index2) => {
283
+ const { id: _, ...rest } = recursiveRemoveFieldTypes(
284
+ componentValue,
285
+ components[componentValue.__component],
286
+ components,
287
+ fields
288
+ );
289
+ return {
290
+ ...rest,
291
+ __temp_key__: index2 + 1
292
+ };
293
+ });
294
+ } else if (attribute.type === "component") {
295
+ const { repeatable, component } = attribute;
296
+ if (repeatable) {
297
+ acc[current] = (data[current] ?? []).map((compoData, index2) => {
298
+ const { id: _, ...rest } = recursiveRemoveFieldTypes(
299
+ compoData,
300
+ components[component],
301
+ components,
302
+ fields
303
+ );
304
+ return {
305
+ ...rest,
306
+ __temp_key__: index2 + 1
307
+ };
308
+ });
309
+ } else {
310
+ const { id: _, ...rest } = recursiveRemoveFieldTypes(
311
+ data[current] ?? {},
312
+ components[component],
313
+ components,
314
+ fields
315
+ );
316
+ acc[current] = rest;
317
+ }
318
+ } else {
319
+ acc[current] = data[current];
320
+ }
321
+ return acc;
322
+ }, {});
323
+ };
244
324
  const isErrorMessageDescriptor = (object) => {
245
325
  return typeof object === "object" && object !== null && "id" in object && "defaultMessage" in object;
246
326
  };
247
- const EntryValidationText = ({ status = "draft", validationErrors }) => {
327
+ const EntryValidationText = ({
328
+ status = "draft",
329
+ validationErrors,
330
+ action
331
+ }) => {
248
332
  const { formatMessage } = reactIntl.useIntl();
249
333
  const getErrorStr = (key, value) => {
250
334
  if (typeof value === "string") {
@@ -278,30 +362,63 @@ const EntryValidationText = ({ status = "draft", validationErrors }) => {
278
362
  ) })
279
363
  ] });
280
364
  }
281
- if (status === "published") {
282
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
283
- /* @__PURE__ */ jsxRuntime.jsx(icons.CheckCircle, { fill: "success600" }),
284
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
285
- id: "content-manager.bulk-publish.already-published",
286
- defaultMessage: "Already Published"
287
- }) })
288
- ] });
289
- }
290
- if (status === "modified") {
291
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
292
- /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowsCounterClockwise, { fill: "alternative600" }),
293
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
294
- id: "app.utils.ready-to-publish-changes",
295
- defaultMessage: "Ready to publish changes"
296
- }) })
297
- ] });
298
- }
365
+ const getStatusMessage = () => {
366
+ if (action === "bulk-publish") {
367
+ if (status === "published") {
368
+ return {
369
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.CheckCircle, { fill: "success600" }),
370
+ text: formatMessage({
371
+ id: "content-manager.bulk-publish.already-published",
372
+ defaultMessage: "Already Published"
373
+ }),
374
+ textColor: "success600",
375
+ fontWeight: "bold"
376
+ };
377
+ } else if (status === "modified") {
378
+ return {
379
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowsCounterClockwise, { fill: "alternative600" }),
380
+ text: formatMessage({
381
+ id: "app.utils.ready-to-publish-changes",
382
+ defaultMessage: "Ready to publish changes"
383
+ })
384
+ };
385
+ } else {
386
+ return {
387
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.CheckCircle, { fill: "success600" }),
388
+ text: formatMessage({
389
+ id: "app.utils.ready-to-publish",
390
+ defaultMessage: "Ready to publish"
391
+ })
392
+ };
393
+ }
394
+ } else {
395
+ if (status === "draft") {
396
+ return {
397
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.CheckCircle, { fill: "success600" }),
398
+ text: formatMessage({
399
+ id: "content-manager.bulk-unpublish.already-unpublished",
400
+ defaultMessage: "Already Unpublished"
401
+ }),
402
+ textColor: "success600",
403
+ fontWeight: "bold"
404
+ };
405
+ } else {
406
+ return {
407
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.CheckCircle, { fill: "success600" }),
408
+ text: formatMessage({
409
+ id: "app.utils.ready-to-unpublish-changes",
410
+ defaultMessage: "Ready to unpublish"
411
+ }),
412
+ textColor: "success600",
413
+ fontWeight: "bold"
414
+ };
415
+ }
416
+ }
417
+ };
418
+ const { icon, text, textColor = "success600", fontWeight = "normal" } = getStatusMessage();
299
419
  return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
300
- /* @__PURE__ */ jsxRuntime.jsx(icons.CheckCircle, { fill: "success600" }),
301
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
302
- id: "app.utils.ready-to-publish",
303
- defaultMessage: "Ready to publish"
304
- }) })
420
+ icon,
421
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor, fontWeight, children: text })
305
422
  ] });
306
423
  };
307
424
  const BoldChunk = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: chunks });
@@ -309,7 +426,8 @@ const BulkLocaleActionModal = ({
309
426
  headers,
310
427
  rows,
311
428
  localesMetadata,
312
- validationErrors = {}
429
+ validationErrors = {},
430
+ action
313
431
  }) => {
314
432
  const { formatMessage } = reactIntl.useIntl();
315
433
  const selectedRows = strapiAdmin.useTable(
@@ -322,22 +440,24 @@ const BulkLocaleActionModal = ({
322
440
  return acc;
323
441
  }, {});
324
442
  const localesWithErrors = Object.keys(validationErrors);
325
- const alreadyPublishedCount = selectedRows.filter(
443
+ const publishedCount = selectedRows.filter(
326
444
  ({ locale }) => currentStatusByLocale[locale] === "published"
327
445
  ).length;
328
- const readyToPublishCount = selectedRows.filter(
446
+ const draftCount = selectedRows.filter(
329
447
  ({ locale }) => (currentStatusByLocale[locale] === "draft" || currentStatusByLocale[locale] === "modified") && !localesWithErrors.includes(locale)
330
448
  ).length;
331
449
  const withErrorsCount = localesWithErrors.length;
450
+ const messageId = action === "bulk-publish" ? "content-manager.containers.list.selectedEntriesModal.selectedCount.publish" : "content-manager.containers.list.selectedEntriesModal.selectedCount.unpublish";
451
+ const defaultMessage = action === "bulk-publish" ? "<b>{publishedCount}</b> {publishedCount, plural, =0 {entries} one {entry} other {entries}} already published. <b>{draftCount}</b> {draftCount, plural, =0 {entries} one {entry} other {entries}} ready to publish. <b>{withErrorsCount}</b> {withErrorsCount, plural, =0 {entries} one {entry} other {entries}} waiting for action." : "<b>{draftCount}</b> {draftCount, plural, =0 {entries} one {entry} other {entries}} already unpublished. <b>{publishedCount}</b> {publishedCount, plural, =0 {entries} one {entry} other {entries}} ready to unpublish.";
332
452
  return formatMessage(
333
453
  {
334
- id: "content-manager.containers.list.selectedEntriesModal.selectedCount",
335
- defaultMessage: "<b>{alreadyPublishedCount}</b> {alreadyPublishedCount, plural, =0 {entries} one {entry} other {entries}} already published. <b>{readyToPublishCount}</b> {readyToPublishCount, plural, =0 {entries} one {entry} other {entries}} ready to publish. <b>{withErrorsCount}</b> {withErrorsCount, plural, =0 {entries} one {entry} other {entries}} waiting for action."
454
+ id: messageId,
455
+ defaultMessage
336
456
  },
337
457
  {
338
458
  withErrorsCount,
339
- readyToPublishCount,
340
- alreadyPublishedCount,
459
+ draftCount,
460
+ publishedCount,
341
461
  b: BoldChunk
342
462
  }
343
463
  );
@@ -369,7 +489,7 @@ const BulkLocaleActionModal = ({
369
489
  children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "span", variant: "pi", fontWeight: "bold", children: capitalize(status) })
370
490
  }
371
491
  ) }) }),
372
- /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(EntryValidationText, { validationErrors: error, status }) }),
492
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(EntryValidationText, { validationErrors: error, status, action }) }),
373
493
  /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
374
494
  designSystem.IconButton,
375
495
  {
@@ -395,6 +515,48 @@ const BulkLocaleActionModal = ({
395
515
  ] }) })
396
516
  ] });
397
517
  };
518
+ const statusVariants = {
519
+ draft: "secondary",
520
+ published: "success",
521
+ modified: "alternative"
522
+ };
523
+ const LocaleOption = ({
524
+ isDraftAndPublishEnabled,
525
+ locale,
526
+ status,
527
+ entryExists
528
+ }) => {
529
+ const { formatMessage } = reactIntl.useIntl();
530
+ if (!entryExists) {
531
+ return formatMessage(
532
+ {
533
+ id: getTranslation("CMEditViewLocalePicker.locale.create"),
534
+ defaultMessage: "Create <bold>{locale}</bold> locale"
535
+ },
536
+ {
537
+ bold: (locale2) => /* @__PURE__ */ jsxRuntime.jsx("b", { children: locale2 }),
538
+ locale: locale.name
539
+ }
540
+ );
541
+ }
542
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", gap: 1, justifyContent: "space-between", children: [
543
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: locale.name }),
544
+ isDraftAndPublishEnabled ? /* @__PURE__ */ jsxRuntime.jsx(
545
+ designSystem.Status,
546
+ {
547
+ display: "flex",
548
+ paddingLeft: "6px",
549
+ paddingRight: "6px",
550
+ paddingTop: "2px",
551
+ paddingBottom: "2px",
552
+ showBullet: false,
553
+ size: "S",
554
+ variant: statusVariants[status],
555
+ children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "span", variant: "pi", fontWeight: "bold", children: capitalize(status) })
556
+ }
557
+ ) : null
558
+ ] });
559
+ };
398
560
  const LocalePickerAction = ({
399
561
  document,
400
562
  meta,
@@ -406,7 +568,13 @@ const LocalePickerAction = ({
406
568
  const [{ query: query2 }, setQuery] = strapiAdmin.useQueryParams();
407
569
  const { hasI18n, canCreate, canRead } = useI18n();
408
570
  const { data: locales = [] } = useGetLocalesQuery();
409
- const { schema } = strapiAdmin$1.unstable_useDocument({ model, collectionType, documentId });
571
+ const currentDesiredLocale = query2.plugins?.i18n?.locale;
572
+ const { schema } = strapiAdmin$1.unstable_useDocument({
573
+ model,
574
+ collectionType,
575
+ documentId,
576
+ params: { locale: currentDesiredLocale }
577
+ });
410
578
  const handleSelect = React__namespace.useCallback(
411
579
  (value) => {
412
580
  setQuery({
@@ -424,53 +592,47 @@ const LocalePickerAction = ({
424
592
  if (!Array.isArray(locales) || !hasI18n) {
425
593
  return;
426
594
  }
427
- const currentDesiredLocale = query2.plugins?.i18n?.locale;
428
595
  const doesLocaleExist = locales.find((loc) => loc.code === currentDesiredLocale);
429
596
  const defaultLocale = locales.find((locale) => locale.isDefault);
430
597
  if (!doesLocaleExist && defaultLocale?.code) {
431
598
  handleSelect(defaultLocale.code);
432
599
  }
433
- }, [handleSelect, hasI18n, locales, query2.plugins?.i18n?.locale]);
434
- if (!hasI18n || !Array.isArray(locales) || locales.length === 0) {
435
- return null;
436
- }
437
- const currentLocale = query2.plugins?.i18n?.locale || locales.find((loc) => loc.isDefault)?.code;
600
+ }, [handleSelect, hasI18n, locales, currentDesiredLocale]);
601
+ const currentLocale = Array.isArray(locales) ? locales.find((locale) => locale.code === currentDesiredLocale) : void 0;
438
602
  const allCurrentLocales = [
439
- { status: getDocumentStatus(document, meta), locale: currentLocale },
603
+ { status: getDocumentStatus(document, meta), locale: currentLocale?.code },
440
604
  ...meta?.availableLocales ?? []
441
605
  ];
606
+ if (!hasI18n || !Array.isArray(locales) || locales.length === 0) {
607
+ return null;
608
+ }
442
609
  return {
443
610
  label: formatMessage({
444
611
  id: getTranslation("Settings.locales.modal.locales.label"),
445
612
  defaultMessage: "Locales"
446
613
  }),
447
614
  options: locales.map((locale) => {
615
+ const entryWithLocaleExists = allCurrentLocales.some((doc) => doc.locale === locale.code);
448
616
  const currentLocaleDoc = allCurrentLocales.find(
449
617
  (doc) => "locale" in doc ? doc.locale === locale.code : false
450
618
  );
451
- const status = currentLocaleDoc?.status ?? "draft";
452
- const permissionsToCheck = currentLocaleDoc ? canCreate : canRead;
453
- const statusVariant = status === "draft" ? "primary" : status === "published" ? "success" : "alternative";
619
+ const permissionsToCheck = currentLocaleDoc ? canRead : canCreate;
454
620
  return {
455
621
  disabled: !permissionsToCheck.includes(locale.code),
456
622
  value: locale.code,
457
- label: locale.name,
458
- startIcon: schema?.options?.draftAndPublish ? /* @__PURE__ */ jsxRuntime.jsx(
459
- designSystem.Status,
623
+ label: /* @__PURE__ */ jsxRuntime.jsx(
624
+ LocaleOption,
460
625
  {
461
- display: "flex",
462
- paddingLeft: "6px",
463
- paddingRight: "6px",
464
- paddingTop: "2px",
465
- paddingBottom: "2px",
466
- showBullet: false,
467
- size: "S",
468
- variant: statusVariant,
469
- children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "span", variant: "pi", fontWeight: "bold", children: capitalize(status) })
626
+ isDraftAndPublishEnabled: !!schema?.options?.draftAndPublish,
627
+ locale,
628
+ status: currentLocaleDoc?.status,
629
+ entryExists: entryWithLocaleExists
470
630
  }
471
- ) : null
631
+ ),
632
+ startIcon: !entryWithLocaleExists ? /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}) : null
472
633
  };
473
634
  }),
635
+ customizeContent: () => currentLocale?.name,
474
636
  onSelect: handleSelect,
475
637
  value: currentLocale
476
638
  };
@@ -486,6 +648,99 @@ const getDocumentStatus = (document, meta) => {
486
648
  }
487
649
  return docStatus;
488
650
  };
651
+ const FillFromAnotherLocaleAction = ({
652
+ documentId,
653
+ meta,
654
+ model,
655
+ collectionType
656
+ }) => {
657
+ const { formatMessage } = reactIntl.useIntl();
658
+ const [{ query: query2 }] = strapiAdmin.useQueryParams();
659
+ const { hasI18n } = useI18n();
660
+ const currentDesiredLocale = query2.plugins?.i18n?.locale;
661
+ const [localeSelected, setLocaleSelected] = React__namespace.useState(null);
662
+ const setValues = strapiAdmin.useForm("FillFromAnotherLocale", (state) => state.setValues);
663
+ const { getDocument } = strapiAdmin$1.unstable_useDocumentActions();
664
+ const { schema, components } = strapiAdmin$1.unstable_useDocument({
665
+ model,
666
+ documentId,
667
+ collectionType,
668
+ params: { locale: currentDesiredLocale }
669
+ });
670
+ const { data: locales = [] } = useGetLocalesQuery();
671
+ const availableLocales = Array.isArray(locales) ? locales.filter((locale) => meta?.availableLocales.some((l) => l.locale === locale.code)) : [];
672
+ const fillFromLocale = (onClose) => async () => {
673
+ const response = await getDocument({
674
+ collectionType,
675
+ model,
676
+ documentId,
677
+ params: { locale: localeSelected }
678
+ });
679
+ if (!response || !schema) {
680
+ return;
681
+ }
682
+ const { data } = response;
683
+ const cleanedData = cleanData(data, schema, components);
684
+ setValues(cleanedData);
685
+ onClose();
686
+ };
687
+ if (!hasI18n) {
688
+ return null;
689
+ }
690
+ return {
691
+ type: "icon",
692
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Download, {}),
693
+ disabled: availableLocales.length === 0,
694
+ label: formatMessage({
695
+ id: getTranslation("CMEditViewCopyLocale.copy-text"),
696
+ defaultMessage: "Fill in from another locale"
697
+ }),
698
+ dialog: {
699
+ type: "dialog",
700
+ title: formatMessage({
701
+ id: getTranslation("CMEditViewCopyLocale.dialog.title"),
702
+ defaultMessage: "Confirmation"
703
+ }),
704
+ content: ({ onClose }) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
705
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 3, children: [
706
+ /* @__PURE__ */ jsxRuntime.jsx(icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
707
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textAlign: "center", children: formatMessage({
708
+ id: getTranslation("CMEditViewCopyLocale.dialog.body"),
709
+ defaultMessage: "Your current content will be erased and filled by the content of the selected locale:"
710
+ }) }),
711
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { width: "100%", children: [
712
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: formatMessage({
713
+ id: getTranslation("CMEditViewCopyLocale.dialog.field.label"),
714
+ defaultMessage: "Locale"
715
+ }) }),
716
+ /* @__PURE__ */ jsxRuntime.jsx(
717
+ designSystem.SingleSelect,
718
+ {
719
+ value: localeSelected,
720
+ placeholder: formatMessage({
721
+ id: getTranslation("CMEditViewCopyLocale.dialog.field.placeholder"),
722
+ defaultMessage: "Select one locale..."
723
+ }),
724
+ onChange: (value) => setLocaleSelected(value),
725
+ children: availableLocales.map((locale) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: locale.code, children: locale.name }, locale.code))
726
+ }
727
+ )
728
+ ] })
729
+ ] }) }),
730
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, width: "100%", children: [
731
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { flex: "auto", variant: "tertiary", onClick: onClose, children: formatMessage({
732
+ id: getTranslation("CMEditViewCopyLocale.cancel-text"),
733
+ defaultMessage: "No, cancel"
734
+ }) }),
735
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { flex: "auto", variant: "success", onClick: fillFromLocale(onClose), children: formatMessage({
736
+ id: getTranslation("CMEditViewCopyLocale.submit-text"),
737
+ defaultMessage: "Yes, fill in"
738
+ }) })
739
+ ] }) })
740
+ ] })
741
+ }
742
+ };
743
+ };
489
744
  const DeleteLocaleAction = ({
490
745
  document,
491
746
  documentId,
@@ -497,16 +752,23 @@ const DeleteLocaleAction = ({
497
752
  const { toggleNotification } = strapiAdmin.useNotification();
498
753
  const { delete: deleteAction } = strapiAdmin$1.unstable_useDocumentActions();
499
754
  const { hasI18n, canDelete } = useI18n();
755
+ const [{ query: query2 }] = strapiAdmin.useQueryParams();
756
+ const { data: locales = [] } = useGetLocalesQuery();
757
+ const currentDesiredLocale = query2.plugins?.i18n?.locale;
758
+ const locale = !("error" in locales) && locales.find((loc) => loc.code === currentDesiredLocale);
500
759
  if (!hasI18n) {
501
760
  return null;
502
761
  }
503
762
  return {
504
763
  disabled: document?.locale && !canDelete.includes(document.locale) || !document || !document.id,
505
764
  position: ["header", "table-row"],
506
- label: formatMessage({
507
- id: getTranslation("actions.delete.label"),
508
- defaultMessage: "Delete locale"
509
- }),
765
+ label: formatMessage(
766
+ {
767
+ id: getTranslation("actions.delete.label"),
768
+ defaultMessage: "Delete entry ({locale})"
769
+ },
770
+ { locale: locale && locale.name }
771
+ ),
510
772
  icon: /* @__PURE__ */ jsxRuntime.jsx(StyledTrash, {}),
511
773
  variant: "danger",
512
774
  dialog: {
@@ -523,7 +785,12 @@ const DeleteLocaleAction = ({
523
785
  }) })
524
786
  ] }),
525
787
  onConfirm: async () => {
526
- if (!documentId || !document?.locale) {
788
+ const unableToDelete = (
789
+ // We are unable to delete a collection type without a document ID
790
+ // & unable to delete generally if there is no document locale
791
+ collectionType !== "single-types" && !documentId || !document?.locale
792
+ );
793
+ if (unableToDelete) {
527
794
  console.error(
528
795
  "You're trying to delete a document without an id or locale, this is likely a bug with Strapi. Please open an issue."
529
796
  );
@@ -549,23 +816,24 @@ const DeleteLocaleAction = ({
549
816
  }
550
817
  };
551
818
  };
552
- const BulkLocalePublishAction = ({
819
+ const BulkLocaleAction = ({
553
820
  document: baseDocument,
554
821
  documentId,
555
822
  model,
556
- collectionType
823
+ collectionType,
824
+ action
557
825
  }) => {
558
826
  const baseLocale = baseDocument?.locale ?? null;
559
827
  const [{ query: query$1 }] = strapiAdmin.useQueryParams();
560
828
  const params = React__namespace.useMemo(() => strapiAdmin$1.buildValidParams(query$1), [query$1]);
561
- const isPublishedTab = query$1.status === "published";
829
+ const isOnPublishedTab = query$1.status === "published";
562
830
  const { formatMessage } = reactIntl.useIntl();
563
831
  const { hasI18n, canPublish } = useI18n();
564
832
  const { toggleNotification } = strapiAdmin.useNotification();
565
833
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
566
834
  const [selectedRows, setSelectedRows] = React__namespace.useState([]);
567
835
  const [isDraftRelationConfirmationOpen, setIsDraftRelationConfirmationOpen] = React__namespace.useState(false);
568
- const { publishMany: publishManyAction } = strapiAdmin$1.unstable_useDocumentActions();
836
+ const { publishMany: publishManyAction, unpublishMany: unpublishManyAction } = strapiAdmin$1.unstable_useDocumentActions();
569
837
  const {
570
838
  document,
571
839
  meta: documentMeta,
@@ -581,7 +849,7 @@ const BulkLocalePublishAction = ({
581
849
  }
582
850
  },
583
851
  {
584
- skip: !hasI18n
852
+ skip: !hasI18n || !baseLocale
585
853
  }
586
854
  );
587
855
  const { data: localesMetadata = [] } = useGetLocalesQuery(hasI18n ? void 0 : query.skipToken);
@@ -633,12 +901,19 @@ const BulkLocalePublishAction = ({
633
901
  }, {});
634
902
  return [rowsFromMeta, errors];
635
903
  }, [document, documentMeta?.availableLocales, validate]);
636
- const localesToPublish = selectedRows.reduce((acc, selectedRow) => {
637
- if (selectedRow.status !== "published" && !Object.keys(validationErrors).includes(selectedRow.locale)) {
904
+ const isBulkPublish = action === "bulk-publish";
905
+ const localesForAction = selectedRows.reduce((acc, selectedRow) => {
906
+ const isValidLocale = (
907
+ // Validation errors are irrelevant if we are trying to unpublish
908
+ !isBulkPublish || !Object.keys(validationErrors).includes(selectedRow.locale)
909
+ );
910
+ const shouldAddLocale = isBulkPublish ? selectedRow.status !== "published" && isValidLocale : selectedRow.status !== "draft" && isValidLocale;
911
+ if (shouldAddLocale) {
638
912
  acc.push(selectedRow.locale);
639
913
  }
640
914
  return acc;
641
915
  }, []);
916
+ const enableDraftRelationsCount = false;
642
917
  const {
643
918
  data: draftRelationsCount = 0,
644
919
  isLoading: isDraftRelationsLoading,
@@ -647,10 +922,10 @@ const BulkLocalePublishAction = ({
647
922
  {
648
923
  model,
649
924
  documentIds: [documentId],
650
- locale: localesToPublish
925
+ locale: localesForAction
651
926
  },
652
927
  {
653
- skip: !documentId || localesToPublish.length === 0
928
+ skip: !enableDraftRelationsCount
654
929
  }
655
930
  );
656
931
  React__namespace.useEffect(() => {
@@ -676,7 +951,18 @@ const BulkLocalePublishAction = ({
676
951
  documentIds: [documentId],
677
952
  params: {
678
953
  ...params,
679
- locale: localesToPublish
954
+ locale: localesForAction
955
+ }
956
+ });
957
+ setSelectedRows([]);
958
+ };
959
+ const unpublish = async () => {
960
+ await unpublishManyAction({
961
+ model,
962
+ documentIds: [documentId],
963
+ params: {
964
+ ...params,
965
+ locale: localesForAction
680
966
  }
681
967
  });
682
968
  setSelectedRows([]);
@@ -684,14 +970,12 @@ const BulkLocalePublishAction = ({
684
970
  const handleAction = async () => {
685
971
  if (draftRelationsCount > 0) {
686
972
  setIsDraftRelationConfirmationOpen(true);
687
- } else {
973
+ } else if (isBulkPublish) {
688
974
  await publish();
975
+ } else {
976
+ await unpublish();
689
977
  }
690
978
  };
691
- const isUnpublish = document?.status === "published";
692
- if (isUnpublish) {
693
- console.warn(["I18N"], "Bulk locale unpublish modal not implemented");
694
- }
695
979
  if (isDraftRelationConfirmationOpen) {
696
980
  return {
697
981
  label: formatMessage({
@@ -729,18 +1013,18 @@ const BulkLocalePublishAction = ({
729
1013
  const hasPermission = selectedRows.map(({ locale }) => locale).every((locale) => canPublish.includes(locale));
730
1014
  return {
731
1015
  label: formatMessage({
732
- id: getTranslation("CMEditViewBulkLocale.publish-title"),
733
- defaultMessage: "Publish Multiple Locales"
1016
+ id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
1017
+ defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
734
1018
  }),
735
- icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ListPlus, {}),
736
- disabled: isPublishedTab || canPublish.length === 0,
1019
+ variant: isBulkPublish ? "secondary" : "danger",
1020
+ icon: isBulkPublish ? /* @__PURE__ */ jsxRuntime.jsx(icons.ListPlus, {}) : /* @__PURE__ */ jsxRuntime.jsx(icons.Cross, {}),
1021
+ disabled: isOnPublishedTab || canPublish.length === 0,
737
1022
  position: ["panel"],
738
- variant: "secondary",
739
1023
  dialog: {
740
1024
  type: "modal",
741
1025
  title: formatMessage({
742
- id: getTranslation("CMEditViewBulkLocale.publish-title"),
743
- defaultMessage: "Publish Multiple Locales"
1026
+ id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
1027
+ defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
744
1028
  }),
745
1029
  content: () => {
746
1030
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -759,7 +1043,8 @@ const BulkLocalePublishAction = ({
759
1043
  validationErrors,
760
1044
  headers,
761
1045
  rows,
762
- localesMetadata
1046
+ localesMetadata,
1047
+ action: action ?? "bulk-publish"
763
1048
  }
764
1049
  )
765
1050
  }
@@ -769,18 +1054,24 @@ const BulkLocalePublishAction = ({
769
1054
  designSystem.Button,
770
1055
  {
771
1056
  loading: isDraftRelationsLoading,
772
- disabled: !hasPermission || localesToPublish.length === 0,
1057
+ disabled: !hasPermission || localesForAction.length === 0,
773
1058
  variant: "default",
774
1059
  onClick: handleAction,
775
1060
  children: formatMessage({
776
- id: "app.utils.publish",
777
- defaultMessage: "Publish"
1061
+ id: isBulkPublish ? "app.utils.publish" : "app.utils.unpublish",
1062
+ defaultMessage: isBulkPublish ? "Publish" : "Unpublish"
778
1063
  })
779
1064
  }
780
1065
  ) })
781
1066
  }
782
1067
  };
783
1068
  };
1069
+ const BulkLocalePublishAction = (props) => {
1070
+ return BulkLocaleAction({ action: "bulk-publish", ...props });
1071
+ };
1072
+ const BulkLocaleUnpublishAction = (props) => {
1073
+ return BulkLocaleAction({ action: "bulk-unpublish", ...props });
1074
+ };
784
1075
  const StyledTrash = styledComponents.styled(icons.Trash)`
785
1076
  path {
786
1077
  fill: currentColor;
@@ -1132,9 +1423,6 @@ const localeMiddleware = (ctx) => (next) => (permissions) => {
1132
1423
  return next(revisedPermissions);
1133
1424
  };
1134
1425
  const prefixPluginTranslations = (trad, pluginId2) => {
1135
- if (!pluginId2) {
1136
- throw new TypeError("pluginId can't be empty");
1137
- }
1138
1426
  return Object.keys(trad).reduce((acc, current) => {
1139
1427
  acc[`${pluginId2}.${current}`] = trad[current];
1140
1428
  return acc;
@@ -1204,11 +1492,11 @@ const index = {
1204
1492
  },
1205
1493
  id: "internationalization",
1206
1494
  to: "internationalization",
1207
- Component: () => Promise.resolve().then(() => require("./SettingsPage-a96ZyFLy.js")).then((mod) => ({ default: mod.ProtectedSettingsPage })),
1495
+ Component: () => Promise.resolve().then(() => require("./SettingsPage-Bcj7380u.js")).then((mod) => ({ default: mod.ProtectedSettingsPage })),
1208
1496
  permissions: PERMISSIONS.accessMain
1209
1497
  });
1210
1498
  const contentManager = app.getPlugin("content-manager");
1211
- contentManager.apis.addDocumentHeaderAction([LocalePickerAction]);
1499
+ contentManager.apis.addDocumentHeaderAction([LocalePickerAction, FillFromAnotherLocaleAction]);
1212
1500
  contentManager.apis.addDocumentAction((actions) => {
1213
1501
  const indexOfDeleteAction = actions.findIndex((action) => action.type === "delete");
1214
1502
  actions.splice(indexOfDeleteAction, 0, DeleteLocaleAction);
@@ -1216,6 +1504,7 @@ const index = {
1216
1504
  });
1217
1505
  contentManager.apis.addDocumentAction((actions) => {
1218
1506
  actions.splice(2, 0, BulkLocalePublishAction);
1507
+ actions.splice(5, 0, BulkLocaleUnpublishAction);
1219
1508
  return actions;
1220
1509
  });
1221
1510
  contentManager.injectComponent("listView", "actions", {
@@ -1321,7 +1610,7 @@ const index = {
1321
1610
  async registerTrads({ locales }) {
1322
1611
  const importedTrads = await Promise.all(
1323
1612
  locales.map((locale) => {
1324
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/de.json": () => Promise.resolve().then(() => require("./de-DtWiGdHl.js")), "./translations/dk.json": () => Promise.resolve().then(() => require("./dk-D8C-casx.js")), "./translations/en.json": () => Promise.resolve().then(() => require("./en-BsOU9o5z.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-DS-XFGSw.js")), "./translations/fr.json": () => Promise.resolve().then(() => require("./fr-BTjekDpq.js")), "./translations/ko.json": () => Promise.resolve().then(() => require("./ko-DmcGUBQ3.js")), "./translations/pl.json": () => Promise.resolve().then(() => require("./pl-Cn5RYonZ.js")), "./translations/ru.json": () => Promise.resolve().then(() => require("./ru-BMBgVL3s.js")), "./translations/tr.json": () => Promise.resolve().then(() => require("./tr-CarUU76c.js")), "./translations/zh-Hans.json": () => Promise.resolve().then(() => require("./zh-Hans-DSHIXAa3.js")), "./translations/zh.json": () => Promise.resolve().then(() => require("./zh-CukOviB0.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
1613
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/de.json": () => Promise.resolve().then(() => require("./de-DtWiGdHl.js")), "./translations/dk.json": () => Promise.resolve().then(() => require("./dk-D8C-casx.js")), "./translations/en.json": () => Promise.resolve().then(() => require("./en-BKBz3tro.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-DS-XFGSw.js")), "./translations/fr.json": () => Promise.resolve().then(() => require("./fr-BTjekDpq.js")), "./translations/ko.json": () => Promise.resolve().then(() => require("./ko-DmcGUBQ3.js")), "./translations/pl.json": () => Promise.resolve().then(() => require("./pl-Cn5RYonZ.js")), "./translations/ru.json": () => Promise.resolve().then(() => require("./ru-BMBgVL3s.js")), "./translations/tr.json": () => Promise.resolve().then(() => require("./tr-CarUU76c.js")), "./translations/zh-Hans.json": () => Promise.resolve().then(() => require("./zh-Hans-DSHIXAa3.js")), "./translations/zh.json": () => Promise.resolve().then(() => require("./zh-CukOviB0.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
1325
1614
  return {
1326
1615
  data: prefixPluginTranslations(data, pluginId),
1327
1616
  locale
@@ -1345,4 +1634,4 @@ exports.useDeleteLocaleMutation = useDeleteLocaleMutation;
1345
1634
  exports.useGetDefaultLocalesQuery = useGetDefaultLocalesQuery;
1346
1635
  exports.useGetLocalesQuery = useGetLocalesQuery;
1347
1636
  exports.useUpdateLocaleMutation = useUpdateLocaleMutation;
1348
- //# sourceMappingURL=index-sfNkjx75.js.map
1637
+ //# sourceMappingURL=index-BKZbxhpm.js.map