Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,6 @@
},
"run-if-changed": {
"renovate.json5": "yarn renovate-config-validator"
}
},
"version": "0.0.0"
}
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) {
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
22 changes: 14 additions & 8 deletions packages/gatsby-source-strapi/src/normalize.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ import { getContentTypeSchema, makeParentNodeName } from "./helpers";
const prepareJSONNode = (json, context) => {
const { createContentDigest, createNodeId, parentNode, attributeName } = context;

const jsonNodeId = createNodeId(
`${parentNode.strapi_document_id_or_regular_id}-${parentNode.internal.type}-${attributeName}-JSONNode`,
);
// Use parentNode.id instead of strapi_document_id_or_regular_id to ensure uniqueness across locales
const jsonNodeId = createNodeId(`${parentNode.id}-${attributeName}-JSONNode`);

const JSONNode = {
...(_.isPlainObject(json) ? { ...json } : { strapi_json_value: json }),
Expand Down Expand Up @@ -48,7 +47,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 +80,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 +146,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