Next.js Discord

Discord Forum

Accessing root URL throws redirects me to "default" 404 page in my project with i18n

Answered
Satin Angora posted this in #help-forum
Open in Discord
Satin AngoraOP
I have a middleware that redirects client to appropriate URL when Locale requested isn't present:
import { NextResponse } from "next/server"
import type { NextRequest } from "next/server"

import { i18n } from "i18n-config"

import { match as matchLocale } from "@formatjs/intl-localematcher"
import Negotiator from "negotiator"


function getLocale(req: NextRequest): string | undefined {
  const headers: Record<string, string> = {}
  req.headers.forEach((val, key) => (headers[key] = val))

  // @ts-ignore locales are readonly
  const availableLocales: string[] = i18n.locales

  const reqLocale = new Negotiator({ headers: headers })
    .languages(availableLocales)

  const locale = matchLocale(reqLocale, availableLocales, i18n.defaultLocale)
  return locale
}

export function middleware(req: NextRequest) {
  const pathname = req.nextUrl.pathname

  const isLocaleMissing = i18n.locales.every(
    (locale) => !pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}`
  )
  
  if (isLocaleMissing) {
    const locale = getLocale(req)

    return NextResponse.redirect(
      new URL(
        `/${locale}${pathname.startsWith("/") ? "" : "/"}${pathname}`,
        req.url
      )
    )
  }
}

export const config = {
  matcher: ['/((?!api|_next/static|_next/image|res|favicon.ico).*)']
}
The home page sits on the path, /src/app/[lang]/page.tsx.

When I run the project in dev mode, and open localhost:3000, it returns a 404 page. I setup a default locale, which I thought would load when I access root route.

Also, it doesn't load the custom not-found.tsx, it loads default 404 page.

How can I solve this issue?
Answered by Satin Angora
From my post on console.log moving the middleware into src solved the issue, and I am now getting redirected. Let's move this errors into their own post, so they can be indexed and solve them there. I will ping you.
View full answer

27 Replies

@Satin Angora I have a middleware that redirects client to appropriate URL when `Locale` requested isn't present: ts import { NextResponse } from "next/server" import type { NextRequest } from "next/server" import { i18n } from "i18n-config" import { match as matchLocale } from "@formatjs/intl-localematcher" import Negotiator from "negotiator" function getLocale(req: NextRequest): string | undefined { const headers: Record<string, string> = {} req.headers.forEach((val, key) => (headers[key] = val)) // @ts-ignore locales are readonly const availableLocales: string[] = i18n.locales const reqLocale = new Negotiator({ headers: headers }) .languages(availableLocales) const locale = matchLocale(reqLocale, availableLocales, i18n.defaultLocale) return locale } export function middleware(req: NextRequest) { const pathname = req.nextUrl.pathname const isLocaleMissing = i18n.locales.every( (locale) => !pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}` ) if (isLocaleMissing) { const locale = getLocale(req) return NextResponse.redirect( new URL( `/${locale}${pathname.startsWith("/") ? "" : "/"}${pathname}`, req.url ) ) } } export const config = { matcher: ['/((?!api|_next/static|_next/image|res|favicon.ico).*)'] } The home page sits on the path, `/src/app/[lang]/page.tsx`. When I run the project in `dev` mode, and open `localhost:3000`, it returns a 404 page. I setup a default locale, which I thought would load when I access root route. Also, it doesn't load the custom `not-found.tsx`, it loads default 404 page. How can I solve this issue?
Can you show me the contents of /src/app/[lang]/layout.tsx?
Satin AngoraOP
Of course.
import type { Metadata, ResolvingMetadata } from 'next'

import { i18n } from 'i18n-config'
import { getDictionaryWithString } from 'repositories/dictionaries'


interface RootProps {
  children: React.ReactNode,
  params: { lang: string }
}


export async function generateStaticParams() {
  return i18n.locales.map((locale) => ({lang: locale}))
}

export async function generateMetadata(
  { params }: RootProps,
  parent?: ResolvingMetadata
): Promise<Metadata> {
  const dict = await getDictionaryWithString(params.lang)

  return {
    title: dict.metadata.title,
    description: dict.metadata.desc
  }
}


export default function RootLayout({
  children,
  params
}: RootProps) {
  return (
    <html lang={params.lang}>
      <body>{children}</body>
    </html>
  )
}
Hm, try adding this at the end of the middleware function:

export const middleware = async (request: NextRequest) => {
  // ... rest of the file

  return NextResponse.next();
};
Satin AngoraOP
Didn't work 😦
Middleware is not working probably, but why...
Try removing the .next folder and then build the app with npm run build and start it with npm run start and see if it runs properly
Satin AngoraOP
This error keeps getting printed on Chrome console:
on-demand-entries-client.js:49 
 GET http://localhost:3000/ 404 (Not Found)
eval    @    on-demand-entries-client.js:49
eval    @    websocket.js:58
handleMessage    @    websocket.js:57
Let me try it.
I have errors in the .next/types/. It doesn't build.
I will take a look at them.
Oooohhh...
The i18n-config import statement is wrong
It should be import { i18n } from './i18n-config'
That ./ is important
Satin AngoraOP
Do you mean in the layout.tsx file?
No, in the middleware.ts file
Satin AngoraOP
I changed it in middleware, but it still doesn't build...
And it's also wrong in layout.tsx
There it should be import { i18n } from '../../../i18n-config'
Satin AngoraOP
I fixed it too. Made it relative, import { i18n } from '../../../i18n-config'
I think this type errors are the issue:
[{
    "resource": "/c:/Users/YMura/Belgeler/React Projects/Durmaz Express Websitesi/durmaz-express-website/.next/types/app/[lang]/page.ts",
    "owner": "typescript",
    "code": "2344",
    "severity": 8,
    "message": "Type 'OmitWithTag<i18nProps, keyof PageProps, \"default\">' does not satisfy the constraint '{ [x: string]: never; }'.\n  Property 'lang' is incompatible with index signature.\n    Type 'string' is not assignable to type 'never'.\n      Type 'string' is not assignable to type 'never'.",
    "source": "ts",
    "startLineNumber": 26,
    "startColumn": 13,
    "endLineNumber": 26,
    "endColumn": 68
},{
    "resource": "/c:/Users/YMura/Belgeler/React Projects/Durmaz Express Websitesi/durmaz-express-website/.next/types/app/[lang]/page.ts",
    "owner": "typescript",
    "code": "2559",
    "severity": 8,
    "message": "Type 'i18nProps' has no properties in common with type 'PageProps'.",
    "source": "ts",
    "startLineNumber": 26,
    "startColumn": 29,
    "endLineNumber": 26,
    "endColumn": 56
}]
These are in .next/types/app/[lang]/page.ts
And these are in .next/types/app/[lang]/layout.ts:
[{
    "resource": "/c:/Users/YMura/Belgeler/React Projects/Durmaz Express Websitesi/durmaz-express-website/.next/types/app/[lang]/layout.ts",
    "owner": "typescript",
    "code": "2344",
    "severity": 8,
    "message": "Type 'ResolvingMetadata | undefined' does not satisfy the constraint 'ResolvingMetadata'.\n  Type 'undefined' is not assignable to type 'Promise<ResolvedMetadata>'.",
    "source": "ts",
    "startLineNumber": 31,
    "startColumn": 39,
    "endLineNumber": 31,
    "endColumn": 88
}]
Satin AngoraOP
From my post on console.log moving the middleware into src solved the issue, and I am now getting redirected. Let's move this errors into their own post, so they can be indexed and solve them there. I will ping you.
Answer
Satin AngoraOP
TY for your help