next-drupal icon indicating copy to clipboard operation
next-drupal copied to clipboard

When multiple locales (in Next.js) getPathsFromContext() creates 404 paths for untranslated (in Drupal) nodes.

Open theRuslan opened this issue 3 years ago • 10 comments

From https://next-drupal.org/docs/reference#getpathsfromcontext: "If you have locales configured in your next.config.js file, it will automatically create localized routes."

When multiple locales (in Next.js) getPathsFromContext() creates 404 paths for untranslated (in Drupal) nodes.

theRuslan avatar Apr 07 '22 13:04 theRuslan

Can you share the next.config.js?

shadcn avatar Apr 08 '22 06:04 shadcn

Yes. And I also use next-i18next for i18n. Here is both configs.

next.config.js:

/** @type {import('next').NextConfig} */

const withPlugins = require("next-compose-plugins");
const { i18n } = require("./next-i18next.config");
const withPWA = require("next-pwa");

const nextConfig = {
  publicRuntimeConfig: {
    canonicalDomain: "https://greenwise.ru",
  },
  reactStrictMode: true,
  images: {
    domains: [process.env.NEXT_IMAGE_DOMAIN],
  },
  i18n,
  experimental: {
    outputStandalone: true,
  },
};

module.exports = withPlugins([
  [
    withPWA,
    {
      pwa: {
        dest: "public",
        disable: process.env.NODE_ENV === "development",
        register: true,
        sw: "/sw.js",
      },
    },
  ],
  [nextConfig],
]);

next-i18next.config.js:

const path = require("path");

module.exports = {
  i18n: {
    defaultLocale: "ru",
    locales: ["ru", "en"],
    localeDetection: false,
  },
  localePath: path.resolve("locales"),
};

theRuslan avatar Apr 12 '22 09:04 theRuslan

I will try to reproduce this issue on clean next/drupal setup with the same language configuration.

theRuslan avatar Apr 12 '22 09:04 theRuslan

@TheRuslan what does the pattern (path alias) for the node type looks like?

You should use [node:source:title] so that Next.js can automatically create the paths.

path-alias-page

shadcn avatar Apr 12 '22 09:04 shadcn

@shadcn I used [node:title] and tried [node:source:title]. I think in this case it doesn't matter.

I made an example with 2 nodes:

  • 1 product which is translated node with the russian original and english translation
  • 1 blog post which is untranslated node with the russian original only

In accordance with next-drupal documentation here https://next-drupal.org/docs/reference#getpathsfromcontext

If you have locales configured in your next.config.js file, it will automatically create localized routes.

So getPathsFromContext returns such result:

[
    {
        "params": {
            "slug": [
                "blog",
                "test-article-original-node-russian-without-translation"
            ]
        },
        "locale": "ru"
    },
    {
        "params": {
            "slug": [
                "blog",
                "test-article-original-node-russian-without-translation"
            ]
        },
        "locale": "en"
    },
    {
        "params": {
            "slug": [
                "product",
                "testovyy-produkt-original-node-russian"
            ]
        },
        "locale": "ru"
    },
    {
        "params": {
            "slug": [
                "product",
                "test-product-translated-node-english"
            ]
        },
        "locale": "en"
    }
]

We can see that it work fine with translated product, but for untranslated blog post it returns inexistent path for "en" locale (second path in this example). And the more locales you have, the more non-existent paths will be returned.

That triggers another problems with next-sitemap for example.

theRuslan avatar Apr 13 '22 13:04 theRuslan

I see. So for your setup, product has translation but not blog?

shadcn avatar Apr 13 '22 14:04 shadcn

Yes. In this example above. In general some nodes can have translations, but some can exist only in one language.

I think it's not specific to a particular case, but common practice for multi-language websites.

Maybe we can check node for system field "content_translations" somewhere in getPathsFromContext or buildPathsFromResources and return only such path which is exist in both nextjs and drupal locales?

theRuslan avatar Apr 13 '22 14:04 theRuslan

Filtering in params for getPathsFromContext can't solve the problem because any filtered resources will be mapped through all the nextjs locales anyway.

theRuslan avatar Apr 13 '22 14:04 theRuslan

Maybe we can check node for system field "content_translations" somewhere in getPathsFromContext or buildPathsFromResources and return only such path which is exist in both nextjs and drupal locales?

We could. I'll look into it.

For now, I think what you could do is use two different calls for paths.

const pathsWithLocale = await getPathsFromContext("node--product", context)
const pathsWithoutLocale = await getPathsFromContext("node--blog", {})

const paths = [
    ...pathsWithLocale,
    ...pathsWIthoutLocale,
]

Can you give this a try and let me know?

shadcn avatar Apr 13 '22 14:04 shadcn