Fabricio Espinoza
Fabricio Espinoza

Reputation: 463

Next.js App router i18n '/' for default language

I am migrating from Next.js /pages to /app and I have 2 languages en and es, the default language is en and the url structure is:

English

Spanish

But when integrating i18n on app router I created a [lang] folder, and after following any of these guides:

https://locize.com/blog/next-13-app-dir-i18n/

https://nextjs.org/docs/app/building-your-application/routing/internationalization

My structure on /app/[lang] is:

English

Spanish

If I go to example.com/ I will be redirected to example.com/en, if I don't solve this I will have problem with our current SEO because the majority of URLs will change.

Upvotes: 10

Views: 4810

Answers (4)

sobczak.dev
sobczak.dev

Reputation: 1308

In my case, the solution was to add this if statement

  if (locale === "en") {
    return NextResponse.rewrite(request.nextUrl);
  } else {
    return NextResponse.redirect(request.nextUrl);
  }

in middleware.js.

Complete file (default template copied from Next.js Docs):

import { NextResponse } from "next/server";
 
let locales = ['en', 'nl-NL', 'nl']
 
function getLocale(request) { ... }
 
export function middleware(request) {
  const { pathname } = request.nextUrl
  const pathnameHasLocale = locales.some(
    (locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`
  )
 
  if (pathnameHasLocale) return
 
  const locale = getLocale(request)
  request.nextUrl.pathname = `/${locale}${pathname}`
  if (locale === "en") {
    return NextResponse.rewrite(request.nextUrl);
  } else {
    return NextResponse.redirect(request.nextUrl);
  }
}
 
export const config = {
  matcher: ['/((?!_next).*)'],
}

Upvotes: 0

Arundev
Arundev

Reputation: 41

This is the best and simple usage I found Doc - next-intl

Update the middle ware configuration like this.

import createMiddleware from 'next-intl/middleware'

export default createMiddleware({
  locales: ['en', 'ja'],
  defaultLocale: 'ja',
  localePrefix: 'as-needed',
})

export const config = {
  matcher: ['/((?!api|_next|.*\\..*).*)'],
}

Upvotes: 1

mcrochet
mcrochet

Reputation: 1

If you want to have this structure :

English

  • example.com/
  • example.com/blog/my-post

Spanish

  • example.com/es

  • example.com/es/blog/mi-articulo

2 options :

  1. use rewrite api yourself

  2. use next-international who do it for you

see docs

see the example here

and configure the middleware like this :

urlMappingStrategy: 'rewriteDefault',

import { createI18nMiddleware } from 'next-international/middleware';
import { NextRequest } from 'next/server';

const I18nMiddleware = createI18nMiddleware({
  locales: ['en', 'es'],
  defaultLocale: 'en',
  urlMappingStrategy: 'rewriteDefault',
});

export function middleware(request: NextRequest) {
  return I18nMiddleware(request);
}

export const config = {
  matcher: ['/((?!api|static|.*\\..*|_next|favicon.ico|robots.txt).*)'],
};

Upvotes: 0

bitShift
bitShift

Reputation: 86

Checkout the rewrite api of NextResponse.

So in the document of nextjs, the return value of the middleware is a Response.redirect(request.nextUrl) which redirect the client to the url contains locale information.

Replace it with NextResponse.rewrite(request.nextUrl), the new url will be accepted to server internally only, without affecting client side. Kind of like a 'proxy' in some way.

* NextResponse can be imported from next/server.

Upvotes: 4

Related Questions