patternjavascriptModerate
next-intl Setup: File-Based Routing with Locale Middleware
Viewed 0 times
next-intlnextjs i18nlocale middlewareapp router i18nNextIntlClientProvidergetRequestConfig
Problem
Setting up internationalization in a Next.js App Router project requires middleware, message loading, and provider wiring that is easy to get wrong.
Solution
Install
next-intl, create a middleware file, and wrap the app with the provider.// middleware.ts
import createMiddleware from 'next-intl/middleware';
export default createMiddleware({
locales: ['en', 'fr', 'de'],
defaultLocale: 'en',
});
export const config = { matcher: ['/', '/(fr|de|en)/:path*'] };
// i18n.ts
import { getRequestConfig } from 'next-intl/server';
export default getRequestConfig(async ({ locale }) => ({
messages: (await import(`../messages/${locale}.json`)).default,
}));
// app/[locale]/layout.tsx
import { NextIntlClientProvider } from 'next-intl';
import { getMessages } from 'next-intl/server';
export default async function LocaleLayout({ children, params: { locale } }) {
const messages = await getMessages();
return (
<html lang={locale}>
<body>
<NextIntlClientProvider messages={messages}>
{children}
</NextIntlClientProvider>
</body>
</html>
);
}Why
next-intl integrates with Next.js App Router's server components, allowing translation lookups on the server without shipping translation data to the client unnecessarily.
Gotchas
- The
[locale]segment must be the first dynamic segment in theapp/directory. - Pass only the messages the page needs to
NextIntlClientProviderto avoid bloating the client bundle. getMessages()fetches all messages — usegetTranslations('namespace')on the server to scope lookups.- next-intl v3+ uses the App Router API; v2 was for Pages Router — do not mix docs.
Revisions (0)
No revisions yet.