Clocale

Next.js

This comprehensive guide walks you through integrating Clocale into your Next.js application, with full support for both server and client components in the App Router.


Installation

Adding Dependencies

Install the Clocale React package to get started:

npm install @clocale/react

This library provides all the necessary tools for handling translations in your Next.js application, including hooks, providers, and server utilities.


Core Setup

Step 1: Create the Translation Provider

The ClocaleTranslationProvider wraps your entire application and makes translations available to all components. This is a client component that initializes Clocale with the user's locale and pre-fetched server-side translations.

'use client';

import { ClocaleProvider, SSRTranslations } from '@clocale/react';

interface ClocaleTranslationProvierProps {
  locale: string;
  children: React.ReactNode;
  ssrTranslations: SSRTranslations;
  isDev: boolean;
}

export const ClocaleTranslationProvider = ({
  children,
  locale,
  ssrTranslations,
  isDev,
}: ClocaleTranslationProvierProps) => {
  return (
    <ClocaleProvider
      type="server"
      locale={locale}
      ssrTranslations={ssrTranslations}
      isDev={isDev}
    >
      {children}
    </ClocaleProvider>
  );
};

Why this matters: By wrapping your app with this provider, you ensure that all child components can access translations without prop drilling, and translations are available immediately without additional fetching.

Step 2: Set Up Locale Management

Create server actions to handle locale persistence using cookies. This ensures the user's language preference is remembered across sessions:

"use server";

import { cookies } from "next/headers";

const COOKIE_NAME = "locale";

export const getLocale = async () => {
  const cookieStore = await cookies();
  return cookieStore.get(COOKIE_NAME)?.value ?? "en";
};

export const setLocale = async (locale: string) => {
  const cookieStore = await cookies();
  cookieStore.set(COOKIE_NAME, locale);
};

Key functions:

  • getLocale() - Retrieves the user's saved locale from cookies (defaults to 'en')
  • setLocale(locale) - Updates the locale cookie when users change their language preference

Step 3: Configure the Server Client

Set up the Clocale client for server-side translation fetching. This creates utilities that work seamlessly with Next.js server components:

import { ClocaleNext, createServerClient } from "@clocale/react/next";

import { getLocale } from "./path/to/locale";

export const { getTranslation, getClocaleClient } = createServerClient({
  getLocale,
  builder: async (locale) =>
    ClocaleNext().init({
      locale,
      baseUrl: "your-project-integration-url",
    }),
});

Configuration details:

  • baseUrl - Your Clocale integration URL from the developer settings (Learn more)
  • getLocale - Function to retrieve the current locale
  • builder - Initializes a new Clocale instance for each request with the appropriate locale

Step 4: Configure the Root Layout

Modify your layout.tsx to fetch translations on the server and provide them to your entire application:

import { getLocale } from './path/to/locale';
import { getClocaleClient } from './path/to/clocale';
import { ClocaleTranslationProvider } from '.path/to/ClocaleTranslationProviders';

export default async function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  const locale = await getLocale();

  const clocaleClient = await getClocaleClient();

  // Array of namespaces used in your project
  const translations = await clocaleClient.fetchTranslations(['test']);
  
  return (
    <html lang={locale}>
      <body
        className={`${geistSans.variable} ${geistMono.variable} antialiased`}
      >
        <ClocaleTranslationProvider
          locale={locale}
          ssrTranslations={translations}
          isDev={true} // Set to false for production
        >
          {children}
        </ClocaleTranslationProvider>
      </body>
    </html>
  );
}

Important: Only set isDev={true} in development. Always use isDev={false} in production to disable development features. Learn more


Building a Language Switcher

Creating the Locale Switcher Component

A language switcher is essential for allowing users to view your application in their preferred language. This reusable component allows users to change their language preference. It uses the setLocale server action and triggers a page refresh to reload translations:

'use client';

import { setLocale } from './path/to/locale';

const LANGUAGES = [
  { code: 'en', label: 'English' },
  { code: 'fr', label: 'Français' },
  { code: 'es', label: 'Español' },
  { code: 'de', label: 'Deutsch' },
];

export const LocaleSwitcher = ({ currentLocale }: { currentLocale: string }) => {

  const handleLocaleChange = async (newLocale: string) => {
    // Update the locale cookie on the server
    await setLocale(newLocale);
    };

  return (
    <select
      value={currentLocale}
      onChange={(e) => handleLocaleChange(e.target.value)}
    >
      {LANGUAGES.map((lang) => (
        <option key={lang.code} value={lang.code}>
          {lang.label}
        </option>
      ))}
    </select>
  );
};

Using the Locale Switcher

Add the locale switcher to your layout or navigation component. Pass the current locale as a prop:

import { getLocale } from './path/to/locale';
import { LocaleSwitcher } from './components/LocaleSwitcher';

export default async function Header() {
  const locale = await getLocale();

  return (
    <header>
      <nav>
        <LocaleSwitcher currentLocale={locale} />
      </nav>
    </header>
  );
}

Using Translations

In Server Components

For server components and server actions, use the getTranslation function to access translations:

import { getTranslation } from './path/to/clocale';

const Login = async () => {
  const { t } = await getTranslation('auth'); // 'auth' is your namespace

  return (
    <div>
       <span>{t('login.title')}</span>
       <span>{t('login.description')}</span>
       <input 
          type="text" 
          placeholder={t("login.input.placeholder")}
       />
    </div>
  );
}

export default Login;

In Client Components

For client-side components, use the useTranslation hook to access reactive translations:

'use client';

import { useTranslation } from '@clocale/react';

export const Dashboard = () => {
  const { t } = useTranslation('home');

  return c
    <>
      <p>{t('description')}</p>
      <input 
        type="text" 
        placeholder={t("input.search")}
      />
    </>
  );
};

Quick Reference

Component TypeMethodImport FromUsage
Server ComponentgetTranslation()'./path/to/clocale'await getTranslation('namespace')
Client ComponentuseTranslation()'@clocale/react'useTranslation('namespace')
Server ActiongetLocale()'./path/to/locale'await getLocale()
Server ActionsetLocale()'./path/to/locale'await setLocale('fr')