@strapi/i18n 0.0.0-next.e7ae51b01f78ddeaa09c4aa3e3882f466a5b3188 → 0.0.0-next.e822ba8a3443f5fce869d85539f9fdaa02e10639
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.
- package/dist/admin/contentManagerHooks/editView.js +26 -42
- package/dist/admin/contentManagerHooks/editView.js.map +1 -1
- package/dist/admin/contentManagerHooks/editView.mjs +26 -23
- package/dist/admin/contentManagerHooks/editView.mjs.map +1 -1
- package/dist/admin/src/contentManagerHooks/tests/EditView.test.d.ts +1 -0
- package/dist/server/constants/iso-locales.json.js +68 -0
- package/dist/server/constants/iso-locales.json.js.map +1 -1
- package/dist/server/constants/iso-locales.json.mjs +68 -0
- package/dist/server/constants/iso-locales.json.mjs.map +1 -1
- package/dist/server/services/ai-localizations.js +2 -1
- package/dist/server/services/ai-localizations.js.map +1 -1
- package/dist/server/services/ai-localizations.mjs +2 -1
- package/dist/server/services/ai-localizations.mjs.map +1 -1
- package/dist/server/src/services/ai-localizations.d.ts.map +1 -1
- package/package.json +9 -9
|
@@ -1,32 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
-
var React = require('react');
|
|
5
4
|
var designSystem = require('@strapi/design-system');
|
|
6
5
|
var icons = require('@strapi/icons');
|
|
7
6
|
var reactIntl = require('react-intl');
|
|
8
7
|
var styledComponents = require('styled-components');
|
|
9
8
|
var getTranslation = require('../utils/getTranslation.js');
|
|
10
9
|
|
|
11
|
-
function _interopNamespaceDefault(e) {
|
|
12
|
-
var n = Object.create(null);
|
|
13
|
-
if (e) {
|
|
14
|
-
Object.keys(e).forEach(function (k) {
|
|
15
|
-
if (k !== 'default') {
|
|
16
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
17
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
18
|
-
enumerable: true,
|
|
19
|
-
get: function () { return e[k]; }
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
n.default = e;
|
|
25
|
-
return Object.freeze(n);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
|
|
29
|
-
|
|
30
10
|
const mutateEditViewHook = ({ layout })=>{
|
|
31
11
|
// If i18n isn't explicitly enabled on the content type, then no field can be localized
|
|
32
12
|
if (!('i18n' in layout.options) || typeof layout.options.i18n === 'object' && layout.options.i18n !== null && 'localized' in layout.options.i18n && !layout.options.i18n.localized) {
|
|
@@ -34,12 +14,13 @@ const mutateEditViewHook = ({ layout })=>{
|
|
|
34
14
|
layout
|
|
35
15
|
};
|
|
36
16
|
}
|
|
17
|
+
const decorateField = (field)=>addLabelActionToField(field, layout);
|
|
37
18
|
const components = Object.entries(layout.components).reduce((acc, [key, componentLayout])=>{
|
|
38
19
|
return {
|
|
39
20
|
...acc,
|
|
40
21
|
[key]: {
|
|
41
22
|
...componentLayout,
|
|
42
|
-
layout: componentLayout.layout.map((row)=>row.map(
|
|
23
|
+
layout: componentLayout.layout.map((row)=>row.map(decorateField))
|
|
43
24
|
}
|
|
44
25
|
};
|
|
45
26
|
}, {});
|
|
@@ -47,36 +28,39 @@ const mutateEditViewHook = ({ layout })=>{
|
|
|
47
28
|
layout: {
|
|
48
29
|
...layout,
|
|
49
30
|
components,
|
|
50
|
-
layout: layout.layout.map((panel)=>panel.map((row)=>row.map(
|
|
31
|
+
layout: layout.layout.map((panel)=>panel.map((row)=>row.map(decorateField)))
|
|
51
32
|
}
|
|
52
33
|
};
|
|
53
34
|
};
|
|
54
|
-
const
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
35
|
+
const isFieldLocalized = (attribute, layout)=>{
|
|
36
|
+
const contentTypeLocalized = !!layout.options?.i18n && !!layout.options.i18n.localized;
|
|
37
|
+
if (!contentTypeLocalized) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
const pluginOptions = attribute && typeof attribute === 'object' && 'pluginOptions' in attribute ? attribute.pluginOptions : undefined;
|
|
41
|
+
return pluginOptions?.i18n?.localized === true;
|
|
42
|
+
};
|
|
43
|
+
const addLabelActionToField = (field, layout)=>{
|
|
44
|
+
const localized = isFieldLocalized(field.attribute, layout);
|
|
45
|
+
if (!localized) {
|
|
46
|
+
return field;
|
|
47
|
+
}
|
|
48
|
+
const title = {
|
|
49
|
+
id: getTranslation.getTranslation('Field.localized'),
|
|
50
|
+
defaultMessage: 'This value is unique for the selected locale'
|
|
62
51
|
};
|
|
63
52
|
return {
|
|
64
53
|
...field,
|
|
65
|
-
labelAction:
|
|
66
|
-
|
|
67
|
-
})
|
|
54
|
+
labelAction: /*#__PURE__*/ jsxRuntime.jsx(LabelAction, {
|
|
55
|
+
title: title
|
|
56
|
+
})
|
|
68
57
|
};
|
|
69
58
|
};
|
|
70
|
-
const
|
|
71
|
-
if (!pluginOpts) {
|
|
72
|
-
return false;
|
|
73
|
-
}
|
|
74
|
-
return 'i18n' in pluginOpts && typeof pluginOpts.i18n === 'object' && pluginOpts.i18n !== null && 'localized' in pluginOpts.i18n;
|
|
75
|
-
};
|
|
76
|
-
const LabelAction = ({ title, icon })=>{
|
|
59
|
+
const LabelAction = ({ title })=>{
|
|
77
60
|
const { formatMessage } = reactIntl.useIntl();
|
|
78
61
|
return /*#__PURE__*/ jsxRuntime.jsxs(Span, {
|
|
79
62
|
tag: "span",
|
|
63
|
+
title: title,
|
|
80
64
|
children: [
|
|
81
65
|
/*#__PURE__*/ jsxRuntime.jsx(designSystem.VisuallyHidden, {
|
|
82
66
|
tag: "span",
|
|
@@ -84,8 +68,8 @@ const LabelAction = ({ title, icon })=>{
|
|
|
84
68
|
}),
|
|
85
69
|
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Tooltip, {
|
|
86
70
|
label: formatMessage(title),
|
|
87
|
-
children: /*#__PURE__*/
|
|
88
|
-
|
|
71
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(icons.Earth, {
|
|
72
|
+
"aria-hidden": true,
|
|
89
73
|
focusable: false
|
|
90
74
|
})
|
|
91
75
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editView.js","sources":["../../../admin/src/contentManagerHooks/editView.tsx"],"sourcesContent":["/* eslint-disable check-file/filename-naming-convention */\nimport
|
|
1
|
+
{"version":3,"file":"editView.js","sources":["../../../admin/src/contentManagerHooks/editView.tsx"],"sourcesContent":["/* eslint-disable check-file/filename-naming-convention */\nimport { Flex, Tooltip, VisuallyHidden } from '@strapi/design-system';\nimport { Earth } from '@strapi/icons';\nimport { MessageDescriptor, useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { getTranslation } from '../utils/getTranslation';\n\nimport type { EditFieldLayout, EditLayout } from '@strapi/content-manager/strapi-admin';\ninterface MutateEditViewArgs {\n layout: EditLayout;\n}\n\nconst mutateEditViewHook = ({ layout }: MutateEditViewArgs): MutateEditViewArgs => {\n // If i18n isn't explicitly enabled on the content type, then no field can be localized\n if (\n !('i18n' in layout.options) ||\n (typeof layout.options.i18n === 'object' &&\n layout.options.i18n !== null &&\n 'localized' in layout.options.i18n &&\n !layout.options.i18n.localized)\n ) {\n return { layout };\n }\n\n const decorateField = (field: EditFieldLayout) => addLabelActionToField(field, layout);\n\n const components = Object.entries(layout.components).reduce<EditLayout['components']>(\n (acc, [key, componentLayout]) => {\n return {\n ...acc,\n [key]: {\n ...componentLayout,\n layout: componentLayout.layout.map((row) => row.map(decorateField)),\n },\n };\n },\n {}\n );\n\n return {\n layout: {\n ...layout,\n components,\n layout: layout.layout.map((panel) => panel.map((row) => row.map(decorateField))),\n },\n } satisfies Pick<MutateEditViewArgs, 'layout'>;\n};\n\nconst isFieldLocalized = (attribute: EditFieldLayout['attribute'], layout: EditLayout) => {\n const contentTypeLocalized =\n !!(layout.options as any)?.i18n && !!(layout.options as any).i18n.localized;\n\n if (!contentTypeLocalized) {\n return false;\n }\n\n const pluginOptions =\n attribute && typeof attribute === 'object' && 'pluginOptions' in (attribute as object)\n ? (attribute as { pluginOptions?: { i18n?: { localized?: boolean } } }).pluginOptions\n : undefined;\n\n return pluginOptions?.i18n?.localized === true;\n};\n\nconst addLabelActionToField = (field: EditFieldLayout, layout: EditLayout) => {\n const localized = isFieldLocalized(field.attribute, layout);\n\n if (!localized) {\n return field;\n }\n\n const title: MessageDescriptor = {\n id: getTranslation('Field.localized'),\n defaultMessage: 'This value is unique for the selected locale',\n };\n\n return {\n ...field,\n labelAction: <LabelAction title={title} />,\n };\n};\n\n/* -------------------------------------------------------------------------------------------------\n * LabelAction\n * -----------------------------------------------------------------------------------------------*/\n\ninterface LabelActionProps {\n title: MessageDescriptor;\n}\n\nconst LabelAction = ({ title }: LabelActionProps) => {\n const { formatMessage } = useIntl();\n\n return (\n <Span tag=\"span\" title={title}>\n <VisuallyHidden tag=\"span\">{formatMessage(title)}</VisuallyHidden>\n <Tooltip label={formatMessage(title)}>\n <Earth aria-hidden focusable={false} />\n </Tooltip>\n </Span>\n );\n};\n\nconst Span = styled(Flex)`\n svg {\n width: 12px;\n height: 12px;\n\n fill: ${({ theme }) => theme.colors.neutral500};\n\n path {\n fill: ${({ theme }) => theme.colors.neutral500};\n }\n }\n`;\n\nexport { mutateEditViewHook };\n"],"names":["mutateEditViewHook","layout","options","i18n","localized","decorateField","field","addLabelActionToField","components","Object","entries","reduce","acc","key","componentLayout","map","row","panel","isFieldLocalized","attribute","contentTypeLocalized","pluginOptions","undefined","title","id","getTranslation","defaultMessage","labelAction","_jsx","LabelAction","formatMessage","useIntl","_jsxs","Span","tag","VisuallyHidden","Tooltip","label","Earth","aria-hidden","focusable","styled","Flex","theme","colors","neutral500"],"mappings":"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"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
-
import * as React from 'react';
|
|
3
2
|
import { Flex, VisuallyHidden, Tooltip } from '@strapi/design-system';
|
|
4
3
|
import { Earth } from '@strapi/icons';
|
|
5
4
|
import { useIntl } from 'react-intl';
|
|
@@ -13,12 +12,13 @@ const mutateEditViewHook = ({ layout })=>{
|
|
|
13
12
|
layout
|
|
14
13
|
};
|
|
15
14
|
}
|
|
15
|
+
const decorateField = (field)=>addLabelActionToField(field, layout);
|
|
16
16
|
const components = Object.entries(layout.components).reduce((acc, [key, componentLayout])=>{
|
|
17
17
|
return {
|
|
18
18
|
...acc,
|
|
19
19
|
[key]: {
|
|
20
20
|
...componentLayout,
|
|
21
|
-
layout: componentLayout.layout.map((row)=>row.map(
|
|
21
|
+
layout: componentLayout.layout.map((row)=>row.map(decorateField))
|
|
22
22
|
}
|
|
23
23
|
};
|
|
24
24
|
}, {});
|
|
@@ -26,36 +26,39 @@ const mutateEditViewHook = ({ layout })=>{
|
|
|
26
26
|
layout: {
|
|
27
27
|
...layout,
|
|
28
28
|
components,
|
|
29
|
-
layout: layout.layout.map((panel)=>panel.map((row)=>row.map(
|
|
29
|
+
layout: layout.layout.map((panel)=>panel.map((row)=>row.map(decorateField)))
|
|
30
30
|
}
|
|
31
31
|
};
|
|
32
32
|
};
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
33
|
+
const isFieldLocalized = (attribute, layout)=>{
|
|
34
|
+
const contentTypeLocalized = !!layout.options?.i18n && !!layout.options.i18n.localized;
|
|
35
|
+
if (!contentTypeLocalized) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
const pluginOptions = attribute && typeof attribute === 'object' && 'pluginOptions' in attribute ? attribute.pluginOptions : undefined;
|
|
39
|
+
return pluginOptions?.i18n?.localized === true;
|
|
40
|
+
};
|
|
41
|
+
const addLabelActionToField = (field, layout)=>{
|
|
42
|
+
const localized = isFieldLocalized(field.attribute, layout);
|
|
43
|
+
if (!localized) {
|
|
44
|
+
return field;
|
|
45
|
+
}
|
|
46
|
+
const title = {
|
|
47
|
+
id: getTranslation('Field.localized'),
|
|
48
|
+
defaultMessage: 'This value is unique for the selected locale'
|
|
41
49
|
};
|
|
42
50
|
return {
|
|
43
51
|
...field,
|
|
44
|
-
labelAction:
|
|
45
|
-
|
|
46
|
-
})
|
|
52
|
+
labelAction: /*#__PURE__*/ jsx(LabelAction, {
|
|
53
|
+
title: title
|
|
54
|
+
})
|
|
47
55
|
};
|
|
48
56
|
};
|
|
49
|
-
const
|
|
50
|
-
if (!pluginOpts) {
|
|
51
|
-
return false;
|
|
52
|
-
}
|
|
53
|
-
return 'i18n' in pluginOpts && typeof pluginOpts.i18n === 'object' && pluginOpts.i18n !== null && 'localized' in pluginOpts.i18n;
|
|
54
|
-
};
|
|
55
|
-
const LabelAction = ({ title, icon })=>{
|
|
57
|
+
const LabelAction = ({ title })=>{
|
|
56
58
|
const { formatMessage } = useIntl();
|
|
57
59
|
return /*#__PURE__*/ jsxs(Span, {
|
|
58
60
|
tag: "span",
|
|
61
|
+
title: title,
|
|
59
62
|
children: [
|
|
60
63
|
/*#__PURE__*/ jsx(VisuallyHidden, {
|
|
61
64
|
tag: "span",
|
|
@@ -63,8 +66,8 @@ const LabelAction = ({ title, icon })=>{
|
|
|
63
66
|
}),
|
|
64
67
|
/*#__PURE__*/ jsx(Tooltip, {
|
|
65
68
|
label: formatMessage(title),
|
|
66
|
-
children: /*#__PURE__*/
|
|
67
|
-
|
|
69
|
+
children: /*#__PURE__*/ jsx(Earth, {
|
|
70
|
+
"aria-hidden": true,
|
|
68
71
|
focusable: false
|
|
69
72
|
})
|
|
70
73
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editView.mjs","sources":["../../../admin/src/contentManagerHooks/editView.tsx"],"sourcesContent":["/* eslint-disable check-file/filename-naming-convention */\nimport
|
|
1
|
+
{"version":3,"file":"editView.mjs","sources":["../../../admin/src/contentManagerHooks/editView.tsx"],"sourcesContent":["/* eslint-disable check-file/filename-naming-convention */\nimport { Flex, Tooltip, VisuallyHidden } from '@strapi/design-system';\nimport { Earth } from '@strapi/icons';\nimport { MessageDescriptor, useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { getTranslation } from '../utils/getTranslation';\n\nimport type { EditFieldLayout, EditLayout } from '@strapi/content-manager/strapi-admin';\ninterface MutateEditViewArgs {\n layout: EditLayout;\n}\n\nconst mutateEditViewHook = ({ layout }: MutateEditViewArgs): MutateEditViewArgs => {\n // If i18n isn't explicitly enabled on the content type, then no field can be localized\n if (\n !('i18n' in layout.options) ||\n (typeof layout.options.i18n === 'object' &&\n layout.options.i18n !== null &&\n 'localized' in layout.options.i18n &&\n !layout.options.i18n.localized)\n ) {\n return { layout };\n }\n\n const decorateField = (field: EditFieldLayout) => addLabelActionToField(field, layout);\n\n const components = Object.entries(layout.components).reduce<EditLayout['components']>(\n (acc, [key, componentLayout]) => {\n return {\n ...acc,\n [key]: {\n ...componentLayout,\n layout: componentLayout.layout.map((row) => row.map(decorateField)),\n },\n };\n },\n {}\n );\n\n return {\n layout: {\n ...layout,\n components,\n layout: layout.layout.map((panel) => panel.map((row) => row.map(decorateField))),\n },\n } satisfies Pick<MutateEditViewArgs, 'layout'>;\n};\n\nconst isFieldLocalized = (attribute: EditFieldLayout['attribute'], layout: EditLayout) => {\n const contentTypeLocalized =\n !!(layout.options as any)?.i18n && !!(layout.options as any).i18n.localized;\n\n if (!contentTypeLocalized) {\n return false;\n }\n\n const pluginOptions =\n attribute && typeof attribute === 'object' && 'pluginOptions' in (attribute as object)\n ? (attribute as { pluginOptions?: { i18n?: { localized?: boolean } } }).pluginOptions\n : undefined;\n\n return pluginOptions?.i18n?.localized === true;\n};\n\nconst addLabelActionToField = (field: EditFieldLayout, layout: EditLayout) => {\n const localized = isFieldLocalized(field.attribute, layout);\n\n if (!localized) {\n return field;\n }\n\n const title: MessageDescriptor = {\n id: getTranslation('Field.localized'),\n defaultMessage: 'This value is unique for the selected locale',\n };\n\n return {\n ...field,\n labelAction: <LabelAction title={title} />,\n };\n};\n\n/* -------------------------------------------------------------------------------------------------\n * LabelAction\n * -----------------------------------------------------------------------------------------------*/\n\ninterface LabelActionProps {\n title: MessageDescriptor;\n}\n\nconst LabelAction = ({ title }: LabelActionProps) => {\n const { formatMessage } = useIntl();\n\n return (\n <Span tag=\"span\" title={title}>\n <VisuallyHidden tag=\"span\">{formatMessage(title)}</VisuallyHidden>\n <Tooltip label={formatMessage(title)}>\n <Earth aria-hidden focusable={false} />\n </Tooltip>\n </Span>\n );\n};\n\nconst Span = styled(Flex)`\n svg {\n width: 12px;\n height: 12px;\n\n fill: ${({ theme }) => theme.colors.neutral500};\n\n path {\n fill: ${({ theme }) => theme.colors.neutral500};\n }\n }\n`;\n\nexport { mutateEditViewHook };\n"],"names":["mutateEditViewHook","layout","options","i18n","localized","decorateField","field","addLabelActionToField","components","Object","entries","reduce","acc","key","componentLayout","map","row","panel","isFieldLocalized","attribute","contentTypeLocalized","pluginOptions","undefined","title","id","getTranslation","defaultMessage","labelAction","_jsx","LabelAction","formatMessage","useIntl","_jsxs","Span","tag","VisuallyHidden","Tooltip","label","Earth","aria-hidden","focusable","styled","Flex","theme","colors","neutral500"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -265,6 +265,22 @@ var isoLocales = [
|
|
|
265
265
|
code: "bs-BA",
|
|
266
266
|
name: "Bosnian (Bosnia and Herzegovina) (bs-BA)"
|
|
267
267
|
},
|
|
268
|
+
{
|
|
269
|
+
code: "bs-Cyrl",
|
|
270
|
+
name: "Bosnian (Cyrillic)"
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
code: "bs-Cyrl-BA",
|
|
274
|
+
name: "Bosnian (Cyrillic, Bosnia and Herzegovina)"
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
code: "bs-Latn",
|
|
278
|
+
name: "Bosnian (Latin)"
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
code: "bs-Latn-BA",
|
|
282
|
+
name: "Bosnian (Latin, Bosnia and Herzegovina)"
|
|
283
|
+
},
|
|
268
284
|
{
|
|
269
285
|
code: "br",
|
|
270
286
|
name: "Breton (br)"
|
|
@@ -329,6 +345,10 @@ var isoLocales = [
|
|
|
329
345
|
code: "chr-US",
|
|
330
346
|
name: "Cherokee (United States) (chr-US)"
|
|
331
347
|
},
|
|
348
|
+
{
|
|
349
|
+
code: "ny",
|
|
350
|
+
name: "Chichewa"
|
|
351
|
+
},
|
|
332
352
|
{
|
|
333
353
|
code: "cgg",
|
|
334
354
|
name: "Chiga (cgg)"
|
|
@@ -421,6 +441,10 @@ var isoLocales = [
|
|
|
421
441
|
code: "da-DK",
|
|
422
442
|
name: "Danish (Denmark) (da-DK)"
|
|
423
443
|
},
|
|
444
|
+
{
|
|
445
|
+
code: "dwr",
|
|
446
|
+
name: "Dawro"
|
|
447
|
+
},
|
|
424
448
|
{
|
|
425
449
|
code: "dua",
|
|
426
450
|
name: "Duala (dua)"
|
|
@@ -665,6 +689,10 @@ var isoLocales = [
|
|
|
665
689
|
code: "en-MG",
|
|
666
690
|
name: "English (Madagascar) (en-MG)"
|
|
667
691
|
},
|
|
692
|
+
{
|
|
693
|
+
code: "en-MM",
|
|
694
|
+
name: "English (Myanmar) (en-MM)"
|
|
695
|
+
},
|
|
668
696
|
{
|
|
669
697
|
code: "en-MW",
|
|
670
698
|
name: "English (Malawi) (en-MW)"
|
|
@@ -1109,6 +1137,10 @@ var isoLocales = [
|
|
|
1109
1137
|
code: "gl-ES",
|
|
1110
1138
|
name: "Galician (Spain) (gl-ES)"
|
|
1111
1139
|
},
|
|
1140
|
+
{
|
|
1141
|
+
code: "gmv",
|
|
1142
|
+
name: "Gamo"
|
|
1143
|
+
},
|
|
1112
1144
|
{
|
|
1113
1145
|
code: "lao",
|
|
1114
1146
|
name: "Laotian (Laos) (lao)"
|
|
@@ -1157,6 +1189,10 @@ var isoLocales = [
|
|
|
1157
1189
|
code: "de-CH",
|
|
1158
1190
|
name: "German (Switzerland) (de-CH)"
|
|
1159
1191
|
},
|
|
1192
|
+
{
|
|
1193
|
+
code: "gof",
|
|
1194
|
+
name: "Gofa"
|
|
1195
|
+
},
|
|
1160
1196
|
{
|
|
1161
1197
|
code: "el",
|
|
1162
1198
|
name: "Greek (el)"
|
|
@@ -1205,6 +1241,10 @@ var isoLocales = [
|
|
|
1205
1241
|
code: "ha-Latn-NG",
|
|
1206
1242
|
name: "Hausa (Latin, Nigeria) (ha-Latn-NG)"
|
|
1207
1243
|
},
|
|
1244
|
+
{
|
|
1245
|
+
code: "ht",
|
|
1246
|
+
name: "Haitian"
|
|
1247
|
+
},
|
|
1208
1248
|
{
|
|
1209
1249
|
code: "haw",
|
|
1210
1250
|
name: "Hawaiian (haw)"
|
|
@@ -1477,6 +1517,14 @@ var isoLocales = [
|
|
|
1477
1517
|
code: "lt-LT",
|
|
1478
1518
|
name: "Lithuanian (Lithuania) (lt-LT)"
|
|
1479
1519
|
},
|
|
1520
|
+
{
|
|
1521
|
+
code: "lb",
|
|
1522
|
+
name: "Luxembourgish (lb)"
|
|
1523
|
+
},
|
|
1524
|
+
{
|
|
1525
|
+
code: "lb-LU",
|
|
1526
|
+
name: "Luxembourgish (Luxembourg) (lb-LU)"
|
|
1527
|
+
},
|
|
1480
1528
|
{
|
|
1481
1529
|
code: "lu",
|
|
1482
1530
|
name: "Luba-Katanga (lu)"
|
|
@@ -1609,6 +1657,10 @@ var isoLocales = [
|
|
|
1609
1657
|
code: "mn",
|
|
1610
1658
|
name: "Mongolian (mn)"
|
|
1611
1659
|
},
|
|
1660
|
+
{
|
|
1661
|
+
code: "mn-Cyrl",
|
|
1662
|
+
name: "Mongolian (Cyrillic)"
|
|
1663
|
+
},
|
|
1612
1664
|
{
|
|
1613
1665
|
code: "mfe",
|
|
1614
1666
|
name: "Morisyen (mfe)"
|
|
@@ -1797,6 +1849,22 @@ var isoLocales = [
|
|
|
1797
1849
|
code: "pa-Guru-IN",
|
|
1798
1850
|
name: "Punjabi (Gurmukhi, India) (pa-Guru-IN)"
|
|
1799
1851
|
},
|
|
1852
|
+
{
|
|
1853
|
+
code: "pap",
|
|
1854
|
+
name: "Papiamento (pap)"
|
|
1855
|
+
},
|
|
1856
|
+
{
|
|
1857
|
+
code: "pap-AW",
|
|
1858
|
+
name: "Papiamento (Aruba) (pap-AW)"
|
|
1859
|
+
},
|
|
1860
|
+
{
|
|
1861
|
+
code: "pap-CW",
|
|
1862
|
+
name: "Papiamentu (Curaçao) (pap-CW)"
|
|
1863
|
+
},
|
|
1864
|
+
{
|
|
1865
|
+
code: "pap-BQ",
|
|
1866
|
+
name: "Papiamentu (Bonaire) (pap-BQ)"
|
|
1867
|
+
},
|
|
1800
1868
|
{
|
|
1801
1869
|
code: "ro",
|
|
1802
1870
|
name: "Romanian (ro)"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iso-locales.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"iso-locales.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -263,6 +263,22 @@ var isoLocales = [
|
|
|
263
263
|
code: "bs-BA",
|
|
264
264
|
name: "Bosnian (Bosnia and Herzegovina) (bs-BA)"
|
|
265
265
|
},
|
|
266
|
+
{
|
|
267
|
+
code: "bs-Cyrl",
|
|
268
|
+
name: "Bosnian (Cyrillic)"
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
code: "bs-Cyrl-BA",
|
|
272
|
+
name: "Bosnian (Cyrillic, Bosnia and Herzegovina)"
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
code: "bs-Latn",
|
|
276
|
+
name: "Bosnian (Latin)"
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
code: "bs-Latn-BA",
|
|
280
|
+
name: "Bosnian (Latin, Bosnia and Herzegovina)"
|
|
281
|
+
},
|
|
266
282
|
{
|
|
267
283
|
code: "br",
|
|
268
284
|
name: "Breton (br)"
|
|
@@ -327,6 +343,10 @@ var isoLocales = [
|
|
|
327
343
|
code: "chr-US",
|
|
328
344
|
name: "Cherokee (United States) (chr-US)"
|
|
329
345
|
},
|
|
346
|
+
{
|
|
347
|
+
code: "ny",
|
|
348
|
+
name: "Chichewa"
|
|
349
|
+
},
|
|
330
350
|
{
|
|
331
351
|
code: "cgg",
|
|
332
352
|
name: "Chiga (cgg)"
|
|
@@ -419,6 +439,10 @@ var isoLocales = [
|
|
|
419
439
|
code: "da-DK",
|
|
420
440
|
name: "Danish (Denmark) (da-DK)"
|
|
421
441
|
},
|
|
442
|
+
{
|
|
443
|
+
code: "dwr",
|
|
444
|
+
name: "Dawro"
|
|
445
|
+
},
|
|
422
446
|
{
|
|
423
447
|
code: "dua",
|
|
424
448
|
name: "Duala (dua)"
|
|
@@ -663,6 +687,10 @@ var isoLocales = [
|
|
|
663
687
|
code: "en-MG",
|
|
664
688
|
name: "English (Madagascar) (en-MG)"
|
|
665
689
|
},
|
|
690
|
+
{
|
|
691
|
+
code: "en-MM",
|
|
692
|
+
name: "English (Myanmar) (en-MM)"
|
|
693
|
+
},
|
|
666
694
|
{
|
|
667
695
|
code: "en-MW",
|
|
668
696
|
name: "English (Malawi) (en-MW)"
|
|
@@ -1107,6 +1135,10 @@ var isoLocales = [
|
|
|
1107
1135
|
code: "gl-ES",
|
|
1108
1136
|
name: "Galician (Spain) (gl-ES)"
|
|
1109
1137
|
},
|
|
1138
|
+
{
|
|
1139
|
+
code: "gmv",
|
|
1140
|
+
name: "Gamo"
|
|
1141
|
+
},
|
|
1110
1142
|
{
|
|
1111
1143
|
code: "lao",
|
|
1112
1144
|
name: "Laotian (Laos) (lao)"
|
|
@@ -1155,6 +1187,10 @@ var isoLocales = [
|
|
|
1155
1187
|
code: "de-CH",
|
|
1156
1188
|
name: "German (Switzerland) (de-CH)"
|
|
1157
1189
|
},
|
|
1190
|
+
{
|
|
1191
|
+
code: "gof",
|
|
1192
|
+
name: "Gofa"
|
|
1193
|
+
},
|
|
1158
1194
|
{
|
|
1159
1195
|
code: "el",
|
|
1160
1196
|
name: "Greek (el)"
|
|
@@ -1203,6 +1239,10 @@ var isoLocales = [
|
|
|
1203
1239
|
code: "ha-Latn-NG",
|
|
1204
1240
|
name: "Hausa (Latin, Nigeria) (ha-Latn-NG)"
|
|
1205
1241
|
},
|
|
1242
|
+
{
|
|
1243
|
+
code: "ht",
|
|
1244
|
+
name: "Haitian"
|
|
1245
|
+
},
|
|
1206
1246
|
{
|
|
1207
1247
|
code: "haw",
|
|
1208
1248
|
name: "Hawaiian (haw)"
|
|
@@ -1475,6 +1515,14 @@ var isoLocales = [
|
|
|
1475
1515
|
code: "lt-LT",
|
|
1476
1516
|
name: "Lithuanian (Lithuania) (lt-LT)"
|
|
1477
1517
|
},
|
|
1518
|
+
{
|
|
1519
|
+
code: "lb",
|
|
1520
|
+
name: "Luxembourgish (lb)"
|
|
1521
|
+
},
|
|
1522
|
+
{
|
|
1523
|
+
code: "lb-LU",
|
|
1524
|
+
name: "Luxembourgish (Luxembourg) (lb-LU)"
|
|
1525
|
+
},
|
|
1478
1526
|
{
|
|
1479
1527
|
code: "lu",
|
|
1480
1528
|
name: "Luba-Katanga (lu)"
|
|
@@ -1607,6 +1655,10 @@ var isoLocales = [
|
|
|
1607
1655
|
code: "mn",
|
|
1608
1656
|
name: "Mongolian (mn)"
|
|
1609
1657
|
},
|
|
1658
|
+
{
|
|
1659
|
+
code: "mn-Cyrl",
|
|
1660
|
+
name: "Mongolian (Cyrillic)"
|
|
1661
|
+
},
|
|
1610
1662
|
{
|
|
1611
1663
|
code: "mfe",
|
|
1612
1664
|
name: "Morisyen (mfe)"
|
|
@@ -1795,6 +1847,22 @@ var isoLocales = [
|
|
|
1795
1847
|
code: "pa-Guru-IN",
|
|
1796
1848
|
name: "Punjabi (Gurmukhi, India) (pa-Guru-IN)"
|
|
1797
1849
|
},
|
|
1850
|
+
{
|
|
1851
|
+
code: "pap",
|
|
1852
|
+
name: "Papiamento (pap)"
|
|
1853
|
+
},
|
|
1854
|
+
{
|
|
1855
|
+
code: "pap-AW",
|
|
1856
|
+
name: "Papiamento (Aruba) (pap-AW)"
|
|
1857
|
+
},
|
|
1858
|
+
{
|
|
1859
|
+
code: "pap-CW",
|
|
1860
|
+
name: "Papiamentu (Curaçao) (pap-CW)"
|
|
1861
|
+
},
|
|
1862
|
+
{
|
|
1863
|
+
code: "pap-BQ",
|
|
1864
|
+
name: "Papiamentu (Bonaire) (pap-BQ)"
|
|
1865
|
+
},
|
|
1798
1866
|
{
|
|
1799
1867
|
code: "ro",
|
|
1800
1868
|
name: "Romanian (ro)"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iso-locales.json.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"iso-locales.json.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-localizations.js","sources":["../../../server/src/services/ai-localizations.ts"],"sourcesContent":["import type { Core, Modules, Schema, UID } from '@strapi/types';\nimport { traverseEntity } from '@strapi/utils';\nimport { getService } from '../utils';\n\nconst isLocalizedAttribute = (attribute: Schema.Attribute.Attribute | undefined): boolean => {\n return (attribute?.pluginOptions as any)?.i18n?.localized === true;\n};\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 const aiLocalizationJobsService = getService('ai-localization-jobs');\n\n const UNSUPPORTED_ATTRIBUTE_TYPES: Schema.Attribute.Kind[] = ['media', 'relation', 'boolean'];\n const IGNORED_FIELDS = [\n 'id',\n 'documentId',\n 'createdAt',\n 'updatedAt',\n 'updatedBy',\n 'localizations',\n ];\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 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 const settings = getService('settings');\n const aiSettings = await settings.getSettings();\n if (!aiSettings?.aiLocalizations) {\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 isFeatureEnabled = await this.isEnabled();\n if (!isFeatureEnabled) {\n return;\n }\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 documentId = document.documentId;\n\n if (!documentId) {\n strapi.log.warn(`AI Localizations: missing documentId for ${schema.uid}`);\n return;\n }\n\n const localizedRoots = new Set();\n\n const translateableContent = await traverseEntity(\n ({ key, attribute, parent, path }, { remove }) => {\n if (IGNORED_FIELDS.includes(key)) {\n remove(key);\n return;\n }\n const hasLocalizedOption = attribute && isLocalizedAttribute(attribute);\n if (attribute && UNSUPPORTED_ATTRIBUTE_TYPES.includes(attribute.type)) {\n remove(key);\n return;\n }\n\n // If this field is localized, keep it (and mark as localized root if component/dz)\n if (hasLocalizedOption) {\n // If it's a component/dynamiczone, add to the set\n if (['component', 'dynamiczone'].includes(attribute.type)) {\n localizedRoots.add(path.raw);\n }\n return; // keep\n }\n\n if (parent && localizedRoots.has(parent.path.raw)) {\n // If parent exists in the localized roots set, keep it\n // If this is also a component/dz, propagate the localized root flag\n if (['component', 'dynamiczone'].includes(attribute?.type ?? '')) {\n localizedRoots.add(path.raw);\n }\n return; // keep\n }\n\n // Otherwise, remove the field\n remove(key);\n },\n { schema, getModel: strapi.getModel.bind(strapi) },\n document\n );\n\n if (Object.keys(translateableContent).length === 0) {\n strapi.log.info(\n `AI Localizations: no translatable content for ${schema.uid} document ${documentId}`\n );\n return;\n }\n\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 await aiLocalizationJobsService.upsertJobForDocument({\n contentType: model,\n documentId,\n sourceLocale: document.locale,\n targetLocales,\n status: 'processing',\n });\n\n let token: string;\n try {\n const tokenData = await strapi.get('ai').getAiToken();\n token = tokenData.token;\n } catch (error) {\n await aiLocalizationJobsService.upsertJobForDocument({\n documentId,\n contentType: model,\n sourceLocale: document.locale,\n targetLocales,\n status: 'failed',\n });\n\n throw new Error('Failed to retrieve AI token', {\n cause: error instanceof Error ? error : undefined,\n });\n }\n\n /**\n * Provide a schema to the LLM so that we can give it instructions about how to handle each\n * type of attribute. Only keep essential schema data to avoid cluttering the context.\n * Ignore fields that don't need to be localized.\n * TODO: also provide a schema of all the referenced components\n */\n const minimalContentTypeSchema = Object.fromEntries(\n Object.entries(schema.attributes)\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n .filter(([_, attr]) => {\n const isLocalized = isLocalizedAttribute(attr);\n const isSupportedType = !UNSUPPORTED_ATTRIBUTE_TYPES.includes(attr.type);\n return isLocalized && isSupportedType;\n })\n .map(([key, attr]) => {\n const minimalAttribute = { type: attr.type };\n if (attr.type === 'component') {\n (\n minimalAttribute as Schema.Attribute.Component<`${string}.${string}`, boolean>\n ).repeatable = attr.repeatable ?? false;\n }\n return [key, minimalAttribute];\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 contentTypeSchema: minimalContentTypeSchema,\n }),\n });\n\n if (!response.ok) {\n strapi.log.error(\n `AI Localizations request failed: ${response.status} ${response.statusText}`\n );\n\n await aiLocalizationJobsService.upsertJobForDocument({\n documentId,\n contentType: model,\n sourceLocale: document.locale,\n targetLocales,\n status: 'failed',\n });\n\n throw new Error(`AI Localizations request failed: ${response.statusText}`);\n }\n\n const aiResult = await response.json();\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.all(\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, works only on first level media fields (root level)\n const mergedData = structuredClone(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 await strapi.documents(model).update({\n documentId,\n locale,\n fields: [],\n data: mergedData,\n });\n\n await aiLocalizationJobsService.upsertJobForDocument({\n documentId,\n contentType: model,\n sourceLocale: document.locale,\n targetLocales,\n status: 'completed',\n });\n })\n );\n } catch (error) {\n await aiLocalizationJobsService.upsertJobForDocument({\n documentId,\n contentType: model,\n sourceLocale: document.locale,\n targetLocales,\n status: 'failed',\n });\n strapi.log.error('AI Localizations generation failed', error);\n }\n },\n setupMiddleware() {\n strapi.documents.use(async (context, next) => {\n const result = await next();\n\n // Only trigger for the allowed actions\n if (!['create', 'update'].includes(context.action)) {\n return result;\n }\n\n // Check if AI localizations are enabled before triggering\n const isEnabled = await this.isEnabled();\n if (!isEnabled) {\n return result;\n }\n\n // Don't await since localizations should be done in the background without blocking the request\n strapi\n .plugin('i18n')\n .service('ai-localizations')\n .generateDocumentLocalizations({\n model: context.contentType.uid,\n document: result,\n })\n .catch((error: any) => {\n strapi.log.error('AI Localizations generation failed', error);\n });\n\n return result;\n });\n },\n };\n};\n\nexport { createAILocalizationsService };\n"],"names":["isLocalizedAttribute","attribute","pluginOptions","i18n","localized","createAILocalizationsService","strapi","aiServerUrl","process","env","STRAPI_AI_URL","aiLocalizationJobsService","getService","UNSUPPORTED_ATTRIBUTE_TYPES","IGNORED_FIELDS","isEnabled","isAIEnabled","config","get","hasAccess","ee","features","settings","aiSettings","getSettings","aiLocalizations","generateDocumentLocalizations","model","document","isFeatureEnabled","schema","getModel","localeService","isLocalizedContentType","defaultLocale","getDefaultLocale","locale","documentId","log","warn","uid","localizedRoots","Set","translateableContent","traverseEntity","key","parent","path","remove","includes","hasLocalizedOption","type","add","raw","has","bind","Object","keys","length","info","localesList","find","targetLocales","filter","l","code","map","upsertJobForDocument","contentType","sourceLocale","status","token","tokenData","getAiToken","error","Error","cause","undefined","minimalContentTypeSchema","fromEntries","entries","attributes","_","attr","isLocalized","isSupportedType","minimalAttribute","repeatable","http","response","fetch","method","headers","Authorization","body","JSON","stringify","content","contentTypeSchema","ok","statusText","aiResult","json","mediaFields","Promise","all","localizations","localization","derivedDoc","documents","findOne","populate","mergedData","structuredClone","field","update","fields","data","setupMiddleware","use","context","next","result","action","plugin","service","catch"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ai-localizations.js","sources":["../../../server/src/services/ai-localizations.ts"],"sourcesContent":["import type { Core, Modules, Schema, UID } from '@strapi/types';\nimport { traverseEntity } from '@strapi/utils';\nimport { getService } from '../utils';\n\nconst isLocalizedAttribute = (attribute: Schema.Attribute.Attribute | undefined): boolean => {\n return (attribute?.pluginOptions as any)?.i18n?.localized === true;\n};\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 const aiLocalizationJobsService = getService('ai-localization-jobs');\n\n const UNSUPPORTED_ATTRIBUTE_TYPES: Schema.Attribute.Kind[] = [\n 'media',\n 'relation',\n 'boolean',\n 'enumeration',\n ];\n const IGNORED_FIELDS = [\n 'id',\n 'documentId',\n 'createdAt',\n 'updatedAt',\n 'updatedBy',\n 'localizations',\n ];\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 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 const settings = getService('settings');\n const aiSettings = await settings.getSettings();\n if (!aiSettings?.aiLocalizations) {\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 isFeatureEnabled = await this.isEnabled();\n if (!isFeatureEnabled) {\n return;\n }\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 documentId = document.documentId;\n\n if (!documentId) {\n strapi.log.warn(`AI Localizations: missing documentId for ${schema.uid}`);\n return;\n }\n\n const localizedRoots = new Set();\n\n const translateableContent = await traverseEntity(\n ({ key, attribute, parent, path }, { remove }) => {\n if (IGNORED_FIELDS.includes(key)) {\n remove(key);\n return;\n }\n const hasLocalizedOption = attribute && isLocalizedAttribute(attribute);\n if (attribute && UNSUPPORTED_ATTRIBUTE_TYPES.includes(attribute.type)) {\n remove(key);\n return;\n }\n\n // If this field is localized, keep it (and mark as localized root if component/dz)\n if (hasLocalizedOption) {\n // If it's a component/dynamiczone, add to the set\n if (['component', 'dynamiczone'].includes(attribute.type)) {\n localizedRoots.add(path.raw);\n }\n return; // keep\n }\n\n if (parent && localizedRoots.has(parent.path.raw)) {\n // If parent exists in the localized roots set, keep it\n // If this is also a component/dz, propagate the localized root flag\n if (['component', 'dynamiczone'].includes(attribute?.type ?? '')) {\n localizedRoots.add(path.raw);\n }\n return; // keep\n }\n\n // Otherwise, remove the field\n remove(key);\n },\n { schema, getModel: strapi.getModel.bind(strapi) },\n document\n );\n\n if (Object.keys(translateableContent).length === 0) {\n strapi.log.info(\n `AI Localizations: no translatable content for ${schema.uid} document ${documentId}`\n );\n return;\n }\n\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 await aiLocalizationJobsService.upsertJobForDocument({\n contentType: model,\n documentId,\n sourceLocale: document.locale,\n targetLocales,\n status: 'processing',\n });\n\n let token: string;\n try {\n const tokenData = await strapi.get('ai').getAiToken();\n token = tokenData.token;\n } catch (error) {\n await aiLocalizationJobsService.upsertJobForDocument({\n documentId,\n contentType: model,\n sourceLocale: document.locale,\n targetLocales,\n status: 'failed',\n });\n\n throw new Error('Failed to retrieve AI token', {\n cause: error instanceof Error ? error : undefined,\n });\n }\n\n /**\n * Provide a schema to the LLM so that we can give it instructions about how to handle each\n * type of attribute. Only keep essential schema data to avoid cluttering the context.\n * Ignore fields that don't need to be localized.\n * TODO: also provide a schema of all the referenced components\n */\n const minimalContentTypeSchema = Object.fromEntries(\n Object.entries(schema.attributes)\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n .filter(([_, attr]) => {\n const isLocalized = isLocalizedAttribute(attr);\n const isSupportedType = !UNSUPPORTED_ATTRIBUTE_TYPES.includes(attr.type);\n return isLocalized && isSupportedType;\n })\n .map(([key, attr]) => {\n const minimalAttribute = { type: attr.type };\n if (attr.type === 'component') {\n (\n minimalAttribute as Schema.Attribute.Component<`${string}.${string}`, boolean>\n ).repeatable = attr.repeatable ?? false;\n }\n return [key, minimalAttribute];\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 contentTypeSchema: minimalContentTypeSchema,\n }),\n });\n\n if (!response.ok) {\n strapi.log.error(\n `AI Localizations request failed: ${response.status} ${response.statusText}`\n );\n\n await aiLocalizationJobsService.upsertJobForDocument({\n documentId,\n contentType: model,\n sourceLocale: document.locale,\n targetLocales,\n status: 'failed',\n });\n\n throw new Error(`AI Localizations request failed: ${response.statusText}`);\n }\n\n const aiResult = await response.json();\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.all(\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, works only on first level media fields (root level)\n const mergedData = structuredClone(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 await strapi.documents(model).update({\n documentId,\n locale,\n fields: [],\n data: mergedData,\n });\n\n await aiLocalizationJobsService.upsertJobForDocument({\n documentId,\n contentType: model,\n sourceLocale: document.locale,\n targetLocales,\n status: 'completed',\n });\n })\n );\n } catch (error) {\n await aiLocalizationJobsService.upsertJobForDocument({\n documentId,\n contentType: model,\n sourceLocale: document.locale,\n targetLocales,\n status: 'failed',\n });\n strapi.log.error('AI Localizations generation failed', error);\n }\n },\n setupMiddleware() {\n strapi.documents.use(async (context, next) => {\n const result = await next();\n\n // Only trigger for the allowed actions\n if (!['create', 'update'].includes(context.action)) {\n return result;\n }\n\n // Check if AI localizations are enabled before triggering\n const isEnabled = await this.isEnabled();\n if (!isEnabled) {\n return result;\n }\n\n // Don't await since localizations should be done in the background without blocking the request\n strapi\n .plugin('i18n')\n .service('ai-localizations')\n .generateDocumentLocalizations({\n model: context.contentType.uid,\n document: result,\n })\n .catch((error: any) => {\n strapi.log.error('AI Localizations generation failed', error);\n });\n\n return result;\n });\n },\n };\n};\n\nexport { createAILocalizationsService };\n"],"names":["isLocalizedAttribute","attribute","pluginOptions","i18n","localized","createAILocalizationsService","strapi","aiServerUrl","process","env","STRAPI_AI_URL","aiLocalizationJobsService","getService","UNSUPPORTED_ATTRIBUTE_TYPES","IGNORED_FIELDS","isEnabled","isAIEnabled","config","get","hasAccess","ee","features","settings","aiSettings","getSettings","aiLocalizations","generateDocumentLocalizations","model","document","isFeatureEnabled","schema","getModel","localeService","isLocalizedContentType","defaultLocale","getDefaultLocale","locale","documentId","log","warn","uid","localizedRoots","Set","translateableContent","traverseEntity","key","parent","path","remove","includes","hasLocalizedOption","type","add","raw","has","bind","Object","keys","length","info","localesList","find","targetLocales","filter","l","code","map","upsertJobForDocument","contentType","sourceLocale","status","token","tokenData","getAiToken","error","Error","cause","undefined","minimalContentTypeSchema","fromEntries","entries","attributes","_","attr","isLocalized","isSupportedType","minimalAttribute","repeatable","http","response","fetch","method","headers","Authorization","body","JSON","stringify","content","contentTypeSchema","ok","statusText","aiResult","json","mediaFields","Promise","all","localizations","localization","derivedDoc","documents","findOne","populate","mergedData","structuredClone","field","update","fields","data","setupMiddleware","use","context","next","result","action","plugin","service","catch"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-localizations.mjs","sources":["../../../server/src/services/ai-localizations.ts"],"sourcesContent":["import type { Core, Modules, Schema, UID } from '@strapi/types';\nimport { traverseEntity } from '@strapi/utils';\nimport { getService } from '../utils';\n\nconst isLocalizedAttribute = (attribute: Schema.Attribute.Attribute | undefined): boolean => {\n return (attribute?.pluginOptions as any)?.i18n?.localized === true;\n};\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 const aiLocalizationJobsService = getService('ai-localization-jobs');\n\n const UNSUPPORTED_ATTRIBUTE_TYPES: Schema.Attribute.Kind[] = ['media', 'relation', 'boolean'];\n const IGNORED_FIELDS = [\n 'id',\n 'documentId',\n 'createdAt',\n 'updatedAt',\n 'updatedBy',\n 'localizations',\n ];\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 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 const settings = getService('settings');\n const aiSettings = await settings.getSettings();\n if (!aiSettings?.aiLocalizations) {\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 isFeatureEnabled = await this.isEnabled();\n if (!isFeatureEnabled) {\n return;\n }\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 documentId = document.documentId;\n\n if (!documentId) {\n strapi.log.warn(`AI Localizations: missing documentId for ${schema.uid}`);\n return;\n }\n\n const localizedRoots = new Set();\n\n const translateableContent = await traverseEntity(\n ({ key, attribute, parent, path }, { remove }) => {\n if (IGNORED_FIELDS.includes(key)) {\n remove(key);\n return;\n }\n const hasLocalizedOption = attribute && isLocalizedAttribute(attribute);\n if (attribute && UNSUPPORTED_ATTRIBUTE_TYPES.includes(attribute.type)) {\n remove(key);\n return;\n }\n\n // If this field is localized, keep it (and mark as localized root if component/dz)\n if (hasLocalizedOption) {\n // If it's a component/dynamiczone, add to the set\n if (['component', 'dynamiczone'].includes(attribute.type)) {\n localizedRoots.add(path.raw);\n }\n return; // keep\n }\n\n if (parent && localizedRoots.has(parent.path.raw)) {\n // If parent exists in the localized roots set, keep it\n // If this is also a component/dz, propagate the localized root flag\n if (['component', 'dynamiczone'].includes(attribute?.type ?? '')) {\n localizedRoots.add(path.raw);\n }\n return; // keep\n }\n\n // Otherwise, remove the field\n remove(key);\n },\n { schema, getModel: strapi.getModel.bind(strapi) },\n document\n );\n\n if (Object.keys(translateableContent).length === 0) {\n strapi.log.info(\n `AI Localizations: no translatable content for ${schema.uid} document ${documentId}`\n );\n return;\n }\n\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 await aiLocalizationJobsService.upsertJobForDocument({\n contentType: model,\n documentId,\n sourceLocale: document.locale,\n targetLocales,\n status: 'processing',\n });\n\n let token: string;\n try {\n const tokenData = await strapi.get('ai').getAiToken();\n token = tokenData.token;\n } catch (error) {\n await aiLocalizationJobsService.upsertJobForDocument({\n documentId,\n contentType: model,\n sourceLocale: document.locale,\n targetLocales,\n status: 'failed',\n });\n\n throw new Error('Failed to retrieve AI token', {\n cause: error instanceof Error ? error : undefined,\n });\n }\n\n /**\n * Provide a schema to the LLM so that we can give it instructions about how to handle each\n * type of attribute. Only keep essential schema data to avoid cluttering the context.\n * Ignore fields that don't need to be localized.\n * TODO: also provide a schema of all the referenced components\n */\n const minimalContentTypeSchema = Object.fromEntries(\n Object.entries(schema.attributes)\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n .filter(([_, attr]) => {\n const isLocalized = isLocalizedAttribute(attr);\n const isSupportedType = !UNSUPPORTED_ATTRIBUTE_TYPES.includes(attr.type);\n return isLocalized && isSupportedType;\n })\n .map(([key, attr]) => {\n const minimalAttribute = { type: attr.type };\n if (attr.type === 'component') {\n (\n minimalAttribute as Schema.Attribute.Component<`${string}.${string}`, boolean>\n ).repeatable = attr.repeatable ?? false;\n }\n return [key, minimalAttribute];\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 contentTypeSchema: minimalContentTypeSchema,\n }),\n });\n\n if (!response.ok) {\n strapi.log.error(\n `AI Localizations request failed: ${response.status} ${response.statusText}`\n );\n\n await aiLocalizationJobsService.upsertJobForDocument({\n documentId,\n contentType: model,\n sourceLocale: document.locale,\n targetLocales,\n status: 'failed',\n });\n\n throw new Error(`AI Localizations request failed: ${response.statusText}`);\n }\n\n const aiResult = await response.json();\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.all(\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, works only on first level media fields (root level)\n const mergedData = structuredClone(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 await strapi.documents(model).update({\n documentId,\n locale,\n fields: [],\n data: mergedData,\n });\n\n await aiLocalizationJobsService.upsertJobForDocument({\n documentId,\n contentType: model,\n sourceLocale: document.locale,\n targetLocales,\n status: 'completed',\n });\n })\n );\n } catch (error) {\n await aiLocalizationJobsService.upsertJobForDocument({\n documentId,\n contentType: model,\n sourceLocale: document.locale,\n targetLocales,\n status: 'failed',\n });\n strapi.log.error('AI Localizations generation failed', error);\n }\n },\n setupMiddleware() {\n strapi.documents.use(async (context, next) => {\n const result = await next();\n\n // Only trigger for the allowed actions\n if (!['create', 'update'].includes(context.action)) {\n return result;\n }\n\n // Check if AI localizations are enabled before triggering\n const isEnabled = await this.isEnabled();\n if (!isEnabled) {\n return result;\n }\n\n // Don't await since localizations should be done in the background without blocking the request\n strapi\n .plugin('i18n')\n .service('ai-localizations')\n .generateDocumentLocalizations({\n model: context.contentType.uid,\n document: result,\n })\n .catch((error: any) => {\n strapi.log.error('AI Localizations generation failed', error);\n });\n\n return result;\n });\n },\n };\n};\n\nexport { createAILocalizationsService };\n"],"names":["isLocalizedAttribute","attribute","pluginOptions","i18n","localized","createAILocalizationsService","strapi","aiServerUrl","process","env","STRAPI_AI_URL","aiLocalizationJobsService","getService","UNSUPPORTED_ATTRIBUTE_TYPES","IGNORED_FIELDS","isEnabled","isAIEnabled","config","get","hasAccess","ee","features","settings","aiSettings","getSettings","aiLocalizations","generateDocumentLocalizations","model","document","isFeatureEnabled","schema","getModel","localeService","isLocalizedContentType","defaultLocale","getDefaultLocale","locale","documentId","log","warn","uid","localizedRoots","Set","translateableContent","traverseEntity","key","parent","path","remove","includes","hasLocalizedOption","type","add","raw","has","bind","Object","keys","length","info","localesList","find","targetLocales","filter","l","code","map","upsertJobForDocument","contentType","sourceLocale","status","token","tokenData","getAiToken","error","Error","cause","undefined","minimalContentTypeSchema","fromEntries","entries","attributes","_","attr","isLocalized","isSupportedType","minimalAttribute","repeatable","http","response","fetch","method","headers","Authorization","body","JSON","stringify","content","contentTypeSchema","ok","statusText","aiResult","json","mediaFields","Promise","all","localizations","localization","derivedDoc","documents","findOne","populate","mergedData","structuredClone","field","update","fields","data","setupMiddleware","use","context","next","result","action","plugin","service","catch"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ai-localizations.mjs","sources":["../../../server/src/services/ai-localizations.ts"],"sourcesContent":["import type { Core, Modules, Schema, UID } from '@strapi/types';\nimport { traverseEntity } from '@strapi/utils';\nimport { getService } from '../utils';\n\nconst isLocalizedAttribute = (attribute: Schema.Attribute.Attribute | undefined): boolean => {\n return (attribute?.pluginOptions as any)?.i18n?.localized === true;\n};\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 const aiLocalizationJobsService = getService('ai-localization-jobs');\n\n const UNSUPPORTED_ATTRIBUTE_TYPES: Schema.Attribute.Kind[] = [\n 'media',\n 'relation',\n 'boolean',\n 'enumeration',\n ];\n const IGNORED_FIELDS = [\n 'id',\n 'documentId',\n 'createdAt',\n 'updatedAt',\n 'updatedBy',\n 'localizations',\n ];\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 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 const settings = getService('settings');\n const aiSettings = await settings.getSettings();\n if (!aiSettings?.aiLocalizations) {\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 isFeatureEnabled = await this.isEnabled();\n if (!isFeatureEnabled) {\n return;\n }\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 documentId = document.documentId;\n\n if (!documentId) {\n strapi.log.warn(`AI Localizations: missing documentId for ${schema.uid}`);\n return;\n }\n\n const localizedRoots = new Set();\n\n const translateableContent = await traverseEntity(\n ({ key, attribute, parent, path }, { remove }) => {\n if (IGNORED_FIELDS.includes(key)) {\n remove(key);\n return;\n }\n const hasLocalizedOption = attribute && isLocalizedAttribute(attribute);\n if (attribute && UNSUPPORTED_ATTRIBUTE_TYPES.includes(attribute.type)) {\n remove(key);\n return;\n }\n\n // If this field is localized, keep it (and mark as localized root if component/dz)\n if (hasLocalizedOption) {\n // If it's a component/dynamiczone, add to the set\n if (['component', 'dynamiczone'].includes(attribute.type)) {\n localizedRoots.add(path.raw);\n }\n return; // keep\n }\n\n if (parent && localizedRoots.has(parent.path.raw)) {\n // If parent exists in the localized roots set, keep it\n // If this is also a component/dz, propagate the localized root flag\n if (['component', 'dynamiczone'].includes(attribute?.type ?? '')) {\n localizedRoots.add(path.raw);\n }\n return; // keep\n }\n\n // Otherwise, remove the field\n remove(key);\n },\n { schema, getModel: strapi.getModel.bind(strapi) },\n document\n );\n\n if (Object.keys(translateableContent).length === 0) {\n strapi.log.info(\n `AI Localizations: no translatable content for ${schema.uid} document ${documentId}`\n );\n return;\n }\n\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 await aiLocalizationJobsService.upsertJobForDocument({\n contentType: model,\n documentId,\n sourceLocale: document.locale,\n targetLocales,\n status: 'processing',\n });\n\n let token: string;\n try {\n const tokenData = await strapi.get('ai').getAiToken();\n token = tokenData.token;\n } catch (error) {\n await aiLocalizationJobsService.upsertJobForDocument({\n documentId,\n contentType: model,\n sourceLocale: document.locale,\n targetLocales,\n status: 'failed',\n });\n\n throw new Error('Failed to retrieve AI token', {\n cause: error instanceof Error ? error : undefined,\n });\n }\n\n /**\n * Provide a schema to the LLM so that we can give it instructions about how to handle each\n * type of attribute. Only keep essential schema data to avoid cluttering the context.\n * Ignore fields that don't need to be localized.\n * TODO: also provide a schema of all the referenced components\n */\n const minimalContentTypeSchema = Object.fromEntries(\n Object.entries(schema.attributes)\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n .filter(([_, attr]) => {\n const isLocalized = isLocalizedAttribute(attr);\n const isSupportedType = !UNSUPPORTED_ATTRIBUTE_TYPES.includes(attr.type);\n return isLocalized && isSupportedType;\n })\n .map(([key, attr]) => {\n const minimalAttribute = { type: attr.type };\n if (attr.type === 'component') {\n (\n minimalAttribute as Schema.Attribute.Component<`${string}.${string}`, boolean>\n ).repeatable = attr.repeatable ?? false;\n }\n return [key, minimalAttribute];\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 contentTypeSchema: minimalContentTypeSchema,\n }),\n });\n\n if (!response.ok) {\n strapi.log.error(\n `AI Localizations request failed: ${response.status} ${response.statusText}`\n );\n\n await aiLocalizationJobsService.upsertJobForDocument({\n documentId,\n contentType: model,\n sourceLocale: document.locale,\n targetLocales,\n status: 'failed',\n });\n\n throw new Error(`AI Localizations request failed: ${response.statusText}`);\n }\n\n const aiResult = await response.json();\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.all(\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, works only on first level media fields (root level)\n const mergedData = structuredClone(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 await strapi.documents(model).update({\n documentId,\n locale,\n fields: [],\n data: mergedData,\n });\n\n await aiLocalizationJobsService.upsertJobForDocument({\n documentId,\n contentType: model,\n sourceLocale: document.locale,\n targetLocales,\n status: 'completed',\n });\n })\n );\n } catch (error) {\n await aiLocalizationJobsService.upsertJobForDocument({\n documentId,\n contentType: model,\n sourceLocale: document.locale,\n targetLocales,\n status: 'failed',\n });\n strapi.log.error('AI Localizations generation failed', error);\n }\n },\n setupMiddleware() {\n strapi.documents.use(async (context, next) => {\n const result = await next();\n\n // Only trigger for the allowed actions\n if (!['create', 'update'].includes(context.action)) {\n return result;\n }\n\n // Check if AI localizations are enabled before triggering\n const isEnabled = await this.isEnabled();\n if (!isEnabled) {\n return result;\n }\n\n // Don't await since localizations should be done in the background without blocking the request\n strapi\n .plugin('i18n')\n .service('ai-localizations')\n .generateDocumentLocalizations({\n model: context.contentType.uid,\n document: result,\n })\n .catch((error: any) => {\n strapi.log.error('AI Localizations generation failed', error);\n });\n\n return result;\n });\n },\n };\n};\n\nexport { createAILocalizationsService };\n"],"names":["isLocalizedAttribute","attribute","pluginOptions","i18n","localized","createAILocalizationsService","strapi","aiServerUrl","process","env","STRAPI_AI_URL","aiLocalizationJobsService","getService","UNSUPPORTED_ATTRIBUTE_TYPES","IGNORED_FIELDS","isEnabled","isAIEnabled","config","get","hasAccess","ee","features","settings","aiSettings","getSettings","aiLocalizations","generateDocumentLocalizations","model","document","isFeatureEnabled","schema","getModel","localeService","isLocalizedContentType","defaultLocale","getDefaultLocale","locale","documentId","log","warn","uid","localizedRoots","Set","translateableContent","traverseEntity","key","parent","path","remove","includes","hasLocalizedOption","type","add","raw","has","bind","Object","keys","length","info","localesList","find","targetLocales","filter","l","code","map","upsertJobForDocument","contentType","sourceLocale","status","token","tokenData","getAiToken","error","Error","cause","undefined","minimalContentTypeSchema","fromEntries","entries","attributes","_","attr","isLocalized","isSupportedType","minimalAttribute","repeatable","http","response","fetch","method","headers","Authorization","body","JSON","stringify","content","contentTypeSchema","ok","statusText","aiResult","json","mediaFields","Promise","all","localizations","localization","derivedDoc","documents","findOne","populate","mergedData","structuredClone","field","update","fields","data","setupMiddleware","use","context","next","result","action","plugin","service","catch"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-localizations.d.ts","sourceRoot":"","sources":["../../../../server/src/services/ai-localizations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAU,GAAG,EAAE,MAAM,eAAe,CAAC;AAQhE,QAAA,MAAM,4BAA4B,eAAgB;IAAE,MAAM,EAAE,KAAK,MAAM,CAAA;CAAE;;
|
|
1
|
+
{"version":3,"file":"ai-localizations.d.ts","sourceRoot":"","sources":["../../../../server/src/services/ai-localizations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAU,GAAG,EAAE,MAAM,eAAe,CAAC;AAQhE,QAAA,MAAM,4BAA4B,eAAgB;IAAE,MAAM,EAAE,KAAK,MAAM,CAAA;CAAE;;IA4CrE;;;;OAIG;wDAIA;QACD,KAAK,EAAE,IAAI,WAAW,CAAC;QACvB,QAAQ,EAAE,QAAQ,SAAS,CAAC,WAAW,CAAC;KACzC;;CAgQJ,CAAC;AAEF,OAAO,EAAE,4BAA4B,EAAE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@strapi/i18n",
|
|
3
|
-
"version": "0.0.0-next.
|
|
3
|
+
"version": "0.0.0-next.e822ba8a3443f5fce869d85539f9fdaa02e10639",
|
|
4
4
|
"description": "Create read and update content in different languages, both from the Admin Panel and from the API",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"@reduxjs/toolkit": "1.9.7",
|
|
60
60
|
"@strapi/design-system": "2.0.1",
|
|
61
61
|
"@strapi/icons": "2.0.1",
|
|
62
|
-
"@strapi/utils": "0.0.0-next.
|
|
62
|
+
"@strapi/utils": "0.0.0-next.e822ba8a3443f5fce869d85539f9fdaa02e10639",
|
|
63
63
|
"lodash": "4.17.21",
|
|
64
64
|
"qs": "6.11.1",
|
|
65
65
|
"react-intl": "6.6.2",
|
|
@@ -68,13 +68,13 @@
|
|
|
68
68
|
"zod": "3.25.67"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
|
-
"@strapi/admin": "0.0.0-next.
|
|
72
|
-
"@strapi/admin-test-utils": "0.0.0-next.
|
|
73
|
-
"@strapi/content-manager": "0.0.0-next.
|
|
74
|
-
"@strapi/database": "0.0.0-next.
|
|
75
|
-
"@strapi/types": "0.0.0-next.
|
|
76
|
-
"@testing-library/react": "
|
|
77
|
-
"@testing-library/user-event": "14.
|
|
71
|
+
"@strapi/admin": "0.0.0-next.e822ba8a3443f5fce869d85539f9fdaa02e10639",
|
|
72
|
+
"@strapi/admin-test-utils": "0.0.0-next.e822ba8a3443f5fce869d85539f9fdaa02e10639",
|
|
73
|
+
"@strapi/content-manager": "0.0.0-next.e822ba8a3443f5fce869d85539f9fdaa02e10639",
|
|
74
|
+
"@strapi/database": "0.0.0-next.e822ba8a3443f5fce869d85539f9fdaa02e10639",
|
|
75
|
+
"@strapi/types": "0.0.0-next.e822ba8a3443f5fce869d85539f9fdaa02e10639",
|
|
76
|
+
"@testing-library/react": "16.3.0",
|
|
77
|
+
"@testing-library/user-event": "14.6.1",
|
|
78
78
|
"koa": "2.16.1",
|
|
79
79
|
"msw": "1.3.0",
|
|
80
80
|
"react": "18.3.1",
|