Hugo hugo.Sites 函数详解:跨语言、版本与角色维度的站点集合访问
Hugo hugo.Sites 函数详解:跨语言、版本与角色维度的站点集合访问【免费下载链接】hugoThe world’s fastest framework for building websites.项目地址: https://gitcode.com/gh_mirrors/hu/hugoHugo 0.156.0 引入了hugo.Sites模板函数,用于在构建多语言、多版本、多角色站点时,从任意模板中一次性访问所有维度组合下的全部站点集合。本文以官方函数文档为骨架,结合仓库源码与测试用例,完整讲解该函数的返回值模型、集合排序规则、hugo.Sites.Default的默认站点判定机制,以及配合where、index等内置函数的进阶用法,帮助你在复杂的多维度站点中实现跨站点导航、版本切换器和站点级元数据渲染。hugo.Sites 是什么根据官方函数文档 Sites.md 的 front matter 定义:函数签名:hugo.Sites(无参数);返回类型:page.Sites,即所有维度下所有站点的集合(Returns a collection of all sites for all dimensions);引入版本:Hugo0.156.0(文档中标注new-in 0.156.0)。Hugo 在 0.156.0 之后支持以三维矩阵构建站点矩阵:语言(Language)× 版本(Version)× 角色(Role)。每一种维度组合都对应一个独立的Site对象,拥有自己的首页、页面集合和渲染输出目录(如public/v2.0.0/de/)。hugo.Sites返回的正是覆盖整个矩阵的所有Site对象的集合,每个元素就是一个Site值,可直接调用.Home、.Title、.Language、.Version、.Role、.IsDefault等站点级方法。模板函数注册机制:从源码结构看在 tpl/hugo/init.go 中可以看到hugo命名空间的注册逻辑:const name hugo func init() { f : func(d *deps.Deps) *internal.TemplateFuncsNamespace { if d.Site nil { panic(no site in deps) } h : d.Site.Hugo() ns : internal.TemplateFuncsNamespace{ Name: name, Context: func(cctx context.Context, args ...any) (any, error) { return h, nil }, } // We just add the Hugo struct as the namespace here. No method mappings. return ns } internal.AddTemplateFuncsNamespace(f) }源码注释明确写道We just add the Hugo struct as the namespace here. No method mappings——hugo命名空间并不是手工映射一个个模板方法,而是直接把Site.Hugo()返回的Hugo结构体挂载为命名空间上下文。因此hugo.Sites实际解析为该结构体上的Sites方法,hugo.Sites.Default则通过 Go 模板的字段/方法链式访问解析。这也解释了为什么在模板中可以像访问结构体一样自由组合hugo.方法的调用方式。与旧 API 的关系:.Site.Sites/.Page.Sites已弃用在 hugolib/site.go 中可以看到旧入口的弃用处理:// Deprecated: Use hugo.Sites instead. ... hugo.Deprecate(.Site.Sites and .Page.Sites, Use hugo.Sites instead., v0.156.0)也就是说,自v0.156.0起,.Site.Sites与.Page.Sites会触发弃用告警,官方函数文档也明确建议迁移。对应的旧方法文档页(Site.Sites 与 Page.Sites)现在都指向同一句话:Use thehugo.Sitesfunction instead。站点矩阵的配置前提hugo.Sites的行为完全由项目配置决定。官方文档给出的最小可复现配置如下(hugo.toml):defaultContentLanguage en defaultContentLanguageInSubdir true defaultContentVersionInSubdir true [languages.de] contentDir content/de direction ltr label Deutsch locale de-DE title Projekt Dokumentation weight 1 [languages.en] contentDir content/en direction ltr label English locale en-US title Project Documentation weight 2 [versions.v1.0.0] [versions.v2.0.0] [versions.v3.0.0]各配置项要点:配置项作用defaultContentLanguage指定默认语言,决定哪个站点在语言维度上被视为默认;defaultContentLanguageInSubdir/defaultContentVersionInSubdir控制各语言/版本是否以子目录形式组织输出 URL;[languages.lang]语言定义:weight用于站点集合中的排序优先级,contentDir指定该语言的内容目录;[versions.v]版本定义,每个版本可单独配置权重等参数,缺省即空表;[roles.r]角色定义(仓库测试中另有[roles.guest]、[roles.member]配合defaultContentRoleInSubdir使用,见下文测试)。在该配置下,构建产物会同时包含en/de × v1.0.0/v2.0.0/v3.0.0共 6 个站点,每个站点拥有独立的首页与内容树。集合的排序规则hugo.Sites返回的集合并非随意顺序,而是遵循一种分层排序(hierarchical sort),每一层维度作为上一层的决胜条件。这部分规则定义在公共片段 sites-collection.md 中,原文为:Language按weight升序排列,权重相同或未定义时回退到字典序(lexicographical order);Version随后按weight升序排列,权重相同(平局)时 Hugo 默认采用语义化版本降序(descending semantic sort);Role最后按weight升序排列,最终回退为字典序。这条规则直接体现在官方文档的示例输出中:由于德语站点weight 1小于英语的weight 2,集合中三个德语站点排在最前面;而每个语言内部,v3.0.0 因语义化降序排列在 v1.0.0 之前。实战一:range 遍历生成跨站点导航官方文档给出的核心示例模板:ul {{ range hugo.Sites }} lia href{{ .Home.RelPermalink }}{{ .Title }} {{ .Version.Name }}/a/li {{ end }} /ul在上述配置下,渲染出指向每一个站点首页的链接列表:ul lia href/v3.0.0/de/Projekt Dokumentation v3.0.0/a/li lia href/v2.0.0/de/Projekt Dokumentation v2.0.0/a/li lia href/v1.0.0/de/Projekt Dokumentation v1.0.0/a/li lia href/v3.0.0/en/Project Documentation v3.0.0/a/li lia href/v2.0.0/en/Project Documentation v2.0.0/a/li lia href/v1.0.0/en/Project Documentation v1.0.0/a/li /ul从输出可以验证两层排序:外层德语在前(语言 weight 1 2),内层版本 v3.0.0 → v1.0.0 降序(语义化排序)。这里用到的站点方法:.Home是该站点的首页节点,.Home.RelPermalink取相对链接,.Title与.Version.Name分别取站点标题与版本名。实战二:hugo.Sites.Default 与默认站点判定要在任意模板中渲染默认站点首页的链接:{{ with hugo.Sites.Default }} a href{{ .Home.RelPermalink }}{{ .Title }}/a {{ end }}官方文档对此的结论是:默认站点 默认语言 默认版本 默认角色所确定的那一个站点,与它在集合中的位置无关。在上例中,三个德语站点因权重较低排在前面,但英语(由defaultContentLanguage en指定)才是默认语言,因此hugo.Sites.Default渲染出的是English v3.0.0 站点的首页链接,而不是集合中的第一个元素。这一点在仓库测试 hugolib/site_sites_test.go 的TestSiteIsDefault中有严格的端到端验证。该测试构造了一个 3 语言(fr/en/de)× 2 角色(guest/member)× 2 版本(v1.0.0/v2.0.0)共 12 个站点的矩阵,配置了defaultContentLanguage fr与defaultContentVersion v2.0.0,模板中同时输出当前站点的.Site.IsDefault与hugo.Sites.Default的结果:Current site is default: {{ .Site.IsDefault }} {{ with hugo.Sites.Default }} Default site: {{ .Language.Name }}-{{ .Role.Name }}-{{ .Version.Name }}: IsDefault{{ .IsDefault }} {{ end }} {{ range hugo.Sites -}} {{ .Language.Name }}-{{ .Role.Name }}-{{ .Version.Name }}: IsDefault{{ .IsDefault }} {{ end }}断言的输出显示:无论当前渲染的是public/guest/v2.0.0/en/、/fr/还是/de/下哪个页面,hugo.Sites.Default始终稳定解析为fr-guest-v2.0.0,且只有该站点IsDefaulttrue,其余 11 个站点全部为false。这验证了两件事:hugo.Sites.Default的解析与当前正在渲染哪个站点无关,是全局确定的;.IsDefault是Site对象上的一等字段,可与range hugo.Sites组合,用于在导航中高亮当前默认站点、或在非默认站点渲染切换到默认版本入口。实战三:用 where / index 筛选站点集合由于返回值是标准的 Hugo 页面集合,hugo.Sites可以无缝组合内置集合操作函数。仓库文档与测试中有几处典型用法:按维度条件过滤——site.GetPage 文档 展示了从其他语言的站点中取页:{{ with where hugo.Sites Language.Name eq de }} {{ index . 0 }} {{ end }}按位置取元素——hugolib/page__fragments_test.go 中使用{{ $secondSite : index hugo.Sites 1 }}直接取集合第二个站点,可用于当前站点之外的另一个站点这类相对引用场景。配合 page.Aliases 的跨站点重定向——Page.Aliases 文档 展示了{{- range hugo.Sites -}}遍历所有站点构建别名,适用于站点重构后为旧维度组合生成 301 重定向的清单。适用前提与限制版本要求:hugo.Sites及配套的.IsDefault语义依赖 Hugo0.156.0 及以上版本;在旧版本上应使用(现已弃用的).Site.Sites/.Page.Sites。配置驱动:集合内容与顺序完全由languages/versions/roles及各自的weight配置决定;未配置版本或角色维度时,集合自然退化为仅按语言维度展开。排序可依赖:由于排序规则(语言 weight 升序 → 版本 weight 升序平局时语义化降序 → 角色 weight 升序)是文档化行为,导航顺序类 UI 可以安全依赖,但涉及第一个/最后一个元素的逻辑仍建议用where显式筛选,避免与权重改动耦合。小结hugo.Sites是 Hugo 多维站点矩阵(语言 × 版本 × 角色)的核心访问入口:它以page.Sites集合暴露全部站点实例,以文档化的分层排序保证集合顺序可预期,以hugo.Sites.Default和.IsDefault明确默认站点语义。结合range、where、index等集合函数,可以在模板层完成跨站点导航、版本切换器、默认站点高亮与站点级重定向等常见需求。相关实现与验证代码可继续在 tpl/hugo/init.go、hugolib/site.go、hugolib/site_sites_test.go 中查阅。【免费下载链接】hugoThe world’s fastest framework for building websites.项目地址: https://gitcode.com/gh_mirrors/hu/hugo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考