Astro 框架原生支持 国际化 特性,可以快速创建多语言版本的网站,但对于内容集合的国际化有一点小问题。根据官方指南的建议,使用 /src/pages/[locale]/blog/[...slug].astro
的方式为内容集合增加多语言支持时,其中 [locale]
部分是必须的,从而使得即使是默认语言的链接也是带语言前缀的。
我希望用户在使用默认语言时,所访问的 URL 中不存在语言前缀。例如,名为 quotes
的数据集合,如果用户使用默认语言 en
时,访问链接应该是 https://tireless.dev/quotes/quote-1
,而不是 https://tireless.dev/en/quotes/quote-1
,后者看起来相当违反直觉。
解决方案是创建两个动态页面模板,分别过滤并展示数据集的默认语言子集,和其它语言子集。
src/pages/quotes/[id].astro
用于默认语言。
---
...
export async function getStaticPaths() {
return (await getCollection("quotes"))
.filter(
(quote) =>
!startsWithLanguages(quote.id) ||
startsWithLanguage(quote.id, defaultLang)
)
.map((quote) => ({
params: { id: stripLangPrefix(quote.id) },
props: { quote },
}));
}
const { quote } = Astro.props;
---
<QuotePage quote={quote} locale={defaultLang} />
src/pages/[locale]/quotes/[id].astro
用于其它语言。
---
...
export async function getStaticPaths() {
return (await getCollection("quotes"))
.filter((quote) => startsWithLanguages(quote.id))
.map((quote) => {
const [lang, ...slug] = quote.id.split("/");
return {
params: { locale: lang as Lang, id: slug.join("/") || undefined },
props: { quote },
};
});
}
const { locale } = Astro.params;
const { quote } = Astro.props;
---
<QuotePage quote={quote} locale={locale} />
数据集合的内容组织,默认语言内容可以放在相应的语言目录,也可以不创建单独目录。
src/conent/quotes
quote-1.md
en
quote-2.md
zh
quote-1.md
quote-2.md
完整的示例代码请参考 样例项目 。