diff --git a/.gitignore b/.gitignore
index 49ac561..7f8c5de 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,6 +26,7 @@ downloads/
eggs/
.eggs/
lib/
+!docs/lib/
lib64/
parts/
sdist/
diff --git a/docs/app/(home)/layout.tsx b/docs/app/(home)/layout.tsx
deleted file mode 100644
index 77379fa..0000000
--- a/docs/app/(home)/layout.tsx
+++ /dev/null
@@ -1,6 +0,0 @@
-import { HomeLayout } from 'fumadocs-ui/layouts/home';
-import { baseOptions } from '@/lib/layout.shared';
-
-export default function Layout({ children }: LayoutProps<'/'>) {
- return {children};
-}
diff --git a/docs/app/(home)/page.tsx b/docs/app/(home)/page.tsx
deleted file mode 100644
index c936084..0000000
--- a/docs/app/(home)/page.tsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import Link from 'next/link';
-
-export default function HomePage() {
- return (
-
-
Hello World
-
- You can open{' '}
-
- /docs
- {' '}
- and see the documentation.
-
-
- );
-}
diff --git a/docs/app/[lang]/(home)/layout.tsx b/docs/app/[lang]/(home)/layout.tsx
new file mode 100644
index 0000000..12db1f0
--- /dev/null
+++ b/docs/app/[lang]/(home)/layout.tsx
@@ -0,0 +1,13 @@
+import { HomeLayout } from "fumadocs-ui/layouts/home";
+import { baseOptions } from "@/lib/layout.shared";
+
+export default async function Layout({
+ params,
+ children,
+}: {
+ params: Promise<{ lang: string }>;
+ children: React.ReactNode;
+}) {
+ const { lang } = await params;
+ return {children};
+}
diff --git a/docs/app/[lang]/(home)/page.tsx b/docs/app/[lang]/(home)/page.tsx
new file mode 100644
index 0000000..7a3af23
--- /dev/null
+++ b/docs/app/[lang]/(home)/page.tsx
@@ -0,0 +1,47 @@
+import { DynamicLink } from "fumadocs-core/dynamic-link";
+
+const greetings: Record = {
+ en: "Hello World",
+ zh: "你好世界",
+ es: "Hola Mundo",
+ ja: "こんにちは世界",
+};
+
+const descriptions: Record = {
+ en: "You can open",
+ zh: "你可以打开",
+ es: "Puedes abrir",
+ ja: "開くことができます",
+};
+
+const docsText: Record = {
+ en: "and see the documentation.",
+ zh: "查看文档。",
+ es: "y ver la documentación.",
+ ja: "でドキュメントを確認できます。",
+};
+
+export default async function HomePage({
+ params,
+}: {
+ params: Promise<{ lang: string }>;
+}) {
+ const { lang } = await params;
+ return (
+
+
+ {greetings[lang] ?? greetings.en}
+
+
+ {descriptions[lang] ?? descriptions.en}{" "}
+
+ /docs
+ {" "}
+ {docsText[lang] ?? docsText.en}
+
+
+ );
+}
diff --git a/docs/app/[lang]/docs/[[...slug]]/page.tsx b/docs/app/[lang]/docs/[[...slug]]/page.tsx
new file mode 100644
index 0000000..eb85ea3
--- /dev/null
+++ b/docs/app/[lang]/docs/[[...slug]]/page.tsx
@@ -0,0 +1,74 @@
+import { getPageImage, source } from "@/lib/source";
+import {
+ DocsBody,
+ DocsDescription,
+ DocsPage,
+ DocsTitle,
+} from "fumadocs-ui/layouts/docs/page";
+import { notFound } from "next/navigation";
+import { getMDXComponents } from "@/mdx-components";
+import type { Metadata } from "next";
+import { createRelativeLink } from "fumadocs-ui/mdx";
+import { LLMCopyButton, ViewOptions } from "@/components/ai/page-actions";
+
+export default async function Page({
+ params,
+}: {
+ params: Promise<{ lang: string; slug?: string[] }>;
+}) {
+ const { lang, slug } = await params;
+ const page = source.getPage(slug, lang);
+ if (!page) notFound();
+
+ const MDX = page.data.body;
+ const gitConfig = {
+ user: "username",
+ repo: "repo",
+ branch: "main",
+ };
+
+ return (
+
+ {page.data.title}
+
+ {page.data.description}
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export async function generateStaticParams() {
+ return source.generateParams();
+}
+
+export async function generateMetadata({
+ params,
+}: {
+ params: Promise<{ lang: string; slug?: string[] }>;
+}): Promise {
+ const { lang, slug } = await params;
+ const page = source.getPage(slug, lang);
+ if (!page) notFound();
+
+ return {
+ title: page.data.title,
+ description: page.data.description,
+ openGraph: {
+ images: getPageImage(page).url,
+ },
+ };
+}
diff --git a/docs/app/[lang]/docs/layout.tsx b/docs/app/[lang]/docs/layout.tsx
new file mode 100644
index 0000000..f894a31
--- /dev/null
+++ b/docs/app/[lang]/docs/layout.tsx
@@ -0,0 +1,18 @@
+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,
+}: {
+ params: Promise<{ lang: string }>;
+ children: React.ReactNode;
+}) {
+ const { lang } = await params;
+ return (
+
+ {children}
+
+ );
+}
diff --git a/docs/app/[lang]/layout.tsx b/docs/app/[lang]/layout.tsx
new file mode 100644
index 0000000..ab7bc3a
--- /dev/null
+++ b/docs/app/[lang]/layout.tsx
@@ -0,0 +1,74 @@
+import { RootProvider } from "fumadocs-ui/provider/next";
+import { Archivo } from "next/font/google";
+import { defineI18nUI } from "fumadocs-ui/i18n";
+import { i18n } from "@/lib/i18n";
+
+const archivo = Archivo({
+ subsets: ["latin", "latin-ext"],
+ weight: ["500"],
+ display: "swap",
+});
+
+const { provider } = defineI18nUI(i18n, {
+ translations: {
+ en: {
+ displayName: "English",
+ },
+ zh: {
+ displayName: "中文",
+ toc: "目录",
+ search: "搜索文档",
+ lastUpdate: "最后更新于",
+ searchNoResult: "没有结果",
+ previousPage: "上一页",
+ nextPage: "下一页",
+ chooseLanguage: "选择语言",
+ chooseTheme: "选择主题",
+ editOnGithub: "在 GitHub 上编辑",
+ tocNoHeadings: "无标题",
+ },
+ es: {
+ displayName: "Español",
+ toc: "En esta página",
+ search: "Buscar documentación",
+ lastUpdate: "Última actualización",
+ searchNoResult: "Sin resultados",
+ previousPage: "Página anterior",
+ nextPage: "Página siguiente",
+ chooseLanguage: "Elegir idioma",
+ chooseTheme: "Elegir tema",
+ editOnGithub: "Editar en GitHub",
+ tocNoHeadings: "Sin encabezados",
+ },
+ ja: {
+ displayName: "日本語",
+ toc: "目次",
+ search: "ドキュメントを検索",
+ lastUpdate: "最終更新",
+ searchNoResult: "結果なし",
+ previousPage: "前のページ",
+ nextPage: "次のページ",
+ chooseLanguage: "言語を選択",
+ chooseTheme: "テーマを選択",
+ editOnGithub: "GitHub で編集",
+ tocNoHeadings: "見出しなし",
+ },
+ },
+});
+
+export default async function Layout({
+ params,
+ children,
+}: {
+ params: Promise<{ lang: string }>;
+ children: React.ReactNode;
+}) {
+ const { lang } = await params;
+ return (
+
+
+ {children}
+
+
+ );
+}
diff --git a/docs/app/api/search/route.ts b/docs/app/api/search/route.ts
index 7ba7e82..b57ef6d 100644
--- a/docs/app/api/search/route.ts
+++ b/docs/app/api/search/route.ts
@@ -1,7 +1,19 @@
-import { source } from '@/lib/source';
-import { createFromSource } from 'fumadocs-core/search/server';
+import { source } from "@/lib/source";
+import { createFromSource } from "fumadocs-core/search/server";
export const { GET } = createFromSource(source, {
- // https://docs.orama.com/docs/orama-js/supported-languages
- language: 'english',
+ localeMap: {
+ zh: {
+ search: {
+ threshold: 0,
+ tolerance: 0,
+ },
+ },
+ ja: {
+ search: {
+ threshold: 0,
+ tolerance: 0,
+ },
+ },
+ },
});
diff --git a/docs/app/docs/[[...slug]]/page.tsx b/docs/app/docs/[[...slug]]/page.tsx
deleted file mode 100644
index 8e76ac4..0000000
--- a/docs/app/docs/[[...slug]]/page.tsx
+++ /dev/null
@@ -1,61 +0,0 @@
-import { getPageImage, source } from '@/lib/source';
-import { DocsBody, DocsDescription, DocsPage, DocsTitle } from 'fumadocs-ui/layouts/docs/page';
-import { notFound } from 'next/navigation';
-import { getMDXComponents } from '@/mdx-components';
-import type { Metadata } from 'next';
-import { createRelativeLink } from 'fumadocs-ui/mdx';
-import { LLMCopyButton, ViewOptions } from '@/components/ai/page-actions';
-
-export default async function Page(props: PageProps<'/docs/[[...slug]]'>) {
- const params = await props.params;
- const page = source.getPage(params.slug);
- if (!page) notFound();
-
- const MDX = page.data.body;
- const gitConfig = {
- user: 'username',
- repo: 'repo',
- branch: 'main',
- };
-
- return (
-
- {page.data.title}
- {page.data.description}
-
-
-
-
-
-
-
-
- );
-}
-
-export async function generateStaticParams() {
- return source.generateParams();
-}
-
-export async function generateMetadata(props: PageProps<'/docs/[[...slug]]'>): Promise {
- const params = await props.params;
- const page = source.getPage(params.slug);
- if (!page) notFound();
-
- return {
- title: page.data.title,
- description: page.data.description,
- openGraph: {
- images: getPageImage(page).url,
- },
- };
-}
diff --git a/docs/app/docs/layout.tsx b/docs/app/docs/layout.tsx
deleted file mode 100644
index a373143..0000000
--- a/docs/app/docs/layout.tsx
+++ /dev/null
@@ -1,11 +0,0 @@
-import { source } from '@/lib/source';
-import { DocsLayout } from 'fumadocs-ui/layouts/docs';
-import { baseOptions } from '@/lib/layout.shared';
-
-export default function Layout({ children }: LayoutProps<'/docs'>) {
- return (
-
- {children}
-
- );
-}
diff --git a/docs/app/layout.tsx b/docs/app/layout.tsx
index a69e70f..0670827 100644
--- a/docs/app/layout.tsx
+++ b/docs/app/layout.tsx
@@ -1,13 +1,6 @@
-import { RootProvider } from "fumadocs-ui/provider/next";
import "./global.css";
-import { Archivo } from "next/font/google";
import type { Metadata } from "next";
-const archivo = Archivo({
- subsets: ["latin"],
- weight: ["500"],
-});
-
export const metadata: Metadata = {
title: "Python Template Documentation",
description: "Super-opinionated Python stack for fast development",
@@ -29,12 +22,6 @@ export const metadata: Metadata = {
},
};
-export default function Layout({ children }: LayoutProps<'/'>) {
- return (
-
-
- {children}
-
-
- );
+export default function Layout({ children }: { children: React.ReactNode }) {
+ return children;
}
diff --git a/docs/app/llms-full.txt/route.ts b/docs/app/llms-full.txt/route.ts
index d494d2c..5bc1cb2 100644
--- a/docs/app/llms-full.txt/route.ts
+++ b/docs/app/llms-full.txt/route.ts
@@ -1,10 +1,13 @@
-import { getLLMText, source } from '@/lib/source';
+import { getLLMText, source } from "@/lib/source";
+import { i18n } from "@/lib/i18n";
+import { type NextRequest } from "next/server";
export const revalidate = false;
-export async function GET() {
- const scan = source.getPages().map(getLLMText);
- const scanned = await Promise.all(scan);
+export async function GET(req: NextRequest) {
+ const lang = req.nextUrl.searchParams.get("lang") ?? i18n.defaultLanguage;
+ const pages = source.getPages(lang);
+ const scanned = await Promise.all(pages.map(getLLMText));
- return new Response(scanned.join('\n\n'));
+ return new Response(scanned.join("\n\n"));
}
diff --git a/docs/app/llms.mdx/[lang]/docs/[[...slug]]/route.ts b/docs/app/llms.mdx/[lang]/docs/[[...slug]]/route.ts
new file mode 100644
index 0000000..38d424f
--- /dev/null
+++ b/docs/app/llms.mdx/[lang]/docs/[[...slug]]/route.ts
@@ -0,0 +1,23 @@
+import { getLLMText, source } from "@/lib/source";
+import { notFound } from "next/navigation";
+
+export const revalidate = false;
+
+export async function GET(
+ _req: Request,
+ { params }: { params: Promise<{ lang: string; slug?: string[] }> },
+) {
+ const { lang, slug } = await params;
+ const page = source.getPage(slug, lang);
+ if (!page) notFound();
+
+ return new Response(await getLLMText(page), {
+ headers: {
+ "Content-Type": "text/markdown",
+ },
+ });
+}
+
+export function generateStaticParams() {
+ return source.generateParams();
+}
diff --git a/docs/app/llms.mdx/docs/[[...slug]]/route.ts b/docs/app/llms.mdx/docs/[[...slug]]/route.ts
deleted file mode 100644
index fde26d9..0000000
--- a/docs/app/llms.mdx/docs/[[...slug]]/route.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import { getLLMText, source } from '@/lib/source';
-import { notFound } from 'next/navigation';
-
-export const revalidate = false;
-
-export async function GET(_req: Request, { params }: RouteContext<'/llms.mdx/docs/[[...slug]]'>) {
- const { slug } = await params;
- const page = source.getPage(slug);
- if (!page) notFound();
-
- return new Response(await getLLMText(page), {
- headers: {
- 'Content-Type': 'text/markdown',
- },
- });
-}
-
-export function generateStaticParams() {
- return source.generateParams();
-}
diff --git a/docs/app/og/[lang]/docs/[...slug]/route.tsx b/docs/app/og/[lang]/docs/[...slug]/route.tsx
new file mode 100644
index 0000000..021d640
--- /dev/null
+++ b/docs/app/og/[lang]/docs/[...slug]/route.tsx
@@ -0,0 +1,34 @@
+import { getPageImage, source } from "@/lib/source";
+import { notFound } from "next/navigation";
+import { ImageResponse } from "next/og";
+import { generate as DefaultImage } from "fumadocs-ui/og";
+
+export const revalidate = false;
+
+export async function GET(
+ _req: Request,
+ { params }: { params: Promise<{ lang: string; slug: string[] }> },
+) {
+ const { lang, slug } = await params;
+ const page = source.getPage(slug.slice(0, -1), lang);
+ if (!page) notFound();
+
+ return new ImageResponse(
+ ,
+ {
+ width: 1200,
+ height: 630,
+ },
+ );
+}
+
+export function generateStaticParams() {
+ return source.getPages().map((page) => ({
+ lang: page.locale,
+ slug: getPageImage(page).segments,
+ }));
+}
diff --git a/docs/app/og/docs/[...slug]/route.tsx b/docs/app/og/docs/[...slug]/route.tsx
deleted file mode 100644
index 2d741be..0000000
--- a/docs/app/og/docs/[...slug]/route.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-import { getPageImage, source } from '@/lib/source';
-import { notFound } from 'next/navigation';
-import { ImageResponse } from 'next/og';
-import { generate as DefaultImage } from 'fumadocs-ui/og';
-
-export const revalidate = false;
-
-export async function GET(_req: Request, { params }: RouteContext<'/og/docs/[...slug]'>) {
- const { slug } = await params;
- const page = source.getPage(slug.slice(0, -1));
- if (!page) notFound();
-
- return new ImageResponse(
- ,
- {
- width: 1200,
- height: 630,
- },
- );
-}
-
-export function generateStaticParams() {
- return source.getPages().map((page) => ({
- lang: page.locale,
- slug: getPageImage(page).segments,
- }));
-}
diff --git a/docs/content/docs/api.es.mdx b/docs/content/docs/api.es.mdx
new file mode 100644
index 0000000..db567eb
--- /dev/null
+++ b/docs/content/docs/api.es.mdx
@@ -0,0 +1,37 @@
+---
+title: Referencia API
+description: Descripcion general de la API y marcadores de posicion para futuros endpoints
+---
+
+## Descripcion General
+
+Esta plantilla no incluye una API publica por defecto. Usa esta pagina como
+punto de partida para documentar cualquier endpoint que agregues.
+
+## URL Base
+
+Configura esto una vez que tu servicio este desplegado, por ejemplo:
+
+```
+https://api.example.com
+```
+
+## Autenticacion
+
+Describe aqui los encabezados o tokens requeridos (por ejemplo, tokens Bearer o
+claves API).
+
+## Formato de Error
+
+Documenta la estructura de error que tu API retorna. Ejemplo:
+
+```
+{
+ "error": "string",
+ "message": "string"
+}
+```
+
+## Endpoints
+
+Agrega tus endpoints aqui a medida que los implementes.
diff --git a/docs/content/docs/api.ja.mdx b/docs/content/docs/api.ja.mdx
new file mode 100644
index 0000000..054304c
--- /dev/null
+++ b/docs/content/docs/api.ja.mdx
@@ -0,0 +1,35 @@
+---
+title: API リファレンス
+description: API の概要と将来のエンドポイントのプレースホルダー
+---
+
+## 概要
+
+このテンプレートはデフォルトではパブリック API を提供していません。このページを、追加するエンドポイントのドキュメントの出発点としてご利用ください。
+
+## ベース URL
+
+サービスをデプロイしたら設定してください。例:
+
+```
+https://api.example.com
+```
+
+## 認証
+
+必要なヘッダーやトークン(例:Bearer トークンや API キー)をここに記述してください。
+
+## エラーフォーマット
+
+API が返すエラーの形式を記述してください。例:
+
+```
+{
+ "error": "string",
+ "message": "string"
+}
+```
+
+## エンドポイント
+
+実装に応じてエンドポイントをここに追加してください。
diff --git a/docs/content/docs/api.zh.mdx b/docs/content/docs/api.zh.mdx
new file mode 100644
index 0000000..5899079
--- /dev/null
+++ b/docs/content/docs/api.zh.mdx
@@ -0,0 +1,35 @@
+---
+title: API 参考
+description: API 概述和未来端点的占位符
+---
+
+## 概述
+
+此模板默认不提供公共 API。请将此页面作为记录您添加的任何端点的起点。
+
+## 基础 URL
+
+部署服务后设置此项,例如:
+
+```
+https://api.example.com
+```
+
+## 身份验证
+
+在此描述所需的请求头或令牌(例如,Bearer 令牌或 API 密钥)。
+
+## 错误格式
+
+记录 API 返回的错误信封。示例结构:
+
+```
+{
+ "error": "string",
+ "message": "string"
+}
+```
+
+## 端点
+
+在实现时在此添加您的端点。
diff --git a/docs/content/docs/index.es.mdx b/docs/content/docs/index.es.mdx
new file mode 100644
index 0000000..8fc9c09
--- /dev/null
+++ b/docs/content/docs/index.es.mdx
@@ -0,0 +1,84 @@
+---
+title: Inicio Rapido
+description: Comienza con esta plantilla de Python
+---
+
+Bienvenido a la documentacion! Sigue estos pasos para comenzar con esta plantilla de Python.
+
+## Inicio Rapido
+
+import { Step, Steps } from 'fumadocs-ui/components/steps';
+
+
+
+
+### Configurar Entorno
+
+Crea y activa tu entorno virtual usando `uv`:
+
+```bash
+make setup
+```
+
+Esto creara un directorio `.venv` y sincronizara todas las dependencias de `pyproject.toml`.
+
+
+
+
+
+### Configurar Ajustes
+
+Copia el archivo de entorno de ejemplo y agrega tus claves API:
+
+```bash
+cp .env.example .env
+```
+
+Edita `common/global_config.yaml` para personalizar los valores de configuracion de tu proyecto.
+
+
+
+
+
+### Ejecutar la Aplicacion
+
+Ejecuta la aplicacion principal:
+
+```bash
+make all
+```
+
+O ejecuta archivos Python especificos directamente:
+
+```bash
+uv run python src/main.py
+```
+
+
+
+
+
+### Ejecutar Pruebas
+
+Verifica que todo funcione ejecutando el conjunto de pruebas:
+
+```bash
+make test
+```
+
+Ejecuta verificaciones de calidad de codigo:
+
+```bash
+make ci
+```
+
+
+
+
+## Proximos Pasos
+
+
+
+
+
+
diff --git a/docs/content/docs/index.ja.mdx b/docs/content/docs/index.ja.mdx
new file mode 100644
index 0000000..b7a95c8
--- /dev/null
+++ b/docs/content/docs/index.ja.mdx
@@ -0,0 +1,84 @@
+---
+title: クイックスタート
+description: この Python テンプレートを始めましょう
+---
+
+ドキュメントへようこそ!以下の手順に従って、この Python テンプレートを使い始めましょう。
+
+## クイックスタート
+
+import { Step, Steps } from 'fumadocs-ui/components/steps';
+
+
+
+
+### 環境のセットアップ
+
+`uv` を使用して仮想環境を作成し、有効化します:
+
+```bash
+make setup
+```
+
+これにより `.venv` ディレクトリが作成され、`pyproject.toml` のすべての依存関係が同期されます。
+
+
+
+
+
+### 設定の構成
+
+環境ファイルの例をコピーして API キーを追加します:
+
+```bash
+cp .env.example .env
+```
+
+`common/global_config.yaml` を編集してプロジェクトの設定値をカスタマイズします。
+
+
+
+
+
+### アプリケーションの実行
+
+メインアプリケーションを実行します:
+
+```bash
+make all
+```
+
+または特定の Python ファイルを直接実行します:
+
+```bash
+uv run python src/main.py
+```
+
+
+
+
+
+### テストの実行
+
+テストスイートを実行してすべてが正常に動作することを確認します:
+
+```bash
+make test
+```
+
+コード品質チェックを実行します:
+
+```bash
+make ci
+```
+
+
+
+
+## 次のステップ
+
+
+
+
+
+
diff --git a/docs/content/docs/index.zh.mdx b/docs/content/docs/index.zh.mdx
new file mode 100644
index 0000000..aad009c
--- /dev/null
+++ b/docs/content/docs/index.zh.mdx
@@ -0,0 +1,84 @@
+---
+title: 快速入门
+description: 开始使用此 Python 模板
+---
+
+欢迎来到文档!按照以下步骤开始使用此 Python 模板。
+
+## 快速入门
+
+import { Step, Steps } from 'fumadocs-ui/components/steps';
+
+
+
+
+### 设置环境
+
+使用 `uv` 创建并激活虚拟环境:
+
+```bash
+make setup
+```
+
+这将创建 `.venv` 目录并同步 `pyproject.toml` 中的所有依赖。
+
+
+
+
+
+### 配置设置
+
+复制示例环境文件并添加 API 密钥:
+
+```bash
+cp .env.example .env
+```
+
+编辑 `common/global_config.yaml` 自定义项目配置。
+
+
+
+
+
+### 运行应用
+
+执行主应用程序:
+
+```bash
+make all
+```
+
+或直接运行特定 Python 文件:
+
+```bash
+uv run python src/main.py
+```
+
+
+
+
+
+### 运行测试
+
+通过运行测试套件验证一切正常:
+
+```bash
+make test
+```
+
+运行代码质量检查:
+
+```bash
+make ci
+```
+
+
+
+
+## 下一步
+
+
+
+
+
+
diff --git a/docs/content/docs/test.es.mdx b/docs/content/docs/test.es.mdx
new file mode 100644
index 0000000..676a9cf
--- /dev/null
+++ b/docs/content/docs/test.es.mdx
@@ -0,0 +1,17 @@
+---
+title: Componentes
+description: Componentes
+---
+
+## Bloque de Codigo
+
+```js
+console.log('Hola Mundo');
+```
+
+## Tarjetas
+
+
+
+
+
diff --git a/docs/content/docs/test.ja.mdx b/docs/content/docs/test.ja.mdx
new file mode 100644
index 0000000..3ce7c6e
--- /dev/null
+++ b/docs/content/docs/test.ja.mdx
@@ -0,0 +1,17 @@
+---
+title: コンポーネント
+description: コンポーネント
+---
+
+## コードブロック
+
+```js
+console.log('こんにちは世界');
+```
+
+## カード
+
+
+
+
+
diff --git a/docs/content/docs/test.zh.mdx b/docs/content/docs/test.zh.mdx
new file mode 100644
index 0000000..4a97cc9
--- /dev/null
+++ b/docs/content/docs/test.zh.mdx
@@ -0,0 +1,17 @@
+---
+title: 组件
+description: 组件展示
+---
+
+## 代码块
+
+```js
+console.log('你好世界');
+```
+
+## 卡片
+
+
+
+
+
diff --git a/docs/lib/cn.ts b/docs/lib/cn.ts
new file mode 100644
index 0000000..652f019
--- /dev/null
+++ b/docs/lib/cn.ts
@@ -0,0 +1,5 @@
+import { twMerge } from "tailwind-merge";
+
+export function cn(...inputs: (string | undefined | null | false)[]) {
+ return twMerge(...inputs);
+}
diff --git a/docs/lib/i18n.ts b/docs/lib/i18n.ts
new file mode 100644
index 0000000..286d40e
--- /dev/null
+++ b/docs/lib/i18n.ts
@@ -0,0 +1,6 @@
+import { defineI18n } from "fumadocs-core/i18n";
+
+export const i18n = defineI18n({
+ defaultLanguage: "en",
+ languages: ["en", "zh", "es", "ja"],
+});
diff --git a/docs/lib/layout.shared.tsx b/docs/lib/layout.shared.tsx
new file mode 100644
index 0000000..6893677
--- /dev/null
+++ b/docs/lib/layout.shared.tsx
@@ -0,0 +1,33 @@
+import type { BaseLayoutProps } from "fumadocs-ui/layouts/shared";
+import { i18n } from "@/lib/i18n";
+
+export function baseOptions(locale: string): BaseLayoutProps {
+ const titles: Record = {
+ en: "Python Template",
+ zh: "Python 模板",
+ es: "Plantilla Python",
+ ja: "Python テンプレート",
+ };
+
+ const docsLabels: Record = {
+ en: "Documentation",
+ zh: "文档",
+ es: "Documentación",
+ ja: "ドキュメント",
+ };
+
+ return {
+ i18n,
+ nav: {
+ title: titles[locale] ?? titles.en,
+ url: `/${locale}`,
+ },
+ links: [
+ {
+ type: "main",
+ text: docsLabels[locale] ?? docsLabels.en,
+ url: `/${locale}/docs`,
+ },
+ ],
+ };
+}
diff --git a/docs/lib/source.ts b/docs/lib/source.ts
new file mode 100644
index 0000000..401df09
--- /dev/null
+++ b/docs/lib/source.ts
@@ -0,0 +1,29 @@
+import { docs } from "fumadocs-mdx:collections/server";
+import { loader } from "fumadocs-core/source";
+import { i18n } from "@/lib/i18n";
+
+export const source = loader({
+ baseUrl: "/docs",
+ source: docs.toFumadocsSource(),
+ i18n,
+});
+
+export function getPageImage(page: ReturnType & {}) {
+ const allSegments = page.url.split("/").filter(Boolean);
+ // Strip locale and "docs" prefix for the slug param (they're separate route params)
+ const docSegments = allSegments.filter(
+ (s) => s !== page.locale && s !== "docs",
+ );
+ return {
+ url: `/og/${allSegments.join("/")}/og.png`,
+ segments: [...docSegments, "og.png"],
+ };
+}
+
+export async function getLLMText(
+ page: ReturnType & {}
+): Promise {
+ const processed = page.data.processedMarkdown;
+ if (!processed) return "";
+ return `# ${page.data.title}\n\n${page.data.description ?? ""}\n\n${processed}`;
+}
diff --git a/docs/middleware.ts b/docs/middleware.ts
new file mode 100644
index 0000000..ae49673
--- /dev/null
+++ b/docs/middleware.ts
@@ -0,0 +1,8 @@
+import { createI18nMiddleware } from "fumadocs-core/i18n/middleware";
+import { i18n } from "@/lib/i18n";
+
+export default createI18nMiddleware(i18n);
+
+export const config = {
+ matcher: ["/((?!api|_next/static|_next/image|favicon.ico|icon-light.png|icon-dark.png|og/).*)"],
+};
diff --git a/docs/next.config.mjs b/docs/next.config.mjs
index 91c6ac1..2ea4933 100644
--- a/docs/next.config.mjs
+++ b/docs/next.config.mjs
@@ -7,9 +7,13 @@ const config = {
reactStrictMode: true,
async rewrites() {
return [
+ {
+ source: '/:lang/docs/:path*.mdx',
+ destination: '/llms.mdx/:lang/docs/:path*',
+ },
{
source: '/docs/:path*.mdx',
- destination: '/llms.mdx/docs/:path*',
+ destination: '/llms.mdx/en/docs/:path*',
},
];
},