1 - 配置
OINK 遵循“原生优先”的配置模型。站点身份、语言、菜单、输出、taxonomy、标记与模块继续放在 Hugo 规定的位置;语义仍然适用的 Docsy 参数也保持原位。只有无法可靠推导的行为选择,OINK 才会增加职责明确的配置。
配置原则
- 优先使用 Hugo 配置,不创建主题专用的重复项。
- 优先使用成熟的 Docsy 参数,不另造 OINK 同义词。
- 品牌、内容、仓库与 UI 选项应放在各自语义位置。
- 内部 vendor 路径与模板组装方式不属于公开 API。
- 遇到非法值或缺少必需端点时,应尽早失败。
OINK 不提供 oink.enabled 开关,也不建立 params.oink.*
配置树。增加这些配置会制造第二套主题模式,让每项修复、测试和文档都产生歧义。
完整基线配置
以下示例把英文设为首要语言、简体中文设为第二语言:
模块版本固定在站点的 go.mod 中。使用传统主题 checkout 时,可以把仓库放在
themes/oink/,并改用 theme: oink。
语言
defaultContentLanguage 决定不带路径前缀的首要站点;语言 weight
控制显示顺序;label 是该语言的自称;locale 提供完整的 HTML 与 SEO
locale。对于 RTL 语言,还应设置 languageDirection: rtl。
文件命名
本站使用并置模型:
基本名称相同的文件互为译文,其逻辑页面身份应保持一致。OINK 读取 Hugo 建立的翻译关系,不会根据任意 URL 模式猜测。
选择器状态
语言选择器不需要模式参数。只配置一种语言时隐藏;配置两种或更多语言时,点击语言图标会按
weight 顺序切换到下一种语言,悬停半秒或聚焦图标则打开完整菜单。
当前页面缺少目标译文时,会进入目标语言首页。不要为了让选择器停留在同一路径而生成貌似存在、实际失效的页面 URL。
品牌与代码仓库
请设置站点与各语言的 title 和描述。params.logo 可以指向 Hugo
Asset,也可以指向 static/
下的路径。favicon 与社交分享图应放在文档指定的资源位置。
仓库元数据用于生成“编辑此页”、问题反馈和最后修改记录链接:
在支持的位置,github_project_repo 默认回退到 github_repo。github_subdir
是内容站在 monorepo 中的路径。github_branch
必须能够解析;用于展示的版本号不一定是 Git ref。
如果希望导航栏、侧边栏抽屉与页脚使用横向品牌图,请设置
params.wordmark。它接受与 params.logo 相同的 Hugo Asset 或 static/
路径。紧凑状态的导航栏会自动回退到
params.logo,因为横向品牌图会占满整行;完全没有设置 wordmark
时,OINK 保留原有的“图标 + 标题”样式:
导航与布局
OINK 沿用 Docsy 菜单与 UI 参数,并增加职责明确的外壳控制项:
navbar_enabled 与 footer_style
决定每个页面是否带站点导航栏、以及使用哪种页脚形态。两者默认开启(分别为 true
与 fat),作用于所有布局,可以通过 cascade 按分区覆盖,也可以在页面 front
matter 中覆盖;footer_style
取值无法识别时构建会失败。详见导航与菜单与站点页脚。
navbar_accordion_single_open已废弃。现在没有独立的移动菜单可供折叠——小于 lg
时导航栏把所有条目保留为图标。
page_width 接受 normal、wide 或 full,也可以在页面 front
matter 中覆盖。侧栏最小与最大值以像素为单位,用来限制桌面端拖动调整的范围。sidebar_item_overflow: wrap
会让长标签换行;其他值保持紧凑的省略号行为。
quick_links 指定外壳中显示的顶层 page
reference。请在各语言主菜单中定义相应的本地化名称。taxonomy_icons
按分类复数名设置右栏分组图标,默认 categories 用文件夹、tags
用标签,其余分类使用通用形状图标。
页面操作是面包屑行中的拆分按钮:左半边复制本页 Markdown,菜单则在所有视口宽度下保证「复制 Markdown 文本」、助手入口、「查阅 Markdown 源码」「查阅编辑历史」「编辑本页」「创建子页面」、文档与项目 issue,以及「打印整个分区」都可访问。内置 ChatGPT 和 Claude 助手入口默认关闭;设置
assistant_links: true
后才会在有源文件的页面上显示。读者激活入口时,完整的当前 URL(包括 query
string 与 fragment)会随本地化提示词离开本站;OINK 不会上传页面正文。请勿在 URL 中放置秘密信息,并披露这一第三方边界。页面可用布尔型
assistant_links front matter 覆盖站点策略。
当 github_repo
能解析“编辑此页面”使用的同一仓库路径时,才会显示“查阅编辑历史”。links
默认为空,额外的自定义链接可使用经过 URL 编码的 {url}、{title} 与
{markdown_url} 占位符:
首页数据
首页内容位于
data/home/<language>.yaml;缺少相应语言数据时回退到英文。每个语言文件包含具名数据块,以及一个可选的
sections
列表;该列表会按照准确顺序把数据块组合成首页。页脚已不再属于这份文件——它现在渲染在所有布局上,数据读取自
data/footer/<language>.yaml。详见站点页脚。
组合首页分区
字符串条目会同时把该值用作分区类型与数据键。映射条目可以选择内置
type,读取另一个具名 key,设置稳定 id,或临时设置 enabled: false:
映射条目也可以通过 data
直接携带内容,适合短小且只使用一次的区块。两个分区需要相同呈现时,可以用不同的键重用内置类型。站点自有布局还可以指定
partial,但这属于自定义模板契约,而不是可移植的首页数据。
如果没有 sections,OINK 会保留 0.1.x 的顺序,从
hero、metrics、capabilities、principles 与 cta
中按存在情况进行渲染。添加 sections
表示显式组合;此后即使文件中仍有某个数据块,只要列表没有引用,它就不会出现在首页。
内置分区
OINK 0.4.0 提供 21 种分区类型:
| 类型 | 适用内容 |
|---|---|
hero |
核心信息、操作按钮与跟随主题的图片 |
metrics |
紧凑的事实、数字、链接与辅助文字 |
capabilities |
交替的功能叙事与专用视觉面板 |
principles |
带编号的产品原则或工作原则 |
cards |
通用功能、价值、服务或路径集合 |
logo-wall |
工具、集成、合作伙伴或项目渊源 |
gallery |
带徽标与操作的截图或图标示例 |
testimonials |
带可选署名与来源链接的引语 |
contributors |
人员、角色、头像与个人页链接 |
faq |
使用原生展开控件与 Markdown 答案的问答 |
markdown |
没有合适集合布局时使用的自由文字 |
cta |
最后一个操作,或一组紧凑操作 |
pricing |
产品层级、价格、功能与操作按钮 |
pricing-compare |
不同价格层级之间的功能对比矩阵 |
command-box |
带复制操作与可选说明的聚焦命令 |
steps |
带可选命令示例的有序步骤 |
timeline |
带日期的里程碑、路线图与发布历史 |
code-plate |
展示面板中的静态代码或逐行内容 |
case-study |
带指标、引语和来源的证据型案例 |
download |
经过验证的滚动与固定版本下载渠道 |
bar-chart |
无需图表 JS 的非负数值比较 |
首页与普通 layout: landing
页面使用同一套注册表。数据解析、9 种场景型分区契约、无 JavaScript 行为与输出规则见
Landing 页面。
通用集合区块接受 eyebrow、title、desc 或 text、 columns 与
items。条目字段随呈现方式而异,但统一使用 title 或 name、desc 或
text、icon、image、url 与
external。普通文字字段会渲染 Markdown。站内 URL 应相对于当前语言根路径;应作为外部导航打开的链接设置
external: true。
Hero 图片
每个区块都可以省略,因此无需复制布局也能得到更精简的首页。例如:
可选的 hero.image 会在 Hero 右侧添加一幅跟随颜色主题的图片。将 light 与
dark 指向站点 static/ 目录下的文件,图片会随主题选择器切换。只配置
src、light 或 dark
中的一项时,OINK 会在两种主题下复用该图;也可以直接用字符串配置通用图片。省略
image 则保持纯文字 Hero。
首页各分区之下,每个页面都以同一个站点页脚收尾:footer_style 为 fat
时先渲染多列网格,然后是 bottom bar。左侧保留 Docsy 的 params.copyright
API:可以使用 Markdown 字符串,也可以使用包含 authors、from_year、to_year
的 Map;未设置时原样渲染 Hugo 顶层的 copyright。OINK 的
params.footer_center_info 接受行内 Markdown,默认显示
Powered by Oink,显式设为空字符串可隐藏中间区域。右侧保留语言控件。
仍在 data/home/<language>.yaml 中保留 footer
块的站点照常读取该数据。这份数据现在供给所有页面的页脚,而不只是首页。方便时请迁移到
data/footer/<language>.yaml。
可导航的功能面板
价值主张区块可以把组件面板变成紧凑导航。为每个可导航项目添加 url,用
aria_label
命名导航区域,并配置一至四列。没有 URL 的项目仍是装饰卡片,因此既有面板会保持原有行为:
搜索
项目站默认启用本地搜索:
offlineSearchIndex
控制每种语言索引中可下载的文本范围,四档范围逐级累加:title
索引标题与分类元数据;heading 增加页面标题;summary
增加描述或摘要;content 再加入完整正文。content
是兼容旧行为的默认值,而多数文档站可从体积更小的 summary
开始。offlineSearchMaxResults 同时约束 Lunr 与 CJK 子串兜底结果数。
每种语言都会得到独立索引。通过 Docsy 既有配置仍可使用托管搜索,但启用它们会显式增加外部服务边界。除非已经决定界面应显示哪一种,否则不要同时配置多个相互竞争的搜索提供方。
内容运行时
纯浏览器运行时
Mermaid 与 KaTeX 会根据内容自动检测;Markmap 需要在站点级启用:
Swagger UI、Redoc、Asciinema、ECharts、Infographic 与轮播资源会在相应短代码出现时加载。它们的本地运行时路径属于内部实现,不应配置。
服务端点
PlantUML 与 Diagrams.net 需要显式端点:
网络隔离站点应保持这些功能关闭,除非上述 URL 可以在隔离网络内部访问。
页面级覆盖
Hugo 的 .Param 查找机制允许在 front matter 中覆盖许多站点参数:
navbar_enabled 与 footer_style 直接从 front matter 顶层读取,不在 ui
块内,因此分区可以在自己的 cascade 中一次性设定。
只应为真实的内容差异使用覆盖,不要靠逐页设置重建另一套视觉系统。
避免虚假配置
不要暴露:
- 在“Docsy”与“OINK”外壳之间切换的开关;
- vendor JavaScript、CSS、字体或内部 partial 的路径;
- 品牌命名空间下重复的语言或仓库值;
- 只用于二选一复制实现的开关。
如果站点需要定制产品矩阵或门户,请把该组件留在站点,并使用范围明确的 hook 或短代码。清晰的本地业务功能,优于误导性的全局主题选项。
验证配置变更
修改配置后:
- 分别使用最低支持版本与当前验证版本的 Hugo Extended 构建;
- 测试每种已配置语言,以及至少一个缺少译文的页面;
- 如果同时支持根路径与子路径部署,验证两种
baseURL输出; - 检查本地搜索与可选运行时请求;
- 检查桌面端和移动端外壳、深浅色主题与打印输出。
真正可接受的配置必须能够正确构建并按预期运行,而不只是可以被 YAML 解析。
2 - 导航与菜单
OINK 把 Hugo 的内容树和菜单模型组织成一套文档工作台:出现在所有布局上的站点导航栏、可折叠且可调整宽度的分区侧边栏、位于右栏的可折叠页面大纲,以及站点页脚。同一套结构适用于英文、中文和从右向左书写的语言。
站点导航栏
导航栏由 Hugo 的 main
菜单与 OINK 自动生成的控件组成:版本选择器、语言选择器、颜色模式控件、搜索,以及项目仓库链接。它会在所有布局上渲染——落地页、文档、博客、Swagger 和分类页面都不例外,因此站点级导航在任何位置都只有一次点击的距离。
关闭导航栏
navbar_enabled 默认为 true。可以对整个站点关闭导航栏,也可以通过 front
matter(前置元数据)cascade 对某个分区关闭,或只对单个页面关闭:
Front matter 的优先级高于站点参数,而且显式写出的 false
在任何层级都会生效。关闭导航栏后,OINK 会恢复此前被导航栏取代的界面:移动端子导航、侧边栏的品牌与搜索行、目录轨道上的工具按钮,以及侧边栏底部的工具区。这个开关适用于必须独占整个视口的页面,不应当作常规排版偏好使用。
两种状态,没有独立的移动菜单
导航栏只有两种状态:
| 宽度 | 状态 |
|---|---|
lg 及以上 |
完整:品牌、菜单文字标签与各个工具控件 |
小于 lg |
紧凑:先是 Logo,其余条目全部右对齐为图标 |
紧凑状态并不是精简过的菜单。菜单项保留各自的图标,搜索仍是放大镜,版本、语言与主题控件也停在原处——没有任何东西会折叠进汉堡按钮,因为根本不存在独立的移动菜单。唯一按宽度切换的控件出现在带侧边栏的页面上:小于
md 时会多出一个图标,用于打开侧边栏抽屉。
navbar_accordion_single_open已废弃。该参数会被忽略,请从现有配置中删除。
添加 main 菜单项
可以在页面 Front Matter 中定义菜单项:
权重越小,位置越靠前。站点级外部链接写法类似:
需要在配置中引用菜单项时,应为其设置 identifier。name 或 linkTitle
可以按语言翻译,但标识符必须稳定。
嵌套下拉菜单
顶层菜单支持一级下拉。用 Hugo 的 parent 建立父子关系:
子项的 params.description 会显示在下拉项的标题下方,帮助读者判断该去哪。
交互上有一个关键设计:父级本身就是一个普通链接。悬停或键盘聚焦时展开面板,点击或按 Enter 则直接跳转到父级页面。这里没有单独的展开箭头,父级页面也不会被自己的下拉「劫持」。Esc 关闭面板并把焦点留在链接上;触屏读者会直接进入父级页面,那里的正文同样列出了这些链接。
版本菜单
配置 params.versions
后会显示版本选择器。它是一个分支图标,悬停或键盘聚焦时展开列表,与语言、主题控件共用同一套浮层样式。条目可以表示标题、分隔线、正式版本、开发版本或站点变体:
version
标识已发布的站点变体,不一定是 Git 引用。安装命令等必须使用可解析标签的内容,应改用项目显式定义的发布引用参数。启用页面链接后,OINK 会先尝试目标版本中的同一路径,找不到时再使用条目配置的 URL。
语言菜单
OINK 根据 Hugo 的 AllTranslations
构造语言目标。当前页面缺少某种语言译文时,会链接到该语言首页,而不是生成损坏的 URL。只配置一种语言时不显示控件;配置两种或更多语言时,点击语言图标会按
weight
顺序切换到下一种语言,悬停半秒或聚焦控件则打开完整菜单。当前站点按英文、简体中文的顺序循环。目标链接包含
lang、hreflang、locale 与文字方向属性。
浅色/深色主题菜单
启用颜色模式后,导航栏会显示主题控件。点击它在浅色与深色之间切换,悬停或聚焦则展开「跟随系统 / 浅色 / 深色」三项选择器,其中「跟随系统」采用读者操作系统的设置。详见浅色/深色模式菜单。
搜索框
搜索是导航栏上的一个放大镜图标,点击后打开命令面板;Cmd/Ctrl-K
以及在可编辑控件之外按下的 /
同样可以打开它。启用离线搜索后该图标才会出现;关闭导航栏时,搜索行会回到侧边栏顶部。在线搜索集成仍可通过显式配置启用。详见搜索。
为导航栏添加图标
在菜单项中使用 pre 或 post。OINK 已在本地提供免费版 Font Awesome 资源:
装饰性图标需要设置
aria-hidden="true";链接本身必须保留有意义的文字或无障碍标签。在新标签页打开的外部链接必须使用
rel="noopener"。
小于 lg 时,图标就是菜单项仅剩的表现形式,因此每个顶层菜单项都应配置 pre
图标。没有图标的菜单项在紧凑状态下无内容可显示。
侧边导航
文档页与博客页的左侧面板由内容层级自动生成。OINK 按 weight 排序,并在存在
linkTitle 时用它作为标签。分区来自 _index.md;翻译后的分区需要配套
_index.zh.md,才能正确本地化导航元数据。
从侧边栏隐藏页面:
从分区落地页摘要中隐藏页面则使用
hide_summary: true。只有页面确实不应出现在这两个发现入口中时,才同时设置二者。
侧边导航选项
常用控制项如下:
sidebar_menu_compact只显示当前分支和附近条目;sidebar_menu_foldable允许读者展开或折叠分区。博客栏目默认展开,在栏目 front matter 中设置sidebar_expanded: false可让它默认收起;sidebar_menu_truncate限制条目数,数值过小时会发出构建警告;sidebar_cache_limit在站点规模超过阈值后启用共享导航标记;sidebar_width_min与sidebar_width_max限制桌面端拖拽调整的宽度;sidebar_item_overflow默认为ellipsis,长标签需要换行时改用wrap。
折叠状态、宽度和滚动位置保存在读者本地。移动端会转换为带遮罩层和安全焦点控件的可关闭抽屉。
为侧边导航添加图标
在页面 Front Matter 中设置 icon:
同级条目的图标用法应保持一致。图标只是辅助线索,不能取代文字标签。
侧栏图标密度
叶子页面全都带图标会产生明显的视觉噪声。用 sidebar_icon_policy 控制密度:
| 取值 | 效果 |
|---|---|
all |
每个有图标的侧栏条目都显示 |
groups |
只有根节点和带子页的节点显示图标,普通叶子页不显示 |
none |
侧栏完全不显示条目图标 |
未设置时的兼容默认值是 all。新站点建议显式设为
groups——保留了分组的语义标识,同时去掉叶子层的噪声。本站就用这个设置。
无效取值会产生警告并回退到 all。
为侧边导航添加手动链接
在所需位置创建占位页面:
内部内容引用应使用 manualLinkRelref 而不是
manualLink;Hugo 无法解析目标时会令构建失败。OINK 会为新标签页链接补充
noopener。由于 Hugo 仍会为占位文件生成页面,正文应简短说明实际去向。
将分区设为侧边栏根节点
侧边栏树以读者当前所在的顶层分区为根,树上方那一行标出的就是这个根节点。规模较大的子树——带版本的 API 参考、独立的手册——可以自己成为一个根节点,让读者不必离开当前分区就能切换过去:
然后在后代分区的 _index.md 中设置:
self 会把该根节点应用于分区索引及其后代;children
会把索引留在父级树中,只限制其后代。根分区可以嵌套,但冗余或无效取值会触发构建警告。
切换器的范围限定在当前顶层分区之内:条目是该分区本身(默认项),加上每个设置了
sidebar_root_for: self
的后代分区。同级的其他顶层分区不会列出——在文档与博客之间跳转是导航栏的职责。因此,没有可切换后代的分区根本不显示下拉框,那一行只是一个指向分区落地页的普通链接,没有边框,与树的顶层条目对齐。
分类术语页没有内容层级,因此术语会采用其成员共同所属的顶层分区。从文档页面点进某个标签后,侧边栏保留的仍是文档树和文档根链接,而不会回退到站点级的树;成员横跨多个分区的术语则不显示根节点行。
页面目录
Hugo 根据 Markdown 标题生成右侧页面大纲。OINK 把它渲染为固定右栏中的第一个分组,后面依次排列当前分区的分类标签云。读者可以折叠整个右栏,状态保存在本地。
由 Markdown 短代码({{%/* ... */%}})输出的标题会进入 Hugo 目录;仅由标准短代码({{</* ... */>}})输出的标题通常不会进入。因此,只要条件允许,内容结构都应保留在 Markdown 中。
目录定制
在单个页面隐藏大纲:
配置 Hugo 收录的标题层级:
toc_on_this_page
等标签在站点 i18n 资源包中翻译。自定义 CSS 调整大纲轨道或固定面板尺寸后,需要测试活动项跟踪、缩放、键盘焦点,以及完全没有标题的页面。
右栏分组
右栏里的每个分组都使用同一套标题行:图标、标题和折叠箭头,整行作为一个条目高亮。大纲分组的标题是「目录」,它的图标是一个三横线字形,作用是折叠整个右栏,而不只是装饰。在侧边栏抽屉中,该分组保留静态的三横线图标,从而与旁边的分类标题保持一致。
分类分组的图标可以按分类复数名配置:
categories 默认使用文件夹图标,tags
默认使用标签图标;其他分类在这里指定之前,一律使用通用的形状图标。标签云本身的范围规则参见分类法支持。
使用 ScrollSpy 跟踪目录活动项
OINK 使用本地 Bootstrap ScrollSpy 补丁与 IntersectionObserver 跟踪活动标题。工作台会绘制连续轨道、活动区段和位置标记。为某个页面关闭跟踪:
旧版 ScrollSpy 配置也接受全局
rootMargin。它会改变条目进入活动状态的时机,应在短分区、长分区和直接片段导航中分别测试。
ScrollSpy 高级定制
优先使用配置与项目 CSS。覆盖 ScrollSpy 属性 Partial 或 docs-shell.js
会形成实现级分支;必须增加浏览器 Fixture,覆盖哈希更新、前进/后退导航、尺寸变化、减少动态效果模式,以及存在重复或缺失 ID 的页面。
面包屑导航
普通内容页上方和分类结果中会显示面包屑,这一行同时承载页面操作。顶层分区页面保留只有一级的面包屑,使这一行在任何层级都保持稳定。全局关闭面包屑的方式如下:
页面或分区 cascade 也可以设置
ui.breadcrumb_disable。面包屑标签来自本地化页面标题,而且必须与侧边栏遵循同一逻辑层级。
页面操作
页面操作是面包屑行末尾的一个纯图标拆分按钮。左半边复制本页 Markdown,成功后翻转为绿色对勾;右侧箭头展开一个包含十项操作的菜单,分为两组。上半组负责把页面内容带到别处:
- 复制 Markdown 文本
- 在 ChatGPT 中打开
- 在 Claude 中打开
- 查阅 Markdown 源码
- 查阅编辑历史
其后是一条分隔线,下半组负责修改或产出内容:
- 编辑本页
- 创建子页面
- 提交文档 issue
- 提交项目 issue
- 打印整个分区
配置的 page_context_menu.links
排在最后,前面还有一条分隔线。每个条目只有在能解析出目标时才出现:Markdown 相关操作需要
markdown 输出格式,仓库相关操作需要 github_repo,项目 issue 需要
github_project_repo,助手操作则需要
params.ui.page_context_menu.assistant_links。
在博客根分区及其一级子分区上,左半边变成 RSS 链接,菜单中仍保留「复制 Markdown 文本」。博客叶子页面不显示订阅图标。没有 Markdown 输出的页面会去掉左半边,改为渲染带文字的「操作」按钮。
create_child_page、create_project_issue 与 print_section
现在都是注册表中的一等操作,因此也会出现在命令面板中。页面级的
print 操作已废弃,读者直接使用浏览器自带的 Cmd/Ctrl+P。
站点页脚
页脚会在所有布局上渲染,由 footer_style 在三种形态之间选择:
| 取值 | 渲染内容 |
|---|---|
fat |
版权行之上的多列网格(默认值) |
slim |
只有版权行 |
none |
完全不渲染页脚 |
Front matter(包含分区 cascade)的优先级高于站点取值:
无法识别的取值会令构建失败,而不是静默回退。
胖页脚数据
多列网格读取 data/footer/<语言>.yaml;单语言站点可以直接使用
data/footer.yaml:
brand.name 与 brand.logo
未设置时回退到站点自身的品牌名、Logo 和 wordmark。tagline 和 slogan
会渲染 Markdown。站内 url 以语言根为基准解析;external: true
会在新标签页打开链接并附带
rel="noopener noreferrer"。网格的列数由数据中的列数决定。
没有数据的 fat 页脚会降级为
slim,因此站点可以先保留默认值,再逐步补齐各列内容。
data/home/<语言>.yaml 中的 footer块仍会作为回退读取。它此前只在首页渲染,现在会应用到全站,因此在继续使用这个旧位置之前,请确认这些链接列从文档深层页面看仍然合理。
标题自链接
使用方站点可以启用 OINK 标题渲染钩子:
生成的 .td-heading-self-link 控件默认使用
#。它在触控设备上始终可见,在指针设备上则于悬停或聚焦时出现。链接必须支持键盘访问,并保留足以避开固定导航的滚动偏移。
标题别名与页内目标
修改标题可能破坏外部片段链接,因此标题 ID 应按公开路由对待。需要重命名 ID 时,应保留旧 ID 的空锚点,并显式写入新 ID:
别名和其他页内目标应使用空的 <a id="..."></a>。不要仅为片段目标使用
span。ID 必须唯一、稳定,在可行时使用 ASCII,并在各语言版本中保持一致。
快速开始
这个真实标题演示了 #get-started 与 #quickstart
都能到达同一位置。译文标题应显式写入英文页面渲染后的 ID,不要依赖不同语言各自生成的自动 slug。
实现说明
- 文档为固定界面设置全局滚动偏移;
- 内置块目标使用
td-anchor-no-extra-offset,避免重复应用额外偏移; - 翻译审计会比较英文与中文页面渲染后的标题 ID;
- 删除旧别名属于破坏性文档变更,需要重定向或明确记录兼容性决策。
3 - 多语言
OINK 直接使用 Hugo 的多语言页面模型,不引入站点专属的域名约定或模板假设。本站以英文为首要语言、简体中文(zh)为第二语言。
配置语言
-
label,string, required 语言选择器里显示的名字,用该语言自己的文字写——
简体中文而不是Chinese。-
locale,string 标准语言标签,用于
<html lang>、hreflang备用链接和 Open Graph 元数据。-
weight,integer 同时决定语言排序和选择器轮换顺序,数字小的在前。
-
title,string 该语言下的站点标题。
-
params.*,map 语言级参数覆盖全局同名值;没定义的继承全局。日期格式通常需要按语言设置。
菜单标签因语言而异时,在各语言下分别定义 menus。
组织译文
译文与原文并排放在同一目录,用文件名后缀区分:
-
content/docs
- install.md
- install.zh.md
相同的基础文件名让 Hugo 把它们识别为同一页面的不同语言版本。
要保持一致的:日期、权重、别名、页面资源,以及所有影响路由的元数据。
要翻译的:front matter 的 title 和
description、摘要、菜单标签、标签、图片 alt 文本、提示块、shortcode 的可见参数。
不要翻译的:命令、标识符、配置键、文件名、URL、产品名。
contentDir
模型。不要混用两种布局——选一种写进规范,并验证 Hugo 是否正确关联了译文。
稳定的标题锚点
这是多语言文档最容易出问题的地方。Hugo 从标题文本生成 ID,所以中文标题会生成中文 ID,/docs/page/#install
和 /zh/docs/page/#安装 变成两个互不相通的锚点。
在译文标题里显式写上原文 ID:
翻译已有页面时,ID 要从英文渲染出的 HTML 里取,不要凭标题文本猜——含 shortcode 或行内代码的标题,生成的 ID 往往和你想的不一样。
本站用一个脚本强制中英标题数量、顺序和 ID 完全一致:
语言选择器行为
选择器读取每个页面的 .Translations:
- 目标语言有对应译文 → 直接跳到那一页
- 目标语言没有译文 → 回退到该语言的首页
回退是有意设计,不是缺陷。把读者送到一个不存在的 URL 更糟。
搜索与语言
offlineSearch: true 时,每种语言生成各自独立的索引:
读者在中文页面搜索,只会命中中文内容。
中文查询走主题的 CJK 子串回退——Lunr 无法可靠地对中文分词,所以命令面板会在检测到 CJK 字符时切换到子串匹配路径,两条路径应用相同的排序加权。
从右向左的语言
在语言下声明书写方向:
OINK 会加载 Bootstrap 的 RTL 样式表,主题自身的 CSS 使用逻辑属性(margin-inline-start
而非 margin-left),因此镜像布局是自动的。
站点自己写的 CSS 也应使用逻辑属性,否则 RTL 下会错位。
界面文案翻译
主题内置 32 个 locale 的界面文案。英文、简体中文(zh-cn 与通用
zh)和繁体中文(zh-tw)经过完整审校;其余语言保留继承自 Docsy 的翻译,OINK 新增的标签暂时使用英文兜底。
站点要覆盖某条界面文案时,在自己的 i18n/ 下建同名文件:
翻译检查清单
- 每个
page.md都有对应的page.zh.md - 中文标题带显式 ID,且与英文渲染 ID 一致
- 影响路由的 front matter 保持一致
- 命令、配置键、URL 未被翻译
- 语言选择器在有译文和无译文的页面上都验证过
- 两种语言的搜索都能返回结果
下一步
4 - 版本管理
产品有多个受支持版本时,文档通常也要分版本。OINK 提供两样东西:版本切换菜单和归档版本横幅。
各版本具体怎么部署由你决定——常见做法是每个版本一个子域名或子路径,各自独立构建。
版本切换菜单
在 params.versions 中列出要出现在菜单里的版本:
-
version_menu,string 菜单按钮上显示的文字,通常是当前版本号。
-
versions[].version,string, required 版本标识,显示在菜单项上。
-
versions[].url,string, required 该版本文档站的地址。留空的条目会显示为不可用。
-
version_menu_pagelinks,boolean, default:false 是否把当前页面路径附加到目标版本的 URL 后面。
菜单里可以用 - name: '---' 插入分隔线,把「受支持版本」和「历史版本」分开:
逐页跳转的取舍
version_menu_pagelinks: true
会把当前页面路径拼到目标版本的 URL 上,读者切换版本时停留在同一篇文档。
代价是:目标版本不一定有这个页面。文档结构在版本之间演进,旧版本可能没有新写的页面,读者会撞上 404。
单个版本条目上的 pagelinks: false 会覆盖全局设置,让该版本只跳转到首页。
pagelinks;差异大时关掉更好——跳到版本首页虽然多一步,但好过 404。
归档版本横幅
在不再维护的旧版本站点上,显式告诉读者:
-
archived_version,boolean, default:false 设为
true时,在每个页面顶部显示归档提示横幅。-
version,string 横幅中显示的当前版本号。
-
url_latest_version,string 指向最新版本的地址。横幅会给出一个链接。
横幅文案随站点语言本地化,不需要你自己写。
部署布局
两种常见做法:
| 布局 | baseURL |
特点 |
|---|---|---|
| 子域名 | https://v1-9.docs.example.com/ |
各版本完全独立,互不影响 |
| 子路径 | https://docs.example.com/v1.9/ |
单一域名,需要托管方支持路径路由 |
baseURL必须包含该路径,否则搜索索引、页面操作和资源链接都会指向错误位置。这是子路径部署最常见的故障。
各版本是独立构建的:从对应的 Git 分支或标签检出内容,用该版本自己的 hugo.yaml
构建,产物发布到对应地址。OINK 不提供跨版本的单次构建。
下一步
5 - 代码仓库链接与页面信息
OINK 的文档与博客布局可以显示指向当前页面源码仓库的链接。它们位于面包屑行末尾的页面操作菜单中:
- 查阅 Markdown 源码:当启用 Markdown 输出时,打开生成的 Markdown 备用版本。
- 查阅编辑历史:打开源文件的提交历史。
- 编辑本页:打开可编辑的源码视图。
- 创建子页面:在当前页面下新建文件,并可使用站点的
assets/stubs/new-page-template.md模板。 - 创建文档 issue:携带页面上下文,在文档仓库中创建 issue。
- 创建项目 issue:可选地把 issue 提交到另一个产品仓库。
内置 URL 模式面向 GitHub 风格的代码仓库。如果使用其他兼容托管服务,请逐项验证;如果 URL 结构不同,应覆盖相应 partial。
链接配置
典型站点配置如下:
当内容来自多个代码仓库时,可以在全局、单种语言、分区 cascade 或页面 front matter 中设置这些值。
github_repo
文档源码仓库 URL。它用于生成编辑、历史、创建子页面和创建文档 issue 链接:
省略后将隐藏从仓库派生的页面操作。如果页面源码实际位于消费站点,不要把它错误地指向主题仓库。
github_subdir(可选)
设置从仓库根目录到 Hugo 站点源码的路径。本项目把站点存放在 oink.pgsty.com 中:
该值是仓库内路径,不是本地绝对路径;除非内容目录就是实际站点根目录,否则也不能直接填写内容目录。
github_project_repo(可选)
设置另一个产品仓库,以显示 创建项目 issue:
内容缺陷应提交到文档仓库,页面讨论的产品行为应提交到产品仓库。如果读者无法清楚理解两者区别,应省略第二条链接。
github_branch(可选)
设置源码与编辑 URL 使用的分支:
通常应填写站点源码分支。它不一定是部署分支、自动生成的 Pages 分支或主题修订版本。
path_base_for_github_subdir(可选)
如果某棵内容子树从另一个仓库挂载,请使用分区 cascade。系统会先移除 path
base,再把剩余内容路径附加到 github_subdir:
对于源页面 content/reference/api/client.md,以上配置会把仓库路径映射为
docs/api/client.md。
path_base_for_github_subdir
可以是正则表达式。按语言目录组织内容的站点可以写成:
OINK 将 .md 与 .zh.md
并置保存,通常两种语言使用相同静态 base,因此表达式中不需要语言目录。
如果源文件使用不同名称,请使用 from 和 to 映射。下面把分区 _index.md
映射到上游 README.md:
请分别从叶子页、分区页和两种语言页面测试查看与编辑链接。正则表达式移除路径过多时,可能生成看似合理却指向错误位置的仓库 URL。
github_url(可选)
github_url 已弃用。新内容应使用
path_base_for_github_subdir
和仓库参数。
旧页面可以在 front matter 中设置完整的自定义编辑 URL:
使用该值的页面会显示 编辑本页,但不显示 查阅编辑历史:这个不透明 URL 没有可供 OINK 推导历史链接的仓库路径。当目标与 GitHub 不兼容时,更适合使用站点专属模板覆盖。
禁用链接
菜单中的每个条目都在 data-oink-action 上携带稳定的操作 ID:
| 链接 | 操作 ID |
|---|---|
| 查阅生成源码 | view_markdown |
| 查阅编辑历史 | view_history |
| 编辑本页 | edit_page |
| 创建子页面 | create_child_page |
| 创建文档 issue | create_issue |
| 创建项目 issue | create_project_issue |
当目标不支持某项操作时,可以在 assets/scss/_styles_project.scss 中将其隐藏:
命令面板中的操作使用同一批 ID,因此只隐藏菜单条目并不会让对应命令从面板中消失。
对于全局不可用的目标,应优先从配置中省略。CSS 隐藏适合选择性策略,但不能让错误链接变正确。
页面最后修改信息
启用 Hugo Git 信息并配置源码仓库:
OINK 随后可以在文档与博客页显示最后一次提交的日期、主题、hash 和源码链接。CI 必须为当前文件获取足够的 Git 历史;浅克隆可能导致元数据缺失或产生误导。
如果要在特定站点或分区隐藏提示,可以覆盖样式或负责页面元信息的 partial。当 Git 历史不可用时,不要把构建时间冒充为“最后修改”时间。