Skip to content

Commit

Permalink
docs: Add blog post for 3.0 RC (#523)
Browse files Browse the repository at this point in the history
  • Loading branch information
amannn authored Sep 28, 2023
1 parent 90ce83d commit 0eb1983
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 15 deletions.
6 changes: 3 additions & 3 deletions docs/components/CodeSnippets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ function buildOutput() {
<span style={{color: 'var(--shiki-color-text)'}}> kB</span>
<span style={{color: 'var(--shiki-color-text)'}}>{' '}</span>
<span style={{color: 'var(--shiki-token-string-expression)'}}>
104 kB
87.6 kB
</span>
</span>
<span className="line">
Expand All @@ -358,7 +358,7 @@ function buildOutput() {
<span style={{color: 'var(--shiki-color-text)'}}> B</span>
<span style={{color: 'var(--shiki-color-text)'}}>{' '}</span>
<span style={{color: 'var(--shiki-token-string-expression)'}}>
97.5 kB
80.2 kB
</span>
</span>
<span className="line">
Expand All @@ -368,7 +368,7 @@ function buildOutput() {
<span style={{color: 'var(--shiki-color-text)'}}> kB</span>
<span style={{color: 'var(--shiki-color-text)'}}>{' '}</span>
<span style={{color: 'var(--shiki-token-string-expression)'}}>
106 kB
89.3 kB
</span>
</span>
<span className="line"> </span>
Expand Down
4 changes: 4 additions & 0 deletions docs/pages/blog/_meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
"index": {
"title": "next-intl blog"
},
"next-intl-3-0": {
"title": "next-intl 3.0",
"display": "hidden"
},
"translations-outside-of-react-components": {
"title": "How (not) to use translations outside of React components",
"display": "hidden"
Expand Down
8 changes: 6 additions & 2 deletions docs/pages/blog/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@ import CommunityLink from 'components/CommunityLink';

# next-intl blog

Failed attempts at writing docs that somehow turned into blog posts.

<div className="flex flex-col gap-4 py-8">
<CommunityLink
href="/blog/next-intl-3-0"
title="next-intl 3.0"
date="Sep 28, 2023"
author="By Jan Amann"
/>
<CommunityLink
href="/blog/translations-outside-of-react-components"
title="How (not) to use translations outside of React components"
Expand Down
123 changes: 123 additions & 0 deletions docs/pages/blog/next-intl-3-0.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
---
title: next-intl 3.0 release candidate
---

# next-intl 3.0 release candidate

<small>Sep 28, 2023 · by Jan Amann</small>

Almost one year ago, on Oct 25, 2022, [Next.js 13 was announced](https://nextjs.org/blog/next-13) with beta support for the App Router and Server Components. Ever since then, `next-intl` began an exploration on what it means to provide an ideal experience for implementing i18n with the newly added capabilities.

Today, [after more than 300 commits and the involvement of over 50 community members](https://github.com/amannn/next-intl/pull/149), I'm absolutely thrilled to share **the first release candidate of `next-intl` 3.0**, which is now App Router-first.

If you're still happy with the Pages Router, rest assured that `next-intl` is dedicated to support this paradigm for as long as Next.js does. For those who already migrated to the App Router, this means that `next-intl` now takes full advantage of the new capabilities.

## New features

1. **Support for React Server Components**: The APIs `useTranslations`, `useFormatter`, `useLocale`, `useNow` and `useTimeZone` can now be used in Server Components ([proposed docs](https://next-intl-docs-git-feat-next-13-rsc-next-intl.vercel.app/docs/environments/server-client-components)).
2. **New async APIs to handle i18n outside of components**: To handle i18n in the Metadata API and Route Handlers, the APIs `getTranslator`, `getFormatter`, `getNow`, and `getTimeZone` have been added ([proposed docs](https://next-intl-docs-git-feat-next-13-rsc-next-intl.vercel.app/docs/environments/metadata-route-handlers)).
3. **Middleware for internationalized routing**: While Next.js has built-in support for this with the Pages Router, the App Router doesn't include a built-in solution anymore. `next-intl` now provides a drop-in solution that has you covered ([proposed docs](https://next-intl-docs-git-feat-next-13-rsc-next-intl.vercel.app/docs/routing/middleware)).
4. **Internationalized navigation APIs**: Similar to the middleware, this provides a drop-in solution that adds internationalization support for Next.js' navigation APIs: `Link`, `useRouter`, `usePathname` and `redirect`. These APIs allow you to handle locale prefixes behind the scenes and also provide support for localizing pathnames (e.g. `/en/about` vs. `/de/ueber-uns`, see the [proposed docs](https://next-intl-docs-git-feat-next-13-rsc-next-intl.vercel.app/docs/routing/navigation)).

The latter two have already been added in minor versions, but 3.0 cleans up the API and includes many improvements and bug fixes.

## Breaking changes

If you've been part of the Server Components beta and have already tried out previous releases, first of all, thank you so much! Second: Some APIs saw iterations over the beta period, please carefully review the breaking changes below, even if you're already using some of the new APIs.

### Updated setup

`next-intl` now requires two additional setup steps when you're using the App Router:

1. [The `i18n.ts` module](https://next-intl-docs-git-feat-next-13-rsc-next-intl.vercel.app/docs/getting-started/app-router-server-components#i18nts) provides configuration for Server Components
2. [`next-intl/plugin`](https://next-intl-docs-git-feat-next-13-rsc-next-intl.vercel.app/docs/getting-started/app-router-server-components#nextconfigjs) needs to be added to link your `i18n.ts` module to `next-intl`

### New navigation APIs

With [v2.14](https://github.com/amannn/next-intl/blob/main/CHANGELOG.md#2140-2023-05-10), the navigation APIs `useRouter`, `usePathname` and `Link` were added to `next-intl` that enabled you to use the APIs you're used to from Next.js while automatically considering a `locale` behind the scenes.

With 3.0, we're cleaning up these APIs by moving them to a shared namespace as well as introducing type-safety for the `locale` prop that can be passed to these APIs.

```diff
- import Link from 'next-intl/link';
- import {useRouter, usePathname} from 'next-intl/client';
- import {redirect} from 'next-intl/server';

+ import {createSharedPathnamesNavigation} from 'next-intl/navigation';
+
+ const locales = ['en', 'de'] as const;
+ const {Link, useRouter, usePathname, redirect} = createSharedPathnamesNavigation({locales});
```

Typically, you'll want to call this factory function in a central place in your app where you can easily import from (see [the proposed navigation docs](https://next-intl-docs-git-feat-next-13-rsc-next-intl.vercel.app/docs/routing/navigation#shared-pathnames)).

These changes bring the existing APIs in line with the new [`createLocalizedPathnamesNavigation` API](https://next-intl-docs-git-feat-next-13-rsc-next-intl.vercel.app/docs/routing/navigation#localized-pathnames) that allows you to localize pathnames:

```tsx filename="navigation.ts"
import {createLocalizedPathnamesNavigation, Pathnames} from 'next-intl/navigation';

export const locales = ['en', 'de'] as const;

// The `pathnames` object holds pairs of internal
// and external paths, separated by locale.
export const pathnames = {
// If all locales use the same pathname, a
// single external path can be provided.
'/': '/',
'/blog': '/blog',

// If locales use different paths, you can
// specify each external path per locale.
'/about': {
en: '/about',
de: '/ueber-uns'
}
} satisfies Pathnames<typeof locales>;

export const {Link, redirect, usePathname, useRouter} =
createLocalizedPathnamesNavigation({locales, pathnames});
```

By using a similar API, you can upgrade from shared pathnames to localized pathnames by replacing the factory function.

### Switching the middleware default of `localePrefix` to `always`

Previously, the [`localePrefix` of the middleware](https://next-intl-docs-git-feat-next-13-rsc-next-intl.vercel.app/docs/routing/middleware#locale-prefix) defaulted to `as-necessary`, meaning that a locale prefix was only added for non-default locales.

This default has now been changed to `always` since this has two advantages:

1. We can recommend [a safer default `matcher`](https://next-intl-docs-git-feat-next-13-rsc-next-intl.vercel.app/docs/routing/middleware#matcher-config) that needs no extra treatment for pathnames with dots (e.g. `/users/jane.doe`)
2. It avoids an [edge case of `Link`](https://next-intl-docs-git-feat-next-13-rsc-next-intl.vercel.app/docs/routing/middleware#locale-prefix-as-necessary) where we include a prefix for the default locale on the server side but patch this on the client side by removing the prefix (certain SEO tools might report a hint that a link points to a redirect in this case).

If you want to stay on the `as-necessary` strategy, you can [configure this option](https://next-intl-docs-git-feat-next-13-rsc-next-intl.vercel.app/docs/routing/middleware#locale-prefix-as-necessary) in the middleware.

### Static rendering of Server Components

With the newly introduced Server Components support comes a temporary workaround for static rendering.

If you call APIs like `useTranslations` in a Server Component, by default, the hook will opt the page into dynamic rendering. This is a temporary limitation that we aim to remove once [`createServerContext`](https://react.dev/blog/2023/05/03/react-canaries#announcing-breaking-changes-and-new-features-early) is supported in Next.js, but as a stopgap solution, we've added the [`unstable_setRequestLocale`](https://next-intl-docs-git-feat-next-13-rsc-next-intl.vercel.app/docs/getting-started/app-router-server-components#static-rendering) API so that you can keep your pages fully static.

Note that if you're using `next-intl` exclusively in Client Components, this doesn't apply to your app and static rendering will continue to work as it did before.

### Other notable changes

1. `next-intl` now uses [`exports` in `package.json`](https://nodejs.org/api/packages.html#subpath-exports) to clearly define which modules are exported. This should not affect you, unless you've previously imported undocumented internals.
2. `NextIntlProvider` has been removed in favor of [`NextIntlClientProvider`](https://next-intl-docs-git-feat-next-13-rsc-next-intl.vercel.app/docs/configuration#client-server-components)
3. `NextIntlClientProvider` now needs to be imported from `next-intl` instead of `next-intl/client`.
4. [The middleware](https://next-intl-docs-git-feat-next-13-rsc-next-intl.vercel.app/docs/routing/middleware) now needs to be imported from `next-intl/middleware` instead of `next-intl/server` (deprecated since v2.14).
5. `next@^13.4` is now required for the RSC APIs. Next.js 12 is still supported for the Pages Router integration.
6. If you're using `NextIntlClientProvider` outside of the App Router (e.g. with the Pages Router), you need to define the `locale` prop explicitly.
7. `useIntl` has been replaced with [`useFormatter`](https://next-intl-docs-git-feat-next-13-rsc-next-intl.vercel.app/docs/usage/dates-times) (deprecated since v2.11).
8. `createIntl` has been replaced with [`createFormatter`](https://next-intl-docs-git-feat-next-13-rsc-next-intl.vercel.app/docs/environments/core-library) (deprecated since v2.11).

## Upgrade now

Along with the release candidate also comes a [preview of the updated docs](https://next-intl-docs-git-feat-next-13-rsc-next-intl.vercel.app/).

We're still looking for more feedback, please try out the release candidate and [reach out](https://github.com/amannn/next-intl/pull/149)!

```
npm install [email protected]
```

This release was truly a team effort and couldn't be nearly where it is today without the involvement of the community. Thank you so much for being part of this!
2 changes: 2 additions & 0 deletions docs/pages/blog/translations-outside-of-react-components.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ title: How (not) to use translations outside of React components

# How (not) to use translations outside of React components

<small>Apr 21, 2023 · by Jan Amann</small>

Have you ever wondered why `next-intl` doesn’t provide an API to consume translations outside of React components?

The traditional way to internationalize your app with `next-intl` is to use the `useTranslations` hook:
Expand Down
18 changes: 8 additions & 10 deletions docs/pages/docs/getting-started/app-router-server-components.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@ import Steps from 'components/Steps';

# Next.js 13: Internationalization (i18n) in Server Components

Next.js 13 introduces support for [React Server Components](https://nextjs.org/docs/getting-started/react-essentials) with the App Router and unlocks [many benefits](/docs/environments/server-client-components) when handling internationalization entirely on the server side. `next-intl` is adopting the new capabilities and is currently offering a beta version to early adopters, who are already building apps with Server Components.
Next.js 13 introduces support for [React Server Components](https://nextjs.org/docs/getting-started/react-essentials) with the App Router and unlocks [many benefits](/docs/environments/server-client-components) when handling internationalization entirely on the server side. `next-intl` is adopting the new capabilities and is currently offering a preview version to early adopters, who are already building apps with Server Components.

<Callout type="warning">
Support for React Server Components is currently in beta. Please use it at
Support for React Server Components is currently available as a release candidate. Please use it at
your own risk, knowing that you may have to migrate upon a stable release.
</Callout>

## Current beta version
## Current version

```
npm install [email protected]beta.19
npm install [email protected]rc.2
```

This beta version was tested with `[email protected]`.
This version was tested with `[email protected]`.

## Roadmap

Expand Down Expand Up @@ -190,9 +190,9 @@ That's all it takes! Now you can internationalize your apps on the server side.

## Static rendering

The support for using `next-intl` in React Server Components currently opts your pages into dynamic rendering. This is a limitation that will eventually be lifted once [`createServerContext`](https://react.dev/blog/2023/05/03/react-canaries#announcing-breaking-changes-and-new-features-early) is available and integrated in Next.js.
By using APIs like `useTranslations` from `next-intl` in Server Components, your pages will currently opt into dynamic rendering. This is a limitation that will eventually be lifted once [`createServerContext`](https://react.dev/blog/2023/05/03/react-canaries#announcing-breaking-changes-and-new-features-early) is available and integrated in Next.js.

If you have a strong need for static rendering, you can enable static rendering as follows:
As a stopgap solution, `next-intl` provides a temporary API that can be used to enable static rendering:

<Steps>

Expand All @@ -210,7 +210,7 @@ export function generateStaticParams() {

### Add `unstable_setRequestLocale` to all layouts and pages

As a stopgap solution, `next-intl` provides a temporary API that can be used to distribute the locale that is received via `params` in a layout or page for usage in all Server Components that are rendered as part of the request.
`next-intl` provides a temporary API that can be used to distribute the locale that is received via `params` in a layout or page for usage in all Server Components that are rendered as part of the request.

```tsx filename="app/[locale]/layout.tsx"
import {unstable_setRequestLocale} from 'next-intl/server';
Expand Down Expand Up @@ -254,8 +254,6 @@ export default async function IndexPage({

Note that Next.js can render layouts and pages indepently. This means that e.g. when you navigate from `/settings/profile` to `/settings/privacy`, the `/settings` segment might not re-render as part of the request. Due to this, it's important that `unstable_setRequestLocale` is called not only in the parent `settings/layout.tsx`, but also in the individual pages `profile/page.tsx` and `privacy/page.tsx`.

Apart from that, the API can only be used for pages that receive `params` (i.e. not `not-found.tsx`).

That being said, the API is expected to work reliably if you're cautious to apply it in all relevant places.

</Steps>
Expand Down
12 changes: 12 additions & 0 deletions docs/theme.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Footer from 'components/Footer';
import PartnerSidebar from 'components/PartnerSidebar';
import Link from 'next/link';
import {useRouter} from 'next/router';
import {Navbar, ThemeSwitch} from 'nextra-theme-docs';

Expand Down Expand Up @@ -73,6 +74,17 @@ export default {
project: {
link: 'https://github.com/amannn/next-intl'
},
banner: {
text: (
<>
Try out the{' '}
<Link className="underline" href="/blog/next-intl-3-0">
3.0 release candidate
</Link>
!
</>
)
},
docsRepositoryBase: 'https://github.com/amannn/next-intl/blob/main/docs',
useNextSeoProps() {
return {
Expand Down

2 comments on commit 0eb1983

@vercel
Copy link

@vercel vercel bot commented on 0eb1983 Sep 28, 2023

Choose a reason for hiding this comment

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

Successfully deployed to the following URLs:

next-intl-example-next-13 – ./examples/example-next-13

next-intl-example-next-13-git-main-next-intl.vercel.app
next-intl-example-next-13-next-intl.vercel.app
next-intl-example-next-13.vercel.app

@vercel
Copy link

@vercel vercel bot commented on 0eb1983 Sep 28, 2023

Choose a reason for hiding this comment

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

Successfully deployed to the following URLs:

next-intl-docs – ./docs

next-intl-docs-next-intl.vercel.app
next-intl-docs-git-main-next-intl.vercel.app
next-intl-docs.vercel.app

Please sign in to comment.