@strapi/i18n 0.0.0-experimental.d954d57341a6623992a0d211daaec8e245c3517d → 0.0.0-experimental.dad3c50630ca4fd9eccdcbe549ee632fc572e23d

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-Dsi2qGtq.mjs → SettingsPage-B6QDUmu9.mjs} +17 -12
  3. package/dist/_chunks/SettingsPage-B6QDUmu9.mjs.map +1 -0
  4. package/dist/_chunks/{SettingsPage-VN7sTzkb.js → SettingsPage-BsHtr3lV.js} +18 -14
  5. package/dist/_chunks/SettingsPage-BsHtr3lV.js.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-kedPlCo6.js → index-3XgwXL6T.js} +459 -225
  11. package/dist/_chunks/index-3XgwXL6T.js.map +1 -0
  12. package/dist/_chunks/{index-DhtjJYrx.mjs → index-iEQ79W05.mjs} +454 -219
  13. package/dist/_chunks/index-iEQ79W05.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/LocaleListCell.d.ts +4 -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 +418 -478
  24. package/dist/server/index.js.map +1 -1
  25. package/dist/server/index.mjs +419 -478
  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 +13 -13
  43. package/dist/_chunks/SettingsPage-Dsi2qGtq.mjs.map +0 -1
  44. package/dist/_chunks/SettingsPage-VN7sTzkb.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-DhtjJYrx.mjs.map +0 -1
  48. package/dist/_chunks/index-kedPlCo6.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,24 +1,32 @@
1
1
  import get from "lodash/get";
2
2
  import * as yup from "yup";
3
- import { jsxs, jsx } from "react/jsx-runtime";
3
+ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
4
4
  import * as React from "react";
5
- import { Typography, Dialog, Field, Checkbox, Flex, 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";
13
14
  import { stringify } from "qs";
14
15
  import omit from "lodash/omit";
15
- const __variableDynamicImportRuntimeHelper = (glob, path) => {
16
+ const __variableDynamicImportRuntimeHelper = (glob, path, segs) => {
16
17
  const v = glob[path];
17
18
  if (v) {
18
19
  return typeof v === "function" ? v() : Promise.resolve(v);
19
20
  }
20
21
  return new Promise((_, reject) => {
21
- (typeof queueMicrotask === "function" ? queueMicrotask : setTimeout)(reject.bind(null, new Error("Unknown variable dynamic import: " + path)));
22
+ (typeof queueMicrotask === "function" ? queueMicrotask : setTimeout)(
23
+ reject.bind(
24
+ null,
25
+ new Error(
26
+ "Unknown variable dynamic import: " + path + (path.split("/").length !== segs ? ". Note that variables only represent file names one level deep." : "")
27
+ )
28
+ )
29
+ );
22
30
  });
23
31
  };
24
32
  const pluginId = "i18n";
@@ -77,11 +85,11 @@ const CheckboxConfirmation = ({
77
85
  }) }) })
78
86
  ] }) }),
79
87
  /* @__PURE__ */ jsxs(Dialog.Footer, { children: [
80
- /* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button$1, { variant: "tertiary", children: formatMessage({
88
+ /* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", children: formatMessage({
81
89
  id: "components.popUpWarning.button.cancel",
82
90
  defaultMessage: "No, cancel"
83
91
  }) }) }),
84
- /* @__PURE__ */ jsx(Dialog.Action, { children: /* @__PURE__ */ jsx(Button$1, { variant: "danger-light", onClick: handleConfirm, children: formatMessage({
92
+ /* @__PURE__ */ jsx(Dialog.Action, { children: /* @__PURE__ */ jsx(Button, { variant: "danger-light", onClick: handleConfirm, children: formatMessage({
85
93
  id: getTranslation("CheckboxConfirmation.Modal.button-confirm"),
86
94
  defaultMessage: "Yes, disable"
87
95
  }) }) })
@@ -136,7 +144,7 @@ const useI18n = () => {
136
144
  model: params.slug
137
145
  },
138
146
  {
139
- skip: !params.slug || !params.collectionType
147
+ skip: true
140
148
  }
141
149
  );
142
150
  if (doesPluginOptionsHaveI18nLocalized(schema?.pluginOptions)) {
@@ -216,10 +224,94 @@ const relationsApi = i18nApi.injectEndpoints({
216
224
  })
217
225
  });
218
226
  const { useGetManyDraftRelationCountQuery } = relationsApi;
227
+ const cleanData = (data, schema, components) => {
228
+ const cleanedData = removeFields(data, [
229
+ "createdAt",
230
+ "createdBy",
231
+ "updatedAt",
232
+ "updatedBy",
233
+ "id",
234
+ "documentId",
235
+ "publishedAt",
236
+ "strapi_stage",
237
+ "strapi_assignee",
238
+ "locale",
239
+ "status"
240
+ ]);
241
+ const cleanedDataWithoutPasswordAndRelation = recursiveRemoveFieldTypes(
242
+ cleanedData,
243
+ schema,
244
+ components,
245
+ ["relation", "password"]
246
+ );
247
+ return cleanedDataWithoutPasswordAndRelation;
248
+ };
249
+ const removeFields = (data, fields) => {
250
+ return Object.keys(data).reduce((acc, current) => {
251
+ if (fields.includes(current)) {
252
+ return acc;
253
+ }
254
+ acc[current] = data[current];
255
+ return acc;
256
+ }, {});
257
+ };
258
+ const recursiveRemoveFieldTypes = (data, schema, components, fields) => {
259
+ return Object.keys(data).reduce((acc, current) => {
260
+ const attribute = schema.attributes[current] ?? { type: void 0 };
261
+ if (fields.includes(attribute.type)) {
262
+ return acc;
263
+ }
264
+ if (attribute.type === "dynamiczone") {
265
+ acc[current] = data[current].map((componentValue, index2) => {
266
+ const { id: _, ...rest } = recursiveRemoveFieldTypes(
267
+ componentValue,
268
+ components[componentValue.__component],
269
+ components,
270
+ fields
271
+ );
272
+ return {
273
+ ...rest,
274
+ __temp_key__: index2 + 1
275
+ };
276
+ });
277
+ } else if (attribute.type === "component") {
278
+ const { repeatable, component } = attribute;
279
+ if (repeatable) {
280
+ acc[current] = (data[current] ?? []).map((compoData, index2) => {
281
+ const { id: _, ...rest } = recursiveRemoveFieldTypes(
282
+ compoData,
283
+ components[component],
284
+ components,
285
+ fields
286
+ );
287
+ return {
288
+ ...rest,
289
+ __temp_key__: index2 + 1
290
+ };
291
+ });
292
+ } else {
293
+ const { id: _, ...rest } = recursiveRemoveFieldTypes(
294
+ data[current] ?? {},
295
+ components[component],
296
+ components,
297
+ fields
298
+ );
299
+ acc[current] = rest;
300
+ }
301
+ } else {
302
+ acc[current] = data[current];
303
+ }
304
+ return acc;
305
+ }, {});
306
+ };
219
307
  const isErrorMessageDescriptor = (object) => {
220
308
  return typeof object === "object" && object !== null && "id" in object && "defaultMessage" in object;
221
309
  };
222
- const EntryValidationText = ({ status = "draft", validationErrors }) => {
310
+ const EntryValidationText = ({
311
+ status = "draft",
312
+ validationErrors,
313
+ action
314
+ }) => {
223
315
  const { formatMessage } = useIntl();
224
316
  const getErrorStr = (key, value) => {
225
317
  if (typeof value === "string") {
@@ -253,30 +345,63 @@ const EntryValidationText = ({ status = "draft", validationErrors }) => {
253
345
  ) })
254
346
  ] });
255
347
  }
256
- if (status === "published") {
257
- return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
258
- /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
259
- /* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
260
- id: "content-manager.bulk-publish.already-published",
261
- defaultMessage: "Already Published"
262
- }) })
263
- ] });
264
- }
265
- if (status === "modified") {
266
- return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
267
- /* @__PURE__ */ jsx(ArrowsCounterClockwise, { fill: "alternative600" }),
268
- /* @__PURE__ */ jsx(Typography, { children: formatMessage({
269
- id: "app.utils.ready-to-publish-changes",
270
- defaultMessage: "Ready to publish changes"
271
- }) })
272
- ] });
273
- }
348
+ const getStatusMessage = () => {
349
+ if (action === "bulk-publish") {
350
+ if (status === "published") {
351
+ return {
352
+ icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
353
+ text: formatMessage({
354
+ id: "content-manager.bulk-publish.already-published",
355
+ defaultMessage: "Already Published"
356
+ }),
357
+ textColor: "success600",
358
+ fontWeight: "bold"
359
+ };
360
+ } else if (status === "modified") {
361
+ return {
362
+ icon: /* @__PURE__ */ jsx(ArrowsCounterClockwise, { fill: "alternative600" }),
363
+ text: formatMessage({
364
+ id: "app.utils.ready-to-publish-changes",
365
+ defaultMessage: "Ready to publish changes"
366
+ })
367
+ };
368
+ } else {
369
+ return {
370
+ icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
371
+ text: formatMessage({
372
+ id: "app.utils.ready-to-publish",
373
+ defaultMessage: "Ready to publish"
374
+ })
375
+ };
376
+ }
377
+ } else {
378
+ if (status === "draft") {
379
+ return {
380
+ icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
381
+ text: formatMessage({
382
+ id: "content-manager.bulk-unpublish.already-unpublished",
383
+ defaultMessage: "Already Unpublished"
384
+ }),
385
+ textColor: "success600",
386
+ fontWeight: "bold"
387
+ };
388
+ } else {
389
+ return {
390
+ icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
391
+ text: formatMessage({
392
+ id: "app.utils.ready-to-unpublish-changes",
393
+ defaultMessage: "Ready to unpublish"
394
+ }),
395
+ textColor: "success600",
396
+ fontWeight: "bold"
397
+ };
398
+ }
399
+ }
400
+ };
401
+ const { icon, text, textColor = "success600", fontWeight = "normal" } = getStatusMessage();
274
402
  return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
275
- /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
276
- /* @__PURE__ */ jsx(Typography, { children: formatMessage({
277
- id: "app.utils.ready-to-publish",
278
- defaultMessage: "Ready to publish"
279
- }) })
403
+ icon,
404
+ /* @__PURE__ */ jsx(Typography, { textColor, fontWeight, children: text })
280
405
  ] });
281
406
  };
282
407
  const BoldChunk = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: chunks });
@@ -284,7 +409,8 @@ const BulkLocaleActionModal = ({
284
409
  headers,
285
410
  rows,
286
411
  localesMetadata,
287
- validationErrors = {}
412
+ validationErrors = {},
413
+ action
288
414
  }) => {
289
415
  const { formatMessage } = useIntl();
290
416
  const selectedRows = useTable(
@@ -297,27 +423,29 @@ const BulkLocaleActionModal = ({
297
423
  return acc;
298
424
  }, {});
299
425
  const localesWithErrors = Object.keys(validationErrors);
300
- const alreadyPublishedCount = selectedRows.filter(
426
+ const publishedCount = selectedRows.filter(
301
427
  ({ locale }) => currentStatusByLocale[locale] === "published"
302
428
  ).length;
303
- const readyToPublishCount = selectedRows.filter(
429
+ const draftCount = selectedRows.filter(
304
430
  ({ locale }) => (currentStatusByLocale[locale] === "draft" || currentStatusByLocale[locale] === "modified") && !localesWithErrors.includes(locale)
305
431
  ).length;
306
432
  const withErrorsCount = localesWithErrors.length;
433
+ const messageId = action === "bulk-publish" ? "content-manager.containers.list.selectedEntriesModal.selectedCount.publish" : "content-manager.containers.list.selectedEntriesModal.selectedCount.unpublish";
434
+ 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.";
307
435
  return formatMessage(
308
436
  {
309
- id: "content-manager.containers.list.selectedEntriesModal.selectedCount",
310
- 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."
437
+ id: messageId,
438
+ defaultMessage
311
439
  },
312
440
  {
313
441
  withErrorsCount,
314
- readyToPublishCount,
315
- alreadyPublishedCount,
442
+ draftCount,
443
+ publishedCount,
316
444
  b: BoldChunk
317
445
  }
318
446
  );
319
447
  };
320
- return /* @__PURE__ */ jsxs(React.Fragment, { children: [
448
+ return /* @__PURE__ */ jsxs(Modal.Body, { children: [
321
449
  /* @__PURE__ */ jsx(Typography, { children: getFormattedCountMessage() }),
322
450
  /* @__PURE__ */ jsx(Box, { marginTop: 5, children: /* @__PURE__ */ jsxs(Table.Content, { children: [
323
451
  /* @__PURE__ */ jsxs(Table.Head, { children: [
@@ -338,13 +466,12 @@ const BulkLocaleActionModal = ({
338
466
  paddingRight: "6px",
339
467
  paddingTop: "2px",
340
468
  paddingBottom: "2px",
341
- showBullet: false,
342
469
  size: "S",
343
470
  variant: statusVariant,
344
471
  children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "pi", fontWeight: "bold", children: capitalize(status) })
345
472
  }
346
473
  ) }) }),
347
- /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(EntryValidationText, { validationErrors: error, status }) }),
474
+ /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(EntryValidationText, { validationErrors: error, status, action }) }),
348
475
  /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
349
476
  IconButton,
350
477
  {
@@ -361,7 +488,7 @@ const BulkLocaleActionModal = ({
361
488
  name: locale
362
489
  }
363
490
  ),
364
- borderWidth: 0,
491
+ variant: "ghost",
365
492
  children: /* @__PURE__ */ jsx(Pencil, {})
366
493
  }
367
494
  ) })
@@ -370,6 +497,47 @@ const BulkLocaleActionModal = ({
370
497
  ] }) })
371
498
  ] });
372
499
  };
500
+ const statusVariants = {
501
+ draft: "secondary",
502
+ published: "success",
503
+ modified: "alternative"
504
+ };
505
+ const LocaleOption = ({
506
+ isDraftAndPublishEnabled,
507
+ locale,
508
+ status,
509
+ entryExists
510
+ }) => {
511
+ const { formatMessage } = useIntl();
512
+ if (!entryExists) {
513
+ return formatMessage(
514
+ {
515
+ id: getTranslation("CMEditViewLocalePicker.locale.create"),
516
+ defaultMessage: "Create <bold>{locale}</bold> locale"
517
+ },
518
+ {
519
+ bold: (locale2) => /* @__PURE__ */ jsx("b", { children: locale2 }),
520
+ locale: locale.name
521
+ }
522
+ );
523
+ }
524
+ return /* @__PURE__ */ jsxs(Flex, { width: "100%", gap: 1, justifyContent: "space-between", children: [
525
+ /* @__PURE__ */ jsx(Typography, { children: locale.name }),
526
+ isDraftAndPublishEnabled ? /* @__PURE__ */ jsx(
527
+ Status,
528
+ {
529
+ display: "flex",
530
+ paddingLeft: "6px",
531
+ paddingRight: "6px",
532
+ paddingTop: "2px",
533
+ paddingBottom: "2px",
534
+ size: "S",
535
+ variant: statusVariants[status],
536
+ children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "pi", fontWeight: "bold", children: capitalize(status) })
537
+ }
538
+ ) : null
539
+ ] });
540
+ };
373
541
  const LocalePickerAction = ({
374
542
  document,
375
543
  meta,
@@ -381,7 +549,13 @@ const LocalePickerAction = ({
381
549
  const [{ query }, setQuery] = useQueryParams();
382
550
  const { hasI18n, canCreate, canRead } = useI18n();
383
551
  const { data: locales = [] } = useGetLocalesQuery();
384
- const { schema } = unstable_useDocument({ model, collectionType, documentId });
552
+ const currentDesiredLocale = query.plugins?.i18n?.locale;
553
+ const { schema } = unstable_useDocument({
554
+ model,
555
+ collectionType,
556
+ documentId,
557
+ params: { locale: currentDesiredLocale }
558
+ });
385
559
  const handleSelect = React.useCallback(
386
560
  (value) => {
387
561
  setQuery({
@@ -399,53 +573,50 @@ const LocalePickerAction = ({
399
573
  if (!Array.isArray(locales) || !hasI18n) {
400
574
  return;
401
575
  }
402
- const currentDesiredLocale = query.plugins?.i18n?.locale;
403
576
  const doesLocaleExist = locales.find((loc) => loc.code === currentDesiredLocale);
404
577
  const defaultLocale = locales.find((locale) => locale.isDefault);
405
578
  if (!doesLocaleExist && defaultLocale?.code) {
406
579
  handleSelect(defaultLocale.code);
407
580
  }
408
- }, [handleSelect, hasI18n, locales, query.plugins?.i18n?.locale]);
581
+ }, [handleSelect, hasI18n, locales, currentDesiredLocale]);
582
+ const currentLocale = Array.isArray(locales) ? locales.find((locale) => locale.code === currentDesiredLocale) : void 0;
583
+ const allCurrentLocales = [
584
+ { status: getDocumentStatus(document, meta), locale: currentLocale?.code },
585
+ ...document?.localizations ?? []
586
+ ];
409
587
  if (!hasI18n || !Array.isArray(locales) || locales.length === 0) {
410
588
  return null;
411
589
  }
412
- const currentLocale = query.plugins?.i18n?.locale || locales.find((loc) => loc.isDefault)?.code;
413
- const allCurrentLocales = [
414
- { status: getDocumentStatus(document, meta), locale: currentLocale },
415
- ...meta?.availableLocales ?? []
416
- ];
590
+ const displayedLocales = locales.filter((locale) => {
591
+ return canRead.includes(locale.code);
592
+ });
417
593
  return {
418
594
  label: formatMessage({
419
595
  id: getTranslation("Settings.locales.modal.locales.label"),
420
596
  defaultMessage: "Locales"
421
597
  }),
422
- options: locales.map((locale) => {
598
+ options: displayedLocales.map((locale) => {
599
+ const entryWithLocaleExists = allCurrentLocales.some((doc) => doc.locale === locale.code);
423
600
  const currentLocaleDoc = allCurrentLocales.find(
424
601
  (doc) => "locale" in doc ? doc.locale === locale.code : false
425
602
  );
426
- const status = currentLocaleDoc?.status ?? "draft";
427
- const permissionsToCheck = currentLocaleDoc ? canCreate : canRead;
428
- const statusVariant = status === "draft" ? "primary" : status === "published" ? "success" : "alternative";
603
+ const permissionsToCheck = currentLocaleDoc ? canRead : canCreate;
429
604
  return {
430
605
  disabled: !permissionsToCheck.includes(locale.code),
431
606
  value: locale.code,
432
- label: locale.name,
433
- startIcon: schema?.options?.draftAndPublish ? /* @__PURE__ */ jsx(
434
- Status,
607
+ label: /* @__PURE__ */ jsx(
608
+ LocaleOption,
435
609
  {
436
- display: "flex",
437
- paddingLeft: "6px",
438
- paddingRight: "6px",
439
- paddingTop: "2px",
440
- paddingBottom: "2px",
441
- showBullet: false,
442
- size: "S",
443
- variant: statusVariant,
444
- children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "pi", fontWeight: "bold", children: capitalize(status) })
610
+ isDraftAndPublishEnabled: !!schema?.options?.draftAndPublish,
611
+ locale,
612
+ status: currentLocaleDoc?.status,
613
+ entryExists: entryWithLocaleExists
445
614
  }
446
- ) : null
615
+ ),
616
+ startIcon: !entryWithLocaleExists ? /* @__PURE__ */ jsx(Plus, {}) : null
447
617
  };
448
618
  }),
619
+ customizeContent: () => currentLocale?.name,
449
620
  onSelect: handleSelect,
450
621
  value: currentLocale
451
622
  };
@@ -461,6 +632,99 @@ const getDocumentStatus = (document, meta) => {
461
632
  }
462
633
  return docStatus;
463
634
  };
635
+ const FillFromAnotherLocaleAction = ({
636
+ documentId,
637
+ meta,
638
+ model,
639
+ collectionType
640
+ }) => {
641
+ const { formatMessage } = useIntl();
642
+ const [{ query }] = useQueryParams();
643
+ const { hasI18n } = useI18n();
644
+ const currentDesiredLocale = query.plugins?.i18n?.locale;
645
+ const [localeSelected, setLocaleSelected] = React.useState(null);
646
+ const setValues = useForm("FillFromAnotherLocale", (state) => state.setValues);
647
+ const { getDocument } = unstable_useDocumentActions();
648
+ const { schema, components } = unstable_useDocument({
649
+ model,
650
+ documentId,
651
+ collectionType,
652
+ params: { locale: currentDesiredLocale }
653
+ });
654
+ const { data: locales = [] } = useGetLocalesQuery();
655
+ const availableLocales = Array.isArray(locales) ? locales.filter((locale) => meta?.availableLocales.some((l) => l.locale === locale.code)) : [];
656
+ const fillFromLocale = (onClose) => async () => {
657
+ const response = await getDocument({
658
+ collectionType,
659
+ model,
660
+ documentId,
661
+ params: { locale: localeSelected }
662
+ });
663
+ if (!response || !schema) {
664
+ return;
665
+ }
666
+ const { data } = response;
667
+ const cleanedData = cleanData(data, schema, components);
668
+ setValues(cleanedData);
669
+ onClose();
670
+ };
671
+ if (!hasI18n) {
672
+ return null;
673
+ }
674
+ return {
675
+ type: "icon",
676
+ icon: /* @__PURE__ */ jsx(Download, {}),
677
+ disabled: availableLocales.length === 0,
678
+ label: formatMessage({
679
+ id: getTranslation("CMEditViewCopyLocale.copy-text"),
680
+ defaultMessage: "Fill in from another locale"
681
+ }),
682
+ dialog: {
683
+ type: "dialog",
684
+ title: formatMessage({
685
+ id: getTranslation("CMEditViewCopyLocale.dialog.title"),
686
+ defaultMessage: "Confirmation"
687
+ }),
688
+ content: ({ onClose }) => /* @__PURE__ */ jsxs(Fragment, { children: [
689
+ /* @__PURE__ */ jsx(Dialog.Body, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 3, children: [
690
+ /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
691
+ /* @__PURE__ */ jsx(Typography, { textAlign: "center", children: formatMessage({
692
+ id: getTranslation("CMEditViewCopyLocale.dialog.body"),
693
+ defaultMessage: "Your current content will be erased and filled by the content of the selected locale:"
694
+ }) }),
695
+ /* @__PURE__ */ jsxs(Field.Root, { width: "100%", children: [
696
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
697
+ id: getTranslation("CMEditViewCopyLocale.dialog.field.label"),
698
+ defaultMessage: "Locale"
699
+ }) }),
700
+ /* @__PURE__ */ jsx(
701
+ SingleSelect,
702
+ {
703
+ value: localeSelected,
704
+ placeholder: formatMessage({
705
+ id: getTranslation("CMEditViewCopyLocale.dialog.field.placeholder"),
706
+ defaultMessage: "Select one locale..."
707
+ }),
708
+ onChange: (value) => setLocaleSelected(value),
709
+ children: availableLocales.map((locale) => /* @__PURE__ */ jsx(SingleSelectOption, { value: locale.code, children: locale.name }, locale.code))
710
+ }
711
+ )
712
+ ] })
713
+ ] }) }),
714
+ /* @__PURE__ */ jsx(Dialog.Footer, { children: /* @__PURE__ */ jsxs(Flex, { gap: 2, width: "100%", children: [
715
+ /* @__PURE__ */ jsx(Button, { flex: "auto", variant: "tertiary", onClick: onClose, children: formatMessage({
716
+ id: getTranslation("CMEditViewCopyLocale.cancel-text"),
717
+ defaultMessage: "No, cancel"
718
+ }) }),
719
+ /* @__PURE__ */ jsx(Button, { flex: "auto", variant: "success", onClick: fillFromLocale(onClose), children: formatMessage({
720
+ id: getTranslation("CMEditViewCopyLocale.submit-text"),
721
+ defaultMessage: "Yes, fill in"
722
+ }) })
723
+ ] }) })
724
+ ] })
725
+ }
726
+ };
727
+ };
464
728
  const DeleteLocaleAction = ({
465
729
  document,
466
730
  documentId,
@@ -472,16 +736,23 @@ const DeleteLocaleAction = ({
472
736
  const { toggleNotification } = useNotification();
473
737
  const { delete: deleteAction } = unstable_useDocumentActions();
474
738
  const { hasI18n, canDelete } = useI18n();
739
+ const [{ query }] = useQueryParams();
740
+ const { data: locales = [] } = useGetLocalesQuery();
741
+ const currentDesiredLocale = query.plugins?.i18n?.locale;
742
+ const locale = !("error" in locales) && locales.find((loc) => loc.code === currentDesiredLocale);
475
743
  if (!hasI18n) {
476
744
  return null;
477
745
  }
478
746
  return {
479
747
  disabled: document?.locale && !canDelete.includes(document.locale) || !document || !document.id,
480
748
  position: ["header", "table-row"],
481
- label: formatMessage({
482
- id: getTranslation("actions.delete.label"),
483
- defaultMessage: "Delete locale"
484
- }),
749
+ label: formatMessage(
750
+ {
751
+ id: getTranslation("actions.delete.label"),
752
+ defaultMessage: "Delete entry ({locale})"
753
+ },
754
+ { locale: locale && locale.name }
755
+ ),
485
756
  icon: /* @__PURE__ */ jsx(StyledTrash, {}),
486
757
  variant: "danger",
487
758
  dialog: {
@@ -498,7 +769,12 @@ const DeleteLocaleAction = ({
498
769
  }) })
499
770
  ] }),
500
771
  onConfirm: async () => {
501
- if (!documentId || !document?.locale) {
772
+ const unableToDelete = (
773
+ // We are unable to delete a collection type without a document ID
774
+ // & unable to delete generally if there is no document locale
775
+ collectionType !== "single-types" && !documentId || !document?.locale
776
+ );
777
+ if (unableToDelete) {
502
778
  console.error(
503
779
  "You're trying to delete a document without an id or locale, this is likely a bug with Strapi. Please open an issue."
504
780
  );
@@ -524,37 +800,39 @@ const DeleteLocaleAction = ({
524
800
  }
525
801
  };
526
802
  };
527
- const BulkLocalePublishAction = ({
528
- document: baseDocument,
803
+ const BulkLocaleAction = ({
804
+ document,
529
805
  documentId,
530
806
  model,
531
- collectionType
807
+ collectionType,
808
+ action
532
809
  }) => {
533
- const baseLocale = baseDocument?.locale ?? null;
810
+ const locale = document?.locale ?? null;
534
811
  const [{ query }] = useQueryParams();
535
812
  const params = React.useMemo(() => buildValidParams(query), [query]);
536
- const isPublishedTab = query.status === "published";
813
+ const isOnPublishedTab = query.status === "published";
537
814
  const { formatMessage } = useIntl();
538
815
  const { hasI18n, canPublish } = useI18n();
539
816
  const { toggleNotification } = useNotification();
540
817
  const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
541
818
  const [selectedRows, setSelectedRows] = React.useState([]);
542
- const [isConfirmationOpen, setIsConfirmationOpen] = React.useState(false);
543
- const { publishMany: publishManyAction } = unstable_useDocumentActions();
544
- const {
545
- document,
546
- meta: documentMeta,
547
- schema,
548
- validate
549
- } = unstable_useDocument({
550
- model,
551
- collectionType,
552
- documentId,
553
- params: {
554
- locale: baseLocale
819
+ const [isDraftRelationConfirmationOpen, setIsDraftRelationConfirmationOpen] = React.useState(false);
820
+ const { publishMany: publishManyAction, unpublishMany: unpublishManyAction } = unstable_useDocumentActions();
821
+ const { schema, validate } = unstable_useDocument(
822
+ {
823
+ model,
824
+ collectionType,
825
+ documentId,
826
+ params: {
827
+ locale
828
+ }
829
+ },
830
+ {
831
+ // No need to fetch the document, the data is already available in the `document` prop
832
+ skip: true
555
833
  }
556
- });
557
- const { data: localesMetadata = [] } = useGetLocalesQuery();
834
+ );
835
+ const { data: localesMetadata = [] } = useGetLocalesQuery(hasI18n ? void 0 : skipToken);
558
836
  const headers = [
559
837
  {
560
838
  label: formatMessage({
@@ -579,18 +857,19 @@ const BulkLocalePublishAction = ({
579
857
  }
580
858
  ];
581
859
  const [rows, validationErrors] = React.useMemo(() => {
582
- if (!document || !documentMeta?.availableLocales) {
860
+ if (!document) {
583
861
  return [[], {}];
584
862
  }
585
- const rowsFromMeta = documentMeta?.availableLocales.map((doc) => {
586
- const { locale, status } = doc;
587
- return { locale, status };
863
+ const localizations = document.localizations ?? [];
864
+ const locales = localizations.map((doc) => {
865
+ const { locale: locale2, status } = doc;
866
+ return { locale: locale2, status };
588
867
  });
589
- rowsFromMeta.unshift({
868
+ locales.unshift({
590
869
  locale: document.locale,
591
870
  status: document.status
592
871
  });
593
- const allDocuments = [document, ...documentMeta?.availableLocales ?? []];
872
+ const allDocuments = [document, ...localizations];
594
873
  const errors = allDocuments.reduce((errs, document2) => {
595
874
  if (!document2) {
596
875
  return errs;
@@ -601,14 +880,21 @@ const BulkLocalePublishAction = ({
601
880
  }
602
881
  return errs;
603
882
  }, {});
604
- return [rowsFromMeta, errors];
605
- }, [document, documentMeta?.availableLocales, validate]);
606
- const localesToPublish = selectedRows.reduce((acc, selectedRow) => {
607
- if (selectedRow.status !== "published" && !Object.keys(validationErrors).includes(selectedRow.locale)) {
883
+ return [locales, errors];
884
+ }, [document, validate]);
885
+ const isBulkPublish = action === "bulk-publish";
886
+ const localesForAction = selectedRows.reduce((acc, selectedRow) => {
887
+ const isValidLocale = (
888
+ // Validation errors are irrelevant if we are trying to unpublish
889
+ !isBulkPublish || !Object.keys(validationErrors).includes(selectedRow.locale)
890
+ );
891
+ const shouldAddLocale = isBulkPublish ? selectedRow.status !== "published" && isValidLocale : selectedRow.status !== "draft" && isValidLocale;
892
+ if (shouldAddLocale) {
608
893
  acc.push(selectedRow.locale);
609
894
  }
610
895
  return acc;
611
896
  }, []);
897
+ const enableDraftRelationsCount = false;
612
898
  const {
613
899
  data: draftRelationsCount = 0,
614
900
  isLoading: isDraftRelationsLoading,
@@ -617,10 +903,10 @@ const BulkLocalePublishAction = ({
617
903
  {
618
904
  model,
619
905
  documentIds: [documentId],
620
- locale: localesToPublish
906
+ locale: localesForAction
621
907
  },
622
908
  {
623
- skip: !documentId || localesToPublish.length === 0
909
+ skip: !enableDraftRelationsCount
624
910
  }
625
911
  );
626
912
  React.useEffect(() => {
@@ -646,23 +932,32 @@ const BulkLocalePublishAction = ({
646
932
  documentIds: [documentId],
647
933
  params: {
648
934
  ...params,
649
- locale: localesToPublish
935
+ locale: localesForAction
936
+ }
937
+ });
938
+ setSelectedRows([]);
939
+ };
940
+ const unpublish = async () => {
941
+ await unpublishManyAction({
942
+ model,
943
+ documentIds: [documentId],
944
+ params: {
945
+ ...params,
946
+ locale: localesForAction
650
947
  }
651
948
  });
652
949
  setSelectedRows([]);
653
950
  };
654
951
  const handleAction = async () => {
655
952
  if (draftRelationsCount > 0) {
656
- setIsConfirmationOpen(true);
657
- } else {
953
+ setIsDraftRelationConfirmationOpen(true);
954
+ } else if (isBulkPublish) {
658
955
  await publish();
956
+ } else {
957
+ await unpublish();
659
958
  }
660
959
  };
661
- const isUnpublish = document?.status === "published";
662
- if (isUnpublish) {
663
- console.warn(["I18N"], "Bulk locale unpublish modal not implemented");
664
- }
665
- if (isConfirmationOpen) {
960
+ if (isDraftRelationConfirmationOpen) {
666
961
  return {
667
962
  label: formatMessage({
668
963
  id: "app.components.ConfirmDialog.title",
@@ -671,11 +966,11 @@ const BulkLocalePublishAction = ({
671
966
  variant: "danger",
672
967
  dialog: {
673
968
  onCancel: () => {
674
- setIsConfirmationOpen(false);
969
+ setIsDraftRelationConfirmationOpen(false);
675
970
  },
676
971
  onConfirm: async () => {
677
972
  await publish();
678
- setIsConfirmationOpen(false);
973
+ setIsDraftRelationConfirmationOpen(false);
679
974
  },
680
975
  type: "dialog",
681
976
  title: formatMessage({
@@ -685,27 +980,32 @@ const BulkLocalePublishAction = ({
685
980
  content: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "center", gap: 2, children: [
686
981
  /* @__PURE__ */ jsx(WarningCircle, { width: "2.4rem", height: "2.4rem", fill: "danger600" }),
687
982
  /* @__PURE__ */ jsx(Typography, { textAlign: "center", children: formatMessage({
688
- id: "content-manager.actions.discard.dialog.body",
689
- defaultMessage: "Are you sure you want to discard the changes? This action is irreversible."
983
+ id: getTranslation("CMEditViewBulkLocale.draft-relation-warning"),
984
+ defaultMessage: "Some locales are related to draft entries. Publishing them could leave broken links in your app."
985
+ }) }),
986
+ /* @__PURE__ */ jsx(Typography, { textAlign: "center", children: formatMessage({
987
+ id: getTranslation("CMEditViewBulkLocale.continue-confirmation"),
988
+ defaultMessage: "Are you sure you want to continue?"
690
989
  }) })
691
990
  ] })
692
991
  }
693
992
  };
694
993
  }
994
+ const hasPermission = selectedRows.map(({ locale: locale2 }) => locale2).every((locale2) => canPublish.includes(locale2));
695
995
  return {
696
996
  label: formatMessage({
697
- id: getTranslation("CMEditViewBulkLocale.publish-title"),
698
- defaultMessage: "Publish Multiple Locales"
997
+ id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
998
+ defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
699
999
  }),
700
- icon: /* @__PURE__ */ jsx(ListPlus, {}),
701
- disabled: isPublishedTab || !canPublish,
1000
+ variant: isBulkPublish ? "secondary" : "danger",
1001
+ icon: isBulkPublish ? /* @__PURE__ */ jsx(ListPlus, {}) : /* @__PURE__ */ jsx(Cross, {}),
1002
+ disabled: isOnPublishedTab || canPublish.length === 0,
702
1003
  position: ["panel"],
703
- variant: "secondary",
704
1004
  dialog: {
705
1005
  type: "modal",
706
1006
  title: formatMessage({
707
- id: getTranslation("CMEditViewBulkLocale.publish-title"),
708
- defaultMessage: "Publish Multiple Locales"
1007
+ id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
1008
+ defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
709
1009
  }),
710
1010
  content: () => {
711
1011
  return /* @__PURE__ */ jsx(
@@ -724,28 +1024,35 @@ const BulkLocalePublishAction = ({
724
1024
  validationErrors,
725
1025
  headers,
726
1026
  rows,
727
- localesMetadata
1027
+ localesMetadata,
1028
+ action: action ?? "bulk-publish"
728
1029
  }
729
1030
  )
730
1031
  }
731
1032
  );
732
1033
  },
733
- footer: () => /* @__PURE__ */ jsx(Flex, { justifyContent: "flex-end", children: /* @__PURE__ */ jsx(
734
- Button$1,
1034
+ footer: () => /* @__PURE__ */ jsx(Modal.Footer, { justifyContent: "flex-end", children: /* @__PURE__ */ jsx(
1035
+ Button,
735
1036
  {
736
1037
  loading: isDraftRelationsLoading,
737
- disabled: localesToPublish.length === 0,
1038
+ disabled: !hasPermission || localesForAction.length === 0,
738
1039
  variant: "default",
739
1040
  onClick: handleAction,
740
1041
  children: formatMessage({
741
- id: "app.utils.publish",
742
- defaultMessage: "Publish"
1042
+ id: isBulkPublish ? "app.utils.publish" : "app.utils.unpublish",
1043
+ defaultMessage: isBulkPublish ? "Publish" : "Unpublish"
743
1044
  })
744
1045
  }
745
1046
  ) })
746
1047
  }
747
1048
  };
748
1049
  };
1050
+ const BulkLocalePublishAction = (props) => {
1051
+ return BulkLocaleAction({ action: "bulk-publish", ...props });
1052
+ };
1053
+ const BulkLocaleUnpublishAction = (props) => {
1054
+ return BulkLocaleAction({ action: "bulk-unpublish", ...props });
1055
+ };
749
1056
  const StyledTrash = styled(Trash)`
750
1057
  path {
751
1058
  fill: currentColor;
@@ -802,13 +1109,6 @@ const UnpublishModalAdditionalInfo = () => {
802
1109
  }
803
1110
  ) });
804
1111
  };
805
- const Initializer = ({ setPlugin }) => {
806
- const setPluginRef = React.useRef(setPlugin);
807
- React.useEffect(() => {
808
- setPluginRef.current(pluginId);
809
- }, []);
810
- return null;
811
- };
812
1112
  const LocalePicker = () => {
813
1113
  const { formatMessage } = useIntl();
814
1114
  const [{ query }, setQuery] = useQueryParams();
@@ -934,29 +1234,16 @@ const Span = styled(Flex)`
934
1234
  }
935
1235
  }
936
1236
  `;
937
- const LocaleListCell = ({
938
- documentId,
939
- locale: currentLocale,
940
- collectionType,
941
- model
942
- }) => {
943
- const { meta, isLoading } = unstable_useDocument({
944
- documentId,
945
- collectionType,
946
- model,
947
- params: {
948
- locale: currentLocale
949
- }
950
- });
1237
+ const LocaleListCell = ({ locale: currentLocale, localizations }) => {
951
1238
  const { locale: language } = useIntl();
952
1239
  const { data: locales = [] } = useGetLocalesQuery();
953
1240
  const formatter = useCollator(language, {
954
1241
  sensitivity: "base"
955
1242
  });
956
- if (!Array.isArray(locales) || isLoading) {
1243
+ if (!Array.isArray(locales) || !localizations) {
957
1244
  return null;
958
1245
  }
959
- const availableLocales = meta?.availableLocales.map((doc) => doc.locale) ?? [];
1246
+ const availableLocales = localizations.map((loc) => loc.locale);
960
1247
  const localesForDocument = locales.reduce((acc, locale) => {
961
1248
  const createdLocale = [currentLocale, ...availableLocales].find((loc) => {
962
1249
  return loc === locale.code;
@@ -972,54 +1259,13 @@ const LocaleListCell = ({
972
1259
  return locale.name;
973
1260
  }).toSorted((a, b) => formatter.compare(a, b));
974
1261
  return /* @__PURE__ */ jsxs(Popover.Root, { children: [
975
- /* @__PURE__ */ jsx(Popover.Trigger, { children: /* @__PURE__ */ jsx(Button, { type: "button", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxs(
976
- ActionWrapper,
977
- {
978
- minWidth: "100%",
979
- alignItems: "center",
980
- justifyContent: "center",
981
- height: "3.2rem",
982
- width: "3.2rem",
983
- children: [
984
- /* @__PURE__ */ jsx(Typography, { textColor: "neutral800", ellipsis: true, children: localesForDocument.join(", ") }),
985
- /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(CaretDown, {}) })
986
- ]
987
- }
988
- ) }) }),
1262
+ /* @__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: [
1263
+ /* @__PURE__ */ jsx(Typography, { textColor: "neutral800", ellipsis: true, marginRight: 2, children: localesForDocument.join(", ") }),
1264
+ /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(CaretDown, { width: "1.2rem", height: "1.2rem" }) })
1265
+ ] }) }) }),
989
1266
  /* @__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)) }) })
990
1267
  ] });
991
1268
  };
992
- const Button = styled.button`
993
- width: 100%;
994
-
995
- svg {
996
- > g,
997
- path {
998
- fill: ${({ theme }) => theme.colors.neutral500};
999
- }
1000
- }
1001
- &:hover {
1002
- svg {
1003
- > g,
1004
- path {
1005
- fill: ${({ theme }) => theme.colors.neutral600};
1006
- }
1007
- }
1008
- }
1009
- &:active {
1010
- svg {
1011
- > g,
1012
- path {
1013
- fill: ${({ theme }) => theme.colors.neutral400};
1014
- }
1015
- }
1016
- }
1017
- `;
1018
- const ActionWrapper = styled(Flex)`
1019
- svg {
1020
- height: 0.4rem;
1021
- }
1022
- `;
1023
1269
  const addColumnToTableHook = ({ displayedHeaders, layout }) => {
1024
1270
  const { options } = layout;
1025
1271
  const isFieldLocalized = doesPluginOptionsHaveI18nLocalized(options) ? options.i18n.localized : false;
@@ -1048,18 +1294,11 @@ const addColumnToTableHook = ({ displayedHeaders, layout }) => {
1048
1294
  const addLocaleToReleasesHook = ({ displayedHeaders = [] }) => {
1049
1295
  return {
1050
1296
  displayedHeaders: [
1051
- // TODO: Fix when migrating to v5
1052
- // ...displayedHeaders,
1297
+ ...displayedHeaders,
1053
1298
  {
1054
- key: "__locale__",
1055
- fieldSchema: { type: "string" },
1056
- metadatas: {
1057
- label: {
1058
- id: "content-releases.page.ReleaseDetails.table.header.label.locale",
1059
- defaultMessage: "locale"
1060
- },
1061
- searchable: false,
1062
- sortable: false
1299
+ label: {
1300
+ id: "content-releases.page.ReleaseDetails.table.header.label.locale",
1301
+ defaultMessage: "locale"
1063
1302
  },
1064
1303
  name: "locale"
1065
1304
  }
@@ -1152,9 +1391,6 @@ const localeMiddleware = (ctx) => (next) => (permissions) => {
1152
1391
  return next(revisedPermissions);
1153
1392
  };
1154
1393
  const prefixPluginTranslations = (trad, pluginId2) => {
1155
- if (!pluginId2) {
1156
- throw new TypeError("pluginId can't be empty");
1157
- }
1158
1394
  return Object.keys(trad).reduce((acc, current) => {
1159
1395
  acc[`${pluginId2}.${current}`] = trad[current];
1160
1396
  return acc;
@@ -1207,8 +1443,6 @@ const index = {
1207
1443
  app.addRBACMiddleware([localeMiddleware]);
1208
1444
  app.registerPlugin({
1209
1445
  id: pluginId,
1210
- initializer: Initializer,
1211
- isReady: false,
1212
1446
  name: pluginId
1213
1447
  });
1214
1448
  },
@@ -1226,11 +1460,11 @@ const index = {
1226
1460
  },
1227
1461
  id: "internationalization",
1228
1462
  to: "internationalization",
1229
- Component: () => import("./SettingsPage-Dsi2qGtq.mjs").then((mod) => ({ default: mod.ProtectedSettingsPage })),
1463
+ Component: () => import("./SettingsPage-B6QDUmu9.mjs").then((mod) => ({ default: mod.ProtectedSettingsPage })),
1230
1464
  permissions: PERMISSIONS.accessMain
1231
1465
  });
1232
1466
  const contentManager = app.getPlugin("content-manager");
1233
- contentManager.apis.addDocumentHeaderAction([LocalePickerAction]);
1467
+ contentManager.apis.addDocumentHeaderAction([LocalePickerAction, FillFromAnotherLocaleAction]);
1234
1468
  contentManager.apis.addDocumentAction((actions) => {
1235
1469
  const indexOfDeleteAction = actions.findIndex((action) => action.type === "delete");
1236
1470
  actions.splice(indexOfDeleteAction, 0, DeleteLocaleAction);
@@ -1238,6 +1472,7 @@ const index = {
1238
1472
  });
1239
1473
  contentManager.apis.addDocumentAction((actions) => {
1240
1474
  actions.splice(2, 0, BulkLocalePublishAction);
1475
+ actions.splice(5, 0, BulkLocaleUnpublishAction);
1241
1476
  return actions;
1242
1477
  });
1243
1478
  contentManager.injectComponent("listView", "actions", {
@@ -1343,7 +1578,7 @@ const index = {
1343
1578
  async registerTrads({ locales }) {
1344
1579
  const importedTrads = await Promise.all(
1345
1580
  locales.map((locale) => {
1346
- 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 }) => {
1581
+ 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`, 3).then(({ default: data }) => {
1347
1582
  return {
1348
1583
  data: prefixPluginTranslations(data, pluginId),
1349
1584
  locale
@@ -1369,4 +1604,4 @@ export {
1369
1604
  index as i,
1370
1605
  useCreateLocaleMutation as u
1371
1606
  };
1372
- //# sourceMappingURL=index-DhtjJYrx.mjs.map
1607
+ //# sourceMappingURL=index-iEQ79W05.mjs.map