ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Hugo 多语言站点中的 Pages.ByLanguage 方法:按语言权重排序页面集合的完整指南

2026/9/19 11:24:41 拓冰建站 浏览量
Hugo 多语言站点中的 Pages.ByLanguage 方法:按语言权重排序页面集合的完整指南 Hugo 多语言站点中的 Pages.ByLanguage 方法按语言权重排序页面集合的完整指南【免费下载链接】hugoThe world’s fastest framework for building websites.项目地址: https://gitcode.com/gh_mirrors/hu/hugo导读ByLanguage是 Hugo 中作用于Pages页面集合page.Pages的一个排序方法它按照语言权重升序 → 日期降序 → LinkTitle 升序的优先级对页面集合重新排序返回一个新的Pages集合。在构建多语言站点如中英双语、多语言新闻站时若你需要把来自多个站点的页面聚合后按语言分组展示或需要统一语言在输出中的先后顺序ByLanguage就是最直接的解决方案。读完本文你将掌握该方法的排序规则、底层实现原理、模板中的典型用法以及它与Rotate、Translations、AllTranslations等相关方法的取舍关系。方法签名与返回值PAGES.ByLanguage返回值类型page.Pages一个页面集合签名无参数直接作用于接收者页面集合副作用不修改原始集合返回排序后的副本在 Hugo 源码中该方法定义于 resources/page/pages_sort.go// ByLanguage sorts the Pages by the languages Weight. // // Adjacent invocations on the same receiver will return a cached result. // // This may safely be executed in parallel. func (p Pages) ByLanguage() Pages { const key pageSort.ByLanguage pages, _ : spc.get(key, pageBy(lessPageLanguage).Sort, p) return pages }从源码可以看到两点关键特性缓存机制方法通过pageCache定义于 resources/page/pages_cache.go以pageSort.ByLanguage为键缓存排序结果。对同一个接收者集合的连续多次调用会直接命中缓存不会重复排序因此在循环或多次渲染的场景中可放心调用。该缓存由sync.RWMutex保护可安全地在并行渲染中执行。稳定排序底层通过sort.Stable进行稳定排序相等元素保持原有相对顺序。排序规则三级优先级当按语言排序时Hugo 按照以下优先级对页面集合排序语言权重Language weight升序日期Date降序LinkTitle升序这一规则由lessPageLanguage比较函数实现同样位于 resources/page/pages_sort.golessPageLanguage func(p1, p2 Page) bool { if p1.Language().Weight p2.Language().Weight { if p1.Date().Unix() p2.Date().Unix() { c : compare.Strings(p1.LinkTitle(), p2.LinkTitle()) if c 0 { if p1.File() ! nil p2.File() ! nil { return compare.LessStrings(p1.File().Filename(), p2.File().Filename()) } } return c 0 } return p1.Date().Unix() p2.Date().Unix() } if p2.Language().Weight 0 { return true } if p1.Language().Weight 0 { return false } return p1.Language().Weight p2.Language().Weight }结合源码可以提炼出更精确的规则细节第一优先级比较两页所属语言的Weight值升序。当p2语言权重为 0 时p2排后当p1语言权重为 0 时p1排后即权重为 0 的语言总是排在非零权重语言之后其余情况按权重值从小到大排列。第二优先级语言权重相同时比较页面Date降序即较新的页面在前。第三优先级日期也相同时比较LinkTitle升序。隐藏的兜底规则若LinkTitle也完全相同则比较两个页面的源文件文件名File().Filename()确保排序结果完全确定。语言权重从哪来语言权重是每个语言的配置项weight在hugo.toml的多语言配置块中声明。在源码 langs/config.go 中其定义如下// The language weight. When set to a non-zero value, this will // be the main sort criteria for the language. Weight int典型的配置示例defaultContentLanguage en [languages.en] weight 1 title English [languages.zh] weight 2 title 中文 [languages.fr] weight 3 title Français上述配置下ByLanguage会先把所有 en 页面排在最前随后是 zh 页面最后是 fr 页面。什么时候用——几乎用不到的方法该文档特别提示这个方法很少甚至几乎不需要手动调用。原因在于Hugo 中已经按语言权重排好序的页面集合有很多Page.Rotate方法返回的集合Page.Translations方法返回的集合Page.AllTranslations方法返回的集合这些方法内部已经按语言权重完成了排序。以AllTranslations为例其实现位于 hugolib/page.go其中直接调用了排序函数page.SortByLanguage(pasc)以及pas pagePredicates.ShouldLink.Filter(pas) page.SortByLanguage(pas) return pas, nil而SortByLanguage正是ByLanguage的无返回值内部版本resources/page/pages_sort.go// SortByLanguage sorts the pages by language. func SortByLanguage(pages Pages) { pageBy(lessPageLanguage).Sort(pages) }也就是说当你通过hugo.Sites遍历站点、或通过.Site.RegularPages获取常规页面时如果这些集合本身已经只包含单一语言那么ByLanguage不会产生任何可见效果。它真正的用武之地是把来自多个站点的、混杂多种语言的页面聚合到同一个集合之后再进行语言排序。实战示例聚合所有站点的页面并按语言排序原文档给出的典型场景是先通过hugo.Sites聚合所有站点的页面再调用ByLanguage排序。{{ $p : slice }} {{ range hugo.Sites }} {{ range .Pages }} {{ $p $p | append . }} {{ end }} {{ end }} {{ range $p.ByLanguage }} h2a href{{ .RelPermalink }}{{ .LinkTitle }}/a/h2 {{ end }}这个示例的执行流程hugo.Sites返回站点集合每个站点对应一个语言如 en、zh、fr内层range .Pages遍历当前站点下的所有页面并通过append追加到共享的$p切片中完成跨语言聚合调用$p.ByLanguage得到按语言权重升序 → 日期降序 → LinkTitle 升序排好的页面集合遍历输出每个页面的链接使用RelPermalink相对永久链接与LinkTitle。降序排列链式调用 Reverse如需将结果按语言权重降序排列例如希望权重最大的语言排在最前只需在ByLanguage之后链式调用Reverse{{ range $p.ByLanguage.Reverse }} h2a href{{ .RelPermalink }}{{ .LinkTitle }}/a/h2 {{ end }}Reverse方法同样定义于 resources/page/pages_sort.go它对页面顺序做原地反转并返回副本同样具备缓存能力键为pageSort.Reverse。与相关方法的对比与取舍方法所属对象作用排序依据Pages.ByLanguagePages集合对任意页面集合按语言排序语言权重升序 → 日期降序 → LinkTitle 升序Page.Translations单个Page返回该页面的所有翻译版本不含自身已按语言权重排序Page.AllTranslations单个Page返回该页面的所有翻译版本含自身已按语言权重排序Page.Rotate单个Page返回该页面的语言变体集合从当前语言开始轮转已按语言权重排序相关方法的详细文档可参阅docs/content/en/methods/page/AllTranslations.mddocs/content/en/methods/page/Translations.mddocs/content/en/methods/page/Rotate.md取舍建议若你已在Page对象上下文中需要遍历某个页面的所有语言版本请直接使用Translations/AllTranslations/Rotate它们已内置语言排序无需再调用ByLanguage若你像上面的示例一样手动把多个hugo.Sites的页面聚合成一个新集合那么ByLanguage是让该混合集合恢复按语言分组、组内按日期与标题有序的唯一内置手段。源码级验证语言排序在测试中的体现Hugo 仓库中 hugolib/pages_language_merge_test.go 对多语言站点下页面集合的语言顺序行为做了大量验证。例如TestMergeByLanguage构造了 en、fr、nn 三个语言站点对应 31 / 6 / 12 个常规页面断言合并后的集合中每个位置的语言归属mergedNN : nnSite.RegularPages().MergeByLanguage(enSite.RegularPages()) c.Assert(len(mergedNN), qt.Equals, 31) for i : 1; i 31; i { expectedLang : en if i 2 || i%3 0 || i 31 { expectedLang nn } p : mergedNN[i-1] c.Assert(p.Language().Lang, qt.Equals, expectedLang) }该测试中的MergeByLanguage与本文的ByLanguage共享同一套语言优先级语义二者均构建于langs的语言权重体系之上可用于理解 Hugo 在多语言集合排序中的一致行为语言权重决定了语言的先后权重为 0 的语言垫底。小结Pages.ByLanguage是 Hugo 为多语言站点提供的一个兜底排序方法排序规则语言权重升序→ 日期降序→ LinkTitle升序三者相同时回退到源文件名以保证确定性适用场景手动聚合了多个站点/多种语言页面后需要按语言分组输出的场景性能特性结果按接收者集合缓存重复调用零开销可安全并行注意事项对于Rotate、Translations、AllTranslations等已经按语言排序的集合无需也无效再调用本方法配套能力需要降序时链式调用Reverse即可。掌握了ByLanguage的规则与边界你在构建多语言 Hugo 站点时就能准确判断什么场景下需要它什么场景下应该直接依赖 Hugo 已排好序的翻译集合。【免费下载链接】hugoThe world’s fastest framework for building websites.项目地址: https://gitcode.com/gh_mirrors/hu/hugo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考