Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Internationalization] Redirect with { locale: false } and dynamic isn't working properly. #19690

Open
raulfdm opened this issue Nov 30, 2020 · 11 comments
Labels
Internationalization (i18n) Related to Internationalization with Next.js. Linking and Navigating Related to Next.js linking (e.g., <Link>) and navigation.
Milestone

Comments

@raulfdm
Copy link
Contributor

raulfdm commented Nov 30, 2020

Bug report

Describe the bug

Redirect with { locale: false } isn't working properly.

Context

Before describe the bug, I need to give you some context about what problem I'm trying to solve.

I recently switch my website default locale from pt to en. It means that some old URLs I had localized, now would be inverted, for example:

URL example:

Before: /blog/e-o-coronavirus-hein (default lang PT)
After: /pt/blog/e-o-coronavirus-hein (Default lang EN)

The problem

What's is happening now is I can't just setup this redirect via next.config.js or via vercel.json (but I'll focus on next config).

The way I would try to solve that is setting up something like this:

module.exports = {
  async redirects() {
    return [
      {
        source: "/blog/e-o-coronavirus-hein",
        destination: "/pt/blog/e-o-coronavirus-hein",
        permanent: true,
      },
    ];
  },
};

This won't work and that's comprehensible. I assume when I try to access /blog/e-o-coronavirus-hein, since my browser is in English, it'll try to resolve the request locale to /en. But the stranger thing is that the redirect works but it concatenates everything and I'm being redirected to: /en/pt/blog/e-o-coronavirus-hein.

That's weird but makes sense because I'm embedding the locale in the path.

In the docs it says we can turn off the locale process, that should do the job, right?

module.exports = {
  async redirects() {
    return [
      {
        source: "/blog/e-o-coronavirus-hein",
        destination: "/pt/blog/e-o-coronavirus-hein",
        locale: false,
        permanent: true,
      },
    ];
  },
};

But now if I try to access /blog/e-o-coronavirus-hein, instead being redirected to /pt/blog/e-o-coronavirus-hein, I just reach 404.

I assume that somehow it's thinking that's is a valid route (because I use pages/blog/[slug].js) and it does not consider the redirect setup.

Another problem (which I can open another issue if you want to) is when I try to redirect from a url which even does not exist from an existing one:

module.exports = {
  async redirects() {
    return [
      {
        source: "/2018/08/09/coronavirus",
        destination: "/pt/blog/e-o-coronavirus-hein",
        locale: false,
        permanent: true,
      },
    ];
  },
};

In this case I also get 404.

To Reproduce

I prepare a demo site with some deeper explanation how to test this problem but:

  1. Access: https://next-redirect-bug.vercel.app/
  2. Check the Defective redirects section
  3. Click in both links which should redirect

Expected behavior

As a dev user, I want to be able to setup a redirect from a /blog/some-post to /<locale>/blog/some-post .

Screenshots

Not applicable

System information

  • OS: Pop!_OS
  • Browser (if applies) [e.g. chrome, safari]: any
  • Version of Next.js: [e.g. 10.0.1]: 10.0.3-canary.3
  • Version of Node.js: [e.g. 12.0.0]: 12.19.1
  • Deployment: [e.g. next start, next export, Vercel, other platform]: Vercel

Additional context

Update

  • This also does not work with rewrites
@raulfdm raulfdm added the bug Issue was opened via the bug report template. label Nov 30, 2020
@raulfdm
Copy link
Contributor Author

raulfdm commented Dec 6, 2020

Any help in this case?

@raulfdm raulfdm changed the title Redirect with { locale: false } and dynamic isn't working properly. [Internationalization] Redirect with { locale: false } and dynamic isn't working properly. Dec 6, 2020
@raulfdm
Copy link
Contributor Author

raulfdm commented Dec 6, 2020

Update

I upgrade the demo project to next@10.0.4-canary.2 and it seems not fixed yet. I'm not sure if it's an edge case.

#19766

@ramiyahya
Copy link

@raulfdm I was having a similar issue. Just out of interest, do you have a routes entry in your now.json or vercel.json file? If so, try removing it and see if it works. I had a few routes doing some rewrites etc. in my now.json file. Removing it fixes the issue for me.

Note - I had to refactor some of my pages to use Next's dynamic routing instead of doing rewrites using legacy routes approach. See https://vercel.com/docs/configuration#project/routes for more info.

@raulfdm
Copy link
Contributor Author

raulfdm commented Dec 10, 2020

Hey @ramiyahya , thanks for answering. No man, I don't have routes configured.

Where do you put your redirects? In you vercel.json or inside next.config.js? I tried both places already and it seems I have the same result ;/

@IanMitchell
Copy link
Contributor

I'm also running into this - exact same behavior as described. Going to spend some time poking around the codebase tomorrow, hoping the fix isn't too hard 🤞

@raulfdm
Copy link
Contributor Author

raulfdm commented Jan 5, 2021

I'm also running into this - exact same behavior as described. Going to spend some time poking around the codebase tomorrow, hoping the fix isn't too hard crossed_fingers

Hey @IanMitchell ... thanks for sharing.

I've been checking every canary release but it seems nobody fix this problem yet.

I'm not sure if it's that complex or it has low prio or even if my PR is clear enough so if you can review that, the examples it would be great.

@Timer Timer added kind: bug and removed bug Issue was opened via the bug report template. labels Jan 6, 2021
@Timer Timer modified the milestones: iteration 16, backlog Jan 6, 2021
@robertcoopercode
Copy link

I think this might also affect rewrites in addition to redirects since I'm having a similar issue: #21096

@timneutkens timneutkens added Internationalization (i18n) Related to Internationalization with Next.js. Linking and Navigating Related to Next.js linking (e.g., <Link>) and navigation. labels Nov 18, 2021
@c7nj7n
Copy link

c7nj7n commented Apr 11, 2022

Despite the traction it does not seem that the issue will be addressed any time soon. Is there a recommended workaround to be able to "cleanly" deal with this? Thank you in advance for your help :)

@GusMartins499
Copy link

Any updates?

@cie
Copy link

cie commented Feb 8, 2024

For those who want to redirect to a different route: It seems that even if "locale": "false" is set, the source is matched with the default locale added. So if you want to match /blog/e-o-coronavirus-hein, the source should be /pt/blog/e-o-coronavirus-hein.

Unfortunately this doesn't help OP with redirecting to the exact same route with the prefix added, because after the first redirect, it matches the same rule again (so it matches both with and without the prefix), and it goes into a redirect loop.

@samcx samcx removed the kind: bug label Apr 30, 2024
@marcospassos
Copy link

It's still a bug. If you're experiencing this issue, here's a temporary workaround to fix it:

type RequestInfo = {
    pathname: string,
    nextPathName: string,
    basePath: string,
    locale: string,
};

function getRequestInfo(request: NextRequest): RequestInfo {
    const {locale} = request.nextUrl;
    let urlPathName = new URL(request.url).pathname;
    let {pathname: nextPathName, basePath} = request.nextUrl;

    if (locale !== '' && basePath === '' && urlPathName === `/${locale}${nextPathName}`) {
        /*
           There is a known bug in Next.js when using localized routes with a basePath.
           For example, if the locale is 'pt' and the basePath is '/app', it leads to:
           - Actual URL: /app/pt
           - request.url = /pt/app/pt
           - request.nextUrl.pathname = /app/pt
           - request.nextUrl.basePath = (empty)

           However, it should be:
           - request.url = /app/pt
           - request.nextUrl.pathname = /
           - request.nextUrl.basePath = /app

           Interestingly, if the basePath starts with the locale (e.g., '/pt/app'), it works as expected.

           Bug report:
           https://github.com/vercel/next.js/issues/19690
       */
        const escapedLocale = escapeRegExp(locale);
        const match = new RegExp(`^/${escapedLocale}((/.+?)/${escapedLocale}(.*))`).exec(urlPathName);

        if (match !== null) {
            basePath = match[2] ?? basePath;
            urlPathName = match[1] ?? urlPathName;
            nextPathName = (match[3] === '' ? '/' : match[3]) ?? nextPathName;
        }
    }

    return {
        pathname: urlPathName,
        locale: locale,
        basePath: basePath,
        nextPathName: nextPathName,
    };
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Internationalization (i18n) Related to Internationalization with Next.js. Linking and Navigating Related to Next.js linking (e.g., <Link>) and navigation.
Projects
None yet
Development

No branches or pull requests