minidocs

多语言

在 Astro 配置里设置 i18n,minidocs 就会按语言组织内容,为每种语言生成页面。这一页讲多语言站点和单语言站点的不同之处。

配置

// astro.config.mjs
export default defineConfig({
  i18n: { locales: ['zh', 'en'], defaultLocale: 'zh' },
  integrations: [mdx(), minidocs()],
});

默认语言的地址不带语言段,比如 /docs/;其他语言带,比如 /en/docs/。想让默认语言也带上,设置 Astro 的 routing: { prefixDefaultLocale: true }。

locales 只支持字符串,routing: 'manual' 也还不支持。没有翻译的页面怎么显示,用下文 minidocs 的 fallback 声明,不要用 Astro 的 i18n.fallback。

内容

集合的第一级目录是语言:

src/content/docs/
├── zh/
│   ├── index.mdx
│   └── guides/sidebar.mdx
└── en/
    ├── index.mdx
    └── guides/sidebar.mdx

页面 id 不含语言,两种语言里的 guides/sidebar.mdx 是同一个页面 guides/sidebar 的两个版本。

路由和数据

和单语言站点相比,有三处不同:

  • 路由文件前面多一层 [...locale],比如 src/pages/[...locale]/docs/[...slug].astro,page.params 里多了 locale
  • defineTree 返回每种语言一棵树,渲染时用 tree[locale]
  • toHref 要传语言:toHref('docs', 'guides/sidebar', locale)

listPages 返回的每个页面都带着 locale,就是它所在的语言,布局里直接用:

---
const { id, locale } = Astro.props;
const nav = navState(tree[locale], id);
---

<html lang={locale}>

没有翻译的页面

页面还没有翻译时,可以先显示另一种语言的内容:

minidocs({ fallback: { en: 'zh' } })

这样英文站上缺的页面会显示中文内容,地址仍然在英文站下,页头、侧边栏这些界面也还是英文。可以依次列出几种语言,按顺序找:{ 'zh-tw': ['zh', 'en'] }。

显示的是另一种语言的内容时,页面的 isFallback 是 true,contentLocale 是内容实际的语言。可以借此提示读者,并让搜索引擎指向原文:

---
const { id, isFallback, contentLocale } = Astro.props;
---

{isFallback && <link rel="canonical" href={toHref('docs', id, contentLocale)} />}
{isFallback && (
  <Callout.Root>
    This page is not translated yet. <a href={toHref('docs', id, contentLocale)}>View the original</a>
  </Callout.Root>
)}

没有声明 fallback 时,缺翻译的页面在那种语言里就不存在。dir() 会跳过它;page() 引用它时,构建会报错。

语言切换器

每个页面的 alternates 列出它存在的所有语言和对应的地址,包括当前语言:

---
const { locale, alternates } = Astro.props;
---

<nav aria-label="Language">
  {alternates.map((alt) => (
    <a href={alt.href} hreflang={alt.locale} aria-current={alt.locale === locale ? 'true' : undefined}>
      {alt.locale}
    </a>
  ))}
</nav>

同样的数据也可以写进 <head>:<link rel="alternate" hreflang={alt.locale} href={alt.href} />。

站点自己的页面

首页这类不来自集合的页面,也放在 [...locale] 下面,用 toLocaleParam 为每种语言生成一份:

---
// src/pages/[...locale]/index.astro
import { type Locale, toLocaleParam } from '@minidocs/astro/runtime';

const locales: Locale[] = ['zh', 'en'];

export function getStaticPaths() {
  return locales.map((locale) => ({ params: { locale: toLocaleParam(locale) }, props: { locale } }));
}
---

默认语言不带语言段时,toLocaleParam 返回 undefined,生成的就是 /。

404 页面放在 src/pages/404.astro,不放在 [...locale] 下面,因为托管平台通常只认站点根目录的 404.html。

正文里的链接

正文里链接到同一个语言目录里的文件,链接就留在这种语言里,没有翻译的页面也是如此,见正文里的链接。

本页目录
搜索范围
输入关键词开始搜索