@strapi/i18n 0.0.0-experimental.3c73a4c6f6073abdf1608121a200c3d4d87b1aa8 → 0.0.0-experimental.3d5794391d4c2d9eddf7bd162c02f4bb836eb7a6

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 (56) hide show
  1. package/LICENSE +18 -3
  2. package/dist/_chunks/{SettingsPage-DnLLGeBa.js → SettingsPage-D0hqaut-.js} +93 -106
  3. package/dist/_chunks/SettingsPage-D0hqaut-.js.map +1 -0
  4. package/dist/_chunks/{SettingsPage-0FFSTUW2.mjs → SettingsPage-D67CaQAB.mjs} +95 -108
  5. package/dist/_chunks/SettingsPage-D67CaQAB.mjs.map +1 -0
  6. package/dist/_chunks/{en-Kv6y9zPQ.js → en-BKBz3tro.js} +12 -3
  7. package/dist/_chunks/en-BKBz3tro.js.map +1 -0
  8. package/dist/_chunks/{en-18tWw4P6.mjs → en-DlXfy6Gy.mjs} +12 -3
  9. package/dist/_chunks/en-DlXfy6Gy.mjs.map +1 -0
  10. package/dist/_chunks/{index-DtEKsPcR.js → index-46DNtLCn.js} +454 -229
  11. package/dist/_chunks/index-46DNtLCn.js.map +1 -0
  12. package/dist/_chunks/{index-BddUXwss.mjs → index-CNR8i3KM.mjs} +448 -223
  13. package/dist/_chunks/index-CNR8i3KM.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 +29 -3
  18. package/dist/admin/src/components/CreateLocale.d.ts +6 -6
  19. package/dist/admin/src/components/EditLocale.d.ts +5 -4
  20. package/dist/admin/src/contentReleasesHooks/releaseDetailsView.d.ts +9 -5
  21. package/dist/admin/src/utils/clean.d.ts +4 -0
  22. package/dist/admin/src/utils/schemas.d.ts +1 -0
  23. package/dist/server/index.js +413 -480
  24. package/dist/server/index.js.map +1 -1
  25. package/dist/server/index.mjs +415 -482
  26. package/dist/server/index.mjs.map +1 -1
  27. package/dist/server/src/bootstrap.d.ts +1 -4
  28. package/dist/server/src/bootstrap.d.ts.map +1 -1
  29. package/dist/server/src/index.d.ts +21 -13
  30. package/dist/server/src/index.d.ts.map +1 -1
  31. package/dist/server/src/register.d.ts.map +1 -1
  32. package/dist/server/src/services/index.d.ts +20 -10
  33. package/dist/server/src/services/index.d.ts.map +1 -1
  34. package/dist/server/src/services/permissions/actions.d.ts +14 -2
  35. package/dist/server/src/services/permissions/actions.d.ts.map +1 -1
  36. package/dist/server/src/services/permissions.d.ts +14 -2
  37. package/dist/server/src/services/permissions.d.ts.map +1 -1
  38. package/dist/server/src/services/sanitize/index.d.ts +11 -0
  39. package/dist/server/src/services/sanitize/index.d.ts.map +1 -0
  40. package/dist/server/src/utils/index.d.ts +2 -2
  41. package/dist/server/src/utils/index.d.ts.map +1 -1
  42. package/package.json +12 -12
  43. package/dist/_chunks/SettingsPage-0FFSTUW2.mjs.map +0 -1
  44. package/dist/_chunks/SettingsPage-DnLLGeBa.js.map +0 -1
  45. package/dist/_chunks/en-18tWw4P6.mjs.map +0 -1
  46. package/dist/_chunks/en-Kv6y9zPQ.js.map +0 -1
  47. package/dist/_chunks/index-BddUXwss.mjs.map +0 -1
  48. package/dist/_chunks/index-DtEKsPcR.js.map +0 -1
  49. package/dist/admin/src/components/Initializer.d.ts +0 -5
  50. package/dist/server/src/migrations/content-type/disable/index.d.ts +0 -3
  51. package/dist/server/src/migrations/content-type/disable/index.d.ts.map +0 -1
  52. package/dist/server/src/migrations/content-type/enable/index.d.ts +0 -3
  53. package/dist/server/src/migrations/content-type/enable/index.d.ts.map +0 -1
  54. package/dist/server/src/services/entity-service-decorator.d.ts +0 -29
  55. package/dist/server/src/services/entity-service-decorator.d.ts.map +0 -1
  56. package/strapi-server.js +0 -3
@@ -1,12 +1,13 @@
1
1
  import get from "lodash/get";
2
2
  import * as yup from "yup";
3
- import { jsxs, Fragment, jsx } from "react/jsx-runtime";
3
+ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
4
4
  import * as React from "react";
5
- import { Typography, Field, Checkbox, Dialog, DialogBody, Flex, DialogFooter, Button as Button$1, Box, Status, IconButton, Tooltip, SingleSelect, SingleSelectOption, VisuallyHidden, useCollator, Popover } from "@strapi/design-system";
6
- import { WarningCircle, Pencil, CrossCircle, CheckCircle, ArrowsCounterClockwise, Trash, ListPlus, Earth, EarthStriked, CaretDown } from "@strapi/icons";
5
+ import { Typography, Dialog, Field, Checkbox, Flex, Button, Modal, Box, Status, IconButton, Tooltip, SingleSelect, SingleSelectOption, VisuallyHidden, useCollator, Popover } from "@strapi/design-system";
6
+ import { WarningCircle, Pencil, CrossCircle, CheckCircle, ArrowsCounterClockwise, Trash, Plus, Download, ListPlus, Cross, Earth, EarthStriked, CaretDown } from "@strapi/icons";
7
7
  import { useIntl } from "react-intl";
8
8
  import { styled } from "styled-components";
9
- import { useAuth, adminApi, useTable, Table, useQueryParams, useNotification, useAPIErrorHandler } from "@strapi/admin/strapi-admin";
9
+ import { skipToken } from "@reduxjs/toolkit/query";
10
+ import { useAuth, adminApi, useTable, Table, useQueryParams, useForm, useNotification, useAPIErrorHandler } from "@strapi/admin/strapi-admin";
10
11
  import { unstable_useDocument, unstable_useDocumentActions, buildValidParams } from "@strapi/content-manager/strapi-admin";
11
12
  import { useParams, Link, useNavigate, matchPath } from "react-router-dom";
12
13
  import * as qs from "qs";
@@ -47,9 +48,7 @@ const CheckboxConfirmation = ({
47
48
  };
48
49
  const handleConfirm = () => {
49
50
  onChange({ target: { name, value: false, type: "checkbox" } });
50
- setIsOpen(false);
51
51
  };
52
- const handleToggle = () => setIsOpen((prev) => !prev);
53
52
  const label = intlLabel.id ? formatMessage(
54
53
  { id: intlLabel.id, defaultMessage: intlLabel.defaultMessage },
55
54
  { ...intlLabel.values }
@@ -58,35 +57,36 @@ const CheckboxConfirmation = ({
58
57
  { id: description.id, defaultMessage: description.defaultMessage },
59
58
  { ...description.values }
60
59
  ) : "";
61
- return /* @__PURE__ */ jsxs(Fragment, { children: [
60
+ return /* @__PURE__ */ jsxs(Dialog.Root, { open: isOpen, onOpenChange: setIsOpen, children: [
62
61
  /* @__PURE__ */ jsxs(Field.Root, { hint, name, children: [
63
- /* @__PURE__ */ jsx(Checkbox, { onValueChange: handleChange, value, type: "checkbox", children: label }),
62
+ /* @__PURE__ */ jsx(Checkbox, { onCheckedChange: handleChange, checked: value, children: label }),
64
63
  /* @__PURE__ */ jsx(Field.Hint, {})
65
64
  ] }),
66
- isOpen && /* @__PURE__ */ jsxs(Dialog, { onClose: handleToggle, title: "Confirmation", isOpen, children: [
67
- /* @__PURE__ */ jsx(DialogBody, { icon: /* @__PURE__ */ jsx(WarningCircle, {}), children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
68
- /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(TextAlignTypography, { id: "confirm-description", children: formatMessage({
65
+ /* @__PURE__ */ jsxs(Dialog.Content, { children: [
66
+ /* @__PURE__ */ jsx(Dialog.Header, { children: formatMessage({
67
+ id: getTranslation("CheckboxConfirmation.Modal.title"),
68
+ defaultMessage: "Disable localization"
69
+ }) }),
70
+ /* @__PURE__ */ jsx(Dialog.Body, { icon: /* @__PURE__ */ jsx(WarningCircle, {}), children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
71
+ /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(TextAlignTypography, { children: formatMessage({
69
72
  id: getTranslation("CheckboxConfirmation.Modal.content"),
70
73
  defaultMessage: "Disabling localization will engender the deletion of all your content but the one associated to your default locale (if existing)."
71
74
  }) }) }),
72
- /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(Typography, { fontWeight: "semiBold", id: "confirm-description", children: formatMessage({
75
+ /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(Typography, { fontWeight: "semiBold", children: formatMessage({
73
76
  id: getTranslation("CheckboxConfirmation.Modal.body"),
74
77
  defaultMessage: "Do you want to disable it?"
75
78
  }) }) })
76
79
  ] }) }),
77
- /* @__PURE__ */ jsx(
78
- DialogFooter,
79
- {
80
- startAction: /* @__PURE__ */ jsx(Button$1, { onClick: handleToggle, variant: "tertiary", children: formatMessage({
81
- id: "components.popUpWarning.button.cancel",
82
- defaultMessage: "No, cancel"
83
- }) }),
84
- endAction: /* @__PURE__ */ jsx(Button$1, { variant: "danger-light", onClick: handleConfirm, children: formatMessage({
85
- id: getTranslation("CheckboxConfirmation.Modal.button-confirm"),
86
- defaultMessage: "Yes, disable"
87
- }) })
88
- }
89
- )
80
+ /* @__PURE__ */ jsxs(Dialog.Footer, { children: [
81
+ /* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", children: formatMessage({
82
+ id: "components.popUpWarning.button.cancel",
83
+ defaultMessage: "No, cancel"
84
+ }) }) }),
85
+ /* @__PURE__ */ jsx(Dialog.Action, { children: /* @__PURE__ */ jsx(Button, { variant: "danger-light", onClick: handleConfirm, children: formatMessage({
86
+ id: getTranslation("CheckboxConfirmation.Modal.button-confirm"),
87
+ defaultMessage: "Yes, disable"
88
+ }) }) })
89
+ ] })
90
90
  ] })
91
91
  ] });
92
92
  };
@@ -137,7 +137,7 @@ const useI18n = () => {
137
137
  model: params.slug
138
138
  },
139
139
  {
140
- skip: !params.slug || !params.collectionType
140
+ skip: true
141
141
  }
142
142
  );
143
143
  if (doesPluginOptionsHaveI18nLocalized(schema?.pluginOptions)) {
@@ -217,10 +217,94 @@ const relationsApi = i18nApi.injectEndpoints({
217
217
  })
218
218
  });
219
219
  const { useGetManyDraftRelationCountQuery } = relationsApi;
220
+ const cleanData = (data, schema, components) => {
221
+ const cleanedData = removeFields(data, [
222
+ "createdAt",
223
+ "createdBy",
224
+ "updatedAt",
225
+ "updatedBy",
226
+ "id",
227
+ "documentId",
228
+ "publishedAt",
229
+ "strapi_stage",
230
+ "strapi_assignee",
231
+ "locale",
232
+ "status"
233
+ ]);
234
+ const cleanedDataWithoutPasswordAndRelation = recursiveRemoveFieldTypes(
235
+ cleanedData,
236
+ schema,
237
+ components,
238
+ ["relation", "password"]
239
+ );
240
+ return cleanedDataWithoutPasswordAndRelation;
241
+ };
242
+ const removeFields = (data, fields) => {
243
+ return Object.keys(data).reduce((acc, current) => {
244
+ if (fields.includes(current)) {
245
+ return acc;
246
+ }
247
+ acc[current] = data[current];
248
+ return acc;
249
+ }, {});
250
+ };
251
+ const recursiveRemoveFieldTypes = (data, schema, components, fields) => {
252
+ return Object.keys(data).reduce((acc, current) => {
253
+ const attribute = schema.attributes[current] ?? { type: void 0 };
254
+ if (fields.includes(attribute.type)) {
255
+ return acc;
256
+ }
257
+ if (attribute.type === "dynamiczone") {
258
+ acc[current] = data[current].map((componentValue, index2) => {
259
+ const { id: _, ...rest } = recursiveRemoveFieldTypes(
260
+ componentValue,
261
+ components[componentValue.__component],
262
+ components,
263
+ fields
264
+ );
265
+ return {
266
+ ...rest,
267
+ __temp_key__: index2 + 1
268
+ };
269
+ });
270
+ } else if (attribute.type === "component") {
271
+ const { repeatable, component } = attribute;
272
+ if (repeatable) {
273
+ acc[current] = (data[current] ?? []).map((compoData, index2) => {
274
+ const { id: _, ...rest } = recursiveRemoveFieldTypes(
275
+ compoData,
276
+ components[component],
277
+ components,
278
+ fields
279
+ );
280
+ return {
281
+ ...rest,
282
+ __temp_key__: index2 + 1
283
+ };
284
+ });
285
+ } else {
286
+ const { id: _, ...rest } = recursiveRemoveFieldTypes(
287
+ data[current] ?? {},
288
+ components[component],
289
+ components,
290
+ fields
291
+ );
292
+ acc[current] = rest;
293
+ }
294
+ } else {
295
+ acc[current] = data[current];
296
+ }
297
+ return acc;
298
+ }, {});
299
+ };
220
300
  const isErrorMessageDescriptor = (object) => {
221
301
  return typeof object === "object" && object !== null && "id" in object && "defaultMessage" in object;
222
302
  };
223
- const EntryValidationText = ({ status = "draft", validationErrors }) => {
303
+ const EntryValidationText = ({
304
+ status = "draft",
305
+ validationErrors,
306
+ action
307
+ }) => {
224
308
  const { formatMessage } = useIntl();
225
309
  const getErrorStr = (key, value) => {
226
310
  if (typeof value === "string") {
@@ -254,30 +338,63 @@ const EntryValidationText = ({ status = "draft", validationErrors }) => {
254
338
  ) })
255
339
  ] });
256
340
  }
257
- if (status === "published") {
258
- return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
259
- /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
260
- /* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
261
- id: "content-manager.bulk-publish.already-published",
262
- defaultMessage: "Already Published"
263
- }) })
264
- ] });
265
- }
266
- if (status === "modified") {
267
- return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
268
- /* @__PURE__ */ jsx(ArrowsCounterClockwise, { fill: "alternative600" }),
269
- /* @__PURE__ */ jsx(Typography, { children: formatMessage({
270
- id: "app.utils.ready-to-publish-changes",
271
- defaultMessage: "Ready to publish changes"
272
- }) })
273
- ] });
274
- }
341
+ const getStatusMessage = () => {
342
+ if (action === "bulk-publish") {
343
+ if (status === "published") {
344
+ return {
345
+ icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
346
+ text: formatMessage({
347
+ id: "content-manager.bulk-publish.already-published",
348
+ defaultMessage: "Already Published"
349
+ }),
350
+ textColor: "success600",
351
+ fontWeight: "bold"
352
+ };
353
+ } else if (status === "modified") {
354
+ return {
355
+ icon: /* @__PURE__ */ jsx(ArrowsCounterClockwise, { fill: "alternative600" }),
356
+ text: formatMessage({
357
+ id: "app.utils.ready-to-publish-changes",
358
+ defaultMessage: "Ready to publish changes"
359
+ })
360
+ };
361
+ } else {
362
+ return {
363
+ icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
364
+ text: formatMessage({
365
+ id: "app.utils.ready-to-publish",
366
+ defaultMessage: "Ready to publish"
367
+ })
368
+ };
369
+ }
370
+ } else {
371
+ if (status === "draft") {
372
+ return {
373
+ icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
374
+ text: formatMessage({
375
+ id: "content-manager.bulk-unpublish.already-unpublished",
376
+ defaultMessage: "Already Unpublished"
377
+ }),
378
+ textColor: "success600",
379
+ fontWeight: "bold"
380
+ };
381
+ } else {
382
+ return {
383
+ icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
384
+ text: formatMessage({
385
+ id: "app.utils.ready-to-unpublish-changes",
386
+ defaultMessage: "Ready to unpublish"
387
+ }),
388
+ textColor: "success600",
389
+ fontWeight: "bold"
390
+ };
391
+ }
392
+ }
393
+ };
394
+ const { icon, text, textColor = "success600", fontWeight = "normal" } = getStatusMessage();
275
395
  return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
276
- /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
277
- /* @__PURE__ */ jsx(Typography, { children: formatMessage({
278
- id: "app.utils.ready-to-publish",
279
- defaultMessage: "Ready to publish"
280
- }) })
396
+ icon,
397
+ /* @__PURE__ */ jsx(Typography, { textColor, fontWeight, children: text })
281
398
  ] });
282
399
  };
283
400
  const BoldChunk = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: chunks });
@@ -285,7 +402,8 @@ const BulkLocaleActionModal = ({
285
402
  headers,
286
403
  rows,
287
404
  localesMetadata,
288
- validationErrors = {}
405
+ validationErrors = {},
406
+ action
289
407
  }) => {
290
408
  const { formatMessage } = useIntl();
291
409
  const selectedRows = useTable(
@@ -298,27 +416,29 @@ const BulkLocaleActionModal = ({
298
416
  return acc;
299
417
  }, {});
300
418
  const localesWithErrors = Object.keys(validationErrors);
301
- const alreadyPublishedCount = selectedRows.filter(
419
+ const publishedCount = selectedRows.filter(
302
420
  ({ locale }) => currentStatusByLocale[locale] === "published"
303
421
  ).length;
304
- const readyToPublishCount = selectedRows.filter(
422
+ const draftCount = selectedRows.filter(
305
423
  ({ locale }) => (currentStatusByLocale[locale] === "draft" || currentStatusByLocale[locale] === "modified") && !localesWithErrors.includes(locale)
306
424
  ).length;
307
425
  const withErrorsCount = localesWithErrors.length;
426
+ const messageId = action === "bulk-publish" ? "content-manager.containers.list.selectedEntriesModal.selectedCount.publish" : "content-manager.containers.list.selectedEntriesModal.selectedCount.unpublish";
427
+ 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.";
308
428
  return formatMessage(
309
429
  {
310
- id: "content-manager.containers.list.selectedEntriesModal.selectedCount",
311
- 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."
430
+ id: messageId,
431
+ defaultMessage
312
432
  },
313
433
  {
314
434
  withErrorsCount,
315
- readyToPublishCount,
316
- alreadyPublishedCount,
435
+ draftCount,
436
+ publishedCount,
317
437
  b: BoldChunk
318
438
  }
319
439
  );
320
440
  };
321
- return /* @__PURE__ */ jsxs(React.Fragment, { children: [
441
+ return /* @__PURE__ */ jsxs(Modal.Body, { children: [
322
442
  /* @__PURE__ */ jsx(Typography, { children: getFormattedCountMessage() }),
323
443
  /* @__PURE__ */ jsx(Box, { marginTop: 5, children: /* @__PURE__ */ jsxs(Table.Content, { children: [
324
444
  /* @__PURE__ */ jsxs(Table.Head, { children: [
@@ -339,13 +459,12 @@ const BulkLocaleActionModal = ({
339
459
  paddingRight: "6px",
340
460
  paddingTop: "2px",
341
461
  paddingBottom: "2px",
342
- showBullet: false,
343
462
  size: "S",
344
463
  variant: statusVariant,
345
464
  children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "pi", fontWeight: "bold", children: capitalize(status) })
346
465
  }
347
466
  ) }) }),
348
- /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(EntryValidationText, { validationErrors: error, status }) }),
467
+ /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(EntryValidationText, { validationErrors: error, status, action }) }),
349
468
  /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
350
469
  IconButton,
351
470
  {
@@ -362,7 +481,7 @@ const BulkLocaleActionModal = ({
362
481
  name: locale
363
482
  }
364
483
  ),
365
- borderWidth: 0,
484
+ variant: "ghost",
366
485
  children: /* @__PURE__ */ jsx(Pencil, {})
367
486
  }
368
487
  ) })
@@ -371,6 +490,47 @@ const BulkLocaleActionModal = ({
371
490
  ] }) })
372
491
  ] });
373
492
  };
493
+ const statusVariants = {
494
+ draft: "secondary",
495
+ published: "success",
496
+ modified: "alternative"
497
+ };
498
+ const LocaleOption = ({
499
+ isDraftAndPublishEnabled,
500
+ locale,
501
+ status,
502
+ entryExists
503
+ }) => {
504
+ const { formatMessage } = useIntl();
505
+ if (!entryExists) {
506
+ return formatMessage(
507
+ {
508
+ id: getTranslation("CMEditViewLocalePicker.locale.create"),
509
+ defaultMessage: "Create <bold>{locale}</bold> locale"
510
+ },
511
+ {
512
+ bold: (locale2) => /* @__PURE__ */ jsx("b", { children: locale2 }),
513
+ locale: locale.name
514
+ }
515
+ );
516
+ }
517
+ return /* @__PURE__ */ jsxs(Flex, { width: "100%", gap: 1, justifyContent: "space-between", children: [
518
+ /* @__PURE__ */ jsx(Typography, { children: locale.name }),
519
+ isDraftAndPublishEnabled ? /* @__PURE__ */ jsx(
520
+ Status,
521
+ {
522
+ display: "flex",
523
+ paddingLeft: "6px",
524
+ paddingRight: "6px",
525
+ paddingTop: "2px",
526
+ paddingBottom: "2px",
527
+ size: "S",
528
+ variant: statusVariants[status],
529
+ children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "pi", fontWeight: "bold", children: capitalize(status) })
530
+ }
531
+ ) : null
532
+ ] });
533
+ };
374
534
  const LocalePickerAction = ({
375
535
  document,
376
536
  meta,
@@ -382,7 +542,13 @@ const LocalePickerAction = ({
382
542
  const [{ query }, setQuery] = useQueryParams();
383
543
  const { hasI18n, canCreate, canRead } = useI18n();
384
544
  const { data: locales = [] } = useGetLocalesQuery();
385
- const { schema } = unstable_useDocument({ model, collectionType, documentId });
545
+ const currentDesiredLocale = query.plugins?.i18n?.locale;
546
+ const { schema } = unstable_useDocument({
547
+ model,
548
+ collectionType,
549
+ documentId,
550
+ params: { locale: currentDesiredLocale }
551
+ });
386
552
  const handleSelect = React.useCallback(
387
553
  (value) => {
388
554
  setQuery({
@@ -400,53 +566,47 @@ const LocalePickerAction = ({
400
566
  if (!Array.isArray(locales) || !hasI18n) {
401
567
  return;
402
568
  }
403
- const currentDesiredLocale = query.plugins?.i18n?.locale;
404
569
  const doesLocaleExist = locales.find((loc) => loc.code === currentDesiredLocale);
405
570
  const defaultLocale = locales.find((locale) => locale.isDefault);
406
571
  if (!doesLocaleExist && defaultLocale?.code) {
407
572
  handleSelect(defaultLocale.code);
408
573
  }
409
- }, [handleSelect, hasI18n, locales, query.plugins?.i18n?.locale]);
410
- if (!hasI18n || !Array.isArray(locales) || locales.length === 0) {
411
- return null;
412
- }
413
- const currentLocale = query.plugins?.i18n?.locale || locales.find((loc) => loc.isDefault)?.code;
574
+ }, [handleSelect, hasI18n, locales, currentDesiredLocale]);
575
+ const currentLocale = Array.isArray(locales) ? locales.find((locale) => locale.code === currentDesiredLocale) : void 0;
414
576
  const allCurrentLocales = [
415
- { status: getDocumentStatus(document, meta), locale: currentLocale },
577
+ { status: getDocumentStatus(document, meta), locale: currentLocale?.code },
416
578
  ...meta?.availableLocales ?? []
417
579
  ];
580
+ if (!hasI18n || !Array.isArray(locales) || locales.length === 0) {
581
+ return null;
582
+ }
418
583
  return {
419
584
  label: formatMessage({
420
585
  id: getTranslation("Settings.locales.modal.locales.label"),
421
586
  defaultMessage: "Locales"
422
587
  }),
423
588
  options: locales.map((locale) => {
589
+ const entryWithLocaleExists = allCurrentLocales.some((doc) => doc.locale === locale.code);
424
590
  const currentLocaleDoc = allCurrentLocales.find(
425
591
  (doc) => "locale" in doc ? doc.locale === locale.code : false
426
592
  );
427
- const status = currentLocaleDoc?.status ?? "draft";
428
- const permissionsToCheck = currentLocaleDoc ? canCreate : canRead;
429
- const statusVariant = status === "draft" ? "primary" : status === "published" ? "success" : "alternative";
593
+ const permissionsToCheck = currentLocaleDoc ? canRead : canCreate;
430
594
  return {
431
595
  disabled: !permissionsToCheck.includes(locale.code),
432
596
  value: locale.code,
433
- label: locale.name,
434
- startIcon: schema?.options?.draftAndPublish ? /* @__PURE__ */ jsx(
435
- Status,
597
+ label: /* @__PURE__ */ jsx(
598
+ LocaleOption,
436
599
  {
437
- display: "flex",
438
- paddingLeft: "6px",
439
- paddingRight: "6px",
440
- paddingTop: "2px",
441
- paddingBottom: "2px",
442
- showBullet: false,
443
- size: "S",
444
- variant: statusVariant,
445
- children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "pi", fontWeight: "bold", children: capitalize(status) })
600
+ isDraftAndPublishEnabled: !!schema?.options?.draftAndPublish,
601
+ locale,
602
+ status: currentLocaleDoc?.status,
603
+ entryExists: entryWithLocaleExists
446
604
  }
447
- ) : null
605
+ ),
606
+ startIcon: !entryWithLocaleExists ? /* @__PURE__ */ jsx(Plus, {}) : null
448
607
  };
449
608
  }),
609
+ customizeContent: () => currentLocale?.name,
450
610
  onSelect: handleSelect,
451
611
  value: currentLocale
452
612
  };
@@ -462,6 +622,99 @@ const getDocumentStatus = (document, meta) => {
462
622
  }
463
623
  return docStatus;
464
624
  };
625
+ const FillFromAnotherLocaleAction = ({
626
+ documentId,
627
+ meta,
628
+ model,
629
+ collectionType
630
+ }) => {
631
+ const { formatMessage } = useIntl();
632
+ const [{ query }] = useQueryParams();
633
+ const { hasI18n } = useI18n();
634
+ const currentDesiredLocale = query.plugins?.i18n?.locale;
635
+ const [localeSelected, setLocaleSelected] = React.useState(null);
636
+ const setValues = useForm("FillFromAnotherLocale", (state) => state.setValues);
637
+ const { getDocument } = unstable_useDocumentActions();
638
+ const { schema, components } = unstable_useDocument({
639
+ model,
640
+ documentId,
641
+ collectionType,
642
+ params: { locale: currentDesiredLocale }
643
+ });
644
+ const { data: locales = [] } = useGetLocalesQuery();
645
+ const availableLocales = Array.isArray(locales) ? locales.filter((locale) => meta?.availableLocales.some((l) => l.locale === locale.code)) : [];
646
+ const fillFromLocale = (onClose) => async () => {
647
+ const response = await getDocument({
648
+ collectionType,
649
+ model,
650
+ documentId,
651
+ params: { locale: localeSelected }
652
+ });
653
+ if (!response || !schema) {
654
+ return;
655
+ }
656
+ const { data } = response;
657
+ const cleanedData = cleanData(data, schema, components);
658
+ setValues(cleanedData);
659
+ onClose();
660
+ };
661
+ if (!hasI18n) {
662
+ return null;
663
+ }
664
+ return {
665
+ type: "icon",
666
+ icon: /* @__PURE__ */ jsx(Download, {}),
667
+ disabled: availableLocales.length === 0,
668
+ label: formatMessage({
669
+ id: getTranslation("CMEditViewCopyLocale.copy-text"),
670
+ defaultMessage: "Fill in from another locale"
671
+ }),
672
+ dialog: {
673
+ type: "dialog",
674
+ title: formatMessage({
675
+ id: getTranslation("CMEditViewCopyLocale.dialog.title"),
676
+ defaultMessage: "Confirmation"
677
+ }),
678
+ content: ({ onClose }) => /* @__PURE__ */ jsxs(Fragment, { children: [
679
+ /* @__PURE__ */ jsx(Dialog.Body, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 3, children: [
680
+ /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
681
+ /* @__PURE__ */ jsx(Typography, { textAlign: "center", children: formatMessage({
682
+ id: getTranslation("CMEditViewCopyLocale.dialog.body"),
683
+ defaultMessage: "Your current content will be erased and filled by the content of the selected locale:"
684
+ }) }),
685
+ /* @__PURE__ */ jsxs(Field.Root, { width: "100%", children: [
686
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
687
+ id: getTranslation("CMEditViewCopyLocale.dialog.field.label"),
688
+ defaultMessage: "Locale"
689
+ }) }),
690
+ /* @__PURE__ */ jsx(
691
+ SingleSelect,
692
+ {
693
+ value: localeSelected,
694
+ placeholder: formatMessage({
695
+ id: getTranslation("CMEditViewCopyLocale.dialog.field.placeholder"),
696
+ defaultMessage: "Select one locale..."
697
+ }),
698
+ onChange: (value) => setLocaleSelected(value),
699
+ children: availableLocales.map((locale) => /* @__PURE__ */ jsx(SingleSelectOption, { value: locale.code, children: locale.name }, locale.code))
700
+ }
701
+ )
702
+ ] })
703
+ ] }) }),
704
+ /* @__PURE__ */ jsx(Dialog.Footer, { children: /* @__PURE__ */ jsxs(Flex, { gap: 2, width: "100%", children: [
705
+ /* @__PURE__ */ jsx(Button, { flex: "auto", variant: "tertiary", onClick: onClose, children: formatMessage({
706
+ id: getTranslation("CMEditViewCopyLocale.cancel-text"),
707
+ defaultMessage: "No, cancel"
708
+ }) }),
709
+ /* @__PURE__ */ jsx(Button, { flex: "auto", variant: "success", onClick: fillFromLocale(onClose), children: formatMessage({
710
+ id: getTranslation("CMEditViewCopyLocale.submit-text"),
711
+ defaultMessage: "Yes, fill in"
712
+ }) })
713
+ ] }) })
714
+ ] })
715
+ }
716
+ };
717
+ };
465
718
  const DeleteLocaleAction = ({
466
719
  document,
467
720
  documentId,
@@ -473,16 +726,23 @@ const DeleteLocaleAction = ({
473
726
  const { toggleNotification } = useNotification();
474
727
  const { delete: deleteAction } = unstable_useDocumentActions();
475
728
  const { hasI18n, canDelete } = useI18n();
729
+ const [{ query }] = useQueryParams();
730
+ const { data: locales = [] } = useGetLocalesQuery();
731
+ const currentDesiredLocale = query.plugins?.i18n?.locale;
732
+ const locale = !("error" in locales) && locales.find((loc) => loc.code === currentDesiredLocale);
476
733
  if (!hasI18n) {
477
734
  return null;
478
735
  }
479
736
  return {
480
737
  disabled: document?.locale && !canDelete.includes(document.locale) || !document || !document.id,
481
738
  position: ["header", "table-row"],
482
- label: formatMessage({
483
- id: getTranslation("actions.delete.label"),
484
- defaultMessage: "Delete locale"
485
- }),
739
+ label: formatMessage(
740
+ {
741
+ id: getTranslation("actions.delete.label"),
742
+ defaultMessage: "Delete entry ({locale})"
743
+ },
744
+ { locale: locale && locale.name }
745
+ ),
486
746
  icon: /* @__PURE__ */ jsx(StyledTrash, {}),
487
747
  variant: "danger",
488
748
  dialog: {
@@ -499,7 +759,12 @@ const DeleteLocaleAction = ({
499
759
  }) })
500
760
  ] }),
501
761
  onConfirm: async () => {
502
- if (!documentId || !document?.locale) {
762
+ const unableToDelete = (
763
+ // We are unable to delete a collection type without a document ID
764
+ // & unable to delete generally if there is no document locale
765
+ collectionType !== "single-types" && !documentId || !document?.locale
766
+ );
767
+ if (unableToDelete) {
503
768
  console.error(
504
769
  "You're trying to delete a document without an id or locale, this is likely a bug with Strapi. Please open an issue."
505
770
  );
@@ -525,37 +790,43 @@ const DeleteLocaleAction = ({
525
790
  }
526
791
  };
527
792
  };
528
- const BulkLocalePublishAction = ({
793
+ const BulkLocaleAction = ({
529
794
  document: baseDocument,
530
795
  documentId,
531
796
  model,
532
- collectionType
797
+ collectionType,
798
+ action
533
799
  }) => {
534
800
  const baseLocale = baseDocument?.locale ?? null;
535
801
  const [{ query }] = useQueryParams();
536
802
  const params = React.useMemo(() => buildValidParams(query), [query]);
537
- const isPublishedTab = query.status === "published";
803
+ const isOnPublishedTab = query.status === "published";
538
804
  const { formatMessage } = useIntl();
539
805
  const { hasI18n, canPublish } = useI18n();
540
806
  const { toggleNotification } = useNotification();
541
807
  const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
542
808
  const [selectedRows, setSelectedRows] = React.useState([]);
543
- const [isConfirmationOpen, setIsConfirmationOpen] = React.useState(false);
544
- const { publishMany: publishManyAction } = unstable_useDocumentActions();
809
+ const [isDraftRelationConfirmationOpen, setIsDraftRelationConfirmationOpen] = React.useState(false);
810
+ const { publishMany: publishManyAction, unpublishMany: unpublishManyAction } = unstable_useDocumentActions();
545
811
  const {
546
812
  document,
547
813
  meta: documentMeta,
548
814
  schema,
549
815
  validate
550
- } = unstable_useDocument({
551
- model,
552
- collectionType,
553
- documentId,
554
- params: {
555
- locale: baseLocale
816
+ } = unstable_useDocument(
817
+ {
818
+ model,
819
+ collectionType,
820
+ documentId,
821
+ params: {
822
+ locale: baseLocale
823
+ }
824
+ },
825
+ {
826
+ skip: !hasI18n || !baseLocale
556
827
  }
557
- });
558
- const { data: localesMetadata = [] } = useGetLocalesQuery();
828
+ );
829
+ const { data: localesMetadata = [] } = useGetLocalesQuery(hasI18n ? void 0 : skipToken);
559
830
  const headers = [
560
831
  {
561
832
  label: formatMessage({
@@ -604,12 +875,19 @@ const BulkLocalePublishAction = ({
604
875
  }, {});
605
876
  return [rowsFromMeta, errors];
606
877
  }, [document, documentMeta?.availableLocales, validate]);
607
- const localesToPublish = selectedRows.reduce((acc, selectedRow) => {
608
- if (selectedRow.status !== "published" && !Object.keys(validationErrors).includes(selectedRow.locale)) {
878
+ const isBulkPublish = action === "bulk-publish";
879
+ const localesForAction = selectedRows.reduce((acc, selectedRow) => {
880
+ const isValidLocale = (
881
+ // Validation errors are irrelevant if we are trying to unpublish
882
+ !isBulkPublish || !Object.keys(validationErrors).includes(selectedRow.locale)
883
+ );
884
+ const shouldAddLocale = isBulkPublish ? selectedRow.status !== "published" && isValidLocale : selectedRow.status !== "draft" && isValidLocale;
885
+ if (shouldAddLocale) {
609
886
  acc.push(selectedRow.locale);
610
887
  }
611
888
  return acc;
612
889
  }, []);
890
+ const enableDraftRelationsCount = false;
613
891
  const {
614
892
  data: draftRelationsCount = 0,
615
893
  isLoading: isDraftRelationsLoading,
@@ -618,10 +896,10 @@ const BulkLocalePublishAction = ({
618
896
  {
619
897
  model,
620
898
  documentIds: [documentId],
621
- locale: localesToPublish
899
+ locale: localesForAction
622
900
  },
623
901
  {
624
- skip: !documentId || localesToPublish.length === 0
902
+ skip: !enableDraftRelationsCount
625
903
  }
626
904
  );
627
905
  React.useEffect(() => {
@@ -647,23 +925,32 @@ const BulkLocalePublishAction = ({
647
925
  documentIds: [documentId],
648
926
  params: {
649
927
  ...params,
650
- locale: localesToPublish
928
+ locale: localesForAction
929
+ }
930
+ });
931
+ setSelectedRows([]);
932
+ };
933
+ const unpublish = async () => {
934
+ await unpublishManyAction({
935
+ model,
936
+ documentIds: [documentId],
937
+ params: {
938
+ ...params,
939
+ locale: localesForAction
651
940
  }
652
941
  });
653
942
  setSelectedRows([]);
654
943
  };
655
944
  const handleAction = async () => {
656
945
  if (draftRelationsCount > 0) {
657
- setIsConfirmationOpen(true);
658
- } else {
946
+ setIsDraftRelationConfirmationOpen(true);
947
+ } else if (isBulkPublish) {
659
948
  await publish();
949
+ } else {
950
+ await unpublish();
660
951
  }
661
952
  };
662
- const isUnpublish = document?.status === "published";
663
- if (isUnpublish) {
664
- console.warn(["I18N"], "Bulk locale unpublish modal not implemented");
665
- }
666
- if (isConfirmationOpen) {
953
+ if (isDraftRelationConfirmationOpen) {
667
954
  return {
668
955
  label: formatMessage({
669
956
  id: "app.components.ConfirmDialog.title",
@@ -672,11 +959,11 @@ const BulkLocalePublishAction = ({
672
959
  variant: "danger",
673
960
  dialog: {
674
961
  onCancel: () => {
675
- setIsConfirmationOpen(false);
962
+ setIsDraftRelationConfirmationOpen(false);
676
963
  },
677
964
  onConfirm: async () => {
678
965
  await publish();
679
- setIsConfirmationOpen(false);
966
+ setIsDraftRelationConfirmationOpen(false);
680
967
  },
681
968
  type: "dialog",
682
969
  title: formatMessage({
@@ -686,27 +973,32 @@ const BulkLocalePublishAction = ({
686
973
  content: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "center", gap: 2, children: [
687
974
  /* @__PURE__ */ jsx(WarningCircle, { width: "2.4rem", height: "2.4rem", fill: "danger600" }),
688
975
  /* @__PURE__ */ jsx(Typography, { textAlign: "center", children: formatMessage({
689
- id: "content-manager.actions.discard.dialog.body",
690
- defaultMessage: "Are you sure you want to discard the changes? This action is irreversible."
976
+ id: getTranslation("CMEditViewBulkLocale.draft-relation-warning"),
977
+ defaultMessage: "Some locales are related to draft entries. Publishing them could leave broken links in your app."
978
+ }) }),
979
+ /* @__PURE__ */ jsx(Typography, { textAlign: "center", children: formatMessage({
980
+ id: getTranslation("CMEditViewBulkLocale.continue-confirmation"),
981
+ defaultMessage: "Are you sure you want to continue?"
691
982
  }) })
692
983
  ] })
693
984
  }
694
985
  };
695
986
  }
987
+ const hasPermission = selectedRows.map(({ locale }) => locale).every((locale) => canPublish.includes(locale));
696
988
  return {
697
989
  label: formatMessage({
698
- id: getTranslation("CMEditViewBulkLocale.publish-title"),
699
- defaultMessage: "Publish Multiple Locales"
990
+ id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
991
+ defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
700
992
  }),
701
- icon: /* @__PURE__ */ jsx(ListPlus, {}),
702
- disabled: isPublishedTab || !canPublish,
993
+ variant: isBulkPublish ? "secondary" : "danger",
994
+ icon: isBulkPublish ? /* @__PURE__ */ jsx(ListPlus, {}) : /* @__PURE__ */ jsx(Cross, {}),
995
+ disabled: isOnPublishedTab || canPublish.length === 0,
703
996
  position: ["panel"],
704
- variant: "secondary",
705
997
  dialog: {
706
998
  type: "modal",
707
999
  title: formatMessage({
708
- id: getTranslation("CMEditViewBulkLocale.publish-title"),
709
- defaultMessage: "Publish Multiple Locales"
1000
+ id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
1001
+ defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
710
1002
  }),
711
1003
  content: () => {
712
1004
  return /* @__PURE__ */ jsx(
@@ -725,28 +1017,35 @@ const BulkLocalePublishAction = ({
725
1017
  validationErrors,
726
1018
  headers,
727
1019
  rows,
728
- localesMetadata
1020
+ localesMetadata,
1021
+ action: action ?? "bulk-publish"
729
1022
  }
730
1023
  )
731
1024
  }
732
1025
  );
733
1026
  },
734
- footer: () => /* @__PURE__ */ jsx(Flex, { justifyContent: "flex-end", children: /* @__PURE__ */ jsx(
735
- Button$1,
1027
+ footer: () => /* @__PURE__ */ jsx(Modal.Footer, { justifyContent: "flex-end", children: /* @__PURE__ */ jsx(
1028
+ Button,
736
1029
  {
737
1030
  loading: isDraftRelationsLoading,
738
- disabled: localesToPublish.length === 0,
1031
+ disabled: !hasPermission || localesForAction.length === 0,
739
1032
  variant: "default",
740
1033
  onClick: handleAction,
741
1034
  children: formatMessage({
742
- id: "app.utils.publish",
743
- defaultMessage: "Publish"
1035
+ id: isBulkPublish ? "app.utils.publish" : "app.utils.unpublish",
1036
+ defaultMessage: isBulkPublish ? "Publish" : "Unpublish"
744
1037
  })
745
1038
  }
746
1039
  ) })
747
1040
  }
748
1041
  };
749
1042
  };
1043
+ const BulkLocalePublishAction = (props) => {
1044
+ return BulkLocaleAction({ action: "bulk-publish", ...props });
1045
+ };
1046
+ const BulkLocaleUnpublishAction = (props) => {
1047
+ return BulkLocaleAction({ action: "bulk-unpublish", ...props });
1048
+ };
750
1049
  const StyledTrash = styled(Trash)`
751
1050
  path {
752
1051
  fill: currentColor;
@@ -803,13 +1102,6 @@ const UnpublishModalAdditionalInfo = () => {
803
1102
  }
804
1103
  ) });
805
1104
  };
806
- const Initializer = ({ setPlugin }) => {
807
- const setPluginRef = React.useRef(setPlugin);
808
- React.useEffect(() => {
809
- setPluginRef.current(pluginId);
810
- }, []);
811
- return null;
812
- };
813
1105
  const LocalePicker = () => {
814
1106
  const { formatMessage } = useIntl();
815
1107
  const [{ query }, setQuery] = useQueryParams();
@@ -869,7 +1161,7 @@ const PERMISSIONS = {
869
1161
  read: [{ action: "plugin::i18n.locale.read", subject: null }]
870
1162
  };
871
1163
  const mutateEditViewHook = ({ layout }) => {
872
- if ("i18n" in layout.options && typeof layout.options.i18n === "object" && layout.options.i18n !== null && "localized" in layout.options.i18n && !layout.options.i18n.localized) {
1164
+ if (!("i18n" in layout.options) || typeof layout.options.i18n === "object" && layout.options.i18n !== null && "localized" in layout.options.i18n && !layout.options.i18n.localized) {
873
1165
  return { layout };
874
1166
  }
875
1167
  const components = Object.entries(layout.components).reduce(
@@ -915,7 +1207,7 @@ const doesFieldHaveI18nPluginOpt = (pluginOpts) => {
915
1207
  const LabelAction = ({ title, icon }) => {
916
1208
  const { formatMessage } = useIntl();
917
1209
  return /* @__PURE__ */ jsxs(Span, { tag: "span", children: [
918
- /* @__PURE__ */ jsx(VisuallyHidden, { tag: "span", children: `(${formatMessage(title)})` }),
1210
+ /* @__PURE__ */ jsx(VisuallyHidden, { tag: "span", children: formatMessage(title) }),
919
1211
  React.cloneElement(icon, {
920
1212
  "aria-hidden": true,
921
1213
  focusable: false
@@ -950,13 +1242,7 @@ const LocaleListCell = ({
950
1242
  }
951
1243
  });
952
1244
  const { locale: language } = useIntl();
953
- const [visible, setVisible] = React.useState(false);
954
- const buttonRef = React.useRef(null);
955
1245
  const { data: locales = [] } = useGetLocalesQuery();
956
- const handleTogglePopover = (e) => {
957
- e.stopPropagation();
958
- setVisible((prev) => !prev);
959
- };
960
1246
  const formatter = useCollator(language, {
961
1247
  sensitivity: "base"
962
1248
  });
@@ -978,64 +1264,14 @@ const LocaleListCell = ({
978
1264
  }
979
1265
  return locale.name;
980
1266
  }).toSorted((a, b) => formatter.compare(a, b));
981
- return /* @__PURE__ */ jsxs(Button, { type: "button", onClick: handleTogglePopover, ref: buttonRef, children: [
982
- /* @__PURE__ */ jsxs(
983
- ActionWrapper,
984
- {
985
- minWidth: "100%",
986
- alignItems: "center",
987
- justifyContent: "center",
988
- height: "3.2rem",
989
- width: "3.2rem",
990
- children: [
991
- /* @__PURE__ */ jsx(Typography, { textColor: "neutral800", ellipsis: true, children: localesForDocument.join(", ") }),
992
- /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(CaretDown, {}) })
993
- ]
994
- }
995
- ),
996
- visible && /* @__PURE__ */ jsx(
997
- Popover,
998
- {
999
- onDismiss: () => setVisible(false),
1000
- source: buttonRef,
1001
- spacing: 16,
1002
- centered: true,
1003
- children: /* @__PURE__ */ jsx("ul", { children: localesForDocument.map((name) => /* @__PURE__ */ jsx(Box, { padding: 3, tag: "li", children: /* @__PURE__ */ jsx(Typography, { children: name }) }, name)) })
1004
- }
1005
- )
1267
+ return /* @__PURE__ */ jsxs(Popover.Root, { children: [
1268
+ /* @__PURE__ */ jsx(Popover.Trigger, { children: /* @__PURE__ */ jsx(Button, { variant: "ghost", type: "button", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxs(Flex, { minWidth: "100%", alignItems: "center", justifyContent: "center", fontWeight: "regular", children: [
1269
+ /* @__PURE__ */ jsx(Typography, { textColor: "neutral800", ellipsis: true, marginRight: 2, children: localesForDocument.join(", ") }),
1270
+ /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(CaretDown, { width: "1.2rem", height: "1.2rem" }) })
1271
+ ] }) }) }),
1272
+ /* @__PURE__ */ jsx(Popover.Content, { sideOffset: 16, children: /* @__PURE__ */ jsx("ul", { children: localesForDocument.map((name) => /* @__PURE__ */ jsx(Box, { padding: 3, tag: "li", children: /* @__PURE__ */ jsx(Typography, { children: name }) }, name)) }) })
1006
1273
  ] });
1007
1274
  };
1008
- const Button = styled.button`
1009
- width: 100%;
1010
-
1011
- svg {
1012
- > g,
1013
- path {
1014
- fill: ${({ theme }) => theme.colors.neutral500};
1015
- }
1016
- }
1017
- &:hover {
1018
- svg {
1019
- > g,
1020
- path {
1021
- fill: ${({ theme }) => theme.colors.neutral600};
1022
- }
1023
- }
1024
- }
1025
- &:active {
1026
- svg {
1027
- > g,
1028
- path {
1029
- fill: ${({ theme }) => theme.colors.neutral400};
1030
- }
1031
- }
1032
- }
1033
- `;
1034
- const ActionWrapper = styled(Flex)`
1035
- svg {
1036
- height: 0.4rem;
1037
- }
1038
- `;
1039
1275
  const addColumnToTableHook = ({ displayedHeaders, layout }) => {
1040
1276
  const { options } = layout;
1041
1277
  const isFieldLocalized = doesPluginOptionsHaveI18nLocalized(options) ? options.i18n.localized : false;
@@ -1064,18 +1300,11 @@ const addColumnToTableHook = ({ displayedHeaders, layout }) => {
1064
1300
  const addLocaleToReleasesHook = ({ displayedHeaders = [] }) => {
1065
1301
  return {
1066
1302
  displayedHeaders: [
1067
- // TODO: Fix when migrating to v5
1068
- // ...displayedHeaders,
1303
+ ...displayedHeaders,
1069
1304
  {
1070
- key: "__locale__",
1071
- fieldSchema: { type: "string" },
1072
- metadatas: {
1073
- label: {
1074
- id: "content-releases.page.ReleaseDetails.table.header.label.locale",
1075
- defaultMessage: "locale"
1076
- },
1077
- searchable: false,
1078
- sortable: false
1305
+ label: {
1306
+ id: "content-releases.page.ReleaseDetails.table.header.label.locale",
1307
+ defaultMessage: "locale"
1079
1308
  },
1080
1309
  name: "locale"
1081
1310
  }
@@ -1168,9 +1397,6 @@ const localeMiddleware = (ctx) => (next) => (permissions) => {
1168
1397
  return next(revisedPermissions);
1169
1398
  };
1170
1399
  const prefixPluginTranslations = (trad, pluginId2) => {
1171
- if (!pluginId2) {
1172
- throw new TypeError("pluginId can't be empty");
1173
- }
1174
1400
  return Object.keys(trad).reduce((acc, current) => {
1175
1401
  acc[`${pluginId2}.${current}`] = trad[current];
1176
1402
  return acc;
@@ -1223,8 +1449,6 @@ const index = {
1223
1449
  app.addRBACMiddleware([localeMiddleware]);
1224
1450
  app.registerPlugin({
1225
1451
  id: pluginId,
1226
- initializer: Initializer,
1227
- isReady: false,
1228
1452
  name: pluginId
1229
1453
  });
1230
1454
  },
@@ -1242,11 +1466,11 @@ const index = {
1242
1466
  },
1243
1467
  id: "internationalization",
1244
1468
  to: "internationalization",
1245
- Component: () => import("./SettingsPage-0FFSTUW2.mjs").then((mod) => ({ default: mod.ProtectedSettingsPage })),
1469
+ Component: () => import("./SettingsPage-D67CaQAB.mjs").then((mod) => ({ default: mod.ProtectedSettingsPage })),
1246
1470
  permissions: PERMISSIONS.accessMain
1247
1471
  });
1248
1472
  const contentManager = app.getPlugin("content-manager");
1249
- contentManager.apis.addDocumentHeaderAction([LocalePickerAction]);
1473
+ contentManager.apis.addDocumentHeaderAction([LocalePickerAction, FillFromAnotherLocaleAction]);
1250
1474
  contentManager.apis.addDocumentAction((actions) => {
1251
1475
  const indexOfDeleteAction = actions.findIndex((action) => action.type === "delete");
1252
1476
  actions.splice(indexOfDeleteAction, 0, DeleteLocaleAction);
@@ -1254,6 +1478,7 @@ const index = {
1254
1478
  });
1255
1479
  contentManager.apis.addDocumentAction((actions) => {
1256
1480
  actions.splice(2, 0, BulkLocalePublishAction);
1481
+ actions.splice(5, 0, BulkLocaleUnpublishAction);
1257
1482
  return actions;
1258
1483
  });
1259
1484
  contentManager.injectComponent("listView", "actions", {
@@ -1359,7 +1584,7 @@ const index = {
1359
1584
  async registerTrads({ locales }) {
1360
1585
  const importedTrads = await Promise.all(
1361
1586
  locales.map((locale) => {
1362
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/de.json": () => import("./de-9eCAqqrB.mjs"), "./translations/dk.json": () => import("./dk-2qBjxt-P.mjs"), "./translations/en.json": () => import("./en-18tWw4P6.mjs"), "./translations/es.json": () => import("./es-DlmMVaBG.mjs"), "./translations/fr.json": () => import("./fr-3S6ke71d.mjs"), "./translations/ko.json": () => import("./ko-qTjQ8IMw.mjs"), "./translations/pl.json": () => import("./pl-B67TSHqT.mjs"), "./translations/ru.json": () => import("./ru-hagMa57T.mjs"), "./translations/tr.json": () => import("./tr-Dw_jmkG-.mjs"), "./translations/zh-Hans.json": () => import("./zh-Hans-Dyc-aR-h.mjs"), "./translations/zh.json": () => import("./zh-57YM4amO.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
1587
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/de.json": () => import("./de-9eCAqqrB.mjs"), "./translations/dk.json": () => import("./dk-2qBjxt-P.mjs"), "./translations/en.json": () => import("./en-DlXfy6Gy.mjs"), "./translations/es.json": () => import("./es-DlmMVaBG.mjs"), "./translations/fr.json": () => import("./fr-3S6ke71d.mjs"), "./translations/ko.json": () => import("./ko-qTjQ8IMw.mjs"), "./translations/pl.json": () => import("./pl-B67TSHqT.mjs"), "./translations/ru.json": () => import("./ru-hagMa57T.mjs"), "./translations/tr.json": () => import("./tr-Dw_jmkG-.mjs"), "./translations/zh-Hans.json": () => import("./zh-Hans-Dyc-aR-h.mjs"), "./translations/zh.json": () => import("./zh-57YM4amO.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
1363
1588
  return {
1364
1589
  data: prefixPluginTranslations(data, pluginId),
1365
1590
  locale
@@ -1385,4 +1610,4 @@ export {
1385
1610
  index as i,
1386
1611
  useCreateLocaleMutation as u
1387
1612
  };
1388
- //# sourceMappingURL=index-BddUXwss.mjs.map
1613
+ //# sourceMappingURL=index-CNR8i3KM.mjs.map