Closed bwlng closed 5 years ago
Hello @bwlng,
could you specify the source plugin version you are using and provide the configuration in gatsby-config.js
for the source plugin?
Just FYI: there are the places, where the data are loaded:
Would you mind to describe your scenario, so that I have the context for the advice?
Hi @Simply007 — I'm using version 3.1.0 of the source plugin. This is what my config looks like:
{
resolve: `gatsby-source-kentico-cloud`,
options: {
deliveryClientConfig: {
previewApiKey: process.env.KENTICO_CLOUD_PREVIEW_API_KEY,
projectId: process.env.KENTICO_CLOUD_PROJECT_ID, // Fill in your Project ID
enablePreviewMode: Boolean(process.env.KENTICO_CLOUD_ENABLE_PREVIEW_MODE || false),
typeResolvers: [],
},
languageCodenames: [
`en-US`, // Languages in Kentico (Project settings -> Localization)
`de`,
`es`,
`fr`,
`it`,
`pl`,
`pt-BR`,
`jp`,
`zh-CN`
]
}
},
It does look like the nodes are created — they are logged to the console when I run gatsby develop
, but I can't seem to retrieve them from a GraphQL query.
I'm hoping that a query like the one below would display all Page content items with fallback content from the default language specified in Kentico Cloud. Similarly, for queries were a content item as been explicitly translated, but a linked item hasn't, I'd like the "not translated" linked item to be included with the default language variant.
{
allKenticoCloudItemPage {
edges {
node {
system {
type
language
}
elements {
title {
value
}
}
otherLanguages {
elements {
title {
value
}
}
}
}
}
}
}
The above only shows nodes that have been explicitly translated.
What would a query look like that will include the data that is loaded?
Hello @bwlng,
I have briefly gone through the code and the otherLanguages
property.
It is being filled only by the items that are in the response with a specific language set. When you load the data and the language fallback is used content item has system.language
set to the original language (not de
but en-US
) in your case.
There is a possibility to transform the node in the onCreateNode lifecycle method prepare the structure you need in your code.
You could try to tune up the source plugin locally, but if there is any chance of changing this behavior via source code modification, it would lead to the breaking change.
I am currently leaving for vacation until 18th of September so that I not able to try or investigate the recommendation right now, but I think the onCreateNode
lifecycle node could help you out!
A workaround is more-or-less putting all translated variants into otherLanguages
until @Simply007 can work out proper support for fallback language variants:
exports.onCreateNode = ({ node }) => {
if (node.system && node.system.language) {
let otherLanguages = [node.id]
if (
node.otherLanguages___NODE &&
node.otherLanguages___NODE[0] !== node.id
) {
otherLanguages = [node.id, ...node.otherLanguages___NODE]
}
node.otherLanguages___NODE = otherLanguages
}
}
This should make sure that otherLanguages
contains at least the default language variant, even if there are no translated variants. Then, in your components or how you use your queries, always check system.language
to make sure the variant is the language that you want.
@yuriys-kentico Thanks for the suggestion. I tried the workaround and it does make sure that otherLanguages
always has a value, but in my testing it seems to either duplicate the current content item into otherLanguages
(in instances where I'm querying the default language) or include the default language in instances where it already when have been included (when I'm querying de
for example).
I think the simplest example of what I'm trying to accomplish is a query like this from the standard API: https://preview-deliver.kenticocloud.com/PROJ_ID/items/homepage?language=es
Where the homepage
item hasn't been translated to es
yet. With the standard API it will return the content item from the default language (en-US
in my case). Is there a similar workaround where a query in a Gatsby project would return the fallback language?
@yuriys-kentico @Simply007 Is it possible to determine the language a node was created from by the time the node is available in onCreateNode
? It seems that the node is created with the an ID created from the system language and and the item’s codename, so if fallback content is used, the node will overwrite previous nodes with the same values for contentItem.system.codename
and contentItem.system.language
.
Would there be any negative side effects if each node included the preferred language (i.e. the language parameter used during the client request)?
These modifications to itemNodes.js
seem to accomplish what I'm aiming for.
Default language nodes:
const getFromDefaultLanguage = async (client, defaultLanguageCodename, contentTypeNodes, createNodeId) => {
…
const contentItemNodes = itemsFlatted.map(contentItem => {
try {
// Add the language parameter used on the client request to a system field
contentItem.system.preferred_language = defaultLanguageCodename
return createContentItemNode(createNodeId, contentItem, contentTypeNodes);
} catch (error) {
console.error(error);
}
});
…
};
Non-default language nodes
const getFromNonDefaultLanguage = async (client, nonDefaultLanguageCodenames, contentTypeNodes, createNodeId) => {
…
for (const languageCodename of nonDefaultLanguageCodenames) {
const languageResponse = await client.items().languageParameter(languageCodename).getPromise();
…
const contentItemsNodes = languageItemsFlatted.map(languageItem => {
// Add the language parameter used on the client request to a system field
languageItem.system.preferred_language = languageCodename
return createContentItemNode(createNodeId, languageItem, contentTypeNodes)
});
nonDefaultLanguageItemNodes.set(languageCodename, contentItemsNodes);
}
;
return nonDefaultLanguageItemNodes;
};
Use the new preferred_language
param for the nodeId
:
const createContentItemNode = (createNodeId, contentItem, contentTypeNodes) => {
…
const codenameParamCase = changeCase.paramCase(contentItem.system.codename);
// Use system.preferred_language instead of system.language
const languageParamCase = changeCase.paramCase(contentItem.system.preferred_language);
const nodeId = createNodeId(`kentico-cloud-item-${codenameParamCase}-${languageParamCase}`);
…
};
Any other way to achieve a similar solution w/o modifying the source plugin?
The issue is currently being solved in cooperation with @bwlng.
There is also a rebranding from Kentico Cloud to Kontent in progress.
There is already a beta with the fix:
Once the new version is released with the readme + upgrade guide I am about to close this issue.
Brief bug description
It doesn’t appear that the source plugin includes fallback content as described in the Localization in Kentico Cloud portions of the docs.
Repro steps
When querying data, include
otherLanguages
in the query and include codenames for additional languages in thedeliveryClientConfig
object ingatsby-config.js
. Content Items won't be included if a translation hasn't been created.Expected behavior
If the language is configured to use a default fallback, content should be included from the default language.
Is there a workaround or config I'm missing?