# next-intl-setRequestLocale-ssg-fix

> Fix for next-intl v4 SSG pages showing wrong locale (typically English fallback) despite correct build output. Use when: (1) next-intl pages build successfully with generateStaticParams but render the default locale instead of the expected one, (2) page metadata (from getTranslations with explicit locale) shows correct locale but client components show wrong locale, (3) getMessages() returns default locale messages in [locale] layout/pages. Root cause: missing setRequestLocale() call before getMessages() in server components with static generation.

- Skill: `hubeiqiao/next-intl-setrequestlocale-ssg-fix` (Agent Skill)
- Install (CLI): `npx skillmds@latest add hubeiqiao/next-intl-setrequestlocale-ssg-fix`
- Raw SKILL.md: https://api.skillmd.com/api/skills/hubeiqiao/next-intl-setrequestlocale-ssg-fix/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: hubeiqiao (https://skillmd.com/u/hubeiqiao)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/hubeiqiao/next-intl-setrequestlocale-ssg-fix

---


# next-intl setRequestLocale SSG Fix

## Problem

When using `next-intl` v4+ with Next.js App Router and static generation
(`generateStaticParams`), locale pages build successfully but render text in the
**default locale** (typically English) instead of the expected locale. The build
output shows no errors — pages are generated for all locales — but at runtime,
all locale variants show identical (default) content.

## Context / Trigger Conditions

- Using `next-intl` v4.x with Next.js 14/15 App Router
- Pages use `generateStaticParams()` to pre-render locale variants
- `[locale]` dynamic segment in the app directory
- **Symptom 1**: Build succeeds, locale pages are listed in build output (e.g., `/zh-CN`, `/zh-TW`)
- **Symptom 2**: Page `<title>` may show correct locale (if `generateMetadata` passes locale explicitly via `getTranslations({ locale })`)
- **Symptom 3**: Client component text (from `useTranslations()`) shows default locale
- **Symptom 4**: `getMessages()` in layout returns default locale messages
- **No error messages** — the fallback is silent

### Especially likely when:
- Using a **custom middleware** (not `createMiddleware` from `next-intl/middleware`)
- The middleware handles auth (e.g., Supabase) alongside locale detection

## Root Cause

During static site generation (SSG), there is no HTTP request context. The
`requestLocale` parameter in `getRequestConfig` resolves to `undefined` because
no middleware sets the `x-next-intl-locale` header, and there's no live request
to extract the locale from.

When `requestLocale` is `undefined`, the `getRequestConfig` function typically
falls back to the default locale:

```typescript
// i18n/request.ts
export default getRequestConfig(async ({ requestLocale }) => {
  let locale = await requestLocale;
  // requestLocale is undefined during SSG!
  if (!locale || !locales.includes(locale)) {
    locale = 'en'; // Always falls back to default
  }
  // ...
});
```

This means `getMessages()` always returns default locale messages during SSG.

## Solution

Call `setRequestLocale(locale)` in **every** server component (layout and page)
that uses `next-intl` server functions, **before** calling `getMessages()`,
`getTranslations()`, or any other `next-intl/server` function.

### Fix the layout:

```typescript
// app/[locale]/layout.tsx
import { getMessages, setRequestLocale } from 'next-intl/server';

export default async function LocaleLayout({ children, params }) {
  const { locale } = params;

  // CRITICAL: Set locale for static rendering context
  setRequestLocale(locale);

  const messages = await getMessages(); // Now returns correct locale messages
  // ...
}
```

### Fix every page:

```typescript
// app/[locale]/page.tsx
import { setRequestLocale } from 'next-intl/server';

export default function LocalePage({ params }) {
  setRequestLocale(params.locale);
  return <PageClient />;
}
```

```typescript
// app/[locale]/about/page.tsx
import { getTranslations, setRequestLocale } from 'next-intl/server';

export default async function LocaleAboutPage({ params }) {
  const { locale } = params;
  setRequestLocale(locale);
  const t = await getTranslations({ locale, namespace: 'about.meta' });
  // ...
}
```

### Rules:
1. Call `setRequestLocale()` **before** any `getMessages()` or `getTranslations()` call
2. Call it in **every** layout and page under `[locale]/`, not just the layout
3. The locale value comes from `params.locale` (the route segment)

## Verification

1. Run `npm run build` — locale pages should still be listed with `●` (SSG)
2. Run `npm run dev` and navigate to a locale page (e.g., `/zh-CN`)
3. Verify client component text renders in the correct locale
4. Verify `useTranslations()` returns translated strings, not default locale

## Why This Is Misleading

- **Build succeeds** with no warnings about wrong locale
- **`generateMetadata` works** if it passes locale explicitly: `getTranslations({ locale })` — this bypasses the request context entirely
- Only `getMessages()` (no locale param) is affected, because it reads from request context
- The `NextIntlClientProvider` receives English messages but is told `locale="zh-CN"`, creating a mismatch where the provider has the right locale but wrong messages

## Notes

- `setRequestLocale` is described by next-intl as a "stopgap" until Next.js natively
  supports accessing route parameters in all Server Components
- This is especially important when NOT using `createMiddleware` from `next-intl/middleware`
  (e.g., when using custom Supabase auth middleware)
- Even when using next-intl's middleware, `setRequestLocale` is still recommended for
  static rendering support
- The function is synchronous — no `await` needed

## References

- [next-intl Routing Setup](https://next-intl.dev/docs/routing/setup)
- [next-intl Request Configuration](https://next-intl.dev/docs/usage/configuration)
- [GitHub Issue #663: Getting rid of setRequestLocale](https://github.com/amannn/next-intl/issues/663)
- [GitHub Issue #891: unstable_setRequestLocale with generateStaticParams](https://github.com/amannn/next-intl/issues/891)
- [GitHub Discussion #446: Unable to find next-intl locale](https://github.com/amannn/next-intl/discussions/446)

