aralroca / next-translate

Next.js plugin + i18n API for Next.js 🌍 - Load page translations and use them in an easy way!
MIT License
2.67k stars 206 forks source link

Error: No router instance found. You should only use "next/router" on the client side of your app. #1022

Open meightythree opened 1 year ago

meightythree commented 1 year ago

I could repro the issue on stackblitz

What version of this package are you using? "next": "13.3.0", "next-translate": "^2.0.4", "next-translate-plugin": "^2.0.4"

What operating system, Node.js, and npm version? stackblitz, node v16.14.2, npm 7.17.0

What happened? I got an error when I change the language.

Ucaught (in promise) Error: No router instance found.
You should only use "next/router" on the client side of your app.

    at getRouter (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next/dist/client/router.js:144:15)
    at Object.get (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next/dist/client/router.js:155:26)
    at eval (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next-translate/lib/esm/setLanguage.js:104:86)
    at step (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next-translate/lib/esm/setLanguage.js:81:27)
    at Object.eval [as next] (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next-translate/lib/esm/setLanguage.js:30:53)
    at eval (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next-translate/lib/esm/setLanguage.js:23:71)
    at new Promise (<anonymous>)
    at __awaiter (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next-translate/lib/esm/setLanguage.js:9:12)
    at setLanguage (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next-translate/lib/esm/setLanguage.js:100:12)
    at _callee$ (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./app/page.tsx:73:114)
    at tryCatch (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next/dist/compiled/regenerator-runtime/runtime.js:45:40)
    at Generator.invoke [as _invoke] (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next/dist/compiled/regenerator-runtime/runtime.js:274:22)
    at prototype.<computed> [as next] (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next/dist/compiled/regenerator-runtime/runtime.js:97:21)
    at asyncGeneratorStep (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next/dist/compiled/@babel/runtime/helpers/esm/asyncToGenerator.js:7:28)
    at _next (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next/dist/compiled/@babel/runtime/helpers/esm/asyncToGenerator.js:27:17)
    at eval (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next/dist/compiled/@babel/runtime/helpers/esm/asyncToGenerator.js:32:13)
    at new Promise (<anonymous>)
    at eval (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next/dist/compiled/@babel/runtime/helpers/esm/asyncToGenerator.js:24:16)
    at HTMLUnknownElement.callCallback (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:19200:14)
    at Object.invokeGuardedCallbackDev (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:19249:16)
    at invokeGuardedCallback (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:19313:31)
    at invokeGuardedCallbackAndCatchFirstError (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:19327:25)
    at executeDispatch (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:30596:3)
    at processDispatchQueueItemsInOrder (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:30628:7)
    at processDispatchQueue (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:30641:5)
    at dispatchEventsForPlugins (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:30652:3)
    at eval (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:30842:12)
    at batchedUpdates$1 (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:23705:12)
    at batchedUpdates (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:27540:12)
    at dispatchEventForPluginEventSystem (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:30841:3)
    at dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:28045:5)
    at dispatchEvent (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:28037:5)
    at dispatchDiscreteEvent (webpack-internal:///(nexttranslateerrornorouterinst-jkmr--3000--b5037fed.local-credentialless.webcontainer.io/app-client)/./node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:28010:5)

What did you expect to happen? Language should change without error.

Are you willing to submit a pull request to fix this bug? Hell yea, this would be my first open source contribution, I might need a little help thou.

aralroca commented 1 year ago

Are you using useRouter? Please provide a reproducible example

meightythree commented 1 year ago

The example is on the stackblitz link. There are two buttons english/spanish, if you click either of them the error will occur.

aralroca commented 1 year ago

Ah ok. Yes, setLanguage is not adapted yet to app dir, you can use useRouter from 'next/navigation': https://beta.nextjs.org/docs/api-reference/use-router

meightythree commented 1 year ago

Thank you for the quick answer @aralroca

meightythree commented 1 year ago

I have extended stackblitz with the provided example in next-translate docs, however it does not change the language with Link tags either. What am I missing @aralroca?

rikusen0335 commented 1 year ago

I'm gonna explain. Well, setLanguage has Router provided from next/router which is deprecated in Next.js 13 (I mean, specifically, only in appDir) and should use next/navigation instead. This is why your current stackblitz is not working.

joaopedrodcf commented 1 year ago

This is how I solved this issue, I created a custom hook

function useSetLanguage() {
    const router = useRouter();
    const pathname = usePathname();
    const searchParams = useSearchParams();

    return (locale: string) => {
        // now you got a read/write object
        const current = new URLSearchParams(Array.from(searchParams.entries())); // -> has to use this form

        current.set('lang', locale);

        // cast to string
        const search = current.toString();
        // or const query = `${'?'.repeat(search.length && 1)}${search}`;
        const query = search ? `?${search}` : '';

        router.push(`${pathname}${query}`);
    };
}

Which then I use like this:

const MyComponent = () => {
    const { lang } = useTranslation('common');
    const setLanguage = useSetLanguage();

    return (
        <Select
            onValueChange={(value) => setLanguage(value)}
            defaultValue={lang}
        >
      ...
        </Select>
    );
};

And this is where I found this solution: https://github.com/vercel/next.js/discussions/47583#discussioncomment-5449707

@aralroca I can try to make a PR to include this if it makes sense to you πŸ‘

aralroca commented 1 year ago

@joaopedrodcf feel free to PR πŸ‘Œ thanks

meightythree commented 1 year ago

@joaopedrodcf is there a way not to include lang as a queryParam and use NEXT_LOCALE cookie?

joaopedrodcf commented 1 year ago

Didn't have time to create the PR about this sorry @aralroca maybe someone can take it over :/

joaopedrodcf commented 1 year ago

@meightythree I would say that is possible but I didn't tried it, just remove the part where we see the query params and check the cookie, then you shouldn't need to add the router.push as well, as the url will be the same.

meightythree commented 1 year ago

@meightythree I would say that is possible but I didn't tried it, just remove the part where we see the query params and check the cookie, then you shouldn't need to add the router.push as well, as the url will be the same.

Thanks I will take a look and comment again if I succeed!

ThijmenGThN commented 1 year ago

Hi @meightythree,

I was wondering if you managed to discover a viable solution to utilize the setLanguage feature.

im-stuart commented 11 months ago

Hi @meightythree

I second the question from @ThijmenGThN Did you manage to find a solution? 😊

rikusen0335 commented 11 months ago

May close the issue for no activity πŸ™ƒ

meightythree commented 11 months ago

I haven't found a solution... started using another package next-international. Sorry it's not the answer you wanted to see.