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.10",
  "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-адресам: