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

App router 404 without middleware or "ERR_TOO_MANY_REDIRECTS" with middleware. #1141

Closed
RubenHamakers opened this issue Aug 31, 2023 · 3 comments

Comments

@RubenHamakers
Copy link

RubenHamakers commented Aug 31, 2023

What version of this package are you using?

"next-translate": "^2.5.3",
"next-translate-plugin": "^2.5.3"

What operating system, Node.js, and npm version?
Mac OS, Node 18.16.1

What happened?
When implementing the basic version as described in the documentation, loading the page /en/translations with my middleware on results in ERR_TOO_MANY_REDIRECTS and when I remove my middleware (which honestly is a no-go, we need it for production obviously) I get a 404.

What did you expect to happen?
Show me a basic translated page.

Are you willing to submit a pull request to fix this bug?
I have spent 2 days trying to debug it but I'm clueless as to what the problem could be.

More information / Code:

page.tsx (app/[lang]/(site)/translations/page.tsx)

import useTranslation from 'next-translate/useTranslation'

export default function Page() {
  const { t, lang } = useTranslation('default')
  return (
    <div className='container w-40 h-40'>
      <h1>{t('Title')}</h1>
    </div>
  )
}

next.config.js

const nextTranslate = require('next-translate-plugin')

/** @type {import('next').NextConfig} */
const nextConfig = {
  images: {
    domains: [
     ...
    ],
    remotePatterns: [
      {
        ...
      },
    ]
  },
  poweredByHeader: false,
}

module.exports = nextTranslate({
  ...nextConfig,
  webpack: (config, { isServer, webpack }) => {
    return config;
  }
})

Maybe relevant middleware code

 const langFromPathname = new URL(request.url).pathname.split('/')[1];

  console.log('Language from pathname: ', langFromPathname);
  
  // If we already have a valid language in the path, all is fair in love and brostep
  if (i18nconfig.locales.includes(langFromPathname)) {
    console.log("Language already set.");
    return NextResponse.next()
  }
  
  const langFromCookie = request.cookies.get('lang')?.value;
  
  // If we didn't have a valid language in the path, we check if we have a language set in the cookie (and if it's valid!), if so prepend the URL with that. 
  if (langFromCookie && i18nconfig.locales.includes(langFromCookie)){
    const newUrl = `/${langFromCookie}${pathname}${request.nextUrl.search}`;
    console.log(`1: Redirecting to ${newUrl}, from ${pathname}`);
    return NextResponse.redirect(new URL(newUrl, request.url));
  } 
  
  // If we have a prefered language in the browser, we'll use that
  const langFromHeader = acceptLanguage.get(request.headers.get('accept-language') || '')
  if (langFromHeader && i18nconfig.locales.includes(langFromHeader)){
    const newUrl = `/${langFromHeader}${pathname}${request.nextUrl.search}`;
    console.log(`2: Redirecting to ${newUrl}, from ${pathname}`);
    return NextResponse.redirect(new URL(newUrl, request.url));
  }

  // Otherwise we'll just go to the English version
  const newUrl =`/${fallbackLang}${pathname}${request.nextUrl.search}`
  console.log(`3: Redirecting to ${newUrl}, from ${pathname}`);
  return NextResponse.redirect(new URL(newUrl, request.url));

i18n.js config

module.exports = {
  "locales": ["en", "de"],
  "defaultLocale": "en",
  "pages": {
    "*": ["default"],
    "/[lang]": ["default"],
    "/[lang]/translations": ["default"]
  }
}

locales folder structure

image

Even more info:
tried this #1111 (comment) this worked on a specific nextjs version but broke with middleware, which means our team cannot implement this solution.

tried suggested NextJS version "next": "^13.4.12",

Thanks for reading and if you have any suggestions let me know!

@oscarrc
Copy link

oscarrc commented Sep 6, 2023

I am using the middleware suggested at the Next.js docs. I've found that when using next-translate-plugin request.nextUrl.pathname does not have the [lang] fragment although the redirection is done:

If I get the next request after the first redirection this is what I get:

{
  href: 'http://localhost:3000/es/get-started',
  origin: 'http://localhost:3000',
  protocol: 'http:',
  username: '',
  password: '',
  host: 'localhost:3000',
  hostname: 'localhost',
  port: '3000',
  pathname: '/get-started',
  search: '',
  searchParams: URLSearchParams {  },
  hash: ''
}

Since the [lang] fragment of the url is not present, in my case, this leads to an infite redirection loop. And If you stop that loop by any other means it leads to a 404 error.

I don't know why this happens, but if I remove i18n from next.config.js export it works as expected and the pathname includes the [lang] fragment as stated here #1142

Maybe it has something to do with the fact that Next.js internationalization docs don't mention putting i18n in the config file for the app router since i18n support has been dropped for the app router (they do mention it for the pages router).

Should the i18n config section still be included when using app router?

@RubenHamakers
Copy link
Author

Can confirm that as mentioned in #1142 comments setting the config.i18n to undefined fixes the issue. Works well enough to keep developing on but I'm not shipping to prod like this.

@aralroca
Copy link
Owner

aralroca commented Jan 22, 2024

This is solved in 3.0.0-canary.1 version (both, next-translate & next-translate-plugin)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants