跳转到内容

国际化 (i18n)

Starlight 提供了内置的多语言支持,包括路由、回退内容和完整的从右到左(RTL)语言支持。

配置 i18n

  1. 通过将 localesdefaultLocale 传递给 Starlight 集成,告诉 Starlight 你支持的语言:

    astro.config.mjs
    import { defineConfig } from 'astro/config';
    import starlight from '@astrojs/starlight';
    export default defineConfig({
    integrations: [
    starlight({
    title: '我的文档',
    // 为此网站设置英语为默认语言。
    defaultLocale: 'en',
    locales: {
    // 英文文档在 `src/content/docs/en/` 中。
    en: {
    label: 'English',
    },
    // 简体中文文档在 `src/content/docs/zh-cn/` 中。
    'zh-cn': {
    label: '简体中文',
    lang: 'zh-CN',
    },
    // 阿拉伯文档在 `src/content/docs/ar/` 中。
    ar: {
    label: 'العربية',
    dir: 'rtl',
    },
    },
    }),
    ],
    });

    你的 defaultLocale 将用于回退内容和 UI 标签,所以选择你最有可能开始编写内容的语言,或者已经有内容的语言。

  2. src/content/docs/ 中为每种语言创建一个目录。 例如,对于上面显示的配置,创建以下文件夹:

    • 文件夹src/
      • 文件夹content/
        • 文件夹docs/
          • 文件夹ar/
          • 文件夹en/
          • 文件夹zh-cn/
  3. 现在你可以在你的语言目录中添加内容文件。使用相同的文件名来关联跨语言的页面,并利用 Starlight 的完整的 i18n 功能,包括回退内容、翻译通知等。

    举个例子,创建 ar/index.mden/index.md 来分别表示阿拉伯语和英语的主页。

对于更高级的 i18n 场景,Starlight 也支持使用 Astro 的 i18n 配置选项来配置国际化。

使用 root 语言

你可以使用“root”语言来提供没有任何 i18n 前缀的语言。例如,如果英语是你的 root 语言,那么英语页面的路径将是 /about 而不是 /en/about

要设置 root 语言,请在你的 locales 配置中使用 root 键。如果 root 语言也是你的内容的默认语言,请删除 defaultLocale 或将其设置为 'root'

astro.config.mjs
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
export default defineConfig({
integrations: [
starlight({
title: '我的文档',
defaultLocale: 'root', // 可选
locales: {
root: {
label: 'English',
lang: 'en', // lang 是 root 语言必须的
},
'zh-cn': {
label: '简体中文',
lang: 'zh-CN',
},
},
}),
],
});

当使用 root 语言时,将页面直接放在 src/content/docs/ 中,而不是在专用的语言文件夹中。例如,当使用上面的配置时,这里是英语和中文的主页文件:

  • 文件夹src/
    • 文件夹content/
      • 文件夹docs/
        • index.md
        • 文件夹zh-cn/
          • index.md

单语言网站

默认情况下,Starlight 是一个单语言(英语)网站。要在其他语言中创建单语言网站,请将其设置为 locales 配置中的 root

astro.config.mjs
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
export default defineConfig({
integrations: [
starlight({
title: 'My Docs',
locales: {
root: {
label: '简体中文',
lang: 'zh-CN',
},
},
}),
],
});

这允许你在不启用其他多语言网站的国际化功能的情况下,覆盖 Starlight 的默认语言,例如语言选择器。

回退内容

Starlight 期望你在所有语言中创建等效的页面。例如,如果你有一个 en/about.md 文件,请为你支持的每种其他语言创建一个 about.md。这允许 Starlight 为尚未翻译的页面提供自动回退内容。

如果某种语言尚未提供翻译,Starlight 将为读者显示该页面的默认语言(通过 defaultLocale 设置)的内容。例如,如果你尚未创建关于你的法语版本,并且你的默认语言是英语,那么访问 /fr/about 的访问者将看到来自 /en/about 的英语内容,并显示该页面尚未翻译的通知。这有助于你在默认语言中添加内容,然后在翻译人员有时间时逐步翻译它。

翻译网站标题

默认情况下,Starlight 会为所有语言使用相同的站点标题。 如果你需要为每种语言自定义标题,你可以在 Starlight 的选项中将一个对象传递给 title

astro.config.mjs
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
export default defineConfig({
integrations: [
starlight({
title: 'My Docs',
title: {
en: 'My Docs',
'zh-CN': '我的文档',
},
defaultLocale: 'en',
locales: {
en: { label: 'English' },
'zh-cn': { label: '简体中文', lang: 'zh-CN' },
},
}),
],
});

翻译 Starlight 的 UI

除了托管翻译的内容文件之外,Starlight 还允许你翻译默认的 UI 字符串(例如,目录中的“本页”标题),以便你的读者可以完全使用所选的语言体验你的网站。

默认提供了阿拉伯语、波兰语、波斯语、丹麦语、德语、俄语、法语、韩语、荷兰语、加利西亚语、捷克语、罗马尼亚语、葡萄牙语、日语、瑞典语、书面挪威语、斯洛伐克语、土耳其语、乌克兰语、西班牙语、希伯来语、意大利语、印地语、印度尼西亚语、英语、越南语、中文和中文(台湾)的翻译 UI 字符串, 同时我们欢迎贡献添加更多默认语言

你可以通过 i18n 数据集合提供你支持的其他语言的翻译 - 或覆盖我们的默认标签。

  1. 如果尚未配置,请在 src/content/config.ts 中配置 i18n 数据集合:

    src/content/config.ts
    import { defineCollection } from 'astro:content';
    import { docsSchema, i18nSchema } from '@astrojs/starlight/schema';
    export const collections = {
    docs: defineCollection({ schema: docsSchema() }),
    i18n: defineCollection({ type: 'data', schema: i18nSchema() }),
    };
  2. 为你想要提供 UI 翻译字符串的每种其他语言在 src/content/i18n/ 中创建一个 JSON 文件。 例如,这将为阿拉伯语和简体中文添加翻译文件:

    • 文件夹src/
      • 文件夹content/
        • 文件夹i18n/
          • ar.json
          • zh-CN.json
  3. 在 JSON 文件中添加你想要翻译的键的翻译。只翻译值,将键保留为英语(例如 "search.label": "搜索")。

    这些是 Starlight 附带的现有字符串的英文默认值:

    {
    "skipLink.label": "Skip to content",
    "search.label": "Search",
    "search.ctrlKey": "Ctrl",
    "search.cancelLabel": "Cancel",
    "search.devWarning": "Search is only available in production builds. \nTry building and previewing the site to test it out locally.",
    "themeSelect.accessibleLabel": "Select theme",
    "themeSelect.dark": "Dark",
    "themeSelect.light": "Light",
    "themeSelect.auto": "Auto",
    "languageSelect.accessibleLabel": "Select language",
    "menuButton.accessibleLabel": "Menu",
    "sidebarNav.accessibleLabel": "Main",
    "tableOfContents.onThisPage": "On this page",
    "tableOfContents.overview": "Overview",
    "i18n.untranslatedContent": "This content is not available in your language yet.",
    "page.editLink": "Edit page",
    "page.lastUpdated": "Last updated:",
    "page.previousLink": "Previous",
    "page.nextLink": "Next",
    "page.draft": "This content is a draft and will not be included in production builds.",
    "404.text": "Page not found. Check the URL or try using the search bar.",
    "aside.note": "Note",
    "aside.tip": "Tip",
    "aside.caution": "Caution",
    "aside.danger": "Danger",
    "fileTree.directory": "Directory",
    "builtWithStarlight.label": "Built with Starlight"
    }

    Starlight 的代码块使用了 Expressive Code。 你可以在同一个 JSON 文件中使用 expressiveCode 键来设置它的 UI 字符串翻译。

    {
    "expressiveCode.copyButtonCopied": "Copied!",
    "expressiveCode.copyButtonTooltip": "Copy to clipboard",
    "expressiveCode.terminalWindowFallbackTitle": "Terminal window"
    }

    Starlight 的搜索模态框由 Pagefind 库提供支持。 你可以在同一个 JSON 文件中使用 pagefind 键来设置它的 UI 字符串翻译。

    {
    "pagefind.clear_search": "Clear",
    "pagefind.load_more": "Load more results",
    "pagefind.search_label": "Search this site",
    "pagefind.filters_label": "Filters",
    "pagefind.zero_results": "No results for [SEARCH_TERM]",
    "pagefind.many_results": "[COUNT] results for [SEARCH_TERM]",
    "pagefind.one_result": "[COUNT] result for [SEARCH_TERM]",
    "pagefind.alt_search": "No results for [SEARCH_TERM]. Showing results for [DIFFERENT_TERM] instead",
    "pagefind.search_suggestion": "No results for [SEARCH_TERM]. Try one of the following searches:",
    "pagefind.searching": "Searching for [SEARCH_TERM]..."
    }

拓展翻译 schema

通过在 i18nSchema() 选项中设置 extend 可以向你网站的翻译字典中添加自定义键。 在下面的示例中添加了一个新的可选的 custom.label 键:

src/content/config.ts
import { defineCollection, z } from 'astro:content';
import { docsSchema, i18nSchema } from '@astrojs/starlight/schema';
export const collections = {
docs: defineCollection({ schema: docsSchema() }),
i18n: defineCollection({
type: 'data',
schema: i18nSchema({
extend: z.object({
'custom.label': z.string().optional(),
}),
}),
}),
};

在 Astro 文档的“定义集合模式”中了解有关内容集合 schema 的更多信息。

使用 UI 翻译

你可以使用由 i18next 提供支持的统一 API 访问 Starlight 的 内置 UI 字符串 以及 用户定义插件提供 的 UI 字符串。 其中包括了对 插值多元化 等功能的支持。

在 Astro 组件中,此 API 作为 全局 Astro 对象 的一部分提供,即 Astro.locals.t

example.astro
<p dir={Astro.locals.t.dir()}>
{Astro.locals.t('404.text')}
</p>

你还可以在 端点 中使用 API,其中的 locals 对象可作为 端点上下文 的一部分使用:

src/pages/404.ts
export const GET = (context) => {
return new Response(context.locals.t('404.text'));
};

渲染 UI 字符串

使用 locals.t() 函数以渲染 UI 字符串。 这是 i18next 的 t() 函数的一个实例,该函数将 UI 字符串键作为其第一个参数,并返回当前语言的相应翻译。

例如,给定一个包含以下内容的自定义翻译文件:

src/content/i18n/en.json
{
"link.astro": "Astro documentation",
"link.astro.custom": "Astro documentation for {{feature}}"
}

第一个 UI 字符串可以通过将 'link.astro' 传递给 t() 函数来渲染:

src/components/Example.astro
<a href="https://docs.astro.build/">
{Astro.locals.t('link.astro')}
</a>
<!-- 渲染结果:<a href="...">Astro documentation</a> -->

第二个 UI 字符串对 {{feature}} 占位符使用了 i18next 的 插值语法feature 的值在被作为第二个参数传递给 t() 时,必须被设置在一个选项对象中:

src/components/Example.astro
<a href="https://docs.astro.build/en/guides/astro-db/">
{Astro.locals.t('link.astro.custom', { feature: 'Astro DB' })}
</a>
<!-- 渲染结果:<a href="...">Astro documentation for Astro DB</a> -->

有关如何使用 t() 函数进行插值、格式化等更多信息,请参阅 i18next 文档

高级 API

t.all()

locals.t.all() 函数可返回一个对象,返回的对象中包含当前区域设置下所有可用的 UI 字符串。

src/components/Example.astro
---
const allStrings = Astro.locals.t.all();
// ^
// {
// "skipLink.label": "Skip to content",
// "search.label": "Search",
// …
// }
---

t.exists()

要检查某个区域设置是否存在某个翻译键,请使用 locals.t.exists() 函数,并将该翻译键作为第一个参数。 如需覆盖当前的区域设置,请传递第二个可选参数。

src/components/Example.astro
---
const keyExistsInCurrentLocale = Astro.locals.t.exists('a.key');
// ^ true
const keyExistsInFrench = Astro.locals.t.exists('another.key', { lng: 'fr' });
// ^ false
---

有关详细信息,请参阅 i18next 文档中的 exists() 参考

t.dir()

locals.t.dir() 函数可返回当前或特定语言环境的文本方向。

src/components/Example.astro
---
const currentDirection = Astro.locals.t.dir();
// ^
// 'ltr'
const arabicDirection = Astro.locals.t.dir('ar');
// ^
// 'rtl'
---

有关详细信息,请参阅 i18next 文档中的 dir() 参考

访问当前语言环境

你可以使用 Astro.currentLocale.astro 组件中读取当前的语言环境。

下面的示例读取当前语言环境,并使用它和 getRelativeLocaleUrl() 助手函数以生成一个当前语言的关于页面的链接:

src/components/AboutLink.astro
---
import { getRelativeLocaleUrl } from 'astro:i18n';
---
<a href={getRelativeLocaleUrl(Astro.currentLocale ?? 'en', 'about')}>About</a>