@strapi/i18n 0.0.0-experimental.e60ec1829240dae21c1e1d29076681c322288813 → 0.0.0-experimental.e9122b401c96877b6707775c4f893660eab93ae3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/LICENSE +18 -3
  2. package/dist/_chunks/{SettingsPage-CeqfDjsb.mjs → SettingsPage-BjxjwEOb.mjs} +115 -126
  3. package/dist/_chunks/SettingsPage-BjxjwEOb.mjs.map +1 -0
  4. package/dist/_chunks/{SettingsPage-Djqsdrzs.js → SettingsPage-CfTmCkup.js} +115 -126
  5. package/dist/_chunks/SettingsPage-CfTmCkup.js.map +1 -0
  6. package/dist/_chunks/{en-CnrTsjWS.mjs → en-2xztdZE1.mjs} +12 -1
  7. package/dist/_chunks/en-2xztdZE1.mjs.map +1 -0
  8. package/dist/_chunks/{en-BuBc6LKZ.js → en-DWpfm8h5.js} +12 -1
  9. package/dist/_chunks/en-DWpfm8h5.js.map +1 -0
  10. package/dist/_chunks/{index-DMXJeGjN.js → index-5XLZwzwx.js} +711 -207
  11. package/dist/_chunks/index-5XLZwzwx.js.map +1 -0
  12. package/dist/_chunks/{index-BDU1w_fd.mjs → index-D-qx3tz4.mjs} +710 -204
  13. package/dist/_chunks/index-D-qx3tz4.mjs.map +1 -0
  14. package/dist/admin/index.js +1 -1
  15. package/dist/admin/index.mjs +2 -2
  16. package/dist/admin/src/components/BulkLocaleActionModal.d.ts +16 -0
  17. package/dist/admin/src/components/CMHeaderActions.d.ts +33 -3
  18. package/dist/admin/src/components/EditLocale.d.ts +5 -4
  19. package/dist/admin/src/contentReleasesHooks/releaseDetailsView.d.ts +9 -5
  20. package/dist/admin/src/services/api.d.ts +2 -3
  21. package/dist/admin/src/services/locales.d.ts +1 -1
  22. package/dist/admin/src/services/relations.d.ts +7 -0
  23. package/dist/admin/src/utils/baseQuery.d.ts +4 -19
  24. package/dist/admin/src/utils/clean.d.ts +4 -0
  25. package/dist/admin/src/utils/schemas.d.ts +1 -0
  26. package/dist/server/index.js +38 -9
  27. package/dist/server/index.js.map +1 -1
  28. package/dist/server/index.mjs +39 -10
  29. package/dist/server/index.mjs.map +1 -1
  30. package/dist/server/src/bootstrap.d.ts.map +1 -1
  31. package/dist/server/src/index.d.ts +14 -2
  32. package/dist/server/src/index.d.ts.map +1 -1
  33. package/dist/server/src/services/index.d.ts +14 -2
  34. package/dist/server/src/services/index.d.ts.map +1 -1
  35. package/dist/server/src/services/permissions/actions.d.ts +14 -2
  36. package/dist/server/src/services/permissions/actions.d.ts.map +1 -1
  37. package/dist/server/src/services/permissions.d.ts +14 -2
  38. package/dist/server/src/services/permissions.d.ts.map +1 -1
  39. package/dist/shared/contracts/content-manager.d.ts +20 -1
  40. package/package.json +15 -16
  41. package/dist/_chunks/SettingsPage-CeqfDjsb.mjs.map +0 -1
  42. package/dist/_chunks/SettingsPage-Djqsdrzs.js.map +0 -1
  43. package/dist/_chunks/en-BuBc6LKZ.js.map +0 -1
  44. package/dist/_chunks/en-CnrTsjWS.mjs.map +0 -1
  45. package/dist/_chunks/index-BDU1w_fd.mjs.map +0 -1
  46. package/dist/_chunks/index-DMXJeGjN.js.map +0 -1
  47. package/dist/admin/src/components/Initializer.d.ts +0 -5
@@ -1,17 +1,17 @@
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, Checkbox, Dialog, DialogBody, Flex, DialogFooter, Button as Button$1, Status, SingleSelect, SingleSelectOption, VisuallyHidden, useCollator, Popover, Box } from "@strapi/design-system";
6
- import { WarningCircle, Trash, 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, Download, ListPlus, Cross, Earth, EarthStriked, CaretDown } from "@strapi/icons";
7
7
  import { useIntl } from "react-intl";
8
- import styled from "styled-components";
9
- import { useAuth, getFetchClient, useQueryParams, useNotification } from "@strapi/admin/strapi-admin";
10
- import { unstable_useDocument, unstable_useDocumentActions } from "@strapi/content-manager/strapi-admin";
11
- import { useParams, useNavigate, matchPath } from "react-router-dom";
12
- import { createApi } from "@reduxjs/toolkit/query/react";
13
- import { isAxiosError } from "axios";
8
+ import { styled } from "styled-components";
9
+ import { skipToken } from "@reduxjs/toolkit/query";
10
+ import { useAuth, adminApi, useTable, Table, useQueryParams, useForm, useNotification, useAPIErrorHandler } from "@strapi/admin/strapi-admin";
11
+ import { unstable_useDocument, unstable_useDocumentActions, buildValidParams } from "@strapi/content-manager/strapi-admin";
12
+ import { useParams, Link, useNavigate, matchPath } from "react-router-dom";
14
13
  import * as qs from "qs";
14
+ import { stringify } from "qs";
15
15
  import omit from "lodash/omit";
16
16
  const __variableDynamicImportRuntimeHelper = (glob, path) => {
17
17
  const v = glob[path];
@@ -48,9 +48,7 @@ const CheckboxConfirmation = ({
48
48
  };
49
49
  const handleConfirm = () => {
50
50
  onChange({ target: { name, value: false, type: "checkbox" } });
51
- setIsOpen(false);
52
51
  };
53
- const handleToggle = () => setIsOpen((prev) => !prev);
54
52
  const label = intlLabel.id ? formatMessage(
55
53
  { id: intlLabel.id, defaultMessage: intlLabel.defaultMessage },
56
54
  { ...intlLabel.values }
@@ -59,43 +57,36 @@ const CheckboxConfirmation = ({
59
57
  { id: description.id, defaultMessage: description.defaultMessage },
60
58
  { ...description.values }
61
59
  ) : "";
62
- return /* @__PURE__ */ jsxs(Fragment, { children: [
63
- /* @__PURE__ */ jsx(
64
- Checkbox,
65
- {
66
- hint,
67
- id: name,
68
- name,
69
- onValueChange: handleChange,
70
- value,
71
- type: "checkbox",
72
- children: label
73
- }
74
- ),
75
- isOpen && /* @__PURE__ */ jsxs(Dialog, { onClose: handleToggle, title: "Confirmation", isOpen, children: [
76
- /* @__PURE__ */ jsx(DialogBody, { icon: /* @__PURE__ */ jsx(WarningCircle, {}), children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
77
- /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(TextAlignTypography, { id: "confirm-description", children: formatMessage({
60
+ return /* @__PURE__ */ jsxs(Dialog.Root, { open: isOpen, onOpenChange: setIsOpen, children: [
61
+ /* @__PURE__ */ jsxs(Field.Root, { hint, name, children: [
62
+ /* @__PURE__ */ jsx(Checkbox, { onCheckedChange: handleChange, checked: value, children: label }),
63
+ /* @__PURE__ */ jsx(Field.Hint, {})
64
+ ] }),
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({
78
72
  id: getTranslation("CheckboxConfirmation.Modal.content"),
79
73
  defaultMessage: "Disabling localization will engender the deletion of all your content but the one associated to your default locale (if existing)."
80
74
  }) }) }),
81
- /* @__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({
82
76
  id: getTranslation("CheckboxConfirmation.Modal.body"),
83
77
  defaultMessage: "Do you want to disable it?"
84
78
  }) }) })
85
79
  ] }) }),
86
- /* @__PURE__ */ jsx(
87
- DialogFooter,
88
- {
89
- startAction: /* @__PURE__ */ jsx(Button$1, { onClick: handleToggle, variant: "tertiary", children: formatMessage({
90
- id: "components.popUpWarning.button.cancel",
91
- defaultMessage: "No, cancel"
92
- }) }),
93
- endAction: /* @__PURE__ */ jsx(Button$1, { variant: "danger-light", onClick: handleConfirm, children: formatMessage({
94
- id: getTranslation("CheckboxConfirmation.Modal.button-confirm"),
95
- defaultMessage: "Yes, disable"
96
- }) })
97
- }
98
- )
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
+ ] })
99
90
  ] })
100
91
  ] });
101
92
  };
@@ -146,7 +137,7 @@ const useI18n = () => {
146
137
  model: params.slug
147
138
  },
148
139
  {
149
- skip: !params.slug || !params.collectionType
140
+ skip: true
150
141
  }
151
142
  );
152
143
  if (doesPluginOptionsHaveI18nLocalized(schema?.pluginOptions)) {
@@ -160,64 +151,8 @@ const useI18n = () => {
160
151
  ...actions
161
152
  };
162
153
  };
163
- const axiosBaseQuery = () => async (query, { signal }) => {
164
- try {
165
- const { get: get2, post, del, put } = getFetchClient();
166
- if (typeof query === "string") {
167
- const result = await get2(query, { signal });
168
- return { data: result.data };
169
- } else {
170
- const { url, method = "GET", data, config } = query;
171
- if (method === "POST") {
172
- const result2 = await post(url, data, { ...config, signal });
173
- return { data: result2.data };
174
- }
175
- if (method === "DELETE") {
176
- const result2 = await del(url, { ...config, signal });
177
- return { data: result2.data };
178
- }
179
- if (method === "PUT") {
180
- const result2 = await put(url, data, { ...config, signal });
181
- return { data: result2.data };
182
- }
183
- const result = await get2(url, { ...config, signal });
184
- return { data: result.data };
185
- }
186
- } catch (err) {
187
- if (isAxiosError(err)) {
188
- if (typeof err.response?.data === "object" && err.response?.data !== null && "error" in err.response?.data) {
189
- return { data: void 0, error: err.response?.data.error };
190
- } else {
191
- return {
192
- data: void 0,
193
- error: {
194
- name: "UnknownError",
195
- message: "There was an unknown error response from the API",
196
- details: err.response?.data,
197
- status: err.response?.status
198
- }
199
- };
200
- }
201
- }
202
- const error = err;
203
- return {
204
- data: void 0,
205
- error: {
206
- name: error.name,
207
- message: error.message,
208
- stack: error.stack
209
- }
210
- };
211
- }
212
- };
213
- const isBaseQueryError = (error) => {
214
- return error.name !== void 0;
215
- };
216
- const i18nApi = createApi({
217
- reducerPath: "i18nApi",
218
- baseQuery: axiosBaseQuery(),
219
- tagTypes: ["Locale"],
220
- endpoints: () => ({})
154
+ const i18nApi = adminApi.enhanceEndpoints({
155
+ addTagTypes: ["Locale"]
221
156
  });
222
157
  const localesApi = i18nApi.injectEndpoints({
223
158
  endpoints: (builder) => ({
@@ -266,6 +201,295 @@ const {
266
201
  useGetDefaultLocalesQuery,
267
202
  useUpdateLocaleMutation
268
203
  } = localesApi;
204
+ const relationsApi = i18nApi.injectEndpoints({
205
+ overrideExisting: true,
206
+ endpoints: (builder) => ({
207
+ getManyDraftRelationCount: builder.query({
208
+ query: ({ model, ...params }) => ({
209
+ url: `/content-manager/collection-types/${model}/actions/countManyEntriesDraftRelations`,
210
+ method: "GET",
211
+ config: {
212
+ params
213
+ }
214
+ }),
215
+ transformResponse: (response) => response.data
216
+ })
217
+ })
218
+ });
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
+ ]);
233
+ const cleanedDataWithoutPasswordAndRelation = recursiveRemoveFieldTypes(
234
+ cleanedData,
235
+ schema,
236
+ components,
237
+ ["relation", "password"]
238
+ );
239
+ return cleanedDataWithoutPasswordAndRelation;
240
+ };
241
+ const removeFields = (data, fields) => {
242
+ return Object.keys(data).reduce((acc, current) => {
243
+ if (fields.includes(current)) {
244
+ return acc;
245
+ }
246
+ acc[current] = data[current];
247
+ return acc;
248
+ }, {});
249
+ };
250
+ const recursiveRemoveFieldTypes = (data, schema, components, fields) => {
251
+ return Object.keys(data).reduce((acc, current) => {
252
+ const attribute = schema.attributes[current] ?? { type: void 0 };
253
+ if (fields.includes(attribute.type)) {
254
+ return acc;
255
+ }
256
+ if (attribute.type === "dynamiczone") {
257
+ acc[current] = data[current].map((componentValue, index2) => {
258
+ const { id: _, ...rest } = recursiveRemoveFieldTypes(
259
+ componentValue,
260
+ components[componentValue.__component],
261
+ components,
262
+ fields
263
+ );
264
+ return {
265
+ ...rest,
266
+ __temp_key__: index2 + 1
267
+ };
268
+ });
269
+ } else if (attribute.type === "component") {
270
+ const { repeatable, component } = attribute;
271
+ if (repeatable) {
272
+ acc[current] = (data[current] ?? []).map((compoData, index2) => {
273
+ const { id: _, ...rest } = recursiveRemoveFieldTypes(
274
+ compoData,
275
+ components[component],
276
+ components,
277
+ fields
278
+ );
279
+ return {
280
+ ...rest,
281
+ __temp_key__: index2 + 1
282
+ };
283
+ });
284
+ } else {
285
+ const { id: _, ...rest } = recursiveRemoveFieldTypes(
286
+ data[current] ?? {},
287
+ components[component],
288
+ components,
289
+ fields
290
+ );
291
+ acc[current] = rest;
292
+ }
293
+ } else {
294
+ acc[current] = data[current];
295
+ }
296
+ return acc;
297
+ }, {});
298
+ };
299
+ const isErrorMessageDescriptor = (object) => {
300
+ return typeof object === "object" && object !== null && "id" in object && "defaultMessage" in object;
301
+ };
302
+ const EntryValidationText = ({
303
+ status = "draft",
304
+ validationErrors,
305
+ action
306
+ }) => {
307
+ const { formatMessage } = useIntl();
308
+ const getErrorStr = (key, value) => {
309
+ if (typeof value === "string") {
310
+ return `${key}: ${value}`;
311
+ } else if (isErrorMessageDescriptor(value)) {
312
+ return `${key}: ${formatMessage(value)}`;
313
+ } else if (Array.isArray(value)) {
314
+ return value.map((v) => getErrorStr(key, v)).join(" ");
315
+ } else if (typeof value === "object" && !Array.isArray(value)) {
316
+ return Object.entries(value).map(([k, v]) => getErrorStr(k, v)).join(" ");
317
+ } else {
318
+ return "";
319
+ }
320
+ };
321
+ if (validationErrors) {
322
+ const validationErrorsMessages = Object.entries(validationErrors).map(([key, value]) => {
323
+ return getErrorStr(key, value);
324
+ }).join(" ");
325
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
326
+ /* @__PURE__ */ jsx(CrossCircle, { fill: "danger600" }),
327
+ /* @__PURE__ */ jsx(Tooltip, { label: validationErrorsMessages, children: /* @__PURE__ */ jsx(
328
+ Typography,
329
+ {
330
+ maxWidth: "30rem",
331
+ textColor: "danger600",
332
+ variant: "omega",
333
+ fontWeight: "semiBold",
334
+ ellipsis: true,
335
+ children: validationErrorsMessages
336
+ }
337
+ ) })
338
+ ] });
339
+ }
340
+ const getStatusMessage = () => {
341
+ if (action === "bulk-publish") {
342
+ if (status === "published") {
343
+ return {
344
+ icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
345
+ text: formatMessage({
346
+ id: "content-manager.bulk-publish.already-published",
347
+ defaultMessage: "Already Published"
348
+ }),
349
+ textColor: "success600",
350
+ fontWeight: "bold"
351
+ };
352
+ } else if (status === "modified") {
353
+ return {
354
+ icon: /* @__PURE__ */ jsx(ArrowsCounterClockwise, { fill: "alternative600" }),
355
+ text: formatMessage({
356
+ id: "app.utils.ready-to-publish-changes",
357
+ defaultMessage: "Ready to publish changes"
358
+ })
359
+ };
360
+ } else {
361
+ return {
362
+ icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
363
+ text: formatMessage({
364
+ id: "app.utils.ready-to-publish",
365
+ defaultMessage: "Ready to publish"
366
+ })
367
+ };
368
+ }
369
+ } else {
370
+ if (status === "draft") {
371
+ return {
372
+ icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
373
+ text: formatMessage({
374
+ id: "content-manager.bulk-unpublish.already-unpublished",
375
+ defaultMessage: "Already Unpublished"
376
+ }),
377
+ textColor: "success600",
378
+ fontWeight: "bold"
379
+ };
380
+ } else {
381
+ return {
382
+ icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
383
+ text: formatMessage({
384
+ id: "app.utils.ready-to-unpublish-changes",
385
+ defaultMessage: "Ready to unpublish"
386
+ }),
387
+ textColor: "success600",
388
+ fontWeight: "bold"
389
+ };
390
+ }
391
+ }
392
+ };
393
+ const { icon, text, textColor = "success600", fontWeight = "normal" } = getStatusMessage();
394
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
395
+ icon,
396
+ /* @__PURE__ */ jsx(Typography, { textColor, fontWeight, children: text })
397
+ ] });
398
+ };
399
+ const BoldChunk = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: chunks });
400
+ const BulkLocaleActionModal = ({
401
+ headers,
402
+ rows,
403
+ localesMetadata,
404
+ validationErrors = {},
405
+ action
406
+ }) => {
407
+ const { formatMessage } = useIntl();
408
+ const selectedRows = useTable(
409
+ "BulkLocaleActionModal",
410
+ (state) => state.selectedRows
411
+ );
412
+ const getFormattedCountMessage = () => {
413
+ const currentStatusByLocale = rows.reduce((acc, { locale, status }) => {
414
+ acc[locale] = status;
415
+ return acc;
416
+ }, {});
417
+ const localesWithErrors = Object.keys(validationErrors);
418
+ const publishedCount = selectedRows.filter(
419
+ ({ locale }) => currentStatusByLocale[locale] === "published"
420
+ ).length;
421
+ const draftCount = selectedRows.filter(
422
+ ({ locale }) => (currentStatusByLocale[locale] === "draft" || currentStatusByLocale[locale] === "modified") && !localesWithErrors.includes(locale)
423
+ ).length;
424
+ const withErrorsCount = localesWithErrors.length;
425
+ const messageId = action === "bulk-publish" ? "content-manager.containers.list.selectedEntriesModal.selectedCount.publish" : "content-manager.containers.list.selectedEntriesModal.selectedCount.unpublish";
426
+ 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.";
427
+ return formatMessage(
428
+ {
429
+ id: messageId,
430
+ defaultMessage
431
+ },
432
+ {
433
+ withErrorsCount,
434
+ draftCount,
435
+ publishedCount,
436
+ b: BoldChunk
437
+ }
438
+ );
439
+ };
440
+ return /* @__PURE__ */ jsxs(Modal.Body, { children: [
441
+ /* @__PURE__ */ jsx(Typography, { children: getFormattedCountMessage() }),
442
+ /* @__PURE__ */ jsx(Box, { marginTop: 5, children: /* @__PURE__ */ jsxs(Table.Content, { children: [
443
+ /* @__PURE__ */ jsxs(Table.Head, { children: [
444
+ /* @__PURE__ */ jsx(Table.HeaderCheckboxCell, {}),
445
+ headers.map((head) => /* @__PURE__ */ jsx(Table.HeaderCell, { ...head }, head.name))
446
+ ] }),
447
+ /* @__PURE__ */ jsx(Table.Body, { children: rows.map(({ locale, status }, index2) => {
448
+ const error = validationErrors?.[locale] ?? null;
449
+ const statusVariant = status === "draft" ? "primary" : status === "published" ? "success" : "alternative";
450
+ return /* @__PURE__ */ jsxs(Table.Row, { children: [
451
+ /* @__PURE__ */ jsx(Table.CheckboxCell, { id: locale, "aria-label": `Select ${locale}` }),
452
+ /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", children: Array.isArray(localesMetadata) ? localesMetadata.find((localeEntry) => localeEntry.code === locale)?.name : locale }) }),
453
+ /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Box, { display: "flex", children: /* @__PURE__ */ jsx(
454
+ Status,
455
+ {
456
+ display: "flex",
457
+ paddingLeft: "6px",
458
+ paddingRight: "6px",
459
+ paddingTop: "2px",
460
+ paddingBottom: "2px",
461
+ showBullet: false,
462
+ size: "S",
463
+ variant: statusVariant,
464
+ children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "pi", fontWeight: "bold", children: capitalize(status) })
465
+ }
466
+ ) }) }),
467
+ /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(EntryValidationText, { validationErrors: error, status, action }) }),
468
+ /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
469
+ IconButton,
470
+ {
471
+ tag: Link,
472
+ to: {
473
+ search: stringify({ plugins: { i18n: { locale } } })
474
+ },
475
+ label: formatMessage(
476
+ {
477
+ id: getTranslation("Settings.list.actions.edit"),
478
+ defaultMessage: "Edit {name} locale"
479
+ },
480
+ {
481
+ name: locale
482
+ }
483
+ ),
484
+ variant: "ghost",
485
+ children: /* @__PURE__ */ jsx(Pencil, {})
486
+ }
487
+ ) })
488
+ ] }, index2);
489
+ }) })
490
+ ] }) })
491
+ ] });
492
+ };
269
493
  const LocalePickerAction = ({
270
494
  document,
271
495
  meta,
@@ -277,7 +501,13 @@ const LocalePickerAction = ({
277
501
  const [{ query }, setQuery] = useQueryParams();
278
502
  const { hasI18n, canCreate, canRead } = useI18n();
279
503
  const { data: locales = [] } = useGetLocalesQuery();
280
- const { schema } = unstable_useDocument({ model, collectionType, documentId });
504
+ const currentDesiredLocale = query.plugins?.i18n?.locale;
505
+ const { schema } = unstable_useDocument({
506
+ model,
507
+ collectionType,
508
+ documentId,
509
+ params: { locale: currentDesiredLocale }
510
+ });
281
511
  const handleSelect = React.useCallback(
282
512
  (value) => {
283
513
  setQuery({
@@ -295,21 +525,20 @@ const LocalePickerAction = ({
295
525
  if (!Array.isArray(locales) || !hasI18n) {
296
526
  return;
297
527
  }
298
- const currentDesiredLocale = query.plugins?.i18n?.locale;
299
528
  const doesLocaleExist = locales.find((loc) => loc.code === currentDesiredLocale);
300
529
  const defaultLocale = locales.find((locale) => locale.isDefault);
301
530
  if (!doesLocaleExist && defaultLocale?.code) {
302
531
  handleSelect(defaultLocale.code);
303
532
  }
304
- }, [handleSelect, hasI18n, locales, query.plugins?.i18n?.locale]);
305
- if (!hasI18n || !Array.isArray(locales) || locales.length === 0) {
306
- return null;
307
- }
308
- const currentLocale = query.plugins?.i18n?.locale || locales.find((loc) => loc.isDefault)?.code;
533
+ }, [handleSelect, hasI18n, locales, currentDesiredLocale]);
534
+ const currentLocale = Array.isArray(locales) ? locales.find((locale) => locale.code === currentDesiredLocale)?.code : void 0;
309
535
  const allCurrentLocales = [
310
536
  { status: getDocumentStatus(document, meta), locale: currentLocale },
311
537
  ...meta?.availableLocales ?? []
312
538
  ];
539
+ if (!hasI18n || !Array.isArray(locales) || locales.length === 0) {
540
+ return null;
541
+ }
313
542
  return {
314
543
  label: formatMessage({
315
544
  id: getTranslation("Settings.locales.modal.locales.label"),
@@ -321,7 +550,7 @@ const LocalePickerAction = ({
321
550
  );
322
551
  const status = currentLocaleDoc?.status ?? "draft";
323
552
  const permissionsToCheck = currentLocaleDoc ? canCreate : canRead;
324
- const statusVariant = status === "draft" ? "primary" : status === "published" ? "success" : "alternative";
553
+ const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
325
554
  return {
326
555
  disabled: !permissionsToCheck.includes(locale.code),
327
556
  value: locale.code,
@@ -337,7 +566,7 @@ const LocalePickerAction = ({
337
566
  showBullet: false,
338
567
  size: "S",
339
568
  variant: statusVariant,
340
- children: /* @__PURE__ */ jsx(Typography, { as: "span", variant: "pi", fontWeight: "bold", children: capitalize(status) })
569
+ children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "pi", fontWeight: "bold", children: capitalize(status) })
341
570
  }
342
571
  ) : null
343
572
  };
@@ -357,6 +586,95 @@ const getDocumentStatus = (document, meta) => {
357
586
  }
358
587
  return docStatus;
359
588
  };
589
+ const FillFromAnotherLocaleAction = ({
590
+ documentId,
591
+ meta,
592
+ model,
593
+ collectionType
594
+ }) => {
595
+ const { formatMessage } = useIntl();
596
+ const [{ query }] = useQueryParams();
597
+ const currentDesiredLocale = query.plugins?.i18n?.locale;
598
+ const [localeSelected, setLocaleSelected] = React.useState(null);
599
+ const setValues = useForm("FillFromAnotherLocale", (state) => state.setValues);
600
+ const { getDocument } = unstable_useDocumentActions();
601
+ const { schema, components } = unstable_useDocument({
602
+ model,
603
+ documentId,
604
+ collectionType,
605
+ params: { locale: currentDesiredLocale }
606
+ });
607
+ const { data: locales = [] } = useGetLocalesQuery();
608
+ const availableLocales = Array.isArray(locales) ? locales.filter((locale) => meta?.availableLocales.some((l) => l.locale === locale.code)) : [];
609
+ const fillFromLocale = (onClose) => async () => {
610
+ const response = await getDocument({
611
+ collectionType,
612
+ model,
613
+ documentId,
614
+ params: { locale: localeSelected }
615
+ });
616
+ if (!response || !schema) {
617
+ return;
618
+ }
619
+ const { data } = response;
620
+ const cleanedData = cleanData(data, schema, components);
621
+ setValues(cleanedData);
622
+ onClose();
623
+ };
624
+ return {
625
+ type: "icon",
626
+ icon: /* @__PURE__ */ jsx(Download, {}),
627
+ disabled: availableLocales.length === 0,
628
+ label: formatMessage({
629
+ id: getTranslation("CMEditViewCopyLocale.copy-text"),
630
+ defaultMessage: "Fill in from another locale"
631
+ }),
632
+ dialog: {
633
+ type: "dialog",
634
+ title: formatMessage({
635
+ id: getTranslation("CMEditViewCopyLocale.dialog.title"),
636
+ defaultMessage: "Confirmation"
637
+ }),
638
+ content: ({ onClose }) => /* @__PURE__ */ jsxs(Fragment, { children: [
639
+ /* @__PURE__ */ jsx(Dialog.Body, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 3, children: [
640
+ /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
641
+ /* @__PURE__ */ jsx(Typography, { textAlign: "center", children: formatMessage({
642
+ id: getTranslation("CMEditViewCopyLocale.dialog.body"),
643
+ defaultMessage: "Your current content will be erased and filled by the content of the selected locale:"
644
+ }) }),
645
+ /* @__PURE__ */ jsxs(Field.Root, { width: "100%", children: [
646
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
647
+ id: getTranslation("CMEditViewCopyLocale.dialog.field.label"),
648
+ defaultMessage: "Locale"
649
+ }) }),
650
+ /* @__PURE__ */ jsx(
651
+ SingleSelect,
652
+ {
653
+ value: localeSelected,
654
+ placeholder: formatMessage({
655
+ id: getTranslation("CMEditViewCopyLocale.dialog.field.placeholder"),
656
+ defaultMessage: "Select one locale..."
657
+ }),
658
+ onChange: (value) => setLocaleSelected(value),
659
+ children: availableLocales.map((locale) => /* @__PURE__ */ jsx(SingleSelectOption, { value: locale.code, children: locale.name }, locale.code))
660
+ }
661
+ )
662
+ ] })
663
+ ] }) }),
664
+ /* @__PURE__ */ jsx(Dialog.Footer, { children: /* @__PURE__ */ jsxs(Flex, { gap: 2, width: "100%", children: [
665
+ /* @__PURE__ */ jsx(Button, { flex: "auto", variant: "tertiary", onClick: onClose, children: formatMessage({
666
+ id: getTranslation("CMEditViewCopyLocale.cancel-text"),
667
+ defaultMessage: "No, cancel"
668
+ }) }),
669
+ /* @__PURE__ */ jsx(Button, { flex: "auto", variant: "success", onClick: fillFromLocale(onClose), children: formatMessage({
670
+ id: getTranslation("CMEditViewCopyLocale.submit-text"),
671
+ defaultMessage: "Yes, fill in"
672
+ }) })
673
+ ] }) })
674
+ ] })
675
+ }
676
+ };
677
+ };
360
678
  const DeleteLocaleAction = ({
361
679
  document,
362
680
  documentId,
@@ -388,7 +706,7 @@ const DeleteLocaleAction = ({
388
706
  }),
389
707
  content: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
390
708
  /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
391
- /* @__PURE__ */ jsx(Typography, { as: "p", variant: "omega", textAlign: "center", children: formatMessage({
709
+ /* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
392
710
  id: getTranslation("actions.delete.dialog.body"),
393
711
  defaultMessage: "Are you sure?"
394
712
  }) })
@@ -420,6 +738,262 @@ const DeleteLocaleAction = ({
420
738
  }
421
739
  };
422
740
  };
741
+ const BulkLocaleAction = ({
742
+ document: baseDocument,
743
+ documentId,
744
+ model,
745
+ collectionType,
746
+ action
747
+ }) => {
748
+ const baseLocale = baseDocument?.locale ?? null;
749
+ const [{ query }] = useQueryParams();
750
+ const params = React.useMemo(() => buildValidParams(query), [query]);
751
+ const isOnPublishedTab = query.status === "published";
752
+ const { formatMessage } = useIntl();
753
+ const { hasI18n, canPublish } = useI18n();
754
+ const { toggleNotification } = useNotification();
755
+ const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
756
+ const [selectedRows, setSelectedRows] = React.useState([]);
757
+ const [isDraftRelationConfirmationOpen, setIsDraftRelationConfirmationOpen] = React.useState(false);
758
+ const { publishMany: publishManyAction, unpublishMany: unpublishManyAction } = unstable_useDocumentActions();
759
+ const {
760
+ document,
761
+ meta: documentMeta,
762
+ schema,
763
+ validate
764
+ } = unstable_useDocument(
765
+ {
766
+ model,
767
+ collectionType,
768
+ documentId,
769
+ params: {
770
+ locale: baseLocale
771
+ }
772
+ },
773
+ {
774
+ skip: !hasI18n || !baseLocale
775
+ }
776
+ );
777
+ const { data: localesMetadata = [] } = useGetLocalesQuery(hasI18n ? void 0 : skipToken);
778
+ const headers = [
779
+ {
780
+ label: formatMessage({
781
+ id: "global.name",
782
+ defaultMessage: "Name"
783
+ }),
784
+ name: "name"
785
+ },
786
+ {
787
+ label: formatMessage({
788
+ id: getTranslation("CMEditViewBulkLocale.status"),
789
+ defaultMessage: "Status"
790
+ }),
791
+ name: "status"
792
+ },
793
+ {
794
+ label: formatMessage({
795
+ id: getTranslation("CMEditViewBulkLocale.publication-status"),
796
+ defaultMessage: "Publication Status"
797
+ }),
798
+ name: "publication-status"
799
+ }
800
+ ];
801
+ const [rows, validationErrors] = React.useMemo(() => {
802
+ if (!document || !documentMeta?.availableLocales) {
803
+ return [[], {}];
804
+ }
805
+ const rowsFromMeta = documentMeta?.availableLocales.map((doc) => {
806
+ const { locale, status } = doc;
807
+ return { locale, status };
808
+ });
809
+ rowsFromMeta.unshift({
810
+ locale: document.locale,
811
+ status: document.status
812
+ });
813
+ const allDocuments = [document, ...documentMeta?.availableLocales ?? []];
814
+ const errors = allDocuments.reduce((errs, document2) => {
815
+ if (!document2) {
816
+ return errs;
817
+ }
818
+ const validation = validate(document2);
819
+ if (validation !== null) {
820
+ errs[document2.locale] = validation;
821
+ }
822
+ return errs;
823
+ }, {});
824
+ return [rowsFromMeta, errors];
825
+ }, [document, documentMeta?.availableLocales, validate]);
826
+ const isBulkPublish = action === "bulk-publish";
827
+ const localesForAction = selectedRows.reduce((acc, selectedRow) => {
828
+ const isValidLocale = (
829
+ // Validation errors are irrelevant if we are trying to unpublish
830
+ !isBulkPublish || !Object.keys(validationErrors).includes(selectedRow.locale)
831
+ );
832
+ const shouldAddLocale = isBulkPublish ? selectedRow.status !== "published" && isValidLocale : selectedRow.status !== "draft" && isValidLocale;
833
+ if (shouldAddLocale) {
834
+ acc.push(selectedRow.locale);
835
+ }
836
+ return acc;
837
+ }, []);
838
+ const enableDraftRelationsCount = false;
839
+ const {
840
+ data: draftRelationsCount = 0,
841
+ isLoading: isDraftRelationsLoading,
842
+ error: isDraftRelationsError
843
+ } = useGetManyDraftRelationCountQuery(
844
+ {
845
+ model,
846
+ documentIds: [documentId],
847
+ locale: localesForAction
848
+ },
849
+ {
850
+ skip: !enableDraftRelationsCount
851
+ }
852
+ );
853
+ React.useEffect(() => {
854
+ if (isDraftRelationsError) {
855
+ toggleNotification({
856
+ type: "danger",
857
+ message: formatAPIError(isDraftRelationsError)
858
+ });
859
+ }
860
+ }, [isDraftRelationsError, toggleNotification, formatAPIError]);
861
+ if (!schema?.options?.draftAndPublish) {
862
+ return null;
863
+ }
864
+ if (!hasI18n) {
865
+ return null;
866
+ }
867
+ if (!documentId) {
868
+ return null;
869
+ }
870
+ const publish = async () => {
871
+ await publishManyAction({
872
+ model,
873
+ documentIds: [documentId],
874
+ params: {
875
+ ...params,
876
+ locale: localesForAction
877
+ }
878
+ });
879
+ setSelectedRows([]);
880
+ };
881
+ const unpublish = async () => {
882
+ await unpublishManyAction({
883
+ model,
884
+ documentIds: [documentId],
885
+ params: {
886
+ ...params,
887
+ locale: localesForAction
888
+ }
889
+ });
890
+ setSelectedRows([]);
891
+ };
892
+ const handleAction = async () => {
893
+ if (draftRelationsCount > 0) {
894
+ setIsDraftRelationConfirmationOpen(true);
895
+ } else if (isBulkPublish) {
896
+ await publish();
897
+ } else {
898
+ await unpublish();
899
+ }
900
+ };
901
+ if (isDraftRelationConfirmationOpen) {
902
+ return {
903
+ label: formatMessage({
904
+ id: "app.components.ConfirmDialog.title",
905
+ defaultMessage: "Confirmation"
906
+ }),
907
+ variant: "danger",
908
+ dialog: {
909
+ onCancel: () => {
910
+ setIsDraftRelationConfirmationOpen(false);
911
+ },
912
+ onConfirm: async () => {
913
+ await publish();
914
+ setIsDraftRelationConfirmationOpen(false);
915
+ },
916
+ type: "dialog",
917
+ title: formatMessage({
918
+ id: getTranslation("actions.publish.dialog.title"),
919
+ defaultMessage: "Confirmation"
920
+ }),
921
+ content: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "center", gap: 2, children: [
922
+ /* @__PURE__ */ jsx(WarningCircle, { width: "2.4rem", height: "2.4rem", fill: "danger600" }),
923
+ /* @__PURE__ */ jsx(Typography, { textAlign: "center", children: formatMessage({
924
+ id: getTranslation("CMEditViewBulkLocale.draft-relation-warning"),
925
+ defaultMessage: "Some locales are related to draft entries. Publishing them could leave broken links in your app."
926
+ }) }),
927
+ /* @__PURE__ */ jsx(Typography, { textAlign: "center", children: formatMessage({
928
+ id: getTranslation("CMEditViewBulkLocale.continue-confirmation"),
929
+ defaultMessage: "Are you sure you want to continue?"
930
+ }) })
931
+ ] })
932
+ }
933
+ };
934
+ }
935
+ const hasPermission = selectedRows.map(({ locale }) => locale).every((locale) => canPublish.includes(locale));
936
+ return {
937
+ label: formatMessage({
938
+ id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
939
+ defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
940
+ }),
941
+ variant: isBulkPublish ? "secondary" : "danger",
942
+ icon: isBulkPublish ? /* @__PURE__ */ jsx(ListPlus, {}) : /* @__PURE__ */ jsx(Cross, {}),
943
+ disabled: isOnPublishedTab || canPublish.length === 0,
944
+ position: ["panel"],
945
+ dialog: {
946
+ type: "modal",
947
+ title: formatMessage({
948
+ id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
949
+ defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
950
+ }),
951
+ content: () => {
952
+ return /* @__PURE__ */ jsx(
953
+ Table.Root,
954
+ {
955
+ headers,
956
+ rows: rows.map((row) => ({
957
+ ...row,
958
+ id: row.locale
959
+ })),
960
+ selectedRows,
961
+ onSelectedRowsChange: (tableSelectedRows) => setSelectedRows(tableSelectedRows),
962
+ children: /* @__PURE__ */ jsx(
963
+ BulkLocaleActionModal,
964
+ {
965
+ validationErrors,
966
+ headers,
967
+ rows,
968
+ localesMetadata,
969
+ action: action ?? "bulk-publish"
970
+ }
971
+ )
972
+ }
973
+ );
974
+ },
975
+ footer: () => /* @__PURE__ */ jsx(Modal.Footer, { justifyContent: "flex-end", children: /* @__PURE__ */ jsx(
976
+ Button,
977
+ {
978
+ loading: isDraftRelationsLoading,
979
+ disabled: !hasPermission || localesForAction.length === 0,
980
+ variant: "default",
981
+ onClick: handleAction,
982
+ children: formatMessage({
983
+ id: isBulkPublish ? "app.utils.publish" : "app.utils.unpublish",
984
+ defaultMessage: isBulkPublish ? "Publish" : "Unpublish"
985
+ })
986
+ }
987
+ ) })
988
+ }
989
+ };
990
+ };
991
+ const BulkLocalePublishAction = (props) => {
992
+ return BulkLocaleAction({ action: "bulk-publish", ...props });
993
+ };
994
+ const BulkLocaleUnpublishAction = (props) => {
995
+ return BulkLocaleAction({ action: "bulk-unpublish", ...props });
996
+ };
423
997
  const StyledTrash = styled(Trash)`
424
998
  path {
425
999
  fill: currentColor;
@@ -476,13 +1050,6 @@ const UnpublishModalAdditionalInfo = () => {
476
1050
  }
477
1051
  ) });
478
1052
  };
479
- const Initializer = ({ setPlugin }) => {
480
- const setPluginRef = React.useRef(setPlugin);
481
- React.useEffect(() => {
482
- setPluginRef.current(pluginId);
483
- }, []);
484
- return null;
485
- };
486
1053
  const LocalePicker = () => {
487
1054
  const { formatMessage } = useIntl();
488
1055
  const [{ query }, setQuery] = useQueryParams();
@@ -542,7 +1109,7 @@ const PERMISSIONS = {
542
1109
  read: [{ action: "plugin::i18n.locale.read", subject: null }]
543
1110
  };
544
1111
  const mutateEditViewHook = ({ layout }) => {
545
- if ("i18n" in layout.options && typeof layout.options.i18n === "object" && layout.options.i18n !== null && "localized" in layout.options.i18n && !layout.options.i18n.localized) {
1112
+ if (!("i18n" in layout.options) || typeof layout.options.i18n === "object" && layout.options.i18n !== null && "localized" in layout.options.i18n && !layout.options.i18n.localized) {
546
1113
  return { layout };
547
1114
  }
548
1115
  const components = Object.entries(layout.components).reduce(
@@ -587,8 +1154,8 @@ const doesFieldHaveI18nPluginOpt = (pluginOpts) => {
587
1154
  };
588
1155
  const LabelAction = ({ title, icon }) => {
589
1156
  const { formatMessage } = useIntl();
590
- return /* @__PURE__ */ jsxs(Span, { as: "span", children: [
591
- /* @__PURE__ */ jsx(VisuallyHidden, { as: "span", children: `(${formatMessage(title)})` }),
1157
+ return /* @__PURE__ */ jsxs(Span, { tag: "span", children: [
1158
+ /* @__PURE__ */ jsx(VisuallyHidden, { tag: "span", children: formatMessage(title) }),
592
1159
  React.cloneElement(icon, {
593
1160
  "aria-hidden": true,
594
1161
  focusable: false
@@ -623,13 +1190,7 @@ const LocaleListCell = ({
623
1190
  }
624
1191
  });
625
1192
  const { locale: language } = useIntl();
626
- const [visible, setVisible] = React.useState(false);
627
- const buttonRef = React.useRef(null);
628
1193
  const { data: locales = [] } = useGetLocalesQuery();
629
- const handleTogglePopover = (e) => {
630
- e.stopPropagation();
631
- setVisible((prev) => !prev);
632
- };
633
1194
  const formatter = useCollator(language, {
634
1195
  sensitivity: "base"
635
1196
  });
@@ -651,64 +1212,14 @@ const LocaleListCell = ({
651
1212
  }
652
1213
  return locale.name;
653
1214
  }).toSorted((a, b) => formatter.compare(a, b));
654
- return /* @__PURE__ */ jsxs(Button, { type: "button", onClick: handleTogglePopover, ref: buttonRef, children: [
655
- /* @__PURE__ */ jsxs(
656
- ActionWrapper,
657
- {
658
- minWidth: "100%",
659
- alignItems: "center",
660
- justifyContent: "center",
661
- height: "3.2rem",
662
- width: "3.2rem",
663
- children: [
664
- /* @__PURE__ */ jsx(Typography, { textColor: "neutral800", ellipsis: true, children: localesForDocument.join(", ") }),
665
- /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(CaretDown, {}) })
666
- ]
667
- }
668
- ),
669
- visible && /* @__PURE__ */ jsx(
670
- Popover,
671
- {
672
- onDismiss: () => setVisible(false),
673
- source: buttonRef,
674
- spacing: 16,
675
- centered: true,
676
- children: /* @__PURE__ */ jsx("ul", { children: localesForDocument.map((name) => /* @__PURE__ */ jsx(Box, { padding: 3, as: "li", children: /* @__PURE__ */ jsx(Typography, { children: name }) }, name)) })
677
- }
678
- )
1215
+ return /* @__PURE__ */ jsxs(Popover.Root, { children: [
1216
+ /* @__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: [
1217
+ /* @__PURE__ */ jsx(Typography, { textColor: "neutral800", ellipsis: true, marginRight: 2, children: localesForDocument.join(", ") }),
1218
+ /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(CaretDown, { width: "1.2rem", height: "1.2rem" }) })
1219
+ ] }) }) }),
1220
+ /* @__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)) }) })
679
1221
  ] });
680
1222
  };
681
- const Button = styled.button`
682
- width: 100%;
683
-
684
- svg {
685
- > g,
686
- path {
687
- fill: ${({ theme }) => theme.colors.neutral500};
688
- }
689
- }
690
- &:hover {
691
- svg {
692
- > g,
693
- path {
694
- fill: ${({ theme }) => theme.colors.neutral600};
695
- }
696
- }
697
- }
698
- &:active {
699
- svg {
700
- > g,
701
- path {
702
- fill: ${({ theme }) => theme.colors.neutral400};
703
- }
704
- }
705
- }
706
- `;
707
- const ActionWrapper = styled(Flex)`
708
- svg {
709
- height: 0.4rem;
710
- }
711
- `;
712
1223
  const addColumnToTableHook = ({ displayedHeaders, layout }) => {
713
1224
  const { options } = layout;
714
1225
  const isFieldLocalized = doesPluginOptionsHaveI18nLocalized(options) ? options.i18n.localized : false;
@@ -737,18 +1248,11 @@ const addColumnToTableHook = ({ displayedHeaders, layout }) => {
737
1248
  const addLocaleToReleasesHook = ({ displayedHeaders = [] }) => {
738
1249
  return {
739
1250
  displayedHeaders: [
740
- // TODO: Fix when migrating to v5
741
- // ...displayedHeaders,
1251
+ ...displayedHeaders,
742
1252
  {
743
- key: "__locale__",
744
- fieldSchema: { type: "string" },
745
- metadatas: {
746
- label: {
747
- id: "content-releases.page.ReleaseDetails.table.header.label.locale",
748
- defaultMessage: "locale"
749
- },
750
- searchable: false,
751
- sortable: false
1253
+ label: {
1254
+ id: "content-releases.page.ReleaseDetails.table.header.label.locale",
1255
+ defaultMessage: "locale"
752
1256
  },
753
1257
  name: "locale"
754
1258
  }
@@ -896,8 +1400,6 @@ const index = {
896
1400
  app.addRBACMiddleware([localeMiddleware]);
897
1401
  app.registerPlugin({
898
1402
  id: pluginId,
899
- initializer: Initializer,
900
- isReady: false,
901
1403
  name: pluginId
902
1404
  });
903
1405
  },
@@ -915,16 +1417,21 @@ const index = {
915
1417
  },
916
1418
  id: "internationalization",
917
1419
  to: "internationalization",
918
- Component: () => import("./SettingsPage-CeqfDjsb.mjs").then((mod) => ({ default: mod.ProtectedSettingsPage })),
1420
+ Component: () => import("./SettingsPage-BjxjwEOb.mjs").then((mod) => ({ default: mod.ProtectedSettingsPage })),
919
1421
  permissions: PERMISSIONS.accessMain
920
1422
  });
921
1423
  const contentManager = app.getPlugin("content-manager");
922
- contentManager.apis.addDocumentHeaderAction([LocalePickerAction]);
1424
+ contentManager.apis.addDocumentHeaderAction([LocalePickerAction, FillFromAnotherLocaleAction]);
923
1425
  contentManager.apis.addDocumentAction((actions) => {
924
1426
  const indexOfDeleteAction = actions.findIndex((action) => action.type === "delete");
925
1427
  actions.splice(indexOfDeleteAction, 0, DeleteLocaleAction);
926
1428
  return actions;
927
1429
  });
1430
+ contentManager.apis.addDocumentAction((actions) => {
1431
+ actions.splice(2, 0, BulkLocalePublishAction);
1432
+ actions.splice(5, 0, BulkLocaleUnpublishAction);
1433
+ return actions;
1434
+ });
928
1435
  contentManager.injectComponent("listView", "actions", {
929
1436
  name: "i18n-locale-filter",
930
1437
  Component: LocalePicker
@@ -1028,7 +1535,7 @@ const index = {
1028
1535
  async registerTrads({ locales }) {
1029
1536
  const importedTrads = await Promise.all(
1030
1537
  locales.map((locale) => {
1031
- 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-CnrTsjWS.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 }) => {
1538
+ 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-2xztdZE1.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 }) => {
1032
1539
  return {
1033
1540
  data: prefixPluginTranslations(data, pluginId),
1034
1541
  locale
@@ -1047,12 +1554,11 @@ const index = {
1047
1554
  export {
1048
1555
  PERMISSIONS as P,
1049
1556
  useGetDefaultLocalesQuery as a,
1050
- useGetLocalesQuery as b,
1051
- useDeleteLocaleMutation as c,
1052
- useUpdateLocaleMutation as d,
1053
- index as e,
1557
+ useDeleteLocaleMutation as b,
1558
+ useUpdateLocaleMutation as c,
1559
+ useGetLocalesQuery as d,
1054
1560
  getTranslation as g,
1055
- isBaseQueryError as i,
1561
+ index as i,
1056
1562
  useCreateLocaleMutation as u
1057
1563
  };
1058
- //# sourceMappingURL=index-BDU1w_fd.mjs.map
1564
+ //# sourceMappingURL=index-D-qx3tz4.mjs.map