Multilingual support is a critical feature for modern web applications. In this guide, we will walk through how to implement a typesafe translation system in a Next.js application without relying on any third-party libraries. This approach ensures that our translations are robust and maintainable.
Step 1: Define Translation Data
Create a directory named locales at the root of your project to store your translation files. Inside this directory, create JSON files for each language you want to support. For example, en.json for English and es.json for Spanish.
locales/en.json:
{
"greeting": "Hello",
"farewell": "Goodbye"
}
locales/es.json:
{
"greeting": "Hola",
"farewell": "Adiós"
}
Step 2: Create Server Action getTranslation
Define a server action named getTranslation.ts
to fetch translation data. Here, we utilize an object called dictionaries, mapping language codes to functions that dynamically import the corresponding JSON file.
getTranslation.ts:
"use server";
const dictionaries = {
en: () => import("./locales/en.json").then((module) => module.default),
es: () => import("./locales/es.json").then((module) => module.default),
};
export default async function getTranslation() {
const { defaultLang, error } = await getPreferredLang(); // Optional: Determine user's preferred language
const lang = await dictionaries?.[defaultLang ?? "en"]?.();
return {
lang,
error,
};
}
Step 3: Create useTranslation Hook
In this example, I used React Query for managing state, but feel free to use any other state management solution of your choice. The main objective remains constant: crafting a versatile hook responsible for fetching translations, thereby enabling its use as a client-side state.
useTranslation.ts:
"use client";
import getTranslation from "@/translation/getTranslation";
import { useQuery } from "@tanstack/react-query";
export default function useTranslation() {
return useQuery({
queryKey: ["lang"],
queryFn: () => getTranslation(),
});
}
Step 4: Integrate Translation in Your Components
Now, let's use our custom hook in an Next.js client component.
You can also use the getTranslation()
server action directly in your server components.