@medusajs/dashboard 3.0.0-snapshot-20251215083939 → 3.0.0-snapshot-20251216103925

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 (115) hide show
  1. package/dist/{api-key-management-detail-7T6OT2S2.mjs → api-key-management-detail-NRGL7HHX.mjs} +1 -1
  2. package/dist/app.css +0 -8
  3. package/dist/app.js +197 -198
  4. package/dist/app.mjs +2 -2
  5. package/dist/{campaign-detail-RT3BIGQA.mjs → campaign-detail-22Q6XWGL.mjs} +1 -1
  6. package/dist/{categories-metadata-QHA62GA3.mjs → categories-metadata-J7M3XWI7.mjs} +1 -1
  7. package/dist/{category-detail-TDB4GR5S.mjs → category-detail-RRKJPMEG.mjs} +2 -2
  8. package/dist/{category-products-KRSKJDWS.mjs → category-products-EFZRTCSF.mjs} +2 -2
  9. package/dist/{chunk-WJKYXU6P.mjs → chunk-DK7IWUMK.mjs} +1 -1
  10. package/dist/{chunk-7ESWXA2P.mjs → chunk-GRZSG4EP.mjs} +31 -9
  11. package/dist/{chunk-P5TFUYGS.mjs → chunk-O7WJSSQR.mjs} +104 -98
  12. package/dist/{chunk-7ZJK3NWL.mjs → chunk-OHY2N2Q4.mjs} +2 -2
  13. package/dist/{chunk-QCRM6BTM.mjs → chunk-PHLCT2HA.mjs} +1 -1
  14. package/dist/{chunk-6EFHOMPL.mjs → chunk-RL5EYTP6.mjs} +1 -1
  15. package/dist/{chunk-SKA4MWCK.mjs → chunk-YYOPBKME.mjs} +1 -1
  16. package/dist/{chunk-QBDKK5O4.mjs → chunk-ZMG5B4FG.mjs} +1 -1
  17. package/dist/{collection-add-products-4RJKJ7XJ.mjs → collection-add-products-XUMV6XR7.mjs} +2 -2
  18. package/dist/{collection-detail-IR23ZT2F.mjs → collection-detail-ONRBKJLN.mjs} +2 -2
  19. package/dist/{collection-list-J4OTLQQL.mjs → collection-list-XCC4SIPJ.mjs} +2 -2
  20. package/dist/{collection-metadata-6XWOWMBN.mjs → collection-metadata-QK7MI3D2.mjs} +1 -1
  21. package/dist/{customer-detail-ZHU4NN7E.mjs → customer-detail-FR6J37ZC.mjs} +1 -1
  22. package/dist/{customer-group-detail-NGJXBGGG.mjs → customer-group-detail-YSKSNETG.mjs} +1 -1
  23. package/dist/{customer-group-list-YLAMT3ZQ.mjs → customer-group-list-XBCD4FZH.mjs} +1 -1
  24. package/dist/{customers-add-customer-group-A2EPZW26.mjs → customers-add-customer-group-Q7FMR2Y5.mjs} +1 -1
  25. package/dist/{edit-rules-4UN6YMCZ.mjs → edit-rules-SMVRTCUP.mjs} +1 -1
  26. package/dist/en.json +3 -0
  27. package/dist/{inventory-create-UB3TTWPQ.mjs → inventory-create-3XONKYMZ.mjs} +1 -1
  28. package/dist/{inventory-detail-FIC7BFZ7.mjs → inventory-detail-6A6GOLB6.mjs} +1 -1
  29. package/dist/{inventory-metadata-WP73FZBX.mjs → inventory-metadata-FNEJ3RAT.mjs} +1 -1
  30. package/dist/{inventory-stock-RR4F6HGF.mjs → inventory-stock-S3ZYYCMZ.mjs} +1 -1
  31. package/dist/{location-detail-MLYCXNYR.mjs → location-detail-N3GUZSY7.mjs} +1 -1
  32. package/dist/{location-fulfillment-providers-CAAUD5VG.mjs → location-fulfillment-providers-WM6DT252.mjs} +2 -2
  33. package/dist/{location-service-zone-shipping-option-create-HHEGEBVB.mjs → location-service-zone-shipping-option-create-MJPH3WKX.mjs} +1 -1
  34. package/dist/{login-C7GZL37K.mjs → login-VNOLI5YG.mjs} +1 -1
  35. package/dist/{order-create-claim-2RQ4SFKM.mjs → order-create-claim-GUYTLVPB.mjs} +1 -1
  36. package/dist/{order-create-edit-JL7FWVNC.mjs → order-create-edit-ODIN6GRW.mjs} +1 -1
  37. package/dist/{order-create-exchange-7EPUMDFZ.mjs → order-create-exchange-ZT5RBRKL.mjs} +1 -1
  38. package/dist/{order-create-fulfillment-5PUUSLCV.mjs → order-create-fulfillment-OWUVTZXW.mjs} +1 -1
  39. package/dist/{order-create-refund-3NYCD4UR.mjs → order-create-refund-Q6HQY42R.mjs} +1 -1
  40. package/dist/{order-create-shipment-PWT3BPP6.mjs → order-create-shipment-WAGGEPRW.mjs} +1 -1
  41. package/dist/{order-detail-CN7VCKHF.mjs → order-detail-HFJONELJ.mjs} +1 -1
  42. package/dist/{order-edit-billing-address-PLAKMBVH.mjs → order-edit-billing-address-UM76J4KX.mjs} +1 -1
  43. package/dist/{order-edit-email-UAP26F5X.mjs → order-edit-email-CL3KNOCM.mjs} +1 -1
  44. package/dist/{order-edit-shipping-address-HAC7UQZS.mjs → order-edit-shipping-address-PIESTGVL.mjs} +1 -1
  45. package/dist/{order-export-ZI4QK6OQ.mjs → order-export-4MZUPMGD.mjs} +1 -1
  46. package/dist/{order-metadata-VQJWKPQC.mjs → order-metadata-FHBB7MTG.mjs} +1 -1
  47. package/dist/{order-receive-return-VTHRRRAB.mjs → order-receive-return-PRVKP6J2.mjs} +1 -1
  48. package/dist/{order-request-transfer-MCWICULW.mjs → order-request-transfer-XSAGRUMT.mjs} +1 -1
  49. package/dist/{price-list-create-KF4BTDBF.mjs → price-list-create-YHXRQSC3.mjs} +2 -2
  50. package/dist/{price-list-detail-UHJWBRBT.mjs → price-list-detail-FR3FQR3H.mjs} +2 -2
  51. package/dist/{price-list-prices-add-YHPWWETC.mjs → price-list-prices-add-GJVI47OY.mjs} +2 -2
  52. package/dist/{product-attributes-CCRPVPA3.mjs → product-attributes-QD3BWV5V.mjs} +2 -2
  53. package/dist/{product-create-TIJWWJEC.mjs → product-create-E2GZYQX4.mjs} +2 -2
  54. package/dist/{product-create-variant-EBVDKJA2.mjs → product-create-variant-KEBN5OR7.mjs} +1 -1
  55. package/dist/{product-detail-MFRDWD74.mjs → product-detail-QBGGKRZ2.mjs} +2 -2
  56. package/dist/{product-edit-VRUDQ3JT.mjs → product-edit-YP4KOQ4T.mjs} +2 -2
  57. package/dist/{product-export-DZKMXMUX.mjs → product-export-WUZYHPS5.mjs} +2 -2
  58. package/dist/{product-image-variants-edit-NN76FX7Y.mjs → product-image-variants-edit-Y363J5NG.mjs} +1 -1
  59. package/dist/{product-import-24JJ73RO.mjs → product-import-V3KQN4TV.mjs} +1 -1
  60. package/dist/{product-list-YMCK3X7X.mjs → product-list-DNTS7WUN.mjs} +2 -2
  61. package/dist/{product-metadata-KFBUYD7A.mjs → product-metadata-GL2MVPDI.mjs} +1 -1
  62. package/dist/{product-organization-BYRWH4KK.mjs → product-organization-H557PLLB.mjs} +2 -2
  63. package/dist/{product-stock-YEHDIJQI.mjs → product-stock-NYUFMEVG.mjs} +1 -1
  64. package/dist/{product-tag-create-BPU54Y3F.mjs → product-tag-create-PQMDDKWH.mjs} +1 -1
  65. package/dist/{product-tag-detail-SYQWG3AL.mjs → product-tag-detail-EHBB3WUB.mjs} +3 -3
  66. package/dist/{product-tag-edit-5XEMIUW6.mjs → product-tag-edit-K3BBQLJR.mjs} +1 -1
  67. package/dist/{product-tag-list-7SQNKPJQ.mjs → product-tag-list-LSW5FFVN.mjs} +3 -3
  68. package/dist/{product-tag-metadata-ZB56PD4G.mjs → product-tag-metadata-MJH5LH7E.mjs} +1 -1
  69. package/dist/{product-type-detail-RMYDLMPI.mjs → product-type-detail-3VB6AWUW.mjs} +2 -2
  70. package/dist/{product-type-metadata-UKF26V3N.mjs → product-type-metadata-CDJDFFGQ.mjs} +1 -1
  71. package/dist/{product-variant-detail-56MJKJZQ.mjs → product-variant-detail-43T33AQP.mjs} +1 -1
  72. package/dist/{product-variant-edit-PVZNSIIQ.mjs → product-variant-edit-DEZEY2H2.mjs} +1 -1
  73. package/dist/{product-variant-metadata-PNFRS7SQ.mjs → product-variant-metadata-VTZDNWUT.mjs} +1 -1
  74. package/dist/{promotion-create-RGLB6D7K.mjs → promotion-create-HWFNUQXG.mjs} +1 -1
  75. package/dist/{promotion-detail-MCCRIT2M.mjs → promotion-detail-VJB55PJK.mjs} +1 -1
  76. package/dist/{refund-reason-create-JYY2USGC.mjs → refund-reason-create-YHCDEHGQ.mjs} +1 -1
  77. package/dist/{refund-reason-edit-5NFS4TQ7.mjs → refund-reason-edit-CZ5QZ2SZ.mjs} +1 -1
  78. package/dist/{refund-reason-list-SDLJWAV3.mjs → refund-reason-list-URYYYEK6.mjs} +1 -1
  79. package/dist/{region-metadata-YBOCBHWP.mjs → region-metadata-H6XXUQ4S.mjs} +1 -1
  80. package/dist/{reservation-detail-7MXAMP3C.mjs → reservation-detail-LZAQL4XA.mjs} +1 -1
  81. package/dist/{reservation-metadata-6NZUP64D.mjs → reservation-metadata-5HZSDDOK.mjs} +1 -1
  82. package/dist/{sales-channel-add-products-BELGXDPF.mjs → sales-channel-add-products-VH5T3GDA.mjs} +2 -2
  83. package/dist/{sales-channel-detail-FAGKAQK2.mjs → sales-channel-detail-I2ZHVXMG.mjs} +2 -2
  84. package/dist/{sales-channel-list-E5QO23E5.mjs → sales-channel-list-3FV4S2NN.mjs} +1 -1
  85. package/dist/{sales-channel-metadata-AXAQY4MY.mjs → sales-channel-metadata-M364R4RJ.mjs} +1 -1
  86. package/dist/{shipping-option-type-create-YTBF47L7.mjs → shipping-option-type-create-C5WUWON7.mjs} +1 -1
  87. package/dist/{shipping-option-type-detail-XJFVNP2V.mjs → shipping-option-type-detail-PENS2K73.mjs} +2 -2
  88. package/dist/{shipping-option-type-edit-DFXO32AG.mjs → shipping-option-type-edit-CIU5EHRP.mjs} +1 -1
  89. package/dist/{shipping-option-type-list-UI7ZTCO7.mjs → shipping-option-type-list-ZMZMXFME.mjs} +2 -2
  90. package/dist/{shipping-profile-metadata-FGZRQKNN.mjs → shipping-profile-metadata-75G2NNMA.mjs} +1 -1
  91. package/dist/{store-add-locales-3MSEBHQG.mjs → store-add-locales-IZOZP5C6.mjs} +1 -1
  92. package/dist/{store-detail-MLYFQGBC.mjs → store-detail-4IBAEVSD.mjs} +1 -1
  93. package/dist/{store-metadata-ITA6AL6H.mjs → store-metadata-CYXTVJUE.mjs} +1 -1
  94. package/dist/{tax-region-create-AXM2SE4T.mjs → tax-region-create-DWGL4EUT.mjs} +1 -1
  95. package/dist/{tax-region-detail-WFXSRH3U.mjs → tax-region-detail-O2T7BI3V.mjs} +5 -5
  96. package/dist/{tax-region-edit-CZ4EDU4K.mjs → tax-region-edit-EEVEEU2Q.mjs} +1 -1
  97. package/dist/{tax-region-province-detail-4B5GWCY7.mjs → tax-region-province-detail-2W7RXAM5.mjs} +5 -5
  98. package/dist/{tax-region-tax-override-create-GDDSUSHK.mjs → tax-region-tax-override-create-7IM4ZVPH.mjs} +3 -3
  99. package/dist/{tax-region-tax-override-edit-QXCSGDVG.mjs → tax-region-tax-override-edit-3ZT5IZYR.mjs} +4 -4
  100. package/dist/{translation-list-S4477JFR.mjs → translation-list-IAKEB7MY.mjs} +74 -85
  101. package/dist/{translations-edit-S3V7SSDA.mjs → translations-edit-QKLE4L5B.mjs} +27 -26
  102. package/dist/{user-metadata-SILGZHTG.mjs → user-metadata-2WPJOEJA.mjs} +1 -1
  103. package/dist/{workflow-execution-detail-GJTST4GO.mjs → workflow-execution-detail-H2AKEZJX.mjs} +1 -1
  104. package/package.json +9 -9
  105. package/src/hooks/api/translations.tsx +61 -31
  106. package/src/i18n/translations/$schema.json +12 -3
  107. package/src/i18n/translations/en.json +3 -0
  108. package/src/i18n/translations/es.json +3 -0
  109. package/src/routes/translations/translation-list/components/translation-list-section/translation-list-section.tsx +8 -10
  110. package/src/routes/translations/translation-list/components/translations-completion-section/translations-completion-section.tsx +16 -10
  111. package/src/routes/translations/translation-list/translation-list.tsx +71 -68
  112. package/src/routes/translations/translations-edit/components/translations-edit-form/translations-edit-form.tsx +7 -2
  113. package/src/routes/translations/translations-edit/translations-edit.tsx +27 -12
  114. package/src/routes/translations/translations-edit/utils/index.ts +0 -1
  115. package/src/routes/translations/translations-edit/utils/reference-label-map.ts +0 -10
@@ -7,7 +7,10 @@ import {
7
7
  import {
8
8
  TwoColumnPageSkeleton
9
9
  } from "./chunk-LPEUYMRK.mjs";
10
- import "./chunk-7ESWXA2P.mjs";
10
+ import {
11
+ useTranslationSettings,
12
+ useTranslationStatistics
13
+ } from "./chunk-GRZSG4EP.mjs";
11
14
  import "./chunk-I4OBEAOJ.mjs";
12
15
  import "./chunk-HI6URQ7H.mjs";
13
16
  import "./chunk-6CLQKVAU.mjs";
@@ -44,8 +47,7 @@ import "./chunk-QZ7TP4HQ.mjs";
44
47
 
45
48
  // src/routes/translations/translation-list/translation-list.tsx
46
49
  import { Container as Container4, Heading as Heading3, Text as Text4 } from "@medusajs/ui";
47
- import { useTranslation as useTranslation3 } from "react-i18next";
48
- import { Buildings } from "@medusajs/icons";
50
+ import { useTranslation as useTranslation4 } from "react-i18next";
49
51
 
50
52
  // src/routes/translations/translation-list/components/active-locales-section/active-locales-section.tsx
51
53
  import { PencilSquare, Language } from "@medusajs/icons";
@@ -88,24 +90,23 @@ var ActiveLocalesSection = ({
88
90
  // src/routes/translations/translation-list/components/translation-list-section/translation-list-section.tsx
89
91
  import { Button, Container as Container2, Text as Text2 } from "@medusajs/ui";
90
92
  import { Link } from "react-router-dom";
93
+ import { useTranslation as useTranslation2 } from "react-i18next";
91
94
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
92
95
  var TranslationListSection = ({
93
96
  entities,
94
97
  hasLocales = false
95
98
  }) => {
99
+ const { t } = useTranslation2();
96
100
  return /* @__PURE__ */ jsx2(Container2, { className: "divide-y p-0", children: entities.map((entity) => /* @__PURE__ */ jsxs2(
97
101
  "div",
98
102
  {
99
103
  className: "grid grid-cols-[250px_1fr_auto] items-center gap-x-4 px-6 py-4",
100
104
  children: [
101
105
  /* @__PURE__ */ jsx2(Text2, { size: "small", weight: "plus", children: entity.label }),
102
- /* @__PURE__ */ jsxs2(Text2, { size: "small", className: "text-ui-fg-subtle", children: [
103
- (entity.translatedCount ?? 0).toLocaleString(),
104
- " of",
105
- " ",
106
- (entity.totalCount ?? 0).toLocaleString(),
107
- " fields translated"
108
- ] }),
106
+ /* @__PURE__ */ jsx2(Text2, { size: "small", className: "text-ui-fg-subtle", children: t("translations.list.metrics", {
107
+ translated: (entity.translatedCount ?? 0).toLocaleString(),
108
+ total: (entity.totalCount ?? 0).toLocaleString()
109
+ }) }),
109
110
  /* @__PURE__ */ jsx2(
110
111
  Link,
111
112
  {
@@ -121,19 +122,25 @@ var TranslationListSection = ({
121
122
 
122
123
  // src/routes/translations/translation-list/components/translations-completion-section/translations-completion-section.tsx
123
124
  import { Container as Container3, Heading as Heading2, Text as Text3 } from "@medusajs/ui";
124
- import { useTranslation as useTranslation2 } from "react-i18next";
125
+ import { useTranslation as useTranslation3 } from "react-i18next";
125
126
  import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
126
127
  var TranslationsCompletionSection = ({
127
- translatedCount = 0,
128
- totalCount = 0
128
+ statistics
129
129
  }) => {
130
- const { t } = useTranslation2();
130
+ const { t } = useTranslation3();
131
+ const { translatedCount, totalCount } = Object.values(statistics).reduce(
132
+ (acc, curr) => ({
133
+ translatedCount: acc.translatedCount + curr.translated,
134
+ totalCount: acc.totalCount + curr.expected
135
+ }),
136
+ { totalCount: 0, translatedCount: 0 }
137
+ );
131
138
  const percentage = totalCount > 0 ? translatedCount / totalCount * 100 : 0;
132
139
  const remaining = Math.max(0, totalCount - translatedCount);
133
140
  return /* @__PURE__ */ jsxs3(Container3, { className: "flex flex-col gap-y-3 px-6 py-4", children: [
134
141
  /* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-between", children: [
135
142
  /* @__PURE__ */ jsx3(Heading2, { children: t("translations.completion.heading") }),
136
- /* @__PURE__ */ jsxs3(Text3, { size: "small", className: "text-ui-fg-subtle", children: [
143
+ /* @__PURE__ */ jsxs3(Text3, { size: "small", weight: "plus", className: "text-ui-fg-subtle", children: [
137
144
  translatedCount.toLocaleString(),
138
145
  " ",
139
146
  t("general.of"),
@@ -141,11 +148,11 @@ var TranslationsCompletionSection = ({
141
148
  totalCount.toLocaleString()
142
149
  ] })
143
150
  ] }),
144
- /* @__PURE__ */ jsx3("div", { className: "flex h-2 w-full overflow-hidden rounded-full", children: percentage > 0 ? /* @__PURE__ */ jsxs3(Fragment, { children: [
151
+ /* @__PURE__ */ jsx3("div", { className: "flex h-3 w-full overflow-hidden", children: percentage > 0 ? /* @__PURE__ */ jsxs3(Fragment, { children: [
145
152
  /* @__PURE__ */ jsx3(
146
153
  "div",
147
154
  {
148
- className: "mr-0.5 h-full rounded-l-full transition-all",
155
+ className: "mr-0.5 h-full rounded-sm transition-all",
149
156
  style: {
150
157
  width: `${percentage}%`,
151
158
  backgroundColor: "var(--bg-interactive)"
@@ -155,7 +162,7 @@ var TranslationsCompletionSection = ({
155
162
  /* @__PURE__ */ jsx3(
156
163
  "div",
157
164
  {
158
- className: "h-full flex-1 rounded-r-full",
165
+ className: "h-full flex-1 rounded-sm",
159
166
  style: {
160
167
  backgroundColor: "var(--bg-interactive)",
161
168
  opacity: 0.3
@@ -173,11 +180,11 @@ var TranslationsCompletionSection = ({
173
180
  }
174
181
  ) }),
175
182
  /* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-between", children: [
176
- /* @__PURE__ */ jsxs3(Text3, { size: "small", className: "text-ui-fg-subtle", children: [
183
+ /* @__PURE__ */ jsxs3(Text3, { size: "small", weight: "plus", className: "text-ui-fg-subtle", children: [
177
184
  percentage.toFixed(1),
178
185
  "%"
179
186
  ] }),
180
- /* @__PURE__ */ jsxs3(Text3, { size: "small", className: "text-ui-fg-subtle", children: [
187
+ /* @__PURE__ */ jsxs3(Text3, { size: "small", weight: "plus", className: "text-ui-fg-subtle", children: [
181
188
  remaining.toLocaleString(),
182
189
  " ",
183
190
  t("general.remaining").toLowerCase()
@@ -187,76 +194,58 @@ var TranslationsCompletionSection = ({
187
194
  };
188
195
 
189
196
  // src/routes/translations/translation-list/translation-list.tsx
197
+ import { useMemo } from "react";
190
198
  import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
191
- var TRANSLATABLE_ENTITIES = [
192
- {
193
- icon: /* @__PURE__ */ jsx4(Buildings, {}),
194
- label: "Product",
195
- reference: "product",
196
- translatedCount: 4,
197
- totalCount: 96
198
- },
199
- {
200
- icon: /* @__PURE__ */ jsx4(Buildings, {}),
201
- label: "Product Variants",
202
- reference: "product_variant",
203
- translatedCount: 4,
204
- totalCount: 2e5
205
- },
206
- {
207
- icon: /* @__PURE__ */ jsx4(Buildings, {}),
208
- label: "Product Categories",
209
- reference: "product_category",
210
- translatedCount: 96,
211
- totalCount: 96
212
- },
213
- {
214
- icon: /* @__PURE__ */ jsx4(Buildings, {}),
215
- label: "Product Collections",
216
- reference: "product_collection",
217
- translatedCount: 4,
218
- totalCount: 96
219
- },
220
- {
221
- icon: /* @__PURE__ */ jsx4(Buildings, {}),
222
- label: "Product Types",
223
- reference: "product_type",
224
- translatedCount: 4,
225
- totalCount: 96
226
- },
227
- {
228
- icon: /* @__PURE__ */ jsx4(Buildings, {}),
229
- label: "Product Tags",
230
- reference: "product_tag",
231
- translatedCount: 96,
232
- totalCount: 96
233
- },
234
- {
235
- icon: /* @__PURE__ */ jsx4(Buildings, {}),
236
- label: "Product Options",
237
- reference: "product_option",
238
- translatedCount: 96,
239
- totalCount: 96
240
- },
241
- {
242
- icon: /* @__PURE__ */ jsx4(Buildings, {}),
243
- label: "Product Option Values",
244
- reference: "product_option_value",
245
- translatedCount: 96,
246
- totalCount: 96
247
- }
248
- ];
249
199
  var TranslationList = () => {
250
- const { t } = useTranslation3();
200
+ const { t } = useTranslation4();
251
201
  const { store, isPending, isError, error } = useStore();
252
- if (isError) {
253
- throw error;
202
+ const {
203
+ translatable_fields,
204
+ isPending: isTranslationSettingsPending,
205
+ isError: isTranslationSettingsError,
206
+ error: translationSettingsError
207
+ } = useTranslationSettings();
208
+ const {
209
+ statistics,
210
+ isPending: isTranslationStatisticsPending,
211
+ isError: isTranslationStatisticsError,
212
+ error: translationStatisticsError
213
+ } = useTranslationStatistics(
214
+ {
215
+ locales: store?.supported_locales?.map(
216
+ (suportedLocale) => suportedLocale.locale_code
217
+ ) ?? [],
218
+ entity_types: Object.keys(translatable_fields ?? {})
219
+ },
220
+ {
221
+ enabled: !!translatable_fields && !!store
222
+ }
223
+ );
224
+ if (isError || isTranslationSettingsError || isTranslationStatisticsError) {
225
+ throw error || translationSettingsError || translationStatisticsError;
254
226
  }
255
- const isReady = !!store && !isPending;
227
+ const hasLocales = (store?.supported_locales ?? []).length > 0;
228
+ const translatableEntities = useMemo(() => {
229
+ if (!translatable_fields || !statistics) {
230
+ return [];
231
+ }
232
+ return Object.entries(translatable_fields).filter(
233
+ ([entity]) => !["product_option", "product_option_value"].includes(entity)
234
+ ).map(([entity, fields]) => {
235
+ const entityStatistics = statistics[entity];
236
+ return {
237
+ label: entity.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" "),
238
+ reference: entity,
239
+ translatableFields: fields,
240
+ translatedCount: entityStatistics.translated,
241
+ totalCount: entityStatistics.expected
242
+ };
243
+ });
244
+ }, [translatable_fields, statistics]);
245
+ const isReady = !!store && !isPending && !isTranslationSettingsPending && !isTranslationStatisticsPending && !!translatable_fields && !!statistics;
256
246
  if (!isReady) {
257
247
  return /* @__PURE__ */ jsx4(TwoColumnPageSkeleton, { sidebarSections: 2 });
258
248
  }
259
- const hasLocales = (store?.supported_locales ?? []).length > 0;
260
249
  return /* @__PURE__ */ jsxs4(
261
250
  TwoColumnPage,
262
251
  {
@@ -278,7 +267,7 @@ var TranslationList = () => {
278
267
  /* @__PURE__ */ jsx4(
279
268
  TranslationListSection,
280
269
  {
281
- entities: TRANSLATABLE_ENTITIES,
270
+ entities: translatableEntities,
282
271
  hasLocales
283
272
  }
284
273
  )
@@ -292,7 +281,7 @@ var TranslationList = () => {
292
281
  ) ?? []
293
282
  }
294
283
  ),
295
- /* @__PURE__ */ jsx4(TranslationsCompletionSection, {})
284
+ statistics && /* @__PURE__ */ jsx4(TranslationsCompletionSection, { statistics })
296
285
  ] })
297
286
  ]
298
287
  }
@@ -23,8 +23,9 @@ import {
23
23
  import "./chunk-OBQI23QM.mjs";
24
24
  import {
25
25
  useBatchTranslations,
26
- useReferenceTranslations
27
- } from "./chunk-7ESWXA2P.mjs";
26
+ useReferenceTranslations,
27
+ useTranslationSettings
28
+ } from "./chunk-GRZSG4EP.mjs";
28
29
  import "./chunk-I4OBEAOJ.mjs";
29
30
  import "./chunk-HI6URQ7H.mjs";
30
31
  import "./chunk-6CLQKVAU.mjs";
@@ -69,20 +70,6 @@ import { useMemo, useRef } from "react";
69
70
  import { useForm } from "react-hook-form";
70
71
  import { useTranslation } from "react-i18next";
71
72
  import { z } from "zod";
72
-
73
- // src/routes/translations/translations-edit/utils/reference-label-map.ts
74
- var REFERENCE_LABEL_MAP = {
75
- product: "Products",
76
- product_variant: "Product Variants",
77
- product_category: "Product Categories",
78
- product_collection: "Product Collections",
79
- product_type: "Product Types",
80
- product_tag: "Product Tags",
81
- product_option: "Product Options",
82
- product_option_value: "Product Option Values"
83
- };
84
-
85
- // src/routes/translations/translations-edit/components/translations-edit-form/translations-edit-form.tsx
86
73
  import { jsx, jsxs } from "react/jsx-runtime";
87
74
  var LocaleTranslationSchema = z.object({
88
75
  id: z.string().nullish(),
@@ -204,7 +191,9 @@ function useTranslationsGridColumns({
204
191
  columnHelper.column({
205
192
  id: "original",
206
193
  name: "original",
194
+ size: 300,
207
195
  header: t("general.original"),
196
+ disableHiding: true,
208
197
  cell: (context) => {
209
198
  const row = context.row.original;
210
199
  if (isEntityRow(row)) {
@@ -223,6 +212,7 @@ function useTranslationsGridColumns({
223
212
  return columnHelper.column({
224
213
  id: locale.locale_code,
225
214
  name: locale.locale.name,
215
+ size: 300,
226
216
  header: () => locale.locale.name,
227
217
  cell: (context) => {
228
218
  const row = context.row.original;
@@ -361,7 +351,7 @@ var TranslationsEditForm = ({
361
351
  defaultValue: entityType,
362
352
  className: "flex h-full flex-col overflow-hidden",
363
353
  children: [
364
- /* @__PURE__ */ jsx(RouteFocusModal.Header, { children: /* @__PURE__ */ jsx("div", { className: "-my-2 w-full border-l", children: /* @__PURE__ */ jsx(ProgressTabs.List, { className: "justify-start-start flex w-full items-center", children: /* @__PURE__ */ jsx(ProgressTabs.Trigger, { value: entityType, children: REFERENCE_LABEL_MAP[entityType] }) }) }) }),
354
+ /* @__PURE__ */ jsx(RouteFocusModal.Header, { children: /* @__PURE__ */ jsx("div", { className: "-my-2 w-full border-l", children: /* @__PURE__ */ jsx(ProgressTabs.List, { className: "justify-start-start flex w-full items-center", children: /* @__PURE__ */ jsx(ProgressTabs.Trigger, { value: entityType, children: entityType.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ") }) }) }) }),
365
355
  /* @__PURE__ */ jsx(RouteFocusModal.Body, { className: "size-full overflow-hidden", children: /* @__PURE__ */ jsx(
366
356
  ProgressTabs.Content,
367
357
  {
@@ -412,10 +402,15 @@ var TranslationsEdit = () => {
412
402
  return;
413
403
  }
414
404
  }, [reference, navigate, isTranslationsEnabled]);
405
+ const {
406
+ translatable_fields,
407
+ isPending: isTranslationSettingsPending,
408
+ isError: isTranslationSettingsError,
409
+ error: translationSettingsError
410
+ } = useTranslationSettings({ entity_type: reference });
415
411
  const {
416
412
  translations,
417
413
  references,
418
- translatableFields,
419
414
  fetchNextPage,
420
415
  count,
421
416
  isFetchingNextPage,
@@ -423,18 +418,24 @@ var TranslationsEdit = () => {
423
418
  isPending,
424
419
  isError,
425
420
  error
426
- } = useReferenceTranslations(reference, referenceIdParam, {
427
- placeholderData: keepPreviousData
428
- });
421
+ } = useReferenceTranslations(
422
+ reference,
423
+ translatable_fields?.[reference] ?? [],
424
+ referenceIdParam,
425
+ {
426
+ enabled: !!translatable_fields && !!reference,
427
+ placeholderData: keepPreviousData
428
+ }
429
+ );
429
430
  const {
430
431
  store,
431
432
  isPending: isStorePending,
432
433
  isError: isStoreError,
433
434
  error: storeError
434
435
  } = useStore();
435
- const ready = !isPending && !!translations && !!translatableFields && !!references && !isStorePending && !!store;
436
- if (isError || isStoreError) {
437
- throw error || storeError;
436
+ const ready = !isPending && !!translations && !!translatable_fields && !isTranslationSettingsPending && !!references && !isStorePending && !!store;
437
+ if (isError || isStoreError || isTranslationSettingsError) {
438
+ throw error || storeError || translationSettingsError;
438
439
  }
439
440
  return /* @__PURE__ */ jsx2(RouteFocusModal, { prev: referenceIdParam.length ? -1 : "..", children: ready && /* @__PURE__ */ jsx2(
440
441
  TranslationsEditForm,
@@ -443,8 +444,8 @@ var TranslationsEdit = () => {
443
444
  references,
444
445
  entityType: reference,
445
446
  availableLocales: store?.supported_locales ?? [],
446
- translatableFields,
447
- modalFields: translatableFields,
447
+ translatableFields: translatable_fields[reference],
448
+ modalFields: translatable_fields[reference],
448
449
  fetchNextPage,
449
450
  hasNextPage,
450
451
  isFetchingNextPage,
@@ -12,7 +12,7 @@ import "./chunk-LPEUYMRK.mjs";
12
12
  import "./chunk-OC7BQLYI.mjs";
13
13
  import "./chunk-S4DMV3ZT.mjs";
14
14
  import "./chunk-OBQI23QM.mjs";
15
- import "./chunk-7ESWXA2P.mjs";
15
+ import "./chunk-GRZSG4EP.mjs";
16
16
  import "./chunk-I4OBEAOJ.mjs";
17
17
  import "./chunk-HI6URQ7H.mjs";
18
18
  import "./chunk-6CLQKVAU.mjs";
@@ -20,7 +20,7 @@ import {
20
20
  import {
21
21
  useDocumentDirection
22
22
  } from "./chunk-S4DMV3ZT.mjs";
23
- import "./chunk-7ESWXA2P.mjs";
23
+ import "./chunk-GRZSG4EP.mjs";
24
24
  import "./chunk-I4OBEAOJ.mjs";
25
25
  import "./chunk-HI6URQ7H.mjs";
26
26
  import "./chunk-6CLQKVAU.mjs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@medusajs/dashboard",
3
- "version": "3.0.0-snapshot-20251215083939",
3
+ "version": "3.0.0-snapshot-20251216103925",
4
4
  "scripts": {
5
5
  "generate:static": "node ./scripts/generate-currencies.js && prettier --write ./src/lib/currencies.ts",
6
6
  "dev": "../../../node_modules/.bin/vite",
@@ -46,10 +46,10 @@
46
46
  "@dnd-kit/utilities": "^3.2.2",
47
47
  "@hookform/error-message": "^2.0.1",
48
48
  "@hookform/resolvers": "3.4.2",
49
- "@medusajs/admin-shared": "3.0.0-snapshot-20251215083939",
50
- "@medusajs/icons": "3.0.0-snapshot-20251215083939",
51
- "@medusajs/js-sdk": "3.0.0-snapshot-20251215083939",
52
- "@medusajs/ui": "4.0.31-snapshot-20251215083939",
49
+ "@medusajs/admin-shared": "3.0.0-snapshot-20251216103925",
50
+ "@medusajs/icons": "3.0.0-snapshot-20251216103925",
51
+ "@medusajs/js-sdk": "3.0.0-snapshot-20251216103925",
52
+ "@medusajs/ui": "4.0.31-snapshot-20251216103925",
53
53
  "@radix-ui/react-dialog": "1.1.4",
54
54
  "@radix-ui/react-dismissable-layer": "1.1.4",
55
55
  "@tanstack/react-query": "5.64.2",
@@ -80,10 +80,10 @@
80
80
  "zod": "3.25.76"
81
81
  },
82
82
  "devDependencies": {
83
- "@medusajs/admin-shared": "3.0.0-snapshot-20251215083939",
84
- "@medusajs/admin-vite-plugin": "3.0.0-snapshot-20251215083939",
85
- "@medusajs/types": "3.0.0-snapshot-20251215083939",
86
- "@medusajs/ui-preset": "3.0.0-snapshot-20251215083939"
83
+ "@medusajs/admin-shared": "3.0.0-snapshot-20251216103925",
84
+ "@medusajs/admin-vite-plugin": "3.0.0-snapshot-20251216103925",
85
+ "@medusajs/types": "3.0.0-snapshot-20251216103925",
86
+ "@medusajs/ui-preset": "3.0.0-snapshot-20251216103925"
87
87
  },
88
88
  "packageManager": "yarn@3.2.1"
89
89
  }
@@ -8,43 +8,36 @@ import {
8
8
  UseMutationOptions,
9
9
  useQuery,
10
10
  UseQueryOptions,
11
- UseQueryResult,
12
11
  } from "@tanstack/react-query"
13
12
  import { sdk } from "../../lib/client"
14
13
  import { queryKeysFactory } from "../../lib/query-key-factory"
15
14
  import { queryClient } from "../../lib/query-client"
16
- import { productsQueryKeys, useInfiniteProducts, useProducts } from "./products"
15
+ import { productsQueryKeys, useInfiniteProducts } from "./products"
17
16
  import {
18
17
  productVariantQueryKeys,
19
18
  useInfiniteVariants,
20
- useVariants,
21
19
  } from "./product-variants"
22
- import {
23
- categoriesQueryKeys,
24
- useInfiniteCategories,
25
- useProductCategories,
26
- } from "./categories"
27
- import {
28
- collectionsQueryKeys,
29
- useCollections,
30
- useInfiniteCollections,
31
- } from "./collections"
32
- import {
33
- productTagsQueryKeys,
34
- useInfiniteProductTags,
35
- useProductTags,
36
- } from "./tags"
37
- import {
38
- productTypesQueryKeys,
39
- useInfiniteProductTypes,
40
- useProductTypes,
41
- } from "./product-types"
20
+ import { categoriesQueryKeys, useInfiniteCategories } from "./categories"
21
+ import { collectionsQueryKeys, useInfiniteCollections } from "./collections"
22
+ import { productTagsQueryKeys, useInfiniteProductTags } from "./tags"
23
+ import { productTypesQueryKeys, useInfiniteProductTypes } from "./product-types"
42
24
 
43
25
  const TRANSLATIONS_QUERY_KEY = "translations" as const
44
26
  export const translationsQueryKeys = queryKeysFactory(TRANSLATIONS_QUERY_KEY)
45
27
 
28
+ const TRANSLATION_SETTINGS_QUERY_KEY = "translation_settings" as const
29
+ export const translationSettingsQueryKeys = queryKeysFactory(
30
+ TRANSLATION_SETTINGS_QUERY_KEY
31
+ )
32
+
33
+ const TRANSLATION_STATISTICS_QUERY_KEY = "translation_statistics" as const
34
+ export const translationStatisticsQueryKeys = queryKeysFactory(
35
+ TRANSLATION_STATISTICS_QUERY_KEY
36
+ )
37
+
46
38
  export const useReferenceTranslations = (
47
39
  reference: string,
40
+ translatableFields: string[],
48
41
  referenceId?: string | string[],
49
42
  options?: Omit<
50
43
  UseInfiniteQueryOptions<any, FetchError, any, any, QueryKey, number>,
@@ -57,7 +50,6 @@ export const useReferenceTranslations = (
57
50
  data: {
58
51
  translations: HttpTypes.AdminTranslation[]
59
52
  references: (Record<string, any> & { id: string })[]
60
- translatableFields: string[]
61
53
  count: number
62
54
  }
63
55
  }
@@ -65,7 +57,6 @@ export const useReferenceTranslations = (
65
57
  [
66
58
  "product",
67
59
  () => {
68
- const translatableFields = ["title", "description"]
69
60
  const fields = translatableFields.concat(["translations.*"]).join(",")
70
61
 
71
62
  const { data, ...rest } = useInfiniteProducts(
@@ -80,7 +71,6 @@ export const useReferenceTranslations = (
80
71
  translations:
81
72
  products?.flatMap((product) => product.translations ?? []) ?? [],
82
73
  references: products ?? [],
83
- translatableFields,
84
74
  count: data?.pages[0]?.count ?? 0,
85
75
  },
86
76
  }
@@ -89,7 +79,6 @@ export const useReferenceTranslations = (
89
79
  [
90
80
  "product_variant",
91
81
  () => {
92
- const translatableFields = ["title"]
93
82
  const fields = translatableFields.concat(["translations.*"]).join(",")
94
83
 
95
84
  const { data, ...rest } = useInfiniteVariants(
@@ -113,7 +102,6 @@ export const useReferenceTranslations = (
113
102
  [
114
103
  "product_category",
115
104
  () => {
116
- const translatableFields = ["name", "description"]
117
105
  const fields = translatableFields.concat(["translations.*"]).join(",")
118
106
 
119
107
  const { data, ...rest } = useInfiniteCategories(
@@ -139,7 +127,6 @@ export const useReferenceTranslations = (
139
127
  [
140
128
  "product_collection",
141
129
  () => {
142
- const translatableFields = ["title"]
143
130
  const fields = translatableFields.concat(["translations.*"]).join(",")
144
131
 
145
132
  const { data, ...rest } = useInfiniteCollections(
@@ -166,7 +153,6 @@ export const useReferenceTranslations = (
166
153
  [
167
154
  "product_type",
168
155
  () => {
169
- const translatableFields = ["value"]
170
156
  const fields = translatableFields.concat(["translations.*"]).join(",")
171
157
 
172
158
  const { data, ...rest } = useInfiniteProductTypes(
@@ -191,7 +177,6 @@ export const useReferenceTranslations = (
191
177
  [
192
178
  "product_tag",
193
179
  () => {
194
- const translatableFields = ["value"]
195
180
  const fields = translatableFields.concat(["translations.*"]).join(",")
196
181
 
197
182
  const { data, ...rest } = useInfiniteProductTags(
@@ -268,9 +253,54 @@ export const useBatchTranslations = (
268
253
  queryClient.invalidateQueries({
269
254
  queryKey: referenceInvalidationKeysMap.get(reference),
270
255
  })
256
+ queryClient.invalidateQueries({
257
+ queryKey: translationStatisticsQueryKeys.lists(),
258
+ })
271
259
 
272
260
  options?.onSuccess?.(data, variables, context)
273
261
  },
274
262
  ...options,
275
263
  })
276
264
  }
265
+
266
+ export const useTranslationSettings = (
267
+ query?: HttpTypes.AdminTranslationSettingsParams,
268
+ options?: Omit<
269
+ UseQueryOptions<
270
+ HttpTypes.AdminTranslationSettingsResponse,
271
+ FetchError,
272
+ HttpTypes.AdminTranslationSettingsResponse,
273
+ QueryKey
274
+ >,
275
+ "queryFn" | "queryKey"
276
+ >
277
+ ) => {
278
+ const { data, ...rest } = useQuery({
279
+ queryKey: translationSettingsQueryKeys.list(query),
280
+ queryFn: () => sdk.admin.translation.settings(query),
281
+ ...options,
282
+ })
283
+
284
+ return { ...data, ...rest }
285
+ }
286
+
287
+ export const useTranslationStatistics = (
288
+ query?: HttpTypes.AdminTranslationStatisticsParams,
289
+ options?: Omit<
290
+ UseQueryOptions<
291
+ HttpTypes.AdminTranslationStatisticsResponse,
292
+ FetchError,
293
+ HttpTypes.AdminTranslationStatisticsResponse,
294
+ QueryKey
295
+ >,
296
+ "queryFn" | "queryKey"
297
+ >
298
+ ) => {
299
+ const { data, ...rest } = useQuery({
300
+ queryKey: translationStatisticsQueryKeys.list(query),
301
+ queryFn: () => sdk.admin.translation.statistics(query),
302
+ ...options,
303
+ })
304
+
305
+ return { ...data, ...rest }
306
+ }
@@ -39,7 +39,7 @@
39
39
  "type": "string"
40
40
  },
41
41
  "original": {
42
- "type": "string"
42
+ "type": "string"
43
43
  },
44
44
  "of": {
45
45
  "type": "string"
@@ -108,7 +108,7 @@
108
108
  "type": "string"
109
109
  },
110
110
  "remaining": {
111
- "type": "string"
111
+ "type": "string"
112
112
  },
113
113
  "admin": {
114
114
  "type": "string"
@@ -9345,6 +9345,15 @@
9345
9345
  "subtitle": {
9346
9346
  "type": "string"
9347
9347
  },
9348
+ "list": {
9349
+ "type": "object",
9350
+ "properties": {
9351
+ "metrics": {
9352
+ "type": "string"
9353
+ }
9354
+ },
9355
+ "required": ["metrics"]
9356
+ },
9348
9357
  "actions": {
9349
9358
  "type": "object",
9350
9359
  "properties": {
@@ -9392,7 +9401,7 @@
9392
9401
  }
9393
9402
  },
9394
9403
  "required": ["heading"]
9395
- },
9404
+ }
9396
9405
  },
9397
9406
  "required": ["domain", "actions", "subtitle", "bulk", "completion"]
9398
9407
  },
@@ -2514,6 +2514,9 @@
2514
2514
  },
2515
2515
  "title": "Translation domains",
2516
2516
  "subtitle": "Manage translations of your data in Medusa",
2517
+ "list": {
2518
+ "metrics": "{{translated}} of {{total}} fields translated"
2519
+ },
2517
2520
  "bulk": {
2518
2521
  "header": "Translations Bulk Editor",
2519
2522
  "mainColumn": "Locale"
@@ -2447,6 +2447,9 @@
2447
2447
  },
2448
2448
  "translations": {
2449
2449
  "domain": "Traducciones",
2450
+ "list": {
2451
+ "metrics": "{{translated}} de {{total}} textos traducidos"
2452
+ },
2450
2453
  "actions": {
2451
2454
  "manage": "Gestionar traducciones",
2452
2455
  "manageLocales": "Gestionar idiomas"