Skip to content

feat!: Next.js 13 RSC integration#149

Merged
amannn merged 378 commits intomainfrom
feat/next-13-rsc
Nov 14, 2023
Merged

feat!: Next.js 13 RSC integration#149
amannn merged 378 commits intomainfrom
feat/next-13-rsc

Conversation

@amannn
Copy link
Copy Markdown
Owner

@amannn amannn commented Dec 8, 2022

→ Please refer to the announcement


Fixes #488
Fixes #402
Fixes #578

@vercel
Copy link
Copy Markdown

vercel bot commented Dec 8, 2022

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
example-next-13-next-auth ✅ Ready (Inspect) Visit Preview 💬 Add feedback Nov 14, 2023 2:37pm
next-intl ✅ Ready (Inspect) Visit Preview 💬 Add feedback Nov 14, 2023 2:37pm
next-intl-docs ✅ Ready (Inspect) Visit Preview 10 resolved Nov 14, 2023 2:37pm
next-intl-example-next-13 ✅ Ready (Inspect) Visit Preview 💬 Add feedback Nov 14, 2023 2:37pm
next-intl-examples-next-13 ✅ Ready (Inspect) Visit Preview 💬 Add feedback Nov 14, 2023 2:37pm

@amannn amannn mentioned this pull request Dec 8, 2022
11 tasks
@amannn amannn changed the title feat: Next.js 13 RSC integration feat!: Next.js 13 RSC integration Dec 8, 2022
@amannn amannn changed the title feat!: Next.js 13 RSC integration feat: Next.js 13 RSC integration Dec 8, 2022
Base automatically changed from feat/next-13-minimum to main December 9, 2022 19:43
@alex289
Copy link
Copy Markdown

alex289 commented Nov 9, 2023

Ok, next-intl@3.0.0-rc.10 is out with improvements for the type safety of the namespace parameter. The parameter is now correctly validated.

This enables autocompletion both for the namespace:

Screenshot 2023-11-09 at 20 09 04 … as well as the `t` function: Screenshot 2023-11-09 at 20 08 18 For some reason, if you pass an object to `getTranslations`, TypeScript still doesn't show autocomplete for me, although the parameter is type safe and is correctly validated. I think this has to do for now.

I can confirm everything here. Lets goo

@jorgebef
Copy link
Copy Markdown

jorgebef commented Nov 9, 2023

Ok, next-intl@3.0.0-rc.10 is out with improvements for the type safety of the namespace parameter. The parameter is now correctly validated.

This enables autocompletion both for the namespace:

Screenshot 2023-11-09 at 20 09 04 … as well as the `t` function: Screenshot 2023-11-09 at 20 08 18 For some reason, if you pass an object to `getTranslations`, TypeScript still doesn't show autocomplete for me, although the parameter is type safe and is correctly validated. I think this has to do for now.

The fact that I can rely on this library, even though I am using unstable features and fixes come this quickly is just insane to me.
Thank you so much for the work you put in, it does not go unnoticed.


```
npm install next-intl@3.0.0-rc.9
npm install next-intl@3.0.0-rc.10
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
npm install next-intl@3.0.0-rc.10
npm install next-intl@next

to not have to update it manually

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, thanks! On the very top of the list for creating such a long-running branch again is definitely setting up a proper canary release channel with full automation! 😄

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I mean is It's already configured. You just should edit this line to the next-intl@next instead of hard-coding the version.
image

@Morishiri
Copy link
Copy Markdown

Morishiri commented Nov 13, 2023

I experienced the following problem while trying to use localized pathnames:

Error: Dynamic href `/en/gallery/[photoId]` found in <Link> while using the `/app` router, this is not supported. Read more: https://nextjs.org/docs/messages/app-dir-dynamic-href

Related section in navigation.ts:

"/gallery/[photoId]": {
  en: "/gallery/[photoId]",
  pl: "/galeria/[photoId]",
},

and the mentioned link:

<Link key={photo.id} href={`/gallery/${photo.id}`}>
  Whatever
</Link>
    "next": "14.0.2",

@amannn
Copy link
Copy Markdown
Owner Author

amannn commented Nov 13, 2023

@Morishiri Your call site of Link doesn't seem right.

This should work:

import {Link} from '../navigation';

<Link href={{
  pathname: '/gallery/[photoId]',
  params: {photoId: photo.id}
}}>
  Gallery
</Link>

See the navigation docs about Link.

@Morishiri
Copy link
Copy Markdown

@Morishiri Your call site of Link doesn't seem right.

This should work:

import {Link} from '../navigation';

<Link href={{
  pathname: '/gallery/[photoId]',
  params: {photoId: photo.id}
}}>
  Gallery
</Link>

See the navigation docs about Link.

I tried that and it causes the same error. Looks like next is no longer accepting this syntax. If you go trough the docs their propose (https://nextjs.org/docs/messages/app-dir-dynamic-href ) they recommend exactly the opposite.

@amannn
Copy link
Copy Markdown
Owner Author

amannn commented Nov 14, 2023

@Morishiri Can you share a reproduction? In this branch, we have both an app example with this syntax as well as an extensive unit test suite for the navigation APIs. Both use next@14.0.1.

My guess would be that either the wrong Link is used or photoId was not provided.

@Morishiri
Copy link
Copy Markdown

@amannn Found the issue!

I had the LocaleLink rendered on every page dynamically with the same path as current, but different locale.

When I landed on /en/gallery/[photoId] that was the pathname which I was providing to link:

export const LocaleLink = ({ switchToLocale, title }: LocaleLinkProps) => {
  const pathname = usePathname();
  const locale = useLocale();

  return (
    <Link
      href={pathname}
      locale={switchToLocale}
      title={title}
    >
      {switchToLocale}
    </Link>
  );
};

I changed it to


export const LocaleLink = ({ switchToLocale, title }: LocaleLinkProps) => {
  const pathname = usePathname();
  const params = useParams();
  const locale = useLocale();

  return (
    <Link
      // @ts-expect-error
      href={{ pathname, params }}
      locale={switchToLocale}
      title={title}
    >
      {switchToLocale}
    </Link>
  );
};

and it works now. Thanks for the pointer!

@Tomekmularczyk
Copy link
Copy Markdown

Tomekmularczyk commented Nov 14, 2023

Hey, I'm using Next 14.0.1, I updated next-intl from rc-6 to rc-10 and now I'm getting this error:

./src/app/[locale]/event/[slug]/page.tsx
 ✓ Compiled /[locale]/[...rest]/page in 13.6s (11099 modules)
 ⨯ node_modules/next-intl/dist/esm/server/RequestLocale.js (1:609) @ eval
 ⨯ Error: Unable to find `next-intl` locale because the middleware didn't run on this request. See https://next-intl-docs.vercel.app/docs/routing/middleware#unable-to-find-locale
    at RootLayout (./src/app/[locale]/layout.tsx:48:74)
    at AsyncLocalStorage.run (node:async_hooks:338:14)
    at Object.apply (./src/app/[locale]/layout.tsx:139:10)
    at async Promise.all (index 0)
null
 ⚠ Fast Refresh had to perform a full reload due to a runtime error.
 ⨯ node_modules/next-intl/dist/esm/server/RequestLocale.js (1:609) @ eval
 ⨯ Error: Unable to find `next-intl` locale because the middleware didn't run on this request. See https://next-intl-docs.vercel.app/docs/routing/middleware#unable-to-find-locale
    at RootLayout (./src/app/[locale]/layout.tsx:48:74)
    at AsyncLocalStorage.run (node:async_hooks:338:14)
    at Object.apply (./src/app/[locale]/layout.tsx:139:10)
    at async Promise.all (index 0)
digest: "1556311853"

the other time:

✓ Compiled /not-found in 5s (11107 modules)
 ✓ Compiled (11093 modules)
 ⚠ Fast Refresh had to perform a full reload. Read more: https://nextjs.org/docs/messages/fast-refresh-reload
 ⨯ node_modules/next-intl/dist/esm/server/RequestLocale.js (1:609) @ eval
 ⨯ Error: Unable to find `next-intl` locale because the middleware didn't run on this request. See https://next-intl-docs.vercel.app/docs/routing/middleware#unable-to-find-locale
    at RootLayout (./src/app/[locale]/layout.tsx:48:74)
    at AsyncLocalStorage.run (node:async_hooks:338:14)
    at Object.apply (./src/app/[locale]/layout.tsx:139:10)
    at async Promise.all (index 0)
null
 ⨯ node_modules/next-intl/dist/esm/server/RequestLocale.js (1:609) @ eval
 ⨯ Error: Unable to find `next-intl` locale because the middleware didn't run on this request. See https://next-intl-docs.vercel.app/docs/routing/middleware#unable-to-find-locale
    at RootLayout (./src/app/[locale]/layout.tsx:48:74)
    at AsyncLocalStorage.run (node:async_hooks:338:14)
    at Object.apply (./src/app/[locale]/layout.tsx:139:10)
    at async Promise.all (index 0)
digest: "1556311853"
null

It doesn't happen immediately, it seems that it happens when there's a compilation error, and then you fix it. Do you have any idea how to fix this error?

EDIT, it's been happening on rc-6 as well

@amannn
Copy link
Copy Markdown
Owner Author

amannn commented Nov 14, 2023

@Tomekmularczyk Can you share a reproduction? (template)

Please also check the relevant troubleshooting section in the docs.

@sFritsch09
Copy link
Copy Markdown

@Tomekmularczyk Can you also check the following:

  1. Structure should be like this in your next app:
  • app
    - [locale]
    - layout.js
    - page.js
    - ...
    • layout.js
    • not-found.js
    • ...
  • middleware.js
  • navigation.js
  • messages
  1. try to delete .next folder after stopping server and rerun
  2. check your config inside middleware.js|ts:
    export const config = { // Skip all paths that should not be internationalized. This example skips the // folders "api", "_next" and all files with an extension (e.g. favicon.ico) matcher: ['/((?!api|_next|.*\\..*).*)'], matcher: ['/', '/(de|en)/:path*'], };

@Tomekmularczyk
Copy link
Copy Markdown

Tomekmularczyk commented Nov 14, 2023

@Tomekmularczyk Can you also check the following:

  1. Structure should be like this in your next app:
  • app

    • [locale]
    • layout.js
    • page.js
    • ...
    • layout.js
    • not-found.js
    • ...
  • middleware.js

  • navigation.js

  • messages

  1. try to delete .next folder after stopping server and rerun
  2. check your config inside middleware.js|ts:
    export const config = { // Skip all paths that should not be internationalized. This example skips the // folders "api", "_next" and all files with an extension (e.g. favicon.ico) matcher: ['/((?!api|_next|.*\\..*).*)'], matcher: ['/', '/(de|en)/:path*'], };

Hi, the directory structure is pretty much the same:
image

I tried deleting node_modules, .next and installing everything again.

export const config = {
  // Skip all paths that aren't pages that you'd like to internationalize
  matcher: ["/((?!api|_next|_vercel|.*\\..*).*)"],
};

It kind of seems that when /[locale]/[...rest]/page is compiled then it happens. Could be unrelated.

I cannot reproduce it on fresh repo.

@Tomekmularczyk
Copy link
Copy Markdown

Hey, I'm using Next 14.0.1, I updated next-intl from rc-6 to rc-10 and now I'm getting this error:

./src/app/[locale]/event/[slug]/page.tsx
 ✓ Compiled /[locale]/[...rest]/page in 13.6s (11099 modules)
 ⨯ node_modules/next-intl/dist/esm/server/RequestLocale.js (1:609) @ eval
 ⨯ Error: Unable to find `next-intl` locale because the middleware didn't run on this request. See https://next-intl-docs.vercel.app/docs/routing/middleware#unable-to-find-locale
    at RootLayout (./src/app/[locale]/layout.tsx:48:74)
    at AsyncLocalStorage.run (node:async_hooks:338:14)
    at Object.apply (./src/app/[locale]/layout.tsx:139:10)
    at async Promise.all (index 0)
null
 ⚠ Fast Refresh had to perform a full reload due to a runtime error.
 ⨯ node_modules/next-intl/dist/esm/server/RequestLocale.js (1:609) @ eval
 ⨯ Error: Unable to find `next-intl` locale because the middleware didn't run on this request. See https://next-intl-docs.vercel.app/docs/routing/middleware#unable-to-find-locale
    at RootLayout (./src/app/[locale]/layout.tsx:48:74)
    at AsyncLocalStorage.run (node:async_hooks:338:14)
    at Object.apply (./src/app/[locale]/layout.tsx:139:10)
    at async Promise.all (index 0)
digest: "1556311853"

the other time:

✓ Compiled /not-found in 5s (11107 modules)
 ✓ Compiled (11093 modules)
 ⚠ Fast Refresh had to perform a full reload. Read more: https://nextjs.org/docs/messages/fast-refresh-reload
 ⨯ node_modules/next-intl/dist/esm/server/RequestLocale.js (1:609) @ eval
 ⨯ Error: Unable to find `next-intl` locale because the middleware didn't run on this request. See https://next-intl-docs.vercel.app/docs/routing/middleware#unable-to-find-locale
    at RootLayout (./src/app/[locale]/layout.tsx:48:74)
    at AsyncLocalStorage.run (node:async_hooks:338:14)
    at Object.apply (./src/app/[locale]/layout.tsx:139:10)
    at async Promise.all (index 0)
null
 ⨯ node_modules/next-intl/dist/esm/server/RequestLocale.js (1:609) @ eval
 ⨯ Error: Unable to find `next-intl` locale because the middleware didn't run on this request. See https://next-intl-docs.vercel.app/docs/routing/middleware#unable-to-find-locale
    at RootLayout (./src/app/[locale]/layout.tsx:48:74)
    at AsyncLocalStorage.run (node:async_hooks:338:14)
    at Object.apply (./src/app/[locale]/layout.tsx:139:10)
    at async Promise.all (index 0)
digest: "1556311853"
null

It doesn't happen immediately, it seems that it happens when there's a compilation error, and then you fix it. Do you have any idea how to fix this error?

Actually, it's been happening on rc-6 for me, I just did not notice it...

@amannn
Copy link
Copy Markdown
Owner Author

amannn commented Nov 14, 2023

@Tomekmularczyk

export const config = {
  // Skip all paths that aren't pages that you'd like to internationalize
  matcher: ["/((?!api|_next|_vercel|.*\\..*).*)"],
};

It kind of seems that when /[locale]/[...rest]/page is compiled then it happens. Could be unrelated.

Maybe this section from the docs is relevant for you: Pathnames without a locale prefix.

If you find that the issue is caused by next-intl, please open a new issue—because … 🥁🥁🥁 … this PR is about to get merged!

@amannn
Copy link
Copy Markdown
Owner Author

amannn commented Nov 14, 2023

meme

Thank you SO MUCH to everyone who has participated in this crazy pull request. Felt almost surreal to finally push that big, green merge button after a year of exploration and iteration on this topic.

All the feedback, code contributions, and testing from everyone who collaborated on this pull request made all the difference on what ended up as the RSC integration of next-intl. I think the result is pretty cool.

If you find something that hasn't been covered so far, please open a new discussion or issue!

See also:

Announcement on Twitter
Announcement blog post

@Tomekmularczyk

This comment was marked as resolved.

@amannn

This comment was marked as resolved.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet