Next.js Discord

Discord Forum

I have a multi-lang site, I would like to make sure that single-lang sites do not have the "/{lang}

Unanswered
Long-legged ant posted this in #help-forum
Open in Discord
Long-legged antOP
This is my file /src/app/[locale], i would like to make single langues site do not have have the "/locale" on the url. I will post you my middleware.ts, i m using i18, i wanted to make, i do a condition if locales.lenght === 1 (one lang), but i have an infinite url redirection loop. do you have an idea ? thank you !

4 Replies

Long-legged antOP
This is the middleware.ts :
import NodeCache from 'node-cache'

import { NextRequest, NextResponse } from 'next/server'

import createMiddleware from 'next-intl/middleware'
import { defineRouting } from 'next-intl/routing'

import { getCountryLanguages } from '@lib/utils/get-country-languages'

import { routing } from '@i18n/routing'

export const config = {
  matcher: [
    '/((?!api|_next/static|_next/image|svg|favicon.ico|robots.txt|test.png|sitemaps).*)',
  ],
}

const cache = new NodeCache()

export async function middleware(request: NextRequest) {
  const localesCacheKey = `locales`
  let locales: string[] = cache.get(localesCacheKey) || []

  const defaultLocaleCacheKey = `default-locale`
  let defaultLocale: string = cache.get(defaultLocaleCacheKey)

  if (locales.length === 0 || !defaultLocale) {
    const languages = await getCountryLanguages(false)
    locales = Object.keys(languages)
    defaultLocale = locales[0]

    cache.set(localesCacheKey, locales)
    cache.set(defaultLocaleCacheKey, defaultLocale)
  }

  const handleI18nRouting = createMiddleware(
    defineRouting({
      locales: locales,
      defaultLocale: defaultLocale,
      pathnames: routing.pathnames,
    })
  )

  const url = new URL(request.url)
  const pathnameParts = url.pathname.split('/').filter(Boolean)

  if (locales.length === 1) {
    if (pathnameParts[0] === defaultLocale) {
      const newPath = `/${pathnameParts.slice(1).join('/')}`
      const cleanedPath = newPath === '/' ? '/' : newPath

      if (url.pathname !== cleanedPath) {
        const response = NextResponse.redirect(new URL(cleanedPath, url.origin))
        response.cookies.set('redirected', 'true', { path: '/', maxAge: 5 }) // Empêcher une boucle
        return response
      }
    }
  }

  const response = handleI18nRouting(request)

  return response
}
@Long-legged ant This is the middleware.ts : import NodeCache from 'node-cache' import { NextRequest, NextResponse } from 'next/server' import createMiddleware from 'next-intl/middleware' import { defineRouting } from 'next-intl/routing' import { getCountryLanguages } from '@lib/utils/get-country-languages' import { routing } from '@i18n/routing' export const config = { matcher: [ '/((?!api|_next/static|_next/image|svg|favicon.ico|robots.txt|test.png|sitemaps).*)', ], } const cache = new NodeCache() export async function middleware(request: NextRequest) { const localesCacheKey = `locales` let locales: string[] = cache.get(localesCacheKey) || [] const defaultLocaleCacheKey = `default-locale` let defaultLocale: string = cache.get(defaultLocaleCacheKey) if (locales.length === 0 || !defaultLocale) { const languages = await getCountryLanguages(false) locales = Object.keys(languages) defaultLocale = locales[0] cache.set(localesCacheKey, locales) cache.set(defaultLocaleCacheKey, defaultLocale) } const handleI18nRouting = createMiddleware( defineRouting({ locales: locales, defaultLocale: defaultLocale, pathnames: routing.pathnames, }) ) const url = new URL(request.url) const pathnameParts = url.pathname.split('/').filter(Boolean) if (locales.length === 1) { if (pathnameParts[0] === defaultLocale) { const newPath = `/${pathnameParts.slice(1).join('/')}` const cleanedPath = newPath === '/' ? '/' : newPath if (url.pathname !== cleanedPath) { const response = NextResponse.redirect(new URL(cleanedPath, url.origin)) response.cookies.set('redirected', 'true', { path: '/', maxAge: 5 }) // Empêcher une boucle return response } } } const response = handleI18nRouting(request) return response }
It looks like you're using next-intl. If so, you just need to configure:
https://next-intl.dev/docs/getting-started/app-router/with-i18n-routing#i18n-routing
import {defineRouting} from 'next-intl/routing';
import {createNavigation} from 'next-intl/navigation';
 
export const routing = defineRouting({
  // A list of all locales that are supported
  locales: ['en', 'de'],
 
  // Used when no locale matches
  defaultLocale: 'en'
});
defaultLocale is the solution for your case.