Frontend
10 min read

Integrate Clocale with Next-Intl: Simplify Localization Management in Your Next.js App

Discover how to integrate the Clocale service with next-intl in Next.js to enable easy translation updates through a user-friendly UI—perfect for non-technical managers.

Next.jsLocalizationClocalenext-intli18n
Suzuki Ren
8/4/2025

Prerequisites

Before starting, ensure you have:

  • An existing Next.js project
  • A plan for which languages your application will support

Installing Dependencies

First, add the next-intl package to your project:

npm install next-intl
# or
yarn add next-intl
# or
pnpm add next-intl

This library provides the core functionality for handling translations in your Next.js application. For comprehensive documentation, visit Next-Intl's official docs.

Environment Configuration

Create or update your .env file with the necessary Clocale service credentials:

CLOCALE_API_URL="https://cdn.clocale.com/translation/YOUR-PROJECT-ID"

You can connect to the localization service for dynamic content translation using this environment variable. You should replace YOUR-PROJECT-ID with the project ID in the developer settings of your project.

Setting Up the Translation Loader

Create or modify the i18n/request.ts file to handle dynamic loading of translations based on the user's selected locale:

import { getRequestConfig } from "next-intl/server";

const namespaces = ["default", "common"]; // Replace with your namespaces

type MessageValue = string | MessageObject;

interface MessageObject {
  [key: string]: MessageValue;
}

const fetchNamespaceMessages = async (
  baseUrl: string,
  locale: string,
  namespace: string
) => {
  const url = `${baseUrl}/${namespace}/${locale}.json`;
  const res = await fetch(url);

  if (!res.ok) {
    console.warn(
      `[i18n] Failed to fetch ${locale}/${namespace}:`,
      res.statusText
    );
    return {};
  }

  const data = await res.json();
  return data;
};

export default getRequestConfig(async () => {
  // Provide a static locale, fetch a user setting,
  // read from `cookies()`, `headers()`, etc.
  const locale = "en";

  const messages: Record<string, MessageObject> = {};

  for (const ns of namespaces) {
    messages[ns] = await fetchNamespaceMessages(
      process.env.CLOCALE_API_URL!,
      locale,
      ns
    );
  }

  return {
    locale,
    messages,
  };
});

Localizing Server Components

For server components or server actions, use getTranslations to access localized content:

"use server";

import { getTranslations } from "next-intl/server";

export default async function Home() {
  // Access translations for the "home" namespace
  const t = await getTranslations("common.home"); // `common` is the name of your namespace

  return (
    <div>
      <h2>{t("title")}</h2>
      <p>{t("description")}</p>
    </div>
  );
}

Localizing Client Components

For client-side components, use the useTranslations hook:

"use client";

import { useTranslations } from "next-intl";

export default function Home() {
  // Access translations for the "home" namespace
  const t = useTranslations("default.home"); // `default` is the name of your namespace

  return (
    <div>
      <h2>{t("title")}</h2>
      <p>{t("description")}</p>
    </div>
  );
}

Best Practices

  • Organize translations by feature or page using namespaces
  • Use meaningful keys that describe the content rather than the text itself
  • Handle pluralization with next-intl's built-in support for plural forms
  • Test thoroughly with all supported languages to catch layout issues early

Troubleshooting

If translations aren't appearing correctly:

  1. Verify your locale files are properly formatted JSON
  2. Check that the namespace being referenced exists in your locale files
  3. Ensure the language cookie is being set correctly