Problems developers face when localizing Next.js apps—and how IntlPull helps.
Designed for App Router. Pages Router projects should use next-i18next instead.
Locale detection and redirects require middleware setup. More moving parts than client-only i18n.
Different patterns for client vs server components. Need to understand the mental model.
Why next-intl is a great choice for Next.js localization.
Full RSC support. Translations resolve on server. Zero client JS for static content.
vs client-only hydration
Built for [locale] route segments. Middleware for redirects. generateMetadata support.
vs Pages Router patterns
TypeScript integration with message key autocomplete. Catch missing keys at build time.
vs runtime key errors
Full ICU syntax support. Plurals, selects, rich text formatting.
vs basic interpolation
Load messages asynchronously. Perfect for large translation files or code splitting.
vs blocking loads
Locale-aware Link and useRouter. Automatic locale prefixing. Language switcher helpers.
vs manual URL handling
Get next-intl running in your Next.js project.
Add next-intl to your Next.js project.
npm install next-intlSet up the [locale] dynamic segment.
# Create locale layout
mkdir -p app/[locale]
mv app/layout.tsx app/[locale]/layout.tsx
mv app/page.tsx app/[locale]/page.tsxHandle locale detection and routing.
import createMiddleware from 'next-intl/middleware';
export default createMiddleware({
locales: ['en', 'es', 'de', 'fr'],
defaultLocale: 'en'
});
export const config = {
matcher: ['/', '/(de|en|es|fr)/:path*']
};Set up the NextIntlClientProvider.
import { NextIntlClientProvider } from 'next-intl';
import { getMessages } from 'next-intl/server';
export default async function LocaleLayout({
children,
params: { locale }
}: {
children: React.ReactNode;
params: { locale: string };
}) {
const messages = await getMessages();
return (
<html lang={locale}>
<body>
<NextIntlClientProvider messages={messages}>
{children}
</NextIntlClientProvider>
</body>
</html>
);
}Use the useTranslations hook in components.
import { useTranslations } from 'next-intl';
export default function HomePage() {
const t = useTranslations('HomePage');
return (
<main>
<h1>{t('title')}</h1>
<p>{t('description')}</p>
</main>
);
}Connect IntlPull to manage translations professionally.
Add the CLI to manage translations.
npm install -D @intlpull/cliSet up the project configuration.
{
"projectId": "your-project-id",
"format": "json",
"sourceLocale": "en",
"localesDir": "./messages",
"filePattern": "{locale}.json"
}Download translations from IntlPull.
npx intlpull pullAutomate translation sync in your pipeline.
# .github/workflows/i18n.yml
name: Sync Translations
on:
push:
branches: [main]
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npx intlpull pull
- run: npx intlpull push --source ./messages/en.jsonComplete guide to React localization with react-i18next. Setup, lazy loading, namespaces, SSR, and IntlPull integration for production i18n.
Complete guide to Nuxt 3 localization with @nuxtjs/i18n. SSR, hybrid rendering, SEO, and IntlPull integration.