-
Notifications
You must be signed in to change notification settings - Fork 28k
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
[i18n] explicit access to /en not redirecting to / #21040
Comments
Found another weird thing. If i put into redirects section this rule:
and try to access to |
I have the exactly same issue. |
I can reproduce it too, it doesn't redirect to the defaultLocale when we specify it in the URL. |
I have reproduced this issue as well, including the infinite redirects. It is unfortunate that the behavior of next does not match the docs. |
I wanted the exact opposite; no "default" routes, only prefixed ones, so any visit to |
Absolutely the same issue, which is definitely bad for SEO and also for legacy routes redirects. Lets say I have the i18n config: i18n: {
locales: ['en', 'de'],
defaultLocale: 'en',
}, In cases of a legacy website which had a route something like {
source: '/en/my-awesome-products...etc',
destination: '/products/:id',
permanent: true,
},
|
Came across the following discussion and the sandbox example mentioned works exactly as I would expect it for the case of defaultLocale auto redirect. |
Well, the NextJs internal redirection is somehow too fishy to use in production. I could not make it work properly. Actually I wanted to remove my custom server but I will not be able to because of the redirects huddle. My workaround: // custom server (should be something like fastify and not express, but you get the point) const next = require('next');
const express = require('express');
const { redirectedRoutes301 } = require('./middlewares');
const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NEXT_ENV !== 'production';
const app = next({ dev });
const routesHandler = app.getRequestHandler();
app
.prepare()
.then(() => {
const server = express();
server.use(redirectedRoutes301);
server.get('*', (req, res) => routesHandler(req, res));
server.listen(port, (err) => {
if (err) throw err;
process.stdout.write(`> nextjs server running on port: ${port}\n`);
});
})
.catch((ex) => {
process.stderr.write(ex.stack);
process.exit(1);
}); // Redirects with proper regular expressions for normal human beings module.exports = [
{
source: /^\/en(.*)$/i,
destination: '/$1',
},
{
source: /(?:\/vin\?q=)(.*)$/i,
destination: '/search?keyword=$1',
},
{
source: /\/{2,}/i,
destination: '/',
},
......... // Redirects middleware const redirectLocation = (url, redirectRule) => {
return url.replace(redirectRule.source, redirectRule.destination);
};
const getRedirectedUrl = (urlToRedirect) => {
const redirectRule = redirects.find(({ source }) => source.test(urlToRedirect));
if (redirectRule) {
// match redirects recursively (if any appear recursively)
return getRedirectedUrl(redirectLocation(urlToRedirect, redirectRule));
}
return urlToRedirect;
};
exports.redirectedRoutes301 = (req, res, next) => {
const { url = '' } = req || {};
const redirectedUrl = getRedirectedUrl(url);
if (url !== redirectedUrl) {
res.redirect(301, redirectedUrl);
} else {
next();
}
}; EDIT: Acutally if one uses a proper CDN like Cloudflare the custom server could be moved to a worker if the business logic is request agnostic or only decorates the req/res |
I don't know if this has been resolved yet, but if anyone still has problems with it, I found that replacing the redirect url given in the documentation using Next 12 middelware solves this problem. I replaced this from the docs: request.nextUrl.href --> returns whole url Fyi NEXT_PUBLIC_HOST is just http://localhost:3000 |
And another little addition, in the statement request.nextUrl.local === "default", shouldn't it be !==. Because you would want to change the url only if the locale it isn't a default one. If it is then it doesn't get the /en/ or some other prefixes. |
@zanzlender Your solution neither works nor makes sense. You are just redirecting /en to /hr. I found a hacky solution with a custom middleware that redirects
// pages/_middleware.ts
import type { NextMiddleware } from 'next/server';
import { NextRequest, NextResponse } from 'next/server';
export const middleware: NextMiddleware = (request: NextRequest) => {
// redirect default locale to base path (e.g. /en/page -> /page)
const { defaultLocale, href } = request.nextUrl;
const detectedLocale = request.nextUrl[Object.getOwnPropertySymbols(request.nextUrl)[0]]
?.locale?.path?.detectedLocale;
if (detectedLocale === defaultLocale)
return NextResponse.redirect(href);
}; Unfortunately, this uses the internal / private data structure of the nextUrl object. Why does it work?
Conclusion: Redirecting to The tricky part now is to write a condition that will detect the default locale in the request url.
So if we now check if |
I have deployed this example to https://i18n-routing-six-gilt.vercel.app and can verify that the url https://i18n-routing-six-gilt.vercel.app/en takes you to a valid page, and that is in conflict with the documentation that clearly states that the default locale does not have a prefix. I expect this can cause problems for SEO as one will get penalized for having duplicated content. |
If you make sure to set the canonical url you avoid SEO issues. Example: https://rishimohan.me/blog/nextjs-canonical-tag |
I do need this feature |
Solution above didn't work completely for me, so I have enhanced it. It was causing endless redirect when surfing between pages.
|
I have another example for this. Default locale is Repo is here: https://github.com/PhilippSchreiber/vercel-middleware-index-404 |
I think what's happening with this: async redirects() {
return [
{
source: '/en',
destination: '/',
locale: false,
permanent: true,
},
{
source: '/en/:path*',
destination: '/:path*',
locale: false,
permanent: true,
}
];
}, Is that the |
Temporary hack in NGINX configuration to fix this issue.
|
So what, no solution and all multilanguage next.js websites will suck at seo forever? |
I am having the same issue. |
We ended up redirecting at DNS level... |
I still have this issue in Next.js v14.1.0, weird that the documentation is saying the opposite. |
The problem is that the issue is subtle and difficult to understand. It's still a problem, but it's hard to convince the engineers. It's been long enough that I'd have to really dig to be able to adequately explain the issue. But to be clear - the last time I looked at this it wasn't "difficult" to write rewrite rules in nextjs - it was flat out impossible. |
We're having the same issue |
This comment has been minimized.
This comment has been minimized.
You can't, because next.js needs to be aware of any redirects, so that it can do it's runtime SPA style redirects to match. It's not a simple task of putting redirects in front of next.js. At this point, I would recommend you just don't self host next.js for a myriad of reasons, unless you use OpenNext. |
What version of Next.js are you using?
10.0.5
What version of Node.js are you using?
14.15.0
What browser are you using?
Chrome
What operating system are you using?
Windows 10
How are you deploying your application?
next dev (localhost)
Describe the Bug
According to docs when enabling i18n with following config:
only available URLs should be:
but if I try to access page explicitly specifing default locale (i.e.
/en-US
) then it will show page as is, without being redirected to/
Expected Behavior
It should redirect all paths prefixed with default locale to non-prefixed paths (i.e.
/en
to/
,/en/hello
to/hello
etc).I would like to get rid of duplicated pages, because it potentially can bring problems with SEO.
Also, I couldn't fix it using
redirects
section because it runs into infinite loop (ERR_TOO_MANY_REDIRECTS ):To Reproduce
i18n-routing
example/en
(default locale) and make sure it will show page without redirectThe text was updated successfully, but these errors were encountered: