skip to Main Content

I’m working on a Next.js project where we have a language dropdown for users to select their preferred language. The current implementation uses the router.push method from next/router to update the language and redirect to the current page without reloading. However, this creates a new entry in the browser history.

Here’s the relevant code:

import { useRouter } from 'next/router';
import setLanguage from 'next-translate/setLanguage';


export const LanguageDropdown = () => {
  const { locales, locale } = useRouter();

  const updateLanguage = async (language: string) => {
    window.localStorage.setItem('language-selected', language.toLowerCase());
    // Assuming setLanguage is a function that updates the language in your app
    await setLanguage(language.toLowerCase());
  };

  return (
    <select onChange={(e) => updateLanguage(e.target.value)} value={locale}>
      {locales?.map((lang) => (
        <option key={lang} value={lang}>
          {lang.toUpperCase()}
        </option>
      ))}
    </select>
  );
};

The problem is that when a user changes the language, a new entry is created in the history. If the user then navigates back, they land on the previously set language and are then redirected to the new language. I would like to prevent this behavior and not create a new history entry when the language is changed.

Any suggestions on how to achieve this would be greatly appreciated.

2

Answers


  1. Instead of router.push. How about window.location.reload() ?

    async function setLanguage(language) {
      // Some code to set language
      window.location.reload()
    }
    

    After the page is reloaded, it will check in the localStorage, see which language is selected.

    Login or Signup to reply.
  2. Based on the current setLanguage function’s implementation it doesn’t appear this is possible as it uses router.push to PUSH a new entry onto the history stack.

    import Router from 'next/router'
    
    export default async function setLanguage(
      locale: string,
      scroll = true
    ): Promise<boolean> {
      return await Router.push(
        {
          pathname: Router.pathname,
          query: Router.query,
        },
        Router.asPath,
        { locale, scroll }
      )
    }
    

    But this hook is simple enough you could create your own that allows for PUSH or REPLACE navigation actions.

    Example:

    import Router from 'next/router';
    
    export default async function setLanguage(
      locale: string,
      { scroll = true, replace = false } = { scroll: true, replace: false },
    ): Promise<boolean> {
      return await Router[replace ? "replace" : "push"](
        {
          pathname: Router.pathname,
          query: Router.query,
        },
        Router.asPath,
        { locale, scroll }
      )
    }
    
    import { useRouter } from 'next/router';
    import setLanguage from '../path/to/setLanguage';
    
    
    export const LanguageDropdown = () => {
      const { locales, locale } = useRouter();
    
      const updateLanguage = async (language: string) => {
        const selectedLanguage = language.toLowerCase();
        window.localStorage.setItem('language-selected', selectedLanguage);
    
        // Set language and redirect
        await setLanguage(selectedLanguage, { replace: true });
      };
    
      return (
        <select onChange={(e) => updateLanguage(e.target.value)} value={locale}>
          {locales?.map((lang) => (
            <option key={lang} value={lang}>
              {lang.toUpperCase()}
            </option>
          ))}
        </select>
      );
    };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search