Skip to content

Commit

Permalink
Add Fumadocs example (#48)
Browse files Browse the repository at this point in the history
* add fumadocs example

* fix: error on uncommited content

* re-use existing i18n config

* add app title to translations

* feat: support glob pattern in `include`
  • Loading branch information
fuma-nama authored Jan 1, 2025
1 parent c93669c commit 2259a30
Show file tree
Hide file tree
Showing 29 changed files with 509 additions and 65 deletions.
Binary file modified bun.lockb
Binary file not shown.
14 changes: 7 additions & 7 deletions examples/expo/locales/i18n.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
// For more information on Expo Localization and usage: https://docs.expo.dev/guides/localization
import { getLocales } from 'expo-localization';
import { I18n } from 'i18n-js';
import { getLocales } from "expo-localization";
import { I18n } from "i18n-js";

const translations = {
en: require('./en.json'),
es: require('./es.json')
}
en: require("./en.json"),
es: require("./es.json"),
};

const i18n = new I18n(translations);

i18n.locale = getLocales().at(0)?.languageCode ?? 'en';
i18n.locale = getLocales().at(0)?.languageCode ?? "en";

i18n.enableFallback = true;

export default i18n;
export default i18n;
28 changes: 28 additions & 0 deletions examples/fumadocs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# deps
/node_modules

# generated content
.contentlayer
.content-collections
.source

# test & build
/coverage
/.next/
/out/
/build
*.tsbuildinfo

# misc
.DS_Store
*.pem
/.pnp
.pnp.js
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# others
.env*.local
.vercel
next-env.d.ts
46 changes: 46 additions & 0 deletions examples/fumadocs/app/[lang]/[[...slug]]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { source } from "@/lib/source";
import {
DocsPage,
DocsBody,
DocsDescription,
DocsTitle,
} from "fumadocs-ui/page";
import { notFound } from "next/navigation";
import defaultMdxComponents from "fumadocs-ui/mdx";

export default async function Page(props: {
params: Promise<{ lang: string; slug?: string[] }>;
}) {
const params = await props.params;
const page = source.getPage(params.slug, params.lang);
if (!page) notFound();

const MDX = page.data.body;

return (
<DocsPage toc={page.data.toc} full={page.data.full}>
<DocsTitle>{page.data.title}</DocsTitle>
<DocsDescription>{page.data.description}</DocsDescription>
<DocsBody>
<MDX components={{ ...(defaultMdxComponents as any) }} />
</DocsBody>
</DocsPage>
);
}

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

export async function generateMetadata(props: {
params: Promise<{ lang: string; slug?: string[] }>;
}) {
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,
};
}
54 changes: 54 additions & 0 deletions examples/fumadocs/app/[lang]/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { RootProvider } from "fumadocs-ui/provider";
import "fumadocs-ui/style.css";
import { Inter } from "next/font/google";
import type { ReactNode } from "react";
import { I18nProvider } from "fumadocs-ui/i18n";
import { baseOptions } from "../layout.config";
import { DocsLayout } from "fumadocs-ui/layouts/docs";
import { source } from "@/lib/source";
import { i18n } from "@/lib/i18n";
import { notFound } from "next/navigation";

const inter = Inter({
subsets: ["latin"],
});

export default async function Layout({
params,
children,
}: { params: Promise<{ lang: string }>; children: ReactNode }) {
const lang = (await params).lang as "en" | "cn";
if (!i18n.languages.includes(lang)) notFound();

return (
<html lang={lang} className={inter.className} suppressHydrationWarning>
<body
style={{
display: "flex",
flexDirection: "column",
minHeight: "100vh",
}}
>
<I18nProvider
locale={lang}
locales={[
{ locale: "en", name: "English" },
{ locale: "cn", name: "Chinese" },
]}
translations={
{
en: (await import("@/content/ui.json")).default,
cn: (await import("@/content/ui.cn.json")).default,
}[lang]
}
>
<RootProvider>
<DocsLayout tree={source.pageTree[lang]} {...baseOptions(lang)}>
{children}
</DocsLayout>
</RootProvider>
</I18nProvider>
</body>
</html>
);
}
4 changes: 4 additions & 0 deletions examples/fumadocs/app/api/search/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { source } from "@/lib/source";
import { createFromSource } from "fumadocs-core/search/server";

export const { GET } = createFromSource(source);
15 changes: 15 additions & 0 deletions examples/fumadocs/app/layout.config.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { BaseLayoutProps } from "fumadocs-ui/layouts/shared";

const translations = {
en: (await import("@/content/app.json")).default,
cn: (await import("@/content/app.cn.json")).default,
} as const;

export const baseOptions = (locale: "en" | "cn") => {
return {
nav: {
title: translations[locale].title,
},
i18n: true,
} satisfies BaseLayoutProps;
};
3 changes: 3 additions & 0 deletions examples/fumadocs/content/app.cn.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"title": "我的应用"
}
3 changes: 3 additions & 0 deletions examples/fumadocs/content/app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"title": "My App"
}
13 changes: 13 additions & 0 deletions examples/fumadocs/content/docs/index.cn.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
title: 你好,世界
description: 您的第一篇文档
---

欢迎来到文档!您可以在 `/content/docs` 中开始撰写文档。

## 接下来是什么?

<Cards>
<Card title="了解更多关于 Next.js 的信息" href="https://nextjs.org/docs" />
<Card title="了解更多关于 Fumadocs 的信息" href="https://fumadocs.vercel.app" />
</Cards>
13 changes: 13 additions & 0 deletions examples/fumadocs/content/docs/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
title: Hello World
description: Your first document
---

Welcome to the docs! You can start writing documents in `/content/docs`.

## What is Next?

<Cards>
<Card title="Learn more about Next.js" href="https://nextjs.org/docs" />
<Card title="Learn more about Fumadocs" href="https://fumadocs.vercel.app" />
</Cards>
17 changes: 17 additions & 0 deletions examples/fumadocs/content/docs/test.cn.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
title: 组件
description: 组件
---

## 代码块

```js
console.log('你好,世界');
```

## 卡片

<Cards>
<Card title="了解更多关于 Next.js 的信息" href="https://nextjs.org/docs" />
<Card title="了解更多关于 Fumadocs 的信息" href="https://fumadocs.vercel.app" />
</Cards>
17 changes: 17 additions & 0 deletions examples/fumadocs/content/docs/test.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
title: Components
description: Components
---

## Code Block

```js
console.log('Hello World');
```

## Cards

<Cards>
<Card title="Learn more about Next.js" href="https://nextjs.org/docs" />
<Card title="Learn more about Fumadocs" href="https://fumadocs.vercel.app" />
</Cards>
12 changes: 12 additions & 0 deletions examples/fumadocs/content/ui.cn.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"search": "搜索",
"searchNoResult": "未找到结果",
"toc": "本页内容",
"tocNoHeadings": "没有标题",
"lastUpdate": "最后更新于",
"chooseLanguage": "选择语言",
"nextPage": "下一页",
"previousPage": "上一页",
"chooseTheme": "主题",
"editOnGithub": "在 GitHub 上编辑"
}
12 changes: 12 additions & 0 deletions examples/fumadocs/content/ui.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"search": "Search",
"searchNoResult": "No results found",
"toc": "On this page",
"tocNoHeadings": "No Headings",
"lastUpdate": "Last updated on",
"chooseLanguage": "Choose a language",
"nextPage": "Next",
"previousPage": "Previous",
"chooseTheme": "Theme",
"editOnGithub": "Edit on GitHub"
}
52 changes: 52 additions & 0 deletions examples/fumadocs/languine.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { defineConfig } from "languine";
import { writeFile } from "node:fs/promises";
import path from "node:path";
import { defaultTranslations } from "fumadocs-ui/i18n";
import { i18n } from "./lib/i18n";

// translate Fumadocs' UI content
await writeFile(
"content/ui.json",
JSON.stringify(defaultTranslations, null, 2),
);

export default defineConfig({
llm: {
provider: "openai",
model: "gpt-4-turbo",
temperature: 0,
},
version: "1.0.0",
locale: {
source: i18n.defaultLanguage,
targets: i18n.languages.filter((v) => v !== i18n.defaultLanguage),
},
files: {
json: {
include: [
{
from: "content/ui.json",
to: "content/ui.[locale].json",
},
{
from: "content/app.json",
to: "content/app.[locale].json",
},
],
},
md: {
include: [
{
glob: "content/docs/**/*.mdx",
to: (file, locale) => {
const { dir, name, ext } = path.parse(file);

return path.join(dir, `${name}.${locale}${ext}`);
},
},
],
// ignore translated content
filter: (file) => path.basename(file).split(".").length === 2,
},
},
});
6 changes: 6 additions & 0 deletions examples/fumadocs/lib/i18n.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import type { I18nConfig } from "fumadocs-core/i18n";

export const i18n: I18nConfig = {
defaultLanguage: "en",
languages: ["en", "cn"],
};
10 changes: 10 additions & 0 deletions examples/fumadocs/lib/source.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { docs, meta } from "@/.source";
import { createMDXSource } from "fumadocs-mdx";
import { loader } from "fumadocs-core/source";
import { i18n } from "./i18n";

export const source = loader({
baseUrl: "/",
source: createMDXSource(docs, meta),
i18n: i18n,
});
9 changes: 9 additions & 0 deletions examples/fumadocs/middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { createI18nMiddleware } from "fumadocs-core/i18n";
import { i18n } from "./lib/i18n";

export default createI18nMiddleware(i18n);

export const config = {
// Matcher ignoring `/_next/` and `/api/`
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
};
10 changes: 10 additions & 0 deletions examples/fumadocs/next.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { createMDX } from "fumadocs-mdx/next";

const withMDX = createMDX();

/** @type {import('next').NextConfig} */
const config = {
reactStrictMode: true,
};

export default withMDX(config);
Loading

0 comments on commit 2259a30

Please sign in to comment.