Repository: gatsbyjs/gatsby
File: packages/gatsby-source-drupal/src/utils.js (JavaScript)

Code before:
  }
}

exports.fetchLanguageConfig = fetchLanguageConfig

const handleReferences = (node, languageConfig, { getNode, createNodeId }) => {
  const relationships = node.relationships
  const rootNodeLanguage = node.langcode

  if (node.drupal_relationships) {
    const referencedNodes = []
    _.each(node.drupal_relationships, (v, k) => {
      if (!v.data) return
      const nodeFieldName = `${k}___NODE`
      if (_.isArray(v.data)) {
        relationships[nodeFieldName] = _.compact(
          v.data.map(data => {
            const isTranslatableReferencedNodeType = (
              languageConfig
              .translatableEntities
              .some(entity => entity.id === data.type)
            )
            const referenceLanguagePrefix = isTranslatableReferencedNodeType
              ? rootNodeLanguage
              : languageConfig.defaultLanguage
            const referencedNodeId = createNodeId(`${referenceLanguagePrefix}${data.id}`)
            if (!getNode(referencedNodeId)) {
              return null
            }

            referencedNodes.push(referencedNodeId)
            return referencedNodeId
          })
        )

        const meta = _.compact(
          v.data.map(data => (!_.isEmpty(data.meta) ? data.meta : null))
        )
        // If there's meta on the field and it's not an existing/internal one
        // create a new node's field with that meta. It can't exist on both
        // @see https://jsonapi.org/format/#document-resource-object-fields
        if (!_.isEmpty(meta) && !(k in node)) {
          node[k] = meta
        }
      } else {
        const isTranslatableReferencedNodeType = (
          languageConfig
          .translatableEntities
          .some(entity => entity.id === v.data.type)
        )
        const referenceLanguagePrefix = isTranslatableReferencedNodeType

Review comment (suggestion):
I'm not sure I understand why we can't just use `createNodeId(`${rootNodeLanguag}${data.id}`)` here and drop lines 81 through 88.

If the entity in Drupal is translatable it uses the rootNodeLanguage value anyway. However, if the entity is not translatable it uses the defaultLanguage which would be `und`. The problem with this approach is that in `normalize.js` it uses the langcode to construct the node id. This means that these references don't look like they will work properly for nodes that are not translateable.

For instance, let's say I have an article content type that does NOT have languages enabled. Assume an article that is language `en` with UUID `1234-1234` and it references a file with language `en` and UUID `abcd-abcd`. 

The nodes will be first created as `en1234-1234` and `enabcd-abcd` in `normalize.js`. Now when it is trying to handle the references the article will try to create a reference using languageConfig.defaultLanguage (which is `und`) so it looks for `undabcd-abcd` which isn't going to correctly reference the file.

If we just set the variable up above to `const rootNodeLanguage = node.langcode ? node.langcode : `und`` and get rid of this extra logic I think it works for both scenarios (translations on and translations off).

I could be missing something here though, so jump in if it needs further clarification. Either way, I can confirm this seems to break on entities without language selection turned on that reference other entities without language selection turned on.

Code after:
            rootNodeLanguage,
            v.data.meta?.target_revision_id,
            entityReferenceRevisions
          )
        )
        if (getNode(referencedNodeId)) {
          relationships[nodeFieldName] = referencedNodeId
          referencedNodes.push(referencedNodeId)
        }
        // If there's meta on the field and it's not an existing/internal one
        // create a new node's field with that meta. It can't exist on both
        // @see https://jsonapi.org/format/#document-resource-object-fields
        if (!_.isEmpty(v.data.meta) && !(k in node)) {
          node[k] = v.data.meta
        }
      }
    })

    delete node.drupal_relationships
    referencedNodesLookup.set(node, referencedNodes)
    if (referencedNodes.length) {
      const nodeFieldName = `${node.internal.type}___NODE`
      referencedNodes.forEach(nodeID => {
        const referencedNode = getNode(nodeID)
        if (!referencedNode.relationships[nodeFieldName]) {
          referencedNode.relationships[nodeFieldName] = []
        }

        if (!referencedNode.relationships[nodeFieldName].includes(node.id)) {
          referencedNode.relationships[nodeFieldName].push(node.id)
        }

        let backRefsNames = backRefsNamesLookup.get(referencedNode)
        if (!backRefsNames) {
          backRefsNames = []
          backRefsNamesLookup.set(referencedNode, backRefsNames)
        }

        if (!backRefsNames.includes(nodeFieldName)) {
          backRefsNames.push(nodeFieldName)
        }
      })
    }
  }

  node.relationships = relationships
}

exports.handleReferences = handleReferences

const handleWebhookUpdate = async (