Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Resolve locale for navigation APIs consistently from i18n/request.ts in react-server like all other APIs do (#1459) #1459

Merged
merged 4 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions docs/src/pages/docs/routing/middleware.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -432,14 +432,23 @@ export default function RootPage() {

## Troubleshooting

### "Unable to find `next-intl` locale because the middleware didn't run on this request and no `locale` was returned in `getRequestConfig`." [#unable-to-find-locale]

If the middleware is not expected to run on this request (e.g. because you're using a setup [without i18n routing](/docs/getting-started/app-router/without-i18n-routing)), you should explicitly return a `locale` from [`getRequestConfig`](/docs/usage/configuration#i18n-request) to recover from this error.
### "The middleware doesn't run for a particular page." [#middleware-not-running]

If the error occurs for pathnames where the middleware is expected to run, please make sure that:
To resolve this, make sure that:

1. The middleware is set up in the correct file (e.g. `src/middleware.ts`).
1. The [middleware](/docs/getting-started/app-router/with-i18n-routing#middleware) is set up in the correct file (e.g. `src/middleware.ts`).
2. Your middleware [matcher](#matcher-config) correctly matches all routes of your application, including dynamic segments with potentially unexpected characters like dots (e.g. `/users/jane.doe`).
3. In case you require static rendering, make sure to follow the [static rendering guide](/docs/getting-started/app-router/with-i18n-routing#static-rendering) instead of relying on hacks like [`force-static`](https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamic).
3. In case you're [composing other middlewares](#composing-other-middlewares), ensure that the middleware is called correctly.
4. In case you require static rendering, make sure to follow the [static rendering guide](/docs/getting-started/app-router/with-i18n-routing#static-rendering) instead of relying on hacks like [`force-static`](https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamic).

### "My page content isn't localized despite the pathname containing a locale prefix." [#content-not-localized]

This is very likely the result of your [middleware not running](#middleware-not-running) on the request. As a result, a potential fallback from [`i18n/request.ts`](/docs/usage/configuration#i18n-request) might be applied.

### "Unable to find `next-intl` locale because the middleware didn't run on this request and no `locale` was returned in `getRequestConfig`." [#unable-to-find-locale]

If the middleware _is not_ expected to run on this request (e.g. because you're using a setup [without i18n routing](/docs/getting-started/app-router/without-i18n-routing)), you should explicitly return a `locale` from [`getRequestConfig`](/docs/usage/configuration#i18n-request) to recover from this error.

If the middleware _is_ expected to run, verify that your [middleware is set up correctly](#middleware-not-running).

Note that `next-intl` will invoke the `notFound()` function to abort the render if no locale is available after `getRequestConfig` has run. You should consider adding a [`not-found` page](/docs/environments/error-files#not-foundjs) due to this.
2 changes: 1 addition & 1 deletion docs/src/pages/docs/workflows/typescript.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ declare global {

## Troubleshooting

If you're encountering problems, please double check that:
If you're encountering problems, double check that:

1. Your interface uses the correct name.
2. You're using TypeScript version 4 or later.
Expand Down
2 changes: 1 addition & 1 deletion packages/next-intl/.size-limit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const config: SizeLimitConfig = [
name: "import {createSharedPathnamesNavigation} from 'next-intl/navigation' (react-server)",
path: 'dist/production/navigation.react-server.js',
import: '{createSharedPathnamesNavigation}',
limit: '16.765 KB'
limit: '16.77 KB'
},
{
name: "import {createLocalizedPathnamesNavigation} from 'next-intl/navigation' (react-server)",
Expand Down
13 changes: 7 additions & 6 deletions packages/next-intl/src/navigation/createNavigation.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import React from 'react';
import {renderToString} from 'react-dom/server';
import {beforeEach, describe, expect, it, vi} from 'vitest';
import {DomainsConfig, Pathnames, defineRouting} from '../routing';
import {getRequestLocale} from '../server/react-server/RequestLocale';
import createNavigationClient from './react-client/createNavigation';
import createNavigationServer from './react-server/createNavigation';
import getServerLocale from './react-server/getServerLocale';

vi.mock('react');
vi.mock('next/navigation', async () => {
Expand All @@ -23,15 +23,16 @@ vi.mock('next/navigation', async () => {
permanentRedirect: vi.fn()
};
});
vi.mock('../../src/server/react-server/RequestLocale');
vi.mock('./react-server/getServerLocale');

function mockCurrentLocale(locale: string) {
// Enable synchronous rendering without having to suspend
const localePromise = Promise.resolve(locale);
(localePromise as any).status = 'fulfilled';
(localePromise as any).value = locale;
const value = locale;
const promise = Promise.resolve(value);
(promise as any).status = 'fulfilled';
(promise as any).value = value;

vi.mocked(getRequestLocale).mockImplementation(() => localePromise);
vi.mocked(getServerLocale).mockImplementation(() => promise);

vi.mocked(nextUseParams<{locale: string}>).mockImplementation(() => ({
locale
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import {
Locales,
Pathnames
} from '../../routing/types';
import {getRequestLocale} from '../../server/react-server/RequestLocale';
import createSharedNavigationFns from '../shared/createSharedNavigationFns';
import getServerLocale from './getServerLocale';

export default function createNavigation<
const AppLocales extends Locales,
Expand All @@ -35,7 +35,7 @@ export default function createNavigation<
type Locale = AppLocales extends never ? string : AppLocales[number];

function getLocale() {
return getRequestLocale() as Promise<Locale>;
return getServerLocale() as Promise<Locale>;
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
Expand Down
10 changes: 10 additions & 0 deletions packages/next-intl/src/navigation/react-server/getServerLocale.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import getConfig from '../../server/react-server/getConfig';

/**
* This is only moved to a separate module for easier mocking in
* `../createNavigatoin.test.tsx` in order to avoid suspending.
*/
export default async function getServerLocale() {
const config = await getConfig();
return config.locale;
}
Loading