skip to Main Content

I implemented a next-intl for multi-language support. So my paths look like www.next.com/de or www.next.com/en

I’m using NextJS 14.

<NextLink href="/support-us">{t("About us")}</NextLink>

And when I want to navigate to for example /support-us it must navigate me to /en/support-us instead I get to /support-us so it throws an error.

NotFoundError: Failed to execute ‘removeChild’ on ‘Node’: The node to
be removed is not a child of this node.

Here is my code.
middleware.ts

import createMiddleware from "next-intl/middleware";
import { locales } from "./i18n";

export default createMiddleware({
  // A list of all locales that are supported
  locales,

  // Used when no locale matches
  defaultLocale: "en",
});

export const config = {
  // Match only internationalized pathnames
  matcher: ["/", "/(en|it|de|nl|fr|sv|es|nb|pt|pl)/:path*"],
};

i18next

import { notFound } from "next/navigation";
import { getRequestConfig } from "next-intl/server";

interface Language {
  symbol: string;
  name: string;
}

export const supportedLanguages: Language[] = [
  { symbol: "EN", name: "English" },
  { symbol: "DE", name: "Deutsch" },

];

const languageSymbolsLowercase: string[] = supportedLanguages.map((lang) =>
  lang.symbol.toLowerCase()
);

const initialLocales: string[] = [];

const combinedLocales: string[] = [
  ...initialLocales,
  ...languageSymbolsLowercase,
];

export const locales: string[] = combinedLocales;

export default getRequestConfig(async ({ locale }) => {
  if (!locales.includes(locale)) notFound();

  return {
    messages: (await import(`../messages/${locale}.json`)).default,
  };
});

2

Answers


  1. Chosen as BEST ANSWER

    At the end I had to add a navigation file as mentioned in the next-intl documentation in there it exports a Link component which solves the problem and navigates to /[locale]/support-us
    for example /en/support-us here is my navigation file

    import {
      createLocalizedPathnamesNavigation,
      Pathnames,
    } from "next-intl/navigation";
    import { locales } from "./i18n";
    
    export const localePrefix = "always"; // Default
    
    export const pathnames = {
      "/support-us": "/support-us",
    } satisfies Pathnames<typeof locales>;
    
    export const { Link, redirect, usePathname, useRouter, getPathname } =
      createLocalizedPathnamesNavigation({ locales, localePrefix, pathnames });
    

    And use the Link exported in the navigation file

    import { Link as NavLink } from "@navigation"
    <NavLink href="/support-us">{t("support us")}</NavLink>
    

  2. To explicitly include the locale in your paths, you can use the useRouter hook from next/navigation (in nextjs 14) to access the current locale, and then prepend it to your paths.

    Here’s how you could adjust your <NextLink> usage to incorporate the current locale:

    "use client"
    import { useRouter } from 'next/navigation';
    
    const SupportUs = () => {
      const router = useRouter();
      const { locale } = router;
    
      return (
        <NextLink href={`/${locale}/support-us`}>{t("About us")}</NextLink>
      );
    };
    

    UPDATE: I tried to simulate your use case on my end, and I think you can achieve your desired result on the server side by adjusting your middleware.ts file. You won’t need to modify your component/page file though.

    So, below is the updated middleware.ts that I tried to revise:

    import { NextResponse } from 'next/server';
    import type { NextRequest } from 'next/server';
    import createMiddleware from 'next-intl/middleware';
    import { locales } from './i18n';
    
    // Your existing createMiddleware setup
    const intlMiddleware = createMiddleware({
      locales,
      defaultLocale: 'en',
    });
    
    export default function middleware(req: NextRequest) {
      // Attempt to retrieve the locale from the previous URL
      const referer = req.headers.get('referer');
      let refererLocale = '';
    
      if (referer) {
        // Extract the locale from the URL path in the Referer header
        const pathLocaleMatch = referer.match(///[^/]+/([^/]+)/);
        if (pathLocaleMatch && locales.includes(pathLocaleMatch[1])) {
          refererLocale = pathLocaleMatch[1];
        }
      }
    
      // Fallback to the default locale if no valid locale was found in the Referer
      const effectiveLocale = refererLocale || 'en';
    
      // Check if the current request's URL already includes a locale
      const hasLocale = locales.some(locale => req.nextUrl.pathname.startsWith(`/${locale}`));
      if (!hasLocale) {
        // If not, redirect to the same URL but with the effective locale prefixed
        const url = req.nextUrl.clone();
        url.pathname = `/${effectiveLocale}${url.pathname}`;
        return NextResponse.redirect(url);
      }
    
      // Proceed with the next-intl middleware if the locale is already present
      return intlMiddleware(req);
    }
    
    export const config = {
      // Match only internationalized pathnames
      matcher: ['/', '/(en|it|de|nl|fr|sv|es|nb|pt|pl)/:path*'],
    };
    

    I hope this could resolve your issue in a better approach.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search