跳转到内容

国际化 (i18n)

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

  1. 通过向 Starlight 集成传递 localesdefaultLocale 来告诉 Starlight 你支持的语言

    astro.config.mjs
    import { defineConfig } from 'astro/config';
    import starlight from '@astrojs/starlight';
    export default defineConfig({
    integrations: [
    starlight({
    title: 'My Docs',
    // Set English as the default language for this site.
    defaultLocale: 'en',
    locales: {
    // English docs in `src/content/docs/en/`
    en: {
    label: 'English',
    },
    // Simplified Chinese docs in `src/content/docs/zh-cn/`
    'zh-cn': {
    label: '简体中文',
    lang: 'zh-CN',
    },
    // Arabic docs in `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 配置选项来配置国际化。

你可以使用“根”语言区域来提供一种语言,而其路径中没有任何 i18n 前缀。例如,如果英语是你的根语言区域,一个英语页面的路径将是 /about 而不是 /en/about

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

astro.config.mjs
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
export default defineConfig({
integrations: [
starlight({
title: 'My Docs',
defaultLocale: 'root', // optional
locales: {
root: {
label: 'English',
lang: 'en', // lang is required for root locales
},
'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 字符串(例如,目录中的“本页内容”标题),以便你的读者可以完全以所选语言体验你的网站。

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

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

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

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

    • 目录src/
      • 目录content/
        • 目录i18n/
          • ar.json
          • zh-CN.json
  3. 将你要翻译的键的译文添加到 JSON 文件中。只翻译值,键保持英文(例如 "search.label": "Buscar")。

    以下是 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",
    "heading.anchorLabel": "Section titled “{{title}}”"
    }

    Starlight 的代码块由 Expressive Code 库提供支持。你可以使用 expressiveCode 键在同一个 JSON 文件中为其 UI 字符串设置翻译

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

    Starlight 的搜索模态框由 Pagefind 库提供支持。你可以使用 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]..."
    }

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

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

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

你可以通过一个由 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'));
};

在 Starlight 插件的上下文中,你可以使用 useTranslations() 辅助函数来访问特定语言的此 API。更多信息请参见插件参考

使用 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.js.cn/">
{Astro.locals.t('link.astro')}
</a>
<!-- Renders: <a href="...">Astro documentation</a> -->

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

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

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

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

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

要检查翻译键是否存在,请使用 locals.t.exists() 函数,并将翻译键作为第一个参数。如果你需要检查特定语言区域是否存在翻译,可以传递一个可选的第二个参数。

src/components/Example.astro
---
const keyExists = Astro.locals.t.exists('a.key');
// ^ true
const keyExistsInFrench = Astro.locals.t.exists('other.key', { lngs: ['fr'] });
// ^ false
---

更多信息请参阅 exists() 参考在 i18next 文档中

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

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

更多信息请参阅 dir() 参考在 i18next 文档中

你可以在 .astro 组件中使用 Astro.currentLocale 来读取当前语言区域。

以下示例读取当前语言区域,并使用 getRelativeLocaleUrl() 辅助函数生成一个链接到当前语言的关于页面

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