@strapi/i18n 0.0.0-next.8f63e1055db761e0213cb6610f80c55658196ae1 → 0.0.0-next.913e7071c9410ff8af2e776e25f9fb1c38cb59dd

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 (422) hide show
  1. package/dist/admin/components/BulkLocaleActionModal.js +262 -0
  2. package/dist/admin/components/BulkLocaleActionModal.js.map +1 -0
  3. package/dist/admin/components/BulkLocaleActionModal.mjs +260 -0
  4. package/dist/admin/components/BulkLocaleActionModal.mjs.map +1 -0
  5. package/dist/admin/components/CMHeaderActions.js +836 -0
  6. package/dist/admin/components/CMHeaderActions.js.map +1 -0
  7. package/dist/admin/components/CMHeaderActions.mjs +810 -0
  8. package/dist/admin/components/CMHeaderActions.mjs.map +1 -0
  9. package/dist/admin/components/CMListViewModalsAdditionalInformation.js +69 -0
  10. package/dist/admin/components/CMListViewModalsAdditionalInformation.js.map +1 -0
  11. package/dist/admin/components/CMListViewModalsAdditionalInformation.mjs +65 -0
  12. package/dist/admin/components/CMListViewModalsAdditionalInformation.mjs.map +1 -0
  13. package/dist/admin/components/CheckboxConfirmation.js +155 -0
  14. package/dist/admin/components/CheckboxConfirmation.js.map +1 -0
  15. package/dist/admin/components/CheckboxConfirmation.mjs +134 -0
  16. package/dist/admin/components/CheckboxConfirmation.mjs.map +1 -0
  17. package/dist/admin/components/CreateLocale.js +395 -0
  18. package/dist/admin/components/CreateLocale.js.map +1 -0
  19. package/dist/admin/components/CreateLocale.mjs +369 -0
  20. package/dist/admin/components/CreateLocale.mjs.map +1 -0
  21. package/dist/admin/components/DeleteLocale.js +90 -0
  22. package/dist/admin/components/DeleteLocale.js.map +1 -0
  23. package/dist/admin/components/DeleteLocale.mjs +69 -0
  24. package/dist/admin/components/DeleteLocale.mjs.map +1 -0
  25. package/dist/admin/components/EditLocale.js +212 -0
  26. package/dist/admin/components/EditLocale.js.map +1 -0
  27. package/dist/admin/components/EditLocale.mjs +190 -0
  28. package/dist/admin/components/EditLocale.mjs.map +1 -0
  29. package/dist/admin/components/LocaleListCell.js +102 -0
  30. package/dist/admin/components/LocaleListCell.js.map +1 -0
  31. package/dist/admin/components/LocaleListCell.mjs +100 -0
  32. package/dist/admin/components/LocaleListCell.mjs.map +1 -0
  33. package/dist/admin/components/LocalePicker.js +105 -0
  34. package/dist/admin/components/LocalePicker.js.map +1 -0
  35. package/dist/admin/components/LocalePicker.mjs +84 -0
  36. package/dist/admin/components/LocalePicker.mjs.map +1 -0
  37. package/dist/admin/components/LocaleTable.js +143 -0
  38. package/dist/admin/components/LocaleTable.js.map +1 -0
  39. package/dist/admin/components/LocaleTable.mjs +122 -0
  40. package/dist/admin/components/LocaleTable.mjs.map +1 -0
  41. package/dist/admin/constants.js +37 -0
  42. package/dist/admin/constants.js.map +1 -0
  43. package/dist/admin/constants.mjs +35 -0
  44. package/dist/admin/constants.mjs.map +1 -0
  45. package/dist/admin/contentManagerHooks/editView.js +109 -0
  46. package/dist/admin/contentManagerHooks/editView.js.map +1 -0
  47. package/dist/admin/contentManagerHooks/editView.mjs +88 -0
  48. package/dist/admin/contentManagerHooks/editView.mjs.map +1 -0
  49. package/dist/admin/contentManagerHooks/listView.js +44 -0
  50. package/dist/admin/contentManagerHooks/listView.js.map +1 -0
  51. package/dist/admin/contentManagerHooks/listView.mjs +42 -0
  52. package/dist/admin/contentManagerHooks/listView.mjs.map +1 -0
  53. package/dist/admin/contentReleasesHooks/releaseDetailsView.js +20 -0
  54. package/dist/admin/contentReleasesHooks/releaseDetailsView.js.map +1 -0
  55. package/dist/admin/contentReleasesHooks/releaseDetailsView.mjs +18 -0
  56. package/dist/admin/contentReleasesHooks/releaseDetailsView.mjs.map +1 -0
  57. package/dist/admin/hooks/useI18n.js +78 -0
  58. package/dist/admin/hooks/useI18n.js.map +1 -0
  59. package/dist/admin/hooks/useI18n.mjs +57 -0
  60. package/dist/admin/hooks/useI18n.mjs.map +1 -0
  61. package/dist/admin/index.js +226 -5
  62. package/dist/admin/index.js.map +1 -1
  63. package/dist/admin/index.mjs +202 -5
  64. package/dist/admin/index.mjs.map +1 -1
  65. package/dist/admin/middlewares/extendCTBAttributeInitialData.js +71 -0
  66. package/dist/admin/middlewares/extendCTBAttributeInitialData.js.map +1 -0
  67. package/dist/admin/middlewares/extendCTBAttributeInitialData.mjs +69 -0
  68. package/dist/admin/middlewares/extendCTBAttributeInitialData.mjs.map +1 -0
  69. package/dist/admin/middlewares/extendCTBInitialData.js +40 -0
  70. package/dist/admin/middlewares/extendCTBInitialData.js.map +1 -0
  71. package/dist/admin/middlewares/extendCTBInitialData.mjs +38 -0
  72. package/dist/admin/middlewares/extendCTBInitialData.mjs.map +1 -0
  73. package/dist/admin/middlewares/rbac-middleware.js +49 -0
  74. package/dist/admin/middlewares/rbac-middleware.js.map +1 -0
  75. package/dist/admin/middlewares/rbac-middleware.mjs +28 -0
  76. package/dist/admin/middlewares/rbac-middleware.mjs.map +1 -0
  77. package/dist/admin/pages/SettingsPage.js +182 -0
  78. package/dist/admin/pages/SettingsPage.js.map +1 -0
  79. package/dist/admin/pages/SettingsPage.mjs +179 -0
  80. package/dist/admin/pages/SettingsPage.mjs.map +1 -0
  81. package/dist/admin/pluginId.js +6 -0
  82. package/dist/admin/pluginId.js.map +1 -0
  83. package/dist/admin/pluginId.mjs +4 -0
  84. package/dist/admin/pluginId.mjs.map +1 -0
  85. package/dist/admin/services/api.js +14 -0
  86. package/dist/admin/services/api.js.map +1 -0
  87. package/dist/admin/services/api.mjs +12 -0
  88. package/dist/admin/services/api.mjs.map +1 -0
  89. package/dist/admin/services/locales.js +72 -0
  90. package/dist/admin/services/locales.js.map +1 -0
  91. package/dist/admin/services/locales.mjs +66 -0
  92. package/dist/admin/services/locales.mjs.map +1 -0
  93. package/dist/admin/services/relations.js +23 -0
  94. package/dist/admin/services/relations.js.map +1 -0
  95. package/dist/admin/services/relations.mjs +21 -0
  96. package/dist/admin/services/relations.mjs.map +1 -0
  97. package/dist/admin/services/settings.js +29 -0
  98. package/dist/admin/services/settings.js.map +1 -0
  99. package/dist/admin/services/settings.mjs +26 -0
  100. package/dist/admin/services/settings.mjs.map +1 -0
  101. package/dist/admin/src/components/CMHeaderActions.d.ts +8 -2
  102. package/dist/admin/src/components/LocaleListCell.d.ts +5 -4
  103. package/dist/admin/src/components/tests/CreateLocale.test.d.ts +1 -0
  104. package/dist/admin/src/components/tests/DeleteLocale.test.d.ts +1 -0
  105. package/dist/admin/src/components/tests/EditLocale.test.d.ts +1 -0
  106. package/dist/admin/src/components/tests/LocaleListCell.test.d.ts +1 -0
  107. package/dist/admin/src/contentReleasesHooks/releaseDetailsView.d.ts +1 -1
  108. package/dist/admin/src/pages/tests/SettingsPage.test.d.ts +1 -0
  109. package/dist/admin/src/services/api.d.ts +1 -1
  110. package/dist/admin/src/services/locales.d.ts +1 -1
  111. package/dist/admin/src/services/relations.d.ts +1 -1
  112. package/dist/admin/src/services/settings.d.ts +5 -0
  113. package/dist/admin/src/utils/schemas.d.ts +642 -16
  114. package/dist/admin/tests/server.d.ts +1 -0
  115. package/dist/admin/tests/utils.d.ts +6 -0
  116. package/dist/admin/translations/de.json.js +66 -0
  117. package/dist/admin/translations/de.json.js.map +1 -0
  118. package/dist/admin/translations/de.json.mjs +64 -0
  119. package/dist/admin/translations/de.json.mjs.map +1 -0
  120. package/dist/admin/translations/dk.json.js +66 -0
  121. package/dist/admin/translations/dk.json.js.map +1 -0
  122. package/dist/admin/translations/dk.json.mjs +64 -0
  123. package/dist/admin/translations/dk.json.mjs.map +1 -0
  124. package/dist/admin/translations/en.json.js +88 -0
  125. package/dist/admin/translations/en.json.js.map +1 -0
  126. package/dist/admin/translations/en.json.mjs +86 -0
  127. package/dist/admin/translations/en.json.mjs.map +1 -0
  128. package/dist/admin/translations/es.json.js +66 -0
  129. package/dist/admin/translations/es.json.js.map +1 -0
  130. package/dist/admin/translations/es.json.mjs +64 -0
  131. package/dist/admin/translations/es.json.mjs.map +1 -0
  132. package/dist/admin/translations/fr.json.js +66 -0
  133. package/dist/admin/translations/fr.json.js.map +1 -0
  134. package/dist/admin/translations/fr.json.mjs +64 -0
  135. package/dist/admin/translations/fr.json.mjs.map +1 -0
  136. package/dist/admin/translations/ko.json.js +65 -0
  137. package/dist/admin/translations/ko.json.js.map +1 -0
  138. package/dist/admin/translations/ko.json.mjs +63 -0
  139. package/dist/admin/translations/ko.json.mjs.map +1 -0
  140. package/dist/admin/translations/pl.json.js +66 -0
  141. package/dist/admin/translations/pl.json.js.map +1 -0
  142. package/dist/admin/translations/pl.json.mjs +64 -0
  143. package/dist/admin/translations/pl.json.mjs.map +1 -0
  144. package/dist/admin/translations/ru.json.js +68 -0
  145. package/dist/admin/translations/ru.json.js.map +1 -0
  146. package/dist/admin/translations/ru.json.mjs +66 -0
  147. package/dist/admin/translations/ru.json.mjs.map +1 -0
  148. package/dist/admin/translations/tr.json.js +66 -0
  149. package/dist/admin/translations/tr.json.js.map +1 -0
  150. package/dist/admin/translations/tr.json.mjs +64 -0
  151. package/dist/admin/translations/tr.json.mjs.map +1 -0
  152. package/dist/admin/translations/uk.json.js +82 -0
  153. package/dist/admin/translations/uk.json.js.map +1 -0
  154. package/dist/admin/translations/uk.json.mjs +80 -0
  155. package/dist/admin/translations/uk.json.mjs.map +1 -0
  156. package/dist/admin/translations/zh-Hans.json.js +57 -0
  157. package/dist/admin/translations/zh-Hans.json.js.map +1 -0
  158. package/dist/admin/translations/zh-Hans.json.mjs +55 -0
  159. package/dist/admin/translations/zh-Hans.json.mjs.map +1 -0
  160. package/dist/admin/translations/zh.json.js +66 -0
  161. package/dist/admin/translations/zh.json.js.map +1 -0
  162. package/dist/admin/translations/zh.json.mjs +64 -0
  163. package/dist/admin/translations/zh.json.mjs.map +1 -0
  164. package/dist/admin/utils/baseQuery.js +8 -0
  165. package/dist/admin/utils/baseQuery.js.map +1 -0
  166. package/dist/admin/utils/baseQuery.mjs +6 -0
  167. package/dist/admin/utils/baseQuery.mjs.map +1 -0
  168. package/dist/admin/utils/clean.js +70 -0
  169. package/dist/admin/utils/clean.js.map +1 -0
  170. package/dist/admin/utils/clean.mjs +68 -0
  171. package/dist/admin/utils/clean.mjs.map +1 -0
  172. package/dist/admin/utils/fields.js +34 -0
  173. package/dist/admin/utils/fields.js.map +1 -0
  174. package/dist/admin/utils/fields.mjs +31 -0
  175. package/dist/admin/utils/fields.mjs.map +1 -0
  176. package/dist/admin/utils/getTranslation.js +8 -0
  177. package/dist/admin/utils/getTranslation.js.map +1 -0
  178. package/dist/admin/utils/getTranslation.mjs +6 -0
  179. package/dist/admin/utils/getTranslation.mjs.map +1 -0
  180. package/dist/admin/utils/prefixPluginTranslations.js +11 -0
  181. package/dist/admin/utils/prefixPluginTranslations.js.map +1 -0
  182. package/dist/admin/utils/prefixPluginTranslations.mjs +9 -0
  183. package/dist/admin/utils/prefixPluginTranslations.mjs.map +1 -0
  184. package/dist/admin/utils/schemas.js +74 -0
  185. package/dist/admin/utils/schemas.js.map +1 -0
  186. package/dist/admin/utils/schemas.mjs +72 -0
  187. package/dist/admin/utils/schemas.mjs.map +1 -0
  188. package/dist/admin/utils/strings.js +6 -0
  189. package/dist/admin/utils/strings.js.map +1 -0
  190. package/dist/admin/utils/strings.mjs +4 -0
  191. package/dist/admin/utils/strings.mjs.map +1 -0
  192. package/dist/server/bootstrap.js +79 -0
  193. package/dist/server/bootstrap.js.map +1 -0
  194. package/dist/server/bootstrap.mjs +77 -0
  195. package/dist/server/bootstrap.mjs.map +1 -0
  196. package/dist/server/constants/index.js +29 -0
  197. package/dist/server/constants/index.js.map +1 -0
  198. package/dist/server/constants/index.mjs +25 -0
  199. package/dist/server/constants/index.mjs.map +1 -0
  200. package/dist/server/constants/iso-locales.json.js +2427 -0
  201. package/dist/server/constants/iso-locales.json.js.map +1 -0
  202. package/dist/server/constants/iso-locales.json.mjs +2425 -0
  203. package/dist/server/constants/iso-locales.json.mjs.map +1 -0
  204. package/dist/server/content-types/index.js +10 -0
  205. package/dist/server/content-types/index.js.map +1 -0
  206. package/dist/server/content-types/index.mjs +8 -0
  207. package/dist/server/content-types/index.mjs.map +1 -0
  208. package/dist/server/content-types/locale/index.js +10 -0
  209. package/dist/server/content-types/locale/index.js.map +1 -0
  210. package/dist/server/content-types/locale/index.mjs +8 -0
  211. package/dist/server/content-types/locale/index.mjs.map +1 -0
  212. package/dist/server/content-types/locale/schema.json.js +46 -0
  213. package/dist/server/content-types/locale/schema.json.js.map +1 -0
  214. package/dist/server/content-types/locale/schema.json.mjs +38 -0
  215. package/dist/server/content-types/locale/schema.json.mjs.map +1 -0
  216. package/dist/server/controllers/content-types.js +76 -0
  217. package/dist/server/controllers/content-types.js.map +1 -0
  218. package/dist/server/controllers/content-types.mjs +74 -0
  219. package/dist/server/controllers/content-types.mjs.map +1 -0
  220. package/dist/server/controllers/index.js +16 -0
  221. package/dist/server/controllers/index.js.map +1 -0
  222. package/dist/server/controllers/index.mjs +14 -0
  223. package/dist/server/controllers/index.mjs.map +1 -0
  224. package/dist/server/controllers/iso-locales.js +13 -0
  225. package/dist/server/controllers/iso-locales.js.map +1 -0
  226. package/dist/server/controllers/iso-locales.mjs +11 -0
  227. package/dist/server/controllers/iso-locales.mjs.map +1 -0
  228. package/dist/server/controllers/locales.js +108 -0
  229. package/dist/server/controllers/locales.js.map +1 -0
  230. package/dist/server/controllers/locales.mjs +87 -0
  231. package/dist/server/controllers/locales.mjs.map +1 -0
  232. package/dist/server/controllers/settings.js +24 -0
  233. package/dist/server/controllers/settings.js.map +1 -0
  234. package/dist/server/controllers/settings.mjs +22 -0
  235. package/dist/server/controllers/settings.mjs.map +1 -0
  236. package/dist/server/controllers/validate-locale-creation.js +47 -0
  237. package/dist/server/controllers/validate-locale-creation.js.map +1 -0
  238. package/dist/server/controllers/validate-locale-creation.mjs +45 -0
  239. package/dist/server/controllers/validate-locale-creation.mjs.map +1 -0
  240. package/dist/server/domain/locale.js +11 -0
  241. package/dist/server/domain/locale.js.map +1 -0
  242. package/dist/server/domain/locale.mjs +9 -0
  243. package/dist/server/domain/locale.mjs.map +1 -0
  244. package/dist/server/graphql.js +115 -0
  245. package/dist/server/graphql.js.map +1 -0
  246. package/dist/server/graphql.mjs +113 -0
  247. package/dist/server/graphql.mjs.map +1 -0
  248. package/dist/server/index.js +18 -3453
  249. package/dist/server/index.js.map +1 -1
  250. package/dist/server/index.mjs +17 -3435
  251. package/dist/server/index.mjs.map +1 -1
  252. package/dist/server/register.js +79 -0
  253. package/dist/server/register.js.map +1 -0
  254. package/dist/server/register.mjs +77 -0
  255. package/dist/server/register.mjs.map +1 -0
  256. package/dist/server/routes/admin.js +122 -0
  257. package/dist/server/routes/admin.js.map +1 -0
  258. package/dist/server/routes/admin.mjs +120 -0
  259. package/dist/server/routes/admin.mjs.map +1 -0
  260. package/dist/server/routes/content-api.js +19 -0
  261. package/dist/server/routes/content-api.js.map +1 -0
  262. package/dist/server/routes/content-api.mjs +17 -0
  263. package/dist/server/routes/content-api.mjs.map +1 -0
  264. package/dist/server/routes/index.js +12 -0
  265. package/dist/server/routes/index.js.map +1 -0
  266. package/dist/server/routes/index.mjs +10 -0
  267. package/dist/server/routes/index.mjs.map +1 -0
  268. package/dist/server/routes/validation/locale.js +57 -0
  269. package/dist/server/routes/validation/locale.js.map +1 -0
  270. package/dist/server/routes/validation/locale.mjs +36 -0
  271. package/dist/server/routes/validation/locale.mjs.map +1 -0
  272. package/dist/server/services/ai-localizations.js +143 -0
  273. package/dist/server/services/ai-localizations.js.map +1 -0
  274. package/dist/server/services/ai-localizations.mjs +141 -0
  275. package/dist/server/services/ai-localizations.mjs.map +1 -0
  276. package/dist/server/services/content-types.js +157 -0
  277. package/dist/server/services/content-types.js.map +1 -0
  278. package/dist/server/services/content-types.mjs +155 -0
  279. package/dist/server/services/content-types.mjs.map +1 -0
  280. package/dist/server/services/index.js +26 -0
  281. package/dist/server/services/index.js.map +1 -0
  282. package/dist/server/services/index.mjs +24 -0
  283. package/dist/server/services/index.mjs.map +1 -0
  284. package/dist/server/services/iso-locales.js +12 -0
  285. package/dist/server/services/iso-locales.js.map +1 -0
  286. package/dist/server/services/iso-locales.mjs +10 -0
  287. package/dist/server/services/iso-locales.mjs.map +1 -0
  288. package/dist/server/services/locales.js +114 -0
  289. package/dist/server/services/locales.js.map +1 -0
  290. package/dist/server/services/locales.mjs +112 -0
  291. package/dist/server/services/locales.mjs.map +1 -0
  292. package/dist/server/services/localizations.js +68 -0
  293. package/dist/server/services/localizations.js.map +1 -0
  294. package/dist/server/services/localizations.mjs +66 -0
  295. package/dist/server/services/localizations.mjs.map +1 -0
  296. package/dist/server/services/metrics.js +30 -0
  297. package/dist/server/services/metrics.js.map +1 -0
  298. package/dist/server/services/metrics.mjs +28 -0
  299. package/dist/server/services/metrics.mjs.map +1 -0
  300. package/dist/server/services/permissions/actions.js +136 -0
  301. package/dist/server/services/permissions/actions.js.map +1 -0
  302. package/dist/server/services/permissions/actions.mjs +134 -0
  303. package/dist/server/services/permissions/actions.mjs.map +1 -0
  304. package/dist/server/services/permissions/engine.js +52 -0
  305. package/dist/server/services/permissions/engine.js.map +1 -0
  306. package/dist/server/services/permissions/engine.mjs +50 -0
  307. package/dist/server/services/permissions/engine.mjs.map +1 -0
  308. package/dist/server/services/permissions/sections-builder.js +45 -0
  309. package/dist/server/services/permissions/sections-builder.js.map +1 -0
  310. package/dist/server/services/permissions/sections-builder.mjs +43 -0
  311. package/dist/server/services/permissions/sections-builder.mjs.map +1 -0
  312. package/dist/server/services/permissions.js +14 -0
  313. package/dist/server/services/permissions.js.map +1 -0
  314. package/dist/server/services/permissions.mjs +12 -0
  315. package/dist/server/services/permissions.mjs.map +1 -0
  316. package/dist/server/services/sanitize/index.js +34 -0
  317. package/dist/server/services/sanitize/index.js.map +1 -0
  318. package/dist/server/services/sanitize/index.mjs +32 -0
  319. package/dist/server/services/sanitize/index.mjs.map +1 -0
  320. package/dist/server/services/settings.js +25 -0
  321. package/dist/server/services/settings.js.map +1 -0
  322. package/dist/server/services/settings.mjs +23 -0
  323. package/dist/server/services/settings.mjs.map +1 -0
  324. package/dist/server/src/controllers/index.d.ts +4 -0
  325. package/dist/server/src/controllers/index.d.ts.map +1 -1
  326. package/dist/server/src/controllers/settings.d.ts +7 -0
  327. package/dist/server/src/controllers/settings.d.ts.map +1 -0
  328. package/dist/server/src/index.d.ts +26 -7
  329. package/dist/server/src/index.d.ts.map +1 -1
  330. package/dist/server/src/routes/admin.d.ts.map +1 -1
  331. package/dist/server/src/routes/content-api.d.ts +5 -8
  332. package/dist/server/src/routes/content-api.d.ts.map +1 -1
  333. package/dist/server/src/routes/index.d.ts +3 -7
  334. package/dist/server/src/routes/index.d.ts.map +1 -1
  335. package/dist/server/src/routes/validation/index.d.ts +2 -0
  336. package/dist/server/src/routes/validation/index.d.ts.map +1 -0
  337. package/dist/server/src/routes/validation/locale.d.ts +41 -0
  338. package/dist/server/src/routes/validation/locale.d.ts.map +1 -0
  339. package/dist/server/src/services/ai-localizations.d.ts +17 -0
  340. package/dist/server/src/services/ai-localizations.d.ts.map +1 -0
  341. package/dist/server/src/services/index.d.ts +19 -0
  342. package/dist/server/src/services/index.d.ts.map +1 -1
  343. package/dist/server/src/services/localizations.d.ts +1 -1
  344. package/dist/server/src/services/localizations.d.ts.map +1 -1
  345. package/dist/server/src/services/settings.d.ts +13 -0
  346. package/dist/server/src/services/settings.d.ts.map +1 -0
  347. package/dist/server/src/utils/index.d.ts +5 -1
  348. package/dist/server/src/utils/index.d.ts.map +1 -1
  349. package/dist/server/src/validation/settings.d.ts +12 -0
  350. package/dist/server/src/validation/settings.d.ts.map +1 -0
  351. package/dist/server/utils/index.js +16 -0
  352. package/dist/server/utils/index.js.map +1 -0
  353. package/dist/server/utils/index.mjs +13 -0
  354. package/dist/server/utils/index.mjs.map +1 -0
  355. package/dist/server/validation/content-types.js +18 -0
  356. package/dist/server/validation/content-types.js.map +1 -0
  357. package/dist/server/validation/content-types.mjs +16 -0
  358. package/dist/server/validation/content-types.mjs.map +1 -0
  359. package/dist/server/validation/locales.js +23 -0
  360. package/dist/server/validation/locales.js.map +1 -0
  361. package/dist/server/validation/locales.mjs +20 -0
  362. package/dist/server/validation/locales.mjs.map +1 -0
  363. package/dist/server/validation/settings.js +11 -0
  364. package/dist/server/validation/settings.js.map +1 -0
  365. package/dist/server/validation/settings.mjs +9 -0
  366. package/dist/server/validation/settings.mjs.map +1 -0
  367. package/dist/shared/contracts/content-manager.d.ts +1 -1
  368. package/dist/shared/contracts/settings.d.ts +40 -0
  369. package/dist/shared/contracts/shared.d.ts +1 -1
  370. package/package.json +20 -16
  371. package/dist/_chunks/SettingsPage-BHvunuIF.mjs +0 -554
  372. package/dist/_chunks/SettingsPage-BHvunuIF.mjs.map +0 -1
  373. package/dist/_chunks/SettingsPage-Bcj7380u.js +0 -574
  374. package/dist/_chunks/SettingsPage-Bcj7380u.js.map +0 -1
  375. package/dist/_chunks/de-9eCAqqrB.mjs +0 -66
  376. package/dist/_chunks/de-9eCAqqrB.mjs.map +0 -1
  377. package/dist/_chunks/de-DtWiGdHl.js +0 -66
  378. package/dist/_chunks/de-DtWiGdHl.js.map +0 -1
  379. package/dist/_chunks/dk-2qBjxt-P.mjs +0 -66
  380. package/dist/_chunks/dk-2qBjxt-P.mjs.map +0 -1
  381. package/dist/_chunks/dk-D8C-casx.js +0 -66
  382. package/dist/_chunks/dk-D8C-casx.js.map +0 -1
  383. package/dist/_chunks/en-BKBz3tro.js +0 -81
  384. package/dist/_chunks/en-BKBz3tro.js.map +0 -1
  385. package/dist/_chunks/en-DlXfy6Gy.mjs +0 -81
  386. package/dist/_chunks/en-DlXfy6Gy.mjs.map +0 -1
  387. package/dist/_chunks/es-DS-XFGSw.js +0 -66
  388. package/dist/_chunks/es-DS-XFGSw.js.map +0 -1
  389. package/dist/_chunks/es-DlmMVaBG.mjs +0 -66
  390. package/dist/_chunks/es-DlmMVaBG.mjs.map +0 -1
  391. package/dist/_chunks/fr-3S6ke71d.mjs +0 -66
  392. package/dist/_chunks/fr-3S6ke71d.mjs.map +0 -1
  393. package/dist/_chunks/fr-BTjekDpq.js +0 -66
  394. package/dist/_chunks/fr-BTjekDpq.js.map +0 -1
  395. package/dist/_chunks/index-BKZbxhpm.js +0 -1637
  396. package/dist/_chunks/index-BKZbxhpm.js.map +0 -1
  397. package/dist/_chunks/index-DUdrr5PR.mjs +0 -1615
  398. package/dist/_chunks/index-DUdrr5PR.mjs.map +0 -1
  399. package/dist/_chunks/ko-DmcGUBQ3.js +0 -65
  400. package/dist/_chunks/ko-DmcGUBQ3.js.map +0 -1
  401. package/dist/_chunks/ko-qTjQ8IMw.mjs +0 -65
  402. package/dist/_chunks/ko-qTjQ8IMw.mjs.map +0 -1
  403. package/dist/_chunks/pl-B67TSHqT.mjs +0 -66
  404. package/dist/_chunks/pl-B67TSHqT.mjs.map +0 -1
  405. package/dist/_chunks/pl-Cn5RYonZ.js +0 -66
  406. package/dist/_chunks/pl-Cn5RYonZ.js.map +0 -1
  407. package/dist/_chunks/ru-BMBgVL3s.js +0 -68
  408. package/dist/_chunks/ru-BMBgVL3s.js.map +0 -1
  409. package/dist/_chunks/ru-hagMa57T.mjs +0 -68
  410. package/dist/_chunks/ru-hagMa57T.mjs.map +0 -1
  411. package/dist/_chunks/tr-CarUU76c.js +0 -66
  412. package/dist/_chunks/tr-CarUU76c.js.map +0 -1
  413. package/dist/_chunks/tr-Dw_jmkG-.mjs +0 -66
  414. package/dist/_chunks/tr-Dw_jmkG-.mjs.map +0 -1
  415. package/dist/_chunks/zh-57YM4amO.mjs +0 -66
  416. package/dist/_chunks/zh-57YM4amO.mjs.map +0 -1
  417. package/dist/_chunks/zh-CukOviB0.js +0 -66
  418. package/dist/_chunks/zh-CukOviB0.js.map +0 -1
  419. package/dist/_chunks/zh-Hans-DSHIXAa3.js +0 -57
  420. package/dist/_chunks/zh-Hans-DSHIXAa3.js.map +0 -1
  421. package/dist/_chunks/zh-Hans-Dyc-aR-h.mjs +0 -57
  422. package/dist/_chunks/zh-Hans-Dyc-aR-h.mjs.map +0 -1
@@ -0,0 +1,19 @@
1
+ 'use strict';
2
+
3
+ var utils = require('@strapi/utils');
4
+ var locale = require('./validation/locale.js');
5
+
6
+ const createContentApiRoutes = utils.createContentApiRoutesFactory(()=>{
7
+ const validator = new locale.I18nLocaleRouteValidator(strapi);
8
+ return [
9
+ {
10
+ method: 'GET',
11
+ path: '/locales',
12
+ handler: 'locales.listLocales',
13
+ response: validator.locales
14
+ }
15
+ ];
16
+ });
17
+
18
+ module.exports = createContentApiRoutes;
19
+ //# sourceMappingURL=content-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-api.js","sources":["../../../server/src/routes/content-api.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\nimport { createContentApiRoutesFactory } from '@strapi/utils';\nimport { I18nLocaleRouteValidator } from './validation';\n\nconst createContentApiRoutes = createContentApiRoutesFactory((): Core.RouterInput['routes'] => {\n const validator = new I18nLocaleRouteValidator(strapi);\n return [\n {\n method: 'GET',\n path: '/locales',\n handler: 'locales.listLocales',\n response: validator.locales,\n },\n ];\n});\n\nexport default createContentApiRoutes;\n"],"names":["createContentApiRoutes","createContentApiRoutesFactory","validator","I18nLocaleRouteValidator","strapi","method","path","handler","response","locales"],"mappings":";;;;;AAIA,MAAMA,yBAAyBC,mCAA8B,CAAA,IAAA;IAC3D,MAAMC,SAAAA,GAAY,IAAIC,+BAAyBC,CAAAA,MAAAA,CAAAA;IAC/C,OAAO;AACL,QAAA;YACEC,MAAQ,EAAA,KAAA;YACRC,IAAM,EAAA,UAAA;YACNC,OAAS,EAAA,qBAAA;AACTC,YAAAA,QAAAA,EAAUN,UAAUO;AACtB;AACD,KAAA;AACH,CAAA;;;;"}
@@ -0,0 +1,17 @@
1
+ import { createContentApiRoutesFactory } from '@strapi/utils';
2
+ import { I18nLocaleRouteValidator } from './validation/locale.mjs';
3
+
4
+ const createContentApiRoutes = createContentApiRoutesFactory(()=>{
5
+ const validator = new I18nLocaleRouteValidator(strapi);
6
+ return [
7
+ {
8
+ method: 'GET',
9
+ path: '/locales',
10
+ handler: 'locales.listLocales',
11
+ response: validator.locales
12
+ }
13
+ ];
14
+ });
15
+
16
+ export { createContentApiRoutes as default };
17
+ //# sourceMappingURL=content-api.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-api.mjs","sources":["../../../server/src/routes/content-api.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\nimport { createContentApiRoutesFactory } from '@strapi/utils';\nimport { I18nLocaleRouteValidator } from './validation';\n\nconst createContentApiRoutes = createContentApiRoutesFactory((): Core.RouterInput['routes'] => {\n const validator = new I18nLocaleRouteValidator(strapi);\n return [\n {\n method: 'GET',\n path: '/locales',\n handler: 'locales.listLocales',\n response: validator.locales,\n },\n ];\n});\n\nexport default createContentApiRoutes;\n"],"names":["createContentApiRoutes","createContentApiRoutesFactory","validator","I18nLocaleRouteValidator","strapi","method","path","handler","response","locales"],"mappings":";;;AAIA,MAAMA,yBAAyBC,6BAA8B,CAAA,IAAA;IAC3D,MAAMC,SAAAA,GAAY,IAAIC,wBAAyBC,CAAAA,MAAAA,CAAAA;IAC/C,OAAO;AACL,QAAA;YACEC,MAAQ,EAAA,KAAA;YACRC,IAAM,EAAA,UAAA;YACNC,OAAS,EAAA,qBAAA;AACTC,YAAAA,QAAAA,EAAUN,UAAUO;AACtB;AACD,KAAA;AACH,CAAA;;;;"}
@@ -0,0 +1,12 @@
1
+ 'use strict';
2
+
3
+ var admin = require('./admin.js');
4
+ var contentApi = require('./content-api.js');
5
+
6
+ var routes = {
7
+ admin,
8
+ 'content-api': contentApi
9
+ };
10
+
11
+ module.exports = routes;
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../../server/src/routes/index.ts"],"sourcesContent":["import admin from './admin';\nimport contentApi from './content-api';\n\nexport default {\n admin,\n 'content-api': contentApi,\n};\n"],"names":["admin","contentApi"],"mappings":";;;;;AAGA,aAAe;AACbA,IAAAA,KAAAA;IACA,aAAeC,EAAAA;AACjB,CAAE;;;;"}
@@ -0,0 +1,10 @@
1
+ import admin from './admin.mjs';
2
+ import createContentApiRoutes from './content-api.mjs';
3
+
4
+ var routes = {
5
+ admin,
6
+ 'content-api': createContentApiRoutes
7
+ };
8
+
9
+ export { routes as default };
10
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../../../server/src/routes/index.ts"],"sourcesContent":["import admin from './admin';\nimport contentApi from './content-api';\n\nexport default {\n admin,\n 'content-api': contentApi,\n};\n"],"names":["admin","contentApi"],"mappings":";;;AAGA,aAAe;AACbA,IAAAA,KAAAA;IACA,aAAeC,EAAAA;AACjB,CAAE;;;;"}
@@ -0,0 +1,57 @@
1
+ 'use strict';
2
+
3
+ var z = require('zod/v4');
4
+
5
+ function _interopNamespaceDefault(e) {
6
+ var n = Object.create(null);
7
+ if (e) {
8
+ Object.keys(e).forEach(function (k) {
9
+ if (k !== 'default') {
10
+ var d = Object.getOwnPropertyDescriptor(e, k);
11
+ Object.defineProperty(n, k, d.get ? d : {
12
+ enumerable: true,
13
+ get: function () { return e[k]; }
14
+ });
15
+ }
16
+ });
17
+ }
18
+ n.default = e;
19
+ return Object.freeze(n);
20
+ }
21
+
22
+ var z__namespace = /*#__PURE__*/_interopNamespaceDefault(z);
23
+
24
+ /**
25
+ * A validator for i18n locale routes.
26
+ *
27
+ */ class I18nLocaleRouteValidator {
28
+ /**
29
+ * Generates a validation schema for a single locale.
30
+ *
31
+ * @returns A schema for validating locale objects
32
+ */ get locale() {
33
+ return z__namespace.object({
34
+ id: z__namespace.number().int().positive(),
35
+ documentId: z__namespace.string().uuid(),
36
+ name: z__namespace.string(),
37
+ code: z__namespace.string().length(2, 'Locale code must be exactly 2 characters'),
38
+ createdAt: z__namespace.string(),
39
+ updatedAt: z__namespace.string(),
40
+ publishedAt: z__namespace.string().nullable(),
41
+ isDefault: z__namespace.boolean()
42
+ });
43
+ }
44
+ /**
45
+ * Generates a validation schema for an array of locales
46
+ *
47
+ * @returns A schema for validating arrays of locales
48
+ */ get locales() {
49
+ return z__namespace.array(this.locale);
50
+ }
51
+ constructor(strapi){
52
+ this._strapi = strapi;
53
+ }
54
+ }
55
+
56
+ exports.I18nLocaleRouteValidator = I18nLocaleRouteValidator;
57
+ //# sourceMappingURL=locale.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locale.js","sources":["../../../../server/src/routes/validation/locale.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\nimport * as z from 'zod/v4';\n\n/**\n * A validator for i18n locale routes.\n *\n */\nexport class I18nLocaleRouteValidator {\n protected readonly _strapi: Core.Strapi;\n\n public constructor(strapi: Core.Strapi) {\n this._strapi = strapi;\n }\n\n /**\n * Generates a validation schema for a single locale.\n *\n * @returns A schema for validating locale objects\n */\n get locale() {\n return z.object({\n id: z.number().int().positive(),\n documentId: z.string().uuid(),\n name: z.string(),\n code: z.string().length(2, 'Locale code must be exactly 2 characters'),\n createdAt: z.string(),\n updatedAt: z.string(),\n publishedAt: z.string().nullable(),\n isDefault: z.boolean(),\n });\n }\n\n /**\n * Generates a validation schema for an array of locales\n *\n * @returns A schema for validating arrays of locales\n */\n get locales() {\n return z.array(this.locale);\n }\n}\n"],"names":["I18nLocaleRouteValidator","locale","z","object","id","number","int","positive","documentId","string","uuid","name","code","length","createdAt","updatedAt","publishedAt","nullable","isDefault","boolean","locales","array","strapi","_strapi"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAGA;;;AAGC,IACM,MAAMA,wBAAAA,CAAAA;AAOX;;;;AAIC,MACD,IAAIC,MAAS,GAAA;QACX,OAAOC,YAAAA,CAAEC,MAAM,CAAC;AACdC,YAAAA,EAAAA,EAAIF,YAAEG,CAAAA,MAAM,EAAGC,CAAAA,GAAG,GAAGC,QAAQ,EAAA;YAC7BC,UAAYN,EAAAA,YAAAA,CAAEO,MAAM,EAAA,CAAGC,IAAI,EAAA;AAC3BC,YAAAA,IAAAA,EAAMT,aAAEO,MAAM,EAAA;AACdG,YAAAA,IAAAA,EAAMV,YAAEO,CAAAA,MAAM,EAAGI,CAAAA,MAAM,CAAC,CAAG,EAAA,0CAAA,CAAA;AAC3BC,YAAAA,SAAAA,EAAWZ,aAAEO,MAAM,EAAA;AACnBM,YAAAA,SAAAA,EAAWb,aAAEO,MAAM,EAAA;YACnBO,WAAad,EAAAA,YAAAA,CAAEO,MAAM,EAAA,CAAGQ,QAAQ,EAAA;AAChCC,YAAAA,SAAAA,EAAWhB,aAAEiB,OAAO;AACtB,SAAA,CAAA;AACF;AAEA;;;;AAIC,MACD,IAAIC,OAAU,GAAA;AACZ,QAAA,OAAOlB,YAAEmB,CAAAA,KAAK,CAAC,IAAI,CAACpB,MAAM,CAAA;AAC5B;AA7BA,IAAA,WAAA,CAAmBqB,MAAmB,CAAE;QACtC,IAAI,CAACC,OAAO,GAAGD,MAAAA;AACjB;AA4BF;;;;"}
@@ -0,0 +1,36 @@
1
+ import * as z from 'zod/v4';
2
+
3
+ /**
4
+ * A validator for i18n locale routes.
5
+ *
6
+ */ class I18nLocaleRouteValidator {
7
+ /**
8
+ * Generates a validation schema for a single locale.
9
+ *
10
+ * @returns A schema for validating locale objects
11
+ */ get locale() {
12
+ return z.object({
13
+ id: z.number().int().positive(),
14
+ documentId: z.string().uuid(),
15
+ name: z.string(),
16
+ code: z.string().length(2, 'Locale code must be exactly 2 characters'),
17
+ createdAt: z.string(),
18
+ updatedAt: z.string(),
19
+ publishedAt: z.string().nullable(),
20
+ isDefault: z.boolean()
21
+ });
22
+ }
23
+ /**
24
+ * Generates a validation schema for an array of locales
25
+ *
26
+ * @returns A schema for validating arrays of locales
27
+ */ get locales() {
28
+ return z.array(this.locale);
29
+ }
30
+ constructor(strapi){
31
+ this._strapi = strapi;
32
+ }
33
+ }
34
+
35
+ export { I18nLocaleRouteValidator };
36
+ //# sourceMappingURL=locale.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locale.mjs","sources":["../../../../server/src/routes/validation/locale.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\nimport * as z from 'zod/v4';\n\n/**\n * A validator for i18n locale routes.\n *\n */\nexport class I18nLocaleRouteValidator {\n protected readonly _strapi: Core.Strapi;\n\n public constructor(strapi: Core.Strapi) {\n this._strapi = strapi;\n }\n\n /**\n * Generates a validation schema for a single locale.\n *\n * @returns A schema for validating locale objects\n */\n get locale() {\n return z.object({\n id: z.number().int().positive(),\n documentId: z.string().uuid(),\n name: z.string(),\n code: z.string().length(2, 'Locale code must be exactly 2 characters'),\n createdAt: z.string(),\n updatedAt: z.string(),\n publishedAt: z.string().nullable(),\n isDefault: z.boolean(),\n });\n }\n\n /**\n * Generates a validation schema for an array of locales\n *\n * @returns A schema for validating arrays of locales\n */\n get locales() {\n return z.array(this.locale);\n }\n}\n"],"names":["I18nLocaleRouteValidator","locale","z","object","id","number","int","positive","documentId","string","uuid","name","code","length","createdAt","updatedAt","publishedAt","nullable","isDefault","boolean","locales","array","strapi","_strapi"],"mappings":";;AAGA;;;AAGC,IACM,MAAMA,wBAAAA,CAAAA;AAOX;;;;AAIC,MACD,IAAIC,MAAS,GAAA;QACX,OAAOC,CAAAA,CAAEC,MAAM,CAAC;AACdC,YAAAA,EAAAA,EAAIF,CAAEG,CAAAA,MAAM,EAAGC,CAAAA,GAAG,GAAGC,QAAQ,EAAA;YAC7BC,UAAYN,EAAAA,CAAAA,CAAEO,MAAM,EAAA,CAAGC,IAAI,EAAA;AAC3BC,YAAAA,IAAAA,EAAMT,EAAEO,MAAM,EAAA;AACdG,YAAAA,IAAAA,EAAMV,CAAEO,CAAAA,MAAM,EAAGI,CAAAA,MAAM,CAAC,CAAG,EAAA,0CAAA,CAAA;AAC3BC,YAAAA,SAAAA,EAAWZ,EAAEO,MAAM,EAAA;AACnBM,YAAAA,SAAAA,EAAWb,EAAEO,MAAM,EAAA;YACnBO,WAAad,EAAAA,CAAAA,CAAEO,MAAM,EAAA,CAAGQ,QAAQ,EAAA;AAChCC,YAAAA,SAAAA,EAAWhB,EAAEiB,OAAO;AACtB,SAAA,CAAA;AACF;AAEA;;;;AAIC,MACD,IAAIC,OAAU,GAAA;AACZ,QAAA,OAAOlB,CAAEmB,CAAAA,KAAK,CAAC,IAAI,CAACpB,MAAM,CAAA;AAC5B;AA7BA,IAAA,WAAA,CAAmBqB,MAAmB,CAAE;QACtC,IAAI,CAACC,OAAO,GAAGD,MAAAA;AACjB;AA4BF;;;;"}
@@ -0,0 +1,143 @@
1
+ 'use strict';
2
+
3
+ var utils = require('@strapi/utils');
4
+ var index = require('../utils/index.js');
5
+
6
+ const createAILocalizationsService = ({ strapi })=>{
7
+ // TODO: add a helper function to get the AI server URL
8
+ const aiServerUrl = process.env.STRAPI_AI_URL || 'https://strapi-ai.apps.strapi.io';
9
+ return {
10
+ // Async to avoid changing the signature later (there will be a db check in the future)
11
+ async isEnabled () {
12
+ // Check if future flag is enabled
13
+ const isFutureFlagEnabled = strapi.features.future.isEnabled('unstableAILocalizations');
14
+ if (!isFutureFlagEnabled) {
15
+ return false;
16
+ }
17
+ // Check if user disabled AI features globally
18
+ const isAIEnabled = strapi.config.get('admin.ai.enabled', true);
19
+ if (!isAIEnabled) {
20
+ return false;
21
+ }
22
+ // Check if the user's license grants access to AI features
23
+ const hasAccess = strapi.ee.features.isEnabled('cms-ai');
24
+ if (!hasAccess) {
25
+ return false;
26
+ }
27
+ return true;
28
+ },
29
+ /**
30
+ * Checks if there are localizations that need to be generated for the given document,
31
+ * and if so, calls the AI service and saves the results to the database.
32
+ * Works for both single and collection types, on create and update.
33
+ */ async generateDocumentLocalizations ({ model, document }) {
34
+ const schema = strapi.getModel(model);
35
+ const localeService = index.getService('locales');
36
+ // No localizations needed for content types with i18n disabled
37
+ const isLocalizedContentType = index.getService('content-types').isLocalizedContentType(schema);
38
+ if (!isLocalizedContentType) {
39
+ return;
40
+ }
41
+ // Don't trigger localizations if the update is on a derived locale, only do it on the default
42
+ const defaultLocale = await localeService.getDefaultLocale();
43
+ if (document.locale !== defaultLocale) {
44
+ return;
45
+ }
46
+ const isFeatureEnabled = await this.isEnabled();
47
+ if (!isFeatureEnabled) {
48
+ return;
49
+ }
50
+ const documentId = document.documentId;
51
+ if (!documentId) {
52
+ strapi.log.warn(`AI Localizations: missing documentId for ${schema.uid}`);
53
+ return;
54
+ }
55
+ // Extract only the localized content from the document
56
+ const translateableContent = await utils.traverseEntity(({ key, attribute }, { remove })=>{
57
+ const hasLocalizedOption = attribute?.pluginOptions?.i18n?.localized === true;
58
+ // Only keep fields that actually need to be localized
59
+ // TODO: remove blocks from this list once the AI server can handle it reliably
60
+ if (!hasLocalizedOption || [
61
+ 'media',
62
+ 'blocks'
63
+ ].includes(attribute.type)) {
64
+ remove(key);
65
+ }
66
+ }, {
67
+ schema,
68
+ getModel: strapi.getModel.bind(strapi)
69
+ }, document);
70
+ // Call the AI server to get the localized content
71
+ const localesList = await localeService.find();
72
+ const targetLocales = localesList.filter((l)=>l.code !== document.locale).map((l)=>l.code);
73
+ if (targetLocales.length === 0) {
74
+ strapi.log.info(`AI Localizations: no target locales for ${schema.uid} document ${documentId}`);
75
+ return;
76
+ }
77
+ let token;
78
+ try {
79
+ const tokenData = await strapi.service('admin::user').getAiToken();
80
+ token = tokenData.token;
81
+ } catch (error) {
82
+ throw new Error('Failed to retrieve AI token', {
83
+ cause: error instanceof Error ? error : undefined
84
+ });
85
+ }
86
+ strapi.log.http('Contacting AI Server for localizations generation');
87
+ const response = await fetch(`${aiServerUrl}/i18n/generate-localizations`, {
88
+ method: 'POST',
89
+ headers: {
90
+ 'Content-Type': 'application/json',
91
+ Authorization: `Bearer ${token}`
92
+ },
93
+ body: JSON.stringify({
94
+ content: translateableContent,
95
+ sourceLocale: document.locale,
96
+ targetLocales
97
+ })
98
+ });
99
+ if (!response.ok) {
100
+ strapi.log.error(`AI Localizations request failed: ${response.status} ${response.statusText}`);
101
+ throw new Error(`AI Localizations request failed: ${response.statusText}`);
102
+ }
103
+ const aiResult = await response.json();
104
+ // Get all media field names dynamically from the schema
105
+ const mediaFields = Object.entries(schema.attributes)// eslint-disable-next-line @typescript-eslint/no-unused-vars
106
+ .filter(([_, attr])=>attr.type === 'media').map(([key])=>key);
107
+ try {
108
+ await Promise.allSettled(aiResult.localizations.map(async (localization)=>{
109
+ const { content, locale } = localization;
110
+ // Fetch the derived locale document
111
+ const derivedDoc = await strapi.documents(model).findOne({
112
+ documentId,
113
+ locale,
114
+ populate: mediaFields
115
+ });
116
+ // Merge AI content and media fields
117
+ const mergedData = {
118
+ ...content
119
+ };
120
+ for (const field of mediaFields){
121
+ // Only copy media if not already set in derived locale
122
+ if (!derivedDoc || !derivedDoc[field]) {
123
+ mergedData[field] = document[field];
124
+ } else {
125
+ mergedData[field] = derivedDoc[field];
126
+ }
127
+ }
128
+ return strapi.documents(model).update({
129
+ documentId,
130
+ locale,
131
+ fields: [],
132
+ data: mergedData
133
+ });
134
+ }));
135
+ } catch (error) {
136
+ strapi.log.error('AI Localizations generation failed', error);
137
+ }
138
+ }
139
+ };
140
+ };
141
+
142
+ exports.createAILocalizationsService = createAILocalizationsService;
143
+ //# sourceMappingURL=ai-localizations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-localizations.js","sources":["../../../server/src/services/ai-localizations.ts"],"sourcesContent":["import type { Core, Modules, UID } from '@strapi/types';\nimport { traverseEntity } from '@strapi/utils';\nimport { getService } from '../utils';\n\nconst createAILocalizationsService = ({ strapi }: { strapi: Core.Strapi }) => {\n // TODO: add a helper function to get the AI server URL\n const aiServerUrl = process.env.STRAPI_AI_URL || 'https://strapi-ai.apps.strapi.io';\n\n return {\n // Async to avoid changing the signature later (there will be a db check in the future)\n async isEnabled() {\n // Check if future flag is enabled\n const isFutureFlagEnabled = strapi.features.future.isEnabled('unstableAILocalizations');\n if (!isFutureFlagEnabled) {\n return false;\n }\n\n // Check if user disabled AI features globally\n const isAIEnabled = strapi.config.get('admin.ai.enabled', true);\n if (!isAIEnabled) {\n return false;\n }\n\n // Check if the user's license grants access to AI features\n const hasAccess = strapi.ee.features.isEnabled('cms-ai');\n if (!hasAccess) {\n return false;\n }\n\n return true;\n },\n\n /**\n * Checks if there are localizations that need to be generated for the given document,\n * and if so, calls the AI service and saves the results to the database.\n * Works for both single and collection types, on create and update.\n */\n async generateDocumentLocalizations({\n model,\n document,\n }: {\n model: UID.ContentType;\n document: Modules.Documents.AnyDocument;\n }) {\n const schema = strapi.getModel(model);\n const localeService = getService('locales');\n\n // No localizations needed for content types with i18n disabled\n const isLocalizedContentType = getService('content-types').isLocalizedContentType(schema);\n if (!isLocalizedContentType) {\n return;\n }\n\n // Don't trigger localizations if the update is on a derived locale, only do it on the default\n const defaultLocale = await localeService.getDefaultLocale();\n if (document.locale !== defaultLocale) {\n return;\n }\n\n const isFeatureEnabled = await this.isEnabled();\n if (!isFeatureEnabled) {\n return;\n }\n\n const documentId = document.documentId;\n\n if (!documentId) {\n strapi.log.warn(`AI Localizations: missing documentId for ${schema.uid}`);\n return;\n }\n\n // Extract only the localized content from the document\n const translateableContent = await traverseEntity(\n ({ key, attribute }, { remove }) => {\n const hasLocalizedOption = attribute?.pluginOptions?.i18n?.localized === true;\n // Only keep fields that actually need to be localized\n // TODO: remove blocks from this list once the AI server can handle it reliably\n if (!hasLocalizedOption || ['media', 'blocks'].includes(attribute.type)) {\n remove(key);\n }\n },\n { schema, getModel: strapi.getModel.bind(strapi) },\n document\n );\n\n // Call the AI server to get the localized content\n const localesList = await localeService.find();\n const targetLocales = localesList\n .filter((l) => l.code !== document.locale)\n .map((l) => l.code);\n\n if (targetLocales.length === 0) {\n strapi.log.info(\n `AI Localizations: no target locales for ${schema.uid} document ${documentId}`\n );\n return;\n }\n\n let token: string;\n try {\n const tokenData = await strapi.service('admin::user').getAiToken();\n token = tokenData.token;\n } catch (error) {\n throw new Error('Failed to retrieve AI token', {\n cause: error instanceof Error ? error : undefined,\n });\n }\n\n strapi.log.http('Contacting AI Server for localizations generation');\n const response = await fetch(`${aiServerUrl}/i18n/generate-localizations`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({\n content: translateableContent,\n sourceLocale: document.locale,\n targetLocales,\n }),\n });\n\n if (!response.ok) {\n strapi.log.error(\n `AI Localizations request failed: ${response.status} ${response.statusText}`\n );\n throw new Error(`AI Localizations request failed: ${response.statusText}`);\n }\n\n const aiResult = await response.json();\n\n // Get all media field names dynamically from the schema\n const mediaFields = Object.entries(schema.attributes)\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n .filter(([_, attr]) => attr.type === 'media')\n .map(([key]) => key);\n\n try {\n await Promise.allSettled(\n aiResult.localizations.map(async (localization: any) => {\n const { content, locale } = localization;\n\n // Fetch the derived locale document\n const derivedDoc = await strapi.documents(model).findOne({\n documentId,\n locale,\n populate: mediaFields,\n });\n\n // Merge AI content and media fields\n const mergedData = { ...content };\n for (const field of mediaFields) {\n // Only copy media if not already set in derived locale\n if (!derivedDoc || !derivedDoc[field]) {\n mergedData[field] = document[field];\n } else {\n mergedData[field] = derivedDoc[field];\n }\n }\n\n return strapi.documents(model).update({\n documentId,\n locale,\n fields: [],\n data: mergedData,\n });\n })\n );\n } catch (error) {\n strapi.log.error('AI Localizations generation failed', error);\n }\n },\n };\n};\n\nexport { createAILocalizationsService };\n"],"names":["createAILocalizationsService","strapi","aiServerUrl","process","env","STRAPI_AI_URL","isEnabled","isFutureFlagEnabled","features","future","isAIEnabled","config","get","hasAccess","ee","generateDocumentLocalizations","model","document","schema","getModel","localeService","getService","isLocalizedContentType","defaultLocale","getDefaultLocale","locale","isFeatureEnabled","documentId","log","warn","uid","translateableContent","traverseEntity","key","attribute","remove","hasLocalizedOption","pluginOptions","i18n","localized","includes","type","bind","localesList","find","targetLocales","filter","l","code","map","length","info","token","tokenData","service","getAiToken","error","Error","cause","undefined","http","response","fetch","method","headers","Authorization","body","JSON","stringify","content","sourceLocale","ok","status","statusText","aiResult","json","mediaFields","Object","entries","attributes","_","attr","Promise","allSettled","localizations","localization","derivedDoc","documents","findOne","populate","mergedData","field","update","fields","data"],"mappings":"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"}
@@ -0,0 +1,141 @@
1
+ import { traverseEntity } from '@strapi/utils';
2
+ import { getService } from '../utils/index.mjs';
3
+
4
+ const createAILocalizationsService = ({ strapi })=>{
5
+ // TODO: add a helper function to get the AI server URL
6
+ const aiServerUrl = process.env.STRAPI_AI_URL || 'https://strapi-ai.apps.strapi.io';
7
+ return {
8
+ // Async to avoid changing the signature later (there will be a db check in the future)
9
+ async isEnabled () {
10
+ // Check if future flag is enabled
11
+ const isFutureFlagEnabled = strapi.features.future.isEnabled('unstableAILocalizations');
12
+ if (!isFutureFlagEnabled) {
13
+ return false;
14
+ }
15
+ // Check if user disabled AI features globally
16
+ const isAIEnabled = strapi.config.get('admin.ai.enabled', true);
17
+ if (!isAIEnabled) {
18
+ return false;
19
+ }
20
+ // Check if the user's license grants access to AI features
21
+ const hasAccess = strapi.ee.features.isEnabled('cms-ai');
22
+ if (!hasAccess) {
23
+ return false;
24
+ }
25
+ return true;
26
+ },
27
+ /**
28
+ * Checks if there are localizations that need to be generated for the given document,
29
+ * and if so, calls the AI service and saves the results to the database.
30
+ * Works for both single and collection types, on create and update.
31
+ */ async generateDocumentLocalizations ({ model, document }) {
32
+ const schema = strapi.getModel(model);
33
+ const localeService = getService('locales');
34
+ // No localizations needed for content types with i18n disabled
35
+ const isLocalizedContentType = getService('content-types').isLocalizedContentType(schema);
36
+ if (!isLocalizedContentType) {
37
+ return;
38
+ }
39
+ // Don't trigger localizations if the update is on a derived locale, only do it on the default
40
+ const defaultLocale = await localeService.getDefaultLocale();
41
+ if (document.locale !== defaultLocale) {
42
+ return;
43
+ }
44
+ const isFeatureEnabled = await this.isEnabled();
45
+ if (!isFeatureEnabled) {
46
+ return;
47
+ }
48
+ const documentId = document.documentId;
49
+ if (!documentId) {
50
+ strapi.log.warn(`AI Localizations: missing documentId for ${schema.uid}`);
51
+ return;
52
+ }
53
+ // Extract only the localized content from the document
54
+ const translateableContent = await traverseEntity(({ key, attribute }, { remove })=>{
55
+ const hasLocalizedOption = attribute?.pluginOptions?.i18n?.localized === true;
56
+ // Only keep fields that actually need to be localized
57
+ // TODO: remove blocks from this list once the AI server can handle it reliably
58
+ if (!hasLocalizedOption || [
59
+ 'media',
60
+ 'blocks'
61
+ ].includes(attribute.type)) {
62
+ remove(key);
63
+ }
64
+ }, {
65
+ schema,
66
+ getModel: strapi.getModel.bind(strapi)
67
+ }, document);
68
+ // Call the AI server to get the localized content
69
+ const localesList = await localeService.find();
70
+ const targetLocales = localesList.filter((l)=>l.code !== document.locale).map((l)=>l.code);
71
+ if (targetLocales.length === 0) {
72
+ strapi.log.info(`AI Localizations: no target locales for ${schema.uid} document ${documentId}`);
73
+ return;
74
+ }
75
+ let token;
76
+ try {
77
+ const tokenData = await strapi.service('admin::user').getAiToken();
78
+ token = tokenData.token;
79
+ } catch (error) {
80
+ throw new Error('Failed to retrieve AI token', {
81
+ cause: error instanceof Error ? error : undefined
82
+ });
83
+ }
84
+ strapi.log.http('Contacting AI Server for localizations generation');
85
+ const response = await fetch(`${aiServerUrl}/i18n/generate-localizations`, {
86
+ method: 'POST',
87
+ headers: {
88
+ 'Content-Type': 'application/json',
89
+ Authorization: `Bearer ${token}`
90
+ },
91
+ body: JSON.stringify({
92
+ content: translateableContent,
93
+ sourceLocale: document.locale,
94
+ targetLocales
95
+ })
96
+ });
97
+ if (!response.ok) {
98
+ strapi.log.error(`AI Localizations request failed: ${response.status} ${response.statusText}`);
99
+ throw new Error(`AI Localizations request failed: ${response.statusText}`);
100
+ }
101
+ const aiResult = await response.json();
102
+ // Get all media field names dynamically from the schema
103
+ const mediaFields = Object.entries(schema.attributes)// eslint-disable-next-line @typescript-eslint/no-unused-vars
104
+ .filter(([_, attr])=>attr.type === 'media').map(([key])=>key);
105
+ try {
106
+ await Promise.allSettled(aiResult.localizations.map(async (localization)=>{
107
+ const { content, locale } = localization;
108
+ // Fetch the derived locale document
109
+ const derivedDoc = await strapi.documents(model).findOne({
110
+ documentId,
111
+ locale,
112
+ populate: mediaFields
113
+ });
114
+ // Merge AI content and media fields
115
+ const mergedData = {
116
+ ...content
117
+ };
118
+ for (const field of mediaFields){
119
+ // Only copy media if not already set in derived locale
120
+ if (!derivedDoc || !derivedDoc[field]) {
121
+ mergedData[field] = document[field];
122
+ } else {
123
+ mergedData[field] = derivedDoc[field];
124
+ }
125
+ }
126
+ return strapi.documents(model).update({
127
+ documentId,
128
+ locale,
129
+ fields: [],
130
+ data: mergedData
131
+ });
132
+ }));
133
+ } catch (error) {
134
+ strapi.log.error('AI Localizations generation failed', error);
135
+ }
136
+ }
137
+ };
138
+ };
139
+
140
+ export { createAILocalizationsService };
141
+ //# sourceMappingURL=ai-localizations.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-localizations.mjs","sources":["../../../server/src/services/ai-localizations.ts"],"sourcesContent":["import type { Core, Modules, UID } from '@strapi/types';\nimport { traverseEntity } from '@strapi/utils';\nimport { getService } from '../utils';\n\nconst createAILocalizationsService = ({ strapi }: { strapi: Core.Strapi }) => {\n // TODO: add a helper function to get the AI server URL\n const aiServerUrl = process.env.STRAPI_AI_URL || 'https://strapi-ai.apps.strapi.io';\n\n return {\n // Async to avoid changing the signature later (there will be a db check in the future)\n async isEnabled() {\n // Check if future flag is enabled\n const isFutureFlagEnabled = strapi.features.future.isEnabled('unstableAILocalizations');\n if (!isFutureFlagEnabled) {\n return false;\n }\n\n // Check if user disabled AI features globally\n const isAIEnabled = strapi.config.get('admin.ai.enabled', true);\n if (!isAIEnabled) {\n return false;\n }\n\n // Check if the user's license grants access to AI features\n const hasAccess = strapi.ee.features.isEnabled('cms-ai');\n if (!hasAccess) {\n return false;\n }\n\n return true;\n },\n\n /**\n * Checks if there are localizations that need to be generated for the given document,\n * and if so, calls the AI service and saves the results to the database.\n * Works for both single and collection types, on create and update.\n */\n async generateDocumentLocalizations({\n model,\n document,\n }: {\n model: UID.ContentType;\n document: Modules.Documents.AnyDocument;\n }) {\n const schema = strapi.getModel(model);\n const localeService = getService('locales');\n\n // No localizations needed for content types with i18n disabled\n const isLocalizedContentType = getService('content-types').isLocalizedContentType(schema);\n if (!isLocalizedContentType) {\n return;\n }\n\n // Don't trigger localizations if the update is on a derived locale, only do it on the default\n const defaultLocale = await localeService.getDefaultLocale();\n if (document.locale !== defaultLocale) {\n return;\n }\n\n const isFeatureEnabled = await this.isEnabled();\n if (!isFeatureEnabled) {\n return;\n }\n\n const documentId = document.documentId;\n\n if (!documentId) {\n strapi.log.warn(`AI Localizations: missing documentId for ${schema.uid}`);\n return;\n }\n\n // Extract only the localized content from the document\n const translateableContent = await traverseEntity(\n ({ key, attribute }, { remove }) => {\n const hasLocalizedOption = attribute?.pluginOptions?.i18n?.localized === true;\n // Only keep fields that actually need to be localized\n // TODO: remove blocks from this list once the AI server can handle it reliably\n if (!hasLocalizedOption || ['media', 'blocks'].includes(attribute.type)) {\n remove(key);\n }\n },\n { schema, getModel: strapi.getModel.bind(strapi) },\n document\n );\n\n // Call the AI server to get the localized content\n const localesList = await localeService.find();\n const targetLocales = localesList\n .filter((l) => l.code !== document.locale)\n .map((l) => l.code);\n\n if (targetLocales.length === 0) {\n strapi.log.info(\n `AI Localizations: no target locales for ${schema.uid} document ${documentId}`\n );\n return;\n }\n\n let token: string;\n try {\n const tokenData = await strapi.service('admin::user').getAiToken();\n token = tokenData.token;\n } catch (error) {\n throw new Error('Failed to retrieve AI token', {\n cause: error instanceof Error ? error : undefined,\n });\n }\n\n strapi.log.http('Contacting AI Server for localizations generation');\n const response = await fetch(`${aiServerUrl}/i18n/generate-localizations`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({\n content: translateableContent,\n sourceLocale: document.locale,\n targetLocales,\n }),\n });\n\n if (!response.ok) {\n strapi.log.error(\n `AI Localizations request failed: ${response.status} ${response.statusText}`\n );\n throw new Error(`AI Localizations request failed: ${response.statusText}`);\n }\n\n const aiResult = await response.json();\n\n // Get all media field names dynamically from the schema\n const mediaFields = Object.entries(schema.attributes)\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n .filter(([_, attr]) => attr.type === 'media')\n .map(([key]) => key);\n\n try {\n await Promise.allSettled(\n aiResult.localizations.map(async (localization: any) => {\n const { content, locale } = localization;\n\n // Fetch the derived locale document\n const derivedDoc = await strapi.documents(model).findOne({\n documentId,\n locale,\n populate: mediaFields,\n });\n\n // Merge AI content and media fields\n const mergedData = { ...content };\n for (const field of mediaFields) {\n // Only copy media if not already set in derived locale\n if (!derivedDoc || !derivedDoc[field]) {\n mergedData[field] = document[field];\n } else {\n mergedData[field] = derivedDoc[field];\n }\n }\n\n return strapi.documents(model).update({\n documentId,\n locale,\n fields: [],\n data: mergedData,\n });\n })\n );\n } catch (error) {\n strapi.log.error('AI Localizations generation failed', error);\n }\n },\n };\n};\n\nexport { createAILocalizationsService };\n"],"names":["createAILocalizationsService","strapi","aiServerUrl","process","env","STRAPI_AI_URL","isEnabled","isFutureFlagEnabled","features","future","isAIEnabled","config","get","hasAccess","ee","generateDocumentLocalizations","model","document","schema","getModel","localeService","getService","isLocalizedContentType","defaultLocale","getDefaultLocale","locale","isFeatureEnabled","documentId","log","warn","uid","translateableContent","traverseEntity","key","attribute","remove","hasLocalizedOption","pluginOptions","i18n","localized","includes","type","bind","localesList","find","targetLocales","filter","l","code","map","length","info","token","tokenData","service","getAiToken","error","Error","cause","undefined","http","response","fetch","method","headers","Authorization","body","JSON","stringify","content","sourceLocale","ok","status","statusText","aiResult","json","mediaFields","Object","entries","attributes","_","attr","Promise","allSettled","localizations","localization","derivedDoc","documents","findOne","populate","mergedData","field","update","fields","data"],"mappings":"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"}