Internationalisation (i18n) is the process of designing an application to be easily adaptable to different languages and regions without engineering changes. In this article, you will learn how to set up i18n in a Next.js application and create a language switcher to toggle between English and Spanish using next-intl
.
Installation
First, you need to install the next-intl
library, which facilitates managing internationalisation in Next.js. Run the following command in your terminal:
npm install next-intl
Project Structure
The project structure will be as follows:
├── messages
│ ├── en.json
│ └── es.json
├── next.config.mjs
└── src
├── i18n.ts
├── middleware.ts
└── app
└── [locale]
├── layout.tsx
└── page.tsx
1. Setting Up Translation Messages
Create a messages
directory at the root of your project. Inside this directory, add JSON files for each language you want to support.
messages/en.json
{
"greeting": "Hello Codú",
"farewell": "Goodbye Codú"
}
messages/es.json
{
"greeting": "Hola Codú",
"farewell": "Adiós Codú"
}
These files contain the translations of the phrases that your application will use.
2. Configuring Next.js
Configure Next.js to support internationalisation in next.config.mjs
.
next.config.mjs
import { getRequestConfig } from 'next-intl/server';
// List of supported languages
const locales = ['en', 'es'];
export default getRequestConfig(async ({ locale }) => {
// Validate that the incoming `locale` parameter is valid
if (!locales.includes(locale)) {
return { notFound: true };
}
return {
messages: (await import(`./messages/${locale}.json`)).default
};
});
This file configures Next.js to load the correct translation messages based on the requested language.
3. Internationalisation Middleware
Create middleware to handle redirection and setting the default language.
src/middleware.ts
import createMiddleware from 'next-intl/middleware';
export default createMiddleware({
// List of all supported languages
locales: ['en', 'es'],
// Default language
defaultLocale: 'en'
});
export const config = {
// Only match internationalised pathnames
matcher: ['/', '/(en|es)/:path*']
};
This middleware handles redirecting to the default language if none is specified.
4. Internationalisation Configuration
Create a configuration file to manage internationalisation settings.
src/i18n.ts
import { notFound } from 'next/navigation';
import { getRequestConfig } from 'next-intl/server';
const locales = ['en', 'es'];
export default getRequestConfig(async ({ locale }) => {
if (!locales.includes(locale as any)) notFound();
return {
messages: (await import(`../messages/${locale}.json`)).default
};
});
This file validates the locales and loads the corresponding messages.
5. Setting Up Layout and Page
Configure the layout and main page to support internationalisation.
src/app/[locale]/layout.tsx
import { useLocale } from 'next-intl';
import { ReactNode } from 'react';
export default function Layout({ children }: { children: ReactNode }) {
const locale = useLocale();
return (
<html lang={locale}>
<body>{children}</body>
</html>
);
}
src/app/[locale]/page.tsx
import { useTranslations } from 'next-intl';
export default function Page() {
const t = useTranslations();
return (
<div>
<h1>{t('greeting')}</h1>
<p>{t('farewell')}</p>
</div>
);
}
These files configure the layout and main page to use the translations.
6. Creating the Language Switcher
Finally, create a language switcher to toggle between English and Spanish.
src/app/[locale]/switcher.tsx
'use client';
import { useLocale } from 'next-intl';
import { useRouter } from 'next/navigation';
import { ChangeEvent, useTransition } from 'react';
export default function LocalSwitcher() {
const [isPending, startTransition] = useTransition();
const router = useRouter();
const localActive = useLocale();
const onSelectChange = (e: ChangeEvent<HTMLSelectElement>) => {
const nextLocale = e.target.value;
startTransition(() => {
router.replace(`/${nextLocale}`);
});
};
return (
<label className='border-2 rounded'>
<p className='sr-only'>Change language</p>
<select
defaultValue={localActive}
className='bg-transparent py-2'
onChange={onSelectChange}
disabled={isPending}
>
<option value='en'>English</option>
<option value='es'>Spanish</option>
</select>
</label>
);
}
This component allows users to change the interface language.
Conclusion
With these steps, you have successfully set up internationalisation in your Next.js application and created a language switcher to toggle between English and Spanish. This will allow your application to support multiple languages and provide a localised user experience.