Skip to content

Commit b278fe3

Browse files
committed
chore: restore complex attributes
1 parent 4e3b7c0 commit b278fe3

File tree

1 file changed

+32
-15
lines changed

1 file changed

+32
-15
lines changed

packages/plugins/i18n/server/src/services/ai-localizations.ts

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,16 @@ import type { Core, Modules, Schema, UID } from '@strapi/types';
22
import { traverseEntity } from '@strapi/utils';
33
import { getService } from '../utils';
44

5+
const isLocalizedAttribute = (attribute: Schema.Attribute.Attribute | undefined): boolean => {
6+
return (attribute?.pluginOptions as any)?.i18n?.localized === true;
7+
};
8+
59
const createAILocalizationsService = ({ strapi }: { strapi: Core.Strapi }) => {
610
// TODO: add a helper function to get the AI server URL
711
const aiServerUrl = process.env.STRAPI_AI_URL || 'https://strapi-ai.apps.strapi.io';
812
const aiLocalizationJobsService = getService('ai-localization-jobs');
913

10-
const UNSUPPORTED_ATTRIBUTE_TYPES: Schema.Attribute.Kind[] = [
11-
'media',
12-
'relation',
13-
// TODO: remove these once the AI server can handle them reliably
14-
'component',
15-
'dynamiczone',
16-
'json',
17-
];
14+
const UNSUPPORTED_ATTRIBUTE_TYPES: Schema.Attribute.Kind[] = ['media', 'relation'];
1815

1916
return {
2017
// Async to avoid changing the signature later (there will be a db check in the future)
@@ -88,7 +85,7 @@ const createAILocalizationsService = ({ strapi }: { strapi: Core.Strapi }) => {
8885
// Extract only the localized content from the document
8986
const translateableContent = await traverseEntity(
9087
({ key, attribute }, { remove }) => {
91-
const hasLocalizedOption = attribute?.pluginOptions?.i18n?.localized === true;
88+
const hasLocalizedOption = attribute && isLocalizedAttribute(attribute);
9289
// Only keep fields that actually need to be localized
9390
// TODO: remove blocks from this list once the AI server can handle it reliably
9491
if (!hasLocalizedOption || UNSUPPORTED_ATTRIBUTE_TYPES.includes(attribute.type)) {
@@ -138,6 +135,31 @@ const createAILocalizationsService = ({ strapi }: { strapi: Core.Strapi }) => {
138135
});
139136
}
140137

138+
/**
139+
* Provide a schema to the LLM so that we can give it instructions about how to handle each
140+
* type of attribute. Only keep essential schema data to avoid cluttering the context.
141+
* Ignore fields that don't need to be localized.
142+
* TODO: also provide a schema of all the referenced components
143+
*/
144+
const minimalContentTypeSchema = Object.fromEntries(
145+
Object.entries(schema.attributes)
146+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
147+
.filter(([_, attr]) => {
148+
const isLocalized = isLocalizedAttribute(attr);
149+
const isSupportedType = !UNSUPPORTED_ATTRIBUTE_TYPES.includes(attr.type);
150+
return isLocalized && isSupportedType;
151+
})
152+
.map(([key, attr]) => {
153+
const minimalAttribute = { type: attr.type };
154+
if (attr.type === 'component') {
155+
(
156+
minimalAttribute as Schema.Attribute.Component<`${string}.${string}`, boolean>
157+
).repeatable = attr.repeatable ?? false;
158+
}
159+
return [key, minimalAttribute];
160+
})
161+
);
162+
141163
strapi.log.http('Contacting AI Server for localizations generation');
142164
const response = await fetch(`${aiServerUrl}/i18n/generate-localizations`, {
143165
method: 'POST',
@@ -149,12 +171,7 @@ const createAILocalizationsService = ({ strapi }: { strapi: Core.Strapi }) => {
149171
content: translateableContent,
150172
sourceLocale: document.locale,
151173
targetLocales,
152-
schema: Object.fromEntries(
153-
Object.entries(schema.attributes)
154-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
155-
.filter(([_, attr]) => (attr?.pluginOptions as any)?.i18n?.localized === true)
156-
.map(([key, attr]) => [key, { type: attr.type }])
157-
),
174+
contentTypeSchema: minimalContentTypeSchema,
158175
}),
159176
});
160177

0 commit comments

Comments
 (0)