Codapult
TarifsPluginsDocs
Codapult

Le boilerplate SaaS pour les créateurs

Produit

  • Tarifs
  • Plugins
  • Documentation

Entreprise

  • Contact
  • GitHub

Mentions légales

  • Politique de confidentialité
  • Conditions d'utilisation

© 2026 Codapult. Tous droits réservés.

Tous les articles

Getting Started

  • Introduction
  • Quick Start
  • Project Structure

Configuration

  • Environment Variables
  • App Configuration

Authentication

  • Authentication
  • OAuth Providers
  • Two-Factor & Passwordless
  • Enterprise SSO (SAML)

Database

  • Database
  • Migrations

Teams

  • Teams & Organizations
  • Permissions & RBAC

Payments

  • Payments & Billing
  • Stripe Setup
  • LemonSqueezy Setup
  • Polar Setup
  • Payment Webhooks

Api

  • API Layer
  • tRPC
  • GraphQL

Ai

  • AI Features

Email

  • Email
  • Email Templates

Infrastructure

  • Infrastructure
  • File Storage
  • Background Jobs

Ui

  • UI & Theming

I18n

  • Internationalization

Content Management

  • Content Management

Admin

  • Admin Panel

Security

  • Security

Monitoring

  • Analytics & Monitoring

Modules

  • Module Architecture

Plugins

  • Plugin System
  • AI Kit Plugin
  • CRM Plugin
  • Helpdesk Plugin
  • Email Marketing Plugin

Deployment

  • Deployment
  • Troubleshooting

Upgrading

  • Upgrading Codapult

Developer Tools

  • MCP Server
  • Testing
I18n

Internationalization

Add languages, translate UI text, and localize blog content with next-intl and URL-based routing.

Codapult uses next-intl with URL path-prefix routing (localePrefix: 'as-needed'). Five locales ship out of the box — English (en), Russian (ru), German (de), French (fr), and Japanese (ja) — and adding more takes just a few minutes.

The default locale (en) has no URL prefix — pages are served at /about, /blog, etc. Non-default locales get a prefix: /ru/about, /de/blog, /ja/pricing.

How It Works

PieceLocation
Routing configsrc/i18n/routing.ts — defineRouting() with locale list
Navigation helperssrc/i18n/navigation.ts — locale-aware Link, useRouter
Request configsrc/i18n/request.ts — getRequestConfig()
Translation filesmessages/{en,ru,de,fr,ja}.json
Layoutsrc/app/[locale]/layout.tsx — root layout with [locale]

The [locale] segment in the App Router captures the active locale from the URL. The proxy layer (src/proxy.ts) integrates next-intl middleware to detect and redirect to the correct locale automatically.


Using Translations

Client Components

'use client';

import { useTranslations } from 'next-intl';

export function Greeting() {
  const t = useTranslations('dashboard');
  return <h1>{t('welcome')}</h1>;
}

Server Components

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

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

Message File Structure

Messages are organized by namespace. Use nested keys for logical grouping:

{
  "dashboard": {
    "welcome": "Welcome back",
    "settings": "Settings",
    "members": "{count, plural, one {# member} other {# members}}"
  },
  "auth": {
    "signIn": "Sign in",
    "signUp": "Create account"
  }
}

Pluralization follows the ICU MessageFormat syntax — {count, plural, one {…} other {…}}.


Locale-Aware Navigation

Always use the locale-aware navigation helpers from @/i18n/navigation instead of next/link and next/navigation:

import { Link, useRouter, usePathname } from '@/i18n/navigation';

// Link automatically adds the locale prefix
<Link href="/about">About</Link>;

// Router navigation preserves locale context
const router = useRouter();
router.push('/dashboard');

These wrappers are generated by createNavigation(routing) and ensure all links and programmatic navigation include the correct locale prefix.


Adding a New Locale

  1. Create the message file — copy messages/en.json and translate:
cp messages/en.json messages/es.json
  1. Register the locale in src/i18n/routing.ts:
export const routing = defineRouting({
  locales: ['en', 'ru', 'de', 'fr', 'ja', 'es'],
  defaultLocale: 'en',
  localePrefix: 'as-needed',
});
  1. Add a label for the locale switcher in src/components/theme/LocaleSwitcher.tsx:
const localeLabels: Record<string, string> = {
  en: 'English',
  ru: 'Русский',
  de: 'Deutsch',
  fr: 'Français',
  ja: '日本語',
  es: 'Español',
};
  1. Done. The LocaleSwitcher component and URL routing pick up the new locale automatically. Pages are available at /es/....

Locale Switcher

The LocaleSwitcher component renders a dropdown that navigates to the current page in a different locale. It uses useRouter().replace(pathname, { locale }) from @/i18n/navigation to switch locales via URL. It is included in the marketing header (Navbar).


Blog Localization

Blog posts use a filename convention for translations:

FileLocale
content/blog/my-post.mdxDefault (en)
content/blog/my-post.ru.mdxRussian
content/blog/my-post.de.mdxGerman
content/blog/my-post.fr.mdxFrench
content/blog/my-post.ja.mdxJapanese

The blog utilities in src/lib/blog/ automatically discover available locales per post and populate the availableLocales field in metadata. A per-post LocaleSwitch component lets readers navigate to the same article in a different locale.

If a post is not translated for the current locale, the reader sees the default-locale version.


Removing the i18n Module

If your product targets a single language, you can remove internationalization entirely via the setup wizard:

npx @codapult/cli setup

The wizard strips next-intl, the messages/ directory, the [locale] segment, the LocaleSwitcher component, and all useTranslations / getTranslations calls — leaving plain strings in their place.


SEO for Multi-Language Sites

Codapult includes built-in SEO support for multi-locale sites:

  • hreflang tags — Every page automatically generates <link rel="alternate" hreflang="xx" href="..." /> tags for all locales via the localeAlternates() helper in src/i18n/routing.ts. This is set via metadata.alternates in each layout/page.
  • Canonical URLs — Each locale version has its own canonical URL (e.g. /de/about for German, /about for English).
  • Sitemap — src/app/sitemap.ts generates per-locale alternate URLs for every page, so search engines discover all locale variants.
  • URL structure — Default locale has clean URLs (/about), non-default locales get path prefixes (/ru/about, /de/about). This is the industry-standard approach recommended by Google.
  • Blog SEO — Blog posts with locale variants automatically include cross-linked hreflang tags and locale-specific OG images.
UI & ThemingContent Management