Fumadocs

AI-перевод для Fumadocs с помощью Lingo.dev CLI

Что такое Fumadocs?

Fumadocs — это фреймворк для создания документации с открытым исходным кодом. Он предоставляет быстрый, типобезопасный сайт документации с встроенным поиском, поддержкой интернационализации и красивым пользовательским интерфейсом.

Что такое Lingo.dev CLI?

Lingo.dev — это платформа перевода на основе искусственного интеллекта. Lingo.dev CLI считывает исходные файлы, отправляет переводимый контент в крупные языковые модели и записывает переведенные файлы обратно в ваш проект.

О данном руководстве

В этом руководстве объясняется, как настроить Lingo.dev CLI в проекте документации Fumadocs. Вы узнаете, как создать проект с помощью Fumadocs, настроить процесс перевода и просмотреть результаты.

Шаг 1. Настройка проекта Fumadocs

  1. Создайте новое приложение Fumadocs:

    npm create fumadocs-app
    
  2. Следуйте инструкциям для настройки проекта с предпочтительными параметрами.

  3. Перейдите в каталог проекта:

    cd <project-name>
    

Шаг 2. Настройка поддержки интернационализации

Fumadocs необходимо знать, какие языки будет поддерживать ваша документация. Вам нужно будет создать конфигурационные файлы, которые укажут Fumadocs, как обрабатывать несколько языков.

  1. Создайте файл lib/i18n.ts, чтобы определить поддерживаемые языки:

    import { defineI18n } from 'fumadocs-core/i18n';
    
    export const i18n = defineI18n({
      defaultLanguage: 'en',
      languages: ['en', 'es'],
      parser: "dir",
    });
    
  2. Обновите файл lib/source.ts, чтобы использовать настройки i18n:

    import { docs } from "@/.source";
    import { loader } from "fumadocs-core/source";
    import { i18n } from "@/lib/i18n";
    
    // Подробнее см. https://fumadocs.vercel.app/docs/headless/source-api
    export const source = loader({
      // назначает URL вашим страницам
      baseUrl: "/docs",
      source: docs.toFumadocsSource(),
      i18n,
    });
    
  3. Создайте middleware для определения и перенаправления пользователей на основе их языковых предпочтений:

    // middleware.ts
    import { createI18nMiddleware } from 'fumadocs-core/i18n/middleware';
    import { i18n } from '@/lib/i18n';
    
    export default createI18nMiddleware(i18n);
    
    export const config = {
      // Исключение для `/_next/` и `/api/`
      // Возможно, потребуется настроить для исключения статических ресурсов в папке `/public`
      matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
    };
    

Шаг 3. Обновите структуру приложения для нескольких языков

  1. Создайте каталог параметров языка в папке app/:

    mkdir app/[lang]
    
  2. Переместите существующие страницы в каталог параметров языка:

    • app/docs/app/[lang]/docs/
    • app/(home)/app/[lang]/(home)/
  3. Создайте файл app/[lang]/layout.tsx, чтобы обернуть все страницы, специфичные для языка:

    import { RootProvider } from "fumadocs-ui/provider";
    import { defineI18nUI } from "fumadocs-ui/i18n";
    import { i18n } from "@/lib/i18n";
    
    const { provider } = defineI18nUI(i18n, {
      translations: {
        en: {
          displayName: "English",
        },
        es: {
          displayName: "Español",
        },
      },
    });
    
    export default async function RootLayout({
      params,
      children,
    }: LayoutProps<"/[lang]">) {
      const lang = (await params).lang;
    
      return (
        <html lang={lang}>
          <body>
            <RootProvider i18n={provider(lang)}>{children}</RootProvider>
          </body>
        </html>
      );
    }
    

Шаг 4. Создайте общие параметры макета

  1. Создайте файл lib/layout.shared.tsx для общих конфигураций макета:

    // lib/layout.shared.tsx
    import type { BaseLayoutProps } from "fumadocs-ui/layouts/shared";
    import { i18n } from "@/lib/i18n";
    
    /**
     * Общие конфигурации макета
     *
     * вы можете настроить макеты индивидуально из:
     * Макет главной страницы: app/(home)/layout.tsx
     * Макет документации: app/docs/layout.tsx
     */
    export function baseOptions(locale: string): BaseLayoutProps {
      return {
        i18n,
        nav: {
          title: (
            <>
              <svg
                width="24"
                height="24"
                xmlns="http://www.w3.org/2000/svg"
                aria-label="Logo"
              >
                <circle cx={12} cy={12} r={12} fill="currentColor" />
              </svg>
              My App
            </>
          ),
        },
        // см. https://fumadocs.dev/docs/ui/navigation/links
        links: [],
      };
    }
    
  2. Обновите файл app/[lang]/docs/layout.tsx, чтобы использовать общие параметры:

    // app/[lang]/docs/layout.tsx
    import type { ReactNode } from "react";
    import { source } from "@/lib/source";
    import { DocsLayout } from "fumadocs-ui/layouts/docs";
    import { baseOptions } from "@/lib/layout.shared";
    
    export default async function Layout({
      params,
      children,
    }: LayoutProps<"/[lang]/docs">) {
      const { lang } = await params;
    
      return (
        <DocsLayout {...baseOptions(lang)} tree={source.pageTree[lang]}>
          {children}
        </DocsLayout>
      );
    }
    
  3. Обновите файл app/[lang]/(home)/layout.tsx, чтобы использовать общие параметры:

    // app/[lang]/(home)/layout.tsx
    import { HomeLayout } from "fumadocs-ui/layouts/home";
    import { baseOptions } from "@/lib/layout.shared";
    
    export default async function Layout({
      children,
      params,
    }: LayoutProps<"/[lang]">) {
      const { lang } = await params;
      return <HomeLayout {...baseOptions(lang)}>{children}</HomeLayout>;
    }
    

Шаг 5. Обновите компоненты страницы

Обновите компоненты страницы (например, app/[lang]/docs/[[...slug]]/page.tsx), чтобы они обрабатывали параметр языка:

import { source } from "@/lib/source";
import {
  DocsBody,
  DocsDescription,
  DocsPage,
  DocsTitle,
} from "fumadocs-ui/page";
import type { Metadata } from "next";
import { notFound } from "next/navigation";
import { createRelativeLink } from "fumadocs-ui/mdx";
import { getMDXComponents } from "@/mdx-components";

export default async function Page(
  props: PageProps<"/[lang]/docs/[[...slug]]">,
) {
  const params = await props.params;
  const page = source.getPage(params.slug, params.lang);
  if (!page) notFound();

  const MDXContent = page.data.body;

  return (
    <DocsPage toc={page.data.toc} full={page.data.full}>
      <DocsTitle>{page.data.title}</DocsTitle>
      <DocsDescription>{page.data.description}</DocsDescription>
      <DocsBody>
        <MDXContent
          components={getMDXComponents({
            // это позволяет ссылаться на другие страницы с относительными путями файлов
            a: createRelativeLink(source, page),
          })}
        />
      </DocsBody>
    </DocsPage>
  );
}

export async function generateStaticParams() {
  return source.generateParams();
}

export async function generateMetadata(
  props: PageProps<"/[lang]/docs/[[...slug]]">,
): Promise<Metadata> {
  const params = await props.params;
  const page = source.getPage(params.slug, params.lang);
  if (!page) notFound();

  return {
    title: page.data.title,
    description: page.data.description,
  };
}

Шаг 6. Организуйте контент для перевода

  1. Создайте языковые директории для контента:

    mkdir -p content/docs/en
    
  2. Переместите существующие MDX-файлы в директорию для английского языка:

    • content/docs/index.mdxcontent/docs/en/index.mdx
    • content/docs/test.mdxcontent/docs/en/test.mdx

Шаг 7. Настройте CLI

В корне проекта создайте файл i18n.json:

{
  "$schema": "https://lingo.dev/schema/i18n.json",
  "version": 1.8,
  "locale": {
    "source": "en",
    "targets": ["es"]
  },
  "buckets": {
    "mdx": {
      "include": ["content/docs/[locale]/*.mdx"]
    }
  }
}

Этот файл определяет:

  • файлы, которые CLI Lingo.dev должен переводить
  • языки для перевода

В данном случае конфигурация переводит MDX-файлы с английского на испанский.

Важно отметить, что:

  • [locale] — это плейсхолдер, который заменяется во время выполнения. Он гарантирует, что контент читается из одного места (например, src/content/docs/en/index.mdx) и записывается в другое место (например, src/content/docs/es/index.mdx).
  • CLI Lingo.dev не поддерживает рекурсивные шаблоны (например, **/*.mdx). Вам нужно будет создать дополнительные шаблоны include, чтобы переводить файлы, находящиеся в вложенных директориях.

Чтобы узнать больше, см. конфигурация i18n.json.

Шаг 8. Переведите контент

  1. Зарегистрируйтесь в Lingo.dev.

  2. Войдите в Lingo.dev через CLI:

    npx lingo.dev@latest login
    
  3. Запустите процесс перевода:

    npx lingo.dev@latest run
    

    CLI создаст директорию content/docs/es/ для хранения переведенного контента и файл i18n.lock для отслеживания переведенного (чтобы избежать ненужных повторных переводов).

Шаг 9. Просмотрите переведенную документацию

  1. Запустите сервер разработки:

    npm run dev
    
  2. Перейдите по следующим URL-адресам: