gatsbyjs / gatsby

The best React-based framework with performance, scalability and security built in.
https://www.gatsbyjs.com
MIT License
55.21k stars 10.33k forks source link

[gatsby-source-contentful]: Not loading image assets when using non-default locale. #7272

Closed supermoos closed 6 years ago

supermoos commented 6 years ago

Description

Looks like there is a bug in which all images assets are null, when using a different language than english:

Steps to reproduce

Here's my GraphQL Query:

fragment LandingPageGalleryFragment on ContentfulPageHome {
  landingGallery {
    id
    title {
      title
    }
    subtitle {
      subtitle
    }
    ctaText
    ctaLink {
      ctaLink
    }
    image {
      id
      node_locale
      description
      file {
        url
        fileName
        contentType
      }
      desktop: sizes(maxWidth: 1680, maxHeight: 945, resizingBehavior: FILL) {
        src
        sizes
      }
      mobile: sizes(maxWidth: 767, maxHeight: 1093, resizingBehavior: FILL) {
        src
        sizes
      }
    }
  }
}

query HomeQuery($languageCode: String) {
  contentfulPageHome(contentful_id: {eq: "REDACTED"}, node_locale: {eq: $languageCode}) {
    id
    slug
    ...LandingPageGalleryFragment
  }
}

Expected result

I should get the image source back for the language request on the pageHome.

Actual result

GraphQL result:

{
  "data": {
    "contentfulPageHome": {
      "id": "RETURN_ID___da-DK",
      "slug": "/danish",
      "landingGallery": [
        {
          "id": "REDACTED___da-DK",
          "title": {
            "title": " danish test"
          },
          "subtitle": {
            "subtitle": " danish test"
          },
          "ctaText": "aefaae ",
          "ctaLink": {
            "ctaLink": "https://google.dk"
          },
          "image": {
            "id": "REDACTED___da-DK",
            "node_locale": "da-DK",
            "description": "",
            "file": null,
            "desktop": {
              "src": null,
              "sizes": null
            },
            "mobile": {
              "src": null,
              "sizes": null
            }
          }
        }
      ]
    }
  }
}

Environment

  System:
    OS: macOS High Sierra 10.13.6
    CPU: x64 Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz
    Shell: 5.3 - /bin/zsh
  Binaries:
    Node: 8.11.3 - /usr/local/bin/node
    npm: 5.6.0 - /usr/local/bin/npm
  Browsers:
    Firefox: 60.0.1
    Safari: 11.1.2
  npmPackages:
    gatsby: ^1.9.277 => 1.9.277
    gatsby-image: ^1.0.55 => 1.0.55
    gatsby-link: latest => 1.6.46
    gatsby-module-loader: latest => 1.0.11
    gatsby-plugin-google-analytics: latest => 1.0.31
    gatsby-plugin-i18n: ^0.4.1 => 0.4.1
    gatsby-plugin-offline: latest => 1.0.18
    gatsby-plugin-react-helmet: ^1.0.5 => 1.0.8
    gatsby-plugin-react-next: ^1.0.11 => 1.0.11
    gatsby-plugin-sass: ^1.0.26 => 1.0.26
    gatsby-plugin-sharp: ^1.6.48 => 1.6.48
    gatsby-plugin-sitemap: ^1.2.25 => 1.2.25
    gatsby-plugin-typescript: ^1.4.20 => 1.4.20
    gatsby-source-contentful: latest => 1.3.54
    gatsby-transformer-remark: latest => 1.7.44
    gatsby-transformer-sharp: ^1.6.27 => 1.6.27
  npmGlobalPackages:
    gatsby-cli: 1.1.58

File contents (if changed)

gatsby-config.js:

const languages = require('./src/data/languages');

module.exports = {
    siteMetadata: {
        title: `Gatsby with Contentful`,
        languages,
        siteUrl: `REDACTED`
    },
    plugins: [
        `gatsby-plugin-react-helmet`,
        {
            resolve: 'gatsby-plugin-i18n',
            options: {
                langKeyForNull: languages.defaultLangKey,
                langKeyDefault: languages.defaultLangKey,
                useLangKeyLayout: false
            }
        },
        {
            resolve: `gatsby-source-contentful`,
            options: {
                spaceId: `REDACTED`,
                accessToken: `REDACTED`,
            },
        },
        {
            resolve: `gatsby-plugin-sass`,
            options: {
                // includePaths: ["./src/styles"],
                data: `@import "./src/styles/variables";@import "./src/styles/mixins";`
            },
        },
        `gatsby-transformer-remark`,
        `gatsby-transformer-sharp`,
        `gatsby-plugin-sharp`,
        `gatsby-plugin-typescript`,
        `gatsby-plugin-sitemap`
    ],
};

package.json:

{
  "name": "gatsby-starter-contentful-i18n",
  "private": true,
  "description": "Gatsby example site using the Contentful source plugin and i18n",
  "version": "1.0.0",
  "author": "Paul McCrodden <paul.mccrodden@x-team.com> (paulmccrodden.com)",
  "dependencies": {
    "@types/gsap": "^1.19.2",
    "gatsby": "^1.9.277",
    "gatsby-image": "^1.0.55",
    "gatsby-link": "latest",
    "gatsby-module-loader": "latest",
    "gatsby-plugin-google-analytics": "latest",
    "gatsby-plugin-i18n": "^0.4.1",
    "gatsby-plugin-offline": "latest",
    "gatsby-plugin-react-helmet": "^1.0.5",
    "gatsby-plugin-react-next": "^1.0.11",
    "gatsby-plugin-sass": "^1.0.26",
    "gatsby-plugin-sharp": "^1.6.48",
    "gatsby-plugin-sitemap": "^1.2.25",
    "gatsby-plugin-typescript": "^1.4.20",
    "gatsby-source-contentful": "latest",
    "gatsby-transformer-remark": "latest",
    "gatsby-transformer-sharp": "^1.6.27",
    "gsap": "^2.0.1",
    "intl": "^1.2.5",
    "lodash": "^4.16.4",
    "react-intl": "^2.4.0",
    "react-typography": "^0.15.0",
    "slash": "^1.0.0",
    "typescript": "^3.0.1",
    "typography": "^0.15.8",
    "typography-breakpoint-constants": "^0.14.0"
  },
  "keywords": [
    "gatsby"
  ],
  "license": "MIT",
  "main": "n/a",
  "scripts": {
    "develop": "gatsby develop",
    "build": "gatsby build",
    "start": "gatsby serve",
    "apollo-watch": "apollo codegen:generate --tagName=graphql --queries='./{graphql,src}/**/*.tsx' --schema=./gatsby-schema.json src/gatsby-queries.d.ts --outputFlat --watch",
    "typescript-graphql": "gql-gen --config ./gqlgen.json --schema http://localhost:8000/___graphql --template graphql-codegen-typescript-template --skip-documents --out ./src/graphql.d.ts"
  },
  "browserslist": [
    "> 1%",
    "IE >= 11",
    "last 2 versions"
  ],
  "devDependencies": {
    "graphql-code-generator": "^0.10.7",
    "graphql-codegen-typescript-template": "^0.10.7",
    "sass-resources-loader": "^1.3.3",
    "url-loader": "^1.0.1"
  }
}

gatsby-node.js:

const _ = require(`lodash`);
const Promise = require(`bluebird`);
const path = require(`path`);
const slash = require(`slash`);
const languages = require('./src/data/languages');

// Implement the Gatsby API “createPages”. This is
// called after the Gatsby bootstrap is finished so you have
// access to any information necessary to programmatically
// create pages.
exports.createPages = ({graphql, boundActionCreators}) => {
    const {createPage} = boundActionCreators;

    //Create index page:
    languages.langs.forEach(language => {
        const prefix = language.langKey === "en" ? "/" : `/${language.langKey}`;
        createPage({
            path: `${prefix}`,
            component: path.resolve(`./src/templates/index.tsx`),
            context: {...language,}
        });
    });

    return new Promise((resolve, reject) => {
        // The “graphql” function allows us to run arbitrary
        // queries against the local Contentful graphql schema. Think of
        // it like the site has a built-in database constructed
        // from the fetched data that you can run queries against.
        graphql(
            `
        {
          allContentfulPageVertical(limit: 1000) {
            edges {
              node {
                id
                contentful_id
                node_locale
                slug
              }
            }
          }
        }
      `
        )
            .then(result => {
                if (result.errors) {
                    reject(result.errors)
                }

                // console.log(result.data.allContentfulPageVertical.edges);

                // Create vertical template pages
                const template = path.resolve(`./src/templates/PageVertical.tsx`);
                // We want to create a detailed page for each
                result.data.allContentfulPageVertical.edges.forEach(edge => {

                    const slug = edge.node.slug;

                    // Gatsby uses Redux to manage its internal state.
                    // Plugins and sites can use functions like "createPage"
                    // to interact with Gatsby.

                    if (slug !== null) {
                        const prefix = edge.node.node_locale === "da-DK" ? "/da/" : `/`;
                        const path = `${prefix}${slug}`;
                        console.log('page: ', path);
                        createPage({
                            // Each page is required to have a `path` as well
                            // as a template component. The `context` is
                            // optional but is often necessary so the template
                            // can query data specific to each page. (GraphQL)
                            path: path,
                            component: slash(template),
                            context: {
                                id: edge.node.contentful_id,
                                languageCode: edge.node.node_locale
                            },
                        });
                    }
                });
                resolve();
            })
    })
};
Chuloo commented 6 years ago

@supermoos could you create a reproduction of your code with a demo contentful account? 👍

supermoos commented 6 years ago

I was setting it up, and the figured that contentful localizes assets too and that was what was causing the problem. I solved it by setting up a fallback locale in contentful so it serves up the default locales images. However this results in text strings also using fallback versions, which is not always what one may want. It would be a really nice feature if there was a way to request a fallback locale only for ContentfulAsset's but not sure if that's already possible somehow?

Greegko commented 5 years ago

I have the same problem and I think it should load the default value if the field is not localised and the fallback is not set for the target language. Similar this fix #2937, so I think it is a bug, fields which are not media assets work as expected.

levino commented 5 years ago

This still does not work for media assets I fear. I only get null as the url for the non-localized images for any other language but the default (in my case en-US)

christina-grannas commented 3 years ago

I have this issue as well