Internationalization

Add multi-language support to your documentation site

Geistdocs supports internationalization (i18n) out of the box using Fumadocs' language-aware routing. You can serve documentation in multiple languages with automatic translation via the Geistdocs CLI.

How It Works

The i18n system uses dynamic routing with a [lang] URL segment. The default language (English) doesn't show in URLs, while other languages get a prefix:

  • /docs/getting-started - English (default)
  • /cn/docs/getting-started - Chinese

Users can switch languages using the language selector in the navigation bar.

Translating Content

Use the Geistdocs CLI to automatically translate your MDX files:

pnpm translate

The CLI reads your target locales from geistdocs.tsx. If no locales are found in the config, you'll be prompted to enter them manually.

Translations are generated using the Geistdocs platform and saved alongside your original file with the locale suffix (e.g., introduction.cn.mdx).

Command Options

You can pass options directly to customize the translation behavior:

# Translate all MDX files (uses default pattern)
pnpm translate

# Translate files matching a specific glob pattern
pnpm translate --pattern "content/docs/**/*.mdx"

# Use a custom config file
pnpm translate --pattern "content/**/*.mdx" --config custom-config.tsx

# Use a custom translation API URL
pnpm translate --url "https://custom-api.example.com/translate"
OptionDescription
--patternGlob pattern to match MDX files (default: content/docs/**/*.mdx)
--configPath to config file with translations (default: geistdocs.tsx)
--urlCustom translation API URL (can also use GEISTDOCS_TRANSLATE_URL env var)

The CLI automatically excludes files that already have a locale suffix (e.g., getting-started.cn.mdx) to avoid translating already-translated content.

Batch Processing

When translating multiple files, the CLI automatically batches them into groups of 10. Progress is displayed as each batch completes, and a 1-second delay is added between batches to avoid rate limiting.

Configuration

Configure supported languages in geistdocs.tsx:

geistdocs.tsx
export const translations = {
  en: {
    displayName: "English",
  },
  cn: {
    displayName: "中文",
    search: "搜尋文檔",
  },
};

The first locale in the translations object is treated as your default/source language and is excluded from translation targets.

Adding a New Language

To add a new language:

  1. Add a new key to the translations object with the language code
  2. Add translations for UI elements like displayName and search
  3. Run pnpm translate --pattern "content/**/*.mdx" to generate translated content

The language selector will automatically include your new language.

Content Organization

Translated files are saved alongside the original with a locale suffix:

content/docs/
├── getting-started.mdx      # English (default)
├── getting-started.cn.mdx   # Chinese
├── getting-started.fr.mdx   # French
└── getting-started.es.mdx   # Spanish

Fumadocs automatically serves the correct file based on the URL path.

Translating UI Elements

The translations object in geistdocs.tsx controls UI text like search placeholders, navigation labels, and error messages. Add translations for each language you support.

If you don't provide a translation for a specific element, it falls back to English.

Language Detection

The language is determined by the URL path. There's no automatic detection based on browser settings - users must explicitly choose their language using the language selector.

This approach gives users full control and ensures they see the language they expect.