How to Use next-intl in Next.js for Internationalization
To use
next-intl in Next.js, install the package, create message files for each language, and wrap your app with NextIntlProvider. Use the useTranslations hook inside components to access translated strings.Syntax
The main parts of using next-intl are:
NextIntlProvider: Wraps your app to provide translations.useTranslations: Hook to get translated messages inside components.- Message files: JSON files containing key-value pairs for each language.
typescript
import { NextIntlProvider } from 'next-intl'; import { useTranslations } from 'next-intl'; // Wrap your app export default function App({ Component, pageProps }) { return ( <NextIntlProvider messages={pageProps.messages} locale={pageProps.locale}> <Component {...pageProps} /> </NextIntlProvider> ); } // Use translations in a component function Greeting() { const t = useTranslations('Greeting'); return <p>{t('hello')}</p>; }
Example
This example shows a simple Next.js page using next-intl to display a greeting in English and Spanish.
typescript
import { NextIntlProvider, useTranslations } from 'next-intl'; // Messages for English and Spanish const messages = { en: { Greeting: { hello: 'Hello, friend!' } }, es: { Greeting: { hello: '¡Hola, amigo!' } } }; function Greeting() { const t = useTranslations('Greeting'); return <h1>{t('hello')}</h1>; } export default function Page({ locale }) { return ( <NextIntlProvider locale={locale} messages={messages[locale]}> <Greeting /> </NextIntlProvider> ); } // Simulate locale prop Page.getInitialProps = () => ({ locale: 'en' });
Output
<h1>Hello, friend!</h1>
Common Pitfalls
- Not wrapping your app or page with
NextIntlProvidercauses translation hooks to fail. - Forgetting to load or pass the correct
messagesfor the current locale results in missing translations. - Using keys in
useTranslationsthat don't exist in message files shows empty or fallback text.
typescript
/* Wrong: Missing NextIntlProvider wrapper */ function Greeting() { const t = useTranslations('Greeting'); return <p>{t('hello')}</p>; } /* Right: Wrap with NextIntlProvider and pass messages */ import { NextIntlProvider } from 'next-intl'; export default function App({ Component, pageProps }) { return ( <NextIntlProvider messages={pageProps.messages} locale={pageProps.locale}> <Component {...pageProps} /> </NextIntlProvider> ); }
Quick Reference
| Concept | Description |
|---|---|
| NextIntlProvider | Wraps your app to provide translations and locale context. |
| useTranslations(namespace) | Hook to get translated strings from a specific namespace. |
| messages | JSON objects with translation keys and values per locale. |
| locale | Current language code like 'en' or 'es' passed to provider. |
| Message files | Organize translations by locale and namespace for clarity. |
Key Takeaways
Always wrap your Next.js app or pages with NextIntlProvider passing locale and messages.
Use the useTranslations hook inside components to access translated text by keys.
Keep your message files organized by locale and namespaces for easy maintenance.
Ensure messages for the current locale are loaded and passed correctly to avoid missing text.
Test your app in different locales to verify translations display as expected.