@strapi/i18n 0.0.0-experimental.60f3ded53a22a24d208ebf6df9b84c118aa97abf → 0.0.0-experimental.626cf5324f21d318dee435c11cb3e08bb4c414b7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/LICENSE +18 -3
  2. package/dist/_chunks/{SettingsPage-B5sTcP82.mjs → SettingsPage-BjxjwEOb.mjs} +6 -6
  3. package/dist/_chunks/SettingsPage-BjxjwEOb.mjs.map +1 -0
  4. package/dist/_chunks/{SettingsPage-DT1sxWa2.js → SettingsPage-CfTmCkup.js} +6 -6
  5. package/dist/_chunks/SettingsPage-CfTmCkup.js.map +1 -0
  6. package/dist/_chunks/{en-CM6Pjfyv.mjs → en-2xztdZE1.mjs} +7 -1
  7. package/dist/_chunks/en-2xztdZE1.mjs.map +1 -0
  8. package/dist/_chunks/{en-BsOU9o5z.js → en-DWpfm8h5.js} +7 -1
  9. package/dist/_chunks/en-DWpfm8h5.js.map +1 -0
  10. package/dist/_chunks/{index-jMrzaEb9.js → index-5XLZwzwx.js} +341 -146
  11. package/dist/_chunks/index-5XLZwzwx.js.map +1 -0
  12. package/dist/_chunks/{index-DsNqyQKx.mjs → index-D-qx3tz4.mjs} +337 -142
  13. package/dist/_chunks/index-D-qx3tz4.mjs.map +1 -0
  14. package/dist/admin/index.js +1 -1
  15. package/dist/admin/index.mjs +1 -1
  16. package/dist/admin/src/components/BulkLocaleActionModal.d.ts +2 -1
  17. package/dist/admin/src/components/CMHeaderActions.d.ts +27 -3
  18. package/dist/admin/src/utils/clean.d.ts +4 -0
  19. package/dist/admin/src/utils/schemas.d.ts +1 -0
  20. package/dist/server/index.js +38 -9
  21. package/dist/server/index.js.map +1 -1
  22. package/dist/server/index.mjs +39 -10
  23. package/dist/server/index.mjs.map +1 -1
  24. package/dist/server/src/bootstrap.d.ts.map +1 -1
  25. package/dist/server/src/index.d.ts +14 -2
  26. package/dist/server/src/index.d.ts.map +1 -1
  27. package/dist/server/src/services/index.d.ts +14 -2
  28. package/dist/server/src/services/index.d.ts.map +1 -1
  29. package/dist/server/src/services/permissions/actions.d.ts +14 -2
  30. package/dist/server/src/services/permissions/actions.d.ts.map +1 -1
  31. package/dist/server/src/services/permissions.d.ts +14 -2
  32. package/dist/server/src/services/permissions.d.ts.map +1 -1
  33. package/package.json +9 -9
  34. package/dist/_chunks/SettingsPage-B5sTcP82.mjs.map +0 -1
  35. package/dist/_chunks/SettingsPage-DT1sxWa2.js.map +0 -1
  36. package/dist/_chunks/en-BsOU9o5z.js.map +0 -1
  37. package/dist/_chunks/en-CM6Pjfyv.mjs.map +0 -1
  38. package/dist/_chunks/index-DsNqyQKx.mjs.map +0 -1
  39. package/dist/_chunks/index-jMrzaEb9.js.map +0 -1
  40. package/dist/admin/src/components/Initializer.d.ts +0 -5
@@ -7,6 +7,7 @@ const designSystem = require("@strapi/design-system");
7
7
  const icons = require("@strapi/icons");
8
8
  const reactIntl = require("react-intl");
9
9
  const styledComponents = require("styled-components");
10
+ const query = require("@reduxjs/toolkit/query");
10
11
  const strapiAdmin = require("@strapi/admin/strapi-admin");
11
12
  const strapiAdmin$1 = require("@strapi/content-manager/strapi-admin");
12
13
  const reactRouterDom = require("react-router-dom");
@@ -160,7 +161,7 @@ const useI18n = () => {
160
161
  model: params.slug
161
162
  },
162
163
  {
163
- skip: !params.slug || !params.collectionType
164
+ skip: true
164
165
  }
165
166
  );
166
167
  if (doesPluginOptionsHaveI18nLocalized(schema?.pluginOptions)) {
@@ -240,10 +241,93 @@ const relationsApi = i18nApi.injectEndpoints({
240
241
  })
241
242
  });
242
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
+ ]);
257
+ const cleanedDataWithoutPasswordAndRelation = recursiveRemoveFieldTypes(
258
+ cleanedData,
259
+ schema,
260
+ components,
261
+ ["relation", "password"]
262
+ );
263
+ return cleanedDataWithoutPasswordAndRelation;
264
+ };
265
+ const removeFields = (data, fields) => {
266
+ return Object.keys(data).reduce((acc, current) => {
267
+ if (fields.includes(current)) {
268
+ return acc;
269
+ }
270
+ acc[current] = data[current];
271
+ return acc;
272
+ }, {});
273
+ };
274
+ const recursiveRemoveFieldTypes = (data, schema, components, fields) => {
275
+ return Object.keys(data).reduce((acc, current) => {
276
+ const attribute = schema.attributes[current] ?? { type: void 0 };
277
+ if (fields.includes(attribute.type)) {
278
+ return acc;
279
+ }
280
+ if (attribute.type === "dynamiczone") {
281
+ acc[current] = data[current].map((componentValue, index2) => {
282
+ const { id: _, ...rest } = recursiveRemoveFieldTypes(
283
+ componentValue,
284
+ components[componentValue.__component],
285
+ components,
286
+ fields
287
+ );
288
+ return {
289
+ ...rest,
290
+ __temp_key__: index2 + 1
291
+ };
292
+ });
293
+ } else if (attribute.type === "component") {
294
+ const { repeatable, component } = attribute;
295
+ if (repeatable) {
296
+ acc[current] = (data[current] ?? []).map((compoData, index2) => {
297
+ const { id: _, ...rest } = recursiveRemoveFieldTypes(
298
+ compoData,
299
+ components[component],
300
+ components,
301
+ fields
302
+ );
303
+ return {
304
+ ...rest,
305
+ __temp_key__: index2 + 1
306
+ };
307
+ });
308
+ } else {
309
+ const { id: _, ...rest } = recursiveRemoveFieldTypes(
310
+ data[current] ?? {},
311
+ components[component],
312
+ components,
313
+ fields
314
+ );
315
+ acc[current] = rest;
316
+ }
317
+ } else {
318
+ acc[current] = data[current];
319
+ }
320
+ return acc;
321
+ }, {});
322
+ };
243
323
  const isErrorMessageDescriptor = (object) => {
244
324
  return typeof object === "object" && object !== null && "id" in object && "defaultMessage" in object;
245
325
  };
246
- const EntryValidationText = ({ status = "draft", validationErrors }) => {
326
+ const EntryValidationText = ({
327
+ status = "draft",
328
+ validationErrors,
329
+ action
330
+ }) => {
247
331
  const { formatMessage } = reactIntl.useIntl();
248
332
  const getErrorStr = (key, value) => {
249
333
  if (typeof value === "string") {
@@ -277,30 +361,63 @@ const EntryValidationText = ({ status = "draft", validationErrors }) => {
277
361
  ) })
278
362
  ] });
279
363
  }
280
- if (status === "published") {
281
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
282
- /* @__PURE__ */ jsxRuntime.jsx(icons.CheckCircle, { fill: "success600" }),
283
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
284
- id: "content-manager.bulk-publish.already-published",
285
- defaultMessage: "Already Published"
286
- }) })
287
- ] });
288
- }
289
- if (status === "modified") {
290
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
291
- /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowsCounterClockwise, { fill: "alternative600" }),
292
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
293
- id: "app.utils.ready-to-publish-changes",
294
- defaultMessage: "Ready to publish changes"
295
- }) })
296
- ] });
297
- }
364
+ const getStatusMessage = () => {
365
+ if (action === "bulk-publish") {
366
+ if (status === "published") {
367
+ return {
368
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.CheckCircle, { fill: "success600" }),
369
+ text: formatMessage({
370
+ id: "content-manager.bulk-publish.already-published",
371
+ defaultMessage: "Already Published"
372
+ }),
373
+ textColor: "success600",
374
+ fontWeight: "bold"
375
+ };
376
+ } else if (status === "modified") {
377
+ return {
378
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowsCounterClockwise, { fill: "alternative600" }),
379
+ text: formatMessage({
380
+ id: "app.utils.ready-to-publish-changes",
381
+ defaultMessage: "Ready to publish changes"
382
+ })
383
+ };
384
+ } else {
385
+ return {
386
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.CheckCircle, { fill: "success600" }),
387
+ text: formatMessage({
388
+ id: "app.utils.ready-to-publish",
389
+ defaultMessage: "Ready to publish"
390
+ })
391
+ };
392
+ }
393
+ } else {
394
+ if (status === "draft") {
395
+ return {
396
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.CheckCircle, { fill: "success600" }),
397
+ text: formatMessage({
398
+ id: "content-manager.bulk-unpublish.already-unpublished",
399
+ defaultMessage: "Already Unpublished"
400
+ }),
401
+ textColor: "success600",
402
+ fontWeight: "bold"
403
+ };
404
+ } else {
405
+ return {
406
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.CheckCircle, { fill: "success600" }),
407
+ text: formatMessage({
408
+ id: "app.utils.ready-to-unpublish-changes",
409
+ defaultMessage: "Ready to unpublish"
410
+ }),
411
+ textColor: "success600",
412
+ fontWeight: "bold"
413
+ };
414
+ }
415
+ }
416
+ };
417
+ const { icon, text, textColor = "success600", fontWeight = "normal" } = getStatusMessage();
298
418
  return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
299
- /* @__PURE__ */ jsxRuntime.jsx(icons.CheckCircle, { fill: "success600" }),
300
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
301
- id: "app.utils.ready-to-publish",
302
- defaultMessage: "Ready to publish"
303
- }) })
419
+ icon,
420
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor, fontWeight, children: text })
304
421
  ] });
305
422
  };
306
423
  const BoldChunk = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: chunks });
@@ -308,7 +425,8 @@ const BulkLocaleActionModal = ({
308
425
  headers,
309
426
  rows,
310
427
  localesMetadata,
311
- validationErrors = {}
428
+ validationErrors = {},
429
+ action
312
430
  }) => {
313
431
  const { formatMessage } = reactIntl.useIntl();
314
432
  const selectedRows = strapiAdmin.useTable(
@@ -321,27 +439,29 @@ const BulkLocaleActionModal = ({
321
439
  return acc;
322
440
  }, {});
323
441
  const localesWithErrors = Object.keys(validationErrors);
324
- const alreadyPublishedCount = selectedRows.filter(
442
+ const publishedCount = selectedRows.filter(
325
443
  ({ locale }) => currentStatusByLocale[locale] === "published"
326
444
  ).length;
327
- const readyToPublishCount = selectedRows.filter(
445
+ const draftCount = selectedRows.filter(
328
446
  ({ locale }) => (currentStatusByLocale[locale] === "draft" || currentStatusByLocale[locale] === "modified") && !localesWithErrors.includes(locale)
329
447
  ).length;
330
448
  const withErrorsCount = localesWithErrors.length;
449
+ const messageId = action === "bulk-publish" ? "content-manager.containers.list.selectedEntriesModal.selectedCount.publish" : "content-manager.containers.list.selectedEntriesModal.selectedCount.unpublish";
450
+ 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.";
331
451
  return formatMessage(
332
452
  {
333
- id: "content-manager.containers.list.selectedEntriesModal.selectedCount",
334
- 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."
453
+ id: messageId,
454
+ defaultMessage
335
455
  },
336
456
  {
337
457
  withErrorsCount,
338
- readyToPublishCount,
339
- alreadyPublishedCount,
458
+ draftCount,
459
+ publishedCount,
340
460
  b: BoldChunk
341
461
  }
342
462
  );
343
463
  };
344
- return /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
464
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Body, { children: [
345
465
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: getFormattedCountMessage() }),
346
466
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 5, children: /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Content, { children: [
347
467
  /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Head, { children: [
@@ -368,7 +488,7 @@ const BulkLocaleActionModal = ({
368
488
  children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "span", variant: "pi", fontWeight: "bold", children: capitalize(status) })
369
489
  }
370
490
  ) }) }),
371
- /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(EntryValidationText, { validationErrors: error, status }) }),
491
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(EntryValidationText, { validationErrors: error, status, action }) }),
372
492
  /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
373
493
  designSystem.IconButton,
374
494
  {
@@ -385,7 +505,7 @@ const BulkLocaleActionModal = ({
385
505
  name: locale
386
506
  }
387
507
  ),
388
- borderWidth: 0,
508
+ variant: "ghost",
389
509
  children: /* @__PURE__ */ jsxRuntime.jsx(icons.Pencil, {})
390
510
  }
391
511
  ) })
@@ -402,42 +522,47 @@ const LocalePickerAction = ({
402
522
  documentId
403
523
  }) => {
404
524
  const { formatMessage } = reactIntl.useIntl();
405
- const [{ query }, setQuery] = strapiAdmin.useQueryParams();
525
+ const [{ query: query2 }, setQuery] = strapiAdmin.useQueryParams();
406
526
  const { hasI18n, canCreate, canRead } = useI18n();
407
527
  const { data: locales = [] } = useGetLocalesQuery();
408
- const { schema } = strapiAdmin$1.unstable_useDocument({ model, collectionType, documentId });
528
+ const currentDesiredLocale = query2.plugins?.i18n?.locale;
529
+ const { schema } = strapiAdmin$1.unstable_useDocument({
530
+ model,
531
+ collectionType,
532
+ documentId,
533
+ params: { locale: currentDesiredLocale }
534
+ });
409
535
  const handleSelect = React__namespace.useCallback(
410
536
  (value) => {
411
537
  setQuery({
412
538
  plugins: {
413
- ...query.plugins,
539
+ ...query2.plugins,
414
540
  i18n: {
415
541
  locale: value
416
542
  }
417
543
  }
418
544
  });
419
545
  },
420
- [query.plugins, setQuery]
546
+ [query2.plugins, setQuery]
421
547
  );
422
548
  React__namespace.useEffect(() => {
423
549
  if (!Array.isArray(locales) || !hasI18n) {
424
550
  return;
425
551
  }
426
- const currentDesiredLocale = query.plugins?.i18n?.locale;
427
552
  const doesLocaleExist = locales.find((loc) => loc.code === currentDesiredLocale);
428
553
  const defaultLocale = locales.find((locale) => locale.isDefault);
429
554
  if (!doesLocaleExist && defaultLocale?.code) {
430
555
  handleSelect(defaultLocale.code);
431
556
  }
432
- }, [handleSelect, hasI18n, locales, query.plugins?.i18n?.locale]);
433
- if (!hasI18n || !Array.isArray(locales) || locales.length === 0) {
434
- return null;
435
- }
436
- const currentLocale = query.plugins?.i18n?.locale || locales.find((loc) => loc.isDefault)?.code;
557
+ }, [handleSelect, hasI18n, locales, currentDesiredLocale]);
558
+ const currentLocale = Array.isArray(locales) ? locales.find((locale) => locale.code === currentDesiredLocale)?.code : void 0;
437
559
  const allCurrentLocales = [
438
560
  { status: getDocumentStatus(document, meta), locale: currentLocale },
439
561
  ...meta?.availableLocales ?? []
440
562
  ];
563
+ if (!hasI18n || !Array.isArray(locales) || locales.length === 0) {
564
+ return null;
565
+ }
441
566
  return {
442
567
  label: formatMessage({
443
568
  id: getTranslation("Settings.locales.modal.locales.label"),
@@ -449,7 +574,7 @@ const LocalePickerAction = ({
449
574
  );
450
575
  const status = currentLocaleDoc?.status ?? "draft";
451
576
  const permissionsToCheck = currentLocaleDoc ? canCreate : canRead;
452
- const statusVariant = status === "draft" ? "primary" : status === "published" ? "success" : "alternative";
577
+ const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
453
578
  return {
454
579
  disabled: !permissionsToCheck.includes(locale.code),
455
580
  value: locale.code,
@@ -485,6 +610,95 @@ const getDocumentStatus = (document, meta) => {
485
610
  }
486
611
  return docStatus;
487
612
  };
613
+ const FillFromAnotherLocaleAction = ({
614
+ documentId,
615
+ meta,
616
+ model,
617
+ collectionType
618
+ }) => {
619
+ const { formatMessage } = reactIntl.useIntl();
620
+ const [{ query: query2 }] = strapiAdmin.useQueryParams();
621
+ const currentDesiredLocale = query2.plugins?.i18n?.locale;
622
+ const [localeSelected, setLocaleSelected] = React__namespace.useState(null);
623
+ const setValues = strapiAdmin.useForm("FillFromAnotherLocale", (state) => state.setValues);
624
+ const { getDocument } = strapiAdmin$1.unstable_useDocumentActions();
625
+ const { schema, components } = strapiAdmin$1.unstable_useDocument({
626
+ model,
627
+ documentId,
628
+ collectionType,
629
+ params: { locale: currentDesiredLocale }
630
+ });
631
+ const { data: locales = [] } = useGetLocalesQuery();
632
+ const availableLocales = Array.isArray(locales) ? locales.filter((locale) => meta?.availableLocales.some((l) => l.locale === locale.code)) : [];
633
+ const fillFromLocale = (onClose) => async () => {
634
+ const response = await getDocument({
635
+ collectionType,
636
+ model,
637
+ documentId,
638
+ params: { locale: localeSelected }
639
+ });
640
+ if (!response || !schema) {
641
+ return;
642
+ }
643
+ const { data } = response;
644
+ const cleanedData = cleanData(data, schema, components);
645
+ setValues(cleanedData);
646
+ onClose();
647
+ };
648
+ return {
649
+ type: "icon",
650
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Download, {}),
651
+ disabled: availableLocales.length === 0,
652
+ label: formatMessage({
653
+ id: getTranslation("CMEditViewCopyLocale.copy-text"),
654
+ defaultMessage: "Fill in from another locale"
655
+ }),
656
+ dialog: {
657
+ type: "dialog",
658
+ title: formatMessage({
659
+ id: getTranslation("CMEditViewCopyLocale.dialog.title"),
660
+ defaultMessage: "Confirmation"
661
+ }),
662
+ content: ({ onClose }) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
663
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 3, children: [
664
+ /* @__PURE__ */ jsxRuntime.jsx(icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
665
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textAlign: "center", children: formatMessage({
666
+ id: getTranslation("CMEditViewCopyLocale.dialog.body"),
667
+ defaultMessage: "Your current content will be erased and filled by the content of the selected locale:"
668
+ }) }),
669
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { width: "100%", children: [
670
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: formatMessage({
671
+ id: getTranslation("CMEditViewCopyLocale.dialog.field.label"),
672
+ defaultMessage: "Locale"
673
+ }) }),
674
+ /* @__PURE__ */ jsxRuntime.jsx(
675
+ designSystem.SingleSelect,
676
+ {
677
+ value: localeSelected,
678
+ placeholder: formatMessage({
679
+ id: getTranslation("CMEditViewCopyLocale.dialog.field.placeholder"),
680
+ defaultMessage: "Select one locale..."
681
+ }),
682
+ onChange: (value) => setLocaleSelected(value),
683
+ children: availableLocales.map((locale) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: locale.code, children: locale.name }, locale.code))
684
+ }
685
+ )
686
+ ] })
687
+ ] }) }),
688
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, width: "100%", children: [
689
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { flex: "auto", variant: "tertiary", onClick: onClose, children: formatMessage({
690
+ id: getTranslation("CMEditViewCopyLocale.cancel-text"),
691
+ defaultMessage: "No, cancel"
692
+ }) }),
693
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { flex: "auto", variant: "success", onClick: fillFromLocale(onClose), children: formatMessage({
694
+ id: getTranslation("CMEditViewCopyLocale.submit-text"),
695
+ defaultMessage: "Yes, fill in"
696
+ }) })
697
+ ] }) })
698
+ ] })
699
+ }
700
+ };
701
+ };
488
702
  const DeleteLocaleAction = ({
489
703
  document,
490
704
  documentId,
@@ -548,37 +762,43 @@ const DeleteLocaleAction = ({
548
762
  }
549
763
  };
550
764
  };
551
- const BulkLocalePublishAction = ({
765
+ const BulkLocaleAction = ({
552
766
  document: baseDocument,
553
767
  documentId,
554
768
  model,
555
- collectionType
769
+ collectionType,
770
+ action
556
771
  }) => {
557
772
  const baseLocale = baseDocument?.locale ?? null;
558
- const [{ query }] = strapiAdmin.useQueryParams();
559
- const params = React__namespace.useMemo(() => strapiAdmin$1.buildValidParams(query), [query]);
560
- const isPublishedTab = query.status === "published";
773
+ const [{ query: query$1 }] = strapiAdmin.useQueryParams();
774
+ const params = React__namespace.useMemo(() => strapiAdmin$1.buildValidParams(query$1), [query$1]);
775
+ const isOnPublishedTab = query$1.status === "published";
561
776
  const { formatMessage } = reactIntl.useIntl();
562
777
  const { hasI18n, canPublish } = useI18n();
563
778
  const { toggleNotification } = strapiAdmin.useNotification();
564
779
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
565
780
  const [selectedRows, setSelectedRows] = React__namespace.useState([]);
566
781
  const [isDraftRelationConfirmationOpen, setIsDraftRelationConfirmationOpen] = React__namespace.useState(false);
567
- const { publishMany: publishManyAction } = strapiAdmin$1.unstable_useDocumentActions();
782
+ const { publishMany: publishManyAction, unpublishMany: unpublishManyAction } = strapiAdmin$1.unstable_useDocumentActions();
568
783
  const {
569
784
  document,
570
785
  meta: documentMeta,
571
786
  schema,
572
787
  validate
573
- } = strapiAdmin$1.unstable_useDocument({
574
- model,
575
- collectionType,
576
- documentId,
577
- params: {
578
- locale: baseLocale
788
+ } = strapiAdmin$1.unstable_useDocument(
789
+ {
790
+ model,
791
+ collectionType,
792
+ documentId,
793
+ params: {
794
+ locale: baseLocale
795
+ }
796
+ },
797
+ {
798
+ skip: !hasI18n || !baseLocale
579
799
  }
580
- });
581
- const { data: localesMetadata = [] } = useGetLocalesQuery();
800
+ );
801
+ const { data: localesMetadata = [] } = useGetLocalesQuery(hasI18n ? void 0 : query.skipToken);
582
802
  const headers = [
583
803
  {
584
804
  label: formatMessage({
@@ -627,12 +847,19 @@ const BulkLocalePublishAction = ({
627
847
  }, {});
628
848
  return [rowsFromMeta, errors];
629
849
  }, [document, documentMeta?.availableLocales, validate]);
630
- const localesToPublish = selectedRows.reduce((acc, selectedRow) => {
631
- if (selectedRow.status !== "published" && !Object.keys(validationErrors).includes(selectedRow.locale)) {
850
+ const isBulkPublish = action === "bulk-publish";
851
+ const localesForAction = selectedRows.reduce((acc, selectedRow) => {
852
+ const isValidLocale = (
853
+ // Validation errors are irrelevant if we are trying to unpublish
854
+ !isBulkPublish || !Object.keys(validationErrors).includes(selectedRow.locale)
855
+ );
856
+ const shouldAddLocale = isBulkPublish ? selectedRow.status !== "published" && isValidLocale : selectedRow.status !== "draft" && isValidLocale;
857
+ if (shouldAddLocale) {
632
858
  acc.push(selectedRow.locale);
633
859
  }
634
860
  return acc;
635
861
  }, []);
862
+ const enableDraftRelationsCount = false;
636
863
  const {
637
864
  data: draftRelationsCount = 0,
638
865
  isLoading: isDraftRelationsLoading,
@@ -641,10 +868,10 @@ const BulkLocalePublishAction = ({
641
868
  {
642
869
  model,
643
870
  documentIds: [documentId],
644
- locale: localesToPublish
871
+ locale: localesForAction
645
872
  },
646
873
  {
647
- skip: !documentId || localesToPublish.length === 0
874
+ skip: !enableDraftRelationsCount
648
875
  }
649
876
  );
650
877
  React__namespace.useEffect(() => {
@@ -670,7 +897,18 @@ const BulkLocalePublishAction = ({
670
897
  documentIds: [documentId],
671
898
  params: {
672
899
  ...params,
673
- locale: localesToPublish
900
+ locale: localesForAction
901
+ }
902
+ });
903
+ setSelectedRows([]);
904
+ };
905
+ const unpublish = async () => {
906
+ await unpublishManyAction({
907
+ model,
908
+ documentIds: [documentId],
909
+ params: {
910
+ ...params,
911
+ locale: localesForAction
674
912
  }
675
913
  });
676
914
  setSelectedRows([]);
@@ -678,14 +916,12 @@ const BulkLocalePublishAction = ({
678
916
  const handleAction = async () => {
679
917
  if (draftRelationsCount > 0) {
680
918
  setIsDraftRelationConfirmationOpen(true);
681
- } else {
919
+ } else if (isBulkPublish) {
682
920
  await publish();
921
+ } else {
922
+ await unpublish();
683
923
  }
684
924
  };
685
- const isUnpublish = document?.status === "published";
686
- if (isUnpublish) {
687
- console.warn(["I18N"], "Bulk locale unpublish modal not implemented");
688
- }
689
925
  if (isDraftRelationConfirmationOpen) {
690
926
  return {
691
927
  label: formatMessage({
@@ -720,20 +956,21 @@ const BulkLocalePublishAction = ({
720
956
  }
721
957
  };
722
958
  }
959
+ const hasPermission = selectedRows.map(({ locale }) => locale).every((locale) => canPublish.includes(locale));
723
960
  return {
724
961
  label: formatMessage({
725
- id: getTranslation("CMEditViewBulkLocale.publish-title"),
726
- defaultMessage: "Publish Multiple Locales"
962
+ id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
963
+ defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
727
964
  }),
728
- icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ListPlus, {}),
729
- disabled: isPublishedTab || !canPublish,
965
+ variant: isBulkPublish ? "secondary" : "danger",
966
+ icon: isBulkPublish ? /* @__PURE__ */ jsxRuntime.jsx(icons.ListPlus, {}) : /* @__PURE__ */ jsxRuntime.jsx(icons.Cross, {}),
967
+ disabled: isOnPublishedTab || canPublish.length === 0,
730
968
  position: ["panel"],
731
- variant: "secondary",
732
969
  dialog: {
733
970
  type: "modal",
734
971
  title: formatMessage({
735
- id: getTranslation("CMEditViewBulkLocale.publish-title"),
736
- defaultMessage: "Publish Multiple Locales"
972
+ id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
973
+ defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
737
974
  }),
738
975
  content: () => {
739
976
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -752,28 +989,35 @@ const BulkLocalePublishAction = ({
752
989
  validationErrors,
753
990
  headers,
754
991
  rows,
755
- localesMetadata
992
+ localesMetadata,
993
+ action: action ?? "bulk-publish"
756
994
  }
757
995
  )
758
996
  }
759
997
  );
760
998
  },
761
- footer: () => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "flex-end", children: /* @__PURE__ */ jsxRuntime.jsx(
999
+ footer: () => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Footer, { justifyContent: "flex-end", children: /* @__PURE__ */ jsxRuntime.jsx(
762
1000
  designSystem.Button,
763
1001
  {
764
1002
  loading: isDraftRelationsLoading,
765
- disabled: localesToPublish.length === 0,
1003
+ disabled: !hasPermission || localesForAction.length === 0,
766
1004
  variant: "default",
767
1005
  onClick: handleAction,
768
1006
  children: formatMessage({
769
- id: "app.utils.publish",
770
- defaultMessage: "Publish"
1007
+ id: isBulkPublish ? "app.utils.publish" : "app.utils.unpublish",
1008
+ defaultMessage: isBulkPublish ? "Publish" : "Unpublish"
771
1009
  })
772
1010
  }
773
1011
  ) })
774
1012
  }
775
1013
  };
776
1014
  };
1015
+ const BulkLocalePublishAction = (props) => {
1016
+ return BulkLocaleAction({ action: "bulk-publish", ...props });
1017
+ };
1018
+ const BulkLocaleUnpublishAction = (props) => {
1019
+ return BulkLocaleAction({ action: "bulk-unpublish", ...props });
1020
+ };
777
1021
  const StyledTrash = styledComponents.styled(icons.Trash)`
778
1022
  path {
779
1023
  fill: currentColor;
@@ -830,16 +1074,9 @@ const UnpublishModalAdditionalInfo = () => {
830
1074
  }
831
1075
  ) });
832
1076
  };
833
- const Initializer = ({ setPlugin }) => {
834
- const setPluginRef = React__namespace.useRef(setPlugin);
835
- React__namespace.useEffect(() => {
836
- setPluginRef.current(pluginId);
837
- }, []);
838
- return null;
839
- };
840
1077
  const LocalePicker = () => {
841
1078
  const { formatMessage } = reactIntl.useIntl();
842
- const [{ query }, setQuery] = strapiAdmin.useQueryParams();
1079
+ const [{ query: query2 }, setQuery] = strapiAdmin.useQueryParams();
843
1080
  const { hasI18n, canRead, canCreate } = useI18n();
844
1081
  const { data: locales = [] } = useGetLocalesQuery(void 0, {
845
1082
  skip: !hasI18n
@@ -849,25 +1086,25 @@ const LocalePicker = () => {
849
1086
  setQuery(
850
1087
  {
851
1088
  page: 1,
852
- plugins: { ...query.plugins, i18n: { locale: code } }
1089
+ plugins: { ...query2.plugins, i18n: { locale: code } }
853
1090
  },
854
1091
  "push",
855
1092
  replace
856
1093
  );
857
1094
  },
858
- [query.plugins, setQuery]
1095
+ [query2.plugins, setQuery]
859
1096
  );
860
1097
  React__namespace.useEffect(() => {
861
1098
  if (!Array.isArray(locales) || !hasI18n) {
862
1099
  return;
863
1100
  }
864
- const currentDesiredLocale = query.plugins?.i18n?.locale;
1101
+ const currentDesiredLocale = query2.plugins?.i18n?.locale;
865
1102
  const doesLocaleExist = locales.find((loc) => loc.code === currentDesiredLocale);
866
1103
  const defaultLocale = locales.find((locale) => locale.isDefault);
867
1104
  if (!doesLocaleExist && defaultLocale?.code) {
868
1105
  handleChange(defaultLocale.code, true);
869
1106
  }
870
- }, [hasI18n, handleChange, locales, query.plugins?.i18n?.locale]);
1107
+ }, [hasI18n, handleChange, locales, query2.plugins?.i18n?.locale]);
871
1108
  if (!hasI18n || !Array.isArray(locales) || locales.length === 0) {
872
1109
  return null;
873
1110
  }
@@ -882,7 +1119,7 @@ const LocalePicker = () => {
882
1119
  id: getTranslation("actions.select-locale"),
883
1120
  defaultMessage: "Select locale"
884
1121
  }),
885
- value: query.plugins?.i18n?.locale || locales.find((locale) => locale.isDefault)?.code,
1122
+ value: query2.plugins?.i18n?.locale || locales.find((locale) => locale.isDefault)?.code,
886
1123
  onChange: handleChange,
887
1124
  children: displayedLocales.map((locale) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: locale.code, children: locale.name }, locale.id))
888
1125
  }
@@ -1000,54 +1237,13 @@ const LocaleListCell = ({
1000
1237
  return locale.name;
1001
1238
  }).toSorted((a, b) => formatter.compare(a, b));
1002
1239
  return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Popover.Root, { children: [
1003
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Popover.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "button", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxRuntime.jsxs(
1004
- ActionWrapper,
1005
- {
1006
- minWidth: "100%",
1007
- alignItems: "center",
1008
- justifyContent: "center",
1009
- height: "3.2rem",
1010
- width: "3.2rem",
1011
- children: [
1012
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral800", ellipsis: true, children: localesForDocument.join(", ") }),
1013
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(icons.CaretDown, {}) })
1014
- ]
1015
- }
1016
- ) }) }),
1240
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Popover.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "ghost", type: "button", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { minWidth: "100%", alignItems: "center", justifyContent: "center", fontWeight: "regular", children: [
1241
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral800", ellipsis: true, marginRight: 2, children: localesForDocument.join(", ") }),
1242
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(icons.CaretDown, { width: "1.2rem", height: "1.2rem" }) })
1243
+ ] }) }) }),
1017
1244
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Popover.Content, { sideOffset: 16, children: /* @__PURE__ */ jsxRuntime.jsx("ul", { children: localesForDocument.map((name) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 3, tag: "li", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: name }) }, name)) }) })
1018
1245
  ] });
1019
1246
  };
1020
- const Button = styledComponents.styled.button`
1021
- width: 100%;
1022
-
1023
- svg {
1024
- > g,
1025
- path {
1026
- fill: ${({ theme }) => theme.colors.neutral500};
1027
- }
1028
- }
1029
- &:hover {
1030
- svg {
1031
- > g,
1032
- path {
1033
- fill: ${({ theme }) => theme.colors.neutral600};
1034
- }
1035
- }
1036
- }
1037
- &:active {
1038
- svg {
1039
- > g,
1040
- path {
1041
- fill: ${({ theme }) => theme.colors.neutral400};
1042
- }
1043
- }
1044
- }
1045
- `;
1046
- const ActionWrapper = styledComponents.styled(designSystem.Flex)`
1047
- svg {
1048
- height: 0.4rem;
1049
- }
1050
- `;
1051
1247
  const addColumnToTableHook = ({ displayedHeaders, layout }) => {
1052
1248
  const { options } = layout;
1053
1249
  const isFieldLocalized = doesPluginOptionsHaveI18nLocalized(options) ? options.i18n.localized : false;
@@ -1228,8 +1424,6 @@ const index = {
1228
1424
  app.addRBACMiddleware([localeMiddleware]);
1229
1425
  app.registerPlugin({
1230
1426
  id: pluginId,
1231
- initializer: Initializer,
1232
- isReady: false,
1233
1427
  name: pluginId
1234
1428
  });
1235
1429
  },
@@ -1247,11 +1441,11 @@ const index = {
1247
1441
  },
1248
1442
  id: "internationalization",
1249
1443
  to: "internationalization",
1250
- Component: () => Promise.resolve().then(() => require("./SettingsPage-DT1sxWa2.js")).then((mod) => ({ default: mod.ProtectedSettingsPage })),
1444
+ Component: () => Promise.resolve().then(() => require("./SettingsPage-CfTmCkup.js")).then((mod) => ({ default: mod.ProtectedSettingsPage })),
1251
1445
  permissions: PERMISSIONS.accessMain
1252
1446
  });
1253
1447
  const contentManager = app.getPlugin("content-manager");
1254
- contentManager.apis.addDocumentHeaderAction([LocalePickerAction]);
1448
+ contentManager.apis.addDocumentHeaderAction([LocalePickerAction, FillFromAnotherLocaleAction]);
1255
1449
  contentManager.apis.addDocumentAction((actions) => {
1256
1450
  const indexOfDeleteAction = actions.findIndex((action) => action.type === "delete");
1257
1451
  actions.splice(indexOfDeleteAction, 0, DeleteLocaleAction);
@@ -1259,6 +1453,7 @@ const index = {
1259
1453
  });
1260
1454
  contentManager.apis.addDocumentAction((actions) => {
1261
1455
  actions.splice(2, 0, BulkLocalePublishAction);
1456
+ actions.splice(5, 0, BulkLocaleUnpublishAction);
1262
1457
  return actions;
1263
1458
  });
1264
1459
  contentManager.injectComponent("listView", "actions", {
@@ -1364,7 +1559,7 @@ const index = {
1364
1559
  async registerTrads({ locales }) {
1365
1560
  const importedTrads = await Promise.all(
1366
1561
  locales.map((locale) => {
1367
- 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 }) => {
1562
+ 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-DWpfm8h5.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 }) => {
1368
1563
  return {
1369
1564
  data: prefixPluginTranslations(data, pluginId),
1370
1565
  locale
@@ -1388,4 +1583,4 @@ exports.useDeleteLocaleMutation = useDeleteLocaleMutation;
1388
1583
  exports.useGetDefaultLocalesQuery = useGetDefaultLocalesQuery;
1389
1584
  exports.useGetLocalesQuery = useGetLocalesQuery;
1390
1585
  exports.useUpdateLocaleMutation = useUpdateLocaleMutation;
1391
- //# sourceMappingURL=index-jMrzaEb9.js.map
1586
+ //# sourceMappingURL=index-5XLZwzwx.js.map