多语言
主题是普通的 VuePress 2 主题,所以 locale 的工作方式和 VuePress 文档描述的一致。值得 专门写清楚的是主题从哪里读,因为 locale 有两个可以声明的地方。
两种 locale
| 层 | 位置 | 控制什么 |
|---|---|---|
| 站点 | VuePress 配置的 locales | lang、title、description,以及哪些页面属于该 locale |
| 主题 | githubTheme({ locales }) | 导航栏、侧边栏、博客路由与所有 UI 文案 |
站点层决定页面解析出的语言,主题层决定外壳用什么渲染。两者使用相同的键(/、/zh/)。
export default defineUserConfig({
locales: {
'/': { lang: 'en-US', title: '我的项目' },
'/zh/': { lang: 'zh-CN', title: '我的项目' },
},
theme: githubTheme({
navbar: [{ text: 'Guide', link: '/guide/' }],
locales: {
'/zh/': {
selectLanguageText: '语言',
navbar: [{ text: '指南', link: '/zh/guide/' }],
sidebar: { '/zh/guide/': ['/zh/guide/README.md'] },
},
},
}),
}) 站点层的键必须存在
主题通过 VuePress 的 locale 映射解析页面所属 locale,所以只有主题里有
/zh/ 条目、 而 VuePress locales['/zh/'] 缺失时,主题会去找一个从未注册过的 locale。文章放在 locale 目录下
blog.postsDir 相对 locale 目录解析,这正是目录结构所暗示的:
docs/
├── posts/ # locale '/' 的 postsDir:'posts'
└── zh/
└── posts/ # locale '/zh/' 使用同一个 postsDir每个 locale 生成自己的博客、自己的标签归档和自己的归档页,并且只列出自己的文章。两个 locale 可以共用标签名而页面不共用:两个 locale 里都写 tags: [guide],会分别产出 /blog/tags/guide/ 与 /zh/blog/tags/guide/,内容各自独立。
按 locale 挪动博客
某个 locale 可以把博客放到别处,这通常也是要覆盖博客选项的原因:
locales: {
'/zh/': {
blog: {
postsPath: '/zh/blog/',
tagsPath: '/zh/blog/tags/',
archivesPath: '/zh/blog/archives/',
},
},
},标签链接、分页链接与归档都会跟随这些路径,包括从该 locale 内渲染的文章页出发。
文案
主题渲染的任何字符串都可以按 locale 覆盖:
| 键 | 默认值 | 用于 |
|---|---|---|
selectLanguageText | Languages | 语言下拉的文案 |
selectLanguageName | English | 没有站点标题的语言条目 |
editLinkText | Edit this page | 页脚 |
lastUpdatedText | Last Updated | 页脚 |
contributorsText | Contributors | 页脚 |
backToTop | Back to top | 返回顶部按钮 |
toggleSidebar | Toggle sidebar | 导航开关 |
toggleColorMode | Toggle color mode | 配色切换按钮 |
sidebarLabel | 站点标题 + navigation | 侧边栏 landmark 的可访问名称 |
tocTitle | On this page | 页内目录标题 |
skipToContent | Skip to content | skip link |
pageNavPrev | Previous | 上一页链接 |
pageNavNext | Next | 下一页链接 |
siteNavLabel | Site navigation | 导航栏 landmark 的可访问名称 |
pageNavLabel | Page navigation | 上一页/下一页 landmark 的可访问名称 |
openRepoLabel | Open {host} repository | 仓库链接的可访问名称,{host} 会被替换为宿主名 |
searchPlaceholder | Search | 搜索框 |
searchEmpty | No results found | 搜索框 |
notFound | 内置 | 404 页面文字 |
paginationLabel | Pagination | 翻页区域的 landmark 名称 |
breadcrumbLabel | Breadcrumb | 博客面包屑的名称 |
codeBlockLabel | Copy code | 代码复制按钮 |
codeBlockCopied | Copied | 复制成功后的按钮文案 |
noDatedPosts | No dated posts yet. | 归档视图没有带日期的文章时的提示 |
archiveMonths | 英文 12 个月 | 归档视图的月份名 |
blog.* | 见博客 | 所有博客视图 |
blog.readingTime | :minutes min read | 日期旁的阅读时间 |
blog.words | :words words | 阅读时间旁的字数;不设则不显示 |
看不见的文案也要本地化
paginationLabel、breadcrumbLabel、codeBlockLabel 只出现在无障碍树里,视力正常的 评审者看不到它们 —— 它们最容易被漏掉。中文站点里读屏用户听到的英文就是从这里来的。归档月份名
archiveMonths 存在的理由是 Intl 只会按页面语言输出月份名。想在中文页面里用英文 月份(或反之)时,覆盖它:
locales: {
'/': { archiveMonths: ['January', 'February', 'March'] }, // 其余按索引补
'/zh/': { archiveMonths: ['一月', '二月', '三月'] },
},数组按 0–11 索引,缺的月份回退到 Intl 输出。
日期跟随文章自己的 lang,而不是列出它的页面语言,所以翻译过的文章在它出现的列表里 保持自己的日期格式。
语言切换器
站点声明了多个 locale 时,导航栏会长出一个语言下拉,条目来自站点 locale 的标题。无需 额外配置。
