i18n Translation Keys in Next.js Applications

Complete guide to structuring i18n translation keys in Next.js with the App Router. Covers next-intl setup, server component translations, client component patterns, and middleware-based locale routing.

Framework Guide

Detailed Explanation

i18n Keys in Next.js

Next.js with the App Router requires a different approach to i18n than traditional React SPAs. The most popular solution is next-intl, which supports both Server Components and Client Components.

File Structure

messages/
  en.json
  ja.json
  fr.json
src/
  app/
    [locale]/
      layout.tsx
      page.tsx
  i18n/
    request.ts
    routing.ts

Message Structure

next-intl uses PascalCase namespace keys by convention:

{
  "Metadata": {
    "title": "DevToolbox - Developer Tools",
    "description": "Free browser-based developer tools"
  },
  "Navigation": {
    "home": "Home",
    "tools": "Tools",
    "about": "About"
  },
  "HomePage": {
    "hero": {
      "title": "Developer Tools at Your Fingertips",
      "subtitle": "100+ free tools that run in your browser"
    },
    "search": {
      "placeholder": "Search tools...",
      "no_results": "No tools found for \"{query}\""
    }
  },
  "Common": {
    "buttons": {
      "copy": "Copy",
      "clear": "Clear",
      "download": "Download"
    },
    "errors": {
      "generic": "Something went wrong. Please try again."
    }
  }
}

Server Component Usage

import { useTranslations } from 'next-intl';

export default function HomePage() {
  const t = useTranslations('HomePage');
  return (
    <div>
      <h1>{t('hero.title')}</h1>
      <p>{t('hero.subtitle')}</p>
    </div>
  );
}

Client Component Usage

'use client';
import { useTranslations } from 'next-intl';

export default function SearchBar() {
  const t = useTranslations('HomePage.search');
  return (
    <input placeholder={t('placeholder')} />
  );
}

Metadata Translations

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

export async function generateMetadata({ params: { locale } }) {
  const t = await getTranslations({ locale, namespace: 'Metadata' });
  return {
    title: t('title'),
    description: t('description'),
  };
}

Dynamic Routes with i18n

For parameterized routes like /[locale]/tools/[slug]:

{
  "ToolPage": {
    "aboutThisTool": "About This Tool",
    "howToUse": "How to Use",
    "faq": "Frequently Asked Questions",
    "relatedTools": "Related Tools"
  }
}

Next.js-Specific Best Practices

  1. Use PascalCase for top-level namespaces -- matches Next.js component naming
  2. Split messages by route -- each [locale]/page.tsx should have its own namespace
  3. Use getTranslations in Server Components -- avoid client-side bundle bloat
  4. Validate messages at build time -- next-intl supports message validation in CI
  5. Use middleware for locale detection -- middleware.ts handles URL-based locale routing

Use Case

Next.js developers building multilingual sites need i18n keys that work with both Server and Client Components. The key structure must support static generation (SSG), server-side rendering (SSR), and client-side interactivity. The i18n Key Generator helps produce keys that follow next-intl conventions and can be used in generateMetadata, Server Components, and Client Components alike.

Try It — i18n Key Generator

Open full tool