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

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 (159) hide show
  1. package/LICENSE +18 -3
  2. package/dist/admin/chunks/SettingsPage-BOEeBbiM.mjs +797 -0
  3. package/dist/admin/chunks/SettingsPage-BOEeBbiM.mjs.map +1 -0
  4. package/dist/admin/chunks/SettingsPage-Mg2Ygywx.js +820 -0
  5. package/dist/admin/chunks/SettingsPage-Mg2Ygywx.js.map +1 -0
  6. package/dist/admin/chunks/de-Cm8mYdaO.mjs +64 -0
  7. package/dist/admin/chunks/de-Cm8mYdaO.mjs.map +1 -0
  8. package/dist/admin/chunks/de-nEMWvIiY.js +66 -0
  9. package/dist/admin/chunks/de-nEMWvIiY.js.map +1 -0
  10. package/dist/admin/chunks/dk-BeUFOegB.mjs +64 -0
  11. package/dist/admin/chunks/dk-BeUFOegB.mjs.map +1 -0
  12. package/dist/admin/chunks/dk-CYATLPVe.js +66 -0
  13. package/dist/admin/chunks/dk-CYATLPVe.js.map +1 -0
  14. package/dist/admin/chunks/en-CG5cUCbD.js +81 -0
  15. package/dist/admin/chunks/en-CG5cUCbD.js.map +1 -0
  16. package/dist/admin/chunks/en-eWSaCeOb.mjs +79 -0
  17. package/dist/admin/chunks/en-eWSaCeOb.mjs.map +1 -0
  18. package/dist/admin/chunks/es-CWsogTGm.js +66 -0
  19. package/dist/admin/chunks/es-CWsogTGm.js.map +1 -0
  20. package/dist/admin/chunks/es-DqF_IdAc.mjs +64 -0
  21. package/dist/admin/chunks/es-DqF_IdAc.mjs.map +1 -0
  22. package/dist/admin/chunks/fr-CC7UFcYd.js +66 -0
  23. package/dist/admin/chunks/fr-CC7UFcYd.js.map +1 -0
  24. package/dist/admin/chunks/fr-CyARbZ3c.mjs +64 -0
  25. package/dist/admin/chunks/fr-CyARbZ3c.mjs.map +1 -0
  26. package/dist/admin/chunks/index--VTS8j_L.mjs +2008 -0
  27. package/dist/admin/chunks/index--VTS8j_L.mjs.map +1 -0
  28. package/dist/admin/chunks/index-hJ67XV0K.js +2037 -0
  29. package/dist/admin/chunks/index-hJ67XV0K.js.map +1 -0
  30. package/dist/admin/chunks/ko-Ax4NSedM.mjs +63 -0
  31. package/dist/admin/chunks/ko-Ax4NSedM.mjs.map +1 -0
  32. package/dist/admin/chunks/ko-XwGmfhoq.js +65 -0
  33. package/dist/admin/chunks/ko-XwGmfhoq.js.map +1 -0
  34. package/dist/admin/chunks/pl-B-aqvMqL.mjs +64 -0
  35. package/dist/admin/chunks/pl-B-aqvMqL.mjs.map +1 -0
  36. package/dist/admin/chunks/pl-B_vzY_ZB.js +66 -0
  37. package/dist/admin/chunks/pl-B_vzY_ZB.js.map +1 -0
  38. package/dist/admin/chunks/ru-VkPjQ-Sk.mjs +66 -0
  39. package/dist/admin/chunks/ru-VkPjQ-Sk.mjs.map +1 -0
  40. package/dist/admin/chunks/ru-WzHcJV1f.js +68 -0
  41. package/dist/admin/chunks/ru-WzHcJV1f.js.map +1 -0
  42. package/dist/admin/chunks/tr-CcWp6u3w.js +66 -0
  43. package/dist/admin/chunks/tr-CcWp6u3w.js.map +1 -0
  44. package/dist/admin/chunks/tr-DcTR88c9.mjs +64 -0
  45. package/dist/admin/chunks/tr-DcTR88c9.mjs.map +1 -0
  46. package/dist/admin/chunks/uk-CMz6iPag.mjs +80 -0
  47. package/dist/admin/chunks/uk-CMz6iPag.mjs.map +1 -0
  48. package/dist/admin/chunks/uk-CO6JHYRC.js +82 -0
  49. package/dist/admin/chunks/uk-CO6JHYRC.js.map +1 -0
  50. package/dist/admin/chunks/zh-C9So4SGq.js +66 -0
  51. package/dist/admin/chunks/zh-C9So4SGq.js.map +1 -0
  52. package/dist/admin/chunks/zh-Hans-DnU2bhri.js +57 -0
  53. package/dist/admin/chunks/zh-Hans-DnU2bhri.js.map +1 -0
  54. package/dist/admin/chunks/zh-Hans-L3wsRegj.mjs +55 -0
  55. package/dist/admin/chunks/zh-Hans-L3wsRegj.mjs.map +1 -0
  56. package/dist/admin/chunks/zh-RZyMiPIs.mjs +64 -0
  57. package/dist/admin/chunks/zh-RZyMiPIs.mjs.map +1 -0
  58. package/dist/admin/index.js +20 -4
  59. package/dist/admin/index.js.map +1 -1
  60. package/dist/admin/index.mjs +15 -6
  61. package/dist/admin/index.mjs.map +1 -1
  62. package/dist/admin/src/components/BulkLocaleActionModal.d.ts +2 -1
  63. package/dist/admin/src/components/CMHeaderActions.d.ts +30 -4
  64. package/dist/admin/src/components/CreateLocale.d.ts +6 -6
  65. package/dist/admin/src/components/LocaleListCell.d.ts +4 -4
  66. package/dist/admin/src/components/tests/CreateLocale.test.d.ts +1 -0
  67. package/dist/admin/src/components/tests/DeleteLocale.test.d.ts +1 -0
  68. package/dist/admin/src/components/tests/EditLocale.test.d.ts +1 -0
  69. package/dist/admin/src/components/tests/LocaleListCell.test.d.ts +1 -0
  70. package/dist/admin/src/contentReleasesHooks/releaseDetailsView.d.ts +10 -6
  71. package/dist/admin/src/pages/tests/SettingsPage.test.d.ts +1 -0
  72. package/dist/admin/src/utils/clean.d.ts +4 -0
  73. package/dist/admin/src/utils/schemas.d.ts +1 -0
  74. package/dist/admin/tests/server.d.ts +1 -0
  75. package/dist/admin/tests/utils.d.ts +6 -0
  76. package/dist/server/index.js +3658 -3458
  77. package/dist/server/index.js.map +1 -1
  78. package/dist/server/index.mjs +3640 -3441
  79. package/dist/server/index.mjs.map +1 -1
  80. package/dist/server/src/bootstrap.d.ts +1 -4
  81. package/dist/server/src/bootstrap.d.ts.map +1 -1
  82. package/dist/server/src/index.d.ts +21 -13
  83. package/dist/server/src/index.d.ts.map +1 -1
  84. package/dist/server/src/register.d.ts.map +1 -1
  85. package/dist/server/src/services/index.d.ts +20 -10
  86. package/dist/server/src/services/index.d.ts.map +1 -1
  87. package/dist/server/src/services/localizations.d.ts +1 -1
  88. package/dist/server/src/services/localizations.d.ts.map +1 -1
  89. package/dist/server/src/services/permissions/actions.d.ts +14 -2
  90. package/dist/server/src/services/permissions/actions.d.ts.map +1 -1
  91. package/dist/server/src/services/permissions.d.ts +14 -2
  92. package/dist/server/src/services/permissions.d.ts.map +1 -1
  93. package/dist/server/src/services/sanitize/index.d.ts +11 -0
  94. package/dist/server/src/services/sanitize/index.d.ts.map +1 -0
  95. package/dist/server/src/utils/index.d.ts +2 -2
  96. package/dist/server/src/utils/index.d.ts.map +1 -1
  97. package/dist/shared/contracts/content-manager.d.ts +1 -1
  98. package/dist/shared/contracts/shared.d.ts +1 -1
  99. package/package.json +18 -16
  100. package/dist/_chunks/SettingsPage-Dsi2qGtq.mjs +0 -549
  101. package/dist/_chunks/SettingsPage-Dsi2qGtq.mjs.map +0 -1
  102. package/dist/_chunks/SettingsPage-VN7sTzkb.js +0 -569
  103. package/dist/_chunks/SettingsPage-VN7sTzkb.js.map +0 -1
  104. package/dist/_chunks/de-9eCAqqrB.mjs +0 -66
  105. package/dist/_chunks/de-9eCAqqrB.mjs.map +0 -1
  106. package/dist/_chunks/de-DtWiGdHl.js +0 -66
  107. package/dist/_chunks/de-DtWiGdHl.js.map +0 -1
  108. package/dist/_chunks/dk-2qBjxt-P.mjs +0 -66
  109. package/dist/_chunks/dk-2qBjxt-P.mjs.map +0 -1
  110. package/dist/_chunks/dk-D8C-casx.js +0 -66
  111. package/dist/_chunks/dk-D8C-casx.js.map +0 -1
  112. package/dist/_chunks/en-18tWw4P6.mjs +0 -72
  113. package/dist/_chunks/en-18tWw4P6.mjs.map +0 -1
  114. package/dist/_chunks/en-Kv6y9zPQ.js +0 -72
  115. package/dist/_chunks/en-Kv6y9zPQ.js.map +0 -1
  116. package/dist/_chunks/es-DS-XFGSw.js +0 -66
  117. package/dist/_chunks/es-DS-XFGSw.js.map +0 -1
  118. package/dist/_chunks/es-DlmMVaBG.mjs +0 -66
  119. package/dist/_chunks/es-DlmMVaBG.mjs.map +0 -1
  120. package/dist/_chunks/fr-3S6ke71d.mjs +0 -66
  121. package/dist/_chunks/fr-3S6ke71d.mjs.map +0 -1
  122. package/dist/_chunks/fr-BTjekDpq.js +0 -66
  123. package/dist/_chunks/fr-BTjekDpq.js.map +0 -1
  124. package/dist/_chunks/index-DhtjJYrx.mjs +0 -1372
  125. package/dist/_chunks/index-DhtjJYrx.mjs.map +0 -1
  126. package/dist/_chunks/index-kedPlCo6.js +0 -1394
  127. package/dist/_chunks/index-kedPlCo6.js.map +0 -1
  128. package/dist/_chunks/ko-DmcGUBQ3.js +0 -65
  129. package/dist/_chunks/ko-DmcGUBQ3.js.map +0 -1
  130. package/dist/_chunks/ko-qTjQ8IMw.mjs +0 -65
  131. package/dist/_chunks/ko-qTjQ8IMw.mjs.map +0 -1
  132. package/dist/_chunks/pl-B67TSHqT.mjs +0 -66
  133. package/dist/_chunks/pl-B67TSHqT.mjs.map +0 -1
  134. package/dist/_chunks/pl-Cn5RYonZ.js +0 -66
  135. package/dist/_chunks/pl-Cn5RYonZ.js.map +0 -1
  136. package/dist/_chunks/ru-BMBgVL3s.js +0 -68
  137. package/dist/_chunks/ru-BMBgVL3s.js.map +0 -1
  138. package/dist/_chunks/ru-hagMa57T.mjs +0 -68
  139. package/dist/_chunks/ru-hagMa57T.mjs.map +0 -1
  140. package/dist/_chunks/tr-CarUU76c.js +0 -66
  141. package/dist/_chunks/tr-CarUU76c.js.map +0 -1
  142. package/dist/_chunks/tr-Dw_jmkG-.mjs +0 -66
  143. package/dist/_chunks/tr-Dw_jmkG-.mjs.map +0 -1
  144. package/dist/_chunks/zh-57YM4amO.mjs +0 -66
  145. package/dist/_chunks/zh-57YM4amO.mjs.map +0 -1
  146. package/dist/_chunks/zh-CukOviB0.js +0 -66
  147. package/dist/_chunks/zh-CukOviB0.js.map +0 -1
  148. package/dist/_chunks/zh-Hans-DSHIXAa3.js +0 -57
  149. package/dist/_chunks/zh-Hans-DSHIXAa3.js.map +0 -1
  150. package/dist/_chunks/zh-Hans-Dyc-aR-h.mjs +0 -57
  151. package/dist/_chunks/zh-Hans-Dyc-aR-h.mjs.map +0 -1
  152. package/dist/admin/src/components/Initializer.d.ts +0 -5
  153. package/dist/server/src/migrations/content-type/disable/index.d.ts +0 -3
  154. package/dist/server/src/migrations/content-type/disable/index.d.ts.map +0 -1
  155. package/dist/server/src/migrations/content-type/enable/index.d.ts +0 -3
  156. package/dist/server/src/migrations/content-type/enable/index.d.ts.map +0 -1
  157. package/dist/server/src/services/entity-service-decorator.d.ts +0 -29
  158. package/dist/server/src/services/entity-service-decorator.d.ts.map +0 -1
  159. package/strapi-server.js +0 -3
@@ -1,1372 +0,0 @@
1
- import get from "lodash/get";
2
- import * as yup from "yup";
3
- import { jsxs, jsx } from "react/jsx-runtime";
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";
7
- import { useIntl } from "react-intl";
8
- import { styled } from "styled-components";
9
- import { useAuth, adminApi, useTable, Table, useQueryParams, useNotification, useAPIErrorHandler } from "@strapi/admin/strapi-admin";
10
- import { unstable_useDocument, unstable_useDocumentActions, buildValidParams } from "@strapi/content-manager/strapi-admin";
11
- import { useParams, Link, useNavigate, matchPath } from "react-router-dom";
12
- import * as qs from "qs";
13
- import { stringify } from "qs";
14
- import omit from "lodash/omit";
15
- const __variableDynamicImportRuntimeHelper = (glob, path) => {
16
- const v = glob[path];
17
- if (v) {
18
- return typeof v === "function" ? v() : Promise.resolve(v);
19
- }
20
- return new Promise((_, reject) => {
21
- (typeof queueMicrotask === "function" ? queueMicrotask : setTimeout)(reject.bind(null, new Error("Unknown variable dynamic import: " + path)));
22
- });
23
- };
24
- const pluginId = "i18n";
25
- const getTranslation = (id) => `${pluginId}.${id}`;
26
- const TextAlignTypography = styled(Typography)`
27
- text-align: center;
28
- `;
29
- const CheckboxConfirmation = ({
30
- description,
31
- isCreating = false,
32
- intlLabel,
33
- name,
34
- onChange,
35
- value
36
- }) => {
37
- const { formatMessage } = useIntl();
38
- const [isOpen, setIsOpen] = React.useState(false);
39
- const handleChange = (value2) => {
40
- if (isCreating || value2) {
41
- return onChange({ target: { name, value: value2, type: "checkbox" } });
42
- }
43
- if (!value2) {
44
- return setIsOpen(true);
45
- }
46
- return null;
47
- };
48
- const handleConfirm = () => {
49
- onChange({ target: { name, value: false, type: "checkbox" } });
50
- };
51
- const label = intlLabel.id ? formatMessage(
52
- { id: intlLabel.id, defaultMessage: intlLabel.defaultMessage },
53
- { ...intlLabel.values }
54
- ) : name;
55
- const hint = description ? formatMessage(
56
- { id: description.id, defaultMessage: description.defaultMessage },
57
- { ...description.values }
58
- ) : "";
59
- return /* @__PURE__ */ jsxs(Dialog.Root, { open: isOpen, onOpenChange: setIsOpen, children: [
60
- /* @__PURE__ */ jsxs(Field.Root, { hint, name, children: [
61
- /* @__PURE__ */ jsx(Checkbox, { onCheckedChange: handleChange, checked: value, children: label }),
62
- /* @__PURE__ */ jsx(Field.Hint, {})
63
- ] }),
64
- /* @__PURE__ */ jsxs(Dialog.Content, { children: [
65
- /* @__PURE__ */ jsx(Dialog.Header, { children: formatMessage({
66
- id: getTranslation("CheckboxConfirmation.Modal.title"),
67
- defaultMessage: "Disable localization"
68
- }) }),
69
- /* @__PURE__ */ jsx(Dialog.Body, { icon: /* @__PURE__ */ jsx(WarningCircle, {}), children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
70
- /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(TextAlignTypography, { children: formatMessage({
71
- id: getTranslation("CheckboxConfirmation.Modal.content"),
72
- defaultMessage: "Disabling localization will engender the deletion of all your content but the one associated to your default locale (if existing)."
73
- }) }) }),
74
- /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(Typography, { fontWeight: "semiBold", children: formatMessage({
75
- id: getTranslation("CheckboxConfirmation.Modal.body"),
76
- defaultMessage: "Do you want to disable it?"
77
- }) }) })
78
- ] }) }),
79
- /* @__PURE__ */ jsxs(Dialog.Footer, { children: [
80
- /* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button$1, { variant: "tertiary", children: formatMessage({
81
- id: "components.popUpWarning.button.cancel",
82
- defaultMessage: "No, cancel"
83
- }) }) }),
84
- /* @__PURE__ */ jsx(Dialog.Action, { children: /* @__PURE__ */ jsx(Button$1, { variant: "danger-light", onClick: handleConfirm, children: formatMessage({
85
- id: getTranslation("CheckboxConfirmation.Modal.button-confirm"),
86
- defaultMessage: "Yes, disable"
87
- }) }) })
88
- ] })
89
- ] })
90
- ] });
91
- };
92
- const LOCALIZED_FIELDS = [
93
- "biginteger",
94
- "boolean",
95
- "component",
96
- "date",
97
- "datetime",
98
- "decimal",
99
- "dynamiczone",
100
- "email",
101
- "enumeration",
102
- "float",
103
- "integer",
104
- "json",
105
- "media",
106
- "number",
107
- "password",
108
- "richtext",
109
- "blocks",
110
- "string",
111
- "text",
112
- "time"
113
- ];
114
- const doesPluginOptionsHaveI18nLocalized = (opts) => typeof opts === "object" && opts !== null && "i18n" in opts && typeof opts.i18n === "object" && opts.i18n !== null && "localized" in opts.i18n && typeof opts.i18n.localized === "boolean";
115
- const capitalize = (str) => str.charAt(0).toUpperCase() + str.slice(1);
116
- const useI18n = () => {
117
- const params = useParams();
118
- const userPermissions = useAuth("useI18n", (state) => state.permissions);
119
- const actions = React.useMemo(() => {
120
- const permissions = userPermissions.filter((permission) => permission.subject === params.slug);
121
- return permissions.reduce(
122
- (acc, permission) => {
123
- const [actionShorthand] = permission.action.split(".").slice(-1);
124
- return {
125
- ...acc,
126
- [`can${capitalize(actionShorthand)}`]: permission.properties?.locales ?? []
127
- };
128
- },
129
- { canCreate: [], canRead: [], canUpdate: [], canDelete: [], canPublish: [] }
130
- );
131
- }, [params.slug, userPermissions]);
132
- const { schema } = unstable_useDocument(
133
- {
134
- // We can non-null assert these because below we skip the query if they are not present
135
- collectionType: params.collectionType,
136
- model: params.slug
137
- },
138
- {
139
- skip: !params.slug || !params.collectionType
140
- }
141
- );
142
- if (doesPluginOptionsHaveI18nLocalized(schema?.pluginOptions)) {
143
- return {
144
- hasI18n: schema.pluginOptions.i18n.localized,
145
- ...actions
146
- };
147
- }
148
- return {
149
- hasI18n: false,
150
- ...actions
151
- };
152
- };
153
- const i18nApi = adminApi.enhanceEndpoints({
154
- addTagTypes: ["Locale"]
155
- });
156
- const localesApi = i18nApi.injectEndpoints({
157
- endpoints: (builder) => ({
158
- createLocale: builder.mutation({
159
- query: (data) => ({
160
- url: "/i18n/locales",
161
- method: "POST",
162
- data
163
- }),
164
- invalidatesTags: [{ type: "Locale", id: "LIST" }]
165
- }),
166
- deleteLocale: builder.mutation({
167
- query: (id) => ({
168
- url: `/i18n/locales/${id}`,
169
- method: "DELETE"
170
- }),
171
- invalidatesTags: (result, error, id) => [{ type: "Locale", id }]
172
- }),
173
- getLocales: builder.query({
174
- query: () => "/i18n/locales",
175
- providesTags: (res) => [
176
- { type: "Locale", id: "LIST" },
177
- ...Array.isArray(res) ? res.map((locale) => ({
178
- type: "Locale",
179
- id: locale.id
180
- })) : []
181
- ]
182
- }),
183
- getDefaultLocales: builder.query({
184
- query: () => "/i18n/iso-locales"
185
- }),
186
- updateLocale: builder.mutation({
187
- query: ({ id, ...data }) => ({
188
- url: `/i18n/locales/${id}`,
189
- method: "PUT",
190
- data
191
- }),
192
- invalidatesTags: (result, error, { id }) => [{ type: "Locale", id }]
193
- })
194
- })
195
- });
196
- const {
197
- useCreateLocaleMutation,
198
- useDeleteLocaleMutation,
199
- useGetLocalesQuery,
200
- useGetDefaultLocalesQuery,
201
- useUpdateLocaleMutation
202
- } = localesApi;
203
- const relationsApi = i18nApi.injectEndpoints({
204
- overrideExisting: true,
205
- endpoints: (builder) => ({
206
- getManyDraftRelationCount: builder.query({
207
- query: ({ model, ...params }) => ({
208
- url: `/content-manager/collection-types/${model}/actions/countManyEntriesDraftRelations`,
209
- method: "GET",
210
- config: {
211
- params
212
- }
213
- }),
214
- transformResponse: (response) => response.data
215
- })
216
- })
217
- });
218
- const { useGetManyDraftRelationCountQuery } = relationsApi;
219
- const isErrorMessageDescriptor = (object) => {
220
- return typeof object === "object" && object !== null && "id" in object && "defaultMessage" in object;
221
- };
222
- const EntryValidationText = ({ status = "draft", validationErrors }) => {
223
- const { formatMessage } = useIntl();
224
- const getErrorStr = (key, value) => {
225
- if (typeof value === "string") {
226
- return `${key}: ${value}`;
227
- } else if (isErrorMessageDescriptor(value)) {
228
- return `${key}: ${formatMessage(value)}`;
229
- } else if (Array.isArray(value)) {
230
- return value.map((v) => getErrorStr(key, v)).join(" ");
231
- } else if (typeof value === "object" && !Array.isArray(value)) {
232
- return Object.entries(value).map(([k, v]) => getErrorStr(k, v)).join(" ");
233
- } else {
234
- return "";
235
- }
236
- };
237
- if (validationErrors) {
238
- const validationErrorsMessages = Object.entries(validationErrors).map(([key, value]) => {
239
- return getErrorStr(key, value);
240
- }).join(" ");
241
- return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
242
- /* @__PURE__ */ jsx(CrossCircle, { fill: "danger600" }),
243
- /* @__PURE__ */ jsx(Tooltip, { label: validationErrorsMessages, children: /* @__PURE__ */ jsx(
244
- Typography,
245
- {
246
- maxWidth: "30rem",
247
- textColor: "danger600",
248
- variant: "omega",
249
- fontWeight: "semiBold",
250
- ellipsis: true,
251
- children: validationErrorsMessages
252
- }
253
- ) })
254
- ] });
255
- }
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
- }
274
- 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
- }) })
280
- ] });
281
- };
282
- const BoldChunk = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: chunks });
283
- const BulkLocaleActionModal = ({
284
- headers,
285
- rows,
286
- localesMetadata,
287
- validationErrors = {}
288
- }) => {
289
- const { formatMessage } = useIntl();
290
- const selectedRows = useTable(
291
- "BulkLocaleActionModal",
292
- (state) => state.selectedRows
293
- );
294
- const getFormattedCountMessage = () => {
295
- const currentStatusByLocale = rows.reduce((acc, { locale, status }) => {
296
- acc[locale] = status;
297
- return acc;
298
- }, {});
299
- const localesWithErrors = Object.keys(validationErrors);
300
- const alreadyPublishedCount = selectedRows.filter(
301
- ({ locale }) => currentStatusByLocale[locale] === "published"
302
- ).length;
303
- const readyToPublishCount = selectedRows.filter(
304
- ({ locale }) => (currentStatusByLocale[locale] === "draft" || currentStatusByLocale[locale] === "modified") && !localesWithErrors.includes(locale)
305
- ).length;
306
- const withErrorsCount = localesWithErrors.length;
307
- return formatMessage(
308
- {
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."
311
- },
312
- {
313
- withErrorsCount,
314
- readyToPublishCount,
315
- alreadyPublishedCount,
316
- b: BoldChunk
317
- }
318
- );
319
- };
320
- return /* @__PURE__ */ jsxs(React.Fragment, { children: [
321
- /* @__PURE__ */ jsx(Typography, { children: getFormattedCountMessage() }),
322
- /* @__PURE__ */ jsx(Box, { marginTop: 5, children: /* @__PURE__ */ jsxs(Table.Content, { children: [
323
- /* @__PURE__ */ jsxs(Table.Head, { children: [
324
- /* @__PURE__ */ jsx(Table.HeaderCheckboxCell, {}),
325
- headers.map((head) => /* @__PURE__ */ jsx(Table.HeaderCell, { ...head }, head.name))
326
- ] }),
327
- /* @__PURE__ */ jsx(Table.Body, { children: rows.map(({ locale, status }, index2) => {
328
- const error = validationErrors?.[locale] ?? null;
329
- const statusVariant = status === "draft" ? "primary" : status === "published" ? "success" : "alternative";
330
- return /* @__PURE__ */ jsxs(Table.Row, { children: [
331
- /* @__PURE__ */ jsx(Table.CheckboxCell, { id: locale, "aria-label": `Select ${locale}` }),
332
- /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", children: Array.isArray(localesMetadata) ? localesMetadata.find((localeEntry) => localeEntry.code === locale)?.name : locale }) }),
333
- /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Box, { display: "flex", children: /* @__PURE__ */ jsx(
334
- Status,
335
- {
336
- display: "flex",
337
- paddingLeft: "6px",
338
- paddingRight: "6px",
339
- paddingTop: "2px",
340
- paddingBottom: "2px",
341
- showBullet: false,
342
- size: "S",
343
- variant: statusVariant,
344
- children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "pi", fontWeight: "bold", children: capitalize(status) })
345
- }
346
- ) }) }),
347
- /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(EntryValidationText, { validationErrors: error, status }) }),
348
- /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
349
- IconButton,
350
- {
351
- tag: Link,
352
- to: {
353
- search: stringify({ plugins: { i18n: { locale } } })
354
- },
355
- label: formatMessage(
356
- {
357
- id: getTranslation("Settings.list.actions.edit"),
358
- defaultMessage: "Edit {name} locale"
359
- },
360
- {
361
- name: locale
362
- }
363
- ),
364
- borderWidth: 0,
365
- children: /* @__PURE__ */ jsx(Pencil, {})
366
- }
367
- ) })
368
- ] }, index2);
369
- }) })
370
- ] }) })
371
- ] });
372
- };
373
- const LocalePickerAction = ({
374
- document,
375
- meta,
376
- model,
377
- collectionType,
378
- documentId
379
- }) => {
380
- const { formatMessage } = useIntl();
381
- const [{ query }, setQuery] = useQueryParams();
382
- const { hasI18n, canCreate, canRead } = useI18n();
383
- const { data: locales = [] } = useGetLocalesQuery();
384
- const { schema } = unstable_useDocument({ model, collectionType, documentId });
385
- const handleSelect = React.useCallback(
386
- (value) => {
387
- setQuery({
388
- plugins: {
389
- ...query.plugins,
390
- i18n: {
391
- locale: value
392
- }
393
- }
394
- });
395
- },
396
- [query.plugins, setQuery]
397
- );
398
- React.useEffect(() => {
399
- if (!Array.isArray(locales) || !hasI18n) {
400
- return;
401
- }
402
- const currentDesiredLocale = query.plugins?.i18n?.locale;
403
- const doesLocaleExist = locales.find((loc) => loc.code === currentDesiredLocale);
404
- const defaultLocale = locales.find((locale) => locale.isDefault);
405
- if (!doesLocaleExist && defaultLocale?.code) {
406
- handleSelect(defaultLocale.code);
407
- }
408
- }, [handleSelect, hasI18n, locales, query.plugins?.i18n?.locale]);
409
- if (!hasI18n || !Array.isArray(locales) || locales.length === 0) {
410
- return null;
411
- }
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
- ];
417
- return {
418
- label: formatMessage({
419
- id: getTranslation("Settings.locales.modal.locales.label"),
420
- defaultMessage: "Locales"
421
- }),
422
- options: locales.map((locale) => {
423
- const currentLocaleDoc = allCurrentLocales.find(
424
- (doc) => "locale" in doc ? doc.locale === locale.code : false
425
- );
426
- const status = currentLocaleDoc?.status ?? "draft";
427
- const permissionsToCheck = currentLocaleDoc ? canCreate : canRead;
428
- const statusVariant = status === "draft" ? "primary" : status === "published" ? "success" : "alternative";
429
- return {
430
- disabled: !permissionsToCheck.includes(locale.code),
431
- value: locale.code,
432
- label: locale.name,
433
- startIcon: schema?.options?.draftAndPublish ? /* @__PURE__ */ jsx(
434
- Status,
435
- {
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) })
445
- }
446
- ) : null
447
- };
448
- }),
449
- onSelect: handleSelect,
450
- value: currentLocale
451
- };
452
- };
453
- const getDocumentStatus = (document, meta) => {
454
- const docStatus = document?.status;
455
- const statuses = meta?.availableStatus ?? [];
456
- if (!docStatus) {
457
- return "draft";
458
- }
459
- if (docStatus === "draft" && statuses.find((doc) => doc.publishedAt !== null)) {
460
- return "published";
461
- }
462
- return docStatus;
463
- };
464
- const DeleteLocaleAction = ({
465
- document,
466
- documentId,
467
- model,
468
- collectionType
469
- }) => {
470
- const { formatMessage } = useIntl();
471
- const navigate = useNavigate();
472
- const { toggleNotification } = useNotification();
473
- const { delete: deleteAction } = unstable_useDocumentActions();
474
- const { hasI18n, canDelete } = useI18n();
475
- if (!hasI18n) {
476
- return null;
477
- }
478
- return {
479
- disabled: document?.locale && !canDelete.includes(document.locale) || !document || !document.id,
480
- position: ["header", "table-row"],
481
- label: formatMessage({
482
- id: getTranslation("actions.delete.label"),
483
- defaultMessage: "Delete locale"
484
- }),
485
- icon: /* @__PURE__ */ jsx(StyledTrash, {}),
486
- variant: "danger",
487
- dialog: {
488
- type: "dialog",
489
- title: formatMessage({
490
- id: getTranslation("actions.delete.dialog.title"),
491
- defaultMessage: "Confirmation"
492
- }),
493
- content: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
494
- /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
495
- /* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
496
- id: getTranslation("actions.delete.dialog.body"),
497
- defaultMessage: "Are you sure?"
498
- }) })
499
- ] }),
500
- onConfirm: async () => {
501
- if (!documentId || !document?.locale) {
502
- console.error(
503
- "You're trying to delete a document without an id or locale, this is likely a bug with Strapi. Please open an issue."
504
- );
505
- toggleNotification({
506
- message: formatMessage({
507
- id: getTranslation("actions.delete.error"),
508
- defaultMessage: "An error occurred while trying to delete the document locale."
509
- }),
510
- type: "danger"
511
- });
512
- return;
513
- }
514
- const res = await deleteAction({
515
- documentId,
516
- model,
517
- collectionType,
518
- params: { locale: document.locale }
519
- });
520
- if (!("error" in res)) {
521
- navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
522
- }
523
- }
524
- }
525
- };
526
- };
527
- const BulkLocalePublishAction = ({
528
- document: baseDocument,
529
- documentId,
530
- model,
531
- collectionType
532
- }) => {
533
- const baseLocale = baseDocument?.locale ?? null;
534
- const [{ query }] = useQueryParams();
535
- const params = React.useMemo(() => buildValidParams(query), [query]);
536
- const isPublishedTab = query.status === "published";
537
- const { formatMessage } = useIntl();
538
- const { hasI18n, canPublish } = useI18n();
539
- const { toggleNotification } = useNotification();
540
- const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
541
- 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
555
- }
556
- });
557
- const { data: localesMetadata = [] } = useGetLocalesQuery();
558
- const headers = [
559
- {
560
- label: formatMessage({
561
- id: "global.name",
562
- defaultMessage: "Name"
563
- }),
564
- name: "name"
565
- },
566
- {
567
- label: formatMessage({
568
- id: getTranslation("CMEditViewBulkLocale.status"),
569
- defaultMessage: "Status"
570
- }),
571
- name: "status"
572
- },
573
- {
574
- label: formatMessage({
575
- id: getTranslation("CMEditViewBulkLocale.publication-status"),
576
- defaultMessage: "Publication Status"
577
- }),
578
- name: "publication-status"
579
- }
580
- ];
581
- const [rows, validationErrors] = React.useMemo(() => {
582
- if (!document || !documentMeta?.availableLocales) {
583
- return [[], {}];
584
- }
585
- const rowsFromMeta = documentMeta?.availableLocales.map((doc) => {
586
- const { locale, status } = doc;
587
- return { locale, status };
588
- });
589
- rowsFromMeta.unshift({
590
- locale: document.locale,
591
- status: document.status
592
- });
593
- const allDocuments = [document, ...documentMeta?.availableLocales ?? []];
594
- const errors = allDocuments.reduce((errs, document2) => {
595
- if (!document2) {
596
- return errs;
597
- }
598
- const validation = validate(document2);
599
- if (validation !== null) {
600
- errs[document2.locale] = validation;
601
- }
602
- return errs;
603
- }, {});
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)) {
608
- acc.push(selectedRow.locale);
609
- }
610
- return acc;
611
- }, []);
612
- const {
613
- data: draftRelationsCount = 0,
614
- isLoading: isDraftRelationsLoading,
615
- error: isDraftRelationsError
616
- } = useGetManyDraftRelationCountQuery(
617
- {
618
- model,
619
- documentIds: [documentId],
620
- locale: localesToPublish
621
- },
622
- {
623
- skip: !documentId || localesToPublish.length === 0
624
- }
625
- );
626
- React.useEffect(() => {
627
- if (isDraftRelationsError) {
628
- toggleNotification({
629
- type: "danger",
630
- message: formatAPIError(isDraftRelationsError)
631
- });
632
- }
633
- }, [isDraftRelationsError, toggleNotification, formatAPIError]);
634
- if (!schema?.options?.draftAndPublish) {
635
- return null;
636
- }
637
- if (!hasI18n) {
638
- return null;
639
- }
640
- if (!documentId) {
641
- return null;
642
- }
643
- const publish = async () => {
644
- await publishManyAction({
645
- model,
646
- documentIds: [documentId],
647
- params: {
648
- ...params,
649
- locale: localesToPublish
650
- }
651
- });
652
- setSelectedRows([]);
653
- };
654
- const handleAction = async () => {
655
- if (draftRelationsCount > 0) {
656
- setIsConfirmationOpen(true);
657
- } else {
658
- await publish();
659
- }
660
- };
661
- const isUnpublish = document?.status === "published";
662
- if (isUnpublish) {
663
- console.warn(["I18N"], "Bulk locale unpublish modal not implemented");
664
- }
665
- if (isConfirmationOpen) {
666
- return {
667
- label: formatMessage({
668
- id: "app.components.ConfirmDialog.title",
669
- defaultMessage: "Confirmation"
670
- }),
671
- variant: "danger",
672
- dialog: {
673
- onCancel: () => {
674
- setIsConfirmationOpen(false);
675
- },
676
- onConfirm: async () => {
677
- await publish();
678
- setIsConfirmationOpen(false);
679
- },
680
- type: "dialog",
681
- title: formatMessage({
682
- id: getTranslation("actions.publish.dialog.title"),
683
- defaultMessage: "Confirmation"
684
- }),
685
- content: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "center", gap: 2, children: [
686
- /* @__PURE__ */ jsx(WarningCircle, { width: "2.4rem", height: "2.4rem", fill: "danger600" }),
687
- /* @__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."
690
- }) })
691
- ] })
692
- }
693
- };
694
- }
695
- return {
696
- label: formatMessage({
697
- id: getTranslation("CMEditViewBulkLocale.publish-title"),
698
- defaultMessage: "Publish Multiple Locales"
699
- }),
700
- icon: /* @__PURE__ */ jsx(ListPlus, {}),
701
- disabled: isPublishedTab || !canPublish,
702
- position: ["panel"],
703
- variant: "secondary",
704
- dialog: {
705
- type: "modal",
706
- title: formatMessage({
707
- id: getTranslation("CMEditViewBulkLocale.publish-title"),
708
- defaultMessage: "Publish Multiple Locales"
709
- }),
710
- content: () => {
711
- return /* @__PURE__ */ jsx(
712
- Table.Root,
713
- {
714
- headers,
715
- rows: rows.map((row) => ({
716
- ...row,
717
- id: row.locale
718
- })),
719
- selectedRows,
720
- onSelectedRowsChange: (tableSelectedRows) => setSelectedRows(tableSelectedRows),
721
- children: /* @__PURE__ */ jsx(
722
- BulkLocaleActionModal,
723
- {
724
- validationErrors,
725
- headers,
726
- rows,
727
- localesMetadata
728
- }
729
- )
730
- }
731
- );
732
- },
733
- footer: () => /* @__PURE__ */ jsx(Flex, { justifyContent: "flex-end", children: /* @__PURE__ */ jsx(
734
- Button$1,
735
- {
736
- loading: isDraftRelationsLoading,
737
- disabled: localesToPublish.length === 0,
738
- variant: "default",
739
- onClick: handleAction,
740
- children: formatMessage({
741
- id: "app.utils.publish",
742
- defaultMessage: "Publish"
743
- })
744
- }
745
- ) })
746
- }
747
- };
748
- };
749
- const StyledTrash = styled(Trash)`
750
- path {
751
- fill: currentColor;
752
- }
753
- `;
754
- const Emphasis = (chunks) => {
755
- return /* @__PURE__ */ jsx(Typography, { fontWeight: "semiBold", textColor: "danger500", children: chunks });
756
- };
757
- const DeleteModalAdditionalInfo = () => {
758
- const { hasI18n } = useI18n();
759
- const { formatMessage } = useIntl();
760
- if (!hasI18n) {
761
- return null;
762
- }
763
- return /* @__PURE__ */ jsx(Typography, { textColor: "danger500", children: formatMessage(
764
- {
765
- id: getTranslation("Settings.list.actions.deleteAdditionalInfos"),
766
- defaultMessage: "This will delete the active locale versions <em>(from Internationalization)</em>"
767
- },
768
- {
769
- em: Emphasis
770
- }
771
- ) });
772
- };
773
- const PublishModalAdditionalInfo = () => {
774
- const { hasI18n } = useI18n();
775
- const { formatMessage } = useIntl();
776
- if (!hasI18n) {
777
- return null;
778
- }
779
- return /* @__PURE__ */ jsx(Typography, { textColor: "danger500", children: formatMessage(
780
- {
781
- id: getTranslation("Settings.list.actions.publishAdditionalInfos"),
782
- defaultMessage: "This will publish the active locale versions <em>(from Internationalization)</em>"
783
- },
784
- {
785
- em: Emphasis
786
- }
787
- ) });
788
- };
789
- const UnpublishModalAdditionalInfo = () => {
790
- const { hasI18n } = useI18n();
791
- const { formatMessage } = useIntl();
792
- if (!hasI18n) {
793
- return null;
794
- }
795
- return /* @__PURE__ */ jsx(Typography, { textColor: "danger500", children: formatMessage(
796
- {
797
- id: getTranslation("Settings.list.actions.unpublishAdditionalInfos"),
798
- defaultMessage: "This will unpublish the active locale versions <em>(from Internationalization)</em>"
799
- },
800
- {
801
- em: Emphasis
802
- }
803
- ) });
804
- };
805
- const Initializer = ({ setPlugin }) => {
806
- const setPluginRef = React.useRef(setPlugin);
807
- React.useEffect(() => {
808
- setPluginRef.current(pluginId);
809
- }, []);
810
- return null;
811
- };
812
- const LocalePicker = () => {
813
- const { formatMessage } = useIntl();
814
- const [{ query }, setQuery] = useQueryParams();
815
- const { hasI18n, canRead, canCreate } = useI18n();
816
- const { data: locales = [] } = useGetLocalesQuery(void 0, {
817
- skip: !hasI18n
818
- });
819
- const handleChange = React.useCallback(
820
- (code, replace = false) => {
821
- setQuery(
822
- {
823
- page: 1,
824
- plugins: { ...query.plugins, i18n: { locale: code } }
825
- },
826
- "push",
827
- replace
828
- );
829
- },
830
- [query.plugins, setQuery]
831
- );
832
- React.useEffect(() => {
833
- if (!Array.isArray(locales) || !hasI18n) {
834
- return;
835
- }
836
- const currentDesiredLocale = query.plugins?.i18n?.locale;
837
- const doesLocaleExist = locales.find((loc) => loc.code === currentDesiredLocale);
838
- const defaultLocale = locales.find((locale) => locale.isDefault);
839
- if (!doesLocaleExist && defaultLocale?.code) {
840
- handleChange(defaultLocale.code, true);
841
- }
842
- }, [hasI18n, handleChange, locales, query.plugins?.i18n?.locale]);
843
- if (!hasI18n || !Array.isArray(locales) || locales.length === 0) {
844
- return null;
845
- }
846
- const displayedLocales = locales.filter((locale) => {
847
- return canCreate.includes(locale.code) || canRead.includes(locale.code);
848
- });
849
- return /* @__PURE__ */ jsx(
850
- SingleSelect,
851
- {
852
- size: "S",
853
- "aria-label": formatMessage({
854
- id: getTranslation("actions.select-locale"),
855
- defaultMessage: "Select locale"
856
- }),
857
- value: query.plugins?.i18n?.locale || locales.find((locale) => locale.isDefault)?.code,
858
- onChange: handleChange,
859
- children: displayedLocales.map((locale) => /* @__PURE__ */ jsx(SingleSelectOption, { value: locale.code, children: locale.name }, locale.id))
860
- }
861
- );
862
- };
863
- const PERMISSIONS = {
864
- accessMain: [{ action: "plugin::i18n.locale.read", subject: null }],
865
- create: [{ action: "plugin::i18n.locale.create", subject: null }],
866
- delete: [{ action: "plugin::i18n.locale.delete", subject: null }],
867
- update: [{ action: "plugin::i18n.locale.update", subject: null }],
868
- read: [{ action: "plugin::i18n.locale.read", subject: null }]
869
- };
870
- const mutateEditViewHook = ({ layout }) => {
871
- if (!("i18n" in layout.options) || typeof layout.options.i18n === "object" && layout.options.i18n !== null && "localized" in layout.options.i18n && !layout.options.i18n.localized) {
872
- return { layout };
873
- }
874
- const components = Object.entries(layout.components).reduce(
875
- (acc, [key, componentLayout]) => {
876
- return {
877
- ...acc,
878
- [key]: {
879
- ...componentLayout,
880
- layout: componentLayout.layout.map((row) => row.map(addLabelActionToField))
881
- }
882
- };
883
- },
884
- {}
885
- );
886
- return {
887
- layout: {
888
- ...layout,
889
- components,
890
- layout: layout.layout.map((panel) => panel.map((row) => row.map(addLabelActionToField)))
891
- }
892
- };
893
- };
894
- const addLabelActionToField = (field) => {
895
- const isFieldLocalized = doesFieldHaveI18nPluginOpt(field.attribute.pluginOptions) ? field.attribute.pluginOptions.i18n.localized : true;
896
- const labelActionProps = {
897
- title: {
898
- id: isFieldLocalized ? getTranslation("Field.localized") : getTranslation("Field.not-localized"),
899
- defaultMessage: isFieldLocalized ? "This value is unique for the selected locale" : "This value is the same across all locales"
900
- },
901
- icon: isFieldLocalized ? /* @__PURE__ */ jsx(Earth, {}) : /* @__PURE__ */ jsx(EarthStriked, {})
902
- };
903
- return {
904
- ...field,
905
- labelAction: /* @__PURE__ */ jsx(LabelAction, { ...labelActionProps })
906
- };
907
- };
908
- const doesFieldHaveI18nPluginOpt = (pluginOpts) => {
909
- if (!pluginOpts) {
910
- return false;
911
- }
912
- return "i18n" in pluginOpts && typeof pluginOpts.i18n === "object" && pluginOpts.i18n !== null && "localized" in pluginOpts.i18n;
913
- };
914
- const LabelAction = ({ title, icon }) => {
915
- const { formatMessage } = useIntl();
916
- return /* @__PURE__ */ jsxs(Span, { tag: "span", children: [
917
- /* @__PURE__ */ jsx(VisuallyHidden, { tag: "span", children: formatMessage(title) }),
918
- React.cloneElement(icon, {
919
- "aria-hidden": true,
920
- focusable: false
921
- // See: https://allyjs.io/tutorials/focusing-in-svg.html#making-svg-elements-focusable
922
- })
923
- ] });
924
- };
925
- const Span = styled(Flex)`
926
- svg {
927
- width: 12px;
928
- height: 12px;
929
-
930
- fill: ${({ theme }) => theme.colors.neutral500};
931
-
932
- path {
933
- fill: ${({ theme }) => theme.colors.neutral500};
934
- }
935
- }
936
- `;
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
- });
951
- const { locale: language } = useIntl();
952
- const { data: locales = [] } = useGetLocalesQuery();
953
- const formatter = useCollator(language, {
954
- sensitivity: "base"
955
- });
956
- if (!Array.isArray(locales) || isLoading) {
957
- return null;
958
- }
959
- const availableLocales = meta?.availableLocales.map((doc) => doc.locale) ?? [];
960
- const localesForDocument = locales.reduce((acc, locale) => {
961
- const createdLocale = [currentLocale, ...availableLocales].find((loc) => {
962
- return loc === locale.code;
963
- });
964
- if (createdLocale) {
965
- acc.push(locale);
966
- }
967
- return acc;
968
- }, []).map((locale) => {
969
- if (locale.isDefault) {
970
- return `${locale.name} (default)`;
971
- }
972
- return locale.name;
973
- }).toSorted((a, b) => formatter.compare(a, b));
974
- 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
- ) }) }),
989
- /* @__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
- ] });
991
- };
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
- const addColumnToTableHook = ({ displayedHeaders, layout }) => {
1024
- const { options } = layout;
1025
- const isFieldLocalized = doesPluginOptionsHaveI18nLocalized(options) ? options.i18n.localized : false;
1026
- if (!isFieldLocalized) {
1027
- return { displayedHeaders, layout };
1028
- }
1029
- return {
1030
- displayedHeaders: [
1031
- ...displayedHeaders,
1032
- {
1033
- attribute: { type: "string" },
1034
- label: {
1035
- id: getTranslation("list-view.table.header.label"),
1036
- defaultMessage: "Available in"
1037
- },
1038
- searchable: false,
1039
- sortable: false,
1040
- name: "locales",
1041
- // @ts-expect-error – ID is seen as number | string; this will change when we move the type over.
1042
- cellFormatter: (props, _header, meta) => /* @__PURE__ */ jsx(LocaleListCell, { ...props, ...meta })
1043
- }
1044
- ],
1045
- layout
1046
- };
1047
- };
1048
- const addLocaleToReleasesHook = ({ displayedHeaders = [] }) => {
1049
- return {
1050
- displayedHeaders: [
1051
- // TODO: Fix when migrating to v5
1052
- // ...displayedHeaders,
1053
- {
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
1063
- },
1064
- name: "locale"
1065
- }
1066
- ],
1067
- hasI18nEnabled: true
1068
- };
1069
- };
1070
- const extendCTBAttributeInitialDataMiddleware = () => {
1071
- return ({ getState }) => (next) => (action) => {
1072
- const enhanceAction = () => {
1073
- try {
1074
- const store = getState();
1075
- const hasi18nEnabled = get(
1076
- store,
1077
- [
1078
- "content-type-builder_dataManagerProvider",
1079
- "modifiedData",
1080
- "contentType",
1081
- "schema",
1082
- "pluginOptions",
1083
- "i18n",
1084
- "localized"
1085
- ],
1086
- false
1087
- );
1088
- if (hasi18nEnabled) {
1089
- const pluginOptions = action.options ? { ...action.options.pluginOptions, i18n: { localized: true } } : { i18n: { localized: true } };
1090
- return next({
1091
- ...action,
1092
- options: {
1093
- pluginOptions
1094
- }
1095
- });
1096
- }
1097
- return next(action);
1098
- } catch (err) {
1099
- return next(action);
1100
- }
1101
- };
1102
- if (action.type === "ContentTypeBuilder/FormModal/SET_ATTRIBUTE_DATA_SCHEMA" && action.forTarget === "contentType" && !["relation", "component"].includes(action.attributeType) && !action.isEditing) {
1103
- return enhanceAction();
1104
- }
1105
- if (action.type === "ContentTypeBuilder/FormModal/SET_CUSTOM_FIELD_DATA_SCHEMA" && action.forTarget === "contentType" && !action.isEditing) {
1106
- return enhanceAction();
1107
- }
1108
- if ((action.type === "ContentTypeBuilder/FormModal/RESET_PROPS_AND_SET_FORM_FOR_ADDING_AN_EXISTING_COMPO" || action.type === "ContentTypeBuilder/FormModal/RESET_PROPS_AND_SAVE_CURRENT_DATA") && action.forTarget === "contentType") {
1109
- return enhanceAction();
1110
- }
1111
- return next(action);
1112
- };
1113
- };
1114
- const extendCTBInitialDataMiddleware = () => {
1115
- return () => (next) => (action) => {
1116
- if (action.type === "ContentTypeBuilder/FormModal/SET_DATA_TO_EDIT" && action.modalType === "contentType") {
1117
- const i18n = { localized: false };
1118
- const pluginOptions = action.data.pluginOptions ? { ...action.data.pluginOptions, i18n } : { i18n };
1119
- const data = { ...action.data, pluginOptions };
1120
- if (action.actionType === "create") {
1121
- return next({ ...action, data });
1122
- }
1123
- if (!action.data.pluginOptions?.i18n?.localized) {
1124
- return next({ ...action, data });
1125
- }
1126
- }
1127
- return next(action);
1128
- };
1129
- };
1130
- const localeMiddleware = (ctx) => (next) => (permissions) => {
1131
- const match = matchPath("/content-manager/:collectionType/:model?/:id", ctx.pathname);
1132
- if (!match) {
1133
- return next(permissions);
1134
- }
1135
- const search = qs.parse(ctx.search);
1136
- if (typeof search !== "object") {
1137
- return next(permissions);
1138
- }
1139
- if (!("plugins" in search && typeof search.plugins === "object")) {
1140
- return next(permissions);
1141
- }
1142
- if (!("i18n" in search.plugins && typeof search.plugins.i18n === "object" && !Array.isArray(search.plugins.i18n))) {
1143
- return next(permissions);
1144
- }
1145
- const { locale } = search.plugins.i18n;
1146
- if (typeof locale !== "string") {
1147
- return next(permissions);
1148
- }
1149
- const revisedPermissions = permissions.filter(
1150
- (permission) => !permission.properties?.locales || permission.properties.locales.includes(locale)
1151
- );
1152
- return next(revisedPermissions);
1153
- };
1154
- const prefixPluginTranslations = (trad, pluginId2) => {
1155
- if (!pluginId2) {
1156
- throw new TypeError("pluginId can't be empty");
1157
- }
1158
- return Object.keys(trad).reduce((acc, current) => {
1159
- acc[`${pluginId2}.${current}`] = trad[current];
1160
- return acc;
1161
- }, {});
1162
- };
1163
- const mutateCTBContentTypeSchema = (nextSchema, prevSchema) => {
1164
- if (!doesPluginOptionsHaveI18nLocalized(nextSchema.pluginOptions)) {
1165
- return nextSchema;
1166
- }
1167
- const isNextSchemaLocalized = nextSchema.pluginOptions.i18n.localized;
1168
- const isPrevSchemaLocalized = doesPluginOptionsHaveI18nLocalized(
1169
- prevSchema?.schema?.pluginOptions
1170
- ) ? prevSchema?.schema?.pluginOptions.i18n.localized : false;
1171
- if (isNextSchemaLocalized && isPrevSchemaLocalized) {
1172
- return nextSchema;
1173
- }
1174
- if (isNextSchemaLocalized) {
1175
- const attributes = addLocalisationToFields(nextSchema.attributes);
1176
- return { ...nextSchema, attributes };
1177
- }
1178
- if (!isNextSchemaLocalized) {
1179
- const pluginOptions = omit(nextSchema.pluginOptions, "i18n");
1180
- const attributes = disableAttributesLocalisation(nextSchema.attributes);
1181
- return { ...nextSchema, pluginOptions, attributes };
1182
- }
1183
- return nextSchema;
1184
- };
1185
- const addLocalisationToFields = (attributes) => Object.keys(attributes).reduce((acc, current) => {
1186
- const currentAttribute = attributes[current];
1187
- if (LOCALIZED_FIELDS.includes(currentAttribute.type)) {
1188
- const i18n = { localized: true };
1189
- const pluginOptions = currentAttribute.pluginOptions ? { ...currentAttribute.pluginOptions, i18n } : { i18n };
1190
- acc[current] = { ...currentAttribute, pluginOptions };
1191
- return acc;
1192
- }
1193
- acc[current] = currentAttribute;
1194
- return acc;
1195
- }, {});
1196
- const disableAttributesLocalisation = (attributes) => Object.keys(attributes).reduce((acc, current) => {
1197
- acc[current] = omit(attributes[current], "pluginOptions.i18n");
1198
- return acc;
1199
- }, {});
1200
- const index = {
1201
- register(app) {
1202
- app.addMiddlewares([extendCTBAttributeInitialDataMiddleware, extendCTBInitialDataMiddleware]);
1203
- app.addMiddlewares([() => i18nApi.middleware]);
1204
- app.addReducers({
1205
- [i18nApi.reducerPath]: i18nApi.reducer
1206
- });
1207
- app.addRBACMiddleware([localeMiddleware]);
1208
- app.registerPlugin({
1209
- id: pluginId,
1210
- initializer: Initializer,
1211
- isReady: false,
1212
- name: pluginId
1213
- });
1214
- },
1215
- bootstrap(app) {
1216
- app.registerHook("Admin/CM/pages/ListView/inject-column-in-table", addColumnToTableHook);
1217
- app.registerHook("Admin/CM/pages/EditView/mutate-edit-view-layout", mutateEditViewHook);
1218
- app.registerHook(
1219
- "ContentReleases/pages/ReleaseDetails/add-locale-in-releases",
1220
- addLocaleToReleasesHook
1221
- );
1222
- app.addSettingsLink("global", {
1223
- intlLabel: {
1224
- id: getTranslation("plugin.name"),
1225
- defaultMessage: "Internationalization"
1226
- },
1227
- id: "internationalization",
1228
- to: "internationalization",
1229
- Component: () => import("./SettingsPage-Dsi2qGtq.mjs").then((mod) => ({ default: mod.ProtectedSettingsPage })),
1230
- permissions: PERMISSIONS.accessMain
1231
- });
1232
- const contentManager = app.getPlugin("content-manager");
1233
- contentManager.apis.addDocumentHeaderAction([LocalePickerAction]);
1234
- contentManager.apis.addDocumentAction((actions) => {
1235
- const indexOfDeleteAction = actions.findIndex((action) => action.type === "delete");
1236
- actions.splice(indexOfDeleteAction, 0, DeleteLocaleAction);
1237
- return actions;
1238
- });
1239
- contentManager.apis.addDocumentAction((actions) => {
1240
- actions.splice(2, 0, BulkLocalePublishAction);
1241
- return actions;
1242
- });
1243
- contentManager.injectComponent("listView", "actions", {
1244
- name: "i18n-locale-filter",
1245
- Component: LocalePicker
1246
- });
1247
- contentManager.injectComponent("listView", "publishModalAdditionalInfos", {
1248
- name: "i18n-publish-bullets-in-modal",
1249
- Component: PublishModalAdditionalInfo
1250
- });
1251
- contentManager.injectComponent("listView", "unpublishModalAdditionalInfos", {
1252
- name: "i18n-unpublish-bullets-in-modal",
1253
- Component: UnpublishModalAdditionalInfo
1254
- });
1255
- contentManager.injectComponent("listView", "deleteModalAdditionalInfos", {
1256
- name: "i18n-delete-bullets-in-modal",
1257
- Component: DeleteModalAdditionalInfo
1258
- });
1259
- const ctbPlugin = app.getPlugin("content-type-builder");
1260
- if (ctbPlugin) {
1261
- const ctbFormsAPI = ctbPlugin.apis.forms;
1262
- ctbFormsAPI.addContentTypeSchemaMutation(mutateCTBContentTypeSchema);
1263
- ctbFormsAPI.components.add({ id: "checkboxConfirmation", component: CheckboxConfirmation });
1264
- ctbFormsAPI.extendContentType({
1265
- validator: () => ({
1266
- i18n: yup.object().shape({
1267
- localized: yup.bool()
1268
- })
1269
- }),
1270
- form: {
1271
- advanced() {
1272
- return [
1273
- {
1274
- name: "pluginOptions.i18n.localized",
1275
- description: {
1276
- id: getTranslation("plugin.schema.i18n.localized.description-content-type"),
1277
- defaultMessage: "Allows translating an entry into different languages"
1278
- },
1279
- type: "checkboxConfirmation",
1280
- intlLabel: {
1281
- id: getTranslation("plugin.schema.i18n.localized.label-content-type"),
1282
- defaultMessage: "Localization"
1283
- }
1284
- }
1285
- ];
1286
- }
1287
- }
1288
- });
1289
- ctbFormsAPI.extendFields(LOCALIZED_FIELDS, {
1290
- validator: (args) => ({
1291
- i18n: yup.object().shape({
1292
- localized: yup.bool().test({
1293
- name: "ensure-unique-localization",
1294
- message: getTranslation("plugin.schema.i18n.ensure-unique-localization"),
1295
- test(value) {
1296
- if (value === void 0 || value) {
1297
- return true;
1298
- }
1299
- const unique = get(args, ["3", "modifiedData", "unique"], null);
1300
- if (unique && !value) {
1301
- return false;
1302
- }
1303
- return true;
1304
- }
1305
- })
1306
- })
1307
- }),
1308
- form: {
1309
- advanced({ contentTypeSchema, forTarget, type, step }) {
1310
- if (forTarget !== "contentType") {
1311
- return [];
1312
- }
1313
- const hasI18nEnabled = get(
1314
- contentTypeSchema,
1315
- ["schema", "pluginOptions", "i18n", "localized"],
1316
- false
1317
- );
1318
- if (!hasI18nEnabled) {
1319
- return [];
1320
- }
1321
- if (type === "component" && step === "1") {
1322
- return [];
1323
- }
1324
- return [
1325
- {
1326
- name: "pluginOptions.i18n.localized",
1327
- description: {
1328
- id: getTranslation("plugin.schema.i18n.localized.description-field"),
1329
- defaultMessage: "The field can have different values in each locale"
1330
- },
1331
- type: "checkbox",
1332
- intlLabel: {
1333
- id: getTranslation("plugin.schema.i18n.localized.label-field"),
1334
- defaultMessage: "Enable localization for this field"
1335
- }
1336
- }
1337
- ];
1338
- }
1339
- }
1340
- });
1341
- }
1342
- },
1343
- async registerTrads({ locales }) {
1344
- const importedTrads = await Promise.all(
1345
- 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 }) => {
1347
- return {
1348
- data: prefixPluginTranslations(data, pluginId),
1349
- locale
1350
- };
1351
- }).catch(() => {
1352
- return {
1353
- data: {},
1354
- locale
1355
- };
1356
- });
1357
- })
1358
- );
1359
- return Promise.resolve(importedTrads);
1360
- }
1361
- };
1362
- export {
1363
- PERMISSIONS as P,
1364
- useGetDefaultLocalesQuery as a,
1365
- useDeleteLocaleMutation as b,
1366
- useUpdateLocaleMutation as c,
1367
- useGetLocalesQuery as d,
1368
- getTranslation as g,
1369
- index as i,
1370
- useCreateLocaleMutation as u
1371
- };
1372
- //# sourceMappingURL=index-DhtjJYrx.mjs.map