Setting Up Next.js + i18n for Client and Server Side Localization

File structure for a Next.js project with localization using next-intl.
File structure for a Next.js project with localization using next-intl.

When I was developing my bilingual website, I needed to implement i18n. Initially, I considered using the standard internationalization feature in Next.js, but I switched to for its added flexibility and functionality:

  • Dynamic translations for server-side and client-side components.
  • Middleware for language detection that automatically redirects users.
  • A translation structure that is easy to maintain.
  • Enhanced development experience with type-safe translations.

 

How to Set It Up?

1. Install next-intl:

1npm install next-intl


2. Define Supported Languages

Create an i18n configuration to define supported languages and a default language:

1// src/i18n/routing.ts
2import { defineRouting } from 'next-intl/routing';
3
4export const routing = defineRouting({
5  locales: ['en', 'uk'],
6  defaultLocale: 'en',
7});


3. Add Translations

1/messages/en.json
2/messages/uk.json


Example of the en.json file:

1{
2  "title": "Next.js i18n demo",
3  "description": "Internationalization with next-intl.",
4  "stepFirst": "Add internationalization support",
5  "stepSecond": "Update routing"
6}


4. Middleware for Language Detection

Create middleware to redirect users to the appropriate language based on their browser settings:

1// src/middleware.ts
2import createMiddleware from "next-intl/middleware";
3import { routing } from "../i18n/routing";
4
5export default createMiddleware(routing);
6
7export const config = {
8  matcher: ["/", "/(uk|en)/:path*"],
9};
10

5. Use on the server and client side.

1// src/app/[locale]/page.tsx
2import { getMessages } from '@/lib/i18nHelpers';
3
4export default async function HomePage({ params }) {
5  const messages = await getMessages(params.locale);
6
7  return (
8    <div>
9      <h1>{messages.title}</h1>
10      <p>{messages.description}</p>
11    </div>
12  );
13}
14
15// src/app/[locale]/components/Steps.tsx
16import { useTranslations } from "next-intl";
17
18export default function Steps() {
19  const t = useTranslations();
20  return (
21    <ul>
22       <li>{t("stepFirst")}</li>
23       <li>{t("stepSecond")}</li>
24     </ul>
25  );
26}

 

You can find the full implementation in the .

made everything simple and convenient. Now my website runs in two languages without extra effort.


After setting up your translations, run the to ensure your language tags and character encoding are properly configured. This step helps validate your i18n setup, improves accessibility, and ensures your website meets global standards. It’s a quick way to guarantee your site is globally accessible and SEO-friendly.

Have questions? Feel free to ask, and we'll figure it out together!

Suggest and support

Contact Me

or

By submitting this form, you agree to our Privacy Policy