Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/little-socks-approve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"gatsby-source-strapi": patch
---

fix(gatsby-source-strapi): Strapi v5 Fix "locale=all" i18n feature for Single Types and Collection Types
152 changes: 103 additions & 49 deletions packages/gatsby-source-strapi/src/fetch.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ export const fetchEntity = async (
},
},
});
for (const localization of response.data.attributes.localizations.data) {
otherLocales.push(localization.attributes.locale);
for (const localization of response.data.localizations) {
otherLocales.push(localization.locale);
}
} else {
// Only one locale
Expand Down Expand Up @@ -140,65 +140,119 @@ export const fetchEntities = async (
},
};

// Use locale from pluginOptions if it's defined
if (pluginOptions?.i18n?.locale) {
// Handle internationalization
const locale = pluginOptions?.i18n?.locale;
const localesToFetch = [];

if (locale) {
delete queryParams.locale;
queryParams.locale = pluginOptions.i18n.locale;

if (locale === "all") {
// Get all available locales from first entity
const { data: previewResponse } = await axiosInstance({
...options,
params: {
...options.params,
pagination: { pageSize: 1 },
populate: {
localizations: {
fields: ["locale"],
},
},
},
});

// Add default locale from first entry
if (previewResponse.data?.[0]) {
const firstEntry = previewResponse.data[0];
const localesSet = new Set();

// Add current entry's locale
if (firstEntry.locale) {
localesSet.add(firstEntry.locale);
}

// Add other locales from localizations array or data property
const localizations = firstEntry.localizations?.data || firstEntry.localizations || [];
for (const localization of localizations) {
const localeValue = localization.locale || localization.attributes?.locale;
if (localeValue) {
localesSet.add(localeValue);
}
}

localesToFetch.push(...localesSet);
}
} else {
// Only one locale
localesToFetch.push(locale);
}
} else {
// No locale specified, fetch default
localesToFetch.push(undefined);
}

try {
reporter.info(
`Starting to fetch data from Strapi - ${
options.url
} with ${options.paramsSerializer.serialize(options.params)}`,
);
// Fetch data for each locale
const allLocalesData = [];

for (const currentLocale of localesToFetch) {
Comment thread
SylvainGibert marked this conversation as resolved.
const localeOptions = {
...options,
params: {
...options.params,
...(currentLocale && { locale: currentLocale }),
},
};

const { data: response } = await axiosInstance(options);
const { data: response } = await axiosInstance(localeOptions);

const data = response?.data || response;
const meta = response?.meta;
const data = response?.data || response;
const meta = response?.meta;

const page = Number.parseInt(meta?.pagination.page || 1, 10);
const pageCount = Number.parseInt(meta?.pagination.pageCount || 1, 10);
const page = Number.parseInt(meta?.pagination.page || 1, 10);
const pageCount = Number.parseInt(meta?.pagination.pageCount || 1, 10);

const pagesToGet = Array.from({
length: pageCount - page,
}).map((_, index) => index + page + 1);
const pagesToGet = Array.from({
length: pageCount - page,
}).map((_, index) => index + page + 1);

const fetchPagesPromises = pagesToGet.map((page) => {
return (async () => {
const fetchOptions = {
...options,
params: {
...options.params,
pagination: {
...options.params.pagination,
page,
const fetchPagesPromises = pagesToGet.map((page) => {
return (async () => {
const fetchOptions = {
...localeOptions,
params: {
...localeOptions.params,
pagination: {
...localeOptions.params.pagination,
page,
},
},
},
};

reporter.info(
`Starting to fetch page ${page} from Strapi - ${
fetchOptions.url
} with ${options.paramsSerializer.serialize(fetchOptions.params)}`,
);

try {
const {
data: { data },
} = await axiosInstance(fetchOptions);

return data;
} catch (error) {
reporter.panic(`Failed to fetch data from Strapi ${fetchOptions.url}`, error);
}
})();
});
};

reporter.info(
`Starting to fetch page ${page} from Strapi - ${
fetchOptions.url
} with ${options.paramsSerializer.serialize(fetchOptions.params)}`,
);

const results = await Promise.all(fetchPagesPromises);
try {
const {
data: { data },
} = await axiosInstance(fetchOptions);

return data;
} catch (error) {
reporter.panic(`Failed to fetch data from Strapi ${fetchOptions.url}`, error);
}
})();
});

const results = await Promise.all(fetchPagesPromises);
allLocalesData.push(...data, ...flattenDeep(results));
}

const cleanedData = [...data, ...flattenDeep(results)].map((entry) =>
const cleanedData = allLocalesData.map((entry) =>
cleanData(entry, { ...context, contentTypeUid: uid }, version),
);

Expand Down
17 changes: 12 additions & 5 deletions packages/gatsby-source-strapi/src/normalize.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,12 @@ const prepareRelationNode = (relation, context) => {

const nodeType = makeParentNodeName(schemas, targetSchemaUid);
const strapi_document_id_or_regular_id = relation.documentId || relation.id; // support both v5 and v4
const relationNodeId = createNodeId(`${nodeType}-${strapi_document_id_or_regular_id}`);

// Include locale in node ID to support multiple locales for the same entity
const localeIdentifier = relation.locale ? `-${relation.locale}` : "";
const relationNodeId = createNodeId(
`${nodeType}-${strapi_document_id_or_regular_id}${localeIdentifier}`,
);

const node = {
...relation,
Expand Down Expand Up @@ -76,9 +81,8 @@ const prepareRelationNode = (relation, context) => {
*/
const prepareTextNode = (text, context) => {
const { createContentDigest, createNodeId, parentNode, attributeName } = context;
const textNodeId = createNodeId(
`${parentNode.strapi_document_id_or_regular_id}-${parentNode.internal.type}-${attributeName}-TextNode`,
);
// Use parentNode.id instead of strapi_document_id_or_regular_id to ensure uniqueness across locales
const textNodeId = createNodeId(`${parentNode.id}-${attributeName}-TextNode`);

const textNode = {
id: textNodeId,
Expand Down Expand Up @@ -143,8 +147,11 @@ export const createNodes = (entity, context, uid) => {
// also, support both v5 documentId and v4 id
const strapi_document_id_or_regular_id = entity.documentId || entity.id;

// Include locale in node ID to support multiple locales for the same entity
const localeIdentifier = entity.locale ? `-${entity.locale}` : "";

let entryNode = {
id: createNodeId(`${nodeType}-${strapi_document_id_or_regular_id}`),
id: createNodeId(`${nodeType}-${strapi_document_id_or_regular_id}${localeIdentifier}`),
documentId: entity.documentId,
strapi_id: entity.id,
strapi_document_id_or_regular_id,
Expand Down