Fumadocs

Translations

Adding Translations to UI

Overview

All official Fumadocs packages use English by default, you can add translations for other languages.

This page mainly covers details for adding UI translations, you may be interested in the full Internationalization guide instead.

Singular

Singular refers to adding translations for only one language:

lib/layout.shared.tsx
import { defineTranslations } from 'fumadocs-core/i18n';
import { uiTranslations } from 'fumadocs-ui/i18n';

export const translations = defineTranslations()
  .extend(uiTranslations())
  // add translations to "ui" namespace
  .add('ui', {
    search: '搜尋文檔',
  });

.add() should only be called after all .extend() calls.

Pass the translations to <RootProvider />.

import { RootProvider } from 'fumadocs-ui/provider/<framework>';
import { i18nProvider } from 'fumadocs-ui/i18n';
import { translations } from '@/lib/layout.shared';

export function Layout({ children }: { children: React.ReactNode }) {
  return (
    <RootProvider
      i18n={i18nProvider(translations)}
    >
      {children}
    </RootProvider>
  );
}

Multilingual

Define translations for multiple languages, this requires a standard i18n setup.

lib/layout.shared.tsx
import { defineTranslations } from 'fumadocs-core/i18n';
import { uiTranslations } from 'fumadocs-ui/i18n';
import { i18n } from '@/lib/i18n';

export const translations = i18n
  .translations()
  .extend(uiTranslations())
  // add translations to "ui" namespace
  .add('ui', {
    // [locale code]: { translations }
    cn: {
      search: '搜尋文檔',
    },
  });

Pass the translations to <RootProvider />.

import { RootProvider } from 'fumadocs-ui/provider/<framework>';
import { i18nProvider } from 'fumadocs-ui/i18n';
import { translations } from '@/lib/layout.shared';

export function Layout({ locale, children }: { locale: string; children: React.ReactNode }) {
  return (
    <RootProvider
      i18n={i18nProvider(translations, locale)}
    >
      {children}
    </RootProvider>
  );
}

Language Packs

Language packs provide translations for fumadocs-ui and several other integrations like Fumadocs OpenAPI.

npm i @fumadocs/language

If your desired language is missing in the official language packs, we welcome contributions to our repository.

Use preset() to consume language packs:

import { defineTranslations } from 'fumadocs-core/i18n';
import { openapiTranslations } from 'fumadocs-openapi/i18n';
import { uiTranslations } from 'fumadocs-ui/i18n';
import { zhTW } from '@fumadocs/language/zh-tw';

export const translations = defineTranslations()
  .extend(uiTranslations())
  // add extensions according to the integrations you configured, e.g. Fumadocs OpenAPI:
  .extend(openapiTranslations())
  // Traditional Chinese
  .preset(zhTW());

Custom Packs

You can also create & publish your own language packs.

For example, the structure of zh-TW language pack looks like:

import type { TranslationPreset } from 'fumadocs-core/i18n';
import * as OpenAPI from 'fumadocs-openapi/i18n';
import * as UI from 'fumadocs-ui/i18n';
import * as Story from '@fumadocs/story/i18n';

const ui = {
  displayName: '繁體中文',
  // ...
} satisfies UI.Translations;

const openapi = {
  loading: '載入中...',
  // ...
} satisfies OpenAPI.Translations;

const story = {
  noVariant: '沒有變體',
  // ...
} satisfies Story.Translations;

export function zhTW(): TranslationPreset<{
  ui: UI.Translations;
  openapi: OpenAPI.Translations;
  story: Story.Translations;
}> {
  return {
    name: 'zh-TW',
    value: {
      ui,
      openapi,
      story,
    },
  };
}

Extensions

Extensions declare the available namespace & labels for translations, only translations in registered namespaces will be sent to client payload.

Custom Extension

If you are building community packages for Fumadocs, you can create extensions to register your own translations.

import type { TranslationsAPIExtension, TranslationValue } from 'fumadocs-core/i18n';

export const defaultTranslations = {
  labelExample: 'Hello World',
  labelWithVariable: 'Hello {user}' as TranslationValue<'user'>,
};

export type Translations = typeof defaultTranslations;

export function myTranslations(): TranslationsAPIExtension<'my-package', Translations> {
  return {
    namespace: 'my-package',
    defaultValue: defaultTranslations,
  };
}

Consumers can use your extension like:

import { defineTranslations } from 'fumadocs-core/i18n';
import { myTranslations } from 'my-package/i18n';

export const translations = defineTranslations()
  .extend(myTranslations())
  .add('my-package', {
    labelExample: 'Hello Apple',
  });

How is this guide?

Last updated on

On this page