跳到正文

多语言

主题是普通的 VuePress 2 主题,所以 locale 的工作方式和 VuePress 文档描述的一致。值得 专门写清楚的是主题从哪里读,因为 locale 有两个可以声明的地方。

两种 locale

层位置控制什么
站点VuePress 配置的 localeslang、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 覆盖:

键默认值用于
selectLanguageTextLanguages语言下拉的文案
selectLanguageNameEnglish没有站点标题的语言条目
editLinkTextEdit this page页脚
lastUpdatedTextLast Updated页脚
contributorsTextContributors页脚
backToTopBack to top返回顶部按钮
toggleSidebarToggle sidebar导航开关
toggleColorModeToggle color mode配色切换按钮
sidebarLabel站点标题 + navigation侧边栏 landmark 的可访问名称
tocTitleOn this page页内目录标题
skipToContentSkip to contentskip link
pageNavPrevPrevious上一页链接
pageNavNextNext下一页链接
siteNavLabelSite navigation导航栏 landmark 的可访问名称
pageNavLabelPage navigation上一页/下一页 landmark 的可访问名称
openRepoLabelOpen {host} repository仓库链接的可访问名称,{host} 会被替换为宿主名
searchPlaceholderSearch搜索框
searchEmptyNo results found搜索框
notFound内置404 页面文字
paginationLabelPagination翻页区域的 landmark 名称
breadcrumbLabelBreadcrumb博客面包屑的名称
codeBlockLabelCopy code代码复制按钮
codeBlockCopiedCopied复制成功后的按钮文案
noDatedPostsNo 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 的标题。无需 额外配置。