Documentation
Documentation
Introduction

Getting Started

Getting StartedInstallationQuick StartProject Structure

Architecture

Architecture OverviewTech StacktRPC MiddlewareDesign Principles

Patterns

Code Patterns & ConventionsFeature ModulesError HandlingType Safety

Database

DatabaseSchema DefinitionDatabase OperationsMigrationsCaching

API

tRPCProceduresRouterstRPC Proxy Setup
APIsOpenAPIREST Endpoints

Auth & Access

AuthenticationConfigurationOAuth ProvidersRolesSession Management
AuthorizationUser RolesPermissions

Routing & i18n

RoutingDeclarative RoutingNavigation
InternationalizationTranslationsLocale Routing

Components & UI

ComponentsButtonsFormsNavigationDialogs
StylesTailwind CSSThemingTypography

Storage

StorageConfigurationUsageBuckets

Configuration

ConfigurationEnvironment VariablesFeature Flags

Templates

Template GuidesCreate New FeatureCreate New PageCreate Database TableCreate tRPC RouterAdd Translations

Development

DevelopmentCommandsAI AgentsBest Practices

Internationalization

Multi-language support with next-intl

This project uses next-intl for internationalization with locale-based routing and automatic locale detection.

Overview

The i18n system provides:

  • Locale-based routing - URLs like /en/about and /it/about
  • Automatic detection - Browser language, cookies, headers
  • Type-safe translations - Full TypeScript support
  • ICU message format - Pluralization, variables, rich text
  • Server and client - Works in all component types

Structure

src/i18n/
├── config.tsx      # Locale configuration
├── init.ts         # i18n initialization
├── navigation.ts   # Localized navigation utilities
├── request.ts      # Request-based locale detection
├── routing.ts      # Routing configuration
├── seo.ts          # SEO helpers
├── server.ts       # Server-side utilities
├── rich-text.tsx   # Rich text rendering
└── translate.tsx   # Translation utilities

src/messages/
├── dictionaries/   # Translation files per locale
│   ├── en/
│   │   ├── common.json
│   │   ├── auth.json
│   │   └── ...
│   └── it/
│       └── ...
└── zod-errors/     # Zod validation messages
    ├── en.json
    └── it.json

Quick Links

Translations

Translation files, namespaces, and usage patterns

Routing

Locale-based routing and navigation

Supported Locales

Configure locales in src/i18n/config.tsx:

export const locales = ["en", "it"] as const;
export const defaultLocale = "en";

Quick Start

Server Components

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

export default async function Page() {
  const t = await getTranslations("common");
  
  return <h1>{t("welcome")}</h1>;
}

Client Components

"use client";

import { useTranslations } from "next-intl";

export function MyComponent() {
  const t = useTranslations("common");
  
  return <p>{t("greeting")}</p>;
}

With Parameters

{
  "greeting": "Hello, {name}!",
  "items": "You have {count, plural, =0 {no items} =1 {one item} other {# items}}"
}
t("greeting", { name: "John" }); // "Hello, John!"
t("items", { count: 5 }); // "You have 5 items"

Adding a New Locale

Step 1: Update config

Add the locale to src/i18n/config.tsx

Step 2: Copy translation files

cp -r src/messages/dictionaries/en src/messages/dictionaries/es

Step 3: Translate files

Update all JSON files in the new locale folder

Step 4: Add Zod errors

cp src/messages/zod-errors/en.json src/messages/zod-errors/es.json

Features

Automatic Locale Detection

The middleware automatically detects locale from:

  1. URL path segment (highest priority)
  2. Cookie (NEXT_LOCALE)
  3. Accept-Language header
  4. Default locale (fallback)

Type-Safe Keys

Translation keys are fully typed when using the correct namespace:

const t = useTranslations("common");
t("welcome");     // ✅ Typed
t("nonexistent"); // ❌ TypeScript error

ICU Message Format

Supports pluralization, gender, and more:

{
  "followers": "{count, plural, =0 {No followers} =1 {1 follower} other {# followers}}",
  "greeting": "Hello {name}!"
}

Rich Text

Use RichText for formatted content with links:

{
  "terms": "By signing up, you agree to our <link>Terms of Service</link>."
}
import { RichText } from "@/i18n/rich-text";

<RichText
  messageKey="common.terms"
  components={{
    link: (chunks) => <Link href="/terms">{chunks}</Link>,
  }}
/>

Best Practices

  1. Use namespaces - Organize translations by feature or page
  2. Keep keys consistent - Use the same structure across all locales
  3. Avoid string concatenation - Use full sentences with parameters
  4. Test all locales - Verify translations before deployment

On this page

Overview
Structure
Quick Links
Supported Locales
Quick Start
Server Components
Client Components
With Parameters
Adding a New Locale
Step 1: Update config
Step 2: Copy translation files
Step 3: Translate files
Step 4: Add Zod errors
Features
Automatic Locale Detection
Type-Safe Keys
ICU Message Format
Rich Text
Best Practices